@open-mercato/core 0.4.6-develop-ce2a0728a5 → 0.4.6-develop-77fa3b7ed8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/AGENTS.md +22 -0
  2. package/dist/modules/customers/backend/customers/companies/page.js +3 -3
  3. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  4. package/dist/modules/customers/backend/customers/deals/page.js +3 -3
  5. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  6. package/dist/modules/customers/backend/customers/people/page.js +3 -3
  7. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  8. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -3
  9. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  10. package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
  11. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  12. package/dist/modules/resources/backend/resources/resources/page.js +3 -3
  13. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  14. package/dist/modules/sales/backend/sales/channels/page.js +3 -3
  15. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  16. package/dist/modules/sales/components/channels/offerTableUtils.js +3 -2
  17. package/dist/modules/sales/components/channels/offerTableUtils.js.map +2 -2
  18. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +3 -3
  19. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  20. package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -3
  21. package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
  22. package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -3
  23. package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
  24. package/dist/modules/staff/backend/staff/team-members/page.js +3 -3
  25. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  26. package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
  27. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  28. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -3
  29. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  30. package/dist/modules/staff/backend/staff/teams/page.js +2 -2
  31. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  32. package/package.json +2 -2
  33. package/src/modules/customers/backend/customers/companies/page.tsx +3 -3
  34. package/src/modules/customers/backend/customers/deals/page.tsx +3 -3
  35. package/src/modules/customers/backend/customers/people/page.tsx +3 -3
  36. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +3 -4
  37. package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -3
  38. package/src/modules/resources/backend/resources/resources/page.tsx +3 -3
  39. package/src/modules/sales/backend/sales/channels/page.tsx +3 -3
  40. package/src/modules/sales/components/channels/offerTableUtils.tsx +3 -2
  41. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +3 -3
  42. package/src/modules/staff/backend/staff/leave-requests/page.tsx +3 -3
  43. package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +3 -3
  44. package/src/modules/staff/backend/staff/team-members/page.tsx +3 -3
  45. package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
  46. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +3 -4
  47. package/src/modules/staff/backend/staff/teams/page.tsx +2 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/staff/backend/staff/team-members/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport type { ColumnDef, SortingFn, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport { readApiResultOrThrow, apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Pencil } from 'lucide-react'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\n\nconst PAGE_SIZE = 50\n\ntype TeamMemberRow = {\n kind: 'team' | 'member'\n id: string\n teamId: string | null\n teamName: string | null\n roleLabel: string | null\n displayName: string\n description: string | null\n userEmail: string | null\n roleNames: string[]\n tags: string[]\n isActive: boolean\n updatedAt: string | null\n}\n\ntype TeamMembersResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\ntype TeamsResponse = {\n items?: Array<{ id?: string; name?: string }>\n}\n\ntype TeamRolesResponse = {\n items?: Array<{ id?: string; name?: string; team?: { name?: string } | null }>\n}\n\nexport default function StaffTeamMembersPage() {\n const t = useT()\n const router = useRouter()\n const pathname = usePathname()\n const scopeVersion = useOrganizationScopeVersion()\n const searchParams = useSearchParams()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<TeamMemberRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'displayName', desc: false }])\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [teamFilterOptions, setTeamFilterOptions] = React.useState<Array<{ value: string; label: string }>>([])\n const [roleFilterOptions, setRoleFilterOptions] = React.useState<Array<{ value: string; label: string }>>([])\n const teamFilterParam = searchParams?.get('teamId')\n const roleFilterParam = searchParams?.get('roleId')\n const resolvedTeamId = typeof filterValues.teamId === 'string' && filterValues.teamId.length\n ? filterValues.teamId\n : teamFilterParam\n\n React.useEffect(() => {\n setPage(1)\n }, [teamFilterParam, roleFilterParam])\n\n React.useEffect(() => {\n if (!teamFilterParam) return\n setFilterValues((prev) => {\n if (prev.teamId === teamFilterParam) return prev\n if (typeof prev.teamId === 'string' && prev.teamId.length > 0) return prev\n return { ...prev, teamId: teamFilterParam }\n })\n }, [teamFilterParam])\n\n React.useEffect(() => {\n if (!roleFilterParam) return\n setFilterValues((prev) => {\n if (prev.roleId === roleFilterParam) return prev\n if (typeof prev.roleId === 'string' && prev.roleId.length > 0) return prev\n return { ...prev, roleId: roleFilterParam }\n })\n }, [roleFilterParam])\n\n const labels = React.useMemo(() => ({\n title: t('staff.teamMembers.page.title', 'Team members'),\n description: t('staff.teamMembers.page.description', 'Manage employees and their team assignments.'),\n table: {\n name: t('staff.teamMembers.table.name', 'Name'),\n user: t('staff.teamMembers.table.user', 'User'),\n roles: t('staff.teamMembers.table.roles', 'Roles'),\n tags: t('staff.teamMembers.table.tags', 'Tags'),\n active: t('staff.teamMembers.table.active', 'Active'),\n updatedAt: t('staff.teamMembers.table.updatedAt', 'Updated'),\n empty: t('staff.teamMembers.table.empty', 'No team members yet.'),\n search: t('staff.teamMembers.table.search', 'Search team members...'),\n },\n groups: {\n unassignedTeam: t('staff.teamMembers.group.unassignedTeam', 'Unassigned team'),\n unassignedRole: t('staff.teamMembers.group.unassignedRole', 'Unassigned role'),\n multipleRoles: t('staff.teamMembers.group.multipleRoles', 'Multiple roles'),\n },\n filters: {\n team: t('staff.teamMembers.filters.team', 'Team'),\n role: t('staff.teamMembers.filters.role', 'Role'),\n },\n actions: {\n add: t('staff.teamMembers.actions.add', 'Add team member'),\n edit: t('staff.teamMembers.actions.edit', 'Edit'),\n delete: t('staff.teamMembers.actions.delete', 'Delete'),\n deleteConfirm: t('staff.teamMembers.actions.deleteConfirm', 'Delete team member \"{{name}}\"?'),\n refresh: t('staff.teamMembers.actions.refresh', 'Refresh'),\n editTeam: t('staff.teams.actions.edit', 'Edit'),\n },\n messages: {\n deleted: t('staff.teamMembers.messages.deleted', 'Team member deleted.'),\n },\n errors: {\n load: t('staff.teamMembers.errors.load', 'Failed to load team members.'),\n delete: t('staff.teamMembers.errors.delete', 'Failed to delete team member.'),\n },\n }), [t])\n\n const groupedSortingFn = React.useCallback((field: GroupedSortField): SortingFn<TeamMemberRow> => {\n return (rowA, rowB) => compareGroupedRows(field, labels.groups, rowA.original, rowB.original)\n }, [labels.groups])\n\n const columns = React.useMemo<ColumnDef<TeamMemberRow>[]>(() => [\n {\n accessorKey: 'displayName',\n header: labels.table.name,\n meta: { priority: 1, sticky: true },\n sortingFn: groupedSortingFn('displayName'),\n cell: ({ row }) => (\n row.original.kind === 'team'\n ? (\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n {row.original.teamId ? <TeamsIcon className=\"h-4 w-4 text-muted-foreground\" /> : null}\n <span className=\"font-semibold\">{row.original.displayName}</span>\n </div>\n {row.original.teamId ? (\n <Button\n asChild\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-7 w-7\"\n title={labels.actions.editTeam}\n aria-label={labels.actions.editTeam}\n >\n <Link href={`/backend/staff/teams/${encodeURIComponent(row.original.teamId)}/edit`}>\n <Pencil className=\"h-4 w-4\" />\n </Link>\n </Button>\n ) : null}\n </div>\n )\n : (\n <div className=\"flex flex-col\">\n <span className=\"font-medium pl-6\">{row.original.displayName}</span>\n {row.original.description ? (\n <span className=\"text-xs text-muted-foreground line-clamp-2 pl-6\">{row.original.description}</span>\n ) : null}\n </div>\n )\n ),\n },\n {\n accessorKey: 'userEmail',\n header: labels.table.user,\n meta: { priority: 2 },\n sortingFn: groupedSortingFn('userEmail'),\n cell: ({ row }) => row.original.kind === 'member' && row.original.userEmail\n ? <span className=\"text-sm\">{row.original.userEmail}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'roleNames',\n header: labels.table.roles,\n meta: { priority: 3 },\n sortingFn: groupedSortingFn('roleNames'),\n cell: ({ row }) => row.original.kind === 'member'\n ? renderLabelPills(row.original.roleNames)\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'tags',\n header: labels.table.tags,\n meta: { priority: 4 },\n sortingFn: groupedSortingFn('tags'),\n cell: ({ row }) => row.original.kind === 'member'\n ? renderLabelPills(row.original.tags)\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'isActive',\n header: labels.table.active,\n meta: { priority: 5 },\n sortingFn: groupedSortingFn('isActive'),\n cell: ({ row }) => row.original.kind === 'member'\n ? <BooleanIcon value={row.original.isActive} />\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'updatedAt',\n header: labels.table.updatedAt,\n meta: { priority: 6 },\n sortingFn: groupedSortingFn('updatedAt'),\n cell: ({ row }) => row.original.kind === 'member' && row.original.updatedAt\n ? <span className=\"text-xs text-muted-foreground\">{formatDateTime(row.original.updatedAt)}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n ], [groupedSortingFn, labels.table.active, labels.table.name, labels.table.roles, labels.table.tags, labels.table.updatedAt, labels.table.user])\n\n const loadTeamMembers = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n const sort = sorting[0]\n if (sort?.id) {\n params.set('sortField', sort.id)\n params.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n if (search.trim()) params.set('search', search.trim())\n if (resolvedTeamId) params.set('teamId', String(resolvedTeamId))\n if (filterValues.roleId) params.set('roleId', String(filterValues.roleId))\n const payload = await readApiResultOrThrow<TeamMembersResponse>(\n `/api/staff/team-members?${params.toString()}`,\n undefined,\n { errorMessage: labels.errors.load, fallback: { items: [], total: 0, totalPages: 1 } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n const mappedItems = items.map(mapApiTeamMember)\n const roleFilterId = typeof filterValues.roleId === 'string' ? filterValues.roleId : null\n const filteredItems = roleFilterId\n ? mappedItems.filter((member) => member.roleIds.includes(roleFilterId))\n : mappedItems\n const roleFilterApplied = roleFilterId != null && filteredItems.length !== mappedItems.length\n setRows(buildTeamMemberRows(filteredItems, labels.groups))\n const resolvedTotal = roleFilterApplied\n ? filteredItems.length\n : typeof payload.total === 'number'\n ? payload.total\n : items.length\n setTotal(resolvedTotal)\n setTotalPages(roleFilterApplied\n ? 1\n : typeof payload.totalPages === 'number'\n ? payload.totalPages\n : Math.max(1, Math.ceil(items.length / PAGE_SIZE)))\n } catch (error) {\n console.error('staff.team-members.list', error)\n flash(labels.errors.load, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [filterValues.roleId, labels.errors.load, labels.groups, page, resolvedTeamId, search, sorting])\n\n React.useEffect(() => {\n void loadTeamMembers()\n }, [loadTeamMembers, scopeVersion, reloadToken])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFilters() {\n try {\n const teamParams = new URLSearchParams({ page: '1', pageSize: '100' })\n const roleParams = new URLSearchParams({ page: '1', pageSize: '100' })\n const [teamsCall, rolesCall] = await Promise.all([\n apiCall<TeamsResponse>(`/api/staff/teams?${teamParams.toString()}`),\n apiCall<TeamRolesResponse>(`/api/staff/team-roles?${roleParams.toString()}`),\n ])\n const teamItems = Array.isArray(teamsCall.result?.items) ? teamsCall.result.items : []\n const roleItems = Array.isArray(rolesCall.result?.items) ? rolesCall.result.items : []\n const teams = teamItems\n .map((team) => {\n const id = typeof team.id === 'string' ? team.id : null\n const name = typeof team.name === 'string' ? team.name : null\n if (!id || !name) return null\n return { value: id, label: name }\n })\n .filter((entry): entry is { value: string; label: string } => entry !== null)\n const roles = roleItems\n .map((role) => {\n const id = typeof role.id === 'string' ? role.id : null\n const name = typeof role.name === 'string' ? role.name : null\n const teamName = role.team && typeof role.team === 'object' && typeof role.team.name === 'string'\n ? role.team.name\n : labels.groups.unassignedTeam\n if (!id || !name) return null\n return { value: id, label: `${teamName} - ${name}` }\n })\n .filter((entry): entry is { value: string; label: string } => entry !== null)\n if (!cancelled) {\n setTeamFilterOptions(teams)\n setRoleFilterOptions(roles)\n }\n } catch {\n if (!cancelled) {\n setTeamFilterOptions([])\n setRoleFilterOptions([])\n }\n }\n }\n loadFilters()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'teamId',\n label: labels.filters.team,\n type: 'select',\n options: teamFilterOptions,\n placeholder: labels.filters.team,\n },\n {\n id: 'roleId',\n label: labels.filters.role,\n type: 'select',\n options: roleFilterOptions,\n placeholder: labels.filters.role,\n },\n ], [labels.filters.role, labels.filters.team, roleFilterOptions, teamFilterOptions])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [pathname, router, searchParams])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n setPage(1)\n\n const params = new URLSearchParams(searchParams?.toString())\n const hasTeamId = typeof values.teamId === 'string' && values.teamId.length > 0\n if (!hasTeamId && params.has('teamId')) {\n params.delete('teamId')\n }\n const hasRoleId = typeof values.roleId === 'string' && values.roleId.length > 0\n if (!hasRoleId && params.has('roleId')) {\n params.delete('roleId')\n }\n const query = params.toString()\n router.replace(query ? `${pathname}?${query}` : pathname)\n }, [pathname, router, searchParams])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n\n const params = new URLSearchParams(searchParams?.toString())\n if (params.has('teamId')) {\n params.delete('teamId')\n }\n if (params.has('roleId')) {\n params.delete('roleId')\n }\n const query = params.toString()\n router.replace(query ? `${pathname}?${query}` : pathname)\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n setReloadToken((token) => token + 1)\n }, [])\n\n const handleDelete = React.useCallback(async (entry: TeamMemberRow) => {\n if (entry.kind !== 'member') return\n const message = labels.actions.deleteConfirm.replace('{{name}}', entry.displayName)\n const confirmed = await confirm({\n title: labels.actions.delete,\n text: message,\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n await deleteCrud('staff/team-members', entry.id, { errorMessage: labels.errors.delete })\n flash(labels.messages.deleted, 'success')\n handleRefresh()\n } catch (error) {\n console.error('staff.team-members.delete', error)\n flash(labels.errors.delete, 'error')\n }\n }, [confirm, handleRefresh, labels.actions.deleteConfirm, labels.actions.delete, labels.errors.delete, labels.messages.deleted])\n\n return (\n <Page>\n <PageBody>\n <DataTable<TeamMemberRow>\n title={labels.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={labels.table.search}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{labels.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/team-members/create\">\n {labels.actions.add}\n </Link>\n </Button>\n )}\n refreshButton={{\n label: labels.actions.refresh,\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n rowActions={(row) => row.kind === 'member' ? (\n <RowActions\n items={[\n { id: 'edit', label: labels.actions.edit, onSelect: () => { router.push(`/backend/staff/team-members/${row.id}`) } },\n { id: 'delete', label: labels.actions.delete, destructive: true, onSelect: () => { void handleDelete(row) } },\n ]}\n />\n ) : null}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n\ntype TeamMemberApiRow = {\n id: string\n displayName: string\n description: string | null\n userEmail: string | null\n roleNames: string[]\n roleIds: string[]\n tags: string[]\n isActive: boolean\n updatedAt: string | null\n teamId: string | null\n teamName: string | null\n}\n\ntype GroupedSortField = 'displayName' | 'userEmail' | 'roleNames' | 'tags' | 'isActive' | 'updatedAt'\n\nfunction mapApiTeamMember(item: Record<string, unknown>): TeamMemberApiRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const displayName = typeof item.displayName === 'string'\n ? item.displayName\n : typeof item.display_name === 'string'\n ? item.display_name\n : id\n const description = typeof item.description === 'string' && item.description.trim().length\n ? item.description.trim()\n : null\n const user = item.user && typeof item.user === 'object' ? item.user as { email?: unknown } : null\n const userEmail = user && typeof user.email === 'string' && user.email.length ? user.email : null\n const roleNames = Array.isArray(item.roleNames) ? item.roleNames.filter((value): value is string => typeof value === 'string') : []\n const roleIds = Array.isArray(item.roleIds)\n ? item.roleIds.filter((value): value is string => typeof value === 'string')\n : Array.isArray(item.role_ids)\n ? item.role_ids.filter((value): value is string => typeof value === 'string')\n : []\n const tags = Array.isArray(item.tags) ? item.tags.filter((value): value is string => typeof value === 'string') : []\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n const isActive = typeof item.isActive === 'boolean'\n ? item.isActive\n : typeof item.is_active === 'boolean'\n ? item.is_active\n : true\n const teamId = typeof item.teamId === 'string'\n ? item.teamId\n : typeof item.team_id === 'string'\n ? item.team_id\n : null\n const team = item.team && typeof item.team === 'object' ? item.team as { name?: unknown } : null\n const teamName = typeof team?.name === 'string' ? team.name : null\n return {\n id,\n displayName,\n description,\n userEmail,\n roleNames,\n roleIds,\n tags,\n isActive,\n updatedAt,\n teamId,\n teamName,\n }\n}\n\nfunction compareGroupedRows(\n field: GroupedSortField,\n labels: { unassignedTeam: string },\n left: TeamMemberRow,\n right: TeamMemberRow,\n): number {\n const leftTeam = (left.teamName ?? labels.unassignedTeam).toLocaleLowerCase()\n const rightTeam = (right.teamName ?? labels.unassignedTeam).toLocaleLowerCase()\n const teamComparison = leftTeam.localeCompare(rightTeam)\n if (teamComparison !== 0) return teamComparison\n if (left.kind !== right.kind) return left.kind === 'team' ? -1 : 1\n if (left.kind === 'team' && right.kind === 'team') return 0\n switch (field) {\n case 'displayName':\n return left.displayName.localeCompare(right.displayName)\n case 'userEmail':\n return (left.userEmail ?? '').localeCompare(right.userEmail ?? '')\n case 'roleNames':\n return left.roleNames.join(', ').localeCompare(right.roleNames.join(', '))\n case 'tags':\n return left.tags.join(', ').localeCompare(right.tags.join(', '))\n case 'isActive':\n return Number(left.isActive) - Number(right.isActive)\n case 'updatedAt':\n return compareDateStrings(left.updatedAt, right.updatedAt)\n }\n}\n\nfunction compareDateStrings(left: string | null, right: string | null): number {\n if (!left && !right) return 0\n if (!left) return -1\n if (!right) return 1\n const leftTime = Date.parse(left)\n const rightTime = Date.parse(right)\n if (Number.isNaN(leftTime) || Number.isNaN(rightTime)) {\n return left.localeCompare(right)\n }\n return leftTime - rightTime\n}\n\nfunction buildTeamMemberRows(\n items: TeamMemberApiRow[],\n labels: { unassignedTeam: string; unassignedRole: string; multipleRoles: string },\n): TeamMemberRow[] {\n const teamGroups = new Map<string, { teamId: string | null; name: string; members: TeamMemberApiRow[] }>()\n for (const member of items) {\n const key = member.teamId ?? 'unassigned'\n const name = member.teamName ?? labels.unassignedTeam\n const group = teamGroups.get(key) ?? { teamId: member.teamId ?? null, name, members: [] }\n group.members.push(member)\n teamGroups.set(key, group)\n }\n const sortedTeams = Array.from(teamGroups.values()).sort((a, b) => a.name.localeCompare(b.name))\n const rows: TeamMemberRow[] = []\n for (const team of sortedTeams) {\n rows.push({\n kind: 'team',\n id: `team:${team.teamId ?? 'unassigned'}`,\n teamId: team.teamId,\n teamName: team.name,\n roleLabel: null,\n displayName: team.name,\n description: null,\n userEmail: null,\n roleNames: [],\n tags: [],\n isActive: true,\n updatedAt: null,\n })\n const sortedMembers = [...team.members].sort((a, b) => a.displayName.localeCompare(b.displayName))\n for (const member of sortedMembers) {\n rows.push({\n kind: 'member',\n id: member.id,\n teamId: member.teamId,\n teamName: member.teamName,\n roleLabel: member.roleNames.length\n ? member.roleNames.join(', ')\n : labels.unassignedRole,\n displayName: member.displayName,\n description: member.description,\n userEmail: member.userEmail,\n roleNames: member.roleNames,\n tags: member.tags,\n isActive: member.isActive,\n updatedAt: member.updatedAt,\n })\n }\n }\n return rows\n}\n\n\n\nfunction renderLabelPills(values: string[]): React.ReactNode {\n if (!values.length) return <span className=\"text-xs text-muted-foreground\">-</span>\n return (\n <div className=\"flex flex-wrap gap-2\">\n {values.map((value) => (\n <span key={value} className=\"inline-flex items-center rounded-full border px-3 py-1 text-xs font-medium\">\n {value}\n </span>\n ))}\n </div>\n )\n}\n\nfunction TeamsIcon({ className }: { className?: string }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n className={className}\n aria-hidden=\"true\"\n >\n <circle cx=\"8\" cy=\"8\" r=\"3\" />\n <circle cx=\"16\" cy=\"8\" r=\"3\" />\n <path d=\"M3 20c0-3 3-5 5-5\" />\n <path d=\"M21 20c0-3-3-5-5-5\" />\n </svg>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport type { ColumnDef, SortingFn, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport { readApiResultOrThrow, apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Pencil } from 'lucide-react'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\n\nconst PAGE_SIZE = 50\n\ntype TeamMemberRow = {\n kind: 'team' | 'member'\n id: string\n teamId: string | null\n teamName: string | null\n roleLabel: string | null\n displayName: string\n description: string | null\n userEmail: string | null\n roleNames: string[]\n tags: string[]\n isActive: boolean\n updatedAt: string | null\n}\n\ntype TeamMembersResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\ntype TeamsResponse = {\n items?: Array<{ id?: string; name?: string }>\n}\n\ntype TeamRolesResponse = {\n items?: Array<{ id?: string; name?: string; team?: { name?: string } | null }>\n}\n\nexport default function StaffTeamMembersPage() {\n const t = useT()\n const router = useRouter()\n const pathname = usePathname()\n const scopeVersion = useOrganizationScopeVersion()\n const searchParams = useSearchParams()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<TeamMemberRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'displayName', desc: false }])\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [teamFilterOptions, setTeamFilterOptions] = React.useState<Array<{ value: string; label: string }>>([])\n const [roleFilterOptions, setRoleFilterOptions] = React.useState<Array<{ value: string; label: string }>>([])\n const teamFilterParam = searchParams?.get('teamId')\n const roleFilterParam = searchParams?.get('roleId')\n const resolvedTeamId = typeof filterValues.teamId === 'string' && filterValues.teamId.length\n ? filterValues.teamId\n : teamFilterParam\n\n React.useEffect(() => {\n setPage(1)\n }, [teamFilterParam, roleFilterParam])\n\n React.useEffect(() => {\n if (!teamFilterParam) return\n setFilterValues((prev) => {\n if (prev.teamId === teamFilterParam) return prev\n if (typeof prev.teamId === 'string' && prev.teamId.length > 0) return prev\n return { ...prev, teamId: teamFilterParam }\n })\n }, [teamFilterParam])\n\n React.useEffect(() => {\n if (!roleFilterParam) return\n setFilterValues((prev) => {\n if (prev.roleId === roleFilterParam) return prev\n if (typeof prev.roleId === 'string' && prev.roleId.length > 0) return prev\n return { ...prev, roleId: roleFilterParam }\n })\n }, [roleFilterParam])\n\n const labels = React.useMemo(() => ({\n title: t('staff.teamMembers.page.title', 'Team members'),\n description: t('staff.teamMembers.page.description', 'Manage employees and their team assignments.'),\n table: {\n name: t('staff.teamMembers.table.name', 'Name'),\n user: t('staff.teamMembers.table.user', 'User'),\n roles: t('staff.teamMembers.table.roles', 'Roles'),\n tags: t('staff.teamMembers.table.tags', 'Tags'),\n active: t('staff.teamMembers.table.active', 'Active'),\n updatedAt: t('staff.teamMembers.table.updatedAt', 'Updated'),\n empty: t('staff.teamMembers.table.empty', 'No team members yet.'),\n search: t('staff.teamMembers.table.search', 'Search team members...'),\n },\n groups: {\n unassignedTeam: t('staff.teamMembers.group.unassignedTeam', 'Unassigned team'),\n unassignedRole: t('staff.teamMembers.group.unassignedRole', 'Unassigned role'),\n multipleRoles: t('staff.teamMembers.group.multipleRoles', 'Multiple roles'),\n },\n filters: {\n team: t('staff.teamMembers.filters.team', 'Team'),\n role: t('staff.teamMembers.filters.role', 'Role'),\n },\n actions: {\n add: t('staff.teamMembers.actions.add', 'Add team member'),\n edit: t('staff.teamMembers.actions.edit', 'Edit'),\n delete: t('staff.teamMembers.actions.delete', 'Delete'),\n deleteConfirm: t('staff.teamMembers.actions.deleteConfirm', 'Delete team member \"{{name}}\"?'),\n refresh: t('staff.teamMembers.actions.refresh', 'Refresh'),\n editTeam: t('staff.teams.actions.edit', 'Edit'),\n },\n messages: {\n deleted: t('staff.teamMembers.messages.deleted', 'Team member deleted.'),\n },\n errors: {\n load: t('staff.teamMembers.errors.load', 'Failed to load team members.'),\n delete: t('staff.teamMembers.errors.delete', 'Failed to delete team member.'),\n },\n }), [t])\n\n const groupedSortingFn = React.useCallback((field: GroupedSortField): SortingFn<TeamMemberRow> => {\n return (rowA, rowB) => compareGroupedRows(field, labels.groups, rowA.original, rowB.original)\n }, [labels.groups])\n\n const columns = React.useMemo<ColumnDef<TeamMemberRow>[]>(() => [\n {\n accessorKey: 'displayName',\n header: labels.table.name,\n meta: { priority: 1, sticky: true },\n sortingFn: groupedSortingFn('displayName'),\n cell: ({ row }) => (\n row.original.kind === 'team'\n ? (\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n {row.original.teamId ? <TeamsIcon className=\"h-4 w-4 text-muted-foreground\" /> : null}\n <span className=\"font-semibold\">{row.original.displayName}</span>\n </div>\n {row.original.teamId ? (\n <Button\n asChild\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-7 w-7\"\n title={labels.actions.editTeam}\n aria-label={labels.actions.editTeam}\n >\n <Link href={`/backend/staff/teams/${encodeURIComponent(row.original.teamId)}/edit`}>\n <Pencil className=\"h-4 w-4\" />\n </Link>\n </Button>\n ) : null}\n </div>\n )\n : (\n <div className=\"flex flex-col\">\n <span className=\"font-medium pl-6\">{row.original.displayName}</span>\n {row.original.description ? (\n <span className=\"text-xs text-muted-foreground line-clamp-2 pl-6\">{row.original.description}</span>\n ) : null}\n </div>\n )\n ),\n },\n {\n accessorKey: 'userEmail',\n header: labels.table.user,\n meta: { priority: 2 },\n sortingFn: groupedSortingFn('userEmail'),\n cell: ({ row }) => row.original.kind === 'member' && row.original.userEmail\n ? <span className=\"text-sm\">{row.original.userEmail}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'roleNames',\n header: labels.table.roles,\n meta: { priority: 3 },\n sortingFn: groupedSortingFn('roleNames'),\n cell: ({ row }) => row.original.kind === 'member'\n ? renderLabelPills(row.original.roleNames)\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'tags',\n header: labels.table.tags,\n meta: { priority: 4 },\n sortingFn: groupedSortingFn('tags'),\n cell: ({ row }) => row.original.kind === 'member'\n ? renderLabelPills(row.original.tags)\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'isActive',\n header: labels.table.active,\n meta: { priority: 5 },\n sortingFn: groupedSortingFn('isActive'),\n cell: ({ row }) => row.original.kind === 'member'\n ? <BooleanIcon value={row.original.isActive} />\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'updatedAt',\n header: labels.table.updatedAt,\n meta: { priority: 6 },\n sortingFn: groupedSortingFn('updatedAt'),\n cell: ({ row }) => row.original.kind === 'member' && row.original.updatedAt\n ? <span className=\"text-xs text-muted-foreground\">{formatDateTime(row.original.updatedAt)}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n ], [groupedSortingFn, labels.table.active, labels.table.name, labels.table.roles, labels.table.tags, labels.table.updatedAt, labels.table.user])\n\n const loadTeamMembers = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n const sort = sorting[0]\n if (sort?.id) {\n params.set('sortField', sort.id)\n params.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n if (search.trim()) params.set('search', search.trim())\n if (resolvedTeamId) params.set('teamId', String(resolvedTeamId))\n if (filterValues.roleId) params.set('roleId', String(filterValues.roleId))\n const payload = await readApiResultOrThrow<TeamMembersResponse>(\n `/api/staff/team-members?${params.toString()}`,\n undefined,\n { errorMessage: labels.errors.load, fallback: { items: [], total: 0, totalPages: 1 } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n const mappedItems = items.map(mapApiTeamMember)\n const roleFilterId = typeof filterValues.roleId === 'string' ? filterValues.roleId : null\n const filteredItems = roleFilterId\n ? mappedItems.filter((member) => member.roleIds.includes(roleFilterId))\n : mappedItems\n const roleFilterApplied = roleFilterId != null && filteredItems.length !== mappedItems.length\n setRows(buildTeamMemberRows(filteredItems, labels.groups))\n const resolvedTotal = roleFilterApplied\n ? filteredItems.length\n : typeof payload.total === 'number'\n ? payload.total\n : items.length\n setTotal(resolvedTotal)\n setTotalPages(roleFilterApplied\n ? 1\n : typeof payload.totalPages === 'number'\n ? payload.totalPages\n : Math.max(1, Math.ceil(items.length / PAGE_SIZE)))\n } catch (error) {\n console.error('staff.team-members.list', error)\n flash(labels.errors.load, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [filterValues.roleId, labels.errors.load, labels.groups, page, resolvedTeamId, search, sorting])\n\n React.useEffect(() => {\n void loadTeamMembers()\n }, [loadTeamMembers, scopeVersion, reloadToken])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFilters() {\n try {\n const teamParams = new URLSearchParams({ page: '1', pageSize: '100' })\n const roleParams = new URLSearchParams({ page: '1', pageSize: '100' })\n const [teamsCall, rolesCall] = await Promise.all([\n apiCall<TeamsResponse>(`/api/staff/teams?${teamParams.toString()}`),\n apiCall<TeamRolesResponse>(`/api/staff/team-roles?${roleParams.toString()}`),\n ])\n const teamItems = Array.isArray(teamsCall.result?.items) ? teamsCall.result.items : []\n const roleItems = Array.isArray(rolesCall.result?.items) ? rolesCall.result.items : []\n const teams = teamItems\n .map((team) => {\n const id = typeof team.id === 'string' ? team.id : null\n const name = typeof team.name === 'string' ? team.name : null\n if (!id || !name) return null\n return { value: id, label: name }\n })\n .filter((entry): entry is { value: string; label: string } => entry !== null)\n const roles = roleItems\n .map((role) => {\n const id = typeof role.id === 'string' ? role.id : null\n const name = typeof role.name === 'string' ? role.name : null\n const teamName = role.team && typeof role.team === 'object' && typeof role.team.name === 'string'\n ? role.team.name\n : labels.groups.unassignedTeam\n if (!id || !name) return null\n return { value: id, label: `${teamName} - ${name}` }\n })\n .filter((entry): entry is { value: string; label: string } => entry !== null)\n if (!cancelled) {\n setTeamFilterOptions(teams)\n setRoleFilterOptions(roles)\n }\n } catch {\n if (!cancelled) {\n setTeamFilterOptions([])\n setRoleFilterOptions([])\n }\n }\n }\n loadFilters()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'teamId',\n label: labels.filters.team,\n type: 'select',\n options: teamFilterOptions,\n placeholder: labels.filters.team,\n },\n {\n id: 'roleId',\n label: labels.filters.role,\n type: 'select',\n options: roleFilterOptions,\n placeholder: labels.filters.role,\n },\n ], [labels.filters.role, labels.filters.team, roleFilterOptions, teamFilterOptions])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [pathname, router, searchParams])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n setPage(1)\n\n const params = new URLSearchParams(searchParams?.toString())\n const hasTeamId = typeof values.teamId === 'string' && values.teamId.length > 0\n if (!hasTeamId && params.has('teamId')) {\n params.delete('teamId')\n }\n const hasRoleId = typeof values.roleId === 'string' && values.roleId.length > 0\n if (!hasRoleId && params.has('roleId')) {\n params.delete('roleId')\n }\n const query = params.toString()\n router.replace(query ? `${pathname}?${query}` : pathname)\n }, [pathname, router, searchParams])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n\n const params = new URLSearchParams(searchParams?.toString())\n if (params.has('teamId')) {\n params.delete('teamId')\n }\n if (params.has('roleId')) {\n params.delete('roleId')\n }\n const query = params.toString()\n router.replace(query ? `${pathname}?${query}` : pathname)\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n setReloadToken((token) => token + 1)\n }, [])\n\n const handleDelete = React.useCallback(async (entry: TeamMemberRow) => {\n if (entry.kind !== 'member') return\n const message = labels.actions.deleteConfirm.replace('{{name}}', entry.displayName)\n const confirmed = await confirm({\n title: labels.actions.delete,\n text: message,\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n await deleteCrud('staff/team-members', entry.id, { errorMessage: labels.errors.delete })\n flash(labels.messages.deleted, 'success')\n handleRefresh()\n } catch (error) {\n console.error('staff.team-members.delete', error)\n flash(labels.errors.delete, 'error')\n }\n }, [confirm, handleRefresh, labels.actions.deleteConfirm, labels.actions.delete, labels.errors.delete, labels.messages.deleted])\n\n return (\n <Page>\n <PageBody>\n <DataTable<TeamMemberRow>\n title={labels.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={labels.table.search}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{labels.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/team-members/create\">\n {labels.actions.add}\n </Link>\n </Button>\n )}\n refreshButton={{\n label: labels.actions.refresh,\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n rowActions={(row) => row.kind === 'member' ? (\n <RowActions\n items={[\n { id: 'edit', label: labels.actions.edit, onSelect: () => { router.push(`/backend/staff/team-members/${row.id}`) } },\n { id: 'delete', label: labels.actions.delete, destructive: true, onSelect: () => { void handleDelete(row) } },\n ]}\n />\n ) : null}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n\ntype TeamMemberApiRow = {\n id: string\n displayName: string\n description: string | null\n userEmail: string | null\n roleNames: string[]\n roleIds: string[]\n tags: string[]\n isActive: boolean\n updatedAt: string | null\n teamId: string | null\n teamName: string | null\n}\n\ntype GroupedSortField = 'displayName' | 'userEmail' | 'roleNames' | 'tags' | 'isActive' | 'updatedAt'\n\nfunction mapApiTeamMember(item: Record<string, unknown>): TeamMemberApiRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const displayName = typeof item.displayName === 'string'\n ? item.displayName\n : typeof item.display_name === 'string'\n ? item.display_name\n : id\n const description = typeof item.description === 'string' && item.description.trim().length\n ? item.description.trim()\n : null\n const user = item.user && typeof item.user === 'object' ? item.user as { email?: unknown } : null\n const userEmail = user && typeof user.email === 'string' && user.email.length ? user.email : null\n const roleNames = Array.isArray(item.roleNames) ? item.roleNames.filter((value): value is string => typeof value === 'string') : []\n const roleIds = Array.isArray(item.roleIds)\n ? item.roleIds.filter((value): value is string => typeof value === 'string')\n : Array.isArray(item.role_ids)\n ? item.role_ids.filter((value): value is string => typeof value === 'string')\n : []\n const tags = Array.isArray(item.tags) ? item.tags.filter((value): value is string => typeof value === 'string') : []\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n const isActive = typeof item.isActive === 'boolean'\n ? item.isActive\n : typeof item.is_active === 'boolean'\n ? item.is_active\n : true\n const teamId = typeof item.teamId === 'string'\n ? item.teamId\n : typeof item.team_id === 'string'\n ? item.team_id\n : null\n const team = item.team && typeof item.team === 'object' ? item.team as { name?: unknown } : null\n const teamName = typeof team?.name === 'string' ? team.name : null\n return withDataTableNamespaces({\n id,\n displayName,\n description,\n userEmail,\n roleNames,\n roleIds,\n tags,\n isActive,\n updatedAt,\n teamId,\n teamName,\n }, item)\n}\n\nfunction compareGroupedRows(\n field: GroupedSortField,\n labels: { unassignedTeam: string },\n left: TeamMemberRow,\n right: TeamMemberRow,\n): number {\n const leftTeam = (left.teamName ?? labels.unassignedTeam).toLocaleLowerCase()\n const rightTeam = (right.teamName ?? labels.unassignedTeam).toLocaleLowerCase()\n const teamComparison = leftTeam.localeCompare(rightTeam)\n if (teamComparison !== 0) return teamComparison\n if (left.kind !== right.kind) return left.kind === 'team' ? -1 : 1\n if (left.kind === 'team' && right.kind === 'team') return 0\n switch (field) {\n case 'displayName':\n return left.displayName.localeCompare(right.displayName)\n case 'userEmail':\n return (left.userEmail ?? '').localeCompare(right.userEmail ?? '')\n case 'roleNames':\n return left.roleNames.join(', ').localeCompare(right.roleNames.join(', '))\n case 'tags':\n return left.tags.join(', ').localeCompare(right.tags.join(', '))\n case 'isActive':\n return Number(left.isActive) - Number(right.isActive)\n case 'updatedAt':\n return compareDateStrings(left.updatedAt, right.updatedAt)\n }\n}\n\nfunction compareDateStrings(left: string | null, right: string | null): number {\n if (!left && !right) return 0\n if (!left) return -1\n if (!right) return 1\n const leftTime = Date.parse(left)\n const rightTime = Date.parse(right)\n if (Number.isNaN(leftTime) || Number.isNaN(rightTime)) {\n return left.localeCompare(right)\n }\n return leftTime - rightTime\n}\n\nfunction buildTeamMemberRows(\n items: TeamMemberApiRow[],\n labels: { unassignedTeam: string; unassignedRole: string; multipleRoles: string },\n): TeamMemberRow[] {\n const teamGroups = new Map<string, { teamId: string | null; name: string; members: TeamMemberApiRow[] }>()\n for (const member of items) {\n const key = member.teamId ?? 'unassigned'\n const name = member.teamName ?? labels.unassignedTeam\n const group = teamGroups.get(key) ?? { teamId: member.teamId ?? null, name, members: [] }\n group.members.push(member)\n teamGroups.set(key, group)\n }\n const sortedTeams = Array.from(teamGroups.values()).sort((a, b) => a.name.localeCompare(b.name))\n const rows: TeamMemberRow[] = []\n for (const team of sortedTeams) {\n rows.push({\n kind: 'team',\n id: `team:${team.teamId ?? 'unassigned'}`,\n teamId: team.teamId,\n teamName: team.name,\n roleLabel: null,\n displayName: team.name,\n description: null,\n userEmail: null,\n roleNames: [],\n tags: [],\n isActive: true,\n updatedAt: null,\n })\n const sortedMembers = [...team.members].sort((a, b) => a.displayName.localeCompare(b.displayName))\n for (const member of sortedMembers) {\n rows.push({\n kind: 'member',\n id: member.id,\n teamId: member.teamId,\n teamName: member.teamName,\n roleLabel: member.roleNames.length\n ? member.roleNames.join(', ')\n : labels.unassignedRole,\n displayName: member.displayName,\n description: member.description,\n userEmail: member.userEmail,\n roleNames: member.roleNames,\n tags: member.tags,\n isActive: member.isActive,\n updatedAt: member.updatedAt,\n })\n }\n }\n return rows\n}\n\n\n\nfunction renderLabelPills(values: string[]): React.ReactNode {\n if (!values.length) return <span className=\"text-xs text-muted-foreground\">-</span>\n return (\n <div className=\"flex flex-wrap gap-2\">\n {values.map((value) => (\n <span key={value} className=\"inline-flex items-center rounded-full border px-3 py-1 text-xs font-medium\">\n {value}\n </span>\n ))}\n </div>\n )\n}\n\nfunction TeamsIcon({ className }: { className?: string }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n className={className}\n aria-hidden=\"true\"\n >\n <circle cx=\"8\" cy=\"8\" r=\"3\" />\n <circle cx=\"16\" cy=\"8\" r=\"3\" />\n <path d=\"M3 20c0-3 3-5 5-5\" />\n <path d=\"M21 20c0-3-3-5-5-5\" />\n </svg>\n )\n}\n"],
5
+ "mappings": ";AAuJc,SACyB,KADzB;AArJd,YAAY,WAAW;AACvB,OAAO,UAAU;AACjB,SAAS,aAAa,WAAW,uBAAuB;AAExD,SAAS,MAAM,gBAAgB;AAC/B,SAAS,WAAW,+BAA+B;AACnD,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB,eAAe;AAC9C,SAAS,kBAAkB;AAC3B,SAAS,aAAa;AACtB,SAAS,wBAAwB;AAEjC,SAAS,mCAAmC;AAC5C,SAAS,YAAY;AACrB,SAAS,cAAc;AACvB,SAAS,sBAAsB;AAE/B,MAAM,YAAY;AA+BH,SAAR,uBAAwC;AAC7C,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,WAAW,YAAY;AAC7B,QAAM,eAAe,4BAA4B;AACjD,QAAM,eAAe,gBAAgB;AACrC,QAAM,EAAE,SAAS,qBAAqB,IAAI,iBAAiB;AAC3D,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAA0B,CAAC,CAAC;AAC1D,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC;AACxC,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,CAAC;AAC1C,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,CAAC;AACpD,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuB,CAAC,EAAE,IAAI,eAAe,MAAM,MAAM,CAAC,CAAC;AAC/F,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAC7C,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,IAAI;AACrD,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAS,CAAC;AACtD,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAuB,CAAC,CAAC;AACvE,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,MAAM,SAAkD,CAAC,CAAC;AAC5G,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,MAAM,SAAkD,CAAC,CAAC;AAC5G,QAAM,kBAAkB,cAAc,IAAI,QAAQ;AAClD,QAAM,kBAAkB,cAAc,IAAI,QAAQ;AAClD,QAAM,iBAAiB,OAAO,aAAa,WAAW,YAAY,aAAa,OAAO,SAClF,aAAa,SACb;AAEJ,QAAM,UAAU,MAAM;AACpB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,iBAAiB,eAAe,CAAC;AAErC,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,gBAAiB;AACtB,oBAAgB,CAAC,SAAS;AACxB,UAAI,KAAK,WAAW,gBAAiB,QAAO;AAC5C,UAAI,OAAO,KAAK,WAAW,YAAY,KAAK,OAAO,SAAS,EAAG,QAAO;AACtE,aAAO,EAAE,GAAG,MAAM,QAAQ,gBAAgB;AAAA,IAC5C,CAAC;AAAA,EACH,GAAG,CAAC,eAAe,CAAC;AAEpB,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,gBAAiB;AACtB,oBAAgB,CAAC,SAAS;AACxB,UAAI,KAAK,WAAW,gBAAiB,QAAO;AAC5C,UAAI,OAAO,KAAK,WAAW,YAAY,KAAK,OAAO,SAAS,EAAG,QAAO;AACtE,aAAO,EAAE,GAAG,MAAM,QAAQ,gBAAgB;AAAA,IAC5C,CAAC;AAAA,EACH,GAAG,CAAC,eAAe,CAAC;AAEpB,QAAM,SAAS,MAAM,QAAQ,OAAO;AAAA,IAClC,OAAO,EAAE,gCAAgC,cAAc;AAAA,IACvD,aAAa,EAAE,sCAAsC,8CAA8C;AAAA,IACnG,OAAO;AAAA,MACL,MAAM,EAAE,gCAAgC,MAAM;AAAA,MAC9C,MAAM,EAAE,gCAAgC,MAAM;AAAA,MAC9C,OAAO,EAAE,iCAAiC,OAAO;AAAA,MACjD,MAAM,EAAE,gCAAgC,MAAM;AAAA,MAC9C,QAAQ,EAAE,kCAAkC,QAAQ;AAAA,MACpD,WAAW,EAAE,qCAAqC,SAAS;AAAA,MAC3D,OAAO,EAAE,iCAAiC,sBAAsB;AAAA,MAChE,QAAQ,EAAE,kCAAkC,wBAAwB;AAAA,IACtE;AAAA,IACA,QAAQ;AAAA,MACN,gBAAgB,EAAE,0CAA0C,iBAAiB;AAAA,MAC7E,gBAAgB,EAAE,0CAA0C,iBAAiB;AAAA,MAC7E,eAAe,EAAE,yCAAyC,gBAAgB;AAAA,IAC5E;AAAA,IACA,SAAS;AAAA,MACP,MAAM,EAAE,kCAAkC,MAAM;AAAA,MAChD,MAAM,EAAE,kCAAkC,MAAM;AAAA,IAClD;AAAA,IACA,SAAS;AAAA,MACP,KAAK,EAAE,iCAAiC,iBAAiB;AAAA,MACzD,MAAM,EAAE,kCAAkC,MAAM;AAAA,MAChD,QAAQ,EAAE,oCAAoC,QAAQ;AAAA,MACtD,eAAe,EAAE,2CAA2C,gCAAgC;AAAA,MAC5F,SAAS,EAAE,qCAAqC,SAAS;AAAA,MACzD,UAAU,EAAE,4BAA4B,MAAM;AAAA,IAChD;AAAA,IACA,UAAU;AAAA,MACR,SAAS,EAAE,sCAAsC,sBAAsB;AAAA,IACzE;AAAA,IACA,QAAQ;AAAA,MACN,MAAM,EAAE,iCAAiC,8BAA8B;AAAA,MACvE,QAAQ,EAAE,mCAAmC,+BAA+B;AAAA,IAC9E;AAAA,EACF,IAAI,CAAC,CAAC,CAAC;AAEP,QAAM,mBAAmB,MAAM,YAAY,CAAC,UAAsD;AAChG,WAAO,CAAC,MAAM,SAAS,mBAAmB,OAAO,OAAO,QAAQ,KAAK,UAAU,KAAK,QAAQ;AAAA,EAC9F,GAAG,CAAC,OAAO,MAAM,CAAC;AAElB,QAAM,UAAU,MAAM,QAAoC,MAAM;AAAA,IAC9D;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,GAAG,QAAQ,KAAK;AAAA,MAClC,WAAW,iBAAiB,aAAa;AAAA,MACzC,MAAM,CAAC,EAAE,IAAI,MACX,IAAI,SAAS,SAAS,SAElB,qBAAC,SAAI,WAAU,2CACb;AAAA,6BAAC,SAAI,WAAU,2BACZ;AAAA,cAAI,SAAS,SAAS,oBAAC,aAAU,WAAU,iCAAgC,IAAK;AAAA,UACjF,oBAAC,UAAK,WAAU,iBAAiB,cAAI,SAAS,aAAY;AAAA,WAC5D;AAAA,QACC,IAAI,SAAS,SACZ;AAAA,UAAC;AAAA;AAAA,YACC,SAAO;AAAA,YACP,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,WAAU;AAAA,YACV,OAAO,OAAO,QAAQ;AAAA,YACtB,cAAY,OAAO,QAAQ;AAAA,YAE3B,8BAAC,QAAK,MAAM,wBAAwB,mBAAmB,IAAI,SAAS,MAAM,CAAC,SACzE,8BAAC,UAAO,WAAU,WAAU,GAC9B;AAAA;AAAA,QACF,IACE;AAAA,SACN,IAGA,qBAAC,SAAI,WAAU,iBACb;AAAA,4BAAC,UAAK,WAAU,oBAAoB,cAAI,SAAS,aAAY;AAAA,QAC5D,IAAI,SAAS,cACZ,oBAAC,UAAK,WAAU,mDAAmD,cAAI,SAAS,aAAY,IAC1F;AAAA,SACN;AAAA,IAGR;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,EAAE;AAAA,MACpB,WAAW,iBAAiB,WAAW;AAAA,MACvC,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,SAAS,YAAY,IAAI,SAAS,YAC9D,oBAAC,UAAK,WAAU,WAAW,cAAI,SAAS,WAAU,IAClD,oBAAC,UAAK,WAAU,iCAAgC,eAAC;AAAA,IACvD;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,EAAE;AAAA,MACpB,WAAW,iBAAiB,WAAW;AAAA,MACvC,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,SAAS,WACrC,iBAAiB,IAAI,SAAS,SAAS,IACvC,oBAAC,UAAK,WAAU,iCAAgC,eAAC;AAAA,IACvD;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,EAAE;AAAA,MACpB,WAAW,iBAAiB,MAAM;AAAA,MAClC,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,SAAS,WACrC,iBAAiB,IAAI,SAAS,IAAI,IAClC,oBAAC,UAAK,WAAU,iCAAgC,eAAC;AAAA,IACvD;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,EAAE;AAAA,MACpB,WAAW,iBAAiB,UAAU;AAAA,MACtC,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,SAAS,WACrC,oBAAC,eAAY,OAAO,IAAI,SAAS,UAAU,IAC3C,oBAAC,UAAK,WAAU,iCAAgC,eAAC;AAAA,IACvD;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,QAAQ,OAAO,MAAM;AAAA,MACrB,MAAM,EAAE,UAAU,EAAE;AAAA,MACpB,WAAW,iBAAiB,WAAW;AAAA,MACvC,MAAM,CAAC,EAAE,IAAI,MAAM,IAAI,SAAS,SAAS,YAAY,IAAI,SAAS,YAC9D,oBAAC,UAAK,WAAU,iCAAiC,yBAAe,IAAI,SAAS,SAAS,GAAE,IACxF,oBAAC,UAAK,WAAU,iCAAgC,eAAC;AAAA,IACvD;AAAA,EACF,GAAG,CAAC,kBAAkB,OAAO,MAAM,QAAQ,OAAO,MAAM,MAAM,OAAO,MAAM,OAAO,OAAO,MAAM,MAAM,OAAO,MAAM,WAAW,OAAO,MAAM,IAAI,CAAC;AAE/I,QAAM,kBAAkB,MAAM,YAAY,YAAY;AACpD,iBAAa,IAAI;AACjB,QAAI;AACF,YAAM,SAAS,IAAI,gBAAgB;AAAA,QACjC,MAAM,OAAO,IAAI;AAAA,QACjB,UAAU,OAAO,SAAS;AAAA,MAC5B,CAAC;AACD,YAAM,OAAO,QAAQ,CAAC;AACtB,UAAI,MAAM,IAAI;AACZ,eAAO,IAAI,aAAa,KAAK,EAAE;AAC/B,eAAO,IAAI,WAAW,KAAK,OAAO,SAAS,KAAK;AAAA,MAClD;AACA,UAAI,OAAO,KAAK,EAAG,QAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AACrD,UAAI,eAAgB,QAAO,IAAI,UAAU,OAAO,cAAc,CAAC;AAC/D,UAAI,aAAa,OAAQ,QAAO,IAAI,UAAU,OAAO,aAAa,MAAM,CAAC;AACzE,YAAM,UAAU,MAAM;AAAA,QACpB,2BAA2B,OAAO,SAAS,CAAC;AAAA,QAC5C;AAAA,QACA,EAAE,cAAc,OAAO,OAAO,MAAM,UAAU,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,YAAY,EAAE,EAAE;AAAA,MACvF;AACA,YAAM,QAAQ,MAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,QAAQ,CAAC;AAC9D,YAAM,cAAc,MAAM,IAAI,gBAAgB;AAC9C,YAAM,eAAe,OAAO,aAAa,WAAW,WAAW,aAAa,SAAS;AACrF,YAAM,gBAAgB,eAClB,YAAY,OAAO,CAAC,WAAW,OAAO,QAAQ,SAAS,YAAY,CAAC,IACpE;AACJ,YAAM,oBAAoB,gBAAgB,QAAQ,cAAc,WAAW,YAAY;AACvF,cAAQ,oBAAoB,eAAe,OAAO,MAAM,CAAC;AACzD,YAAM,gBAAgB,oBAClB,cAAc,SACd,OAAO,QAAQ,UAAU,WACvB,QAAQ,QACR,MAAM;AACZ,eAAS,aAAa;AACtB,oBAAc,oBACV,IACA,OAAO,QAAQ,eAAe,WAC5B,QAAQ,aACR,KAAK,IAAI,GAAG,KAAK,KAAK,MAAM,SAAS,SAAS,CAAC,CAAC;AAAA,IACxD,SAAS,OAAO;AACd,cAAQ,MAAM,2BAA2B,KAAK;AAC9C,YAAM,OAAO,OAAO,MAAM,OAAO;AAAA,IACnC,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,aAAa,QAAQ,OAAO,OAAO,MAAM,OAAO,QAAQ,MAAM,gBAAgB,QAAQ,OAAO,CAAC;AAElG,QAAM,UAAU,MAAM;AACpB,SAAK,gBAAgB;AAAA,EACvB,GAAG,CAAC,iBAAiB,cAAc,WAAW,CAAC;AAE/C,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,mBAAe,cAAc;AAC3B,UAAI;AACF,cAAM,aAAa,IAAI,gBAAgB,EAAE,MAAM,KAAK,UAAU,MAAM,CAAC;AACrE,cAAM,aAAa,IAAI,gBAAgB,EAAE,MAAM,KAAK,UAAU,MAAM,CAAC;AACrE,cAAM,CAAC,WAAW,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,UAC/C,QAAuB,oBAAoB,WAAW,SAAS,CAAC,EAAE;AAAA,UAClE,QAA2B,yBAAyB,WAAW,SAAS,CAAC,EAAE;AAAA,QAC7E,CAAC;AACD,cAAM,YAAY,MAAM,QAAQ,UAAU,QAAQ,KAAK,IAAI,UAAU,OAAO,QAAQ,CAAC;AACrF,cAAM,YAAY,MAAM,QAAQ,UAAU,QAAQ,KAAK,IAAI,UAAU,OAAO,QAAQ,CAAC;AACrF,cAAM,QAAQ,UACX,IAAI,CAAC,SAAS;AACb,gBAAM,KAAK,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AACnD,gBAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AACzD,cAAI,CAAC,MAAM,CAAC,KAAM,QAAO;AACzB,iBAAO,EAAE,OAAO,IAAI,OAAO,KAAK;AAAA,QAClC,CAAC,EACA,OAAO,CAAC,UAAqD,UAAU,IAAI;AAC9E,cAAM,QAAQ,UACX,IAAI,CAAC,SAAS;AACb,gBAAM,KAAK,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AACnD,gBAAM,OAAO,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO;AACzD,gBAAM,WAAW,KAAK,QAAQ,OAAO,KAAK,SAAS,YAAY,OAAO,KAAK,KAAK,SAAS,WACrF,KAAK,KAAK,OACV,OAAO,OAAO;AAClB,cAAI,CAAC,MAAM,CAAC,KAAM,QAAO;AACzB,iBAAO,EAAE,OAAO,IAAI,OAAO,GAAG,QAAQ,MAAM,IAAI,GAAG;AAAA,QACrD,CAAC,EACA,OAAO,CAAC,UAAqD,UAAU,IAAI;AAC9E,YAAI,CAAC,WAAW;AACd,+BAAqB,KAAK;AAC1B,+BAAqB,KAAK;AAAA,QAC5B;AAAA,MACF,QAAQ;AACN,YAAI,CAAC,WAAW;AACd,+BAAqB,CAAC,CAAC;AACvB,+BAAqB,CAAC,CAAC;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AACA,gBAAY;AACZ,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,YAAY,CAAC;AAEjB,QAAM,UAAU,MAAM,QAAqB,MAAM;AAAA,IAC/C;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO,QAAQ;AAAA,MACtB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa,OAAO,QAAQ;AAAA,IAC9B;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,OAAO,QAAQ;AAAA,MACtB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa,OAAO,QAAQ;AAAA,IAC9B;AAAA,EACF,GAAG,CAAC,OAAO,QAAQ,MAAM,OAAO,QAAQ,MAAM,mBAAmB,iBAAiB,CAAC;AAEnF,QAAM,qBAAqB,MAAM,YAAY,CAAC,UAAkB;AAC9D,cAAU,KAAK;AACf,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,UAAU,QAAQ,YAAY,CAAC;AAEnC,QAAM,qBAAqB,MAAM,YAAY,CAAC,WAAyB;AACrE,oBAAgB,MAAM;AACtB,YAAQ,CAAC;AAET,UAAM,SAAS,IAAI,gBAAgB,cAAc,SAAS,CAAC;AAC3D,UAAM,YAAY,OAAO,OAAO,WAAW,YAAY,OAAO,OAAO,SAAS;AAC9E,QAAI,CAAC,aAAa,OAAO,IAAI,QAAQ,GAAG;AACtC,aAAO,OAAO,QAAQ;AAAA,IACxB;AACA,UAAM,YAAY,OAAO,OAAO,WAAW,YAAY,OAAO,OAAO,SAAS;AAC9E,QAAI,CAAC,aAAa,OAAO,IAAI,QAAQ,GAAG;AACtC,aAAO,OAAO,QAAQ;AAAA,IACxB;AACA,UAAM,QAAQ,OAAO,SAAS;AAC9B,WAAO,QAAQ,QAAQ,GAAG,QAAQ,IAAI,KAAK,KAAK,QAAQ;AAAA,EAC1D,GAAG,CAAC,UAAU,QAAQ,YAAY,CAAC;AAEnC,QAAM,qBAAqB,MAAM,YAAY,MAAM;AACjD,oBAAgB,CAAC,CAAC;AAClB,YAAQ,CAAC;AAET,UAAM,SAAS,IAAI,gBAAgB,cAAc,SAAS,CAAC;AAC3D,QAAI,OAAO,IAAI,QAAQ,GAAG;AACxB,aAAO,OAAO,QAAQ;AAAA,IACxB;AACA,QAAI,OAAO,IAAI,QAAQ,GAAG;AACxB,aAAO,OAAO,QAAQ;AAAA,IACxB;AACA,UAAM,QAAQ,OAAO,SAAS;AAC9B,WAAO,QAAQ,QAAQ,GAAG,QAAQ,IAAI,KAAK,KAAK,QAAQ;AAAA,EAC1D,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgB,MAAM,YAAY,MAAM;AAC5C,mBAAe,CAAC,UAAU,QAAQ,CAAC;AAAA,EACrC,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,MAAM,YAAY,OAAO,UAAyB;AACrE,QAAI,MAAM,SAAS,SAAU;AAC7B,UAAM,UAAU,OAAO,QAAQ,cAAc,QAAQ,YAAY,MAAM,WAAW;AAClF,UAAM,YAAY,MAAM,QAAQ;AAAA,MAC9B,OAAO,OAAO,QAAQ;AAAA,MACtB,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAW;AAChB,QAAI;AACF,YAAM,WAAW,sBAAsB,MAAM,IAAI,EAAE,cAAc,OAAO,OAAO,OAAO,CAAC;AACvF,YAAM,OAAO,SAAS,SAAS,SAAS;AACxC,oBAAc;AAAA,IAChB,SAAS,OAAO;AACd,cAAQ,MAAM,6BAA6B,KAAK;AAChD,YAAM,OAAO,OAAO,QAAQ,OAAO;AAAA,IACrC;AAAA,EACF,GAAG,CAAC,SAAS,eAAe,OAAO,QAAQ,eAAe,OAAO,QAAQ,QAAQ,OAAO,OAAO,QAAQ,OAAO,SAAS,OAAO,CAAC;AAE/H,SACE,qBAAC,QACC;AAAA,wBAAC,YACC;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,OAAO;AAAA,QACd,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,mBAAmB,OAAO,MAAM;AAAA,QAChC;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB,gBAAgB;AAAA,QAChB,YAAY,oBAAC,OAAE,WAAU,kDAAkD,iBAAO,MAAM,OAAM;AAAA,QAC9F,SACE,oBAAC,UAAO,SAAO,MAAC,MAAK,MACnB,8BAAC,QAAK,MAAK,sCACR,iBAAO,QAAQ,KAClB,GACF;AAAA,QAEF,eAAe;AAAA,UACb,OAAO,OAAO,QAAQ;AAAA,UACtB,WAAW;AAAA,UACX,cAAc;AAAA,QAChB;AAAA,QACA,UAAQ;AAAA,QACR;AAAA,QACA,iBAAiB;AAAA,QACjB,YAAY;AAAA,UACV;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA;AAAA,UACA,cAAc;AAAA,QAChB;AAAA,QACA,YAAY,CAAC,QAAQ,IAAI,SAAS,WAChC;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,EAAE,IAAI,QAAQ,OAAO,OAAO,QAAQ,MAAM,UAAU,MAAM;AAAE,uBAAO,KAAK,+BAA+B,IAAI,EAAE,EAAE;AAAA,cAAE,EAAE;AAAA,cACnH,EAAE,IAAI,UAAU,OAAO,OAAO,QAAQ,QAAQ,aAAa,MAAM,UAAU,MAAM;AAAE,qBAAK,aAAa,GAAG;AAAA,cAAE,EAAE;AAAA,YAC9G;AAAA;AAAA,QACF,IACE;AAAA;AAAA,IACN,GACF;AAAA,IACC;AAAA,KACH;AAEJ;AAkBA,SAAS,iBAAiB,MAAiD;AACzE,QAAM,KAAK,OAAO,KAAK,OAAO,WAAW,KAAK,KAAK;AACnD,QAAM,cAAc,OAAO,KAAK,gBAAgB,WAC5C,KAAK,cACL,OAAO,KAAK,iBAAiB,WAC3B,KAAK,eACL;AACN,QAAM,cAAc,OAAO,KAAK,gBAAgB,YAAY,KAAK,YAAY,KAAK,EAAE,SAChF,KAAK,YAAY,KAAK,IACtB;AACJ,QAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,SAAS,WAAW,KAAK,OAA8B;AAC7F,QAAM,YAAY,QAAQ,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,SAAS,KAAK,QAAQ;AAC7F,QAAM,YAAY,MAAM,QAAQ,KAAK,SAAS,IAAI,KAAK,UAAU,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ,IAAI,CAAC;AAClI,QAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,IACtC,KAAK,QAAQ,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ,IACzE,MAAM,QAAQ,KAAK,QAAQ,IACzB,KAAK,SAAS,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ,IAC1E,CAAC;AACP,QAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,KAAK,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ,IAAI,CAAC;AACnH,QAAM,YAAY,OAAO,KAAK,cAAc,WACxC,KAAK,YACL,OAAO,KAAK,eAAe,WACzB,KAAK,aACL;AACN,QAAM,WAAW,OAAO,KAAK,aAAa,YACtC,KAAK,WACL,OAAO,KAAK,cAAc,YACxB,KAAK,YACL;AACN,QAAM,SAAS,OAAO,KAAK,WAAW,WAClC,KAAK,SACL,OAAO,KAAK,YAAY,WACtB,KAAK,UACL;AACN,QAAM,OAAO,KAAK,QAAQ,OAAO,KAAK,SAAS,WAAW,KAAK,OAA6B;AAC5F,QAAM,WAAW,OAAO,MAAM,SAAS,WAAW,KAAK,OAAO;AAC9D,SAAO,wBAAwB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAG,IAAI;AACT;AAEA,SAAS,mBACP,OACA,QACA,MACA,OACQ;AACR,QAAM,YAAY,KAAK,YAAY,OAAO,gBAAgB,kBAAkB;AAC5E,QAAM,aAAa,MAAM,YAAY,OAAO,gBAAgB,kBAAkB;AAC9E,QAAM,iBAAiB,SAAS,cAAc,SAAS;AACvD,MAAI,mBAAmB,EAAG,QAAO;AACjC,MAAI,KAAK,SAAS,MAAM,KAAM,QAAO,KAAK,SAAS,SAAS,KAAK;AACjE,MAAI,KAAK,SAAS,UAAU,MAAM,SAAS,OAAQ,QAAO;AAC1D,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,KAAK,YAAY,cAAc,MAAM,WAAW;AAAA,IACzD,KAAK;AACH,cAAQ,KAAK,aAAa,IAAI,cAAc,MAAM,aAAa,EAAE;AAAA,IACnE,KAAK;AACH,aAAO,KAAK,UAAU,KAAK,IAAI,EAAE,cAAc,MAAM,UAAU,KAAK,IAAI,CAAC;AAAA,IAC3E,KAAK;AACH,aAAO,KAAK,KAAK,KAAK,IAAI,EAAE,cAAc,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,IACjE,KAAK;AACH,aAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,MAAM,QAAQ;AAAA,IACtD,KAAK;AACH,aAAO,mBAAmB,KAAK,WAAW,MAAM,SAAS;AAAA,EAC7D;AACF;AAEA,SAAS,mBAAmB,MAAqB,OAA8B;AAC7E,MAAI,CAAC,QAAQ,CAAC,MAAO,QAAO;AAC5B,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,WAAW,KAAK,MAAM,IAAI;AAChC,QAAM,YAAY,KAAK,MAAM,KAAK;AAClC,MAAI,OAAO,MAAM,QAAQ,KAAK,OAAO,MAAM,SAAS,GAAG;AACrD,WAAO,KAAK,cAAc,KAAK;AAAA,EACjC;AACA,SAAO,WAAW;AACpB;AAEA,SAAS,oBACP,OACA,QACiB;AACjB,QAAM,aAAa,oBAAI,IAAkF;AACzG,aAAW,UAAU,OAAO;AAC1B,UAAM,MAAM,OAAO,UAAU;AAC7B,UAAM,OAAO,OAAO,YAAY,OAAO;AACvC,UAAM,QAAQ,WAAW,IAAI,GAAG,KAAK,EAAE,QAAQ,OAAO,UAAU,MAAM,MAAM,SAAS,CAAC,EAAE;AACxF,UAAM,QAAQ,KAAK,MAAM;AACzB,eAAW,IAAI,KAAK,KAAK;AAAA,EAC3B;AACA,QAAM,cAAc,MAAM,KAAK,WAAW,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAC/F,QAAM,OAAwB,CAAC;AAC/B,aAAW,QAAQ,aAAa;AAC9B,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,IAAI,QAAQ,KAAK,UAAU,YAAY;AAAA,MACvC,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,WAAW;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,aAAa;AAAA,MACb,WAAW;AAAA,MACX,WAAW,CAAC;AAAA,MACZ,MAAM,CAAC;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,IACb,CAAC;AACD,UAAM,gBAAgB,CAAC,GAAG,KAAK,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,cAAc,EAAE,WAAW,CAAC;AACjG,eAAW,UAAU,eAAe;AAClC,WAAK,KAAK;AAAA,QACR,MAAM;AAAA,QACN,IAAI,OAAO;AAAA,QACX,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO;AAAA,QACjB,WAAW,OAAO,UAAU,SACxB,OAAO,UAAU,KAAK,IAAI,IAC1B,OAAO;AAAA,QACX,aAAa,OAAO;AAAA,QACpB,aAAa,OAAO;AAAA,QACpB,WAAW,OAAO;AAAA,QAClB,WAAW,OAAO;AAAA,QAClB,MAAM,OAAO;AAAA,QACb,UAAU,OAAO;AAAA,QACjB,WAAW,OAAO;AAAA,MACpB,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAIA,SAAS,iBAAiB,QAAmC;AAC3D,MAAI,CAAC,OAAO,OAAQ,QAAO,oBAAC,UAAK,WAAU,iCAAgC,eAAC;AAC5E,SACE,oBAAC,SAAI,WAAU,wBACZ,iBAAO,IAAI,CAAC,UACX,oBAAC,UAAiB,WAAU,8EACzB,mBADQ,KAEX,CACD,GACH;AAEJ;AAEA,SAAS,UAAU,EAAE,UAAU,GAA2B;AACxD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,QAAO;AAAA,MACP,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAY;AAAA,MACZ;AAAA,MACA,eAAY;AAAA,MAEZ;AAAA,4BAAC,YAAO,IAAG,KAAI,IAAG,KAAI,GAAE,KAAI;AAAA,QAC5B,oBAAC,YAAO,IAAG,MAAK,IAAG,KAAI,GAAE,KAAI;AAAA,QAC7B,oBAAC,UAAK,GAAE,qBAAoB;AAAA,QAC5B,oBAAC,UAAK,GAAE,sBAAqB;AAAA;AAAA;AAAA,EAC/B;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -5,7 +5,7 @@ import Link from "next/link";
5
5
  import dynamic from "next/dynamic";
6
6
  import { useRouter } from "next/navigation";
7
7
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
8
- import { DataTable } from "@open-mercato/ui/backend/DataTable";
8
+ import { DataTable, withDataTableNamespaces } from "@open-mercato/ui/backend/DataTable";
9
9
  import { RowActions } from "@open-mercato/ui/backend/RowActions";
10
10
  import { Button } from "@open-mercato/ui/primitives/button";
11
11
  import { readApiResultOrThrow, apiCall } from "@open-mercato/ui/backend/utils/apiCall";
@@ -304,7 +304,7 @@ function mapApiTeamRole(item) {
304
304
  const team = item.team && typeof item.team === "object" ? item.team : null;
305
305
  const teamName = typeof team?.name === "string" ? team.name : null;
306
306
  const memberCount = typeof item.memberCount === "number" ? item.memberCount : 0;
307
- return { id, name, description, updatedAt, teamId, teamName, memberCount };
307
+ return withDataTableNamespaces({ id, name, description, updatedAt, teamId, teamName, memberCount }, item);
308
308
  }
309
309
  function buildTeamRoleRows(items, unassignedLabel) {
310
310
  const groups = /* @__PURE__ */ new Map();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/staff/backend/staff/team-roles/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport dynamic from 'next/dynamic'\nimport type { PluggableList } from 'unified'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow, apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { Pencil, Users } from 'lucide-react'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { truncate } from 'fs'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\n\nconst PAGE_SIZE = 50\nconst isTestEnv = typeof process !== 'undefined' && process.env.NODE_ENV === 'test'\nconst MARKDOWN_CLASSNAME =\n 'text-sm text-foreground break-words [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs'\n\ntype MarkdownPreviewProps = { children: string; className?: string; remarkPlugins?: PluggableList }\n\nconst MarkdownPreview: React.ComponentType<MarkdownPreviewProps> = isTestEnv\n ? ({ children, className }) => <div className={className}>{children}</div>\n : (dynamic(() => import('react-markdown').then((mod) => mod.default as React.ComponentType<MarkdownPreviewProps>), {\n ssr: false,\n loading: () => null,\n }) as unknown as React.ComponentType<MarkdownPreviewProps>)\n\nlet markdownPluginsPromise: Promise<PluggableList> | null = null\n\nasync function loadMarkdownPlugins(): Promise<PluggableList> {\n if (isTestEnv) return []\n if (!markdownPluginsPromise) {\n markdownPluginsPromise = import('remark-gfm')\n .then((mod) => [mod.default ?? mod] as PluggableList)\n .catch(() => [])\n }\n return markdownPluginsPromise\n}\n\ntype TeamRoleRow = {\n kind: 'team' | 'role'\n id: string\n teamId: string | null\n name: string\n description: string | null\n updatedAt: string | null\n memberCount: number\n}\n\ntype TeamRolesResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\ntype TeamsResponse = {\n items?: Array<{ id?: string; name?: string }>\n}\n\nexport default function StaffTeamRolesPage() {\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<TeamRoleRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [markdownPlugins, setMarkdownPlugins] = React.useState<PluggableList>([])\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [teamFilterOptions, setTeamFilterOptions] = React.useState<Array<{ value: string; label: string }>>([])\n\n React.useEffect(() => {\n void loadMarkdownPlugins().then((plugins) => setMarkdownPlugins(plugins))\n }, [])\n\n const labels = React.useMemo(() => ({\n title: t('staff.teamRoles.page.title', 'Team roles'),\n description: t('staff.teamRoles.page.description', 'Define roles that can be assigned to team members.'),\n table: {\n name: t('staff.teamRoles.table.name', 'Name'),\n description: t('staff.teamRoles.table.description', 'Description'),\n members: t('staff.teamRoles.table.members', 'Team members'),\n updatedAt: t('staff.teamRoles.table.updatedAt', 'Updated'),\n empty: t('staff.teamRoles.table.empty', 'No team roles yet.'),\n search: t('staff.teamRoles.table.search', 'Search roles...'),\n },\n groups: {\n unassigned: t('staff.teamRoles.group.unassigned', 'Unassigned'),\n },\n filters: {\n team: t('staff.teamRoles.filters.team', 'Team'),\n },\n actions: {\n add: t('staff.teamRoles.actions.add', 'Add team role'),\n edit: t('staff.teamRoles.actions.edit', 'Edit'),\n showMembers: t('staff.teamRoles.actions.showMembers', 'Show team members ({{count}})'),\n delete: t('staff.teamRoles.actions.delete', 'Delete'),\n deleteConfirm: t('staff.teamRoles.actions.deleteConfirm', 'Delete team role \"{{name}}\"?'),\n refresh: t('staff.teamRoles.actions.refresh', 'Refresh'),\n editTeam: t('staff.teams.actions.edit', 'Edit'),\n },\n messages: {\n deleted: t('staff.teamRoles.messages.deleted', 'Team role deleted.'),\n },\n errors: {\n load: t('staff.teamRoles.errors.load', 'Failed to load team roles.'),\n delete: t('staff.teamRoles.errors.delete', 'Failed to delete team role.'),\n },\n }), [t])\n\n const columns = React.useMemo<ColumnDef<TeamRoleRow>[]>(() => [\n {\n accessorKey: 'name',\n header: labels.table.name,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => {\n if (row.original.kind === 'team') {\n return (\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n {row.original.teamId ? <TeamsIcon className=\"h-4 w-4 text-muted-foreground\" /> : null}\n <span className=\"font-semibold\">{row.original.name}</span>\n </div>\n {row.original.teamId ? (\n <Button\n asChild\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-7 w-7\"\n title={labels.actions.editTeam}\n aria-label={labels.actions.editTeam}\n >\n <Link href={`/backend/staff/teams/${encodeURIComponent(row.original.teamId)}/edit`}>\n <Pencil className=\"h-4 w-4\" />\n </Link>\n </Button>\n ) : null}\n </div>\n )\n }\n return (\n <div className=\"flex flex-col\">\n <span className=\"font-medium pl-6\">{row.original.name}</span>\n {row.original.description ? (\n <MarkdownPreview\n remarkPlugins={markdownPlugins}\n className={`${MARKDOWN_CLASSNAME} pl-6 text-xs text-muted-foreground line-clamp-2`}\n >\n {row.original.description}\n </MarkdownPreview>\n ) : null}\n </div>\n )\n },\n },\n {\n accessorKey: 'description',\n header: labels.table.description,\n meta: { priority: 3 },\n cell: ({ row }) => row.original.kind === 'team'\n ? <span className=\"text-xs text-muted-foreground\">-</span>\n : row.original.description\n ? (\n <MarkdownPreview remarkPlugins={markdownPlugins} className={MARKDOWN_CLASSNAME}>\n {row.original.description}\n </MarkdownPreview>\n )\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'memberCount',\n header: () => <span className=\"inline-block min-w-[250px]\">{labels.table.members}</span>,\n meta: { priority: 3, maxWidth: '250px', truncate: true },\n enableSorting: false,\n cell: ({ row }) => row.original.kind === 'role'\n ? (\n <Link\n className=\"inline-flex min-w-[220px] items-center gap-2 text-sm text-muted-foreground hover:text-foreground\"\n href={`/backend/staff/team-members?roleId=${encodeURIComponent(row.original.id)}`}\n onClick={(event) => event.stopPropagation()}\n >\n <Users className=\"h-4 w-4\" aria-hidden />\n {labels.actions.showMembers.replace('{{count}}', String(row.original.memberCount))}\n </Link>\n )\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'updatedAt',\n header: labels.table.updatedAt,\n meta: { priority: 4 },\n cell: ({ row }) => row.original.kind === 'team'\n ? <span className=\"text-xs text-muted-foreground\">-</span>\n : row.original.updatedAt\n ? <span className=\"text-xs text-muted-foreground\">{formatDateTime(row.original.updatedAt)}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n ], [labels.actions.showMembers, labels.table.description, labels.table.members, labels.table.name, labels.table.updatedAt, markdownPlugins])\n\n const loadTeamRoles = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n if (search.trim()) params.set('search', search.trim())\n if (typeof filterValues.teamId === 'string' && filterValues.teamId.trim()) {\n params.set('teamId', filterValues.teamId)\n }\n const payload = await readApiResultOrThrow<TeamRolesResponse>(\n `/api/staff/team-roles?${params.toString()}`,\n undefined,\n { errorMessage: labels.errors.load, fallback: { items: [], total: 0, totalPages: 1 } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(buildTeamRoleRows(items.map(mapApiTeamRole), labels.groups.unassigned))\n setTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : Math.max(1, Math.ceil(items.length / PAGE_SIZE)))\n } catch (error) {\n console.error('staff.team-roles.list', error)\n flash(labels.errors.load, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [filterValues.teamId, labels.errors.load, labels.groups, page, search])\n\n React.useEffect(() => {\n void loadTeamRoles()\n }, [loadTeamRoles, scopeVersion, reloadToken])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFilters() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100' })\n const response = await apiCall<TeamsResponse>(`/api/staff/teams?${params.toString()}`)\n const teamItems = Array.isArray(response.result?.items) ? response.result.items : []\n const teams = teamItems\n .map((team) => {\n const id = typeof team.id === 'string' ? team.id : null\n const name = typeof team.name === 'string' ? team.name : null\n if (!id || !name) return null\n return { value: id, label: name }\n })\n .filter((entry): entry is { value: string; label: string } => entry !== null)\n if (!cancelled) setTeamFilterOptions(teams)\n } catch {\n if (!cancelled) setTeamFilterOptions([])\n }\n }\n loadFilters()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'teamId',\n label: labels.filters.team,\n type: 'select',\n options: teamFilterOptions,\n placeholder: labels.filters.team,\n },\n ], [labels.filters.team, teamFilterOptions])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n setReloadToken((token) => token + 1)\n }, [])\n\n const handleDelete = React.useCallback(async (entry: TeamRoleRow) => {\n if (entry.kind !== 'role') return\n const message = labels.actions.deleteConfirm.replace('{{name}}', entry.name)\n const confirmed = await confirm({\n title: labels.actions.delete,\n text: message,\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n await deleteCrud('staff/team-roles', entry.id, { errorMessage: labels.errors.delete })\n flash(labels.messages.deleted, 'success')\n handleRefresh()\n } catch (error) {\n console.error('staff.team-roles.delete', error)\n flash(labels.errors.delete, 'error')\n }\n }, [confirm, handleRefresh, labels.actions.deleteConfirm, labels.actions.delete, labels.errors.delete, labels.messages.deleted])\n\n return (\n <Page>\n <PageBody>\n <DataTable<TeamRoleRow>\n title={labels.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={labels.table.search}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{labels.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/team-roles/create\">\n {labels.actions.add}\n </Link>\n </Button>\n )}\n refreshButton={{\n label: labels.actions.refresh,\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n rowActions={(row) => row.kind === 'role' ? (\n <RowActions\n items={[\n { id: 'edit', label: labels.actions.edit, onSelect: () => { router.push(`/backend/staff/team-roles/${row.id}/edit`) } },\n { id: 'delete', label: labels.actions.delete, destructive: true, onSelect: () => { void handleDelete(row) } },\n ]}\n />\n ) : null}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n\ntype TeamRoleApiRow = {\n id: string\n name: string\n description: string | null\n updatedAt: string | null\n teamId: string | null\n teamName: string | null\n memberCount: number\n}\n\nfunction mapApiTeamRole(item: Record<string, unknown>): TeamRoleApiRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const name = typeof item.name === 'string' ? item.name : id\n const description = typeof item.description === 'string' && item.description.trim().length ? item.description.trim() : null\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n const teamId = typeof item.teamId === 'string'\n ? item.teamId\n : typeof item.team_id === 'string'\n ? item.team_id\n : null\n const team = item.team && typeof item.team === 'object'\n ? item.team as { name?: unknown }\n : null\n const teamName = typeof team?.name === 'string' ? team.name : null\n const memberCount = typeof item.memberCount === 'number' ? item.memberCount : 0\n return { id, name, description, updatedAt, teamId, teamName, memberCount }\n}\n\nfunction buildTeamRoleRows(items: TeamRoleApiRow[], unassignedLabel: string): TeamRoleRow[] {\n const groups = new Map<string, { teamId: string | null; name: string; roles: TeamRoleApiRow[] }>()\n for (const role of items) {\n const key = role.teamId ?? 'unassigned'\n const label = role.teamName ?? unassignedLabel\n const group = groups.get(key) ?? { teamId: role.teamId ?? null, name: label, roles: [] }\n group.roles.push(role)\n groups.set(key, group)\n }\n const sortedGroups = Array.from(groups.values()).sort((a, b) => a.name.localeCompare(b.name))\n const rows: TeamRoleRow[] = []\n for (const group of sortedGroups) {\n rows.push({\n kind: 'team',\n id: `team:${group.teamId ?? 'unassigned'}`,\n teamId: group.teamId,\n name: group.name,\n description: null,\n updatedAt: null,\n memberCount: 0,\n })\n const sortedRoles = [...group.roles].sort((a, b) => a.name.localeCompare(b.name))\n for (const role of sortedRoles) {\n rows.push({\n kind: 'role',\n id: role.id,\n teamId: role.teamId,\n name: role.name,\n description: role.description,\n updatedAt: role.updatedAt,\n memberCount: role.memberCount,\n })\n }\n }\n return rows\n}\n\n\n\nfunction TeamsIcon({ className }: { className?: string }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n className={className}\n aria-hidden=\"true\"\n >\n <circle cx=\"8\" cy=\"8\" r=\"3\" />\n <circle cx=\"16\" cy=\"8\" r=\"3\" />\n <path d=\"M3 20c0-3 3-5 5-5\" />\n <path d=\"M21 20c0-3-3-5-5-5\" />\n </svg>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport dynamic from 'next/dynamic'\nimport type { PluggableList } from 'unified'\nimport { useRouter } from 'next/navigation'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow, apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { Pencil, Users } from 'lucide-react'\nimport type { FilterDef, FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { truncate } from 'fs'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\n\nconst PAGE_SIZE = 50\nconst isTestEnv = typeof process !== 'undefined' && process.env.NODE_ENV === 'test'\nconst MARKDOWN_CLASSNAME =\n 'text-sm text-foreground break-words [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs'\n\ntype MarkdownPreviewProps = { children: string; className?: string; remarkPlugins?: PluggableList }\n\nconst MarkdownPreview: React.ComponentType<MarkdownPreviewProps> = isTestEnv\n ? ({ children, className }) => <div className={className}>{children}</div>\n : (dynamic(() => import('react-markdown').then((mod) => mod.default as React.ComponentType<MarkdownPreviewProps>), {\n ssr: false,\n loading: () => null,\n }) as unknown as React.ComponentType<MarkdownPreviewProps>)\n\nlet markdownPluginsPromise: Promise<PluggableList> | null = null\n\nasync function loadMarkdownPlugins(): Promise<PluggableList> {\n if (isTestEnv) return []\n if (!markdownPluginsPromise) {\n markdownPluginsPromise = import('remark-gfm')\n .then((mod) => [mod.default ?? mod] as PluggableList)\n .catch(() => [])\n }\n return markdownPluginsPromise\n}\n\ntype TeamRoleRow = {\n kind: 'team' | 'role'\n id: string\n teamId: string | null\n name: string\n description: string | null\n updatedAt: string | null\n memberCount: number\n}\n\ntype TeamRolesResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\ntype TeamsResponse = {\n items?: Array<{ id?: string; name?: string }>\n}\n\nexport default function StaffTeamRolesPage() {\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [rows, setRows] = React.useState<TeamRoleRow[]>([])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [markdownPlugins, setMarkdownPlugins] = React.useState<PluggableList>([])\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [teamFilterOptions, setTeamFilterOptions] = React.useState<Array<{ value: string; label: string }>>([])\n\n React.useEffect(() => {\n void loadMarkdownPlugins().then((plugins) => setMarkdownPlugins(plugins))\n }, [])\n\n const labels = React.useMemo(() => ({\n title: t('staff.teamRoles.page.title', 'Team roles'),\n description: t('staff.teamRoles.page.description', 'Define roles that can be assigned to team members.'),\n table: {\n name: t('staff.teamRoles.table.name', 'Name'),\n description: t('staff.teamRoles.table.description', 'Description'),\n members: t('staff.teamRoles.table.members', 'Team members'),\n updatedAt: t('staff.teamRoles.table.updatedAt', 'Updated'),\n empty: t('staff.teamRoles.table.empty', 'No team roles yet.'),\n search: t('staff.teamRoles.table.search', 'Search roles...'),\n },\n groups: {\n unassigned: t('staff.teamRoles.group.unassigned', 'Unassigned'),\n },\n filters: {\n team: t('staff.teamRoles.filters.team', 'Team'),\n },\n actions: {\n add: t('staff.teamRoles.actions.add', 'Add team role'),\n edit: t('staff.teamRoles.actions.edit', 'Edit'),\n showMembers: t('staff.teamRoles.actions.showMembers', 'Show team members ({{count}})'),\n delete: t('staff.teamRoles.actions.delete', 'Delete'),\n deleteConfirm: t('staff.teamRoles.actions.deleteConfirm', 'Delete team role \"{{name}}\"?'),\n refresh: t('staff.teamRoles.actions.refresh', 'Refresh'),\n editTeam: t('staff.teams.actions.edit', 'Edit'),\n },\n messages: {\n deleted: t('staff.teamRoles.messages.deleted', 'Team role deleted.'),\n },\n errors: {\n load: t('staff.teamRoles.errors.load', 'Failed to load team roles.'),\n delete: t('staff.teamRoles.errors.delete', 'Failed to delete team role.'),\n },\n }), [t])\n\n const columns = React.useMemo<ColumnDef<TeamRoleRow>[]>(() => [\n {\n accessorKey: 'name',\n header: labels.table.name,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => {\n if (row.original.kind === 'team') {\n return (\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n {row.original.teamId ? <TeamsIcon className=\"h-4 w-4 text-muted-foreground\" /> : null}\n <span className=\"font-semibold\">{row.original.name}</span>\n </div>\n {row.original.teamId ? (\n <Button\n asChild\n size=\"icon\"\n variant=\"ghost\"\n className=\"h-7 w-7\"\n title={labels.actions.editTeam}\n aria-label={labels.actions.editTeam}\n >\n <Link href={`/backend/staff/teams/${encodeURIComponent(row.original.teamId)}/edit`}>\n <Pencil className=\"h-4 w-4\" />\n </Link>\n </Button>\n ) : null}\n </div>\n )\n }\n return (\n <div className=\"flex flex-col\">\n <span className=\"font-medium pl-6\">{row.original.name}</span>\n {row.original.description ? (\n <MarkdownPreview\n remarkPlugins={markdownPlugins}\n className={`${MARKDOWN_CLASSNAME} pl-6 text-xs text-muted-foreground line-clamp-2`}\n >\n {row.original.description}\n </MarkdownPreview>\n ) : null}\n </div>\n )\n },\n },\n {\n accessorKey: 'description',\n header: labels.table.description,\n meta: { priority: 3 },\n cell: ({ row }) => row.original.kind === 'team'\n ? <span className=\"text-xs text-muted-foreground\">-</span>\n : row.original.description\n ? (\n <MarkdownPreview remarkPlugins={markdownPlugins} className={MARKDOWN_CLASSNAME}>\n {row.original.description}\n </MarkdownPreview>\n )\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'memberCount',\n header: () => <span className=\"inline-block min-w-[250px]\">{labels.table.members}</span>,\n meta: { priority: 3, maxWidth: '250px', truncate: true },\n enableSorting: false,\n cell: ({ row }) => row.original.kind === 'role'\n ? (\n <Link\n className=\"inline-flex min-w-[220px] items-center gap-2 text-sm text-muted-foreground hover:text-foreground\"\n href={`/backend/staff/team-members?roleId=${encodeURIComponent(row.original.id)}`}\n onClick={(event) => event.stopPropagation()}\n >\n <Users className=\"h-4 w-4\" aria-hidden />\n {labels.actions.showMembers.replace('{{count}}', String(row.original.memberCount))}\n </Link>\n )\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'updatedAt',\n header: labels.table.updatedAt,\n meta: { priority: 4 },\n cell: ({ row }) => row.original.kind === 'team'\n ? <span className=\"text-xs text-muted-foreground\">-</span>\n : row.original.updatedAt\n ? <span className=\"text-xs text-muted-foreground\">{formatDateTime(row.original.updatedAt)}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n ], [labels.actions.showMembers, labels.table.description, labels.table.members, labels.table.name, labels.table.updatedAt, markdownPlugins])\n\n const loadTeamRoles = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(page),\n pageSize: String(PAGE_SIZE),\n })\n if (search.trim()) params.set('search', search.trim())\n if (typeof filterValues.teamId === 'string' && filterValues.teamId.trim()) {\n params.set('teamId', filterValues.teamId)\n }\n const payload = await readApiResultOrThrow<TeamRolesResponse>(\n `/api/staff/team-roles?${params.toString()}`,\n undefined,\n { errorMessage: labels.errors.load, fallback: { items: [], total: 0, totalPages: 1 } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setRows(buildTeamRoleRows(items.map(mapApiTeamRole), labels.groups.unassigned))\n setTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setTotalPages(typeof payload.totalPages === 'number' ? payload.totalPages : Math.max(1, Math.ceil(items.length / PAGE_SIZE)))\n } catch (error) {\n console.error('staff.team-roles.list', error)\n flash(labels.errors.load, 'error')\n } finally {\n setIsLoading(false)\n }\n }, [filterValues.teamId, labels.errors.load, labels.groups, page, search])\n\n React.useEffect(() => {\n void loadTeamRoles()\n }, [loadTeamRoles, scopeVersion, reloadToken])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFilters() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100' })\n const response = await apiCall<TeamsResponse>(`/api/staff/teams?${params.toString()}`)\n const teamItems = Array.isArray(response.result?.items) ? response.result.items : []\n const teams = teamItems\n .map((team) => {\n const id = typeof team.id === 'string' ? team.id : null\n const name = typeof team.name === 'string' ? team.name : null\n if (!id || !name) return null\n return { value: id, label: name }\n })\n .filter((entry): entry is { value: string; label: string } => entry !== null)\n if (!cancelled) setTeamFilterOptions(teams)\n } catch {\n if (!cancelled) setTeamFilterOptions([])\n }\n }\n loadFilters()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'teamId',\n label: labels.filters.team,\n type: 'select',\n options: teamFilterOptions,\n placeholder: labels.filters.team,\n },\n ], [labels.filters.team, teamFilterOptions])\n\n const handleSearchChange = React.useCallback((value: string) => {\n setSearch(value)\n setPage(1)\n }, [])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n setPage(1)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n setPage(1)\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n setReloadToken((token) => token + 1)\n }, [])\n\n const handleDelete = React.useCallback(async (entry: TeamRoleRow) => {\n if (entry.kind !== 'role') return\n const message = labels.actions.deleteConfirm.replace('{{name}}', entry.name)\n const confirmed = await confirm({\n title: labels.actions.delete,\n text: message,\n variant: 'destructive',\n })\n if (!confirmed) return\n try {\n await deleteCrud('staff/team-roles', entry.id, { errorMessage: labels.errors.delete })\n flash(labels.messages.deleted, 'success')\n handleRefresh()\n } catch (error) {\n console.error('staff.team-roles.delete', error)\n flash(labels.errors.delete, 'error')\n }\n }, [confirm, handleRefresh, labels.actions.deleteConfirm, labels.actions.delete, labels.errors.delete, labels.messages.deleted])\n\n return (\n <Page>\n <PageBody>\n <DataTable<TeamRoleRow>\n title={labels.title}\n data={rows}\n columns={columns}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={handleSearchChange}\n searchPlaceholder={labels.table.search}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{labels.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/team-roles/create\">\n {labels.actions.add}\n </Link>\n </Button>\n )}\n refreshButton={{\n label: labels.actions.refresh,\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n pagination={{\n page,\n pageSize: PAGE_SIZE,\n total,\n totalPages,\n onPageChange: setPage,\n }}\n rowActions={(row) => row.kind === 'role' ? (\n <RowActions\n items={[\n { id: 'edit', label: labels.actions.edit, onSelect: () => { router.push(`/backend/staff/team-roles/${row.id}/edit`) } },\n { id: 'delete', label: labels.actions.delete, destructive: true, onSelect: () => { void handleDelete(row) } },\n ]}\n />\n ) : null}\n />\n </PageBody>\n {ConfirmDialogElement}\n </Page>\n )\n}\n\ntype TeamRoleApiRow = {\n id: string\n name: string\n description: string | null\n updatedAt: string | null\n teamId: string | null\n teamName: string | null\n memberCount: number\n}\n\nfunction mapApiTeamRole(item: Record<string, unknown>): TeamRoleApiRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const name = typeof item.name === 'string' ? item.name : id\n const description = typeof item.description === 'string' && item.description.trim().length ? item.description.trim() : null\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n const teamId = typeof item.teamId === 'string'\n ? item.teamId\n : typeof item.team_id === 'string'\n ? item.team_id\n : null\n const team = item.team && typeof item.team === 'object'\n ? item.team as { name?: unknown }\n : null\n const teamName = typeof team?.name === 'string' ? team.name : null\n const memberCount = typeof item.memberCount === 'number' ? item.memberCount : 0\n return withDataTableNamespaces({ id, name, description, updatedAt, teamId, teamName, memberCount }, item)\n}\n\nfunction buildTeamRoleRows(items: TeamRoleApiRow[], unassignedLabel: string): TeamRoleRow[] {\n const groups = new Map<string, { teamId: string | null; name: string; roles: TeamRoleApiRow[] }>()\n for (const role of items) {\n const key = role.teamId ?? 'unassigned'\n const label = role.teamName ?? unassignedLabel\n const group = groups.get(key) ?? { teamId: role.teamId ?? null, name: label, roles: [] }\n group.roles.push(role)\n groups.set(key, group)\n }\n const sortedGroups = Array.from(groups.values()).sort((a, b) => a.name.localeCompare(b.name))\n const rows: TeamRoleRow[] = []\n for (const group of sortedGroups) {\n rows.push({\n kind: 'team',\n id: `team:${group.teamId ?? 'unassigned'}`,\n teamId: group.teamId,\n name: group.name,\n description: null,\n updatedAt: null,\n memberCount: 0,\n })\n const sortedRoles = [...group.roles].sort((a, b) => a.name.localeCompare(b.name))\n for (const role of sortedRoles) {\n rows.push({\n kind: 'role',\n id: role.id,\n teamId: role.teamId,\n name: role.name,\n description: role.description,\n updatedAt: role.updatedAt,\n memberCount: role.memberCount,\n })\n }\n }\n return rows\n}\n\n\n\nfunction TeamsIcon({ className }: { className?: string }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n className={className}\n aria-hidden=\"true\"\n >\n <circle cx=\"8\" cy=\"8\" r=\"3\" />\n <circle cx=\"16\" cy=\"8\" r=\"3\" />\n <path d=\"M3 20c0-3 3-5 5-5\" />\n <path d=\"M21 20c0-3-3-5-5-5\" />\n </svg>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -6,7 +6,7 @@ import { useRouter, useSearchParams } from "next/navigation";
6
6
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
7
7
  import { readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
8
8
  import { updateCrud, deleteCrud } from "@open-mercato/ui/backend/utils/crud";
9
- import { DataTable } from "@open-mercato/ui/backend/DataTable";
9
+ import { DataTable, withDataTableNamespaces } from "@open-mercato/ui/backend/DataTable";
10
10
  import { RowActions } from "@open-mercato/ui/backend/RowActions";
11
11
  import { Button } from "@open-mercato/ui/primitives/button";
12
12
  import { BooleanIcon } from "@open-mercato/ui/backend/ValueIcons";
@@ -331,7 +331,7 @@ function mapApiTeamMember(item) {
331
331
  const updatedAt = typeof item.updatedAt === "string" ? item.updatedAt : typeof item.updated_at === "string" ? item.updated_at : null;
332
332
  const isActive = typeof item.isActive === "boolean" ? item.isActive : typeof item.is_active === "boolean" ? item.is_active : true;
333
333
  const teamId = typeof item.teamId === "string" ? item.teamId : typeof item.team_id === "string" ? item.team_id : null;
334
- return {
334
+ return withDataTableNamespaces({
335
335
  id,
336
336
  displayName,
337
337
  description,
@@ -341,7 +341,7 @@ function mapApiTeamMember(item) {
341
341
  isActive,
342
342
  updatedAt,
343
343
  teamId
344
- };
344
+ }, item);
345
345
  }
346
346
  export {
347
347
  StaffTeamEditPage as default
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../../src/modules/staff/backend/staff/teams/%5Bid%5D/edit/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { TeamForm, type TeamFormValues, buildTeamPayload } from '@open-mercato/core/modules/staff/components/TeamForm'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\nimport { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Plus } from 'lucide-react'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\n\nconst TEAM_MEMBERS_PAGE_SIZE = 50\n\ntype TeamRecord = {\n id: string\n name: string\n description?: string | null\n isActive?: boolean\n is_active?: boolean\n} & Record<string, unknown>\n\ntype TeamResponse = {\n items?: TeamRecord[]\n}\n\ntype TeamMemberRow = {\n id: string\n displayName: string\n description: string | null\n userEmail: string | null\n roleNames: string[]\n tags: string[]\n isActive: boolean\n updatedAt: string | null\n teamId: string | null\n}\n\ntype TeamMembersResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\nexport default function StaffTeamEditPage({ params }: { params?: { id?: string } }) {\n const teamId = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const scopeVersion = useOrganizationScopeVersion()\n const [initialValues, setInitialValues] = React.useState<TeamFormValues | null>(null)\n const [activeTab, setActiveTab] = React.useState<'details' | 'members'>('details')\n const [memberRows, setMemberRows] = React.useState<TeamMemberRow[]>([])\n const [memberPage, setMemberPage] = React.useState(1)\n const [memberTotal, setMemberTotal] = React.useState(0)\n const [memberTotalPages, setMemberTotalPages] = React.useState(1)\n const [memberSorting, setMemberSorting] = React.useState<SortingState>([{ id: 'displayName', desc: false }])\n const [memberSearch, setMemberSearch] = React.useState('')\n const [membersLoading, setMembersLoading] = React.useState(false)\n const [memberReloadToken, setMemberReloadToken] = React.useState(0)\n\n const memberLabels = React.useMemo(() => ({\n title: t('staff.teams.tabs.members', 'Team members'),\n description: t('staff.teamMembers.page.description', 'Manage employees and their team assignments.'),\n table: {\n name: t('staff.teamMembers.table.name', 'Name'),\n user: t('staff.teamMembers.table.user', 'User'),\n roles: t('staff.teamMembers.table.roles', 'Roles'),\n tags: t('staff.teamMembers.table.tags', 'Tags'),\n active: t('staff.teamMembers.table.active', 'Active'),\n updatedAt: t('staff.teamMembers.table.updatedAt', 'Updated'),\n empty: t('staff.teamMembers.table.empty', 'No team members yet.'),\n search: t('staff.teamMembers.table.search', 'Search team members...'),\n },\n actions: {\n add: t('staff.teamMembers.actions.add', 'Add team member'),\n edit: t('staff.teamMembers.actions.edit', 'Edit'),\n unassign: t('staff.teamMembers.actions.unassign', 'Unassign'),\n refresh: t('staff.teamMembers.actions.refresh', 'Refresh'),\n },\n messages: {\n unassigned: t('staff.teamMembers.messages.unassigned', 'Team member unassigned.'),\n },\n errors: {\n load: t('staff.teamMembers.errors.load', 'Failed to load team members.'),\n unassign: t('staff.teamMembers.errors.unassign', 'Failed to unassign team member.'),\n },\n tabs: {\n details: t('staff.teams.tabs.details', 'Details'),\n members: t('staff.teams.tabs.members', 'Team members'),\n label: t('staff.teams.tabs.label', 'Team sections'),\n },\n }), [t])\n\n const memberColumns = React.useMemo<ColumnDef<TeamMemberRow>[]>(() => [\n {\n accessorKey: 'displayName',\n header: memberLabels.table.name,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => (\n <div className=\"flex flex-col\">\n <span className=\"font-medium\">{row.original.displayName}</span>\n {row.original.description ? (\n <span className=\"text-xs text-muted-foreground line-clamp-2\">{row.original.description}</span>\n ) : null}\n </div>\n ),\n },\n {\n accessorKey: 'userEmail',\n header: memberLabels.table.user,\n meta: { priority: 2 },\n cell: ({ row }) => row.original.userEmail\n ? <span className=\"text-sm\">{row.original.userEmail}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'roleNames',\n header: memberLabels.table.roles,\n meta: { priority: 3 },\n cell: ({ row }) => row.original.roleNames.length\n ? <span className=\"text-sm\">{row.original.roleNames.join(', ')}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'tags',\n header: memberLabels.table.tags,\n meta: { priority: 4 },\n cell: ({ row }) => row.original.tags.length\n ? <span className=\"text-xs text-muted-foreground\">{row.original.tags.join(', ')}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'isActive',\n header: memberLabels.table.active,\n meta: { priority: 5 },\n cell: ({ row }) => <BooleanIcon value={row.original.isActive} />,\n },\n {\n accessorKey: 'updatedAt',\n header: memberLabels.table.updatedAt,\n meta: { priority: 6 },\n cell: ({ row }) => row.original.updatedAt\n ? <span className=\"text-xs text-muted-foreground\">{formatDateTime(row.original.updatedAt)}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n ], [\n memberLabels.table.active,\n memberLabels.table.name,\n memberLabels.table.roles,\n memberLabels.table.tags,\n memberLabels.table.updatedAt,\n memberLabels.table.user,\n ])\n\n React.useEffect(() => {\n if (!teamId) return\n const teamIdValue = teamId\n let cancelled = false\n async function loadTeam() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: teamIdValue })\n const payload = await readApiResultOrThrow<TeamResponse>(\n `/api/staff/teams?${params.toString()}`,\n undefined,\n { errorMessage: t('staff.teams.errors.load', 'Failed to load team.') },\n )\n const record = Array.isArray(payload.items) ? payload.items[0] : null\n if (!record) throw new Error(t('staff.teams.errors.notFound', 'Team not found.'))\n const customFields = extractCustomFieldEntries(record)\n const isActive = typeof record.isActive === 'boolean'\n ? record.isActive\n : typeof record.is_active === 'boolean'\n ? record.is_active\n : true\n if (!cancelled) {\n setInitialValues({\n id: record.id,\n name: record.name ?? '',\n description: record.description ?? '',\n isActive,\n ...customFields,\n })\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : t('staff.teams.errors.load', 'Failed to load team.')\n flash(message, 'error')\n }\n }\n loadTeam()\n return () => { cancelled = true }\n }, [teamId, t])\n\n React.useEffect(() => {\n if (!searchParams) return\n const tabParam = searchParams.get('tab')\n if (tabParam === 'members') {\n setActiveTab('members')\n }\n }, [searchParams])\n\n const loadTeamMembers = React.useCallback(async () => {\n if (!teamId) return\n setMembersLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(memberPage),\n pageSize: String(TEAM_MEMBERS_PAGE_SIZE),\n teamId,\n })\n const sort = memberSorting[0]\n if (sort?.id) {\n params.set('sortField', sort.id)\n params.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n if (memberSearch.trim()) params.set('search', memberSearch.trim())\n const payload = await readApiResultOrThrow<TeamMembersResponse>(\n `/api/staff/team-members?${params.toString()}`,\n undefined,\n { errorMessage: memberLabels.errors.load, fallback: { items: [], total: 0, totalPages: 1 } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setMemberRows(items.map(mapApiTeamMember))\n setMemberTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setMemberTotalPages(\n typeof payload.totalPages === 'number'\n ? payload.totalPages\n : Math.max(1, Math.ceil(items.length / TEAM_MEMBERS_PAGE_SIZE)),\n )\n } catch (error) {\n console.error('staff.teams.team-members.list', error)\n flash(memberLabels.errors.load, 'error')\n } finally {\n setMembersLoading(false)\n }\n }, [memberLabels.errors.load, memberPage, memberSearch, memberSorting, teamId])\n\n React.useEffect(() => {\n if (activeTab !== 'members') return\n void loadTeamMembers()\n }, [activeTab, loadTeamMembers, memberReloadToken, scopeVersion])\n\n const handleMemberSearchChange = React.useCallback((value: string) => {\n setMemberSearch(value)\n setMemberPage(1)\n }, [])\n\n const handleMemberRefresh = React.useCallback(() => {\n setMemberReloadToken((token) => token + 1)\n }, [])\n\n const handleUnassignMember = React.useCallback(async (entry: TeamMemberRow) => {\n if (!teamId || entry.teamId !== teamId) return\n try {\n await updateCrud('staff/team-members', { id: entry.id, teamId: null }, { errorMessage: memberLabels.errors.unassign })\n flash(memberLabels.messages.unassigned, 'success')\n handleMemberRefresh()\n } catch (error) {\n console.error('staff.teams.team-members.unassign', error)\n flash(memberLabels.errors.unassign, 'error')\n }\n }, [handleMemberRefresh, memberLabels.errors.unassign, memberLabels.messages.unassigned, teamId])\n\n const handleSubmit = React.useCallback(async (values: TeamFormValues) => {\n if (!teamId) return\n const payload = buildTeamPayload(values, { id: teamId })\n await updateCrud('staff/teams', payload, {\n errorMessage: t('staff.teams.errors.save', 'Failed to save team.'),\n })\n flash(t('staff.teams.messages.saved', 'Team saved.'), 'success')\n }, [teamId, t])\n\n const handleDelete = React.useCallback(async () => {\n if (!teamId) return\n try {\n await deleteCrud('staff/teams', teamId, {\n errorMessage: t('staff.teams.errors.delete', 'Failed to delete team.'),\n })\n flash(t('staff.teams.messages.deleted', 'Team deleted.'), 'success')\n router.push('/backend/staff/teams')\n } catch (error) {\n const message = error instanceof Error\n ? error.message\n : t('staff.teams.errors.delete', 'Failed to delete team.')\n flash(message, 'error')\n }\n }, [teamId, router, t])\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <div className=\"border-b\">\n <nav className=\"flex flex-wrap items-center gap-5 text-sm\" aria-label={memberLabels.tabs.label}>\n {[\n { id: 'details', label: memberLabels.tabs.details },\n { id: 'members', label: memberLabels.tabs.members },\n ].map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n onClick={() => setActiveTab(tab.id as 'details' | 'members')}\n className={`relative -mb-px border-b-2 px-0 py-2 text-sm font-medium transition-colors ${\n activeTab === tab.id\n ? 'border-primary text-foreground'\n : 'border-transparent text-muted-foreground hover:text-foreground'\n }`}\n >\n {tab.label}\n </button>\n ))}\n </nav>\n </div>\n\n {activeTab === 'details' ? (\n <TeamForm\n title={t('staff.teams.form.editTitle', 'Edit team')}\n backHref=\"/backend/staff/teams\"\n cancelHref=\"/backend/staff/teams\"\n initialValues={initialValues ?? { name: '', description: '', isActive: true }}\n onSubmit={handleSubmit}\n onDelete={handleDelete}\n isLoading={!initialValues}\n loadingMessage={t('staff.teams.form.loading', 'Loading team...')}\n extraActions={teamId ? (\n <SendObjectMessageDialog\n object={{\n entityModule: 'staff',\n entityType: 'team',\n entityId: teamId,\n previewData: { title: initialValues?.name ?? ''},\n }}\n viewHref={`/backend/staff/teams/${teamId}/edit`}\n />\n ) : undefined}\n />\n ) : (\n <DataTable<TeamMemberRow>\n title={memberLabels.title}\n data={memberRows}\n columns={memberColumns}\n isLoading={membersLoading}\n searchValue={memberSearch}\n onSearchChange={handleMemberSearchChange}\n searchPlaceholder={memberLabels.table.search}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{memberLabels.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href={`/backend/staff/team-members/create?teamId=${encodeURIComponent(teamId ?? '')}`}>\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {memberLabels.actions.add}\n </Link>\n </Button>\n )}\n refreshButton={{\n label: memberLabels.actions.refresh,\n onRefresh: handleMemberRefresh,\n isRefreshing: membersLoading,\n }}\n sortable\n sorting={memberSorting}\n onSortingChange={setMemberSorting}\n pagination={{\n page: memberPage,\n pageSize: TEAM_MEMBERS_PAGE_SIZE,\n total: memberTotal,\n totalPages: memberTotalPages,\n onPageChange: setMemberPage,\n }}\n rowActions={(row) => (\n <RowActions\n items={[\n { id: 'edit', label: memberLabels.actions.edit, onSelect: () => { router.push(`/backend/staff/team-members/${row.id}`) } },\n { id: 'unassign', label: memberLabels.actions.unassign, onSelect: () => { void handleUnassignMember(row) } },\n ]}\n />\n )}\n />\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n\nfunction mapApiTeamMember(item: Record<string, unknown>): TeamMemberRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const displayName = typeof item.displayName === 'string'\n ? item.displayName\n : typeof item.display_name === 'string'\n ? item.display_name\n : id\n const description = typeof item.description === 'string' && item.description.trim().length\n ? item.description.trim()\n : null\n const user = item.user && typeof item.user === 'object' ? item.user as { email?: unknown } : null\n const userEmail = user && typeof user.email === 'string' && user.email.length ? user.email : null\n const roleNames = Array.isArray(item.roleNames) ? item.roleNames.filter((value): value is string => typeof value === 'string') : []\n const tags = Array.isArray(item.tags) ? item.tags.filter((value): value is string => typeof value === 'string') : []\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n const isActive = typeof item.isActive === 'boolean'\n ? item.isActive\n : typeof item.is_active === 'boolean'\n ? item.is_active\n : true\n const teamId = typeof item.teamId === 'string'\n ? item.teamId\n : typeof item.team_id === 'string'\n ? item.team_id\n : null\n return {\n id,\n displayName,\n description,\n userEmail,\n roleNames,\n tags,\n isActive,\n updatedAt,\n teamId,\n }\n}\n\n\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { TeamForm, type TeamFormValues, buildTeamPayload } from '@open-mercato/core/modules/staff/components/TeamForm'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\nimport { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Plus } from 'lucide-react'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\n\nconst TEAM_MEMBERS_PAGE_SIZE = 50\n\ntype TeamRecord = {\n id: string\n name: string\n description?: string | null\n isActive?: boolean\n is_active?: boolean\n} & Record<string, unknown>\n\ntype TeamResponse = {\n items?: TeamRecord[]\n}\n\ntype TeamMemberRow = {\n id: string\n displayName: string\n description: string | null\n userEmail: string | null\n roleNames: string[]\n tags: string[]\n isActive: boolean\n updatedAt: string | null\n teamId: string | null\n}\n\ntype TeamMembersResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n totalPages?: number\n}\n\nexport default function StaffTeamEditPage({ params }: { params?: { id?: string } }) {\n const teamId = params?.id\n const t = useT()\n const router = useRouter()\n const searchParams = useSearchParams()\n const scopeVersion = useOrganizationScopeVersion()\n const [initialValues, setInitialValues] = React.useState<TeamFormValues | null>(null)\n const [activeTab, setActiveTab] = React.useState<'details' | 'members'>('details')\n const [memberRows, setMemberRows] = React.useState<TeamMemberRow[]>([])\n const [memberPage, setMemberPage] = React.useState(1)\n const [memberTotal, setMemberTotal] = React.useState(0)\n const [memberTotalPages, setMemberTotalPages] = React.useState(1)\n const [memberSorting, setMemberSorting] = React.useState<SortingState>([{ id: 'displayName', desc: false }])\n const [memberSearch, setMemberSearch] = React.useState('')\n const [membersLoading, setMembersLoading] = React.useState(false)\n const [memberReloadToken, setMemberReloadToken] = React.useState(0)\n\n const memberLabels = React.useMemo(() => ({\n title: t('staff.teams.tabs.members', 'Team members'),\n description: t('staff.teamMembers.page.description', 'Manage employees and their team assignments.'),\n table: {\n name: t('staff.teamMembers.table.name', 'Name'),\n user: t('staff.teamMembers.table.user', 'User'),\n roles: t('staff.teamMembers.table.roles', 'Roles'),\n tags: t('staff.teamMembers.table.tags', 'Tags'),\n active: t('staff.teamMembers.table.active', 'Active'),\n updatedAt: t('staff.teamMembers.table.updatedAt', 'Updated'),\n empty: t('staff.teamMembers.table.empty', 'No team members yet.'),\n search: t('staff.teamMembers.table.search', 'Search team members...'),\n },\n actions: {\n add: t('staff.teamMembers.actions.add', 'Add team member'),\n edit: t('staff.teamMembers.actions.edit', 'Edit'),\n unassign: t('staff.teamMembers.actions.unassign', 'Unassign'),\n refresh: t('staff.teamMembers.actions.refresh', 'Refresh'),\n },\n messages: {\n unassigned: t('staff.teamMembers.messages.unassigned', 'Team member unassigned.'),\n },\n errors: {\n load: t('staff.teamMembers.errors.load', 'Failed to load team members.'),\n unassign: t('staff.teamMembers.errors.unassign', 'Failed to unassign team member.'),\n },\n tabs: {\n details: t('staff.teams.tabs.details', 'Details'),\n members: t('staff.teams.tabs.members', 'Team members'),\n label: t('staff.teams.tabs.label', 'Team sections'),\n },\n }), [t])\n\n const memberColumns = React.useMemo<ColumnDef<TeamMemberRow>[]>(() => [\n {\n accessorKey: 'displayName',\n header: memberLabels.table.name,\n meta: { priority: 1, sticky: true },\n cell: ({ row }) => (\n <div className=\"flex flex-col\">\n <span className=\"font-medium\">{row.original.displayName}</span>\n {row.original.description ? (\n <span className=\"text-xs text-muted-foreground line-clamp-2\">{row.original.description}</span>\n ) : null}\n </div>\n ),\n },\n {\n accessorKey: 'userEmail',\n header: memberLabels.table.user,\n meta: { priority: 2 },\n cell: ({ row }) => row.original.userEmail\n ? <span className=\"text-sm\">{row.original.userEmail}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'roleNames',\n header: memberLabels.table.roles,\n meta: { priority: 3 },\n cell: ({ row }) => row.original.roleNames.length\n ? <span className=\"text-sm\">{row.original.roleNames.join(', ')}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'tags',\n header: memberLabels.table.tags,\n meta: { priority: 4 },\n cell: ({ row }) => row.original.tags.length\n ? <span className=\"text-xs text-muted-foreground\">{row.original.tags.join(', ')}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n {\n accessorKey: 'isActive',\n header: memberLabels.table.active,\n meta: { priority: 5 },\n cell: ({ row }) => <BooleanIcon value={row.original.isActive} />,\n },\n {\n accessorKey: 'updatedAt',\n header: memberLabels.table.updatedAt,\n meta: { priority: 6 },\n cell: ({ row }) => row.original.updatedAt\n ? <span className=\"text-xs text-muted-foreground\">{formatDateTime(row.original.updatedAt)}</span>\n : <span className=\"text-xs text-muted-foreground\">-</span>,\n },\n ], [\n memberLabels.table.active,\n memberLabels.table.name,\n memberLabels.table.roles,\n memberLabels.table.tags,\n memberLabels.table.updatedAt,\n memberLabels.table.user,\n ])\n\n React.useEffect(() => {\n if (!teamId) return\n const teamIdValue = teamId\n let cancelled = false\n async function loadTeam() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: teamIdValue })\n const payload = await readApiResultOrThrow<TeamResponse>(\n `/api/staff/teams?${params.toString()}`,\n undefined,\n { errorMessage: t('staff.teams.errors.load', 'Failed to load team.') },\n )\n const record = Array.isArray(payload.items) ? payload.items[0] : null\n if (!record) throw new Error(t('staff.teams.errors.notFound', 'Team not found.'))\n const customFields = extractCustomFieldEntries(record)\n const isActive = typeof record.isActive === 'boolean'\n ? record.isActive\n : typeof record.is_active === 'boolean'\n ? record.is_active\n : true\n if (!cancelled) {\n setInitialValues({\n id: record.id,\n name: record.name ?? '',\n description: record.description ?? '',\n isActive,\n ...customFields,\n })\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : t('staff.teams.errors.load', 'Failed to load team.')\n flash(message, 'error')\n }\n }\n loadTeam()\n return () => { cancelled = true }\n }, [teamId, t])\n\n React.useEffect(() => {\n if (!searchParams) return\n const tabParam = searchParams.get('tab')\n if (tabParam === 'members') {\n setActiveTab('members')\n }\n }, [searchParams])\n\n const loadTeamMembers = React.useCallback(async () => {\n if (!teamId) return\n setMembersLoading(true)\n try {\n const params = new URLSearchParams({\n page: String(memberPage),\n pageSize: String(TEAM_MEMBERS_PAGE_SIZE),\n teamId,\n })\n const sort = memberSorting[0]\n if (sort?.id) {\n params.set('sortField', sort.id)\n params.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n if (memberSearch.trim()) params.set('search', memberSearch.trim())\n const payload = await readApiResultOrThrow<TeamMembersResponse>(\n `/api/staff/team-members?${params.toString()}`,\n undefined,\n { errorMessage: memberLabels.errors.load, fallback: { items: [], total: 0, totalPages: 1 } },\n )\n const items = Array.isArray(payload.items) ? payload.items : []\n setMemberRows(items.map(mapApiTeamMember))\n setMemberTotal(typeof payload.total === 'number' ? payload.total : items.length)\n setMemberTotalPages(\n typeof payload.totalPages === 'number'\n ? payload.totalPages\n : Math.max(1, Math.ceil(items.length / TEAM_MEMBERS_PAGE_SIZE)),\n )\n } catch (error) {\n console.error('staff.teams.team-members.list', error)\n flash(memberLabels.errors.load, 'error')\n } finally {\n setMembersLoading(false)\n }\n }, [memberLabels.errors.load, memberPage, memberSearch, memberSorting, teamId])\n\n React.useEffect(() => {\n if (activeTab !== 'members') return\n void loadTeamMembers()\n }, [activeTab, loadTeamMembers, memberReloadToken, scopeVersion])\n\n const handleMemberSearchChange = React.useCallback((value: string) => {\n setMemberSearch(value)\n setMemberPage(1)\n }, [])\n\n const handleMemberRefresh = React.useCallback(() => {\n setMemberReloadToken((token) => token + 1)\n }, [])\n\n const handleUnassignMember = React.useCallback(async (entry: TeamMemberRow) => {\n if (!teamId || entry.teamId !== teamId) return\n try {\n await updateCrud('staff/team-members', { id: entry.id, teamId: null }, { errorMessage: memberLabels.errors.unassign })\n flash(memberLabels.messages.unassigned, 'success')\n handleMemberRefresh()\n } catch (error) {\n console.error('staff.teams.team-members.unassign', error)\n flash(memberLabels.errors.unassign, 'error')\n }\n }, [handleMemberRefresh, memberLabels.errors.unassign, memberLabels.messages.unassigned, teamId])\n\n const handleSubmit = React.useCallback(async (values: TeamFormValues) => {\n if (!teamId) return\n const payload = buildTeamPayload(values, { id: teamId })\n await updateCrud('staff/teams', payload, {\n errorMessage: t('staff.teams.errors.save', 'Failed to save team.'),\n })\n flash(t('staff.teams.messages.saved', 'Team saved.'), 'success')\n }, [teamId, t])\n\n const handleDelete = React.useCallback(async () => {\n if (!teamId) return\n try {\n await deleteCrud('staff/teams', teamId, {\n errorMessage: t('staff.teams.errors.delete', 'Failed to delete team.'),\n })\n flash(t('staff.teams.messages.deleted', 'Team deleted.'), 'success')\n router.push('/backend/staff/teams')\n } catch (error) {\n const message = error instanceof Error\n ? error.message\n : t('staff.teams.errors.delete', 'Failed to delete team.')\n flash(message, 'error')\n }\n }, [teamId, router, t])\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <div className=\"border-b\">\n <nav className=\"flex flex-wrap items-center gap-5 text-sm\" aria-label={memberLabels.tabs.label}>\n {[\n { id: 'details', label: memberLabels.tabs.details },\n { id: 'members', label: memberLabels.tabs.members },\n ].map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={activeTab === tab.id}\n onClick={() => setActiveTab(tab.id as 'details' | 'members')}\n className={`relative -mb-px border-b-2 px-0 py-2 text-sm font-medium transition-colors ${\n activeTab === tab.id\n ? 'border-primary text-foreground'\n : 'border-transparent text-muted-foreground hover:text-foreground'\n }`}\n >\n {tab.label}\n </button>\n ))}\n </nav>\n </div>\n\n {activeTab === 'details' ? (\n <TeamForm\n title={t('staff.teams.form.editTitle', 'Edit team')}\n backHref=\"/backend/staff/teams\"\n cancelHref=\"/backend/staff/teams\"\n initialValues={initialValues ?? { name: '', description: '', isActive: true }}\n onSubmit={handleSubmit}\n onDelete={handleDelete}\n isLoading={!initialValues}\n loadingMessage={t('staff.teams.form.loading', 'Loading team...')}\n extraActions={teamId ? (\n <SendObjectMessageDialog\n object={{\n entityModule: 'staff',\n entityType: 'team',\n entityId: teamId,\n previewData: { title: initialValues?.name ?? ''},\n }}\n viewHref={`/backend/staff/teams/${teamId}/edit`}\n />\n ) : undefined}\n />\n ) : (\n <DataTable<TeamMemberRow>\n title={memberLabels.title}\n data={memberRows}\n columns={memberColumns}\n isLoading={membersLoading}\n searchValue={memberSearch}\n onSearchChange={handleMemberSearchChange}\n searchPlaceholder={memberLabels.table.search}\n emptyState={<p className=\"py-8 text-center text-sm text-muted-foreground\">{memberLabels.table.empty}</p>}\n actions={(\n <Button asChild size=\"sm\">\n <Link href={`/backend/staff/team-members/create?teamId=${encodeURIComponent(teamId ?? '')}`}>\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {memberLabels.actions.add}\n </Link>\n </Button>\n )}\n refreshButton={{\n label: memberLabels.actions.refresh,\n onRefresh: handleMemberRefresh,\n isRefreshing: membersLoading,\n }}\n sortable\n sorting={memberSorting}\n onSortingChange={setMemberSorting}\n pagination={{\n page: memberPage,\n pageSize: TEAM_MEMBERS_PAGE_SIZE,\n total: memberTotal,\n totalPages: memberTotalPages,\n onPageChange: setMemberPage,\n }}\n rowActions={(row) => (\n <RowActions\n items={[\n { id: 'edit', label: memberLabels.actions.edit, onSelect: () => { router.push(`/backend/staff/team-members/${row.id}`) } },\n { id: 'unassign', label: memberLabels.actions.unassign, onSelect: () => { void handleUnassignMember(row) } },\n ]}\n />\n )}\n />\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n\nfunction mapApiTeamMember(item: Record<string, unknown>): TeamMemberRow {\n const id = typeof item.id === 'string' ? item.id : ''\n const displayName = typeof item.displayName === 'string'\n ? item.displayName\n : typeof item.display_name === 'string'\n ? item.display_name\n : id\n const description = typeof item.description === 'string' && item.description.trim().length\n ? item.description.trim()\n : null\n const user = item.user && typeof item.user === 'object' ? item.user as { email?: unknown } : null\n const userEmail = user && typeof user.email === 'string' && user.email.length ? user.email : null\n const roleNames = Array.isArray(item.roleNames) ? item.roleNames.filter((value): value is string => typeof value === 'string') : []\n const tags = Array.isArray(item.tags) ? item.tags.filter((value): value is string => typeof value === 'string') : []\n const updatedAt = typeof item.updatedAt === 'string'\n ? item.updatedAt\n : typeof item.updated_at === 'string'\n ? item.updated_at\n : null\n const isActive = typeof item.isActive === 'boolean'\n ? item.isActive\n : typeof item.is_active === 'boolean'\n ? item.is_active\n : true\n const teamId = typeof item.teamId === 'string'\n ? item.teamId\n : typeof item.team_id === 'string'\n ? item.team_id\n : null\n return withDataTableNamespaces({\n id,\n displayName,\n description,\n userEmail,\n roleNames,\n tags,\n isActive,\n updatedAt,\n teamId,\n }, item)\n}\n\n"],
5
+ "mappings": "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",
6
6
  "names": ["params"]
7
7
  }
@@ -5,7 +5,7 @@ import Link from "next/link";
5
5
  import dynamic from "next/dynamic";
6
6
  import { useRouter } from "next/navigation";
7
7
  import { Page, PageBody } from "@open-mercato/ui/backend/Page";
8
- import { DataTable } from "@open-mercato/ui/backend/DataTable";
8
+ import { DataTable, withDataTableNamespaces } from "@open-mercato/ui/backend/DataTable";
9
9
  import { RowActions } from "@open-mercato/ui/backend/RowActions";
10
10
  import { Button } from "@open-mercato/ui/primitives/button";
11
11
  import { BooleanIcon } from "@open-mercato/ui/backend/ValueIcons";
@@ -252,7 +252,7 @@ function mapApiTeam(item) {
252
252
  const updatedAt = typeof item.updatedAt === "string" ? item.updatedAt : typeof item.updated_at === "string" ? item.updated_at : null;
253
253
  const isActive = typeof item.isActive === "boolean" ? item.isActive : typeof item.is_active === "boolean" ? item.is_active : true;
254
254
  const memberCount = typeof item.memberCount === "number" ? item.memberCount : typeof item.member_count === "number" ? item.member_count : 0;
255
- return { id, name, description, isActive, updatedAt, memberCount };
255
+ return withDataTableNamespaces({ id, name, description, isActive, updatedAt, memberCount }, item);
256
256
  }
257
257
  export {
258
258
  StaffTeamsPage as default