73 lines
5.1 KiB
JavaScript

import Avatar from "@mui/material/Avatar";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import Alert from "@mui/material/Alert";
import { useCallback, useMemo, useState } from "react";
import { useParams } from "react-router-dom";
import { listOrganizations } from "../api/business.js";
import { useExternalAuth } from "../auth/ExternalAuthProvider.jsx";
import { hasExternalCapability } from "../config/capabilities.js";
import { useExternalI18n } from "../i18n/ExternalI18nProvider.jsx";
import { ExternalPage, ExternalPageState, PagePagination, ResponsiveDataList, StatusChip } from "../shared/PageComponents.jsx";
import { usePagedResource } from "../shared/usePagedResource.js";
const organizationKinds = {
agencies: { capability: "agency:list", titleKey: "organization.agencies" },
bds: { capability: "bd:list", titleKey: "organization.bds" },
"bd-leaders": { capability: "bd-manager:list", titleKey: "organization.bdManagers" },
hosts: { capability: "host:list", titleKey: "organization.hosts" },
managers: { capability: "bd-manager:list", titleKey: "organization.managers" },
"super-admins": { capability: "super-admin:list", titleKey: "organization.superAdmins" },
team: { capability: "team:view", titleKey: "organization.team" }
};
export default function OrganizationPage() {
const { kind = "hosts" } = useParams();
const config = organizationKinds[kind];
const { session } = useExternalAuth();
const { t } = useExternalI18n();
const [keyword, setKeyword] = useState("");
const [query, setQuery] = useState({ keyword: "", page: 1 });
const allowed = Boolean(config && hasExternalCapability(session, config.capability));
const load = useCallback(() => allowed ? listOrganizations(kind, { keyword: query.keyword, page: query.page, page_size: 20 }) : Promise.resolve({ items: [], page: 1, pageSize: 20, total: 0 }), [allowed, kind, query]);
const { data, error, loading, reload } = usePagedResource(load);
const columns = useMemo(() => kind === "team" ? [
{ key: "agency", label: t("organization.agency"), render: (item) => <Box><Typography fontWeight={650}>{t("organization.agencyReference", { id: item.id || "-" })}</Typography><Typography color="text.secondary" variant="caption">{t("organization.owner")} {item.userId || "-"}</Typography></Box> },
{ key: "parent", label: t("organization.parentBd"), render: (item) => item.parentBdUserId || "-" },
{ key: "status", label: t("common.status"), render: (item) => <StatusChip status={item.status} /> }
] : [
{ key: "identity", label: t("organization.member"), render: (item) => <Stack direction="row" spacing={1} sx={{ alignItems: "center" }}><Avatar src={item.avatar}>{(item.name || item.username || "-").slice(0, 1)}</Avatar><Box><Typography fontWeight={650}>{item.name || item.username || "-"}</Typography><Typography color="text.secondary" variant="caption">ID {item.id || "-"}{item.userId && item.userId !== item.id ? ` / ${t("organization.userReference", { id: item.userId })}` : ""}</Typography></Box></Stack> },
{ key: "prettyId", label: t("users.prettyId"), render: (item) => item.prettyId || "-" },
{ key: "country", label: t("organization.country"), render: (item) => item.country || "-" },
{ key: "status", label: t("common.status"), render: (item) => <StatusChip status={item.status} /> }
], [kind, t]);
if (!config || !allowed) {
return <ExternalPage title={config ? t(config.titleKey) : t("organization.title")}><Alert severity="warning">{t("organization.noPermission")}</Alert></ExternalPage>;
}
return (
<ExternalPage title={t(config.titleKey)}>
<Stack className="external-filter-bar" component="form" direction={{ xs: "column", sm: "row" }} spacing={1.5} onSubmit={(event) => { event.preventDefault(); setQuery({ keyword, page: 1 }); }}>
<TextField label={kind === "team" ? t("organization.teamSearch") : t("users.search")} value={keyword} onChange={(event) => setKeyword(event.target.value)} />
<Button type="submit" variant="contained">{t("common.query")}</Button>
</Stack>
<ExternalPageState error={error} loading={loading} onRetry={reload} />
{kind === "team" && !loading && !error ? (
<Box className="external-form-panel">
<Stack direction={{ xs: "column", sm: "row" }} spacing={{ xs: 1, sm: 4 }}>
<Typography>{t("organization.bdLeaderCount", { count: data.totalBdLeaders || 0 })}</Typography>
<Typography>{t("organization.bdCount", { count: data.totalBds || 0 })}</Typography>
<Typography>{t("organization.agencyCount", { count: data.total || data.items.length })}</Typography>
</Stack>
{data.truncated ? <Alert severity="warning" sx={{ mt: 2 }}>{t("organization.truncated")}</Alert> : null}
</Box>
) : null}
{!loading && !error ? <><ResponsiveDataList columns={columns} items={data.items} rowKey={(item, index) => item.id || index} /><PagePagination {...data} onChange={(page) => setQuery({ ...query, page })} /></> : null}
</ExternalPage>
);
}