@open-mercato/core 0.4.5-develop-610fbb24ec → 0.4.5-develop-811deeb983
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/data/validators.js +4 -3
- package/dist/modules/catalog/data/validators.js.map +2 -2
- 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/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/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/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/package.json +3 -3
- 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/data/validators.ts +47 -45
- 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/lib/messageObjectPreviews.ts +43 -3
- package/src/modules/customers/message-objects.ts +31 -11
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +236 -0
- package/src/modules/customers/migrations/.snapshot-openmercato.json +236 -0
- 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/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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/staff/backend/staff/my-availability/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { AvailabilityRulesEditor } from '@open-mercato/core/modules/planner/components/AvailabilityRulesEditor'\nimport { buildMemberScheduleItems } from '@open-mercato/core/modules/staff/lib/memberSchedule'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype SelfMemberResponse = {\n member?: {\n id?: string\n displayName?: string\n availabilityRuleSetId?: string | null\n } | null\n}\n\ntype FeatureCheckResponse = {\n ok?: boolean\n granted?: string[]\n}\n\nexport default function StaffMyAvailabilityPage() {\n const t = useT()\n const [member, setMember] = React.useState<SelfMemberResponse['member']>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [canManageAvailability, setCanManageAvailability] = React.useState(false)\n const [canManageUnavailability, setCanManageUnavailability] = React.useState(false)\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n setError(null)\n try {\n const memberCall = await apiCall<SelfMemberResponse>('/api/staff/team-members/self')\n const featureCall = await apiCall<FeatureCheckResponse>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n features: [\n 'planner.manage_availability',\n 'staff.my_availability.manage',\n 'staff.my_availability.unavailability',\n ],\n }),\n })\n if (!cancelled) {\n setMember(memberCall.result?.member ?? null)\n const granted = Array.isArray(featureCall.result?.granted) ? featureCall.result?.granted ?? [] : []\n const hasPlannerManage = granted.includes('planner.manage_availability')\n const hasSelfManage = granted.includes('staff.my_availability.manage')\n const hasSelfUnavailability = granted.includes('staff.my_availability.unavailability')\n const canManage = hasPlannerManage || hasSelfManage\n setCanManageAvailability(canManage)\n setCanManageUnavailability(canManage && (hasPlannerManage || hasSelfUnavailability))\n }\n } catch (err) {\n if (!cancelled) {\n setError(t('staff.myAvailability.errors.load', 'Failed to load availability.'))\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n void load()\n return () => { cancelled = true }\n }, [t])\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('staff.myAvailability.loading', 'Loading availability...')} />\n </PageBody>\n </Page>\n )\n }\n\n if (error) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage label={error} />\n </PageBody>\n </Page>\n )\n }\n\n if (!member?.id) {\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-3 rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n <p>{t('staff.myAvailability.empty.profileRequired', 'Create your team member profile to manage availability.')}</p>\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/profile/create\">\n {t('staff.leaveRequests.actions.createProfile', 'Create my profile')}\n </Link>\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {!canManageAvailability ? (\n <div className=\"space-y-2 rounded-lg border bg-card p-4 text-sm text-muted-foreground\">\n <p className=\"font-medium text-foreground\">\n {t('staff.myAvailability.readOnly.title', 'Only an administrator can manage your availability.')}\n </p>\n <p>\n {t('staff.myAvailability.readOnly.body', 'Use leave requests to request changes.')}\n </p>\n <Button asChild size=\"sm\" variant=\"outline\">\n <Link href=\"/backend/staff/my-leave-requests\">\n {t('staff.leaveRequests.my.title', 'My leave requests')}\n </Link>\n </Button>\n </div>\n ) : null}\n <AvailabilityRulesEditor\n subjectType=\"member\"\n subjectId={member.id}\n labelPrefix=\"staff.teamMembers\"\n mode=\"availability\"\n rulesetId={member.availabilityRuleSetId ?? null}\n buildScheduleItems={({ availabilityRules, translate }) => (\n buildMemberScheduleItems({ availabilityRules, translate })\n )}\n readOnly={!canManageAvailability}\n allowUnavailability={canManageUnavailability}\n />\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { AvailabilityRulesEditor } from '@open-mercato/core/modules/planner/components/AvailabilityRulesEditor'\nimport { buildMemberScheduleItems } from '@open-mercato/core/modules/staff/lib/memberSchedule'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\n\ntype SelfMemberResponse = {\n member?: {\n id?: string\n displayName?: string\n availabilityRuleSetId?: string | null\n } | null\n}\n\ntype FeatureCheckResponse = {\n ok?: boolean\n granted?: string[]\n}\n\nexport default function StaffMyAvailabilityPage() {\n const t = useT()\n const [member, setMember] = React.useState<SelfMemberResponse['member']>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [canManageAvailability, setCanManageAvailability] = React.useState(false)\n const [canManageUnavailability, setCanManageUnavailability] = React.useState(false)\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n setError(null)\n try {\n const memberCall = await apiCall<SelfMemberResponse>('/api/staff/team-members/self')\n const featureCall = await apiCall<FeatureCheckResponse>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n features: [\n 'planner.manage_availability',\n 'staff.my_availability.manage',\n 'staff.my_availability.unavailability',\n ],\n }),\n })\n if (!cancelled) {\n setMember(memberCall.result?.member ?? null)\n const granted = Array.isArray(featureCall.result?.granted) ? featureCall.result?.granted ?? [] : []\n const hasPlannerManage = granted.includes('planner.manage_availability')\n const hasSelfManage = granted.includes('staff.my_availability.manage')\n const hasSelfUnavailability = granted.includes('staff.my_availability.unavailability')\n const canManage = hasPlannerManage || hasSelfManage\n setCanManageAvailability(canManage)\n setCanManageUnavailability(canManage && (hasPlannerManage || hasSelfUnavailability))\n }\n } catch (err) {\n if (!cancelled) {\n setError(t('staff.myAvailability.errors.load', 'Failed to load availability.'))\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n void load()\n return () => { cancelled = true }\n }, [t])\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('staff.myAvailability.loading', 'Loading availability...')} />\n </PageBody>\n </Page>\n )\n }\n\n if (error) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage label={error} />\n </PageBody>\n </Page>\n )\n }\n\n if (!member?.id) {\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-3 rounded-lg border bg-card p-6 text-center text-sm text-muted-foreground\">\n <p>{t('staff.myAvailability.empty.profileRequired', 'Create your team member profile to manage availability.')}</p>\n <Button asChild size=\"sm\">\n <Link href=\"/backend/staff/profile/create\">\n {t('staff.leaveRequests.actions.createProfile', 'Create my profile')}\n </Link>\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-4\">\n {member.availabilityRuleSetId ? (\n <div className=\"flex justify-end\">\n <SendObjectMessageDialog\n object={{\n entityModule: 'staff',\n entityType: 'my_availability',\n entityId: member.availabilityRuleSetId,\n previewData: { title: member.displayName ?? t('staff.myAvailability.title', 'My Availability') },\n }}\n viewHref=\"/backend/staff/my-availability\"\n />\n </div>\n ) : null}\n {!canManageAvailability ? (\n <div className=\"space-y-2 rounded-lg border bg-card p-4 text-sm text-muted-foreground\">\n <p className=\"font-medium text-foreground\">\n {t('staff.myAvailability.readOnly.title', 'Only an administrator can manage your availability.')}\n </p>\n <p>\n {t('staff.myAvailability.readOnly.body', 'Use leave requests to request changes.')}\n </p>\n <Button asChild size=\"sm\" variant=\"outline\">\n <Link href=\"/backend/staff/my-leave-requests\">\n {t('staff.leaveRequests.my.title', 'My leave requests')}\n </Link>\n </Button>\n </div>\n ) : null}\n <AvailabilityRulesEditor\n subjectType=\"member\"\n subjectId={member.id}\n labelPrefix=\"staff.teamMembers\"\n mode=\"availability\"\n rulesetId={member.availabilityRuleSetId ?? null}\n buildScheduleItems={({ availabilityRules, translate }) => (\n buildMemberScheduleItems({ availabilityRules, translate })\n )}\n readOnly={!canManageAvailability}\n allowUnavailability={canManageUnavailability}\n />\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { useRouter } from "next/navigation";
|
|
5
|
-
import { Leaf } from "lucide-react";
|
|
6
5
|
import { Page, PageBody } from "@open-mercato/ui/backend/Page";
|
|
7
6
|
import { Badge } from "@open-mercato/ui/primitives/badge";
|
|
8
|
-
import { Button } from "@open-mercato/ui/primitives/button";
|
|
9
7
|
import { LoadingMessage, ErrorMessage } from "@open-mercato/ui/backend/detail";
|
|
10
8
|
import { SendObjectMessageDialog } from "@open-mercato/ui/backend/messages";
|
|
11
9
|
import { readApiResultOrThrow } from "@open-mercato/ui/backend/utils/apiCall";
|
|
@@ -75,19 +73,6 @@ function StaffMyLeaveRequestDetailPage({ params }) {
|
|
|
75
73
|
record?.startDate ?? record?.start_date ?? null,
|
|
76
74
|
record?.endDate ?? record?.end_date ?? null
|
|
77
75
|
);
|
|
78
|
-
const messageContextPreview = React.useMemo(() => /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
79
|
-
/* @__PURE__ */ jsx("p", { className: "font-medium", children: t("staff.leaveRequests.messages.contextTitle", "Linked leave request") }),
|
|
80
|
-
memberLabel ? /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
81
|
-
t("staff.leaveRequests.detail.member", "Team member"),
|
|
82
|
-
": ",
|
|
83
|
-
memberLabel
|
|
84
|
-
] }) : null,
|
|
85
|
-
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
86
|
-
t("staff.leaveRequests.detail.dates", "Dates"),
|
|
87
|
-
": ",
|
|
88
|
-
dateSummary
|
|
89
|
-
] })
|
|
90
|
-
] }), [dateSummary, memberLabel, t]);
|
|
91
76
|
const handleSubmit = React.useCallback(async (values) => {
|
|
92
77
|
if (!record?.id) return;
|
|
93
78
|
const payload = buildLeaveRequestPayload(values, { id: record.id });
|
|
@@ -137,8 +122,14 @@ function StaffMyLeaveRequestDetailPage({ params }) {
|
|
|
137
122
|
entityType: "leave_request",
|
|
138
123
|
entityId: record.id,
|
|
139
124
|
sourceEntityType: "staff:leave_request",
|
|
140
|
-
sourceEntityId: record.id
|
|
125
|
+
sourceEntityId: record.id,
|
|
126
|
+
previewData: {
|
|
127
|
+
title: memberLabel || t("staff.leaveRequests.messages.contextTitle", "Linked leave request"),
|
|
128
|
+
subtitle: dateSummary || void 0,
|
|
129
|
+
status: record?.status ?? void 0
|
|
130
|
+
}
|
|
141
131
|
},
|
|
132
|
+
viewHref: `/backend/staff/leave-requests/${record.id}`,
|
|
142
133
|
lockedType: "staff.leave_request_approval",
|
|
143
134
|
requiredActionConfig: {
|
|
144
135
|
mode: "required",
|
|
@@ -151,21 +142,7 @@ function StaffMyLeaveRequestDetailPage({ params }) {
|
|
|
151
142
|
type: "staff.leave_request_approval",
|
|
152
143
|
subject: t("staff.leaveRequests.messages.compose.subject", "Leave request approval needed"),
|
|
153
144
|
body: t("staff.leaveRequests.messages.compose.body", "Please review this leave request and take action.")
|
|
154
|
-
}
|
|
155
|
-
contextPreview: messageContextPreview,
|
|
156
|
-
renderTrigger: ({ openComposer, disabled }) => /* @__PURE__ */ jsx(
|
|
157
|
-
Button,
|
|
158
|
-
{
|
|
159
|
-
type: "button",
|
|
160
|
-
size: "icon",
|
|
161
|
-
variant: "outline",
|
|
162
|
-
onClick: openComposer,
|
|
163
|
-
disabled,
|
|
164
|
-
"aria-label": t("staff.leaveRequests.messages.compose.action", "Send for review"),
|
|
165
|
-
title: t("staff.leaveRequests.messages.compose.action", "Send for review"),
|
|
166
|
-
children: /* @__PURE__ */ jsx(Leaf, { className: "h-4 w-4" })
|
|
167
|
-
}
|
|
168
|
-
)
|
|
145
|
+
}
|
|
169
146
|
}
|
|
170
147
|
) : null
|
|
171
148
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/staff/backend/staff/my-leave-requests/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Leaf } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { updateCrud } 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 { LeaveRequestForm, buildLeaveRequestPayload, type LeaveRequestFormValues } from '@open-mercato/core/modules/staff/components/LeaveRequestForm'\n\ntype LeaveRequestRecord = {\n id: string\n member?: { id?: string; displayName?: string }\n memberId?: string | null\n member_id?: string | null\n startDate?: string | null\n start_date?: string | null\n endDate?: string | null\n end_date?: string | null\n timezone?: string | null\n status?: 'pending' | 'approved' | 'rejected'\n unavailabilityReasonEntryId?: string | null\n unavailability_reason_entry_id?: string | null\n unavailabilityReasonValue?: string | null\n unavailability_reason_value?: string | null\n note?: string | null\n decisionComment?: string | null\n decision_comment?: string | null\n decidedAt?: string | null\n decided_at?: string | null\n} & Record<string, unknown>\n\ntype LeaveRequestsResponse = {\n items?: LeaveRequestRecord[]\n}\n\nexport default function StaffMyLeaveRequestDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [record, setRecord] = React.useState<LeaveRequestRecord | null>(null)\n\n React.useEffect(() => {\n if (!id) {\n setError(t('staff.leaveRequests.errors.notFound', 'Leave request not found.'))\n setIsLoading(false)\n return\n }\n const requestId = id\n let cancelled = false\n async function load() {\n setIsLoading(true)\n setError(null)\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: requestId })\n const payload = await readApiResultOrThrow<LeaveRequestsResponse>(\n `/api/staff/leave-requests?${params.toString()}`,\n undefined,\n { errorMessage: t('staff.leaveRequests.errors.load', 'Failed to load leave request.') },\n )\n const entry = Array.isArray(payload.items) ? payload.items[0] : null\n if (!entry) throw new Error(t('staff.leaveRequests.errors.notFound', 'Leave request not found.'))\n if (!cancelled) {\n setRecord(entry)\n }\n } catch (err) {\n if (!cancelled) {\n const message = err instanceof Error ? err.message : t('staff.leaveRequests.errors.load', 'Failed to load leave request.')\n setError(message)\n setRecord(null)\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n void load()\n return () => { cancelled = true }\n }, [id, t])\n\n const status = record?.status ?? 'pending'\n const memberLabel = record?.member?.displayName ?? null\n const initialValues = React.useMemo<LeaveRequestFormValues>(() => ({\n id: record?.id,\n memberId: record?.memberId ?? record?.member_id ?? null,\n memberLabel,\n startDate: record?.startDate ?? record?.start_date ?? null,\n endDate: record?.endDate ?? record?.end_date ?? null,\n timezone: record?.timezone ?? null,\n unavailabilityReasonEntryId: record?.unavailabilityReasonEntryId ?? record?.unavailability_reason_entry_id ?? null,\n unavailabilityReasonValue: record?.unavailabilityReasonValue ?? record?.unavailability_reason_value ?? null,\n note: record?.note ?? null,\n }), [record, memberLabel])\n const dateSummary = formatDateRange(\n record?.startDate ?? record?.start_date ?? null,\n record?.endDate ?? record?.end_date ?? null,\n )\n const messageContextPreview = React.useMemo(() => (\n <div className=\"space-y-1\">\n <p className=\"font-medium\">{t('staff.leaveRequests.messages.contextTitle', 'Linked leave request')}</p>\n {memberLabel ? (\n <p className=\"text-xs text-muted-foreground\">\n {t('staff.leaveRequests.detail.member', 'Team member')}: {memberLabel}\n </p>\n ) : null}\n <p className=\"text-xs text-muted-foreground\">\n {t('staff.leaveRequests.detail.dates', 'Dates')}: {dateSummary}\n </p>\n </div>\n ), [dateSummary, memberLabel, t])\n\n const handleSubmit = React.useCallback(async (values: LeaveRequestFormValues) => {\n if (!record?.id) return\n const payload = buildLeaveRequestPayload(values, { id: record.id })\n await updateCrud('staff/leave-requests', payload, {\n errorMessage: t('staff.leaveRequests.form.errors.update', 'Failed to update leave request.'),\n })\n flash(t('staff.leaveRequests.form.flash.updated', 'Leave request updated.'), 'success')\n router.push('/backend/staff/my-leave-requests')\n }, [record?.id, router, t])\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('staff.leaveRequests.form.loading', 'Loading leave request...')} />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !record) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage label={error ?? t('staff.leaveRequests.errors.load', 'Failed to load leave request.')} />\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"mb-6 space-y-2 rounded-lg border bg-card p-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Badge variant={resolveStatusVariant(status)}>\n {t(`staff.leaveRequests.status.${status}`, status)}\n </Badge>\n {record.decided_at || record.decidedAt ? (\n <span className=\"text-xs text-muted-foreground\">\n {t('staff.leaveRequests.decision.at', 'Decision at')} {formatDateLabel(record.decidedAt ?? record.decided_at ?? null)}\n </span>\n ) : null}\n </div>\n {record.decisionComment || record.decision_comment ? (\n <div className=\"text-sm text-muted-foreground\">\n <div className=\"font-medium text-foreground\">{t('staff.leaveRequests.decision.comment', 'Decision comment')}</div>\n <p>{record.decisionComment ?? record.decision_comment}</p>\n </div>\n ) : null}\n </div>\n\n {status === 'pending' ? (\n <LeaveRequestForm\n title={t('staff.leaveRequests.form.editTitle', 'Leave request')}\n submitLabel={t('staff.leaveRequests.form.actions.save', 'Save')}\n backHref=\"/backend/staff/my-leave-requests\"\n cancelHref=\"/backend/staff/my-leave-requests\"\n initialValues={initialValues}\n onSubmit={handleSubmit}\n allowMemberSelect={false}\n memberLabel={memberLabel}\n extraActions={record.id ? (\n <SendObjectMessageDialog\n object={{\n entityModule: 'staff',\n entityType: 'leave_request',\n entityId: record.id,\n sourceEntityType: 'staff:leave_request',\n sourceEntityId: record.id,\n }}\n lockedType=\"staff.leave_request_approval\"\n requiredActionConfig={{\n mode: 'required',\n options: [\n { id: 'approve', label: t('staff.notifications.leaveRequest.actions.approve', 'Approve') },\n { id: 'reject', label: t('staff.notifications.leaveRequest.actions.reject', 'Reject') },\n ],\n }}\n defaultValues={{\n type: 'staff.leave_request_approval',\n subject: t('staff.leaveRequests.messages.compose.subject', 'Leave request approval needed'),\n body: t('staff.leaveRequests.messages.compose.body', 'Please review this leave request and take action.'),\n }}\n contextPreview={messageContextPreview}\n renderTrigger={({ openComposer, disabled }) => (\n <Button\n type=\"button\"\n size=\"icon\"\n variant=\"outline\"\n onClick={openComposer}\n disabled={disabled}\n aria-label={t('staff.leaveRequests.messages.compose.action', 'Send for review')}\n title={t('staff.leaveRequests.messages.compose.action', 'Send for review')}\n >\n <Leaf className=\"h-4 w-4\" />\n </Button>\n )}\n />\n ) : null}\n />\n ) : (\n <div className=\"rounded-lg border bg-card p-4 text-sm text-muted-foreground\">\n <div className=\"font-medium text-foreground\">{t('staff.leaveRequests.detail.summary', 'Request details')}</div>\n <p>{memberLabel ? t('staff.leaveRequests.detail.member', 'Team member') + `: ${memberLabel}` : null}</p>\n <p>{t('staff.leaveRequests.detail.dates', 'Dates')}: {formatDateRange(record.startDate ?? record.start_date ?? null, record.endDate ?? record.end_date ?? null)}</p>\n {record.unavailabilityReasonValue || record.unavailability_reason_value ? (\n <p>{t('staff.leaveRequests.detail.reason', 'Reason')}: {record.unavailabilityReasonValue ?? record.unavailability_reason_value}</p>\n ) : null}\n {record.note ? <p>{t('staff.leaveRequests.detail.note', 'Note')}: {record.note}</p> : null}\n </div>\n )}\n </PageBody>\n </Page>\n )\n}\n\nfunction resolveStatusVariant(status: 'pending' | 'approved' | 'rejected') {\n if (status === 'approved') return 'default'\n if (status === 'rejected') return 'destructive'\n return 'secondary'\n}\n\nfunction formatDateLabel(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toLocaleDateString()\n}\n\nfunction formatDateRange(start?: string | null, end?: string | null): string {\n const startLabel = formatDateLabel(start)\n const endLabel = formatDateLabel(end)\n if (startLabel && endLabel) return `${startLabel} -> ${endLabel}`\n return startLabel || endLabel || '-'\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Send } from 'lucide-react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { LoadingMessage, ErrorMessage } from '@open-mercato/ui/backend/detail'\nimport { SendObjectMessageDialog } from '@open-mercato/ui/backend/messages'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { updateCrud } 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 { LeaveRequestForm, buildLeaveRequestPayload, type LeaveRequestFormValues } from '@open-mercato/core/modules/staff/components/LeaveRequestForm'\n\ntype LeaveRequestRecord = {\n id: string\n member?: { id?: string; displayName?: string }\n memberId?: string | null\n member_id?: string | null\n startDate?: string | null\n start_date?: string | null\n endDate?: string | null\n end_date?: string | null\n timezone?: string | null\n status?: 'pending' | 'approved' | 'rejected'\n unavailabilityReasonEntryId?: string | null\n unavailability_reason_entry_id?: string | null\n unavailabilityReasonValue?: string | null\n unavailability_reason_value?: string | null\n note?: string | null\n decisionComment?: string | null\n decision_comment?: string | null\n decidedAt?: string | null\n decided_at?: string | null\n} & Record<string, unknown>\n\ntype LeaveRequestsResponse = {\n items?: LeaveRequestRecord[]\n}\n\nexport default function StaffMyLeaveRequestDetailPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const router = useRouter()\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [record, setRecord] = React.useState<LeaveRequestRecord | null>(null)\n\n React.useEffect(() => {\n if (!id) {\n setError(t('staff.leaveRequests.errors.notFound', 'Leave request not found.'))\n setIsLoading(false)\n return\n }\n const requestId = id\n let cancelled = false\n async function load() {\n setIsLoading(true)\n setError(null)\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '1', ids: requestId })\n const payload = await readApiResultOrThrow<LeaveRequestsResponse>(\n `/api/staff/leave-requests?${params.toString()}`,\n undefined,\n { errorMessage: t('staff.leaveRequests.errors.load', 'Failed to load leave request.') },\n )\n const entry = Array.isArray(payload.items) ? payload.items[0] : null\n if (!entry) throw new Error(t('staff.leaveRequests.errors.notFound', 'Leave request not found.'))\n if (!cancelled) {\n setRecord(entry)\n }\n } catch (err) {\n if (!cancelled) {\n const message = err instanceof Error ? err.message : t('staff.leaveRequests.errors.load', 'Failed to load leave request.')\n setError(message)\n setRecord(null)\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n void load()\n return () => { cancelled = true }\n }, [id, t])\n\n const status = record?.status ?? 'pending'\n const memberLabel = record?.member?.displayName ?? null\n const initialValues = React.useMemo<LeaveRequestFormValues>(() => ({\n id: record?.id,\n memberId: record?.memberId ?? record?.member_id ?? null,\n memberLabel,\n startDate: record?.startDate ?? record?.start_date ?? null,\n endDate: record?.endDate ?? record?.end_date ?? null,\n timezone: record?.timezone ?? null,\n unavailabilityReasonEntryId: record?.unavailabilityReasonEntryId ?? record?.unavailability_reason_entry_id ?? null,\n unavailabilityReasonValue: record?.unavailabilityReasonValue ?? record?.unavailability_reason_value ?? null,\n note: record?.note ?? null,\n }), [record, memberLabel])\n const dateSummary = formatDateRange(\n record?.startDate ?? record?.start_date ?? null,\n record?.endDate ?? record?.end_date ?? null,\n )\nconst handleSubmit = React.useCallback(async (values: LeaveRequestFormValues) => {\n if (!record?.id) return\n const payload = buildLeaveRequestPayload(values, { id: record.id })\n await updateCrud('staff/leave-requests', payload, {\n errorMessage: t('staff.leaveRequests.form.errors.update', 'Failed to update leave request.'),\n })\n flash(t('staff.leaveRequests.form.flash.updated', 'Leave request updated.'), 'success')\n router.push('/backend/staff/my-leave-requests')\n }, [record?.id, router, t])\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <LoadingMessage label={t('staff.leaveRequests.form.loading', 'Loading leave request...')} />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !record) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage label={error ?? t('staff.leaveRequests.errors.load', 'Failed to load leave request.')} />\n </PageBody>\n </Page>\n )\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"mb-6 space-y-2 rounded-lg border bg-card p-4\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <Badge variant={resolveStatusVariant(status)}>\n {t(`staff.leaveRequests.status.${status}`, status)}\n </Badge>\n {record.decided_at || record.decidedAt ? (\n <span className=\"text-xs text-muted-foreground\">\n {t('staff.leaveRequests.decision.at', 'Decision at')} {formatDateLabel(record.decidedAt ?? record.decided_at ?? null)}\n </span>\n ) : null}\n </div>\n {record.decisionComment || record.decision_comment ? (\n <div className=\"text-sm text-muted-foreground\">\n <div className=\"font-medium text-foreground\">{t('staff.leaveRequests.decision.comment', 'Decision comment')}</div>\n <p>{record.decisionComment ?? record.decision_comment}</p>\n </div>\n ) : null}\n </div>\n\n {status === 'pending' ? (\n <LeaveRequestForm\n title={t('staff.leaveRequests.form.editTitle', 'Leave request')}\n submitLabel={t('staff.leaveRequests.form.actions.save', 'Save')}\n backHref=\"/backend/staff/my-leave-requests\"\n cancelHref=\"/backend/staff/my-leave-requests\"\n initialValues={initialValues}\n onSubmit={handleSubmit}\n allowMemberSelect={false}\n memberLabel={memberLabel}\n extraActions={record.id ? (\n <SendObjectMessageDialog\n object={{\n entityModule: 'staff',\n entityType: 'leave_request',\n entityId: record.id,\n sourceEntityType: 'staff:leave_request',\n sourceEntityId: record.id,\n previewData: {\n title: memberLabel || t('staff.leaveRequests.messages.contextTitle', 'Linked leave request'),\n subtitle: dateSummary || undefined,\n status: record?.status ?? undefined,\n },\n }}\n viewHref={`/backend/staff/leave-requests/${record.id}`}\n lockedType=\"staff.leave_request_approval\"\n requiredActionConfig={{\n mode: 'required',\n options: [\n { id: 'approve', label: t('staff.notifications.leaveRequest.actions.approve', 'Approve') },\n { id: 'reject', label: t('staff.notifications.leaveRequest.actions.reject', 'Reject') },\n ],\n }}\n defaultValues={{\n type: 'staff.leave_request_approval',\n subject: t('staff.leaveRequests.messages.compose.subject', 'Leave request approval needed'),\n body: t('staff.leaveRequests.messages.compose.body', 'Please review this leave request and take action.'),\n }}\n />\n ) : null}\n />\n ) : (\n <div className=\"rounded-lg border bg-card p-4 text-sm text-muted-foreground\">\n <div className=\"font-medium text-foreground\">{t('staff.leaveRequests.detail.summary', 'Request details')}</div>\n <p>{memberLabel ? t('staff.leaveRequests.detail.member', 'Team member') + `: ${memberLabel}` : null}</p>\n <p>{t('staff.leaveRequests.detail.dates', 'Dates')}: {formatDateRange(record.startDate ?? record.start_date ?? null, record.endDate ?? record.end_date ?? null)}</p>\n {record.unavailabilityReasonValue || record.unavailability_reason_value ? (\n <p>{t('staff.leaveRequests.detail.reason', 'Reason')}: {record.unavailabilityReasonValue ?? record.unavailability_reason_value}</p>\n ) : null}\n {record.note ? <p>{t('staff.leaveRequests.detail.note', 'Note')}: {record.note}</p> : null}\n </div>\n )}\n </PageBody>\n </Page>\n )\n}\n\nfunction resolveStatusVariant(status: 'pending' | 'approved' | 'rejected') {\n if (status === 'approved') return 'default'\n if (status === 'rejected') return 'destructive'\n return 'secondary'\n}\n\nfunction formatDateLabel(value?: string | null): string {\n if (!value) return ''\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return value\n return date.toLocaleDateString()\n}\n\nfunction formatDateRange(start?: string | null, end?: string | null): string {\n const startLabel = formatDateLabel(start)\n const endLabel = formatDateLabel(end)\n if (startLabel && endLabel) return `${startLabel} -> ${endLabel}`\n return startLabel || endLabel || '-'\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["params"]
|
|
7
7
|
}
|
|
@@ -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": "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",
|
|
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
|
}
|