"use client"; import { useAuth } from "@/lib/auth-context"; import { DEPARTMENTS } from "@/lib/constants"; import { useShift } from "@/lib/shift-context"; import { useQuery } from "@tanstack/react-query"; import { useEffect, useState } from "react"; import type { ShiftDetailModalProps } from "./ShiftSchedule.types"; function parseShiftDate(date: Date | string | undefined): Date | null { if (!date) return null; // Date object → dùng thẳng if (date instanceof Date) return isNaN(date.getTime()) ? null : date; // ISO string hoặc "YYYY-MM-DD" → chỉ lấy 10 ký tự đầu tránh lệch timezone const [y, m, d] = (date as string).slice(0, 10).split("-").map(Number); if (!y || !m || !d) return null; return new Date(y, m - 1, d); } export default function ShiftDetailModal({ shift, isOpen, onClose, }: ShiftDetailModalProps) { const { user } = useAuth(); const { registerShift, unregisterShift, deleteShift } = useShift(); const [error, setError] = useState(null); const [success, setSuccess] = useState(null); if (!isOpen || !shift) return null; // const dept = DEPARTMENTS.find((d) => d.id === shift.department); const isManager = user?.role === "manager"; const registeredStaff = shift.registeredStaff ?? []; const isRegistered = user ? registeredStaff.some((s) => s.id === user.id) : false; const isFull = registeredStaff.length >= shift.maxStaff; const handleRegister = async () => { if (!user) return; setError(null); setSuccess(null); const result = await registerShift(shift.id, user.id, user.name); if (result.success) { setSuccess("Shift registered successfully!"); setTimeout(onClose, 1200); } else { setError(result.error ?? "An error occurred."); } }; const handleUnregister = () => { if (!user) return; setError(null); unregisterShift(shift.id, user.id); setSuccess("Shift registration cancelled."); setTimeout(onClose, 1200); }; const handleManagerUnregister = (staffId: string) => { unregisterShift(shift.id, staffId); setSuccess("Staff removed from shift."); }; const handleDelete = async () => { await deleteShift(shift.id); onClose(); }; const statusLabel = { available: "Available", registered: "Registered", approved_leave: "On leave", absent: "Absent", }; const statusColor = { available: "bg-blue-100 text-blue-700", registered: "bg-blue-200 text-blue-900", approved_leave: "bg-purple-100 text-purple-700", absent: "bg-red-100 text-red-700", }; const StaffName = ({ staffId }: { staffId: string }) => { const [name, setName] = useState(""); const [loading, setLoading] = useState(true); useEffect(() => { // Hàm gọi API const getName = async () => { try { setLoading(true); const response = await fetch(`/api/staff/${staffId}`); if (!response.ok) { throw new Error("Mạng lỗi hoặc không tìm thấy nhân viên"); } const data = await response.json(); setName(data["name"]); } catch (error) { console.error("Lỗi khi lấy tên:", error); setName("Lỗi tải tên"); } finally { setLoading(false); } }; if (staffId) { getName(); } }, [staffId]); // Chạy lại nếu staffId thay đổi if (loading) return ...; return {name || "N/A"}; }; return (
{/* Backdrop */}
{/* Modal */}
{/* Header */}
{/* {dept && } */}

Shift Details

{/*

{dept?.name}

*/}
{/* Body */}
{/* Status badge */} {/*
{statusLabel[shift.status]}
*/} {/* Shift info grid */}

Date

{parseShiftDate( shift.date as Date | string | undefined, )?.toLocaleDateString("vi-VN", { weekday: "long", day: "2-digit", month: "2-digit", year: "numeric", }) ?? "—"}

Working hours

{shift.startTime} – {shift.endTime}

Duration

{""} giờ

Shift wage

{(shift.wage ?? 0).toLocaleString("vi-VN")} VND

{/* Registered staff */}

Registered staff ({registeredStaff.length}/{shift.maxStaff})

{registeredStaff.length === 0 ? (

No staff registered yet

) : (
{registeredStaff.map((staff) => (
{isManager && ( )}
))}
)}
{/* Feedback messages */} {error && (
{error}
)} {success && (
{success}
)}
{/* Footer actions */}
{!isManager && !isRegistered && !isFull && ( )} {isRegistered && ( )} {isManager && ( )}
); }