mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 06:59:01 +00:00
119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
|
|
import { useMemo } from "react";
|
||
|
|
import { Popover, Skeleton } from "@mui/material";
|
||
|
|
import { ChevronDown, Users } from "lucide-react";
|
||
|
|
import type { WorkOrderUser } from "@/domain/work-orders/types/work-order";
|
||
|
|
import { CheckboxMenuItem } from "@/components/ui/checkbox-menu-item";
|
||
|
|
import { MenuAnchorButton } from "@/components/ui/menu-anchor-button";
|
||
|
|
import { useMenuAnchor } from "@/hooks/use-menu-anchor";
|
||
|
|
import type { DashboardScope } from "./dashboard-scope";
|
||
|
|
|
||
|
|
type DashboardScopePickerProps = {
|
||
|
|
scope: DashboardScope;
|
||
|
|
onChange: (scope: DashboardScope) => void;
|
||
|
|
users: WorkOrderUser[];
|
||
|
|
usersLoading?: boolean;
|
||
|
|
currentUserId?: string | number;
|
||
|
|
};
|
||
|
|
|
||
|
|
export function DashboardScopePicker({
|
||
|
|
scope,
|
||
|
|
onChange,
|
||
|
|
users,
|
||
|
|
usersLoading = false,
|
||
|
|
currentUserId,
|
||
|
|
}: DashboardScopePickerProps) {
|
||
|
|
const { anchorEl, open, setAnchor, close } = useMenuAnchor();
|
||
|
|
const meId = currentUserId != null && currentUserId !== "" ? String(currentUserId) : null;
|
||
|
|
|
||
|
|
const dispatchers = useMemo(
|
||
|
|
() => [...users].sort((a, b) => a.name.localeCompare(b.name)),
|
||
|
|
[users],
|
||
|
|
);
|
||
|
|
|
||
|
|
const label = useMemo(() => {
|
||
|
|
if (scope.mode === "all") return "All dispatchers";
|
||
|
|
if (scope.mode === "mine") return "My WOs";
|
||
|
|
return dispatchers.find((user) => String(user.id) === scope.id)?.name ?? "Dispatcher";
|
||
|
|
}, [scope, dispatchers]);
|
||
|
|
|
||
|
|
const select = (next: DashboardScope) => {
|
||
|
|
onChange(next);
|
||
|
|
close();
|
||
|
|
};
|
||
|
|
|
||
|
|
if (usersLoading && users.length === 0) {
|
||
|
|
return (
|
||
|
|
<Skeleton
|
||
|
|
variant="rounded"
|
||
|
|
width={140}
|
||
|
|
height={18}
|
||
|
|
animation="wave"
|
||
|
|
aria-label="Loading dispatchers"
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<MenuAnchorButton
|
||
|
|
onAnchor={setAnchor}
|
||
|
|
open={open}
|
||
|
|
className="flex w-auto shrink-0 items-center gap-1.5 whitespace-nowrap transition-colors"
|
||
|
|
style={{ fontSize: 13, fontWeight: 500, color: "var(--muted-foreground)" }}
|
||
|
|
aria-haspopup="listbox"
|
||
|
|
>
|
||
|
|
<Users size={13} aria-hidden style={{ color: "var(--muted-foreground)" }} />
|
||
|
|
{label}
|
||
|
|
<ChevronDown size={13} aria-hidden style={{ color: "var(--muted-foreground)" }} />
|
||
|
|
</MenuAnchorButton>
|
||
|
|
|
||
|
|
<Popover
|
||
|
|
open={open}
|
||
|
|
anchorEl={anchorEl}
|
||
|
|
onClose={close}
|
||
|
|
anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
|
||
|
|
transformOrigin={{ vertical: "top", horizontal: "left" }}
|
||
|
|
slotProps={{
|
||
|
|
paper: {
|
||
|
|
className: "mt-1 w-[220px] rounded-lg border border-border p-1.5 shadow-md",
|
||
|
|
},
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<CheckboxMenuItem
|
||
|
|
checked={scope.mode === "all"}
|
||
|
|
label="All dispatchers"
|
||
|
|
onClick={() => select({ mode: "all" })}
|
||
|
|
/>
|
||
|
|
|
||
|
|
{meId != null && (
|
||
|
|
<CheckboxMenuItem
|
||
|
|
checked={scope.mode === "mine"}
|
||
|
|
label="My WOs only"
|
||
|
|
labelClassName="font-medium text-primary"
|
||
|
|
className="mb-1 pb-2"
|
||
|
|
style={{ borderBottom: "1px solid var(--color-border)" }}
|
||
|
|
onClick={() => select({ mode: "mine" })}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
|
||
|
|
{dispatchers.map((user) => {
|
||
|
|
const id = String(user.id);
|
||
|
|
return (
|
||
|
|
<CheckboxMenuItem
|
||
|
|
key={id}
|
||
|
|
checked={scope.mode === "individual" && scope.id === id}
|
||
|
|
label={user.name}
|
||
|
|
right={
|
||
|
|
meId === id ? (
|
||
|
|
<span className="text-[10px] text-muted-foreground">me</span>
|
||
|
|
) : undefined
|
||
|
|
}
|
||
|
|
onClick={() => select({ mode: "individual", id })}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
})}
|
||
|
|
</Popover>
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
}
|