@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.
- package/dist/modules/currencies/backend/exchange-rates/[id]/page.js +17 -154
- package/dist/modules/currencies/backend/exchange-rates/[id]/page.js.map +3 -3
- package/dist/modules/currencies/backend/exchange-rates/create/page.js +14 -152
- package/dist/modules/currencies/backend/exchange-rates/create/page.js.map +2 -2
- package/dist/modules/currencies/lib/exchangeRateFormConfig.js +167 -0
- package/dist/modules/currencies/lib/exchangeRateFormConfig.js.map +7 -0
- package/dist/modules/customers/api/dashboard/widgets/utils.js +1 -34
- package/dist/modules/customers/api/dashboard/widgets/utils.js.map +2 -2
- package/dist/modules/customers/commands/activities.js +3 -8
- package/dist/modules/customers/commands/activities.js.map +2 -2
- package/dist/modules/customers/commands/comments.js +2 -8
- package/dist/modules/customers/commands/comments.js.map +2 -2
- package/dist/modules/dashboards/lib/widgetScope.js +38 -0
- package/dist/modules/dashboards/lib/widgetScope.js.map +7 -0
- package/dist/modules/entities/lib/makeActivityRoute.js +265 -0
- package/dist/modules/entities/lib/makeActivityRoute.js.map +7 -0
- package/dist/modules/resources/api/activities.js +24 -232
- package/dist/modules/resources/api/activities.js.map +2 -2
- package/dist/modules/resources/commands/activities.js +3 -8
- package/dist/modules/resources/commands/activities.js.map +2 -2
- package/dist/modules/resources/commands/comments.js +2 -8
- package/dist/modules/resources/commands/comments.js.map +2 -2
- package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js +27 -182
- package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js.map +2 -2
- package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js +28 -183
- package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js.map +2 -2
- package/dist/modules/sales/api/order-line-statuses/route.js +15 -194
- package/dist/modules/sales/api/order-line-statuses/route.js.map +2 -2
- package/dist/modules/sales/api/order-lines/route.js +15 -281
- package/dist/modules/sales/api/order-lines/route.js.map +2 -2
- package/dist/modules/sales/api/order-statuses/route.js +15 -194
- package/dist/modules/sales/api/order-statuses/route.js.map +2 -2
- package/dist/modules/sales/api/payment-statuses/route.js +15 -194
- package/dist/modules/sales/api/payment-statuses/route.js.map +2 -2
- package/dist/modules/sales/api/quote-lines/route.js +15 -279
- package/dist/modules/sales/api/quote-lines/route.js.map +2 -2
- package/dist/modules/sales/api/shipment-statuses/route.js +15 -194
- package/dist/modules/sales/api/shipment-statuses/route.js.map +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js +3 -84
- package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/ProviderFieldInput.js +86 -0
- package/dist/modules/sales/components/ProviderFieldInput.js.map +7 -0
- package/dist/modules/sales/components/ShippingMethodsSettings.js +3 -82
- package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
- package/dist/modules/sales/lib/makeSalesLineRoute.js +308 -0
- package/dist/modules/sales/lib/makeSalesLineRoute.js.map +7 -0
- package/dist/modules/sales/lib/makeStatusDictionaryRoute.js +206 -0
- package/dist/modules/sales/lib/makeStatusDictionaryRoute.js.map +7 -0
- package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js +178 -0
- package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js.map +7 -0
- package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js +1 -39
- package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js.map +2 -2
- package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js +1 -39
- package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js.map +2 -2
- package/dist/modules/sales/widgets/dashboard/shared.js +46 -0
- package/dist/modules/sales/widgets/dashboard/shared.js.map +7 -0
- package/dist/modules/staff/api/activities.js +24 -232
- package/dist/modules/staff/api/activities.js.map +2 -2
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js +14 -34
- package/dist/modules/staff/backend/staff/leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js +15 -34
- package/dist/modules/staff/backend/staff/my-leave-requests/[id]/page.js.map +2 -2
- package/dist/modules/staff/commands/activities.js +3 -8
- package/dist/modules/staff/commands/activities.js.map +2 -2
- package/dist/modules/staff/commands/comments.js +2 -8
- package/dist/modules/staff/commands/comments.js.map +2 -2
- package/dist/modules/staff/lib/leaveRequestHelpers.js +41 -0
- package/dist/modules/staff/lib/leaveRequestHelpers.js.map +7 -0
- package/package.json +2 -2
- package/src/modules/currencies/backend/exchange-rates/[id]/page.tsx +20 -180
- package/src/modules/currencies/backend/exchange-rates/create/page.tsx +16 -175
- package/src/modules/currencies/lib/exchangeRateFormConfig.ts +200 -0
- package/src/modules/customers/api/dashboard/widgets/utils.ts +1 -53
- package/src/modules/customers/commands/activities.ts +2 -8
- package/src/modules/customers/commands/comments.ts +2 -8
- package/src/modules/dashboards/i18n/de.json +3 -0
- package/src/modules/dashboards/i18n/en.json +3 -0
- package/src/modules/dashboards/i18n/es.json +3 -0
- package/src/modules/dashboards/i18n/pl.json +3 -0
- package/src/modules/dashboards/lib/widgetScope.ts +53 -0
- package/src/modules/entities/lib/makeActivityRoute.ts +327 -0
- package/src/modules/resources/api/activities.ts +25 -269
- package/src/modules/resources/commands/activities.ts +2 -7
- package/src/modules/resources/commands/comments.ts +2 -8
- package/src/modules/sales/api/dashboard/widgets/new-orders/route.ts +29 -244
- package/src/modules/sales/api/dashboard/widgets/new-quotes/route.ts +30 -245
- package/src/modules/sales/api/order-line-statuses/route.ts +16 -209
- package/src/modules/sales/api/order-lines/route.ts +16 -300
- package/src/modules/sales/api/order-statuses/route.ts +16 -209
- package/src/modules/sales/api/payment-statuses/route.ts +16 -209
- package/src/modules/sales/api/quote-lines/route.ts +16 -298
- package/src/modules/sales/api/shipment-statuses/route.ts +16 -209
- package/src/modules/sales/components/PaymentMethodsSettings.tsx +3 -88
- package/src/modules/sales/components/ProviderFieldInput.tsx +85 -0
- package/src/modules/sales/components/ShippingMethodsSettings.tsx +3 -86
- package/src/modules/sales/lib/makeSalesLineRoute.ts +345 -0
- package/src/modules/sales/lib/makeStatusDictionaryRoute.ts +229 -0
- package/src/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.ts +247 -0
- package/src/modules/sales/widgets/dashboard/new-orders/widget.client.tsx +7 -50
- package/src/modules/sales/widgets/dashboard/new-quotes/widget.client.tsx +7 -49
- package/src/modules/sales/widgets/dashboard/shared.ts +44 -0
- package/src/modules/staff/api/activities.ts +25 -269
- package/src/modules/staff/backend/staff/leave-requests/[id]/page.tsx +15 -69
- package/src/modules/staff/backend/staff/my-leave-requests/[id]/page.tsx +16 -65
- package/src/modules/staff/commands/activities.ts +2 -7
- package/src/modules/staff/commands/comments.ts +2 -8
- 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": ";
|
|
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
|
|
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": "AAAA,SAAS,uBAAuB;AAEhC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AAEpC,SAAS,+BAA+B;AACxC;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP,SAAS,yBAAyB,mBAAmB,oBAAoB,yBAAyB;AAClG,SAAS,SAAS;AAClB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAEP,MAAM,sBAAkE;AAAA,EACtE,YAAY,EAAE,MAAM;AACtB;AA4BA,eAAe,qBAAqB,IAAmB,IAA8C;AACnG,QAAM,WAAW,MAAM,GAAG,QAAQ,yBAAyB,EAAE,GAAG,CAAC;AACjE,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,SAAS,MAAM,wBAAwB,IAAI;AAAA,IAC/C,UAAU,EAAE,MAAM;AAAA,IAClB,UAAU,SAAS;AAAA,IACnB,UAAU,SAAS;AAAA,IACnB,gBAAgB,SAAS;AAAA,EAC3B,CAAC;AACD,SAAO;AAAA,IACL,UAAU;AAAA,MACR,IAAI,SAAS;AAAA,MACb,gBAAgB,SAAS;AAAA,MACzB,UAAU,SAAS;AAAA,MACnB,UAAU,OAAO,SAAS,WAAW,WAAW,SAAS,SAAS,SAAS,OAAO;AAAA,MAClF,cAAc,SAAS;AAAA,MACvB,SAAS,SAAS,WAAW;AAAA,MAC7B,MAAM,SAAS,QAAQ;AAAA,MACvB,YAAY,SAAS,cAAc;AAAA,MACnC,cAAc,SAAS,gBAAgB;AAAA,MACvC,gBAAgB,SAAS,kBAAkB;AAAA,MAC3C,iBAAiB,SAAS,mBAAmB;AAAA,IAC/C;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,wBACb,KACA,YACA,gBACA,UACA,QACA;AACA,MAAI,CAAC,UAAU,CAAC,OAAO,KAAK,MAAM,EAAE,OAAQ;AAC5C,QAAM,KAAM,IAAI,UAAU,QAAQ,YAAY;AAC9C,QAAM,qBAAqB;AAAA,IACzB,YAAY;AAAA,IACZ,UAAU,EAAE,MAAM;AAAA,IAClB,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV,CAAC;AACH;AAEA,MAAM,wBAGF;AAAA,EACF,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,EAAE,QAAQ,OAAO,IAAI,sBAAsB,qCAAqC,QAAQ;AAC9F,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAClD,UAAM,
|
|
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
|
|
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": "AAAA,SAAS,uBAAuB;AAEhC,SAAS,qBAAqB,yBAAyB,cAAc,
|
|
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": "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",
|
|
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-
|
|
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-
|
|
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",
|