ソースを参照

Add filters to staff allocation

tags/Baseline_30082024_FRONTEND_UAT
Wayne 1年前
コミット
a98e364b02
1個のファイルの変更72行の追加15行の削除
  1. +72
    -15
      src/components/CreateProject/StaffAllocation.tsx

+ 72
- 15
src/components/CreateProject/StaffAllocation.tsx ファイルの表示

@@ -24,8 +24,10 @@ import {
TabsProps,
Tab,
Tabs,
SelectChangeEvent,
} from "@mui/material";
import differenceBy from "lodash/differenceBy";
import uniq from "lodash/uniq";

interface StaffResult {
id: string;
@@ -100,16 +102,17 @@ const StaffAllocation: React.FC<Props> = ({
const [selectedStaff, setSelectedStaff] = React.useState<
typeof filteredStaff
>(initiallySelectedStaff);
const filters = React.useMemo<(keyof StaffResult)[]>(
() => ["team", "grade"],
[],
);

// 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([]);
}, []);

const staffPoolColumns = React.useMemo<Column<StaffResult>[]>(
() => [
@@ -145,6 +148,7 @@ const StaffAllocation: React.FC<Props> = ({
[removeStaff, t],
);

// Query related
const [query, setQuery] = React.useState("");
const onQueryInputChange = React.useCallback<
React.ChangeEventHandler<HTMLInputElement>
@@ -154,18 +158,55 @@ const StaffAllocation: React.FC<Props> = ({
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<string>) => {
setFilters((f) => ({ ...f, [filter]: event.target.value }));
},
[],
);

React.useEffect(() => {
setFilteredStaff(
allStaff.filter(
(staff) =>
staff.name.toLowerCase().includes(query) ||
staff.id.toLowerCase().includes(query) ||
staff.title.toLowerCase().includes(query),
),
allStaff.filter((staff) => {
const q = query.toLowerCase();
return (
(staff.name.toLowerCase().includes(q) ||
staff.id.toLowerCase().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, query]);
}, [allStaff, filters, query]);

// Tab related
const [tabIndex, setTabIndex] = React.useState(0);
const handleTabChange = React.useCallback<NonNullable<TabsProps["onChange"]>>(
(_e, newValue) => {
@@ -174,6 +215,12 @@ const StaffAllocation: React.FC<Props> = ({
[],
);

const reset = React.useCallback(() => {
clearQueryInput();
clearStaff();
setFilters(defaultFilterValues);
}, [clearQueryInput, clearStaff, defaultFilterValues]);

return (
<Card>
<CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
@@ -201,7 +248,7 @@ const StaffAllocation: React.FC<Props> = ({
}}
/>
</Grid>
{filters.map((filter, idx) => {
{columnFilters.map((filter, idx) => {
const label = staffPoolColumns.find(
(c) => c.name === filter,
)!.label;
@@ -210,8 +257,18 @@ const StaffAllocation: React.FC<Props> = ({
<Grid key={`${filter.toString()}-${idx}`} item xs={3}>
<FormControl fullWidth>
<InputLabel size="small">{label}</InputLabel>
<Select label={label} size="small">
<Select
label={label}
size="small"
value={filters[filter]}
onChange={makeFilterSelect(filter)}
>
<MenuItem value={"All"}>{t("All")}</MenuItem>
{filterValues[filter]?.map((option, index) => (
<MenuItem key={`${option}-${index}`} value={option}>
{option}
</MenuItem>
))}
</Select>
</FormControl>
</Grid>
@@ -220,7 +277,7 @@ const StaffAllocation: React.FC<Props> = ({
</Grid>
<Tabs value={tabIndex} onChange={handleTabChange}>
<Tab label={t("Staff Pool")} />
<Tab label={t("Allocated Staff")} />
<Tab label={`${t("Allocated Staff")} (${selectedStaff.length})`} />
</Tabs>
<Box sx={{ marginInline: -3 }}>
{tabIndex === 0 && (
@@ -240,7 +297,7 @@ const StaffAllocation: React.FC<Props> = ({
</Box>
</Stack>
<CardActions sx={{ justifyContent: "flex-end" }}>
<Button variant="text" startIcon={<RestartAlt />}>
<Button variant="text" startIcon={<RestartAlt />} onClick={reset}>
{t("Reset")}
</Button>
</CardActions>


読み込み中…
キャンセル
保存