@open-mercato/core 0.4.5-develop-636d33c995 → 0.4.5-develop-3d8e759e45
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.
- package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js +17 -2
- package/dist/modules/catalog/backend/catalog/categories/[id]/edit/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +15 -0
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +30 -0
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
- package/dist/modules/catalog/inbox-actions.js +51 -0
- package/dist/modules/catalog/inbox-actions.js.map +7 -0
- package/dist/modules/catalog/lib/messageObjectPreviews.js +146 -0
- package/dist/modules/catalog/lib/messageObjectPreviews.js.map +7 -0
- package/dist/modules/catalog/message-objects.js +95 -0
- package/dist/modules/catalog/message-objects.js.map +7 -0
- package/dist/modules/currencies/backend/currencies/[id]/page.js +21 -0
- package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
- package/dist/modules/currencies/lib/messageObjectPreviews.js +51 -0
- package/dist/modules/currencies/lib/messageObjectPreviews.js.map +7 -0
- package/dist/modules/currencies/message-objects.js +41 -0
- package/dist/modules/currencies/message-objects.js.map +7 -0
- package/dist/modules/customers/backend/customers/companies/[id]/page.js +20 -0
- package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +12 -1
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +20 -0
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyHighlights.js +18 -14
- package/dist/modules/customers/components/detail/CompanyHighlights.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonHighlights.js +18 -14
- package/dist/modules/customers/components/detail/PersonHighlights.js.map +2 -2
- package/dist/modules/customers/inbox-actions.js +230 -0
- package/dist/modules/customers/inbox-actions.js.map +7 -0
- package/dist/modules/customers/lib/messageObjectPreviews.js +41 -5
- package/dist/modules/customers/lib/messageObjectPreviews.js.map +2 -2
- package/dist/modules/customers/message-objects.js +31 -11
- package/dist/modules/customers/message-objects.js.map +2 -2
- package/dist/modules/inbox_ops/api/emails/[id]/route.js +40 -1
- package/dist/modules/inbox_ops/api/emails/[id]/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/extract/route.js +87 -0
- package/dist/modules/inbox_ops/api/extract/route.js.map +7 -0
- package/dist/modules/inbox_ops/api/proposals/[id]/translate/route.js +6 -1
- package/dist/modules/inbox_ops/api/proposals/[id]/translate/route.js.map +2 -2
- package/dist/modules/inbox_ops/api/proposals/counts/route.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +40 -14
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.meta.js +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.meta.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js +161 -79
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.meta.js +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.meta.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js +109 -62
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.js.map +3 -3
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.meta.js +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.meta.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +36 -14
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.meta.js +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.meta.js.map +2 -2
- package/dist/modules/inbox_ops/components/proposals/ActionCard.js +65 -10
- package/dist/modules/inbox_ops/components/proposals/ActionCard.js.map +2 -2
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +58 -10
- package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
- package/dist/modules/inbox_ops/lib/constants.js.map +2 -2
- package/dist/modules/inbox_ops/lib/contactValidation.js +40 -0
- package/dist/modules/inbox_ops/lib/contactValidation.js.map +7 -0
- package/dist/modules/inbox_ops/lib/executionEngine.js +31 -826
- package/dist/modules/inbox_ops/lib/executionEngine.js.map +3 -3
- package/dist/modules/inbox_ops/lib/executionHelpers.js +368 -0
- package/dist/modules/inbox_ops/lib/executionHelpers.js.map +7 -0
- package/dist/modules/inbox_ops/lib/extractionPrompt.js +28 -35
- package/dist/modules/inbox_ops/lib/extractionPrompt.js.map +3 -3
- package/dist/modules/inbox_ops/lib/inbox-actions-generated.d.js +1 -0
- package/dist/modules/inbox_ops/lib/inbox-actions-generated.d.js.map +7 -0
- package/dist/modules/inbox_ops/lib/translationProvider.js +15 -10
- package/dist/modules/inbox_ops/lib/translationProvider.js.map +2 -2
- package/dist/modules/inbox_ops/subscribers/extractionWorker.js +16 -16
- package/dist/modules/inbox_ops/subscribers/extractionWorker.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +3 -0
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/objects-panel.js +6 -1
- package/dist/modules/messages/components/message-detail/panels/objects-panel.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js +4 -1
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +2 -2
- package/dist/modules/messages/frontend/messages/view/[token]/page.js +1 -0
- package/dist/modules/messages/frontend/messages/view/[token]/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +24 -7
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/resources/lib/messageObjectPreviews.js +43 -0
- package/dist/modules/resources/lib/messageObjectPreviews.js.map +7 -0
- package/dist/modules/resources/message-objects.js +37 -0
- package/dist/modules/resources/message-objects.js.map +7 -0
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +19 -0
- package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +23 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/quotes/[id]/page.js +1 -1
- package/dist/modules/sales/backend/sales/quotes/[id]/page.js.map +2 -2
- package/dist/modules/sales/inbox-actions.js +278 -0
- package/dist/modules/sales/inbox-actions.js.map +7 -0
- package/dist/modules/sales/lib/messageObjectPreviews.js +49 -4
- package/dist/modules/sales/lib/messageObjectPreviews.js.map +2 -2
- package/dist/modules/sales/message-objects.js +44 -2
- package/dist/modules/sales/message-objects.js.map +2 -2
- package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js +59 -30
- package/dist/modules/sales/widgets/messages/SalesDocumentMessageDetail.js.map +2 -2
- package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js +1 -1
- package/dist/modules/sales/widgets/messages/SalesDocumentMessagePreview.js.map +1 -1
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +8 -30
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-availability/page.js +13 -0
- package/dist/modules/staff/backend/staff/my-availability/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +8 -31
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +32 -10
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js +14 -1
- package/dist/modules/staff/backend/staff/team-roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +14 -1
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/components/TeamForm.js +4 -2
- package/dist/modules/staff/components/TeamForm.js.map +2 -2
- package/dist/modules/staff/components/TeamRoleForm.js +4 -2
- package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
- package/dist/modules/staff/lib/messageObjectPreviews.js +111 -2
- package/dist/modules/staff/lib/messageObjectPreviews.js.map +2 -2
- package/dist/modules/staff/message-objects.js +79 -8
- package/dist/modules/staff/message-objects.js.map +2 -2
- package/jest.config.cjs +1 -0
- package/jest.mocks/inbox-actions.generated.js +5 -0
- package/package.json +2 -2
- package/src/modules/catalog/backend/catalog/categories/[id]/edit/page.tsx +19 -5
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +14 -0
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +40 -0
- package/src/modules/catalog/inbox-actions.ts +60 -0
- package/src/modules/catalog/lib/messageObjectPreviews.ts +176 -0
- package/src/modules/catalog/message-objects.ts +102 -0
- package/src/modules/currencies/backend/currencies/[id]/page.tsx +20 -0
- package/src/modules/currencies/lib/messageObjectPreviews.ts +65 -0
- package/src/modules/currencies/message-objects.ts +40 -0
- package/src/modules/customers/backend/customers/companies/[id]/page.tsx +19 -0
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +13 -0
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +19 -0
- package/src/modules/customers/components/detail/CompanyHighlights.tsx +14 -9
- package/src/modules/customers/components/detail/PersonHighlights.tsx +14 -9
- package/src/modules/customers/inbox-actions.ts +285 -0
- package/src/modules/customers/lib/messageObjectPreviews.ts +43 -3
- package/src/modules/customers/message-objects.ts +31 -11
- package/src/modules/inbox_ops/api/emails/[id]/route.ts +44 -0
- package/src/modules/inbox_ops/api/extract/route.ts +94 -0
- package/src/modules/inbox_ops/api/proposals/[id]/translate/route.ts +6 -1
- package/src/modules/inbox_ops/api/proposals/counts/route.ts +2 -0
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.meta.ts +2 -2
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +43 -13
- package/src/modules/inbox_ops/backend/inbox-ops/page.meta.ts +2 -2
- package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +176 -81
- package/src/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.meta.ts +2 -2
- package/src/modules/inbox_ops/backend/inbox-ops/proposals/[id]/page.tsx +122 -68
- package/src/modules/inbox_ops/backend/inbox-ops/settings/page.meta.ts +2 -2
- package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +36 -14
- package/src/modules/inbox_ops/components/proposals/ActionCard.tsx +91 -7
- package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +64 -12
- package/src/modules/inbox_ops/lib/constants.ts +9 -0
- package/src/modules/inbox_ops/lib/contactValidation.ts +54 -0
- package/src/modules/inbox_ops/lib/executionEngine.ts +47 -1060
- package/src/modules/inbox_ops/lib/executionHelpers.ts +527 -0
- package/src/modules/inbox_ops/lib/extractionPrompt.ts +45 -34
- package/src/modules/inbox_ops/lib/inbox-actions-generated.d.ts +11 -0
- package/src/modules/inbox_ops/lib/translationProvider.ts +16 -10
- package/src/modules/inbox_ops/subscribers/extractionWorker.ts +16 -18
- package/src/modules/messages/commands/messages.ts +4 -0
- package/src/modules/messages/components/message-detail/panels/objects-panel.tsx +8 -1
- package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +3 -0
- package/src/modules/messages/frontend/messages/view/[token]/page.tsx +1 -0
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +20 -4
- package/src/modules/resources/lib/messageObjectPreviews.ts +55 -0
- package/src/modules/resources/message-objects.ts +36 -0
- package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +18 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +23 -0
- package/src/modules/sales/backend/sales/quotes/[id]/page.tsx +1 -1
- package/src/modules/sales/inbox-actions.ts +359 -0
- package/src/modules/sales/lib/messageObjectPreviews.ts +54 -4
- package/src/modules/sales/message-objects.ts +44 -2
- package/src/modules/sales/widgets/messages/SalesDocumentMessageDetail.tsx +72 -34
- package/src/modules/sales/widgets/messages/SalesDocumentMessagePreview.tsx +1 -1
- package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +7 -29
- package/src/modules/staff/backend/staff/my-availability/page.tsx +14 -0
- package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +8 -30
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +28 -7
- package/src/modules/staff/backend/staff/team-roles/[id]/edit/page.tsx +12 -0
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +12 -0
- package/src/modules/staff/components/TeamForm.tsx +3 -0
- package/src/modules/staff/components/TeamRoleForm.tsx +3 -0
- package/src/modules/staff/lib/messageObjectPreviews.ts +133 -2
- package/src/modules/staff/message-objects.ts +79 -8
- package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js +0 -51
- package/dist/modules/customers/widgets/messages/CustomerMessageObjectDetail.js.map +0 -7
- package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js +0 -35
- package/dist/modules/customers/widgets/messages/CustomerMessageObjectPreview.js.map +0 -7
- package/dist/modules/customers/widgets/messages/index.js +0 -7
- package/dist/modules/customers/widgets/messages/index.js.map +0 -7
- package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js +0 -51
- package/dist/modules/staff/widgets/messages/StaffMessageObjectDetail.js.map +0 -7
- package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js +0 -34
- package/dist/modules/staff/widgets/messages/StaffMessageObjectPreview.js.map +0 -7
- package/dist/modules/staff/widgets/messages/index.js +0 -7
- package/dist/modules/staff/widgets/messages/index.js.map +0 -7
- package/src/modules/customers/widgets/messages/CustomerMessageObjectDetail.tsx +0 -57
- package/src/modules/customers/widgets/messages/CustomerMessageObjectPreview.tsx +0 -49
- package/src/modules/customers/widgets/messages/index.ts +0 -2
- package/src/modules/staff/widgets/messages/StaffMessageObjectDetail.tsx +0 -57
- package/src/modules/staff/widgets/messages/StaffMessageObjectPreview.tsx +0 -44
- package/src/modules/staff/widgets/messages/index.ts +0 -2
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
import { JobHistorySection } from "@open-mercato/core/modules/staff/components/detail/JobHistorySection";
|
|
30
30
|
import { Plus } from "lucide-react";
|
|
31
31
|
import { TranslationDrawerAction } from "@open-mercato/core/modules/translations/components/TranslationDrawerAction";
|
|
32
|
+
import { SendObjectMessageDialog } from "@open-mercato/ui/backend/messages";
|
|
32
33
|
const MARKDOWN_CLASSNAME = "text-sm text-muted-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";
|
|
33
34
|
function StaffTeamMemberDetailPage({ params }) {
|
|
34
35
|
const memberId = params?.id;
|
|
@@ -260,16 +261,37 @@ function StaffTeamMemberDetailPage({ params }) {
|
|
|
260
261
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: t("staff.teamMembers.detail.subtitle", "Team member profile and activity") })
|
|
261
262
|
] })
|
|
262
263
|
] }),
|
|
263
|
-
/* @__PURE__ */
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
264
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
265
|
+
memberId ? /* @__PURE__ */ jsx(
|
|
266
|
+
SendObjectMessageDialog,
|
|
267
|
+
{
|
|
268
|
+
object: {
|
|
269
|
+
entityModule: "staff",
|
|
270
|
+
entityType: "team_member",
|
|
271
|
+
entityId: memberId,
|
|
272
|
+
previewData: {
|
|
273
|
+
title: displayName,
|
|
274
|
+
metadata: {
|
|
275
|
+
[t("staff.teamMembers.detail.fields.team")]: teamLabel,
|
|
276
|
+
[t("staff.teamMembers.detail.fields.user")]: userEmail ?? t("staff.teamMembers.detail.fields.userEmpty", "No user linked"),
|
|
277
|
+
[t("staff.teamMembers.detail.fields.roles")]: roleLabels.join(", ")
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
viewHref: `/backend/staff/team-members/${memberId}`
|
|
282
|
+
}
|
|
283
|
+
) : null,
|
|
284
|
+
/* @__PURE__ */ jsx(
|
|
285
|
+
TranslationDrawerAction,
|
|
286
|
+
{
|
|
287
|
+
config: memberId ? {
|
|
288
|
+
entityType: "staff:staff_team_member",
|
|
289
|
+
recordId: memberId,
|
|
290
|
+
baseValues: memberRecord ?? void 0
|
|
291
|
+
} : null
|
|
292
|
+
}
|
|
293
|
+
)
|
|
294
|
+
] })
|
|
273
295
|
] }),
|
|
274
296
|
/* @__PURE__ */ jsx("div", { className: "border-b", children: /* @__PURE__ */ jsx(
|
|
275
297
|
"nav",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/staff/backend/staff/team-members/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useRouter, useSearchParams } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { AvailabilityRulesEditor } from '@open-mercato/core/modules/planner/components/AvailabilityRulesEditor'\nimport { buildMemberScheduleItems } from '@open-mercato/core/modules/staff/lib/memberSchedule'\nimport { TeamMemberForm, buildTeamMemberPayload, type TeamMemberFormValues } from '@open-mercato/core/modules/staff/components/TeamMemberForm'\nimport { NotesSection } from '@open-mercato/ui/backend/detail'\nimport { ActivitiesSection, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { AddressesSection as SharedAddressesSection } from '@open-mercato/ui/backend/detail'\nimport { renderDictionaryColor, renderDictionaryIcon, ICON_SUGGESTIONS } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { createStaffNotesAdapter } from '@open-mercato/core/modules/staff/components/detail/notesAdapter'\nimport { createStaffActivitiesAdapter } from '@open-mercato/core/modules/staff/components/detail/activitiesAdapter'\nimport { createStaffAddressAdapter, createStaffAddressTypesAdapter } from '@open-mercato/core/modules/staff/components/detail/addressesAdapter'\nimport { MarkdownContent } from '@open-mercato/ui/backend/markdown/MarkdownContent'\nimport {\n createStaffDictionaryEntry,\n loadStaffDictionary,\n type DictionaryEntryOption,\n} from '@open-mercato/core/modules/staff/components/detail/dictionaries'\nimport { JobHistorySection } from '@open-mercato/core/modules/staff/components/detail/JobHistorySection'\nimport type { DictionarySelectLabels } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { Plus } from 'lucide-react'\nimport { TranslationDrawerAction } from '@open-mercato/core/modules/translations/components/TranslationDrawerAction'\n\nconst MARKDOWN_CLASSNAME =\n 'text-sm text-muted-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 TeamMemberRecord = {\n id: string\n teamId?: string | null\n team_id?: string | null\n displayName: string\n display_name?: string\n description?: string | null\n userId?: string | null\n user_id?: string | null\n roleIds?: string[]\n role_ids?: string[]\n roleNames?: string[]\n tags?: string[]\n isActive?: boolean\n is_active?: boolean\n availabilityRuleSetId?: string | null\n availability_rule_set_id?: string | null\n user?: { id?: string; email?: string | null } | null\n team?: { id?: string; name?: string | null } | null\n customFields?: Record<string, unknown> | null\n} & Record<string, unknown>\n\ntype TeamMemberResponse = {\n items?: TeamMemberRecord[]\n}\n\nexport default function StaffTeamMemberDetailPage({ params }: { params?: { id?: string } }) {\n const memberId = params?.id\n const t = useT()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n const router = useRouter()\n const searchParams = useSearchParams()\n const [initialValues, setInitialValues] = React.useState<TeamMemberFormValues | null>(null)\n const [memberRecord, setMemberRecord] = React.useState<TeamMemberRecord | null>(null)\n const [availabilityRuleSetId, setAvailabilityRuleSetId] = React.useState<string | null>(null)\n const [activePanel, setActivePanel] = React.useState<'details' | 'availability' | 'jobHistory'>('details')\n const [activeTab, setActiveTab] = React.useState<'notes' | 'activities' | 'addresses'>('notes')\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [activityDictionaryId, setActivityDictionaryId] = React.useState<string | null>(null)\n const [activityTypeEntries, setActivityTypeEntries] = React.useState<DictionaryEntryOption[]>([])\n const flashShownRef = React.useRef(false)\n\n const notesAdapter = React.useMemo(() => createStaffNotesAdapter(detailTranslator), [detailTranslator])\n const activitiesAdapter = React.useMemo(() => createStaffActivitiesAdapter(detailTranslator), [detailTranslator])\n const addressesAdapter = React.useMemo(() => createStaffAddressAdapter(detailTranslator), [detailTranslator])\n const addressTypesAdapter = React.useMemo(() => createStaffAddressTypesAdapter(detailTranslator), [detailTranslator])\n\n const activityTypeLabels = React.useMemo<DictionarySelectLabels>(() => ({\n placeholder: t('staff.teamMembers.detail.activities.dictionary.placeholder', 'Select an activity type'),\n addLabel: t('staff.teamMembers.detail.activities.dictionary.add', 'Add type'),\n addPrompt: t('staff.teamMembers.detail.activities.dictionary.prompt', 'Name the type'),\n dialogTitle: t('staff.teamMembers.detail.activities.dictionary.dialogTitle', 'Add activity type'),\n valueLabel: t('staff.teamMembers.detail.activities.dictionary.valueLabel', 'Name'),\n valuePlaceholder: t('staff.teamMembers.detail.activities.dictionary.valuePlaceholder', 'Name'),\n labelLabel: t('staff.teamMembers.detail.activities.dictionary.labelLabel', 'Label'),\n labelPlaceholder: t('staff.teamMembers.detail.activities.dictionary.labelPlaceholder', 'Display name shown in UI'),\n emptyError: t('staff.teamMembers.detail.activities.dictionary.emptyError', 'Please enter a name'),\n cancelLabel: t('staff.teamMembers.detail.activities.dictionary.cancel', 'Cancel'),\n saveLabel: t('staff.teamMembers.detail.activities.dictionary.save', 'Save'),\n saveShortcutHint: t('staff.teamMembers.detail.activities.dictionary.saveShortcut', '\u2318/Ctrl + Enter'),\n errorLoad: t('staff.teamMembers.detail.activities.dictionary.errorLoad', 'Failed to load options'),\n errorSave: t('staff.teamMembers.detail.activities.dictionary.errorSave', 'Failed to save option'),\n loadingLabel: t('staff.teamMembers.detail.activities.dictionary.loading', 'Loading\u2026'),\n manageTitle: t('staff.teamMembers.detail.activities.dictionary.manage', 'Manage dictionary'),\n }), [t])\n\n const loadActivityOptions = React.useCallback(async () => {\n const { dictionary, entries } = await loadStaffDictionary('activityTypes')\n setActivityDictionaryId(dictionary?.id ?? null)\n setActivityTypeEntries(entries)\n return entries\n }, [])\n\n const createActivityOption = React.useCallback(\n async (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => {\n const entry = await createStaffDictionaryEntry('activityTypes', input)\n if (!entry) {\n throw new Error(t('staff.teamMembers.detail.activities.dictionary.errorSave', 'Failed to save option'))\n }\n return entry\n },\n [t],\n )\n\n React.useEffect(() => {\n loadActivityOptions().catch(() => {})\n }, [loadActivityOptions])\n\n const activityTypeMap = React.useMemo(\n () => new Map(activityTypeEntries.map((entry) => [entry.value, entry])),\n [activityTypeEntries],\n )\n\n const resolveActivityPresentation = React.useCallback(\n (activity: { activityType: string; appearanceIcon?: string | null; appearanceColor?: string | null }) => {\n const entry = activityTypeMap.get(activity.activityType)\n return {\n label: entry?.label ?? activity.activityType,\n icon: entry?.icon ?? activity.appearanceIcon ?? null,\n color: entry?.color ?? activity.appearanceColor ?? null,\n }\n },\n [activityTypeMap],\n )\n\n const manageActivityHref = React.useMemo(() => {\n if (!activityDictionaryId) return '/backend/config/dictionaries'\n return `/backend/config/dictionaries?dictionaryId=${encodeURIComponent(activityDictionaryId)}`\n }, [activityDictionaryId])\n\n const appearanceLabels = React.useMemo(() => ({\n colorLabel: t('staff.teamMembers.detail.activities.appearance.colorLabel', 'Color'),\n colorHelp: t('staff.teamMembers.detail.activities.appearance.colorHelp', 'Pick a highlight color for this entry.'),\n colorClearLabel: t('staff.teamMembers.detail.activities.appearance.colorClear', 'Remove color'),\n iconLabel: t('staff.teamMembers.detail.activities.appearance.iconLabel', 'Icon or emoji'),\n iconPlaceholder: t('staff.teamMembers.detail.activities.appearance.iconPlaceholder', 'Type an emoji or pick one of the suggestions.'),\n iconPickerTriggerLabel: t('staff.teamMembers.detail.activities.appearance.iconBrowse', 'Browse icons and emojis'),\n iconSearchPlaceholder: t('staff.teamMembers.detail.activities.appearance.iconSearchPlaceholder', 'Search icons or emojis\u2026'),\n iconSearchEmptyLabel: t('staff.teamMembers.detail.activities.appearance.iconSearchEmpty', 'No icons match your search.'),\n iconSuggestionsLabel: t('staff.teamMembers.detail.activities.appearance.iconSuggestions', 'Suggestions'),\n iconClearLabel: t('staff.teamMembers.detail.activities.appearance.iconClear', 'Remove icon'),\n previewEmptyLabel: t('staff.teamMembers.detail.activities.appearance.previewEmpty', 'No appearance selected'),\n }), [t])\n\n const renderCustomFields = React.useCallback((activity: { id?: string; customFields?: Array<{ key: string; label?: string | null; value: unknown }> }) => {\n const entries = Array.isArray(activity.customFields) ? activity.customFields : []\n if (!entries.length) return null\n const emptyLabel = t('staff.teamMembers.detail.activities.customFields.empty', 'Not provided')\n return (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {entries.map((entry, index) => {\n const label = entry.label ?? entry.key\n const value = entry.value\n const hasValue = !(value == null || value === '' || (Array.isArray(value) && value.length === 0))\n const content = hasValue\n ? Array.isArray(value)\n ? value.map((item) => String(item)).join(', ')\n : String(value)\n : emptyLabel\n return (\n <div\n key={`activity-${activity.id ?? 'row'}-custom-${index}`}\n className=\"rounded-md border border-border/60 bg-muted/10 px-3 py-2\"\n >\n <div className=\"text-xs font-medium text-muted-foreground\">{label}</div>\n <div className=\"mt-1 text-sm text-foreground\">{content}</div>\n </div>\n )\n })}\n </div>\n )\n }, [t])\n\n React.useEffect(() => {\n if (!memberId) return\n const memberIdValue = memberId\n let cancelled = false\n async function loadMember() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: memberIdValue })\n const payload = await readApiResultOrThrow<TeamMemberResponse>(\n `/api/staff/team-members?${params.toString()}`,\n undefined,\n { errorMessage: t('staff.teamMembers.form.errors.load', 'Failed to load team member.') },\n )\n const record = Array.isArray(payload.items) ? payload.items[0] : null\n if (!record) throw new Error(t('staff.teamMembers.form.errors.notFound', 'Team member not found.'))\n const customFields = extractCustomFieldEntries(record)\n if (!cancelled) {\n const resolvedTeamId = record.teamId ?? record.team_id ?? null\n const normalizedRoleIds = normalizeStringList(resolvePreferredArray(record.roleIds, record.role_ids))\n setInitialValues({\n id: record.id,\n teamId: resolvedTeamId,\n userId: record.userId ?? record.user_id ?? null,\n displayName: record.displayName ?? record.display_name ?? '',\n description: record.description ?? '',\n roleIds: normalizedRoleIds,\n tags: normalizeStringList(record.tags),\n isActive: record.isActive ?? record.is_active ?? true,\n ...customFields,\n })\n setMemberRecord(record)\n setAvailabilityRuleSetId(\n typeof record.availabilityRuleSetId === 'string'\n ? record.availabilityRuleSetId\n : typeof record.availability_rule_set_id === 'string'\n ? record.availability_rule_set_id\n : null,\n )\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : t('staff.teamMembers.form.errors.load', 'Failed to load team member.')\n flash(message, 'error')\n }\n }\n void loadMember()\n return () => { cancelled = true }\n }, [memberId, t])\n\n React.useEffect(() => {\n if (!searchParams) return\n const created = searchParams.get('created') === '1'\n if (created && !flashShownRef.current) {\n flashShownRef.current = true\n flash(t('staff.teamMembers.flash.createdAvailability', 'Saved. You can now set availability.'), 'success')\n const nextParams = new URLSearchParams(searchParams.toString())\n nextParams.delete('created')\n const nextQuery = nextParams.toString()\n const nextPath = memberId\n ? `/backend/staff/team-members/${encodeURIComponent(memberId)}${nextQuery ? `?${nextQuery}` : ''}`\n : `/backend/staff/team-members${nextQuery ? `?${nextQuery}` : ''}`\n router.replace(nextPath)\n }\n }, [memberId, router, searchParams, t])\n\n const handleSubmit = React.useCallback(async (values: TeamMemberFormValues) => {\n if (!memberId) return\n const payload = buildTeamMemberPayload(values, { id: memberId })\n await updateCrud('staff/team-members', payload, {\n errorMessage: t('staff.teamMembers.form.errors.update', 'Failed to update team member.'),\n })\n flash(t('staff.teamMembers.form.flash.updated', 'Team member updated.'), 'success')\n router.push('/backend/staff/team-members')\n }, [memberId, router, t])\n\n const handleDelete = React.useCallback(async () => {\n if (!memberId) return\n await deleteCrud('staff/team-members', memberId, {\n errorMessage: t('staff.teamMembers.form.errors.delete', 'Failed to delete team member.'),\n })\n flash(t('staff.teamMembers.form.flash.deleted', 'Team member deleted.'), 'success')\n router.push('/backend/staff/team-members')\n }, [memberId, router, t])\n\n const handleRulesetChange = React.useCallback(async (nextId: string | null) => {\n if (!memberId) return\n await updateCrud('staff/team-members', { id: memberId, availabilityRuleSetId: nextId }, {\n errorMessage: t('staff.teamMembers.availability.ruleset.updateError', 'Failed to update schedule.'),\n })\n setAvailabilityRuleSetId(nextId)\n flash(t('staff.teamMembers.availability.ruleset.updateSuccess', 'Schedule updated.'), 'success')\n }, [memberId, t])\n\n const panelTabs = React.useMemo(() => ([\n { id: 'details' as const, label: t('staff.teamMembers.detail.tabs.details', 'Details') },\n { id: 'availability' as const, label: t('staff.teamMembers.detail.tabs.availability', 'Availability') },\n { id: 'jobHistory' as const, label: t('staff.teamMembers.detail.tabs.jobHistory', 'Job history') },\n ]), [t])\n\n const tabs = React.useMemo(() => ([\n { id: 'notes' as const, label: t('staff.teamMembers.detail.tabs.notes', 'Notes') },\n { id: 'activities' as const, label: t('staff.teamMembers.detail.tabs.activities', 'Activities') },\n { id: 'addresses' as const, label: t('staff.teamMembers.detail.tabs.addresses', 'Addresses') },\n ]), [t])\n\n const resolvedInitialValues = initialValues ?? {\n roleIds: [],\n isActive: true,\n }\n\n const displayName = memberRecord?.displayName ?? memberRecord?.display_name ?? resolvedInitialValues.displayName ?? ''\n const teamLabel = memberRecord?.team?.name ?? t('staff.teamMembers.detail.team.unassigned', 'Unassigned team')\n const roleLabels = Array.isArray(memberRecord?.roleNames) && memberRecord?.roleNames.length\n ? memberRecord?.roleNames\n : [t('staff.teamMembers.detail.roles.unassigned', 'No roles assigned')]\n const userEmail = memberRecord?.user?.email ?? null\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n <Link\n href=\"/backend/staff/team-members\"\n className=\"inline-flex items-center text-sm text-muted-foreground hover:text-foreground\"\n >\n <span aria-hidden className=\"mr-1 text-base\">\u2190</span>\n <span className=\"sr-only\">{t('staff.teamMembers.detail.back', 'Back to team members')}</span>\n </Link>\n <div className=\"space-y-1\">\n <h1 className=\"text-2xl font-semibold text-foreground\">\n {displayName || t('staff.teamMembers.detail.untitled', 'Unnamed team member')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n {t('staff.teamMembers.detail.subtitle', 'Team member profile and activity')}\n </p>\n </div>\n </div>\n <TranslationDrawerAction\n config={memberId ? {\n entityType: 'staff:staff_team_member',\n recordId: memberId,\n baseValues: memberRecord ?? undefined,\n } : null}\n />\n </div>\n\n <div className=\"border-b\">\n <nav\n className=\"flex flex-wrap items-center gap-5 text-sm\"\n aria-label={t('staff.teamMembers.detail.tabs.label', 'Team member sections')}\n >\n {panelTabs.map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={activePanel === tab.id}\n onClick={() => setActivePanel(tab.id)}\n className={`relative -mb-px border-b-2 px-0 py-2 text-sm font-medium transition-colors ${\n activePanel === 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 {activePanel === 'details' ? (\n <>\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,2fr),minmax(0,1.1fr)]\">\n <div className=\"space-y-6\">\n <div className=\"rounded-lg border bg-card p-4\">\n <h2 className=\"mb-4 text-sm font-semibold uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.highlights', 'Highlights')}\n </h2>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div>\n <p className=\"text-xs font-medium uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.fields.team', 'Team')}\n </p>\n <p className=\"text-base text-foreground\">{teamLabel}</p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.fields.roles', 'Roles')}\n </p>\n <p className=\"text-base text-foreground\">{roleLabels.join(', ')}</p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.fields.user', 'User')}\n </p>\n <p className=\"text-base text-foreground\">\n {userEmail ?? t('staff.teamMembers.detail.fields.userEmpty', 'No user linked')}\n </p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.fields.status', 'Status')}\n </p>\n <p className=\"text-base text-foreground\">\n {memberRecord?.isActive ?? memberRecord?.is_active\n ? t('staff.teamMembers.detail.status.active', 'Active')\n : t('staff.teamMembers.detail.status.inactive', 'Inactive')}\n </p>\n </div>\n </div>\n </div>\n\n <div className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex gap-2\">\n {tabs.map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => setActiveTab(tab.id)}\n className={`relative -mb-px border-b-2 px-0 py-1 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 </div>\n {sectionAction ? (\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={sectionAction.disabled}\n onClick={() => sectionAction.onClick()}\n >\n {sectionAction.icon ?? (activeTab === 'addresses' ? <Plus className=\"mr-2 h-4 w-4\" /> : null)}\n {sectionAction.label}\n </Button>\n ) : null}\n </div>\n {activeTab === 'notes' ? (\n <NotesSection\n entityId={memberId ?? null}\n emptyLabel={t('staff.teamMembers.detail.notes.empty', 'No notes yet.')}\n viewerUserId={null}\n viewerName={null}\n viewerEmail={null}\n addActionLabel={t('staff.teamMembers.detail.notes.add', 'Add note')}\n emptyState={{\n title: t('staff.teamMembers.detail.notes.emptyTitle', 'Keep everyone in the loop'),\n actionLabel: t('staff.teamMembers.detail.notes.emptyAction', 'Add a note'),\n }}\n onActionChange={setSectionAction}\n translator={detailTranslator}\n labelPrefix=\"staff.teamMembers.detail.notes\"\n inlineLabelPrefix=\"staff.teamMembers.detail.inline\"\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n />\n ) : null}\n {activeTab === 'activities' ? (\n <ActivitiesSection\n entityId={memberId ?? null}\n addActionLabel={t('staff.teamMembers.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('staff.teamMembers.detail.activities.emptyTitle', 'No activities yet'),\n actionLabel: t('staff.teamMembers.detail.activities.emptyAction', 'Add an activity'),\n }}\n onActionChange={setSectionAction}\n dataAdapter={activitiesAdapter}\n activityTypeLabels={activityTypeLabels}\n loadActivityOptions={loadActivityOptions}\n createActivityOption={createActivityOption}\n resolveActivityPresentation={resolveActivityPresentation}\n renderCustomFields={renderCustomFields}\n labelPrefix=\"staff.teamMembers.detail.activities\"\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n appearanceLabels={appearanceLabels}\n manageHref={manageActivityHref}\n customFieldEntityIds={['staff:staff_team_member_activity']}\n />\n ) : null}\n {activeTab === 'addresses' ? (\n <SharedAddressesSection\n entityId={memberId ?? null}\n emptyLabel={t('staff.teamMembers.detail.addresses.empty', 'No addresses yet.')}\n addActionLabel={t('staff.teamMembers.detail.addresses.add', 'Add address')}\n emptyState={{\n title: t('staff.teamMembers.detail.addresses.emptyTitle', 'No addresses yet'),\n actionLabel: t('staff.teamMembers.detail.addresses.emptyAction', 'Add an address'),\n }}\n onActionChange={setSectionAction}\n dataAdapter={addressesAdapter}\n addressTypesAdapter={addressTypesAdapter}\n labelPrefix=\"staff.teamMembers.detail.addresses\"\n />\n ) : null}\n </div>\n </div>\n <div className=\"space-y-4\">\n <div className=\"rounded-lg border bg-card p-4\">\n <h2 className=\"mb-4 text-sm font-semibold uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.details', 'Member details')}\n </h2>\n <div className=\"space-y-2\">\n {memberRecord?.description ? (\n <MarkdownContent body={memberRecord.description} format=\"markdown\" className={MARKDOWN_CLASSNAME} />\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n {t('staff.teamMembers.detail.descriptionEmpty', 'No description provided.')}\n </p>\n )}\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"rounded-lg border bg-card p-4\">\n <h2 className=\"mb-4 text-sm font-semibold uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.formTitle', 'Member settings')}\n </h2>\n <TeamMemberForm\n embedded\n title={t('staff.teamMembers.form.editTitle', 'Edit team member')}\n backHref=\"/backend/staff/team-members\"\n cancelHref=\"/backend/staff/team-members\"\n initialValues={resolvedInitialValues}\n onSubmit={handleSubmit}\n onDelete={handleDelete}\n isLoading={!initialValues}\n loadingMessage={t('staff.teamMembers.form.loading', 'Loading team member...')}\n />\n </div>\n </>\n ) : activePanel === 'availability' ? (\n <AvailabilityRulesEditor\n subjectType=\"member\"\n subjectId={memberId ?? ''}\n labelPrefix=\"staff.teamMembers\"\n mode=\"availability\"\n rulesetId={availabilityRuleSetId}\n onRulesetChange={handleRulesetChange}\n buildScheduleItems={({ availabilityRules, translate: translateLabel }) => (\n buildMemberScheduleItems({ availabilityRules, translate: translateLabel })\n )}\n />\n ) : (\n <div className=\"rounded-lg border bg-card p-4\">\n <JobHistorySection memberId={memberId ?? null} />\n </div>\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n\nfunction normalizeStringList(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return value\n .map((entry) => (typeof entry === 'string' ? entry.trim() : ''))\n .filter((entry) => entry.length > 0)\n}\n\nfunction resolvePreferredArray<T>(primary?: T[] | null, fallback?: T[] | null): T[] | undefined {\n if (Array.isArray(primary) && primary.length) return primary\n if (Array.isArray(fallback) && fallback.length) return fallback\n return Array.isArray(primary) ? primary : Array.isArray(fallback) ? fallback : undefined\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 { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'\nimport { AvailabilityRulesEditor } from '@open-mercato/core/modules/planner/components/AvailabilityRulesEditor'\nimport { buildMemberScheduleItems } from '@open-mercato/core/modules/staff/lib/memberSchedule'\nimport { TeamMemberForm, buildTeamMemberPayload, type TeamMemberFormValues } from '@open-mercato/core/modules/staff/components/TeamMemberForm'\nimport { NotesSection } from '@open-mercato/ui/backend/detail'\nimport { ActivitiesSection, type SectionAction } from '@open-mercato/ui/backend/detail'\nimport { AddressesSection as SharedAddressesSection } from '@open-mercato/ui/backend/detail'\nimport { renderDictionaryColor, renderDictionaryIcon, ICON_SUGGESTIONS } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { createStaffNotesAdapter } from '@open-mercato/core/modules/staff/components/detail/notesAdapter'\nimport { createStaffActivitiesAdapter } from '@open-mercato/core/modules/staff/components/detail/activitiesAdapter'\nimport { createStaffAddressAdapter, createStaffAddressTypesAdapter } from '@open-mercato/core/modules/staff/components/detail/addressesAdapter'\nimport { MarkdownContent } from '@open-mercato/ui/backend/markdown/MarkdownContent'\nimport {\n createStaffDictionaryEntry,\n loadStaffDictionary,\n type DictionaryEntryOption,\n} from '@open-mercato/core/modules/staff/components/detail/dictionaries'\nimport { JobHistorySection } from '@open-mercato/core/modules/staff/components/detail/JobHistorySection'\nimport type { DictionarySelectLabels } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'\nimport { Plus } from 'lucide-react'\nimport { TranslationDrawerAction } from '@open-mercato/core/modules/translations/components/TranslationDrawerAction'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\n\nconst MARKDOWN_CLASSNAME =\n 'text-sm text-muted-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 TeamMemberRecord = {\n id: string\n teamId?: string | null\n team_id?: string | null\n displayName: string\n display_name?: string\n description?: string | null\n userId?: string | null\n user_id?: string | null\n roleIds?: string[]\n role_ids?: string[]\n roleNames?: string[]\n tags?: string[]\n isActive?: boolean\n is_active?: boolean\n availabilityRuleSetId?: string | null\n availability_rule_set_id?: string | null\n user?: { id?: string; email?: string | null } | null\n team?: { id?: string; name?: string | null } | null\n customFields?: Record<string, unknown> | null\n} & Record<string, unknown>\n\ntype TeamMemberResponse = {\n items?: TeamMemberRecord[]\n}\n\nexport default function StaffTeamMemberDetailPage({ params }: { params?: { id?: string } }) {\n const memberId = params?.id\n const t = useT()\n const detailTranslator = React.useMemo(() => createTranslatorWithFallback(t), [t])\n const router = useRouter()\n const searchParams = useSearchParams()\n const [initialValues, setInitialValues] = React.useState<TeamMemberFormValues | null>(null)\n const [memberRecord, setMemberRecord] = React.useState<TeamMemberRecord | null>(null)\n const [availabilityRuleSetId, setAvailabilityRuleSetId] = React.useState<string | null>(null)\n const [activePanel, setActivePanel] = React.useState<'details' | 'availability' | 'jobHistory'>('details')\n const [activeTab, setActiveTab] = React.useState<'notes' | 'activities' | 'addresses'>('notes')\n const [sectionAction, setSectionAction] = React.useState<SectionAction | null>(null)\n const [activityDictionaryId, setActivityDictionaryId] = React.useState<string | null>(null)\n const [activityTypeEntries, setActivityTypeEntries] = React.useState<DictionaryEntryOption[]>([])\n const flashShownRef = React.useRef(false)\n\n const notesAdapter = React.useMemo(() => createStaffNotesAdapter(detailTranslator), [detailTranslator])\n const activitiesAdapter = React.useMemo(() => createStaffActivitiesAdapter(detailTranslator), [detailTranslator])\n const addressesAdapter = React.useMemo(() => createStaffAddressAdapter(detailTranslator), [detailTranslator])\n const addressTypesAdapter = React.useMemo(() => createStaffAddressTypesAdapter(detailTranslator), [detailTranslator])\n\n const activityTypeLabels = React.useMemo<DictionarySelectLabels>(() => ({\n placeholder: t('staff.teamMembers.detail.activities.dictionary.placeholder', 'Select an activity type'),\n addLabel: t('staff.teamMembers.detail.activities.dictionary.add', 'Add type'),\n addPrompt: t('staff.teamMembers.detail.activities.dictionary.prompt', 'Name the type'),\n dialogTitle: t('staff.teamMembers.detail.activities.dictionary.dialogTitle', 'Add activity type'),\n valueLabel: t('staff.teamMembers.detail.activities.dictionary.valueLabel', 'Name'),\n valuePlaceholder: t('staff.teamMembers.detail.activities.dictionary.valuePlaceholder', 'Name'),\n labelLabel: t('staff.teamMembers.detail.activities.dictionary.labelLabel', 'Label'),\n labelPlaceholder: t('staff.teamMembers.detail.activities.dictionary.labelPlaceholder', 'Display name shown in UI'),\n emptyError: t('staff.teamMembers.detail.activities.dictionary.emptyError', 'Please enter a name'),\n cancelLabel: t('staff.teamMembers.detail.activities.dictionary.cancel', 'Cancel'),\n saveLabel: t('staff.teamMembers.detail.activities.dictionary.save', 'Save'),\n saveShortcutHint: t('staff.teamMembers.detail.activities.dictionary.saveShortcut', '\u2318/Ctrl + Enter'),\n errorLoad: t('staff.teamMembers.detail.activities.dictionary.errorLoad', 'Failed to load options'),\n errorSave: t('staff.teamMembers.detail.activities.dictionary.errorSave', 'Failed to save option'),\n loadingLabel: t('staff.teamMembers.detail.activities.dictionary.loading', 'Loading\u2026'),\n manageTitle: t('staff.teamMembers.detail.activities.dictionary.manage', 'Manage dictionary'),\n }), [t])\n\n const loadActivityOptions = React.useCallback(async () => {\n const { dictionary, entries } = await loadStaffDictionary('activityTypes')\n setActivityDictionaryId(dictionary?.id ?? null)\n setActivityTypeEntries(entries)\n return entries\n }, [])\n\n const createActivityOption = React.useCallback(\n async (input: { value: string; label?: string; color?: string | null; icon?: string | null }) => {\n const entry = await createStaffDictionaryEntry('activityTypes', input)\n if (!entry) {\n throw new Error(t('staff.teamMembers.detail.activities.dictionary.errorSave', 'Failed to save option'))\n }\n return entry\n },\n [t],\n )\n\n React.useEffect(() => {\n loadActivityOptions().catch(() => {})\n }, [loadActivityOptions])\n\n const activityTypeMap = React.useMemo(\n () => new Map(activityTypeEntries.map((entry) => [entry.value, entry])),\n [activityTypeEntries],\n )\n\n const resolveActivityPresentation = React.useCallback(\n (activity: { activityType: string; appearanceIcon?: string | null; appearanceColor?: string | null }) => {\n const entry = activityTypeMap.get(activity.activityType)\n return {\n label: entry?.label ?? activity.activityType,\n icon: entry?.icon ?? activity.appearanceIcon ?? null,\n color: entry?.color ?? activity.appearanceColor ?? null,\n }\n },\n [activityTypeMap],\n )\n\n const manageActivityHref = React.useMemo(() => {\n if (!activityDictionaryId) return '/backend/config/dictionaries'\n return `/backend/config/dictionaries?dictionaryId=${encodeURIComponent(activityDictionaryId)}`\n }, [activityDictionaryId])\n\n const appearanceLabels = React.useMemo(() => ({\n colorLabel: t('staff.teamMembers.detail.activities.appearance.colorLabel', 'Color'),\n colorHelp: t('staff.teamMembers.detail.activities.appearance.colorHelp', 'Pick a highlight color for this entry.'),\n colorClearLabel: t('staff.teamMembers.detail.activities.appearance.colorClear', 'Remove color'),\n iconLabel: t('staff.teamMembers.detail.activities.appearance.iconLabel', 'Icon or emoji'),\n iconPlaceholder: t('staff.teamMembers.detail.activities.appearance.iconPlaceholder', 'Type an emoji or pick one of the suggestions.'),\n iconPickerTriggerLabel: t('staff.teamMembers.detail.activities.appearance.iconBrowse', 'Browse icons and emojis'),\n iconSearchPlaceholder: t('staff.teamMembers.detail.activities.appearance.iconSearchPlaceholder', 'Search icons or emojis\u2026'),\n iconSearchEmptyLabel: t('staff.teamMembers.detail.activities.appearance.iconSearchEmpty', 'No icons match your search.'),\n iconSuggestionsLabel: t('staff.teamMembers.detail.activities.appearance.iconSuggestions', 'Suggestions'),\n iconClearLabel: t('staff.teamMembers.detail.activities.appearance.iconClear', 'Remove icon'),\n previewEmptyLabel: t('staff.teamMembers.detail.activities.appearance.previewEmpty', 'No appearance selected'),\n }), [t])\n\n const renderCustomFields = React.useCallback((activity: { id?: string; customFields?: Array<{ key: string; label?: string | null; value: unknown }> }) => {\n const entries = Array.isArray(activity.customFields) ? activity.customFields : []\n if (!entries.length) return null\n const emptyLabel = t('staff.teamMembers.detail.activities.customFields.empty', 'Not provided')\n return (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {entries.map((entry, index) => {\n const label = entry.label ?? entry.key\n const value = entry.value\n const hasValue = !(value == null || value === '' || (Array.isArray(value) && value.length === 0))\n const content = hasValue\n ? Array.isArray(value)\n ? value.map((item) => String(item)).join(', ')\n : String(value)\n : emptyLabel\n return (\n <div\n key={`activity-${activity.id ?? 'row'}-custom-${index}`}\n className=\"rounded-md border border-border/60 bg-muted/10 px-3 py-2\"\n >\n <div className=\"text-xs font-medium text-muted-foreground\">{label}</div>\n <div className=\"mt-1 text-sm text-foreground\">{content}</div>\n </div>\n )\n })}\n </div>\n )\n }, [t])\n\n React.useEffect(() => {\n if (!memberId) return\n const memberIdValue = memberId\n let cancelled = false\n async function loadMember() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: memberIdValue })\n const payload = await readApiResultOrThrow<TeamMemberResponse>(\n `/api/staff/team-members?${params.toString()}`,\n undefined,\n { errorMessage: t('staff.teamMembers.form.errors.load', 'Failed to load team member.') },\n )\n const record = Array.isArray(payload.items) ? payload.items[0] : null\n if (!record) throw new Error(t('staff.teamMembers.form.errors.notFound', 'Team member not found.'))\n const customFields = extractCustomFieldEntries(record)\n if (!cancelled) {\n const resolvedTeamId = record.teamId ?? record.team_id ?? null\n const normalizedRoleIds = normalizeStringList(resolvePreferredArray(record.roleIds, record.role_ids))\n setInitialValues({\n id: record.id,\n teamId: resolvedTeamId,\n userId: record.userId ?? record.user_id ?? null,\n displayName: record.displayName ?? record.display_name ?? '',\n description: record.description ?? '',\n roleIds: normalizedRoleIds,\n tags: normalizeStringList(record.tags),\n isActive: record.isActive ?? record.is_active ?? true,\n ...customFields,\n })\n setMemberRecord(record)\n setAvailabilityRuleSetId(\n typeof record.availabilityRuleSetId === 'string'\n ? record.availabilityRuleSetId\n : typeof record.availability_rule_set_id === 'string'\n ? record.availability_rule_set_id\n : null,\n )\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : t('staff.teamMembers.form.errors.load', 'Failed to load team member.')\n flash(message, 'error')\n }\n }\n void loadMember()\n return () => { cancelled = true }\n }, [memberId, t])\n\n React.useEffect(() => {\n if (!searchParams) return\n const created = searchParams.get('created') === '1'\n if (created && !flashShownRef.current) {\n flashShownRef.current = true\n flash(t('staff.teamMembers.flash.createdAvailability', 'Saved. You can now set availability.'), 'success')\n const nextParams = new URLSearchParams(searchParams.toString())\n nextParams.delete('created')\n const nextQuery = nextParams.toString()\n const nextPath = memberId\n ? `/backend/staff/team-members/${encodeURIComponent(memberId)}${nextQuery ? `?${nextQuery}` : ''}`\n : `/backend/staff/team-members${nextQuery ? `?${nextQuery}` : ''}`\n router.replace(nextPath)\n }\n }, [memberId, router, searchParams, t])\n\n const handleSubmit = React.useCallback(async (values: TeamMemberFormValues) => {\n if (!memberId) return\n const payload = buildTeamMemberPayload(values, { id: memberId })\n await updateCrud('staff/team-members', payload, {\n errorMessage: t('staff.teamMembers.form.errors.update', 'Failed to update team member.'),\n })\n flash(t('staff.teamMembers.form.flash.updated', 'Team member updated.'), 'success')\n router.push('/backend/staff/team-members')\n }, [memberId, router, t])\n\n const handleDelete = React.useCallback(async () => {\n if (!memberId) return\n await deleteCrud('staff/team-members', memberId, {\n errorMessage: t('staff.teamMembers.form.errors.delete', 'Failed to delete team member.'),\n })\n flash(t('staff.teamMembers.form.flash.deleted', 'Team member deleted.'), 'success')\n router.push('/backend/staff/team-members')\n }, [memberId, router, t])\n\n const handleRulesetChange = React.useCallback(async (nextId: string | null) => {\n if (!memberId) return\n await updateCrud('staff/team-members', { id: memberId, availabilityRuleSetId: nextId }, {\n errorMessage: t('staff.teamMembers.availability.ruleset.updateError', 'Failed to update schedule.'),\n })\n setAvailabilityRuleSetId(nextId)\n flash(t('staff.teamMembers.availability.ruleset.updateSuccess', 'Schedule updated.'), 'success')\n }, [memberId, t])\n\n const panelTabs = React.useMemo(() => ([\n { id: 'details' as const, label: t('staff.teamMembers.detail.tabs.details', 'Details') },\n { id: 'availability' as const, label: t('staff.teamMembers.detail.tabs.availability', 'Availability') },\n { id: 'jobHistory' as const, label: t('staff.teamMembers.detail.tabs.jobHistory', 'Job history') },\n ]), [t])\n\n const tabs = React.useMemo(() => ([\n { id: 'notes' as const, label: t('staff.teamMembers.detail.tabs.notes', 'Notes') },\n { id: 'activities' as const, label: t('staff.teamMembers.detail.tabs.activities', 'Activities') },\n { id: 'addresses' as const, label: t('staff.teamMembers.detail.tabs.addresses', 'Addresses') },\n ]), [t])\n\n const resolvedInitialValues = initialValues ?? {\n roleIds: [],\n isActive: true,\n }\n\n const displayName = memberRecord?.displayName ?? memberRecord?.display_name ?? resolvedInitialValues.displayName ?? ''\n const teamLabel = memberRecord?.team?.name ?? t('staff.teamMembers.detail.team.unassigned', 'Unassigned team')\n const roleLabels = Array.isArray(memberRecord?.roleNames) && memberRecord?.roleNames.length\n ? memberRecord?.roleNames\n : [t('staff.teamMembers.detail.roles.unassigned', 'No roles assigned')]\n const userEmail = memberRecord?.user?.email ?? null\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n <Link\n href=\"/backend/staff/team-members\"\n className=\"inline-flex items-center text-sm text-muted-foreground hover:text-foreground\"\n >\n <span aria-hidden className=\"mr-1 text-base\">\u2190</span>\n <span className=\"sr-only\">{t('staff.teamMembers.detail.back', 'Back to team members')}</span>\n </Link>\n <div className=\"space-y-1\">\n <h1 className=\"text-2xl font-semibold text-foreground\">\n {displayName || t('staff.teamMembers.detail.untitled', 'Unnamed team member')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n {t('staff.teamMembers.detail.subtitle', 'Team member profile and activity')}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {memberId ? (\n <SendObjectMessageDialog\n object={{\n entityModule: 'staff',\n entityType: 'team_member',\n entityId: memberId,\n previewData: {\n title: displayName,\n metadata: {\n [t('staff.teamMembers.detail.fields.team')]: teamLabel,\n [t('staff.teamMembers.detail.fields.user')]: userEmail ?? t('staff.teamMembers.detail.fields.userEmpty', 'No user linked'),\n [t('staff.teamMembers.detail.fields.roles')]: roleLabels.join(', '),\n },\n },\n }}\n viewHref={`/backend/staff/team-members/${memberId}`}\n />\n ) : null}\n <TranslationDrawerAction\n config={memberId ? {\n entityType: 'staff:staff_team_member',\n recordId: memberId,\n baseValues: memberRecord ?? undefined,\n } : null}\n />\n </div>\n </div>\n\n <div className=\"border-b\">\n <nav\n className=\"flex flex-wrap items-center gap-5 text-sm\"\n aria-label={t('staff.teamMembers.detail.tabs.label', 'Team member sections')}\n >\n {panelTabs.map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={activePanel === tab.id}\n onClick={() => setActivePanel(tab.id)}\n className={`relative -mb-px border-b-2 px-0 py-2 text-sm font-medium transition-colors ${\n activePanel === 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 {activePanel === 'details' ? (\n <>\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,2fr),minmax(0,1.1fr)]\">\n <div className=\"space-y-6\">\n <div className=\"rounded-lg border bg-card p-4\">\n <h2 className=\"mb-4 text-sm font-semibold uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.highlights', 'Highlights')}\n </h2>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div>\n <p className=\"text-xs font-medium uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.fields.team', 'Team')}\n </p>\n <p className=\"text-base text-foreground\">{teamLabel}</p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.fields.roles', 'Roles')}\n </p>\n <p className=\"text-base text-foreground\">{roleLabels.join(', ')}</p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.fields.user', 'User')}\n </p>\n <p className=\"text-base text-foreground\">\n {userEmail ?? t('staff.teamMembers.detail.fields.userEmpty', 'No user linked')}\n </p>\n </div>\n <div>\n <p className=\"text-xs font-medium uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.fields.status', 'Status')}\n </p>\n <p className=\"text-base text-foreground\">\n {memberRecord?.isActive ?? memberRecord?.is_active\n ? t('staff.teamMembers.detail.status.active', 'Active')\n : t('staff.teamMembers.detail.status.inactive', 'Inactive')}\n </p>\n </div>\n </div>\n </div>\n\n <div className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex flex-wrap items-center justify-between gap-3\">\n <div className=\"flex gap-2\">\n {tabs.map((tab) => (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => setActiveTab(tab.id)}\n className={`relative -mb-px border-b-2 px-0 py-1 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 </div>\n {sectionAction ? (\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={sectionAction.disabled}\n onClick={() => sectionAction.onClick()}\n >\n {sectionAction.icon ?? (activeTab === 'addresses' ? <Plus className=\"mr-2 h-4 w-4\" /> : null)}\n {sectionAction.label}\n </Button>\n ) : null}\n </div>\n {activeTab === 'notes' ? (\n <NotesSection\n entityId={memberId ?? null}\n emptyLabel={t('staff.teamMembers.detail.notes.empty', 'No notes yet.')}\n viewerUserId={null}\n viewerName={null}\n viewerEmail={null}\n addActionLabel={t('staff.teamMembers.detail.notes.add', 'Add note')}\n emptyState={{\n title: t('staff.teamMembers.detail.notes.emptyTitle', 'Keep everyone in the loop'),\n actionLabel: t('staff.teamMembers.detail.notes.emptyAction', 'Add a note'),\n }}\n onActionChange={setSectionAction}\n translator={detailTranslator}\n labelPrefix=\"staff.teamMembers.detail.notes\"\n inlineLabelPrefix=\"staff.teamMembers.detail.inline\"\n dataAdapter={notesAdapter}\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n iconSuggestions={ICON_SUGGESTIONS}\n />\n ) : null}\n {activeTab === 'activities' ? (\n <ActivitiesSection\n entityId={memberId ?? null}\n addActionLabel={t('staff.teamMembers.detail.activities.add', 'Log activity')}\n emptyState={{\n title: t('staff.teamMembers.detail.activities.emptyTitle', 'No activities yet'),\n actionLabel: t('staff.teamMembers.detail.activities.emptyAction', 'Add an activity'),\n }}\n onActionChange={setSectionAction}\n dataAdapter={activitiesAdapter}\n activityTypeLabels={activityTypeLabels}\n loadActivityOptions={loadActivityOptions}\n createActivityOption={createActivityOption}\n resolveActivityPresentation={resolveActivityPresentation}\n renderCustomFields={renderCustomFields}\n labelPrefix=\"staff.teamMembers.detail.activities\"\n renderIcon={renderDictionaryIcon}\n renderColor={renderDictionaryColor}\n appearanceLabels={appearanceLabels}\n manageHref={manageActivityHref}\n customFieldEntityIds={['staff:staff_team_member_activity']}\n />\n ) : null}\n {activeTab === 'addresses' ? (\n <SharedAddressesSection\n entityId={memberId ?? null}\n emptyLabel={t('staff.teamMembers.detail.addresses.empty', 'No addresses yet.')}\n addActionLabel={t('staff.teamMembers.detail.addresses.add', 'Add address')}\n emptyState={{\n title: t('staff.teamMembers.detail.addresses.emptyTitle', 'No addresses yet'),\n actionLabel: t('staff.teamMembers.detail.addresses.emptyAction', 'Add an address'),\n }}\n onActionChange={setSectionAction}\n dataAdapter={addressesAdapter}\n addressTypesAdapter={addressTypesAdapter}\n labelPrefix=\"staff.teamMembers.detail.addresses\"\n />\n ) : null}\n </div>\n </div>\n <div className=\"space-y-4\">\n <div className=\"rounded-lg border bg-card p-4\">\n <h2 className=\"mb-4 text-sm font-semibold uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.details', 'Member details')}\n </h2>\n <div className=\"space-y-2\">\n {memberRecord?.description ? (\n <MarkdownContent body={memberRecord.description} format=\"markdown\" className={MARKDOWN_CLASSNAME} />\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n {t('staff.teamMembers.detail.descriptionEmpty', 'No description provided.')}\n </p>\n )}\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"rounded-lg border bg-card p-4\">\n <h2 className=\"mb-4 text-sm font-semibold uppercase text-muted-foreground\">\n {t('staff.teamMembers.detail.formTitle', 'Member settings')}\n </h2>\n <TeamMemberForm\n embedded\n title={t('staff.teamMembers.form.editTitle', 'Edit team member')}\n backHref=\"/backend/staff/team-members\"\n cancelHref=\"/backend/staff/team-members\"\n initialValues={resolvedInitialValues}\n onSubmit={handleSubmit}\n onDelete={handleDelete}\n isLoading={!initialValues}\n loadingMessage={t('staff.teamMembers.form.loading', 'Loading team member...')}\n />\n </div>\n </>\n ) : activePanel === 'availability' ? (\n <AvailabilityRulesEditor\n subjectType=\"member\"\n subjectId={memberId ?? ''}\n labelPrefix=\"staff.teamMembers\"\n mode=\"availability\"\n rulesetId={availabilityRuleSetId}\n onRulesetChange={handleRulesetChange}\n buildScheduleItems={({ availabilityRules, translate: translateLabel }) => (\n buildMemberScheduleItems({ availabilityRules, translate: translateLabel })\n )}\n />\n ) : (\n <div className=\"rounded-lg border bg-card p-4\">\n <JobHistorySection memberId={memberId ?? null} />\n </div>\n )}\n </div>\n </PageBody>\n </Page>\n )\n}\n\nfunction normalizeStringList(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n return value\n .map((entry) => (typeof entry === 'string' ? entry.trim() : ''))\n .filter((entry) => entry.length > 0)\n}\n\nfunction resolvePreferredArray<T>(primary?: T[] | null, fallback?: T[] | null): T[] | undefined {\n if (Array.isArray(primary) && primary.length) return primary\n if (Array.isArray(fallback) && fallback.length) return fallback\n return Array.isArray(primary) ? primary : Array.isArray(fallback) ? fallback : undefined\n}\n"],
|
|
5
|
+
"mappings": ";AAkLY,SA4MA,UAxME,KAJF;AAhLZ,YAAY,WAAW;AACvB,OAAO,UAAU;AACjB,SAAS,WAAW,uBAAuB;AAC3C,SAAS,MAAM,gBAAgB;AAC/B,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC,SAAS,iCAAiC;AAC1C,SAAS,YAAY,kBAAkB;AACvC,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,oCAAoC;AAC7C,SAAS,+BAA+B;AACxC,SAAS,gCAAgC;AACzC,SAAS,gBAAgB,8BAAyD;AAClF,SAAS,oBAAoB;AAC7B,SAAS,yBAA6C;AACtD,SAAS,oBAAoB,8BAA8B;AAC3D,SAAS,uBAAuB,sBAAsB,wBAAwB;AAC9E,SAAS,+BAA+B;AACxC,SAAS,oCAAoC;AAC7C,SAAS,2BAA2B,sCAAsC;AAC1E,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,yBAAyB;AAElC,SAAS,YAAY;AACrB,SAAS,+BAA+B;AACxC,SAAS,+BAA+B;AAExC,MAAM,qBACJ;AA4Ba,SAAR,0BAA2C,EAAE,OAAO,GAAiC;AAC1F,QAAM,WAAW,QAAQ;AACzB,QAAM,IAAI,KAAK;AACf,QAAM,mBAAmB,MAAM,QAAQ,MAAM,6BAA6B,CAAC,GAAG,CAAC,CAAC,CAAC;AACjF,QAAM,SAAS,UAAU;AACzB,QAAM,eAAe,gBAAgB;AACrC,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAsC,IAAI;AAC1F,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAkC,IAAI;AACpF,QAAM,CAAC,uBAAuB,wBAAwB,IAAI,MAAM,SAAwB,IAAI;AAC5F,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAoD,SAAS;AACzG,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAA+C,OAAO;AAC9F,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAA+B,IAAI;AACnF,QAAM,CAAC,sBAAsB,uBAAuB,IAAI,MAAM,SAAwB,IAAI;AAC1F,QAAM,CAAC,qBAAqB,sBAAsB,IAAI,MAAM,SAAkC,CAAC,CAAC;AAChG,QAAM,gBAAgB,MAAM,OAAO,KAAK;AAExC,QAAM,eAAe,MAAM,QAAQ,MAAM,wBAAwB,gBAAgB,GAAG,CAAC,gBAAgB,CAAC;AACtG,QAAM,oBAAoB,MAAM,QAAQ,MAAM,6BAA6B,gBAAgB,GAAG,CAAC,gBAAgB,CAAC;AAChH,QAAM,mBAAmB,MAAM,QAAQ,MAAM,0BAA0B,gBAAgB,GAAG,CAAC,gBAAgB,CAAC;AAC5G,QAAM,sBAAsB,MAAM,QAAQ,MAAM,+BAA+B,gBAAgB,GAAG,CAAC,gBAAgB,CAAC;AAEpH,QAAM,qBAAqB,MAAM,QAAgC,OAAO;AAAA,IACtE,aAAa,EAAE,8DAA8D,yBAAyB;AAAA,IACtG,UAAU,EAAE,sDAAsD,UAAU;AAAA,IAC5E,WAAW,EAAE,yDAAyD,eAAe;AAAA,IACrF,aAAa,EAAE,8DAA8D,mBAAmB;AAAA,IAChG,YAAY,EAAE,6DAA6D,MAAM;AAAA,IACjF,kBAAkB,EAAE,mEAAmE,MAAM;AAAA,IAC7F,YAAY,EAAE,6DAA6D,OAAO;AAAA,IAClF,kBAAkB,EAAE,mEAAmE,0BAA0B;AAAA,IACjH,YAAY,EAAE,6DAA6D,qBAAqB;AAAA,IAChG,aAAa,EAAE,yDAAyD,QAAQ;AAAA,IAChF,WAAW,EAAE,uDAAuD,MAAM;AAAA,IAC1E,kBAAkB,EAAE,+DAA+D,qBAAgB;AAAA,IACnG,WAAW,EAAE,4DAA4D,wBAAwB;AAAA,IACjG,WAAW,EAAE,4DAA4D,uBAAuB;AAAA,IAChG,cAAc,EAAE,0DAA0D,eAAU;AAAA,IACpF,aAAa,EAAE,yDAAyD,mBAAmB;AAAA,EAC7F,IAAI,CAAC,CAAC,CAAC;AAEP,QAAM,sBAAsB,MAAM,YAAY,YAAY;AACxD,UAAM,EAAE,YAAY,QAAQ,IAAI,MAAM,oBAAoB,eAAe;AACzE,4BAAwB,YAAY,MAAM,IAAI;AAC9C,2BAAuB,OAAO;AAC9B,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,uBAAuB,MAAM;AAAA,IACjC,OAAO,UAA0F;AAC/F,YAAM,QAAQ,MAAM,2BAA2B,iBAAiB,KAAK;AACrE,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,EAAE,4DAA4D,uBAAuB,CAAC;AAAA,MACxG;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,CAAC;AAAA,EACJ;AAEA,QAAM,UAAU,MAAM;AACpB,wBAAoB,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACtC,GAAG,CAAC,mBAAmB,CAAC;AAExB,QAAM,kBAAkB,MAAM;AAAA,IAC5B,MAAM,IAAI,IAAI,oBAAoB,IAAI,CAAC,UAAU,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,IACtE,CAAC,mBAAmB;AAAA,EACtB;AAEA,QAAM,8BAA8B,MAAM;AAAA,IACxC,CAAC,aAAwG;AACvG,YAAM,QAAQ,gBAAgB,IAAI,SAAS,YAAY;AACvD,aAAO;AAAA,QACL,OAAO,OAAO,SAAS,SAAS;AAAA,QAChC,MAAM,OAAO,QAAQ,SAAS,kBAAkB;AAAA,QAChD,OAAO,OAAO,SAAS,SAAS,mBAAmB;AAAA,MACrD;AAAA,IACF;AAAA,IACA,CAAC,eAAe;AAAA,EAClB;AAEA,QAAM,qBAAqB,MAAM,QAAQ,MAAM;AAC7C,QAAI,CAAC,qBAAsB,QAAO;AAClC,WAAO,6CAA6C,mBAAmB,oBAAoB,CAAC;AAAA,EAC9F,GAAG,CAAC,oBAAoB,CAAC;AAEzB,QAAM,mBAAmB,MAAM,QAAQ,OAAO;AAAA,IAC5C,YAAY,EAAE,6DAA6D,OAAO;AAAA,IAClF,WAAW,EAAE,4DAA4D,wCAAwC;AAAA,IACjH,iBAAiB,EAAE,6DAA6D,cAAc;AAAA,IAC9F,WAAW,EAAE,4DAA4D,eAAe;AAAA,IACxF,iBAAiB,EAAE,kEAAkE,+CAA+C;AAAA,IACpI,wBAAwB,EAAE,6DAA6D,yBAAyB;AAAA,IAChH,uBAAuB,EAAE,wEAAwE,8BAAyB;AAAA,IAC1H,sBAAsB,EAAE,kEAAkE,6BAA6B;AAAA,IACvH,sBAAsB,EAAE,kEAAkE,aAAa;AAAA,IACvG,gBAAgB,EAAE,4DAA4D,aAAa;AAAA,IAC3F,mBAAmB,EAAE,+DAA+D,wBAAwB;AAAA,EAC9G,IAAI,CAAC,CAAC,CAAC;AAEP,QAAM,qBAAqB,MAAM,YAAY,CAAC,aAA4G;AACxJ,UAAM,UAAU,MAAM,QAAQ,SAAS,YAAY,IAAI,SAAS,eAAe,CAAC;AAChF,QAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,UAAM,aAAa,EAAE,0DAA0D,cAAc;AAC7F,WACE,oBAAC,SAAI,WAAU,6BACZ,kBAAQ,IAAI,CAAC,OAAO,UAAU;AAC7B,YAAM,QAAQ,MAAM,SAAS,MAAM;AACnC,YAAM,QAAQ,MAAM;AACpB,YAAM,WAAW,EAAE,SAAS,QAAQ,UAAU,MAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,WAAW;AAC9F,YAAM,UAAU,WACZ,MAAM,QAAQ,KAAK,IACjB,MAAM,IAAI,CAAC,SAAS,OAAO,IAAI,CAAC,EAAE,KAAK,IAAI,IAC3C,OAAO,KAAK,IACd;AACJ,aACE;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAEV;AAAA,gCAAC,SAAI,WAAU,6CAA6C,iBAAM;AAAA,YAClE,oBAAC,SAAI,WAAU,gCAAgC,mBAAQ;AAAA;AAAA;AAAA,QAJlD,YAAY,SAAS,MAAM,KAAK,WAAW,KAAK;AAAA,MAKvD;AAAA,IAEJ,CAAC,GACH;AAAA,EAEJ,GAAG,CAAC,CAAC,CAAC;AAEN,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,SAAU;AACf,UAAM,gBAAgB;AACtB,QAAI,YAAY;AAChB,mBAAe,aAAa;AAC1B,UAAI;AACF,cAAMA,UAAS,IAAI,gBAAgB,EAAE,MAAM,KAAK,UAAU,KAAK,KAAK,cAAc,CAAC;AACnF,cAAM,UAAU,MAAM;AAAA,UACpB,2BAA2BA,QAAO,SAAS,CAAC;AAAA,UAC5C;AAAA,UACA,EAAE,cAAc,EAAE,sCAAsC,6BAA6B,EAAE;AAAA,QACzF;AACA,cAAM,SAAS,MAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,MAAM,CAAC,IAAI;AACjE,YAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,EAAE,0CAA0C,wBAAwB,CAAC;AAClG,cAAM,eAAe,0BAA0B,MAAM;AACrD,YAAI,CAAC,WAAW;AACd,gBAAM,iBAAiB,OAAO,UAAU,OAAO,WAAW;AAC1D,gBAAM,oBAAoB,oBAAoB,sBAAsB,OAAO,SAAS,OAAO,QAAQ,CAAC;AACpG,2BAAiB;AAAA,YACf,IAAI,OAAO;AAAA,YACX,QAAQ;AAAA,YACR,QAAQ,OAAO,UAAU,OAAO,WAAW;AAAA,YAC3C,aAAa,OAAO,eAAe,OAAO,gBAAgB;AAAA,YAC1D,aAAa,OAAO,eAAe;AAAA,YACnC,SAAS;AAAA,YACT,MAAM,oBAAoB,OAAO,IAAI;AAAA,YACrC,UAAU,OAAO,YAAY,OAAO,aAAa;AAAA,YACjD,GAAG;AAAA,UACL,CAAC;AACD,0BAAgB,MAAM;AACtB;AAAA,YACE,OAAO,OAAO,0BAA0B,WACpC,OAAO,wBACP,OAAO,OAAO,6BAA6B,WACzC,OAAO,2BACP;AAAA,UACR;AAAA,QACF;AAAA,MACF,SAAS,OAAO;AACd,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,EAAE,sCAAsC,6BAA6B;AAC9H,cAAM,SAAS,OAAO;AAAA,MACxB;AAAA,IACF;AACA,SAAK,WAAW;AAChB,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,UAAU,CAAC,CAAC;AAEhB,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,aAAc;AACnB,UAAM,UAAU,aAAa,IAAI,SAAS,MAAM;AAChD,QAAI,WAAW,CAAC,cAAc,SAAS;AACrC,oBAAc,UAAU;AACxB,YAAM,EAAE,+CAA+C,sCAAsC,GAAG,SAAS;AACzG,YAAM,aAAa,IAAI,gBAAgB,aAAa,SAAS,CAAC;AAC9D,iBAAW,OAAO,SAAS;AAC3B,YAAM,YAAY,WAAW,SAAS;AACtC,YAAM,WAAW,WACb,+BAA+B,mBAAmB,QAAQ,CAAC,GAAG,YAAY,IAAI,SAAS,KAAK,EAAE,KAC9F,8BAA8B,YAAY,IAAI,SAAS,KAAK,EAAE;AAClE,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,UAAU,QAAQ,cAAc,CAAC,CAAC;AAEtC,QAAM,eAAe,MAAM,YAAY,OAAO,WAAiC;AAC7E,QAAI,CAAC,SAAU;AACf,UAAM,UAAU,uBAAuB,QAAQ,EAAE,IAAI,SAAS,CAAC;AAC/D,UAAM,WAAW,sBAAsB,SAAS;AAAA,MAC9C,cAAc,EAAE,wCAAwC,+BAA+B;AAAA,IACzF,CAAC;AACD,UAAM,EAAE,wCAAwC,sBAAsB,GAAG,SAAS;AAClF,WAAO,KAAK,6BAA6B;AAAA,EAC3C,GAAG,CAAC,UAAU,QAAQ,CAAC,CAAC;AAExB,QAAM,eAAe,MAAM,YAAY,YAAY;AACjD,QAAI,CAAC,SAAU;AACf,UAAM,WAAW,sBAAsB,UAAU;AAAA,MAC/C,cAAc,EAAE,wCAAwC,+BAA+B;AAAA,IACzF,CAAC;AACD,UAAM,EAAE,wCAAwC,sBAAsB,GAAG,SAAS;AAClF,WAAO,KAAK,6BAA6B;AAAA,EAC3C,GAAG,CAAC,UAAU,QAAQ,CAAC,CAAC;AAExB,QAAM,sBAAsB,MAAM,YAAY,OAAO,WAA0B;AAC7E,QAAI,CAAC,SAAU;AACf,UAAM,WAAW,sBAAsB,EAAE,IAAI,UAAU,uBAAuB,OAAO,GAAG;AAAA,MACtF,cAAc,EAAE,sDAAsD,4BAA4B;AAAA,IACpG,CAAC;AACD,6BAAyB,MAAM;AAC/B,UAAM,EAAE,wDAAwD,mBAAmB,GAAG,SAAS;AAAA,EACjG,GAAG,CAAC,UAAU,CAAC,CAAC;AAEhB,QAAM,YAAY,MAAM,QAAQ,MAAO;AAAA,IACrC,EAAE,IAAI,WAAoB,OAAO,EAAE,yCAAyC,SAAS,EAAE;AAAA,IACvF,EAAE,IAAI,gBAAyB,OAAO,EAAE,8CAA8C,cAAc,EAAE;AAAA,IACtG,EAAE,IAAI,cAAuB,OAAO,EAAE,4CAA4C,aAAa,EAAE;AAAA,EACnG,GAAI,CAAC,CAAC,CAAC;AAEP,QAAM,OAAO,MAAM,QAAQ,MAAO;AAAA,IAChC,EAAE,IAAI,SAAkB,OAAO,EAAE,uCAAuC,OAAO,EAAE;AAAA,IACjF,EAAE,IAAI,cAAuB,OAAO,EAAE,4CAA4C,YAAY,EAAE;AAAA,IAChG,EAAE,IAAI,aAAsB,OAAO,EAAE,2CAA2C,WAAW,EAAE;AAAA,EAC/F,GAAI,CAAC,CAAC,CAAC;AAEP,QAAM,wBAAwB,iBAAiB;AAAA,IAC7C,SAAS,CAAC;AAAA,IACV,UAAU;AAAA,EACZ;AAEA,QAAM,cAAc,cAAc,eAAe,cAAc,gBAAgB,sBAAsB,eAAe;AACpH,QAAM,YAAY,cAAc,MAAM,QAAQ,EAAE,4CAA4C,iBAAiB;AAC7G,QAAM,aAAa,MAAM,QAAQ,cAAc,SAAS,KAAK,cAAc,UAAU,SACjF,cAAc,YACd,CAAC,EAAE,6CAA6C,mBAAmB,CAAC;AACxE,QAAM,YAAY,cAAc,MAAM,SAAS;AAE/C,SACE,oBAAC,QACC,8BAAC,YACC,+BAAC,SAAI,WAAU,aACb;AAAA,yBAAC,SAAI,WAAU,qDACb;AAAA,2BAAC,SAAI,WAAU,2BACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YAEV;AAAA,kCAAC,UAAK,eAAW,MAAC,WAAU,kBAAiB,oBAAC;AAAA,cAC9C,oBAAC,UAAK,WAAU,WAAW,YAAE,iCAAiC,sBAAsB,GAAE;AAAA;AAAA;AAAA,QACxF;AAAA,QACA,qBAAC,SAAI,WAAU,aACb;AAAA,8BAAC,QAAG,WAAU,0CACX,yBAAe,EAAE,qCAAqC,qBAAqB,GAC9E;AAAA,UACA,oBAAC,OAAE,WAAU,iCACV,YAAE,qCAAqC,kCAAkC,GAC5E;AAAA,WACF;AAAA,SACF;AAAA,MACA,qBAAC,SAAI,WAAU,2BACZ;AAAA,mBACC;AAAA,UAAC;AAAA;AAAA,YACC,QAAQ;AAAA,cACN,cAAc;AAAA,cACd,YAAY;AAAA,cACZ,UAAU;AAAA,cACV,aAAa;AAAA,gBACX,OAAO;AAAA,gBACP,UAAU;AAAA,kBACR,CAAC,EAAE,sCAAsC,CAAC,GAAG;AAAA,kBAC7C,CAAC,EAAE,sCAAsC,CAAC,GAAG,aAAa,EAAE,6CAA6C,gBAAgB;AAAA,kBACzH,CAAC,EAAE,uCAAuC,CAAC,GAAG,WAAW,KAAK,IAAI;AAAA,gBACpE;AAAA,cACF;AAAA,YACF;AAAA,YACA,UAAU,+BAA+B,QAAQ;AAAA;AAAA,QACnD,IACE;AAAA,QACJ;AAAA,UAAC;AAAA;AAAA,YACC,QAAQ,WAAW;AAAA,cACjB,YAAY;AAAA,cACZ,UAAU;AAAA,cACV,YAAY,gBAAgB;AAAA,YAC9B,IAAI;AAAA;AAAA,QACN;AAAA,SACF;AAAA,OACF;AAAA,IAEA,oBAAC,SAAI,WAAU,YACb;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,cAAY,EAAE,uCAAuC,sBAAsB;AAAA,QAE1E,oBAAU,IAAI,CAAC,QACd;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,iBAAe,gBAAgB,IAAI;AAAA,YACnC,SAAS,MAAM,eAAe,IAAI,EAAE;AAAA,YACpC,WAAW,8EACT,gBAAgB,IAAI,KAChB,mCACA,gEACN;AAAA,YAEC,cAAI;AAAA;AAAA,UAXA,IAAI;AAAA,QAYX,CACD;AAAA;AAAA,IACH,GACF;AAAA,IAEC,gBAAgB,YACf,iCACE;AAAA,2BAAC,SAAI,WAAU,2DACb;AAAA,6BAAC,SAAI,WAAU,aACb;AAAA,+BAAC,SAAI,WAAU,iCACb;AAAA,gCAAC,QAAG,WAAU,8DACX,YAAE,uCAAuC,YAAY,GACxD;AAAA,YACA,qBAAC,SAAI,WAAU,6BACb;AAAA,mCAAC,SACC;AAAA,oCAAC,OAAE,WAAU,uDACV,YAAE,wCAAwC,MAAM,GACnD;AAAA,gBACA,oBAAC,OAAE,WAAU,6BAA6B,qBAAU;AAAA,iBACtD;AAAA,cACA,qBAAC,SACC;AAAA,oCAAC,OAAE,WAAU,uDACV,YAAE,yCAAyC,OAAO,GACrD;AAAA,gBACA,oBAAC,OAAE,WAAU,6BAA6B,qBAAW,KAAK,IAAI,GAAE;AAAA,iBAClE;AAAA,cACA,qBAAC,SACC;AAAA,oCAAC,OAAE,WAAU,uDACV,YAAE,wCAAwC,MAAM,GACnD;AAAA,gBACA,oBAAC,OAAE,WAAU,6BACV,uBAAa,EAAE,6CAA6C,gBAAgB,GAC/E;AAAA,iBACF;AAAA,cACA,qBAAC,SACC;AAAA,oCAAC,OAAE,WAAU,uDACV,YAAE,0CAA0C,QAAQ,GACvD;AAAA,gBACA,oBAAC,OAAE,WAAU,6BACV,wBAAc,YAAY,cAAc,YACrC,EAAE,0CAA0C,QAAQ,IACpD,EAAE,4CAA4C,UAAU,GAC9D;AAAA,iBACF;AAAA,eACF;AAAA,aACF;AAAA,UAEA,qBAAC,SAAI,WAAU,iCACb;AAAA,iCAAC,SAAI,WAAU,qDACb;AAAA,kCAAC,SAAI,WAAU,cACZ,eAAK,IAAI,CAAC,QACT;AAAA,gBAAC;AAAA;AAAA,kBAEC,MAAK;AAAA,kBACL,SAAS,MAAM,aAAa,IAAI,EAAE;AAAA,kBAClC,WAAW,8EACT,cAAc,IAAI,KACd,mCACA,gEACN;AAAA,kBAEC,cAAI;AAAA;AAAA,gBATA,IAAI;AAAA,cAUX,CACD,GACH;AAAA,cACC,gBACC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,MAAK;AAAA,kBACL,UAAU,cAAc;AAAA,kBACxB,SAAS,MAAM,cAAc,QAAQ;AAAA,kBAEpC;AAAA,kCAAc,SAAS,cAAc,cAAc,oBAAC,QAAK,WAAU,gBAAe,IAAK;AAAA,oBACvF,cAAc;AAAA;AAAA;AAAA,cACjB,IACE;AAAA,eACN;AAAA,YACC,cAAc,UACb;AAAA,cAAC;AAAA;AAAA,gBACC,UAAU,YAAY;AAAA,gBACtB,YAAY,EAAE,wCAAwC,eAAe;AAAA,gBACrE,cAAc;AAAA,gBACd,YAAY;AAAA,gBACZ,aAAa;AAAA,gBACb,gBAAgB,EAAE,sCAAsC,UAAU;AAAA,gBAClE,YAAY;AAAA,kBACV,OAAO,EAAE,6CAA6C,2BAA2B;AAAA,kBACjF,aAAa,EAAE,8CAA8C,YAAY;AAAA,gBAC3E;AAAA,gBACA,gBAAgB;AAAA,gBAChB,YAAY;AAAA,gBACZ,aAAY;AAAA,gBACZ,mBAAkB;AAAA,gBAClB,aAAa;AAAA,gBACb,YAAY;AAAA,gBACZ,aAAa;AAAA,gBACb,iBAAiB;AAAA;AAAA,YACnB,IACE;AAAA,YACH,cAAc,eACb;AAAA,cAAC;AAAA;AAAA,gBACC,UAAU,YAAY;AAAA,gBACtB,gBAAgB,EAAE,2CAA2C,cAAc;AAAA,gBAC3E,YAAY;AAAA,kBACV,OAAO,EAAE,kDAAkD,mBAAmB;AAAA,kBAC9E,aAAa,EAAE,mDAAmD,iBAAiB;AAAA,gBACrF;AAAA,gBACA,gBAAgB;AAAA,gBAChB,aAAa;AAAA,gBACb;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,aAAY;AAAA,gBACZ,YAAY;AAAA,gBACZ,aAAa;AAAA,gBACb;AAAA,gBACA,YAAY;AAAA,gBACZ,sBAAsB,CAAC,kCAAkC;AAAA;AAAA,YAC3D,IACE;AAAA,YACH,cAAc,cACb;AAAA,cAAC;AAAA;AAAA,gBACC,UAAU,YAAY;AAAA,gBACtB,YAAY,EAAE,4CAA4C,mBAAmB;AAAA,gBAC7E,gBAAgB,EAAE,0CAA0C,aAAa;AAAA,gBACzE,YAAY;AAAA,kBACV,OAAO,EAAE,iDAAiD,kBAAkB;AAAA,kBAC5E,aAAa,EAAE,kDAAkD,gBAAgB;AAAA,gBACnF;AAAA,gBACA,gBAAgB;AAAA,gBAChB,aAAa;AAAA,gBACb;AAAA,gBACA,aAAY;AAAA;AAAA,YACd,IACE;AAAA,aACN;AAAA,WACF;AAAA,QACA,oBAAC,SAAI,WAAU,aACb,+BAAC,SAAI,WAAU,iCACb;AAAA,8BAAC,QAAG,WAAU,8DACX,YAAE,oCAAoC,gBAAgB,GACzD;AAAA,UACA,oBAAC,SAAI,WAAU,aACZ,wBAAc,cACb,oBAAC,mBAAgB,MAAM,aAAa,aAAa,QAAO,YAAW,WAAW,oBAAoB,IAElG,oBAAC,OAAE,WAAU,iCACV,YAAE,6CAA6C,0BAA0B,GAC5E,GAEJ;AAAA,WACF,GACF;AAAA,SACF;AAAA,MAEA,qBAAC,SAAI,WAAU,iCACb;AAAA,4BAAC,QAAG,WAAU,8DACX,YAAE,sCAAsC,iBAAiB,GAC5D;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,UAAQ;AAAA,YACR,OAAO,EAAE,oCAAoC,kBAAkB;AAAA,YAC/D,UAAS;AAAA,YACT,YAAW;AAAA,YACX,eAAe;AAAA,YACf,UAAU;AAAA,YACV,UAAU;AAAA,YACV,WAAW,CAAC;AAAA,YACZ,gBAAgB,EAAE,kCAAkC,wBAAwB;AAAA;AAAA,QAC9E;AAAA,SACF;AAAA,OACF,IACE,gBAAgB,iBAClB;AAAA,MAAC;AAAA;AAAA,QACC,aAAY;AAAA,QACZ,WAAW,YAAY;AAAA,QACvB,aAAY;AAAA,QACZ,MAAK;AAAA,QACL,WAAW;AAAA,QACX,iBAAiB;AAAA,QACjB,oBAAoB,CAAC,EAAE,mBAAmB,WAAW,eAAe,MAClE,yBAAyB,EAAE,mBAAmB,WAAW,eAAe,CAAC;AAAA;AAAA,IAE7E,IAEA,oBAAC,SAAI,WAAU,iCACb,8BAAC,qBAAkB,UAAU,YAAY,MAAM,GACjD;AAAA,KAEJ,GACF,GACF;AAEJ;AAEA,SAAS,oBAAoB,OAA0B;AACrD,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MACJ,IAAI,CAAC,UAAW,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI,EAAG,EAC9D,OAAO,CAAC,UAAU,MAAM,SAAS,CAAC;AACvC;AAEA,SAAS,sBAAyB,SAAsB,UAAwC;AAC9F,MAAI,MAAM,QAAQ,OAAO,KAAK,QAAQ,OAAQ,QAAO;AACrD,MAAI,MAAM,QAAQ,QAAQ,KAAK,SAAS,OAAQ,QAAO;AACvD,SAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,MAAM,QAAQ,QAAQ,IAAI,WAAW;AACjF;",
|
|
6
6
|
"names": ["params"]
|
|
7
7
|
}
|
|
@@ -8,6 +8,7 @@ import { updateCrud, deleteCrud } from "@open-mercato/ui/backend/utils/crud";
|
|
|
8
8
|
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
9
9
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
10
10
|
import { TeamRoleForm, buildTeamRolePayload } from "@open-mercato/core/modules/staff/components/TeamRoleForm";
|
|
11
|
+
import { SendObjectMessageDialog } from "@open-mercato/ui/backend/messages";
|
|
11
12
|
import { extractCustomFieldEntries } from "@open-mercato/shared/lib/crud/custom-fields-client";
|
|
12
13
|
import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
|
|
13
14
|
function StaffTeamRoleEditPage({ params }) {
|
|
@@ -105,7 +106,19 @@ function StaffTeamRoleEditPage({ params }) {
|
|
|
105
106
|
onSubmit: handleSubmit,
|
|
106
107
|
onDelete: handleDelete,
|
|
107
108
|
isLoading: !initialValues,
|
|
108
|
-
loadingMessage: t("staff.teamRoles.form.loading", "Loading team role...")
|
|
109
|
+
loadingMessage: t("staff.teamRoles.form.loading", "Loading team role..."),
|
|
110
|
+
extraActions: roleId ? /* @__PURE__ */ jsx(
|
|
111
|
+
SendObjectMessageDialog,
|
|
112
|
+
{
|
|
113
|
+
object: {
|
|
114
|
+
entityModule: "staff",
|
|
115
|
+
entityType: "team_role",
|
|
116
|
+
entityId: roleId,
|
|
117
|
+
previewData: { title: initialValues?.name ?? "" }
|
|
118
|
+
},
|
|
119
|
+
viewHref: `/backend/staff/team-roles/${roleId}/edit`
|
|
120
|
+
}
|
|
121
|
+
) : void 0
|
|
109
122
|
}
|
|
110
123
|
) }) });
|
|
111
124
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../../src/modules/staff/backend/staff/team-roles/%5Bid%5D/edit/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { readApiResultOrThrow, apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { TeamRoleForm, type TeamRoleFormValues, type TeamRoleOption, buildTeamRolePayload } from '@open-mercato/core/modules/staff/components/TeamRoleForm'\nimport { extractCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields-client'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\n\ntype TeamRoleRecord = {\n id: string\n name: string\n description?: string | null\n teamId?: string | null\n team_id?: string | null\n appearanceIcon?: string | null\n appearanceColor?: string | null\n appearance_icon?: string | null\n appearance_color?: string | null\n} & Record<string, unknown>\n\ntype TeamRoleResponse = {\n items?: TeamRoleRecord[]\n}\n\ntype TeamsResponse = {\n items?: Array<{ id?: string; name?: string }>\n}\n\nexport default function StaffTeamRoleEditPage({ params }: { params?: { id?: string } }) {\n const roleId = params?.id\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [initialValues, setInitialValues] = React.useState<TeamRoleFormValues | null>(null)\n const [teams, setTeams] = React.useState<TeamRoleOption[]>([])\n\n React.useEffect(() => {\n if (!roleId) return\n const roleIdValue = roleId\n let cancelled = false\n async function loadRole() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: roleIdValue })\n const payload = await readApiResultOrThrow<TeamRoleResponse>(\n `/api/staff/team-roles?${params.toString()}`,\n undefined,\n { errorMessage: t('staff.teamRoles.errors.load', 'Failed to load team role.') },\n )\n const record = Array.isArray(payload.items) ? payload.items[0] : null\n if (!record) throw new Error(t('staff.teamRoles.errors.notFound', 'Team role not found.'))\n const customFields = extractCustomFieldEntries(record)\n const appearanceIcon = typeof record.appearanceIcon === 'string'\n ? record.appearanceIcon\n : typeof record.appearance_icon === 'string'\n ? record.appearance_icon\n : null\n const appearanceColor = typeof record.appearanceColor === 'string'\n ? record.appearanceColor\n : typeof record.appearance_color === 'string'\n ? record.appearance_color\n : null\n if (!cancelled) {\n setInitialValues({\n id: record.id,\n teamId: typeof record.teamId === 'string'\n ? record.teamId\n : typeof record.team_id === 'string'\n ? record.team_id\n : null,\n name: record.name ?? '',\n description: record.description ?? '',\n appearance: { icon: appearanceIcon, color: appearanceColor },\n ...customFields,\n })\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : t('staff.teamRoles.errors.load', 'Failed to load team role.')\n flash(message, 'error')\n }\n }\n loadRole()\n return () => { cancelled = true }\n }, [roleId, t])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadTeams() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100' })\n const call = await apiCall<TeamsResponse>(`/api/staff/teams?${params.toString()}`)\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const options = items\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 { id, name }\n })\n .filter((entry): entry is TeamRoleOption => entry !== null)\n if (!cancelled) setTeams(options)\n } catch {\n if (!cancelled) setTeams([])\n }\n }\n loadTeams()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n const handleSubmit = React.useCallback(async (values: TeamRoleFormValues) => {\n if (!roleId) return\n const payload = buildTeamRolePayload(values, { id: roleId })\n await updateCrud('staff/team-roles', payload, {\n errorMessage: t('staff.teamRoles.errors.save', 'Failed to save team role.'),\n })\n flash(t('staff.teamRoles.messages.saved', 'Team role saved.'), 'success')\n router.push('/backend/staff/team-roles')\n }, [roleId, router, t])\n\n const handleDelete = React.useCallback(async () => {\n if (!roleId) return\n await deleteCrud('staff/team-roles', roleId, {\n errorMessage: t('staff.teamRoles.errors.delete', 'Failed to delete team role.'),\n })\n flash(t('staff.teamRoles.messages.deleted', 'Team role deleted.'), 'success')\n router.push('/backend/staff/team-roles')\n }, [roleId, router, t])\n\n return (\n <Page>\n <PageBody>\n <TeamRoleForm\n title={t('staff.teamRoles.form.editTitle', 'Edit team role')}\n backHref=\"/backend/staff/team-roles\"\n cancelHref=\"/backend/staff/team-roles\"\n initialValues={initialValues ?? { name: '', description: '', appearance: { icon: null, color: null }, teamId: null }}\n teamOptions={teams}\n onSubmit={handleSubmit}\n onDelete={handleDelete}\n isLoading={!initialValues}\n loadingMessage={t('staff.teamRoles.form.loading', 'Loading team role...')}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { readApiResultOrThrow, apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { TeamRoleForm, type TeamRoleFormValues, type TeamRoleOption, buildTeamRolePayload } from '@open-mercato/core/modules/staff/components/TeamRoleForm'\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'\n\ntype TeamRoleRecord = {\n id: string\n name: string\n description?: string | null\n teamId?: string | null\n team_id?: string | null\n appearanceIcon?: string | null\n appearanceColor?: string | null\n appearance_icon?: string | null\n appearance_color?: string | null\n} & Record<string, unknown>\n\ntype TeamRoleResponse = {\n items?: TeamRoleRecord[]\n}\n\ntype TeamsResponse = {\n items?: Array<{ id?: string; name?: string }>\n}\n\nexport default function StaffTeamRoleEditPage({ params }: { params?: { id?: string } }) {\n const roleId = params?.id\n const t = useT()\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [initialValues, setInitialValues] = React.useState<TeamRoleFormValues | null>(null)\n const [teams, setTeams] = React.useState<TeamRoleOption[]>([])\n\n React.useEffect(() => {\n if (!roleId) return\n const roleIdValue = roleId\n let cancelled = false\n async function loadRole() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: roleIdValue })\n const payload = await readApiResultOrThrow<TeamRoleResponse>(\n `/api/staff/team-roles?${params.toString()}`,\n undefined,\n { errorMessage: t('staff.teamRoles.errors.load', 'Failed to load team role.') },\n )\n const record = Array.isArray(payload.items) ? payload.items[0] : null\n if (!record) throw new Error(t('staff.teamRoles.errors.notFound', 'Team role not found.'))\n const customFields = extractCustomFieldEntries(record)\n const appearanceIcon = typeof record.appearanceIcon === 'string'\n ? record.appearanceIcon\n : typeof record.appearance_icon === 'string'\n ? record.appearance_icon\n : null\n const appearanceColor = typeof record.appearanceColor === 'string'\n ? record.appearanceColor\n : typeof record.appearance_color === 'string'\n ? record.appearance_color\n : null\n if (!cancelled) {\n setInitialValues({\n id: record.id,\n teamId: typeof record.teamId === 'string'\n ? record.teamId\n : typeof record.team_id === 'string'\n ? record.team_id\n : null,\n name: record.name ?? '',\n description: record.description ?? '',\n appearance: { icon: appearanceIcon, color: appearanceColor },\n ...customFields,\n })\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : t('staff.teamRoles.errors.load', 'Failed to load team role.')\n flash(message, 'error')\n }\n }\n loadRole()\n return () => { cancelled = true }\n }, [roleId, t])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadTeams() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100' })\n const call = await apiCall<TeamsResponse>(`/api/staff/teams?${params.toString()}`)\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const options = items\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 { id, name }\n })\n .filter((entry): entry is TeamRoleOption => entry !== null)\n if (!cancelled) setTeams(options)\n } catch {\n if (!cancelled) setTeams([])\n }\n }\n loadTeams()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n const handleSubmit = React.useCallback(async (values: TeamRoleFormValues) => {\n if (!roleId) return\n const payload = buildTeamRolePayload(values, { id: roleId })\n await updateCrud('staff/team-roles', payload, {\n errorMessage: t('staff.teamRoles.errors.save', 'Failed to save team role.'),\n })\n flash(t('staff.teamRoles.messages.saved', 'Team role saved.'), 'success')\n router.push('/backend/staff/team-roles')\n }, [roleId, router, t])\n\n const handleDelete = React.useCallback(async () => {\n if (!roleId) return\n await deleteCrud('staff/team-roles', roleId, {\n errorMessage: t('staff.teamRoles.errors.delete', 'Failed to delete team role.'),\n })\n flash(t('staff.teamRoles.messages.deleted', 'Team role deleted.'), 'success')\n router.push('/backend/staff/team-roles')\n }, [roleId, router, t])\n\n return (\n <Page>\n <PageBody>\n <TeamRoleForm\n title={t('staff.teamRoles.form.editTitle', 'Edit team role')}\n backHref=\"/backend/staff/team-roles\"\n cancelHref=\"/backend/staff/team-roles\"\n initialValues={initialValues ?? { name: '', description: '', appearance: { icon: null, color: null }, teamId: null }}\n teamOptions={teams}\n onSubmit={handleSubmit}\n onDelete={handleDelete}\n isLoading={!initialValues}\n loadingMessage={t('staff.teamRoles.form.loading', 'Loading team role...')}\n extraActions={roleId ? (\n <SendObjectMessageDialog\n object={{\n entityModule: 'staff',\n entityType: 'team_role',\n entityId: roleId,\n previewData: { title: initialValues?.name ?? ''},\n }}\n viewHref={`/backend/staff/team-roles/${roleId}/edit`}\n />\n ) : undefined}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["params"]
|
|
7
7
|
}
|
|
@@ -13,6 +13,7 @@ import { BooleanIcon } from "@open-mercato/ui/backend/ValueIcons";
|
|
|
13
13
|
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
14
14
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
15
15
|
import { TeamForm, buildTeamPayload } from "@open-mercato/core/modules/staff/components/TeamForm";
|
|
16
|
+
import { SendObjectMessageDialog } from "@open-mercato/ui/backend/messages";
|
|
16
17
|
import { extractCustomFieldEntries } from "@open-mercato/shared/lib/crud/custom-fields-client";
|
|
17
18
|
import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
|
|
18
19
|
import { Plus } from "lucide-react";
|
|
@@ -258,7 +259,19 @@ function StaffTeamEditPage({ params }) {
|
|
|
258
259
|
onSubmit: handleSubmit,
|
|
259
260
|
onDelete: handleDelete,
|
|
260
261
|
isLoading: !initialValues,
|
|
261
|
-
loadingMessage: t("staff.teams.form.loading", "Loading team...")
|
|
262
|
+
loadingMessage: t("staff.teams.form.loading", "Loading team..."),
|
|
263
|
+
extraActions: teamId ? /* @__PURE__ */ jsx(
|
|
264
|
+
SendObjectMessageDialog,
|
|
265
|
+
{
|
|
266
|
+
object: {
|
|
267
|
+
entityModule: "staff",
|
|
268
|
+
entityType: "team",
|
|
269
|
+
entityId: teamId,
|
|
270
|
+
previewData: { title: initialValues?.name ?? "" }
|
|
271
|
+
},
|
|
272
|
+
viewHref: `/backend/staff/teams/${teamId}/edit`
|
|
273
|
+
}
|
|
274
|
+
) : void 0
|
|
262
275
|
}
|
|
263
276
|
) : /* @__PURE__ */ jsx(
|
|
264
277
|
DataTable,
|
|
@@ -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 { 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 />\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": ";
|
|
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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",
|
|
6
6
|
"names": ["params"]
|
|
7
7
|
}
|
|
@@ -32,7 +32,8 @@ function TeamForm(props) {
|
|
|
32
32
|
onSubmit,
|
|
33
33
|
onDelete,
|
|
34
34
|
isLoading,
|
|
35
|
-
loadingMessage
|
|
35
|
+
loadingMessage,
|
|
36
|
+
extraActions
|
|
36
37
|
} = props;
|
|
37
38
|
const t = useT();
|
|
38
39
|
const fields = React.useMemo(() => [
|
|
@@ -59,7 +60,8 @@ function TeamForm(props) {
|
|
|
59
60
|
onSubmit,
|
|
60
61
|
onDelete,
|
|
61
62
|
isLoading,
|
|
62
|
-
loadingMessage
|
|
63
|
+
loadingMessage,
|
|
64
|
+
extraActions
|
|
63
65
|
}
|
|
64
66
|
);
|
|
65
67
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/components/TeamForm.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { normalizeCustomFieldValues } from '@open-mercato/shared/lib/custom-fields/normalize'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport type TeamFormValues = {\n id?: string\n name: string\n description?: string | null\n isActive?: boolean\n} & Record<string, unknown>\n\nexport type TeamFormProps = {\n title: string\n submitLabel?: string\n backHref: string\n cancelHref: string\n initialValues: TeamFormValues\n onSubmit: (values: TeamFormValues) => Promise<void>\n onDelete?: () => Promise<void>\n isLoading?: boolean\n loadingMessage?: string\n}\n\nconst normalizeCustomFieldSubmitValue = (value: unknown): unknown => {\n const normalized = normalizeCustomFieldValues({ value })\n return normalized.value\n}\n\nexport const buildTeamPayload = (\n values: TeamFormValues,\n options: { id?: string } = {},\n): Record<string, unknown> => {\n const name = typeof values.name === 'string' ? values.name.trim() : ''\n const description = typeof values.description === 'string' && values.description.trim().length\n ? values.description.trim()\n : null\n const customFields = collectCustomFieldValues(values, { transform: normalizeCustomFieldSubmitValue })\n return {\n ...(options.id ? { id: options.id } : {}),\n name,\n description,\n isActive: values.isActive ?? true,\n ...(Object.keys(customFields).length ? { customFields } : {}),\n }\n}\n\nexport function TeamForm(props: TeamFormProps) {\n const {\n title,\n submitLabel,\n backHref,\n cancelHref,\n initialValues,\n onSubmit,\n onDelete,\n isLoading,\n loadingMessage,\n } = props\n const t = useT()\n\n const fields = React.useMemo<CrudField[]>(() => [\n { id: 'name', label: t('staff.teams.form.fields.name', 'Name'), type: 'text', required: true },\n { id: 'description', label: t('staff.teams.form.fields.description', 'Description'), type: 'richtext' },\n { id: 'isActive', label: t('staff.teams.form.fields.active', 'Active'), type: 'checkbox' },\n ], [t])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => [\n { id: 'details', fields: ['name', 'description', 'isActive'] },\n { id: 'custom', title: t('entities.customFields.title', 'Custom Attributes'), column: 2, kind: 'customFields' },\n ], [t])\n\n return (\n <CrudForm<TeamFormValues>\n title={title}\n backHref={backHref}\n cancelHref={cancelHref}\n versionHistory={initialValues.id\n ? { resourceKind: 'staff.team', resourceId: String(initialValues.id) }\n : undefined}\n submitLabel={submitLabel}\n fields={fields}\n groups={groups}\n entityId={E.staff.staff_team}\n initialValues={initialValues}\n onSubmit={onSubmit}\n onDelete={onDelete}\n isLoading={isLoading}\n loadingMessage={loadingMessage}\n />\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { normalizeCustomFieldValues } from '@open-mercato/shared/lib/custom-fields/normalize'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport type TeamFormValues = {\n id?: string\n name: string\n description?: string | null\n isActive?: boolean\n} & Record<string, unknown>\n\nexport type TeamFormProps = {\n title: string\n submitLabel?: string\n backHref: string\n cancelHref: string\n initialValues: TeamFormValues\n onSubmit: (values: TeamFormValues) => Promise<void>\n onDelete?: () => Promise<void>\n isLoading?: boolean\n loadingMessage?: string\n extraActions?: React.ReactNode\n}\n\nconst normalizeCustomFieldSubmitValue = (value: unknown): unknown => {\n const normalized = normalizeCustomFieldValues({ value })\n return normalized.value\n}\n\nexport const buildTeamPayload = (\n values: TeamFormValues,\n options: { id?: string } = {},\n): Record<string, unknown> => {\n const name = typeof values.name === 'string' ? values.name.trim() : ''\n const description = typeof values.description === 'string' && values.description.trim().length\n ? values.description.trim()\n : null\n const customFields = collectCustomFieldValues(values, { transform: normalizeCustomFieldSubmitValue })\n return {\n ...(options.id ? { id: options.id } : {}),\n name,\n description,\n isActive: values.isActive ?? true,\n ...(Object.keys(customFields).length ? { customFields } : {}),\n }\n}\n\nexport function TeamForm(props: TeamFormProps) {\n const {\n title,\n submitLabel,\n backHref,\n cancelHref,\n initialValues,\n onSubmit,\n onDelete,\n isLoading,\n loadingMessage,\n extraActions,\n } = props\n const t = useT()\n\n const fields = React.useMemo<CrudField[]>(() => [\n { id: 'name', label: t('staff.teams.form.fields.name', 'Name'), type: 'text', required: true },\n { id: 'description', label: t('staff.teams.form.fields.description', 'Description'), type: 'richtext' },\n { id: 'isActive', label: t('staff.teams.form.fields.active', 'Active'), type: 'checkbox' },\n ], [t])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => [\n { id: 'details', fields: ['name', 'description', 'isActive'] },\n { id: 'custom', title: t('entities.customFields.title', 'Custom Attributes'), column: 2, kind: 'customFields' },\n ], [t])\n\n return (\n <CrudForm<TeamFormValues>\n title={title}\n backHref={backHref}\n cancelHref={cancelHref}\n versionHistory={initialValues.id\n ? { resourceKind: 'staff.team', resourceId: String(initialValues.id) }\n : undefined}\n submitLabel={submitLabel}\n fields={fields}\n groups={groups}\n entityId={E.staff.staff_team}\n initialValues={initialValues}\n onSubmit={onSubmit}\n onDelete={onDelete}\n isLoading={isLoading}\n loadingMessage={loadingMessage}\n extraActions={extraActions}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": ";AA+EI;AA7EJ,YAAY,WAAW;AACvB,SAAS,gBAAoD;AAC7D,SAAS,gCAAgC;AACzC,SAAS,kCAAkC;AAC3C,SAAS,SAAS;AAClB,SAAS,YAAY;AAsBrB,MAAM,kCAAkC,CAAC,UAA4B;AACnE,QAAM,aAAa,2BAA2B,EAAE,MAAM,CAAC;AACvD,SAAO,WAAW;AACpB;AAEO,MAAM,mBAAmB,CAC9B,QACA,UAA2B,CAAC,MACA;AAC5B,QAAM,OAAO,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK,KAAK,IAAI;AACpE,QAAM,cAAc,OAAO,OAAO,gBAAgB,YAAY,OAAO,YAAY,KAAK,EAAE,SACpF,OAAO,YAAY,KAAK,IACxB;AACJ,QAAM,eAAe,yBAAyB,QAAQ,EAAE,WAAW,gCAAgC,CAAC;AACpG,SAAO;AAAA,IACL,GAAI,QAAQ,KAAK,EAAE,IAAI,QAAQ,GAAG,IAAI,CAAC;AAAA,IACvC;AAAA,IACA;AAAA,IACA,UAAU,OAAO,YAAY;AAAA,IAC7B,GAAI,OAAO,KAAK,YAAY,EAAE,SAAS,EAAE,aAAa,IAAI,CAAC;AAAA,EAC7D;AACF;AAEO,SAAS,SAAS,OAAsB;AAC7C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACJ,QAAM,IAAI,KAAK;AAEf,QAAM,SAAS,MAAM,QAAqB,MAAM;AAAA,IAC9C,EAAE,IAAI,QAAQ,OAAO,EAAE,gCAAgC,MAAM,GAAG,MAAM,QAAQ,UAAU,KAAK;AAAA,IAC7F,EAAE,IAAI,eAAe,OAAO,EAAE,uCAAuC,aAAa,GAAG,MAAM,WAAW;AAAA,IACtG,EAAE,IAAI,YAAY,OAAO,EAAE,kCAAkC,QAAQ,GAAG,MAAM,WAAW;AAAA,EAC3F,GAAG,CAAC,CAAC,CAAC;AAEN,QAAM,SAAS,MAAM,QAAyB,MAAM;AAAA,IAClD,EAAE,IAAI,WAAW,QAAQ,CAAC,QAAQ,eAAe,UAAU,EAAE;AAAA,IAC7D,EAAE,IAAI,UAAU,OAAO,EAAE,+BAA+B,mBAAmB,GAAG,QAAQ,GAAG,MAAM,eAAe;AAAA,EAChH,GAAG,CAAC,CAAC,CAAC;AAEN,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,cAAc,KAC1B,EAAE,cAAc,cAAc,YAAY,OAAO,cAAc,EAAE,EAAE,IACnE;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,EAAE,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,EACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|