73 lines
5.1 KiB
JavaScript
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>
|
|
);
|
|
}
|