/* Operations screens: DailyQueue, Calendar, AddJob */ // ============ shared date stepper ============ function DateStepper({ date, onChange, compact }){ return (
{CK.thDate(date,{withDow:true})}
{!compact &&
{date===CK.TODAY?'วันนี้':''}
}
); } // ============ capacity bar ============ function CapacityBar({ ds }){ const d = CK.DAYSTATUS[ds.status]; return (
{ds.used} / {ds.max} unit
); } function sortQueue(jobs){ const slotRank = s => ['คิวแรก (09.00)','ช่วงเช้า','ช่วงบ่าย','สะดวกทั้งวัน'].indexOf(s); return [...jobs].sort((a,b)=>{ if (a.urgency!==b.urgency) return a.urgency==='urgent'?-1:1; return slotRank(a.slot)-slotRank(b.slot); }); } // ============ Daily Queue ============ function DailyQueueScreen(){ const { jobs, device, tweaks, nav, navigate } = useCK(); const [date,setDate] = React.useState(nav.date || CK.TODAY); const [filters,setFilters] = React.useState({}); const [openId,setOpenId] = React.useState(null); const [view,setView] = React.useState('day'); // day | week React.useEffect(()=>{ if(nav.date){ setDate(nav.date); setView('day'); } }, [nav.date]); const ds = computeDayStatus(jobs, date); const dayJobs = sortQueue(applyFilters(jobs.filter(j=>j.date===date), filters)); const isMobile = device==='mobile'; const useTable = tweaks.queueLayout==='table' && !isMobile; const isWeek = view==='week'; const ViewToggle = () => (
{[['day','รายวัน','CalendarDays'],['week','สัปดาห์','Columns3']].map(([k,l,ic])=>( ))}
); return (
{isMobile ? (

คิวรายวัน

{!isWeek && } {!isWeek && }
) : ( {!isWeek && } )} {!isMobile && !isWeek && (
แอร์ {ds.air} ชุด · งานบริการ {ds.service} งาน
)}
{isWeek ? ( setOpenId(id)} onOpenDay={(d)=>{ setDate(d); setView('day'); }} /> ) : ( <> {ds.status==='full' && (
คิววันนี้เต็มแล้ว ({ds.used}/{ds.max} unit) — การรับงานเพิ่มต้องให้สำนักงานใหญ่อนุมัติ
)} {dayJobs.length===0 ? ( ) : useTable ? ( {dayJobs.map((j,i)=>setOpenId(j.id)} />)}
#ลูกค้า อำเภอสาขา ประเภทสินค้า ช่วงเวลาสถานะทีมช่าง
) : (
{dayJobs.map((j,i)=>setOpenId(j.id)} />)}
)} {/* sticky summary */}
สรุปงานวันนี้ (อัตโนมัติ)
)} {openId && setOpenId(null)} />}
); } // ============ Calendar ============ function CalendarScreen(){ const { jobs, device, tweaks, navigate } = useCK(); const base = new Date(CK.TODAY+'T00:00:00'); const [ym,setYm] = React.useState({ y:base.getFullYear(), m:base.getMonth() }); const isMobile = device==='mobile'; const style = tweaks.calendarStyle; const first = new Date(ym.y, ym.m, 1); const startPad = first.getDay(); const daysIn = new Date(ym.y, ym.m+1, 0).getDate(); const cells = []; for (let i=0;icomputeDayStatus(jobs,d).count)); function step(n){ let m=ym.m+n, y=ym.y; if(m<0){m=11;y--;} if(m>11){m=0;y++;} setYm({y,m}); } const heat = (pct)=>`rgba(220,38,38,${0.08 + pct/100*0.55})`; return (
{isMobile ?

ปฏิทินคิวงาน

: }
{CK.TH_MON_FULL[ym.m]} {ym.y+543}
{['อา','จ','อ','พ','พฤ','ศ','ส'].map((d,i)=>(
{d}
))}
{cells.map((d,i)=>{ if(!d) return
; const day = new Date(d+'T00:00:00').getDate(); const ds = computeDayStatus(jobs,d); const isToday = d===CK.TODAY; const empty = ds.count===0 && !ds.closed; const sc = CK.DAYSTATUS[ds.status]; const bg = style==='heat' && !empty ? heat(ds.pct) : undefined; return ( ); })}
{/* legend */}
{Object.values(CK.DAYSTATUS).map(s=>( {s.th} ))}
); } Object.assign(window, { DailyQueueScreen, CalendarScreen, DateStepper, CapacityBar, sortQueue });