/* 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 });