@open-mercato/core 0.4.6-develop-f7d3079656 → 0.4.6-develop-0861f05ea9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +17 -154
  2. package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +3 -3
  3. package/dist/modules/currencies/backend/exchange-rates/create/page.js +14 -152
  4. package/dist/modules/currencies/backend/exchange-rates/create/page.js.map +2 -2
  5. package/dist/modules/currencies/lib/exchangeRateFormConfig.js +167 -0
  6. package/dist/modules/currencies/lib/exchangeRateFormConfig.js.map +7 -0
  7. package/dist/modules/customers/api/dashboard/widgets/utils.js +1 -34
  8. package/dist/modules/customers/api/dashboard/widgets/utils.js.map +2 -2
  9. package/dist/modules/customers/commands/activities.js +3 -8
  10. package/dist/modules/customers/commands/activities.js.map +2 -2
  11. package/dist/modules/customers/commands/comments.js +2 -8
  12. package/dist/modules/customers/commands/comments.js.map +2 -2
  13. package/dist/modules/dashboards/lib/widgetScope.js +38 -0
  14. package/dist/modules/dashboards/lib/widgetScope.js.map +7 -0
  15. package/dist/modules/entities/lib/makeActivityRoute.js +265 -0
  16. package/dist/modules/entities/lib/makeActivityRoute.js.map +7 -0
  17. package/dist/modules/resources/api/activities.js +24 -232
  18. package/dist/modules/resources/api/activities.js.map +2 -2
  19. package/dist/modules/resources/commands/activities.js +3 -8
  20. package/dist/modules/resources/commands/activities.js.map +2 -2
  21. package/dist/modules/resources/commands/comments.js +2 -8
  22. package/dist/modules/resources/commands/comments.js.map +2 -2
  23. package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js +27 -182
  24. package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js.map +2 -2
  25. package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js +28 -183
  26. package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js.map +2 -2
  27. package/dist/modules/sales/api/order-line-statuses/route.js +15 -194
  28. package/dist/modules/sales/api/order-line-statuses/route.js.map +2 -2
  29. package/dist/modules/sales/api/order-lines/route.js +15 -281
  30. package/dist/modules/sales/api/order-lines/route.js.map +2 -2
  31. package/dist/modules/sales/api/order-statuses/route.js +15 -194
  32. package/dist/modules/sales/api/order-statuses/route.js.map +2 -2
  33. package/dist/modules/sales/api/payment-statuses/route.js +15 -194
  34. package/dist/modules/sales/api/payment-statuses/route.js.map +2 -2
  35. package/dist/modules/sales/api/quote-lines/route.js +15 -279
  36. package/dist/modules/sales/api/quote-lines/route.js.map +2 -2
  37. package/dist/modules/sales/api/shipment-statuses/route.js +15 -194
  38. package/dist/modules/sales/api/shipment-statuses/route.js.map +2 -2
  39. package/dist/modules/sales/components/PaymentMethodsSettings.js +3 -84
  40. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  41. package/dist/modules/sales/components/ProviderFieldInput.js +86 -0
  42. package/dist/modules/sales/components/ProviderFieldInput.js.map +7 -0
  43. package/dist/modules/sales/components/ShippingMethodsSettings.js +3 -82
  44. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  45. package/dist/modules/sales/lib/makeSalesLineRoute.js +308 -0
  46. package/dist/modules/sales/lib/makeSalesLineRoute.js.map +7 -0
  47. package/dist/modules/sales/lib/makeStatusDictionaryRoute.js +206 -0
  48. package/dist/modules/sales/lib/makeStatusDictionaryRoute.js.map +7 -0
  49. package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js +178 -0
  50. package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js.map +7 -0
  51. package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js +1 -39
  52. package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js.map +2 -2
  53. package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js +1 -39
  54. package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js.map +2 -2
  55. package/dist/modules/sales/widgets/dashboard/shared.js +46 -0
  56. package/dist/modules/sales/widgets/dashboard/shared.js.map +7 -0
  57. package/dist/modules/staff/api/activities.js +24 -232
  58. package/dist/modules/staff/api/activities.js.map +2 -2
  59. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +14 -34
  60. package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
  61. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +15 -34
  62. package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
  63. package/dist/modules/staff/commands/activities.js +3 -8
  64. package/dist/modules/staff/commands/activities.js.map +2 -2
  65. package/dist/modules/staff/commands/comments.js +2 -8
  66. package/dist/modules/staff/commands/comments.js.map +2 -2
  67. package/dist/modules/staff/lib/leaveRequestHelpers.js +41 -0
  68. package/dist/modules/staff/lib/leaveRequestHelpers.js.map +7 -0
  69. package/package.json +2 -2
  70. package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +20 -180
  71. package/src/modules/currencies/backend/exchange-rates/create/page.tsx +16 -175
  72. package/src/modules/currencies/lib/exchangeRateFormConfig.ts +200 -0
  73. package/src/modules/customers/api/dashboard/widgets/utils.ts +1 -53
  74. package/src/modules/customers/commands/activities.ts +2 -8
  75. package/src/modules/customers/commands/comments.ts +2 -8
  76. package/src/modules/dashboards/i18n/de.json +3 -0
  77. package/src/modules/dashboards/i18n/en.json +3 -0
  78. package/src/modules/dashboards/i18n/es.json +3 -0
  79. package/src/modules/dashboards/i18n/pl.json +3 -0
  80. package/src/modules/dashboards/lib/widgetScope.ts +53 -0
  81. package/src/modules/entities/lib/makeActivityRoute.ts +327 -0
  82. package/src/modules/resources/api/activities.ts +25 -269
  83. package/src/modules/resources/commands/activities.ts +2 -7
  84. package/src/modules/resources/commands/comments.ts +2 -8
  85. package/src/modules/sales/api/dashboard/widgets/new-orders/route.ts +29 -244
  86. package/src/modules/sales/api/dashboard/widgets/new-quotes/route.ts +30 -245
  87. package/src/modules/sales/api/order-line-statuses/route.ts +16 -209
  88. package/src/modules/sales/api/order-lines/route.ts +16 -300
  89. package/src/modules/sales/api/order-statuses/route.ts +16 -209
  90. package/src/modules/sales/api/payment-statuses/route.ts +16 -209
  91. package/src/modules/sales/api/quote-lines/route.ts +16 -298
  92. package/src/modules/sales/api/shipment-statuses/route.ts +16 -209
  93. package/src/modules/sales/components/PaymentMethodsSettings.tsx +3 -88
  94. package/src/modules/sales/components/ProviderFieldInput.tsx +85 -0
  95. package/src/modules/sales/components/ShippingMethodsSettings.tsx +3 -86
  96. package/src/modules/sales/lib/makeSalesLineRoute.ts +345 -0
  97. package/src/modules/sales/lib/makeStatusDictionaryRoute.ts +229 -0
  98. package/src/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.ts +247 -0
  99. package/src/modules/sales/widgets/dashboard/new-orders/widget.client.tsx +7 -50
  100. package/src/modules/sales/widgets/dashboard/new-quotes/widget.client.tsx +7 -49
  101. package/src/modules/sales/widgets/dashboard/shared.ts +44 -0
  102. package/src/modules/staff/api/activities.ts +25 -269
  103. package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +15 -69
  104. package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +16 -65
  105. package/src/modules/staff/commands/activities.ts +2 -7
  106. package/src/modules/staff/commands/comments.ts +2 -8
  107. package/src/modules/staff/lib/leaveRequestHelpers.ts +78 -0
@@ -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 { 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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",
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 { 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'\nimport { type LeaveRequestsResponse, type NormalizedLeaveRequest, normalizeLeaveRequest, resolveStatusVariant, formatDateLabel, formatDateRange } from '../../../../lib/leaveRequestHelpers'\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<NormalizedLeaveRequest | 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(normalizeLeaveRequest(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 ?? null,\n memberLabel,\n startDate: record?.startDate ?? null,\n endDate: record?.endDate ?? null,\n timezone: record?.timezone ?? null,\n unavailabilityReasonEntryId: record?.unavailabilityReasonEntryId ?? null,\n unavailabilityReasonValue: record?.unavailabilityReasonValue ?? null,\n note: record?.note ?? null,\n }), [record, memberLabel])\n const dateSummary = formatDateRange(record?.startDate, record?.endDate)\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.decidedAt ? (\n <span className=\"text-xs text-muted-foreground\">\n {t('staff.leaveRequests.decision.at', 'Decision at')} {formatDateLabel(record.decidedAt)}\n </span>\n ) : null}\n </div>\n {record.decisionComment ? (\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}</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.endDate)}</p>\n {record.unavailabilityReasonValue ? (\n <p>{t('staff.leaveRequests.detail.reason', 'Reason')}: {record.unavailabilityReasonValue}</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"],
5
+ "mappings": "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",
6
6
  "names": ["params"]
7
7
  }
@@ -5,7 +5,8 @@ import {
5
5
  buildChanges,
6
6
  requireId,
7
7
  parseWithCustomFields,
8
- setCustomFieldsIfAny
8
+ setCustomFieldsIfAny,
9
+ normalizeAuthorUserId
9
10
  } from "@open-mercato/shared/lib/commands/helpers";
10
11
  import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
11
12
  import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
@@ -69,13 +70,7 @@ const createActivityCommand = {
69
70
  const { parsed, custom } = parseWithCustomFields(staffTeamMemberActivityCreateSchema, rawInput);
70
71
  ensureTenantScope(ctx, parsed.tenantId);
71
72
  ensureOrganizationScope(ctx, parsed.organizationId);
72
- const authSub = ctx.auth?.isApiKey ? null : ctx.auth?.sub ?? null;
73
- const normalizedAuthor = (() => {
74
- if (parsed.authorUserId) return parsed.authorUserId;
75
- if (!authSub) return null;
76
- const uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/;
77
- return uuidRegex.test(authSub) ? authSub : null;
78
- })();
73
+ const normalizedAuthor = normalizeAuthorUserId(parsed.authorUserId, ctx.auth);
79
74
  const em = ctx.container.resolve("em").fork();
80
75
  const member = await requireTeamMember(em, parsed.entityId, "Team member not found");
81
76
  ensureTenantScope(ctx, member.tenantId);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/staff/commands/activities.ts"],
4
- "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport {\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n buildChanges,\n requireId,\n parseWithCustomFields,\n setCustomFieldsIfAny,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTeamMemberActivity } from '../data/entities'\nimport {\n staffTeamMemberActivityCreateSchema,\n staffTeamMemberActivityUpdateSchema,\n type StaffTeamMemberActivityCreateInput,\n type StaffTeamMemberActivityUpdateInput,\n} from '../data/validators'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload, requireTeamMember } from './shared'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n loadCustomFieldSnapshot,\n diffCustomFieldChanges,\n buildCustomFieldResetMap,\n type CustomFieldChangeSet,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\n\nconst activityCrudIndexer: CrudIndexerConfig<StaffTeamMemberActivity> = {\n entityType: E.staff.staff_team_member_activity,\n}\n\ntype ActivitySnapshot = {\n activity: {\n id: string\n organizationId: string\n tenantId: string\n memberId: string\n activityType: string\n subject: string | null\n body: string | null\n occurredAt: Date | null\n authorUserId: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n }\n custom?: Record<string, unknown>\n}\n\ntype ActivityUndoPayload = {\n before?: ActivitySnapshot | null\n after?: ActivitySnapshot | null\n}\n\ntype ActivityChangeMap = Record<string, { from: unknown; to: unknown }> & {\n custom?: CustomFieldChangeSet\n}\n\nasync function loadActivitySnapshot(em: EntityManager, id: string): Promise<ActivitySnapshot | null> {\n const activity = await em.findOne(StaffTeamMemberActivity, { id })\n if (!activity) return null\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.staff.staff_team_member_activity,\n recordId: activity.id,\n tenantId: activity.tenantId,\n organizationId: activity.organizationId,\n })\n return {\n activity: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n memberId: typeof activity.member === 'string' ? activity.member : activity.member.id,\n activityType: activity.activityType,\n subject: activity.subject ?? null,\n body: activity.body ?? null,\n occurredAt: activity.occurredAt ?? null,\n authorUserId: activity.authorUserId ?? null,\n appearanceIcon: activity.appearanceIcon ?? null,\n appearanceColor: activity.appearanceColor ?? null,\n },\n custom,\n }\n}\n\nasync function setActivityCustomFields(\n ctx: CommandRuntimeContext,\n activityId: string,\n organizationId: string,\n tenantId: string,\n values: Record<string, unknown>\n) {\n if (!values || !Object.keys(values).length) return\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member_activity,\n recordId: activityId,\n organizationId,\n tenantId,\n values,\n notify: false,\n })\n}\n\nconst createActivityCommand: CommandHandler<\n StaffTeamMemberActivityCreateInput,\n { activityId: string; authorUserId: string | null }\n> = {\n id: 'staff.team-member-activities.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberActivityCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const authSub = ctx.auth?.isApiKey ? null : ctx.auth?.sub ?? null\n const normalizedAuthor = (() => {\n if (parsed.authorUserId) return parsed.authorUserId\n if (!authSub) return null\n const uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/\n return uuidRegex.test(authSub) ? authSub : null\n })()\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(em, parsed.entityId, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const activity = em.create(StaffTeamMemberActivity, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n member,\n activityType: parsed.activityType,\n subject: parsed.subject ?? null,\n body: parsed.body ?? null,\n occurredAt: parsed.occurredAt ?? null,\n authorUserId: normalizedAuthor,\n appearanceIcon: parsed.appearanceIcon ?? null,\n appearanceColor: parsed.appearanceColor ?? null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(activity)\n await em.flush()\n\n await setActivityCustomFields(ctx, activity.id, parsed.organizationId, parsed.tenantId, custom)\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n\n return { activityId: activity.id, authorUserId: activity.authorUserId ?? null }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadActivitySnapshot(em, result.activityId)\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as ActivitySnapshot | undefined\n return {\n actionLabel: translate('staff.audit.teamMemberActivities.create', 'Create activity'),\n resourceKind: 'staff.team_member_activity',\n resourceId: result.activityId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: snapshot?.activity?.memberId ?? null,\n tenantId: snapshot?.activity.tenantId ?? null,\n organizationId: snapshot?.activity.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n } satisfies ActivityUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const activityId = logEntry?.resourceId ?? null\n if (!activityId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(StaffTeamMemberActivity, { id: activityId })\n if (existing) {\n em.remove(existing)\n await em.flush()\n }\n },\n}\n\nconst updateActivityCommand: CommandHandler<StaffTeamMemberActivityUpdateInput, { activityId: string }> = {\n id: 'staff.team-member-activities.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTeamMemberActivityUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadActivitySnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberActivityUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const activity = await em.findOne(StaffTeamMemberActivity, { id: parsed.id })\n if (!activity) throw new CrudHttpError(404, { error: 'Activity not found' })\n ensureTenantScope(ctx, activity.tenantId)\n ensureOrganizationScope(ctx, activity.organizationId)\n\n if (parsed.entityId !== undefined) {\n const member = await requireTeamMember(em, parsed.entityId, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n activity.member = member\n }\n if (parsed.activityType !== undefined) activity.activityType = parsed.activityType\n if (parsed.subject !== undefined) activity.subject = parsed.subject ?? null\n if (parsed.body !== undefined) activity.body = parsed.body ?? null\n if (parsed.occurredAt !== undefined) activity.occurredAt = parsed.occurredAt ?? null\n if (parsed.authorUserId !== undefined) activity.authorUserId = parsed.authorUserId ?? null\n if (parsed.appearanceIcon !== undefined) activity.appearanceIcon = parsed.appearanceIcon ?? null\n if (parsed.appearanceColor !== undefined) activity.appearanceColor = parsed.appearanceColor ?? null\n\n await em.flush()\n\n await setActivityCustomFields(ctx, activity.id, activity.organizationId, activity.tenantId, custom)\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n\n return { activityId: activity.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadActivitySnapshot(em, result.activityId)\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as ActivitySnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as ActivitySnapshot | undefined\n const changeKeys: readonly string[] = [\n 'memberId',\n 'activityType',\n 'subject',\n 'body',\n 'occurredAt',\n 'authorUserId',\n 'appearanceIcon',\n 'appearanceColor',\n ]\n const changes: ActivityChangeMap =\n afterSnapshot && before\n ? buildChanges(\n before.activity as Record<string, unknown>,\n afterSnapshot.activity as Record<string, unknown>,\n changeKeys\n )\n : {}\n const customChanges = diffCustomFieldChanges(before.custom, afterSnapshot?.custom)\n if (Object.keys(customChanges).length) changes.custom = customChanges\n return {\n actionLabel: translate('staff.audit.teamMemberActivities.update', 'Update activity'),\n resourceKind: 'staff.team_member_activity',\n resourceId: before.activity.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.activity.memberId ?? null,\n tenantId: before.activity.tenantId,\n organizationId: before.activity.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies ActivityUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ActivityUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let activity = await em.findOne(StaffTeamMemberActivity, { id: before.activity.id })\n const member = await requireTeamMember(em, before.activity.memberId, 'Team member not found')\n\n if (!activity) {\n activity = em.create(StaffTeamMemberActivity, {\n id: before.activity.id,\n organizationId: before.activity.organizationId,\n tenantId: before.activity.tenantId,\n member,\n activityType: before.activity.activityType,\n subject: before.activity.subject,\n body: before.activity.body,\n occurredAt: before.activity.occurredAt ?? null,\n authorUserId: before.activity.authorUserId,\n appearanceIcon: before.activity.appearanceIcon,\n appearanceColor: before.activity.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(activity)\n } else {\n activity.member = member\n activity.activityType = before.activity.activityType\n activity.subject = before.activity.subject\n activity.body = before.activity.body\n activity.occurredAt = before.activity.occurredAt ?? null\n activity.authorUserId = before.activity.authorUserId\n activity.appearanceIcon = before.activity.appearanceIcon\n activity.appearanceColor = before.activity.appearanceColor\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member_activity,\n recordId: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n}\n\nconst deleteActivityCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { activityId: string }> =\n {\n id: 'staff.team-member-activities.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Activity id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadActivitySnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Activity id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const activity = await em.findOne(StaffTeamMemberActivity, { id })\n if (!activity) throw new CrudHttpError(404, { error: 'Activity not found' })\n ensureTenantScope(ctx, activity.tenantId)\n ensureOrganizationScope(ctx, activity.organizationId)\n em.remove(activity)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n return { activityId: activity.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as ActivitySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMemberActivities.delete', 'Delete activity'),\n resourceKind: 'staff.team_member_activity',\n resourceId: before.activity.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.activity.memberId ?? null,\n tenantId: before.activity.tenantId,\n organizationId: before.activity.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies ActivityUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ActivityUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(em, before.activity.memberId, 'Team member not found')\n let activity = await em.findOne(StaffTeamMemberActivity, { id: before.activity.id })\n if (!activity) {\n activity = em.create(StaffTeamMemberActivity, {\n id: before.activity.id,\n organizationId: before.activity.organizationId,\n tenantId: before.activity.tenantId,\n member,\n activityType: before.activity.activityType,\n subject: before.activity.subject,\n body: before.activity.body,\n occurredAt: before.activity.occurredAt ?? null,\n authorUserId: before.activity.authorUserId,\n appearanceIcon: before.activity.appearanceIcon,\n appearanceColor: before.activity.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(activity)\n } else {\n activity.member = member\n activity.activityType = before.activity.activityType\n activity.subject = before.activity.subject\n activity.body = before.activity.body\n activity.occurredAt = before.activity.occurredAt ?? null\n activity.authorUserId = before.activity.authorUserId\n activity.appearanceIcon = before.activity.appearanceIcon\n activity.appearanceColor = before.activity.appearanceColor\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member_activity,\n recordId: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n }\n\nregisterCommand(createActivityCommand)\nregisterCommand(updateActivityCommand)\nregisterCommand(deleteActivityCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport {\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n buildChanges,\n requireId,\n parseWithCustomFields,\n setCustomFieldsIfAny,\n normalizeAuthorUserId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTeamMemberActivity } from '../data/entities'\nimport {\n staffTeamMemberActivityCreateSchema,\n staffTeamMemberActivityUpdateSchema,\n type StaffTeamMemberActivityCreateInput,\n type StaffTeamMemberActivityUpdateInput,\n} from '../data/validators'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload, requireTeamMember } from './shared'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n loadCustomFieldSnapshot,\n diffCustomFieldChanges,\n buildCustomFieldResetMap,\n type CustomFieldChangeSet,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\n\nconst activityCrudIndexer: CrudIndexerConfig<StaffTeamMemberActivity> = {\n entityType: E.staff.staff_team_member_activity,\n}\n\ntype ActivitySnapshot = {\n activity: {\n id: string\n organizationId: string\n tenantId: string\n memberId: string\n activityType: string\n subject: string | null\n body: string | null\n occurredAt: Date | null\n authorUserId: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n }\n custom?: Record<string, unknown>\n}\n\ntype ActivityUndoPayload = {\n before?: ActivitySnapshot | null\n after?: ActivitySnapshot | null\n}\n\ntype ActivityChangeMap = Record<string, { from: unknown; to: unknown }> & {\n custom?: CustomFieldChangeSet\n}\n\nasync function loadActivitySnapshot(em: EntityManager, id: string): Promise<ActivitySnapshot | null> {\n const activity = await em.findOne(StaffTeamMemberActivity, { id })\n if (!activity) return null\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.staff.staff_team_member_activity,\n recordId: activity.id,\n tenantId: activity.tenantId,\n organizationId: activity.organizationId,\n })\n return {\n activity: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n memberId: typeof activity.member === 'string' ? activity.member : activity.member.id,\n activityType: activity.activityType,\n subject: activity.subject ?? null,\n body: activity.body ?? null,\n occurredAt: activity.occurredAt ?? null,\n authorUserId: activity.authorUserId ?? null,\n appearanceIcon: activity.appearanceIcon ?? null,\n appearanceColor: activity.appearanceColor ?? null,\n },\n custom,\n }\n}\n\nasync function setActivityCustomFields(\n ctx: CommandRuntimeContext,\n activityId: string,\n organizationId: string,\n tenantId: string,\n values: Record<string, unknown>\n) {\n if (!values || !Object.keys(values).length) return\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member_activity,\n recordId: activityId,\n organizationId,\n tenantId,\n values,\n notify: false,\n })\n}\n\nconst createActivityCommand: CommandHandler<\n StaffTeamMemberActivityCreateInput,\n { activityId: string; authorUserId: string | null }\n> = {\n id: 'staff.team-member-activities.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberActivityCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const normalizedAuthor = normalizeAuthorUserId(parsed.authorUserId, ctx.auth)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(em, parsed.entityId, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const activity = em.create(StaffTeamMemberActivity, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n member,\n activityType: parsed.activityType,\n subject: parsed.subject ?? null,\n body: parsed.body ?? null,\n occurredAt: parsed.occurredAt ?? null,\n authorUserId: normalizedAuthor,\n appearanceIcon: parsed.appearanceIcon ?? null,\n appearanceColor: parsed.appearanceColor ?? null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(activity)\n await em.flush()\n\n await setActivityCustomFields(ctx, activity.id, parsed.organizationId, parsed.tenantId, custom)\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n\n return { activityId: activity.id, authorUserId: activity.authorUserId ?? null }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadActivitySnapshot(em, result.activityId)\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as ActivitySnapshot | undefined\n return {\n actionLabel: translate('staff.audit.teamMemberActivities.create', 'Create activity'),\n resourceKind: 'staff.team_member_activity',\n resourceId: result.activityId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: snapshot?.activity?.memberId ?? null,\n tenantId: snapshot?.activity.tenantId ?? null,\n organizationId: snapshot?.activity.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n } satisfies ActivityUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const activityId = logEntry?.resourceId ?? null\n if (!activityId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(StaffTeamMemberActivity, { id: activityId })\n if (existing) {\n em.remove(existing)\n await em.flush()\n }\n },\n}\n\nconst updateActivityCommand: CommandHandler<StaffTeamMemberActivityUpdateInput, { activityId: string }> = {\n id: 'staff.team-member-activities.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTeamMemberActivityUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadActivitySnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberActivityUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const activity = await em.findOne(StaffTeamMemberActivity, { id: parsed.id })\n if (!activity) throw new CrudHttpError(404, { error: 'Activity not found' })\n ensureTenantScope(ctx, activity.tenantId)\n ensureOrganizationScope(ctx, activity.organizationId)\n\n if (parsed.entityId !== undefined) {\n const member = await requireTeamMember(em, parsed.entityId, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n activity.member = member\n }\n if (parsed.activityType !== undefined) activity.activityType = parsed.activityType\n if (parsed.subject !== undefined) activity.subject = parsed.subject ?? null\n if (parsed.body !== undefined) activity.body = parsed.body ?? null\n if (parsed.occurredAt !== undefined) activity.occurredAt = parsed.occurredAt ?? null\n if (parsed.authorUserId !== undefined) activity.authorUserId = parsed.authorUserId ?? null\n if (parsed.appearanceIcon !== undefined) activity.appearanceIcon = parsed.appearanceIcon ?? null\n if (parsed.appearanceColor !== undefined) activity.appearanceColor = parsed.appearanceColor ?? null\n\n await em.flush()\n\n await setActivityCustomFields(ctx, activity.id, activity.organizationId, activity.tenantId, custom)\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n\n return { activityId: activity.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadActivitySnapshot(em, result.activityId)\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as ActivitySnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as ActivitySnapshot | undefined\n const changeKeys: readonly string[] = [\n 'memberId',\n 'activityType',\n 'subject',\n 'body',\n 'occurredAt',\n 'authorUserId',\n 'appearanceIcon',\n 'appearanceColor',\n ]\n const changes: ActivityChangeMap =\n afterSnapshot && before\n ? buildChanges(\n before.activity as Record<string, unknown>,\n afterSnapshot.activity as Record<string, unknown>,\n changeKeys\n )\n : {}\n const customChanges = diffCustomFieldChanges(before.custom, afterSnapshot?.custom)\n if (Object.keys(customChanges).length) changes.custom = customChanges\n return {\n actionLabel: translate('staff.audit.teamMemberActivities.update', 'Update activity'),\n resourceKind: 'staff.team_member_activity',\n resourceId: before.activity.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.activity.memberId ?? null,\n tenantId: before.activity.tenantId,\n organizationId: before.activity.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies ActivityUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ActivityUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let activity = await em.findOne(StaffTeamMemberActivity, { id: before.activity.id })\n const member = await requireTeamMember(em, before.activity.memberId, 'Team member not found')\n\n if (!activity) {\n activity = em.create(StaffTeamMemberActivity, {\n id: before.activity.id,\n organizationId: before.activity.organizationId,\n tenantId: before.activity.tenantId,\n member,\n activityType: before.activity.activityType,\n subject: before.activity.subject,\n body: before.activity.body,\n occurredAt: before.activity.occurredAt ?? null,\n authorUserId: before.activity.authorUserId,\n appearanceIcon: before.activity.appearanceIcon,\n appearanceColor: before.activity.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(activity)\n } else {\n activity.member = member\n activity.activityType = before.activity.activityType\n activity.subject = before.activity.subject\n activity.body = before.activity.body\n activity.occurredAt = before.activity.occurredAt ?? null\n activity.authorUserId = before.activity.authorUserId\n activity.appearanceIcon = before.activity.appearanceIcon\n activity.appearanceColor = before.activity.appearanceColor\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member_activity,\n recordId: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n}\n\nconst deleteActivityCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { activityId: string }> =\n {\n id: 'staff.team-member-activities.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Activity id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadActivitySnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Activity id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const activity = await em.findOne(StaffTeamMemberActivity, { id })\n if (!activity) throw new CrudHttpError(404, { error: 'Activity not found' })\n ensureTenantScope(ctx, activity.tenantId)\n ensureOrganizationScope(ctx, activity.organizationId)\n em.remove(activity)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n return { activityId: activity.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as ActivitySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMemberActivities.delete', 'Delete activity'),\n resourceKind: 'staff.team_member_activity',\n resourceId: before.activity.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.activity.memberId ?? null,\n tenantId: before.activity.tenantId,\n organizationId: before.activity.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies ActivityUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<ActivityUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(em, before.activity.memberId, 'Team member not found')\n let activity = await em.findOne(StaffTeamMemberActivity, { id: before.activity.id })\n if (!activity) {\n activity = em.create(StaffTeamMemberActivity, {\n id: before.activity.id,\n organizationId: before.activity.organizationId,\n tenantId: before.activity.tenantId,\n member,\n activityType: before.activity.activityType,\n subject: before.activity.subject,\n body: before.activity.body,\n occurredAt: before.activity.occurredAt ?? null,\n authorUserId: before.activity.authorUserId,\n appearanceIcon: before.activity.appearanceIcon,\n appearanceColor: before.activity.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(activity)\n } else {\n activity.member = member\n activity.activityType = before.activity.activityType\n activity.subject = before.activity.subject\n activity.body = before.activity.body\n activity.occurredAt = before.activity.occurredAt ?? null\n activity.authorUserId = before.activity.authorUserId\n activity.appearanceIcon = before.activity.appearanceIcon\n activity.appearanceColor = before.activity.appearanceColor\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: activity,\n identifiers: {\n id: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n },\n indexer: activityCrudIndexer,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member_activity,\n recordId: activity.id,\n organizationId: activity.organizationId,\n tenantId: activity.tenantId,\n values: resetValues,\n notify: false,\n })\n }\n },\n }\n\nregisterCommand(createActivityCommand)\nregisterCommand(updateActivityCommand)\nregisterCommand(deleteActivityCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,5 @@
1
1
  import { registerCommand } from "@open-mercato/shared/lib/commands";
2
- import { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges, requireId } from "@open-mercato/shared/lib/commands/helpers";
2
+ import { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges, requireId, normalizeAuthorUserId } from "@open-mercato/shared/lib/commands/helpers";
3
3
  import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
4
4
  import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
5
5
  import { StaffTeamMemberComment } from "../data/entities.js";
@@ -32,13 +32,7 @@ const createCommentCommand = {
32
32
  const parsed = staffTeamMemberCommentCreateSchema.parse(rawInput);
33
33
  ensureTenantScope(ctx, parsed.tenantId);
34
34
  ensureOrganizationScope(ctx, parsed.organizationId);
35
- const authSub = ctx.auth?.isApiKey ? null : ctx.auth?.sub ?? null;
36
- const normalizedAuthor = (() => {
37
- if (parsed.authorUserId) return parsed.authorUserId;
38
- if (!authSub) return null;
39
- const uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/;
40
- return uuidRegex.test(authSub) ? authSub : null;
41
- })();
35
+ const normalizedAuthor = normalizeAuthorUserId(parsed.authorUserId, ctx.auth);
42
36
  const em = ctx.container.resolve("em").fork();
43
37
  const member = await requireTeamMember(em, parsed.entityId, "Team member not found");
44
38
  ensureTenantScope(ctx, member.tenantId);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/staff/commands/comments.ts"],
4
- "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges, requireId } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTeamMemberComment } from '../data/entities'\nimport {\n staffTeamMemberCommentCreateSchema,\n staffTeamMemberCommentUpdateSchema,\n type StaffTeamMemberCommentCreateInput,\n type StaffTeamMemberCommentUpdateInput,\n} from '../data/validators'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload, requireTeamMember } from './shared'\nimport { E } from '#generated/entities.ids.generated'\n\nconst commentCrudIndexer: CrudIndexerConfig<StaffTeamMemberComment> = {\n entityType: E.staff.staff_team_member_comment,\n}\n\ntype CommentSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n memberId: string\n body: string\n authorUserId: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n}\n\ntype CommentUndoPayload = {\n before?: CommentSnapshot | null\n after?: CommentSnapshot | null\n}\n\nasync function loadCommentSnapshot(em: EntityManager, id: string): Promise<CommentSnapshot | null> {\n const comment = await em.findOne(StaffTeamMemberComment, { id })\n if (!comment) return null\n return {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n memberId: typeof comment.member === 'string' ? comment.member : comment.member.id,\n body: comment.body,\n authorUserId: comment.authorUserId ?? null,\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n }\n}\n\nconst createCommentCommand: CommandHandler<\n StaffTeamMemberCommentCreateInput,\n { commentId: string; authorUserId: string | null }\n> = {\n id: 'staff.team-member-comments.create',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberCommentCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const authSub = ctx.auth?.isApiKey ? null : ctx.auth?.sub ?? null\n const normalizedAuthor = (() => {\n if (parsed.authorUserId) return parsed.authorUserId\n if (!authSub) return null\n const uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/\n return uuidRegex.test(authSub) ? authSub : null\n })()\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(em, parsed.entityId, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const comment = em.create(StaffTeamMemberComment, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n member,\n body: parsed.body,\n authorUserId: normalizedAuthor,\n appearanceIcon: parsed.appearanceIcon ?? null,\n appearanceColor: parsed.appearanceColor ?? null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n\n return { commentId: comment.id, authorUserId: comment.authorUserId ?? null }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadCommentSnapshot(em, result.commentId)\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as CommentSnapshot | undefined\n return {\n actionLabel: translate('staff.audit.teamMemberComments.create', 'Create note'),\n resourceKind: 'staff.team_member_comment',\n resourceId: result.commentId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: snapshot?.memberId ?? null,\n tenantId: snapshot?.tenantId ?? null,\n organizationId: snapshot?.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const commentId = logEntry?.resourceId ?? null\n if (!commentId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(StaffTeamMemberComment, { id: commentId })\n if (existing) {\n em.remove(existing)\n await em.flush()\n }\n },\n}\n\nconst updateCommentCommand: CommandHandler<StaffTeamMemberCommentUpdateInput, { commentId: string }> = {\n id: 'staff.team-member-comments.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTeamMemberCommentUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadCommentSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberCommentUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const comment = await em.findOne(StaffTeamMemberComment, { id: parsed.id })\n if (!comment) throw new CrudHttpError(404, { error: 'Comment not found' })\n ensureTenantScope(ctx, comment.tenantId)\n ensureOrganizationScope(ctx, comment.organizationId)\n\n if (parsed.entityId !== undefined) {\n const member = await requireTeamMember(em, parsed.entityId, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n comment.member = member\n }\n if (parsed.body !== undefined) comment.body = parsed.body\n if (parsed.authorUserId !== undefined) comment.authorUserId = parsed.authorUserId ?? null\n if (parsed.appearanceIcon !== undefined) comment.appearanceIcon = parsed.appearanceIcon ?? null\n if (parsed.appearanceColor !== undefined) comment.appearanceColor = parsed.appearanceColor ?? null\n\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n\n return { commentId: comment.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadCommentSnapshot(em, result.commentId)\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as CommentSnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as CommentSnapshot | undefined\n const changes =\n afterSnapshot && before\n ? buildChanges(\n before as unknown as Record<string, unknown>,\n afterSnapshot as unknown as Record<string, unknown>,\n ['memberId', 'body', 'authorUserId', 'appearanceIcon', 'appearanceColor']\n )\n : {}\n return {\n actionLabel: translate('staff.audit.teamMemberComments.update', 'Update note'),\n resourceKind: 'staff.team_member_comment',\n resourceId: before.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.memberId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CommentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let comment = await em.findOne(StaffTeamMemberComment, { id: before.id })\n const member = await requireTeamMember(em, before.memberId, 'Team member not found')\n\n if (!comment) {\n comment = em.create(StaffTeamMemberComment, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n body: before.body,\n authorUserId: before.authorUserId,\n appearanceIcon: before.appearanceIcon,\n appearanceColor: before.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n } else {\n comment.member = member\n comment.body = before.body\n comment.authorUserId = before.authorUserId\n comment.appearanceIcon = before.appearanceIcon\n comment.appearanceColor = before.appearanceColor\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n },\n}\n\nconst deleteCommentCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { commentId: string }> =\n {\n id: 'staff.team-member-comments.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Comment id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadCommentSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Comment id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const comment = await em.findOne(StaffTeamMemberComment, { id })\n if (!comment) throw new CrudHttpError(404, { error: 'Comment not found' })\n ensureTenantScope(ctx, comment.tenantId)\n ensureOrganizationScope(ctx, comment.organizationId)\n em.remove(comment)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n return { commentId: comment.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CommentSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMemberComments.delete', 'Delete note'),\n resourceKind: 'staff.team_member_comment',\n resourceId: before.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.memberId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CommentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(em, before.memberId, 'Team member not found')\n let comment = await em.findOne(StaffTeamMemberComment, { id: before.id })\n if (!comment) {\n comment = em.create(StaffTeamMemberComment, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n body: before.body,\n authorUserId: before.authorUserId,\n appearanceIcon: before.appearanceIcon,\n appearanceColor: before.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n } else {\n comment.member = member\n comment.body = before.body\n comment.authorUserId = before.authorUserId\n comment.appearanceIcon = before.appearanceIcon\n comment.appearanceColor = before.appearanceColor\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n },\n }\n\nregisterCommand(createCommentCommand)\nregisterCommand(updateCommentCommand)\nregisterCommand(deleteCommentCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges, requireId, normalizeAuthorUserId } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTeamMemberComment } from '../data/entities'\nimport {\n staffTeamMemberCommentCreateSchema,\n staffTeamMemberCommentUpdateSchema,\n type StaffTeamMemberCommentCreateInput,\n type StaffTeamMemberCommentUpdateInput,\n} from '../data/validators'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload, requireTeamMember } from './shared'\nimport { E } from '#generated/entities.ids.generated'\n\nconst commentCrudIndexer: CrudIndexerConfig<StaffTeamMemberComment> = {\n entityType: E.staff.staff_team_member_comment,\n}\n\ntype CommentSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n memberId: string\n body: string\n authorUserId: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n}\n\ntype CommentUndoPayload = {\n before?: CommentSnapshot | null\n after?: CommentSnapshot | null\n}\n\nasync function loadCommentSnapshot(em: EntityManager, id: string): Promise<CommentSnapshot | null> {\n const comment = await em.findOne(StaffTeamMemberComment, { id })\n if (!comment) return null\n return {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n memberId: typeof comment.member === 'string' ? comment.member : comment.member.id,\n body: comment.body,\n authorUserId: comment.authorUserId ?? null,\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n }\n}\n\nconst createCommentCommand: CommandHandler<\n StaffTeamMemberCommentCreateInput,\n { commentId: string; authorUserId: string | null }\n> = {\n id: 'staff.team-member-comments.create',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberCommentCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const normalizedAuthor = normalizeAuthorUserId(parsed.authorUserId, ctx.auth)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(em, parsed.entityId, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const comment = em.create(StaffTeamMemberComment, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n member,\n body: parsed.body,\n authorUserId: normalizedAuthor,\n appearanceIcon: parsed.appearanceIcon ?? null,\n appearanceColor: parsed.appearanceColor ?? null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n\n return { commentId: comment.id, authorUserId: comment.authorUserId ?? null }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadCommentSnapshot(em, result.commentId)\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as CommentSnapshot | undefined\n return {\n actionLabel: translate('staff.audit.teamMemberComments.create', 'Create note'),\n resourceKind: 'staff.team_member_comment',\n resourceId: result.commentId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: snapshot?.memberId ?? null,\n tenantId: snapshot?.tenantId ?? null,\n organizationId: snapshot?.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const commentId = logEntry?.resourceId ?? null\n if (!commentId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(StaffTeamMemberComment, { id: commentId })\n if (existing) {\n em.remove(existing)\n await em.flush()\n }\n },\n}\n\nconst updateCommentCommand: CommandHandler<StaffTeamMemberCommentUpdateInput, { commentId: string }> = {\n id: 'staff.team-member-comments.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTeamMemberCommentUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadCommentSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberCommentUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const comment = await em.findOne(StaffTeamMemberComment, { id: parsed.id })\n if (!comment) throw new CrudHttpError(404, { error: 'Comment not found' })\n ensureTenantScope(ctx, comment.tenantId)\n ensureOrganizationScope(ctx, comment.organizationId)\n\n if (parsed.entityId !== undefined) {\n const member = await requireTeamMember(em, parsed.entityId, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n comment.member = member\n }\n if (parsed.body !== undefined) comment.body = parsed.body\n if (parsed.authorUserId !== undefined) comment.authorUserId = parsed.authorUserId ?? null\n if (parsed.appearanceIcon !== undefined) comment.appearanceIcon = parsed.appearanceIcon ?? null\n if (parsed.appearanceColor !== undefined) comment.appearanceColor = parsed.appearanceColor ?? null\n\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n\n return { commentId: comment.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadCommentSnapshot(em, result.commentId)\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as CommentSnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as CommentSnapshot | undefined\n const changes =\n afterSnapshot && before\n ? buildChanges(\n before as unknown as Record<string, unknown>,\n afterSnapshot as unknown as Record<string, unknown>,\n ['memberId', 'body', 'authorUserId', 'appearanceIcon', 'appearanceColor']\n )\n : {}\n return {\n actionLabel: translate('staff.audit.teamMemberComments.update', 'Update note'),\n resourceKind: 'staff.team_member_comment',\n resourceId: before.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.memberId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CommentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let comment = await em.findOne(StaffTeamMemberComment, { id: before.id })\n const member = await requireTeamMember(em, before.memberId, 'Team member not found')\n\n if (!comment) {\n comment = em.create(StaffTeamMemberComment, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n body: before.body,\n authorUserId: before.authorUserId,\n appearanceIcon: before.appearanceIcon,\n appearanceColor: before.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n } else {\n comment.member = member\n comment.body = before.body\n comment.authorUserId = before.authorUserId\n comment.appearanceIcon = before.appearanceIcon\n comment.appearanceColor = before.appearanceColor\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n },\n}\n\nconst deleteCommentCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { commentId: string }> =\n {\n id: 'staff.team-member-comments.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Comment id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadCommentSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Comment id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const comment = await em.findOne(StaffTeamMemberComment, { id })\n if (!comment) throw new CrudHttpError(404, { error: 'Comment not found' })\n ensureTenantScope(ctx, comment.tenantId)\n ensureOrganizationScope(ctx, comment.organizationId)\n em.remove(comment)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n return { commentId: comment.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CommentSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMemberComments.delete', 'Delete note'),\n resourceKind: 'staff.team_member_comment',\n resourceId: before.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.memberId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CommentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(em, before.memberId, 'Team member not found')\n let comment = await em.findOne(StaffTeamMemberComment, { id: before.id })\n if (!comment) {\n comment = em.create(StaffTeamMemberComment, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n body: before.body,\n authorUserId: before.authorUserId,\n appearanceIcon: before.appearanceIcon,\n appearanceColor: before.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n } else {\n comment.member = member\n comment.body = before.body\n comment.authorUserId = before.authorUserId\n comment.appearanceIcon = before.appearanceIcon\n comment.appearanceColor = before.appearanceColor\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n indexer: commentCrudIndexer,\n })\n },\n }\n\nregisterCommand(createCommentCommand)\nregisterCommand(updateCommentCommand)\nregisterCommand(deleteCommentCommand)\n"],
5
+ "mappings": "AAAA,SAAS,uBAAuB;AAEhC,SAAS,qBAAqB,yBAAyB,cAAc,WAAW,6BAA6B;AAG7G,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AAEpC,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP,SAAS,yBAAyB,mBAAmB,oBAAoB,yBAAyB;AAClG,SAAS,SAAS;AAElB,MAAM,qBAAgE;AAAA,EACpE,YAAY,EAAE,MAAM;AACtB;AAkBA,eAAe,oBAAoB,IAAmB,IAA6C;AACjG,QAAM,UAAU,MAAM,GAAG,QAAQ,wBAAwB,EAAE,GAAG,CAAC;AAC/D,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO;AAAA,IACL,IAAI,QAAQ;AAAA,IACZ,gBAAgB,QAAQ;AAAA,IACxB,UAAU,QAAQ;AAAA,IAClB,UAAU,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS,QAAQ,OAAO;AAAA,IAC/E,MAAM,QAAQ;AAAA,IACd,cAAc,QAAQ,gBAAgB;AAAA,IACtC,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,iBAAiB,QAAQ,mBAAmB;AAAA,EAC9C;AACF;AAEA,MAAM,uBAGF;AAAA,EACF,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,mCAAmC,MAAM,QAAQ;AAChE,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAClD,UAAM,mBAAmB,sBAAsB,OAAO,cAAc,IAAI,IAAI;AAE5E,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,SAAS,MAAM,kBAAkB,IAAI,OAAO,UAAU,uBAAuB;AACnF,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAElD,UAAM,UAAU,GAAG,OAAO,wBAAwB;AAAA,MAChD,gBAAgB,OAAO;AAAA,MACvB,UAAU,OAAO;AAAA,MACjB;AAAA,MACA,MAAM,OAAO;AAAA,MACb,cAAc;AAAA,MACd,gBAAgB,OAAO,kBAAkB;AAAA,MACzC,iBAAiB,OAAO,mBAAmB;AAAA,MAC3C,WAAW,oBAAI,KAAK;AAAA,MACpB,WAAW,oBAAI,KAAK;AAAA,IACtB,CAAC;AACD,OAAG,QAAQ,OAAO;AAClB,UAAM,GAAG,MAAM;AAEf,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,oBAAoB;AAAA,MACxB,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAED,WAAO,EAAE,WAAW,QAAQ,IAAI,cAAc,QAAQ,gBAAgB,KAAK;AAAA,EAC7E;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,WAAO,MAAM,oBAAoB,IAAI,OAAO,SAAS;AAAA,EACvD;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,UAAU,MAAM;AACzC,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,WAAW,UAAU;AAC3B,WAAO;AAAA,MACL,aAAa,UAAU,yCAAyC,aAAa;AAAA,MAC7E,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB,UAAU,YAAY;AAAA,MACxC,UAAU,UAAU,YAAY;AAAA,MAChC,gBAAgB,UAAU,kBAAkB;AAAA,MAC5C,eAAe,YAAY;AAAA,MAC3B,SAAS;AAAA,QACP,MAAM;AAAA,UACJ,OAAO,YAAY;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,YAAY,UAAU,cAAc;AAC1C,QAAI,CAAC,UAAW;AAChB,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,WAAW,MAAM,GAAG,QAAQ,wBAAwB,EAAE,IAAI,UAAU,CAAC;AAC3E,QAAI,UAAU;AACZ,SAAG,OAAO,QAAQ;AAClB,YAAM,GAAG,MAAM;AAAA,IACjB;AAAA,EACF;AACF;AAEA,MAAM,uBAAiG;AAAA,EACrG,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,mCAAmC,MAAM,QAAQ;AAChE,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI;AACtC,UAAM,WAAW,MAAM,oBAAoB,IAAI,OAAO,EAAE;AACxD,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,mCAAmC,MAAM,QAAQ;AAChE,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,UAAU,MAAM,GAAG,QAAQ,wBAAwB,EAAE,IAAI,OAAO,GAAG,CAAC;AAC1E,QAAI,CAAC,QAAS,OAAM,IAAI,cAAc,KAAK,EAAE,OAAO,oBAAoB,CAAC;AACzE,sBAAkB,KAAK,QAAQ,QAAQ;AACvC,4BAAwB,KAAK,QAAQ,cAAc;AAEnD,QAAI,OAAO,aAAa,QAAW;AACjC,YAAM,SAAS,MAAM,kBAAkB,IAAI,OAAO,UAAU,uBAAuB;AACnF,wBAAkB,KAAK,OAAO,QAAQ;AACtC,8BAAwB,KAAK,OAAO,cAAc;AAClD,cAAQ,SAAS;AAAA,IACnB;AACA,QAAI,OAAO,SAAS,OAAW,SAAQ,OAAO,OAAO;AACrD,QAAI,OAAO,iBAAiB,OAAW,SAAQ,eAAe,OAAO,gBAAgB;AACrF,QAAI,OAAO,mBAAmB,OAAW,SAAQ,iBAAiB,OAAO,kBAAkB;AAC3F,QAAI,OAAO,oBAAoB,OAAW,SAAQ,kBAAkB,OAAO,mBAAmB;AAE9F,UAAM,GAAG,MAAM;AAEf,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,oBAAoB;AAAA,MACxB,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAED,WAAO,EAAE,WAAW,QAAQ,GAAG;AAAA,EACjC;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,WAAO,MAAM,oBAAoB,IAAI,OAAO,SAAS;AAAA,EACvD;AAAA,EACA,UAAU,OAAO,EAAE,UAAU,MAAM;AACjC,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,gBAAgB,UAAU;AAChC,UAAM,UACJ,iBAAiB,SACb;AAAA,MACE;AAAA,MACA;AAAA,MACA,CAAC,YAAY,QAAQ,gBAAgB,kBAAkB,iBAAiB;AAAA,IAC1E,IACA,CAAC;AACP,WAAO;AAAA,MACL,aAAa,UAAU,yCAAyC,aAAa;AAAA,MAC7E,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB,OAAO,YAAY;AAAA,MACrC,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,gBAAgB;AAAA,MAChB,eAAe,iBAAiB;AAAA,MAChC;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,UACJ;AAAA,UACA,OAAO,iBAAiB;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAuC,QAAQ;AAC/D,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AACb,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,QAAI,UAAU,MAAM,GAAG,QAAQ,wBAAwB,EAAE,IAAI,OAAO,GAAG,CAAC;AACxE,UAAM,SAAS,MAAM,kBAAkB,IAAI,OAAO,UAAU,uBAAuB;AAEnF,QAAI,CAAC,SAAS;AACZ,gBAAU,GAAG,OAAO,wBAAwB;AAAA,QAC1C,IAAI,OAAO;AAAA,QACX,gBAAgB,OAAO;AAAA,QACvB,UAAU,OAAO;AAAA,QACjB;AAAA,QACA,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,QACrB,gBAAgB,OAAO;AAAA,QACvB,iBAAiB,OAAO;AAAA,QACxB,WAAW,oBAAI,KAAK;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,MACtB,CAAC;AACD,SAAG,QAAQ,OAAO;AAAA,IACpB,OAAO;AACL,cAAQ,SAAS;AACjB,cAAQ,OAAO,OAAO;AACtB,cAAQ,eAAe,OAAO;AAC9B,cAAQ,iBAAiB,OAAO;AAChC,cAAQ,kBAAkB,OAAO;AAAA,IACnC;AACA,UAAM,GAAG,MAAM;AAEf,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,wBAAwB;AAAA,MAC5B,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;AAEA,MAAM,uBACJ;AAAA,EACE,IAAI;AAAA,EACJ,MAAM,QAAQ,OAAO,KAAK;AACxB,UAAM,KAAK,UAAU,OAAO,qBAAqB;AACjD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI;AACtC,UAAM,WAAW,MAAM,oBAAoB,IAAI,EAAE;AACjD,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,OAAO,KAAK;AACxB,UAAM,KAAK,UAAU,OAAO,qBAAqB;AACjD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,UAAU,MAAM,GAAG,QAAQ,wBAAwB,EAAE,GAAG,CAAC;AAC/D,QAAI,CAAC,QAAS,OAAM,IAAI,cAAc,KAAK,EAAE,OAAO,oBAAoB,CAAC;AACzE,sBAAkB,KAAK,QAAQ,QAAQ;AACvC,4BAAwB,KAAK,QAAQ,cAAc;AACnD,OAAG,OAAO,OAAO;AACjB,UAAM,GAAG,MAAM;AAEf,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,oBAAoB;AAAA,MACxB,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AACD,WAAO,EAAE,WAAW,QAAQ,GAAG;AAAA,EACjC;AAAA,EACA,UAAU,OAAO,EAAE,UAAU,MAAM;AACjC,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,WAAO;AAAA,MACL,aAAa,UAAU,yCAAyC,aAAa;AAAA,MAC7E,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB;AAAA,MACpB,kBAAkB,OAAO,YAAY;AAAA,MACrC,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,gBAAgB;AAAA,MAChB,SAAS;AAAA,QACP,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAAuC,QAAQ;AAC/D,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AACb,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,SAAS,MAAM,kBAAkB,IAAI,OAAO,UAAU,uBAAuB;AACnF,QAAI,UAAU,MAAM,GAAG,QAAQ,wBAAwB,EAAE,IAAI,OAAO,GAAG,CAAC;AACxE,QAAI,CAAC,SAAS;AACZ,gBAAU,GAAG,OAAO,wBAAwB;AAAA,QAC1C,IAAI,OAAO;AAAA,QACX,gBAAgB,OAAO;AAAA,QACvB,UAAU,OAAO;AAAA,QACjB;AAAA,QACA,MAAM,OAAO;AAAA,QACb,cAAc,OAAO;AAAA,QACrB,gBAAgB,OAAO;AAAA,QACvB,iBAAiB,OAAO;AAAA,QACxB,WAAW,oBAAI,KAAK;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,MACtB,CAAC;AACD,SAAG,QAAQ,OAAO;AAAA,IACpB,OAAO;AACL,cAAQ,SAAS;AACjB,cAAQ,OAAO,OAAO;AACtB,cAAQ,eAAe,OAAO;AAC9B,cAAQ,iBAAiB,OAAO;AAChC,cAAQ,kBAAkB,OAAO;AAAA,IACnC;AACA,UAAM,GAAG,MAAM;AAEf,UAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,UAAM,wBAAwB;AAAA,MAC5B,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,aAAa;AAAA,QACX,IAAI,QAAQ;AAAA,QACZ,gBAAgB,QAAQ;AAAA,QACxB,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;AAEF,gBAAgB,oBAAoB;AACpC,gBAAgB,oBAAoB;AACpC,gBAAgB,oBAAoB;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,41 @@
1
+ function normalizeLeaveRequest(record) {
2
+ return {
3
+ ...record,
4
+ id: record.id,
5
+ member: record.member,
6
+ memberId: record.memberId ?? record.member_id ?? null,
7
+ startDate: record.startDate ?? record.start_date ?? null,
8
+ endDate: record.endDate ?? record.end_date ?? null,
9
+ timezone: record.timezone ?? null,
10
+ status: record.status ?? "pending",
11
+ unavailabilityReasonEntryId: record.unavailabilityReasonEntryId ?? record.unavailability_reason_entry_id ?? null,
12
+ unavailabilityReasonValue: record.unavailabilityReasonValue ?? record.unavailability_reason_value ?? null,
13
+ note: record.note ?? null,
14
+ decisionComment: record.decisionComment ?? record.decision_comment ?? null,
15
+ decidedAt: record.decidedAt ?? record.decided_at ?? null
16
+ };
17
+ }
18
+ function resolveStatusVariant(status) {
19
+ if (status === "approved") return "default";
20
+ if (status === "rejected") return "destructive";
21
+ return "secondary";
22
+ }
23
+ function formatDateLabel(value) {
24
+ if (!value) return "";
25
+ const date = new Date(value);
26
+ if (Number.isNaN(date.getTime())) return value;
27
+ return date.toLocaleDateString();
28
+ }
29
+ function formatDateRange(start, end) {
30
+ const startLabel = formatDateLabel(start);
31
+ const endLabel = formatDateLabel(end);
32
+ if (startLabel && endLabel) return `${startLabel} -> ${endLabel}`;
33
+ return startLabel || endLabel || "-";
34
+ }
35
+ export {
36
+ formatDateLabel,
37
+ formatDateRange,
38
+ normalizeLeaveRequest,
39
+ resolveStatusVariant
40
+ };
41
+ //# sourceMappingURL=leaveRequestHelpers.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/staff/lib/leaveRequestHelpers.ts"],
4
+ "sourcesContent": ["export type 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\nexport type NormalizedLeaveRequest = {\n id: string\n member?: { id?: string; displayName?: string }\n memberId: string | null\n startDate: string | null\n endDate: string | null\n timezone: string | null\n status: 'pending' | 'approved' | 'rejected'\n unavailabilityReasonEntryId: string | null\n unavailabilityReasonValue: string | null\n note: string | null\n decisionComment: string | null\n decidedAt: string | null\n} & Record<string, unknown>\n\nexport function normalizeLeaveRequest(record: LeaveRequestRecord): NormalizedLeaveRequest {\n return {\n ...record,\n id: record.id,\n member: record.member,\n memberId: record.memberId ?? record.member_id ?? null,\n startDate: record.startDate ?? record.start_date ?? null,\n endDate: record.endDate ?? record.end_date ?? null,\n timezone: record.timezone ?? null,\n status: record.status ?? 'pending',\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 decisionComment: record.decisionComment ?? record.decision_comment ?? null,\n decidedAt: record.decidedAt ?? record.decided_at ?? null,\n }\n}\n\nexport type LeaveRequestsResponse = {\n items?: LeaveRequestRecord[]\n}\n\nexport function resolveStatusVariant(status: 'pending' | 'approved' | 'rejected') {\n if (status === 'approved') return 'default'\n if (status === 'rejected') return 'destructive'\n return 'secondary'\n}\n\nexport function 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\nexport function 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": "AAqCO,SAAS,sBAAsB,QAAoD;AACxF,SAAO;AAAA,IACL,GAAG;AAAA,IACH,IAAI,OAAO;AAAA,IACX,QAAQ,OAAO;AAAA,IACf,UAAU,OAAO,YAAY,OAAO,aAAa;AAAA,IACjD,WAAW,OAAO,aAAa,OAAO,cAAc;AAAA,IACpD,SAAS,OAAO,WAAW,OAAO,YAAY;AAAA,IAC9C,UAAU,OAAO,YAAY;AAAA,IAC7B,QAAQ,OAAO,UAAU;AAAA,IACzB,6BAA6B,OAAO,+BAA+B,OAAO,kCAAkC;AAAA,IAC5G,2BAA2B,OAAO,6BAA6B,OAAO,+BAA+B;AAAA,IACrG,MAAM,OAAO,QAAQ;AAAA,IACrB,iBAAiB,OAAO,mBAAmB,OAAO,oBAAoB;AAAA,IACtE,WAAW,OAAO,aAAa,OAAO,cAAc;AAAA,EACtD;AACF;AAMO,SAAS,qBAAqB,QAA6C;AAChF,MAAI,WAAW,WAAY,QAAO;AAClC,MAAI,WAAW,WAAY,QAAO;AAClC,SAAO;AACT;AAEO,SAAS,gBAAgB,OAA+B;AAC7D,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,IAAI,KAAK,KAAK;AAC3B,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AACzC,SAAO,KAAK,mBAAmB;AACjC;AAEO,SAAS,gBAAgB,OAAuB,KAA6B;AAClF,QAAM,aAAa,gBAAgB,KAAK;AACxC,QAAM,WAAW,gBAAgB,GAAG;AACpC,MAAI,cAAc,SAAU,QAAO,GAAG,UAAU,OAAO,QAAQ;AAC/D,SAAO,cAAc,YAAY;AACnC;",
6
+ "names": []
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.4.6-develop-f7d3079656",
3
+ "version": "0.4.6-develop-0861f05ea9",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -207,7 +207,7 @@
207
207
  }
208
208
  },
209
209
  "dependencies": {
210
- "@open-mercato/shared": "0.4.6-develop-f7d3079656",
210
+ "@open-mercato/shared": "0.4.6-develop-0861f05ea9",
211
211
  "@types/html-to-text": "^9.0.4",
212
212
  "@types/semver": "^7.5.8",
213
213
  "@xyflow/react": "^12.6.0",