"use client"; import { useTranslation } from "react-i18next"; import React, { useEffect } from "react"; import RestartAlt from "@mui/icons-material/RestartAlt"; import SearchResults, { Column } from "../SearchResults"; import { Search, Clear, PersonAdd, PersonRemove } from "@mui/icons-material"; import { Stack, Typography, Grid, TextField, InputAdornment, IconButton, FormControl, InputLabel, Select, MenuItem, Box, Button, Card, CardActions, CardContent, TabsProps, Tab, Tabs, SelectChangeEvent, } from "@mui/material"; import differenceBy from "lodash/differenceBy"; import uniq from "lodash/uniq"; import ResourceCapacity from "./ResourceCapacity"; import { useFormContext } from "react-hook-form"; import { CreateProjectInputs } from "@/app/api/projects/actions"; interface StaffResult { id: number; name: string; team: string; grade: string; title: string; } const mockStaffs: StaffResult[] = [ { name: "Albert", grade: "1", id: 1, team: "ABC", title: "Associate Quantity Surveyor", }, { name: "Bernard", grade: "2", id: 2, team: "ABC", title: "Quantity Surveyor", }, { name: "Carl", grade: "3", id: 3, team: "XYZ", title: "Senior Quantity Surveyor", }, { name: "Denis", grade: "4", id: 4, team: "ABC", title: "Manager" }, { name: "Edward", grade: "5", id: 5, team: "ABC", title: "Director" }, { name: "Fred", grade: "1", id: 6, team: "XYZ", title: "General Laborer" }, { name: "Gordon", grade: "2", id: 7, team: "ABC", title: "Inspector" }, { name: "Heather", grade: "3", id: 8, team: "XYZ", title: "Field Engineer", }, { name: "Ivan", grade: "4", id: 9, team: "ABC", title: "Senior Manager" }, { name: "Jackson", grade: "5", id: 10, team: "XYZ", title: "Senior Director", }, { name: "Kurt", grade: "1", id: 11, team: "ABC", title: "Construction Assistant", }, { name: "Lawrence", grade: "2", id: 12, team: "ABC", title: "Operator" }, ]; interface Props { allStaff?: StaffResult[]; isActive: boolean; } const StaffAllocation: React.FC = ({ allStaff = mockStaffs, isActive, }) => { const { t } = useTranslation(); const { setValue, getValues } = useFormContext(); const [filteredStaff, setFilteredStaff] = React.useState(allStaff); const [selectedStaff, setSelectedStaff] = React.useState< typeof filteredStaff >( allStaff.filter((staff) => getValues("allocatedStaffIds").includes(staff.id), ), ); // Adding / Removing staff const addStaff = React.useCallback((staff: StaffResult) => { setSelectedStaff((staffs) => [...staffs, staff]); }, []); const removeStaff = React.useCallback((staff: StaffResult) => { setSelectedStaff((staffs) => staffs.filter((s) => s.id !== staff.id)); }, []); const clearStaff = React.useCallback(() => { setSelectedStaff([]); }, []); // Sync with form useEffect(() => { setValue( "allocatedStaffIds", selectedStaff.map((staff) => staff.id), ); }, [selectedStaff, setValue]); const staffPoolColumns = React.useMemo[]>( () => [ { label: t("Add"), name: "id", onClick: addStaff, buttonIcon: , }, { label: t("Staff ID"), name: "id" }, { label: t("Staff Name"), name: "name" }, { label: t("Team"), name: "team" }, { label: t("Grade"), name: "grade" }, { label: t("Title"), name: "title" }, ], [addStaff, t], ); const allocatedStaffColumns = React.useMemo[]>( () => [ { label: t("Remove"), name: "id", onClick: removeStaff, buttonIcon: , }, { label: t("Staff ID"), name: "id" }, { label: t("Staff Name"), name: "name" }, { label: t("Team"), name: "team" }, { label: t("Grade"), name: "grade" }, { label: t("Title"), name: "title" }, ], [removeStaff, t], ); // Query related const [query, setQuery] = React.useState(""); const onQueryInputChange = React.useCallback< React.ChangeEventHandler >((e) => { setQuery(e.target.value); }, []); const clearQueryInput = React.useCallback(() => { setQuery(""); }, []); const columnFilters = React.useMemo<(keyof StaffResult)[]>( () => ["team", "grade"], [], ); const filterValues = React.useMemo(() => { return columnFilters.reduce<{ [filter in keyof StaffResult]?: string[] }>( (acc, filter) => { return { ...acc, [filter]: uniq(allStaff.map((staff) => staff[filter])), }; }, {}, ); }, [columnFilters, allStaff]); const defaultFilterValues = React.useMemo(() => { return columnFilters.reduce<{ [filter in keyof StaffResult]?: string }>( (acc, filter) => { return { ...acc, [filter]: "All" }; }, {}, ); }, [columnFilters]); const [filters, setFilters] = React.useState(defaultFilterValues); const makeFilterSelect = React.useCallback( (filter: keyof StaffResult) => (event: SelectChangeEvent) => { setFilters((f) => ({ ...f, [filter]: event.target.value })); }, [], ); React.useEffect(() => { setFilteredStaff( allStaff.filter((staff) => { const q = query.toLowerCase(); return ( (staff.name.toLowerCase().includes(q) || staff.id.toString().includes(q) || staff.title.toLowerCase().includes(q)) && Object.entries(filters).every(([filterKey, filterValue]) => { const staffColumnValue = staff[filterKey as keyof StaffResult]; return staffColumnValue === filterValue || filterValue === "All"; }) ); }), ); }, [allStaff, filters, query]); // Tab related const [tabIndex, setTabIndex] = React.useState(0); const handleTabChange = React.useCallback>( (_e, newValue) => { setTabIndex(newValue); }, [], ); const reset = React.useCallback(() => { clearQueryInput(); clearStaff(); setFilters(defaultFilterValues); }, [clearQueryInput, clearStaff, defaultFilterValues]); return ( <> {t("Staff Allocation")} ), }} /> {columnFilters.map((filter, idx) => { const label = staffPoolColumns.find( (c) => c.name === filter, )!.label; return ( {label} ); })} {tabIndex === 0 && ( )} {tabIndex === 1 && ( )} ); }; export default StaffAllocation;