feat(chat): rich shared-media view, status selector, drag-drop upload + fixes

Chat / shared media:
- Media/Docs/Links: clean underline tabs (green active), audio & video now
  classified as Media and rendered as tiles (download + headphone/play +
  duration) instead of broken-image glyphs; image thumbnails -> lightbox
- Drag-and-drop a file/video/image onto a conversation to send it
- Fix: removed #chatPanel{position:relative} override that collapsed the
  conversation pane (messages spilled into a clipped right-edge strip)
- "Media, links & docs" row cleaned up (no folder/placeholder icon); media
  popup keeps the back arrow, drops the redundant close button

Presence / status:
- Single current-status row with an arrow that expands Available/Away/On leave
- On leave = circle with minus, In a call = solid red indicators
- Fix: selected-status tick now follows the chosen option

Icons: added headphones + play; bumped icons.js cache-bust to v4

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 17:01:15 +05:30
parent e9e5c7f406
commit 06f0b08a18
12 changed files with 589 additions and 116 deletions
+13 -15
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>BizGaze Support</title>
<title>Biz Connect</title>
<style>
:root{ --brand:#FFC708; --brand-d:#E0AC00; --blue:#1F3B73; --blue-d:#16294f; --blue-soft:#EAF0FB; --ink:#1f2430; --muted:#6b7280; --bg:#f6f8fb; --line:#e6e9ef; }
*{box-sizing:border-box;}
@@ -47,24 +47,26 @@
<header>
<div class="brandrow">
<img src="/logo.png" alt="" style="height:40px;width:auto;max-width:170px;border-radius:8px;object-fit:contain;background:#fff;padding:4px 10px" onerror="this.style.display='none'">
<div class="brand">BizGaze <span>Support</span></div>
<div class="brand">Biz <span>Connect</span></div>
</div>
<div id="authArea"></div>
</header>
<div class="wrap">
<div class="inner">
<h1>Welcome to BizGaze Connect</h1>
<h1>Welcome to Biz Connect</h1>
<div class="sub">Chat, meetings and secure remote support — for the BizGaze ecosystem.</div>
<!-- Stub SSO: routes to staff login for now; swap href to /sso once BizGaze SSO is wired. -->
<a class="ssobtn" id="ssoBtn" href="/home"><span class="bmark">B</span> Log in with BizGaze</a>
<div class="divider">need support? no account required</div>
<!-- Customer path FIRST (no account needed): share your screen for support. -->
<div class="divider">Need support? — no account needed</div>
<div class="choices" style="max-width:400px;margin:0 auto">
<a class="choice" href="/share">
<div class="icon share"><svg viewBox="0 0 24 24" fill="none" stroke="#BA7515" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2"/><path d="M8 21h8M12 17v4"/></svg></div>
<div><h3>Share my screen</h3><p>Get a one-time code and show your screen to a BizGaze support agent — no login, no download.</p></div>
<div><h3>Share my screen</h3><p>Get a one-time code and show your screen to a Biz Connect support agent — no login, no download.</p></div>
</a>
</div>
<div class="foot"><span data-ic="lock" data-sz="14"></span> Screen sharing only starts after you approve it, and can be stopped anytime.</div>
<div class="foot" style="margin:.7rem 0 0"><span data-ic="lock" data-sz="14"></span> Screen sharing only starts after you approve it, and can be stopped anytime.</div>
<!-- Team member path BELOW: log in to the full app. Stub SSO -> /home for now. -->
<div class="divider" style="margin-top:1.6rem">BizGaze team member?</div>
<a class="ssobtn" id="ssoBtn" href="/home"><span class="bmark">B</span> Log in with BizGaze</a>
</div>
</div>
<footer>© BizGaze · Remote Support</footer>
@@ -74,13 +76,9 @@ function profileHTML(name){return '<div class="profile"><button class="pbtn" id=
function wireProfile(){const btn=document.getElementById('pbtn'),menu=document.getElementById('pmenu');if(!btn)return;btn.onclick=(e)=>{e.stopPropagation();menu.classList.toggle('open');};document.addEventListener('click',()=>menu.classList.remove('open'));const lo=document.getElementById('plogout');if(lo)lo.onclick=async()=>{try{await fetch('/api/logout',{method:'POST'});}catch(_){}location.href='/';};}
function makeBrandClickable(){document.querySelectorAll('.brandrow,.wordmark').forEach(el=>{el.style.cursor='pointer';el.addEventListener('click',()=>{location.href='/';});});}
makeBrandClickable();
(async function(){try{const r=await fetch('/api/me');if(r.ok){const me=await r.json();
document.getElementById('authArea').innerHTML=profileHTML(me.name||me.email);wireProfile();
// Already signed in: swap the login CTA for an "enter app" CTA.
const b=document.getElementById('ssoBtn'); if(b){ b.innerHTML='Open BizGaze Connect &rarr;'; b.href='/home'; }
const h=document.querySelector('.inner h1'); if(h){ const fn=String(me.name||'').trim().split(/\s+/)[0]; h.textContent='Welcome back'+(fn?', '+fn:'')+'!'; }
const dv=document.querySelector('.divider'); if(dv) dv.textContent='need to help someone? share your screen';
}}catch(_){}})();
// Already signed in -> skip this landing entirely and go straight to the app (no redundant
// "Open Biz Connect" page). This landing only shows when logged out.
(async function(){try{const r=await fetch('/api/me');if(r.ok){ location.replace('/home'); return; }}catch(_){}})();
</script>
<script>(function(){var s=document.createElement('style');s.textContent='.ic{display:inline-block;vertical-align:middle}';document.head.appendChild(s);document.querySelectorAll('[data-ic]').forEach(function(e){e.insertAdjacentHTML('afterbegin',window.ic(e.getAttribute('data-ic'),+e.getAttribute('data-sz')||16));});})();</script>
</body>