/* App root: store, context, router, tweaks, render */ const DEFAULT_TWEAKS = { calendarStyle: 'badge', // badge | dot | heat queueLayout: 'card', // card | table assignMethod: 'select', // select | drag dashboardStyle:'charts', // charts | cards headerTheme: 'red', // red | dark deviceFrame: true, // show phone bezel in mobile view accent: '#dc2626', }; function useStore() { const [jobs, setJobs] = React.useState(() => CK.JOBS.map(j => ({ ...j }))); const [toasts, setToasts] = React.useState([]); const toast = React.useCallback((msg, kind='info') => { const id = Math.random().toString(36).slice(2); setToasts(t => [...t, { id, msg, kind }]); setTimeout(() => setToasts(t => t.filter(x => x.id !== id)), 3200); }, []); const addJob = React.useCallback((job) => { setJobs(j => [{ ...job }, ...j]); toast('บันทึกงานใหม่เรียบร้อย • แจ้งสำนักงานใหญ่แบบ real-time', 'success'); }, [toast]); const updateJob = React.useCallback((id, patch) => { setJobs(j => j.map(x => x.id === id ? { ...x, ...patch } : x)); }, []); const setStatus = React.useCallback((id, status, note='', by='ผู้ใช้ปัจจุบัน') => { setJobs(j => j.map(x => { if (x.id !== id) return x; const entry = { by, from: x.status, to: status, note, at: new Date().toLocaleString('th-TH', { day:'2-digit', month:'short', hour:'2-digit', minute:'2-digit' }) }; return { ...x, status, log: [...(x.log||[]), entry] }; })); toast('อัปเดตสถานะเป็น "' + CK.STATUS[status].th + '"', 'success'); }, [toast]); const assign = React.useCallback((id, teamId) => { setJobs(j => j.map(x => x.id === id ? { ...x, team: teamId, status: x.status==='cancelled'?x.status:'assigned' } : x)); }, []); return { jobs, addJob, updateJob, setStatus, assign, toast, toasts }; } function Toasts() { const { toasts } = useCK(); return (