import { useMemo, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import { Header, PageLayout } from "../../components/layout/Header"; import { useAuthStore } from "../../store/auth"; import { PanelMenu } from "../../components/PanelMenu"; import { accountMenuItems, useLogout } from "./panelMenu"; import { InventoryTopNav } from "./InventoryTopNav"; import { useInventoryData, unitName, whName } from "./useInventoryData"; import { faNum } from "../../lib/formatters"; import { gregorianToJalali, MONTHS, toFa } from "../../lib/jalali"; import type { InventoryTransaction } from "../../lib/types"; function gregKey(d: Date): string { return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`; } function todayKey(): string { return gregKey(new Date()); } // کنترل روزانه — پورت کامل تقویم شمسی نسخه‌ی ارسالی export function DailyControlPage() { const location = useLocation(); const logout = useLogout(); const user = useAuthStore((s) => s.user); const data = useInventoryData(); const navigate = useNavigate(); const isPM = user?.role === "pm"; const [anchor, setAnchor] = useState(new Date()); const [sel, setSel] = useState(todayKey()); const [actRec, setActRec] = useState(null); // فیلتر پروژه — فقط برای مدیر تدارکات/ادمین (مدیر پروژه به پروژه خودش محدود است) const isAdmin = user?.role === "admin" || user?.role === "procurement_manager"; const [projFilter, setProjFilter] = useState(""); const txByDay = useMemo(() => { const map = new Map(); const projWhIds = projFilter ? new Set(data.warehouses.filter((w) => String(w.project_id) === String(projFilter)).map((w) => w.id)) : null; data.transactions.forEach((t) => { if (projWhIds && !projWhIds.has(t.warehouse_id)) return; const k = gregKey(new Date(t.transaction_date)); const arr = map.get(k) || []; arr.push(t); map.set(k, arr); }); map.forEach((arr) => arr.sort((a, b) => new Date(a.transaction_date).getTime() - new Date(b.transaction_date).getTime())); return map; }, [data.transactions, data.warehouses, projFilter]); // cells: 42 روز از شنبه قبلِ اولین روز ماه جلالی const cells = useMemo(() => { const [ty, tm] = gregorianToJalali(anchor.getFullYear(), anchor.getMonth() + 1, anchor.getDate()); let first: Date | null = null; for (let i = 0; i <= 33; i++) { const d = new Date(anchor.getTime() - i * 86400000); const [py, pm] = gregorianToJalali(d.getFullYear(), d.getMonth() + 1, d.getDate()); if (py !== ty || pm !== tm) { first = new Date(anchor.getTime() - (i - 1) * 86400000); break; } } if (!first) first = new Date(anchor.getTime() - 33 * 86400000); const offset = (first.getDay() + 1) % 7; // شنبه = 0 const gridStart = new Date(first.getTime() - offset * 86400000); const out: { d: Date; inMonth: boolean; isToday: boolean; n: number }[] = []; for (let c = 0; c < 42; c++) { const day = new Date(gridStart.getTime() + c * 86400000); const [jy, jm] = gregorianToJalali(day.getFullYear(), day.getMonth() + 1, day.getDate()); const k = gregKey(day); out.push({ d: day, inMonth: jy === ty && jm === tm, isToday: k === todayKey(), n: (txByDay.get(k) || []).length, }); } return out; }, [anchor, txByDay]); const [ty, tm] = gregorianToJalali(anchor.getFullYear(), anchor.getMonth() + 1, anchor.getDate()); const monthTitle = `${toFa(ty)} ${MONTHS[tm - 1]}`; const dayTx = txByDay.get(sel) || []; const withdrawals = dayTx.filter((t) => t.transaction_type === "WITHDRAWAL"); const wGroups = useMemo(() => { const gmap = new Map(); withdrawals.forEach((t) => { const g = gmap.get(t.inventory_id); if (!g) { gmap.set(t.inventory_id, { recId: t.inventory_id, q: Math.abs(t.quantity_number || 0), last: t.transaction_date, tx: t }); } else { g.q += Math.abs(t.quantity_number || 0); if (t.transaction_date > g.last) g.last = t.transaction_date; } }); return [...gmap.values()]; }, [withdrawals]); const isToday = sel === todayKey(); const selDate = new Date(Number(sel.split("-")[0]), Number(sel.split("-")[1]) - 1, Number(sel.split("-")[2])); return (
: undefined} actions={isAdmin || isPM ? : undefined} /> {isAdmin && (
{projFilter ? "نمایش کنترل روزانه فقط برای پروژه انتخابی" : "نمایش کنترل روزانه همه پروژه‌ها"}
)}
{/* تقویم */}
📅 {monthTitle}
{["ش", "ی", "د", "س", "چ", "پ", "ج"].map((d) => (
{d}
))} {cells.map((c, i) => { const [jd] = gregorianToJalali(c.d.getFullYear(), c.d.getMonth() + 1, c.d.getDate()); const k = gregKey(c.d); return ( ); })}
{/* برداشت‌های روز */}

🕘 کنترل روزانه — {isToday ? "امروز" : ""} {faNum(selDate.getDate())} {MONTHS[selDate.getMonth()]} {toFa(selDate.getFullYear())}

▼ برداشت‌ها: {faNum(wGroups.length)} قلم

مواردی که این روز از انبار برداشت و به ساختمان برده شده‌اند. روی هر مورد بزنید و برگشت / مفقودی / اتلاف را انتخاب کنید.

{!wGroups.length ? (
{isToday ? "امروز هنوز برداشتی ثبت نشده است." : "در این روز برداشتی ثبت نشده است."} هر برداشتی که در «تغییر موجودی» ثبت کنید، همین‌جا نمایش داده می‌شود.
) : (
{wGroups.map((g) => (
{actRec === g.recId && isPM && (
)}
))}
)}
); }