This commit is contained in:
2026-07-16 05:48:12 -05:00
parent c36d46c3b3
commit e9be65df8c
558 changed files with 74087 additions and 75 deletions
+296
View File
@@ -0,0 +1,296 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Compose & preview · Portal · MKDRealtor.com</title>
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Work+Sans:300,400,500,700%7CPoppins:400,600,700">
<link rel="stylesheet" href="proposal.css">
</head>
<body class="portal">
<div class="proposal-banner">
<div><span class="tag">Proposal mockup</span> &nbsp; MKDRealtor.com — UX examples (not production)</div>
<div><a href="index.html">All screens</a></div>
</div>
<div class="portal-shell">
<aside class="portal-sidebar">
<a class="portal-brand" href="portal-dashboard.html"><img src="brand/exit_logo.png" alt="EXIT Realty"><span>MKDRealtor.com</span></a>
<nav class="portal-nav">
<div class="nav-section">Overview</div>
<a class="" href="portal-dashboard.html">Dashboard</a>
<a class="" href="portal-leads.html">Leads</a>
<a class="" href="portal-analytics.html">Analytics</a>
<div class="nav-section">Outreach</div>
<a class="" href="portal-contacts.html">Mailing list</a>
<a class="" href="portal-campaign.html">Campaigns</a>
<a class="" href="portal-postcard-designer.html">Postcard design</a>
<div class="nav-section">Social</div>
<a class="active" href="portal-social.html">Compose & preview</a>
<a class="" href="portal-social-accounts.html">Accounts</a>
</nav>
</aside>
<div class="portal-main">
<div class="portal-topbar">
<h1>Compose & preview</h1>
<div class="portal-user">Signed in as <strong>Monica Dhillon</strong> · <a href="portal-login.html" style="color:#00626c">Sign out</a></div>
</div>
<div class="portal-content">
<div class="proposal-note"><strong>UX note:</strong> AI chat helps draft captions (tone, length, hashtags). Insert or replace into the composer — live FB / IG / LinkedIn previews update instantly.</div>
<div class="auth-alert" id="li-warn">
<strong>LinkedIn needs re-auth.</strong> Token expired —
<a href="portal-social-accounts.html">Re-authorize in Accounts</a> before scheduling to LinkedIn.
</div>
<div class="designer-layout with-ai">
<div class="designer-controls">
<div class="panel">
<div class="panel-h"><h2>Compose</h2><a class="btn btn-sm btn-ghost" href="portal-social-accounts.html">Manage accounts</a></div>
<div class="panel-b form-grid">
<div class="field"><label>Caption</label>
<textarea id="soc-caption" style="min-height:130px" oninput="syncSocial()">Open house this Saturday 111 at 412 Willow Lane. Quiet street, updated kitchen, walkable to Oakridge. DM or text me for details.
#JustListed #OpenHouse</textarea>
<div class="hint"><span id="char-count">0</span> characters · IG soft limit ~2,200</div>
</div>
<div class="field"><label>Media</label>
<select id="soc-media" onchange="syncSocial()">
<option value="images/grid-layout-1-370x256.jpg">Willow Lane exterior</option>
<option value="images/grid-layout-2-370x256.jpg">Kitchen</option>
<option value="images/grid-layout-3-370x256.jpg">Living room</option>
<option value="">Text only (FB / LI)</option>
</select>
</div>
<div class="field"><label>Platforms</label>
<div class="platform-toggles">
<label class="toggle-pill"><input type="checkbox" id="plat-fb" checked onchange="syncSocial()"> Facebook</label>
<label class="toggle-pill"><input type="checkbox" id="plat-ig" checked onchange="syncSocial()"> Instagram</label>
<label class="toggle-pill warn"><input type="checkbox" id="plat-li" onchange="syncSocial()"> LinkedIn <span class="muted">(re-auth)</span></label>
</div>
</div>
<div class="form-grid cols-2">
<div class="field"><label>Publish</label>
<select id="soc-when-mode"><option>Schedule</option><option>Publish now</option></select>
</div>
<div class="field"><label>When</label><input type="datetime-local" value="2026-07-16T09:00"></div>
</div>
<div class="field"><label>Preview as</label>
<div class="channel-tabs" style="margin:0">
<a href="#" class="active" id="prev-fb" onclick="setPreview('fb');return false">Facebook</a>
<a href="#" id="prev-ig" onclick="setPreview('ig');return false">Instagram</a>
<a href="#" id="prev-li" onclick="setPreview('li');return false">LinkedIn</a>
</div>
</div>
<button class="btn btn-primary" type="button" onclick="alert('Mockup: SocialPost + SocialPostTargets enqueued')">Schedule to selected platforms</button>
</div>
</div>
</div>
<div class="ai-assist-col">
<div class="ai-chat">
<div class="ai-chat-h">
<h2>AI post assistant</h2>
<span class="ai-pill">Beta mockup</span>
</div>
<div class="ai-chat-messages" id="ai-messages">
<div class="ai-msg bot">
<div class="who">Assistant</div>
<div class="bubble">
I can draft or refine captions for Facebook, Instagram, and LinkedIn.
Tell me the listing, tone (warm / bold / luxury), and any must-include details —
or tap a quick prompt below.
</div>
</div>
</div>
<div class="ai-chat-prompts">
<button type="button" class="chip" onclick="sendPrompt('Write an open-house post for 412 Willow Lane')">Open house draft</button>
<button type="button" class="chip" onclick="sendPrompt('Make my caption shorter for Instagram')">Shorter for IG</button>
<button type="button" class="chip" onclick="sendPrompt('Rewrite in a warmer, neighborly tone')">Warmer tone</button>
<button type="button" class="chip" onclick="sendPrompt('Add 4 relevant hashtags')">Add hashtags</button>
<button type="button" class="chip" onclick="sendPrompt('Make a LinkedIn-friendly professional version')">LinkedIn version</button>
</div>
<div class="ai-chat-input">
<textarea id="ai-input" placeholder="Ask for a draft, rewrite, or hashtags…" rows="2"
onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();sendChat();}"></textarea>
<button class="btn btn-primary" type="button" onclick="sendChat()">Send</button>
</div>
</div>
</div>
<div class="designer-preview-col">
<div class="panel">
<div class="panel-h"><h2>Live post preview</h2><span class="muted" style="font-size:12px" id="prev-label">Facebook</span></div>
<div class="panel-b" style="background:#e8edf3;display:flex;justify-content:center;padding:24px">
<div class="social-phone" id="preview-fb">
<div class="soc-header">
<div class="soc-avatar">MR</div>
<div>
<div class="soc-name">Monica Dhillon · MKDRealtor.com</div>
<div class="soc-meta">Sponsored · Just now · 🌐</div>
</div>
</div>
<div class="soc-caption" id="fb-caption"></div>
<div class="soc-image" id="fb-image"></div>
<div class="soc-actions">Like · Comment · Share</div>
</div>
<div class="social-phone ig" id="preview-ig" style="display:none">
<div class="soc-header">
<div class="soc-avatar round">MR</div>
<div>
<div class="soc-name">monicadhillonhomes</div>
<div class="soc-meta">Metro Area</div>
</div>
<div class="soc-more">•••</div>
</div>
<div class="soc-image square" id="ig-image"></div>
<div class="soc-actions ig-act">&nbsp; 💬 &nbsp;</div>
<div class="soc-caption"><strong>monicadhillonhomes</strong> <span id="ig-caption"></span></div>
</div>
<div class="social-phone li" id="preview-li" style="display:none">
<div class="soc-header">
<div class="soc-avatar sq">MR</div>
<div>
<div class="soc-name">Monica Dhillon</div>
<div class="soc-meta">Realtor · 1st · Just now</div>
</div>
</div>
<div class="soc-caption" id="li-caption"></div>
<div class="soc-image" id="li-image"></div>
<div class="soc-actions">Like · Comment · Repost · Send</div>
</div>
</div>
</div>
<div class="panel">
<div class="panel-h"><h2>Scheduled</h2></div>
<div class="panel-b" style="padding:0">
<table class="table">
<thead><tr><th>Post</th><th>Platforms</th><th>Status</th></tr></thead>
<tbody>
<tr><td>Open house Willow Lane</td><td>FB · IG</td><td><span class="badge badge-scheduled">Scheduled</span></td></tr>
<tr><td>Just sold — Birch Ave</td><td>FB · IG · LI</td><td><span class="badge badge-delivered">Published</span></td></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
let previewPlat = 'fb';
let lastDraft = '';
function setPreview(p) {
previewPlat = p;
['fb','ig','li'].forEach(x => {
document.getElementById('preview-' + x).style.display = x === p ? 'block' : 'none';
document.getElementById('prev-' + x).classList.toggle('active', x === p);
});
document.getElementById('prev-label').textContent = ({fb:'Facebook',ig:'Instagram',li:'LinkedIn'})[p];
}
function syncSocial() {
const cap = document.getElementById('soc-caption').value;
const media = document.getElementById('soc-media').value;
document.getElementById('char-count').textContent = cap.length;
document.getElementById('fb-caption').textContent = cap;
document.getElementById('ig-caption').textContent = cap;
document.getElementById('li-caption').textContent = cap;
['fb','ig','li'].forEach(x => {
const el = document.getElementById(x + '-image');
if (!media) { el.style.display = 'none'; }
else { el.style.display = 'block'; el.style.backgroundImage = 'url(' + media + ')'; }
});
document.getElementById('li-warn').style.display = document.getElementById('plat-li').checked ? 'block' : 'none';
}
function escapeHtml(s) {
return String(s).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
}
function appendMsg(role, html) {
const root = document.getElementById('ai-messages');
const div = document.createElement('div');
div.className = 'ai-msg ' + role;
div.innerHTML =
'<div class="who">' + (role === 'user' ? 'You' : 'Assistant') + '</div>' +
'<div class="bubble">' + html + '</div>';
root.appendChild(div);
root.scrollTop = root.scrollHeight;
}
function draftActions(draft) {
lastDraft = draft;
const id = 'draft-' + Date.now();
return (
'<div class="ai-draft" id="' + id + '">' + escapeHtml(draft) + '</div>' +
'<div class="ai-msg-actions">' +
'<button type="button" class="btn btn-sm btn-primary" onclick="insertDraft(false)">Replace caption</button>' +
'<button type="button" class="btn btn-sm btn-ghost" onclick="insertDraft(true)">Append</button>' +
'</div>'
);
}
function insertDraft(append) {
const ta = document.getElementById('soc-caption');
if (append && ta.value.trim()) ta.value = ta.value.replace(/\s*$/, '') + '\n\n' + lastDraft;
else ta.value = lastDraft;
syncSocial();
}
function inventReply(prompt, current) {
const p = prompt.toLowerCase();
if (p.includes('shorter') || p.includes('instagram')) {
return 'Open house Sat 111 · 412 Willow Lane\nUpdated kitchen, quiet street, walk to Oakridge.\nDM for details 🏡\n\n#JustListed #OpenHouse #WillowLane';
}
if (p.includes('warm') || p.includes('neighbor')) {
return 'I\'d love to show you around this Saturday.\n\n412 Willow Lane is open 111 — quiet street, bright kitchen, and an easy walk to Oakridge schools. Come say hi, no pressure.\n\nText me anytime if you want a private look first.';
}
if (p.includes('hashtag')) {
const base = current.trim() || 'Just listed — 412 Willow Lane. Open house Saturday 111.';
return base.replace(/\s*#\S+/g, '').trim() + '\n\n#JustListed #OpenHouse #RealEstate #HomeTour';
}
if (p.includes('linkedin') || p.includes('professional')) {
return 'Hosting an open house this Saturday, 111, at 412 Willow Lane.\n\nUpdated kitchen, walkable to Oakridge schools, asking $449,000. Happy to arrange a private showing for clients who can\'t make the window.\n\n#RealEstate #OpenHouse';
}
if (p.includes('open house') || p.includes('willow') || p.includes('draft')) {
return 'Open house this Saturday 111 at 412 Willow Lane.\n\nQuiet street · updated kitchen · walkable to Oakridge.\nDM or text me for details — hope to see you there!\n\n#JustListed #OpenHouse';
}
if (p.includes('rewrite') || p.includes('improve') || current.trim()) {
return 'Just listed: 412 Willow Lane.\n\nOpen Saturday 111. Updated kitchen, quiet street, walkable to Oakridge schools. Asking $449,000.\n\nMessage me for a private showing.\n\n#JustListed #OpenHouse';
}
return 'Tell me the address, price band, and vibe (warm / bold / luxury) and I\'ll draft a caption you can drop straight into the composer.';
}
function respond(prompt) {
const current = document.getElementById('soc-caption').value;
const draft = inventReply(prompt, current);
const needsDraft = !/tell me the address/i.test(draft);
const body = needsDraft
? 'Here\'s a draft you can use:' + draftActions(draft)
: escapeHtml(draft);
appendMsg('bot', body);
}
function sendPrompt(text) {
document.getElementById('ai-input').value = text;
sendChat();
}
function sendChat() {
const input = document.getElementById('ai-input');
const text = input.value.trim();
if (!text) return;
appendMsg('user', escapeHtml(text));
input.value = '';
setTimeout(() => respond(text), 350);
}
syncSocial();
</script>
</body>
</html>