"use client" import { useState } from "react" import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query" import { useAuthApi } from "@/shared/useApi" import { EMPLOYEE_ROUTES } from "@garage/api" import { Button } from "@/shared/components/ui/button" import { Checkbox } from "@/shared/components/ui/checkbox" import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card" import { Badge } from "@/shared/components/ui/badge" import { toast } from "sonner" import { Save, ShieldCheck } from "lucide-react" import DashboardPage from "@/base/components/layout/dashboard/dashboard-page" // ── Permission resource groups ── const PERMISSION_GROUPS: { label: string; key: string }[] = [ { label: "Appointments", key: "appointments" }, { label: "Bills", key: "bills" }, { label: "Check Point Labels", key: "check_point_labels" }, { label: "Credit Notes", key: "credit_notes" }, { label: "Customers", key: "customers" }, { label: "Departments", key: "departments" }, { label: "Document Types", key: "document_types" }, { label: "Employees", key: "employees" }, { label: "Estimates", key: "estimates" }, { label: "Expense Items", key: "expense_items" }, { label: "Expenses", key: "expenses" }, { label: "Holidays", key: "holidays" }, { label: "Inspection Categories", key: "inspection_categories" }, { label: "Inspection Check Points", key: "inspection_check_points" }, { label: "Inspections", key: "inspections" }, { label: "Insurance Types", key: "insurance_types" }, { label: "Inventory Adjustments", key: "inventory_adjustments" }, { label: "Inventory Categories", key: "inventory_categories" }, { label: "Invoice Documents", key: "invoice_documents" }, { label: "Invoice Labels", key: "invoice_labels" }, { label: "Invoice Notes", key: "invoice_notes" }, { label: "Invoice Sequences", key: "invoice_sequences" }, { label: "Invoices", key: "invoices" }, { label: "Job Cards", key: "job_cards" }, { label: "Labels", key: "labels" }, { label: "Labor Rates", key: "labor_rates" }, { label: "Make & Models", key: "make_and_models" }, { label: "Parts", key: "parts" }, { label: "Payment Mades", key: "payment_mades" }, { label: "Payment Modes", key: "payment_modes" }, { label: "Payment Received", key: "payment_recieveds" }, { label: "Payment Terms", key: "payment_terms" }, { label: "Purchase Orders", key: "purchase_orders" }, { label: "Quick Notes", key: "quick_notes" }, { label: "Quick Remarks", key: "quick_remarks" }, { label: "Reasons", key: "reasons" }, { label: "Referral Sources", key: "referral_sources" }, { label: "Service Group Includes", key: "service_group_includes" }, { label: "Service Group Parts", key: "service_group_parts" }, { label: "Service Group Pricings", key: "service_group_pricings" }, { label: "Service Group Services", key: "service_group_services" }, { label: "Service Groups", key: "service_groups" }, { label: "Services", key: "services" }, { label: "Settings", key: "settings" }, { label: "Shop Calendars", key: "shop_calenders" }, { label: "Shop Timings", key: "shop_timings" }, { label: "Shop Types", key: "shop_types" }, { label: "Task Sections", key: "task_sections" }, { label: "Task Types", key: "task_types" }, { label: "Tasks", key: "tasks" }, { label: "Taxes", key: "taxes" }, { label: "Time Sheets", key: "time_sheets" }, { label: "Unit Types", key: "unit_types" }, { label: "Vehicle Body Types", key: "vehicle_body_types" }, { label: "Vehicle Colors", key: "vehicle_colors" }, { label: "Vehicle Documents", key: "vehicle_documents" }, { label: "Vehicle Fuel Types", key: "vehicle_fuel_types" }, { label: "Vehicle Mile & Kms", key: "vehicle_mile_and_kms" }, { label: "Vehicle Transmissions", key: "vehicle_transmissions" }, { label: "Vehicles", key: "vehicles" }, { label: "Vendor Credits", key: "vendor_credits" }, { label: "Vendors", key: "vendors" }, ] const ACTIONS = ["view", "create", "update", "delete"] as const type PermissionAction = typeof ACTIONS[number] type PermissionsState = Record function buildPermissionsPayload(state: PermissionsState) { return state } function extractPermissions(data: Record | null | undefined): PermissionsState { if (!data) return {} const result: PermissionsState = {} for (const group of PERMISSION_GROUPS) { for (const action of ACTIONS) { const key = `can_${action}_${group.key}` result[key] = Boolean(data[key]) } } return result } type EmployeePermissionsFormProps = { employeeId: string } export function EmployeePermissionsForm({ employeeId }: EmployeePermissionsFormProps) { const api = useAuthApi() const queryClient = useQueryClient() const queryKey = [EMPLOYEE_ROUTES.BY_ID, employeeId] const { data, isLoading } = useQuery({ queryKey, queryFn: () => api.employees.getById(employeeId), }) const employeeData = (data as any)?.data as Record | undefined const [permissions, setPermissions] = useState(null) const currentPermissions = permissions ?? extractPermissions(employeeData) const { mutate, isPending } = useMutation({ mutationFn: (payload: PermissionsState) => api.employees.updatePermissions(employeeId, payload as never), onSuccess: () => { toast.success("Permissions updated successfully") queryClient.invalidateQueries({ queryKey }) }, onError: () => { toast.error("Failed to update permissions") }, }) const handleToggle = (key: string, value: boolean) => { setPermissions((prev) => ({ ...(prev ?? extractPermissions(employeeData)), [key]: value, })) } const handleRowToggle = (groupKey: string, checked: boolean) => { const updates: PermissionsState = {} for (const action of ACTIONS) { updates[`can_${action}_${groupKey}`] = checked } setPermissions((prev) => ({ ...(prev ?? extractPermissions(employeeData)), ...updates, })) } const handleColumnToggle = (action: PermissionAction, checked: boolean) => { const updates: PermissionsState = {} for (const group of PERMISSION_GROUPS) { updates[`can_${action}_${group.key}`] = checked } setPermissions((prev) => ({ ...(prev ?? extractPermissions(employeeData)), ...updates, })) } const isRowChecked = (groupKey: string) => ACTIONS.every((action) => currentPermissions[`can_${action}_${groupKey}`]) const isRowIndeterminate = (groupKey: string) => { const values = ACTIONS.map((action) => currentPermissions[`can_${action}_${groupKey}`]) return values.some(Boolean) && !values.every(Boolean) } const isColumnChecked = (action: PermissionAction) => PERMISSION_GROUPS.every((g) => currentPermissions[`can_${action}_${g.key}`]) const isColumnIndeterminate = (action: PermissionAction) => { const values = PERMISSION_GROUPS.map((g) => currentPermissions[`can_${action}_${g.key}`]) return values.some(Boolean) && !values.every(Boolean) } const isAllChecked = PERMISSION_GROUPS.every((g) => ACTIONS.every((action) => currentPermissions[`can_${action}_${g.key}`]) ) const isAllIndeterminate = (() => { const values = PERMISSION_GROUPS.flatMap((g) => ACTIONS.map((action) => currentPermissions[`can_${action}_${g.key}`]) ) return values.some(Boolean) && !values.every(Boolean) })() const handleToggleAll = (checked: boolean) => { const updates: PermissionsState = {} for (const group of PERMISSION_GROUPS) { for (const action of ACTIONS) { updates[`can_${action}_${group.key}`] = checked } } setPermissions(updates) } if (isLoading) { return (
Loading permissions...
) } return ( Permissions {ACTIONS.map((action) => ( ))} {PERMISSION_GROUPS.map((group) => ( {ACTIONS.map((action) => { const key = `can_${action}_${group.key}` return ( ) })} ))}
handleToggleAll(Boolean(v))} /> Resource
handleColumnToggle(action, Boolean(v))} /> {action}
handleRowToggle(group.key, Boolean(v))} /> {group.label}
handleToggle(key, Boolean(v))} />
) }