// Student · Channels — a locked preview of the coach/admin broadcast channels
// (Announcement, All Members, Free Trial Tier, VIP Members, Signal View).
// Free/Trial members see every channel listed but locked; VIP members get a
// read-only viewer. Boardroom is coach/admin-internal and never shown here.
// Exposes window.ChannelsPanel({client, isVIP, onNeedVip}).
(function(){
const { useState, useEffect } = React;
// Channel identity. Emoji were replaced with gold line-art SVGs — emoji render
// inconsistently across Windows/Android and read as unpolished next to the rest
// of the brand. VIP Members carries the real VIP Signal mark, the same one used
// on the Telegram broadcasts, so members recognise it instantly.
const ICON = {
announcement: ,
all: ,
trial: ,
vip: ,
signal: ,
lock: ,
};
const CH_LIST=[
{key:'announcement',label:'Announcement',icon:ICON.announcement,desc:'Broadcasts from your coaches'},
{key:'broadcast:all',label:'All Members',icon:ICON.all,desc:'Community room for every student & staff'},
{key:'broadcast:trial',label:'Free Trial Tier',icon:ICON.trial,desc:'Space for trial members'},
{key:'broadcast:vip',label:'VIP Members',icon:ICON.vip,desc:'VIP-only room with your coaches',brand:'assets/brand/vip-128.png'},
{key:'signalview',label:'Signal View',icon:ICON.signal,desc:'Live trade signal feed'},
];
// One tile renderer for both the list row and the open viewer header.
function ChIcon({ch, size}){
const s = size || 38;
if (ch.brand) return ;
return
{React.cloneElement(ch.icon,{style:{width:'100%',height:'100%',fill:'none',stroke:'var(--gold-2)',
strokeWidth:1.7,strokeLinecap:'round',strokeLinejoin:'round'}})}
;
}
const fmtTime = d => new Date(d).toLocaleString(undefined,{month:'short',day:'numeric',hour:'2-digit',minute:'2-digit'});
function ChannelViewer({client,ch,onClose}){
const [rows,setRows]=useState(null);
useEffect(()=>{ let stop=false; async function load(){ if(stop) return;
if(ch.key==='signalview'){ const { data } = await client.from('signals').select('*').order('created_at',{ascending:false}).limit(30); setRows(data||[]); }
else if(ch.key==='announcement'){ const { data } = await client.from('announcements').select('*').eq('active',true).order('created_at',{ascending:false}); setRows(data||[]); }
else { const { data } = await client.from('chat_messages').select('*').eq('thread_key',ch.key).eq('deleted',false).order('created_at',{ascending:false}).limit(30); setRows(data||[]); }
} load(); const iv=setInterval(load,8000); return ()=>{ stop=true; clearInterval(iv); }; },[ch.key]);
return
Nothing here yet.
} {ch.key==='signalview' && (rows||[]).map(r=>{ const dc=r.direction==='buy'?'var(--green)':'var(--red)'; return{isVIP ? 'Browse the community rooms your coaches use.' : 'A look at the community rooms \u2014 unlock with VIP to view them.'}