v0.9.85 minor ui updates
This commit is contained in:
@@ -52,9 +52,9 @@ const RESP_ICON = {
|
||||
),
|
||||
};
|
||||
const BELL_ICON = (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="#ef4444" width={15} height={15} style={{flexShrink:0}}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="#fbbf24" viewBox="0 0 24 24" strokeWidth={1.5} stroke="var(--warning-stroke)" width={15} height={15} style={{flexShrink:0}}>
|
||||
<title>Awaiting your response</title>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -715,9 +715,12 @@ function ScheduleView({ events, selectedDate, onSelect, filterKeyword='', filter
|
||||
const today=new Date(); today.setHours(0,0,0,0);
|
||||
const terms=parseKeywords(filterKeyword);
|
||||
const hasFilters = terms.length > 0 || !!filterTypeId;
|
||||
// No filters: show selected month only (desktop and mobile — month nav arrows control the month).
|
||||
// Filters active: show today + all future on both platforms.
|
||||
const from = hasFilters ? today : new Date(y,m,1);
|
||||
const now = new Date(); // exact now for end-time comparison
|
||||
const isCurrentMonth = y === today.getFullYear() && m === today.getMonth();
|
||||
// No filters: show from today (if current month) or start of month (future months) to end of month.
|
||||
// Past months show nothing — navigate forward to see events.
|
||||
// Filters active: today + all future events.
|
||||
const from = hasFilters ? today : (isCurrentMonth ? today : new Date(y,m,1));
|
||||
const to = hasFilters ? new Date(9999,11,31) : new Date(y,m+1,0,23,59,59);
|
||||
const filtered=events.filter(e=>{
|
||||
const s=new Date(e.start_at);
|
||||
@@ -729,19 +732,62 @@ function ScheduleView({ events, selectedDate, onSelect, filterKeyword='', filter
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const emptyMsg = hasFilters ? 'No events match your filters' : `No events in ${MONTHS[m]} ${y}`;
|
||||
const emptyMsg = hasFilters
|
||||
? 'No events match your filters'
|
||||
: new Date(y,m+1,0) < today
|
||||
? `No events — ${MONTHS[m]} ${y} is in the past`
|
||||
: `No events in ${MONTHS[m]} ${y}`;
|
||||
if(!filtered.length) return <div style={{textAlign:'center',padding:'60px 20px',color:'var(--text-tertiary)',fontSize:14}}>{emptyMsg}</div>;
|
||||
return <>{filtered.map(e=>{const s=new Date(e.start_at);const col=e.event_type?.colour||'#9ca3af';
|
||||
// Desktop: original pre-v0.9.64 sizes. Mobile: compact sizes from v0.9.64
|
||||
const rowPad=isMobile?'12px 14px':'14px 20px';
|
||||
const rowGap=isMobile?10:20;
|
||||
const datW=isMobile?36:44; const datFs=isMobile?20:22; const datSFs=isMobile?10:11;
|
||||
const timeW=isMobile?62:100; const timeGap=isMobile?5:8; const timeFs=isMobile?11:13;
|
||||
const dotSz=isMobile?8:10;
|
||||
const typeFs=isMobile?10:11; const titleGap=isMobile?6:8;
|
||||
return(<div key={e.id} onClick={()=>onSelect(e)} style={{display:'flex',alignItems:'center',gap:rowGap,padding:rowPad,borderBottom:'1px solid var(--border)',cursor:'pointer'}} onMouseEnter={el=>el.currentTarget.style.background='var(--background)'} onMouseLeave={el=>el.currentTarget.style.background=''}><div style={{width:datW,textAlign:'center',flexShrink:0}}><div style={{fontSize:datFs,fontWeight:700,lineHeight:1}}>{s.getDate()}</div><div style={{fontSize:datSFs,color:'var(--text-tertiary)',textTransform:'uppercase'}}>{SHORT_MONTHS[s.getMonth()]}, {DAYS[s.getDay()]}</div></div><div style={{width:timeW,flexShrink:0,display:'flex',alignItems:'flex-start',gap:timeGap,fontSize:timeFs,color:'var(--text-secondary)'}}><span style={{width:dotSz,height:dotSz,borderRadius:'50%',background:col,flexShrink:0,marginTop:3}}/>{e.all_day?<span>All day</span>:<span style={{lineHeight:1.5}}>{fmtTime(e.start_at)} –<br/>{fmtTime(e.end_at)}</span>}</div><div style={{flex:1,minWidth:0}}><div style={{fontSize:14,fontWeight:600,display:'flex',alignItems:'center',gap:titleGap,flexWrap:'nowrap'}}>{e.event_type?.name&&<span style={{fontSize:typeFs,color:'var(--text-tertiary)',textTransform:'uppercase',letterSpacing:'0.5px',fontWeight:600,flexShrink:0}}>{e.event_type.name}:</span>}<span style={{minWidth:0,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{e.title}</span>{!!e.track_availability&&(
|
||||
e.my_response ? RESP_ICON[e.my_response](RESP_COLOR[e.my_response]) : BELL_ICON
|
||||
)}</div>{e.location&&<div style={{fontSize:12,color:'var(--text-tertiary)',marginTop:2}}>{e.location}</div>}</div></div>);})}</>;
|
||||
return <>{filtered.map(e=>{
|
||||
const s=new Date(e.start_at);
|
||||
const end=new Date(e.end_at);
|
||||
const isPast = !e.all_day && end < now; // event fully ended
|
||||
const col = isPast ? '#9ca3af' : (e.event_type?.colour||'#9ca3af');
|
||||
const textColor = isPast ? 'var(--text-tertiary)' : 'var(--text-primary)';
|
||||
const subColor = isPast ? 'var(--text-tertiary)' : 'var(--text-secondary)';
|
||||
// Use CSS media query breakpoint logic — compact below 640px regardless of isMobile prop
|
||||
// so responsive desktop doesn't compact when there's plenty of room
|
||||
const compact = isMobile; // isMobile is only true on genuine mobile, not responsive desktop
|
||||
const rowPad=compact?'12px 14px':'14px 20px';
|
||||
const rowGap=compact?10:20;
|
||||
const datW=compact?36:44; const datFs=compact?20:22; const datSFs=compact?10:11;
|
||||
const timeW=compact?80:100; const timeGap=compact?5:8; const timeFs=compact?11:13;
|
||||
const dotSz=compact?8:10;
|
||||
const availIcon = !!e.track_availability && (
|
||||
e.my_response
|
||||
? RESP_ICON[e.my_response](isPast ? '#9ca3af' : RESP_COLOR[e.my_response])
|
||||
: isPast
|
||||
? <svg xmlns="http://www.w3.org/2000/svg" fill="#d97706" viewBox="0 0 24 24" strokeWidth={1.5} stroke="var(--warning-stroke)" width={15} height={15} style={{flexShrink:0,opacity:0.5}}><path strokeLinecap="round" strokeLinejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"/></svg>
|
||||
: BELL_ICON
|
||||
);
|
||||
return(
|
||||
<div key={e.id} onClick={()=>onSelect(e)} style={{display:'flex',alignItems:'center',gap:rowGap,padding:rowPad,borderBottom:'1px solid var(--border)',cursor:'pointer',opacity:isPast?0.7:1}} onMouseEnter={el=>el.currentTarget.style.background='var(--background)'} onMouseLeave={el=>el.currentTarget.style.background=''}>
|
||||
{/* Date column */}
|
||||
<div style={{width:datW,textAlign:'center',flexShrink:0}}>
|
||||
<div style={{fontSize:datFs,fontWeight:700,lineHeight:1,color:textColor}}>{s.getDate()}</div>
|
||||
<div style={{fontSize:datSFs,color:'var(--text-tertiary)',textTransform:'uppercase'}}>{SHORT_MONTHS[s.getMonth()]}, {DAYS[s.getDay()]}</div>
|
||||
</div>
|
||||
{/* Time + dot column */}
|
||||
<div style={{width:timeW,flexShrink:0,display:'flex',alignItems:'flex-start',gap:timeGap,fontSize:timeFs,color:subColor}}>
|
||||
<span style={{width:dotSz,height:dotSz,borderRadius:'50%',background:col,flexShrink:0,marginTop:3}}/>
|
||||
{e.all_day?<span>All day</span>:<span style={{lineHeight:1.5}}>{fmtTime(e.start_at)} –<br/>{fmtTime(e.end_at)}</span>}
|
||||
</div>
|
||||
{/* Title + meta column */}
|
||||
<div style={{flex:1,minWidth:0}}>
|
||||
<div style={{display:'flex',alignItems:'center',gap:8,minWidth:0}}>
|
||||
<span style={{fontSize:14,fontWeight:600,color:textColor,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap',flex:1,minWidth:0}}>{e.title}</span>
|
||||
{availIcon}
|
||||
</div>
|
||||
{(e.event_type?.name||e.location) && (
|
||||
<div style={{fontSize:12,color:'var(--text-tertiary)',marginTop:2,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>
|
||||
{e.event_type?.name&&<span style={{textTransform:'uppercase',letterSpacing:'0.4px',fontWeight:600,marginRight:e.location?6:0}}>{e.event_type.name}{e.location?' ·':''}</span>}
|
||||
{e.location&&<span>{e.location}</span>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}</>;
|
||||
}
|
||||
|
||||
const HOUR_H = 52; // px per hour row
|
||||
|
||||
Reference in New Issue
Block a user