/* HQ screens: CoverSheet, Assignment */
// ================= Cover Sheet =================
function groupJobs(jobs, by){
if (by==='none') return [{ key:'all', label:'รายการทั้งหมด', jobs }];
const m = new Map();
jobs.forEach(j=>{
let key, label;
if (by==='branch'){ const b=CK.branch(j.branch); key=j.branch; label=`${b?.code} ${b?.name}`; }
else if (by==='district'){ key=j.district; label=`อ.${j.district}`; }
else { const t=CK.team(j.team); key=j.team||'none'; label=t?t.name:'ยังไม่มอบหมายช่าง'; }
if(!m.has(key)) m.set(key,{key,label,jobs:[]});
m.get(key).jobs.push(j);
});
return [...m.values()];
}
function CoverSheetScreen(){
const { jobs, toast, device } = useCK();
const isMobile = device==='mobile';
const [date,setDate] = React.useState(CK.TODAY);
const [by,setBy] = React.useState('district');
const dayJobs = sortQueue(jobs.filter(j=>j.date===date && j.status!=='cancelled'));
const groups = groupJobs(dayJobs, by);
const s = computeSummary(dayJobs);
const byOpts = [['district','อำเภอ'],['branch','สาขา'],['team','ทีมช่าง'],['none','ไม่จัดกลุ่ม']];
return (
{isMobile ?
ใบปะหน้ารายวัน
:
toast('กำลังส่งออก Excel (.xlsx)','success')}>Excel
toast('กำลังส่งออก PDF','success')}>PDF
window.print()}>พิมพ์
}
จัดกลุ่มตาม
{byOpts.map(([k,l])=>(
))}
{/* PRINT AREA */}
ใบปะหน้างานติดตั้ง / บริการ
บริษัท เจริญกิจ อิเล็คทริค จำกัด · เครื่องใช้ไฟฟ้าและงานบริการ
{CK.thDate(date,{withDow:true,full:true})}
จัดกลุ่มตาม{byOpts.find(o=>o[0]===by)[1]} · {dayJobs.length} งาน
{groups.map(g=>(
{g.label}
({g.jobs.length} งาน)
| # |
ลูกค้า / เบอร์โทร |
ที่อยู่ / อำเภอ |
สาขา |
สินค้า / รุ่น / BTU |
จำนวน |
หมายเหตุ |
ทีมช่าง |
จัดของ |
{g.jobs.map((j,i)=>{ const b=CK.branch(j.branch); const t=CK.team(j.team); const jt=CK.jobType(j.jobType);
const qty = j.items.reduce((a,it)=>a+(it.qty||1),0);
return (
| {i+1} |
{j.customer} {j.phone} |
อ.{j.district} |
{b?.code} |
{jt?.th} · {j.items.map(it=>`${CK.product(it.p)?.th}${it.btu?' '+it.btu:''}${it.model?' '+it.model:''}`).join(', ')} |
{qty} |
{[j.routeNote,j.urgency==='urgent'?'⚡ด่วน':''].filter(Boolean).join(' · ')} |
{t?t.name.split('—')[0].trim():'—'} |
{j.prepared?'☑':'☐'} |
);
})}
))}
สรุป:
{s.lines.map((l,i)=>{l.label} {l.qty} {l.unit})}
รวม {s.totalJobs} งาน
ผู้จัดคิว ......................................
ผู้ตรวจสอบ ......................................
ผู้รับสินค้า ......................................
);
}
// ================= Assignment =================
function TeamColumn({ team, jobs, onDrop, onUnassign, dragMethod }){
const [over,setOver] = React.useState(false);
const load = Math.round(jobs.reduce((s,j)=>s+CK.jobUnits(j),0)*10)/10;
const pct = Math.min(100, Math.round(load/team.capacity*100));
const stat = pct>=100?'full':pct>=80?'almost':'open';
const sc = CK.DAYSTATUS[stat];
return (
{e.preventDefault();setOver(true);}:undefined}
onDragLeave={dragMethod?()=>setOver(false):undefined}
onDrop={dragMethod?e=>{e.preventDefault();setOver(false);onDrop(e.dataTransfer.getData('id'));}:undefined}
className={`rounded-2xl ring-1 transition flex flex-col ${over?'ring-2 ring-brand-500 bg-brand-50/40':'ring-slate-200 bg-white'}`}>
{jobs.length===0 &&
{dragMethod?'ลากงานมาวางที่นี่':'ยังไม่มีงาน'}
}
{jobs.map(j=>(
{j.customer}
อ.{j.district} · {itemsShort(j.items)}
))}
);
}
function AssignScreen(){
const { jobs, assign, updateJob, tweaks, toast, device } = useCK();
const isMobile = device==='mobile';
const [date,setDate] = React.useState(CK.TODAY);
const dragMethod = tweaks.assignMethod==='drag';
const [sel,setSel] = React.useState(null); // selected pool job (select mode)
const dayJobs = jobs.filter(j=>j.date===date && j.status!=='cancelled');
const pool = sortQueue(dayJobs.filter(j=>!j.team));
const byTeam = id => dayJobs.filter(j=>j.team===id);
function doAssign(jobId, teamId){ assign(jobId, teamId); setSel(null); toast('มอบหมายงานให้ทีมช่างแล้ว','success'); }
function unassign(jobId){ updateJob(jobId,{team:null, status:'ready'}); }
return (
{isMobile ?
มอบหมายงานช่าง
:
}
{isMobile &&
}
{/* Pool */}
งานรอมอบหมาย
{pool.length}
{pool.length===0 &&
}
{pool.map(j=>(
e.dataTransfer.setData('id',j.id):undefined}
onClick={!dragMethod?()=>setSel(sel===j.id?null:j.id):undefined}
className={`rounded-xl p-2.5 ring-1 transition ${dragMethod?'cursor-grab active:cursor-grabbing':'cursor-pointer'} ${sel===j.id?'ring-2 ring-brand-500 bg-brand-50':'ring-slate-200 bg-white hover:ring-brand-300'}`}>
{dragMethod &&
}
{j.customer}{j.urgency==='urgent'&&}
อ.{j.district} · {CK.jobType(j.jobType)?.th} · {itemsShort(j.items)}
{!dragMethod && sel===j.id && (
{CK.TEAMS.map(t=>(
))}
)}
))}
{/* Teams */}
{CK.TEAMS.map(t=>(
doAssign(id,t.id)} onUnassign={unassign} />
))}
);
}
Object.assign(window, { CoverSheetScreen, AssignScreen, groupJobs });