@open-mercato/core 0.6.6-develop.6519.1.bdc91fb755 → 0.6.6-develop.6520.1.55df6df792

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/customers/backend/calendar/page.js +9 -1
  3. package/dist/modules/customers/backend/calendar/page.js.map +2 -2
  4. package/dist/modules/customers/components/calendar/AgendaList.js +0 -11
  5. package/dist/modules/customers/components/calendar/AgendaList.js.map +2 -2
  6. package/dist/modules/customers/components/calendar/CalendarEventEditor.js +391 -235
  7. package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +2 -2
  8. package/dist/modules/customers/components/calendar/CalendarScreen.js +5 -5
  9. package/dist/modules/customers/components/calendar/CalendarScreen.js.map +2 -2
  10. package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +2 -2
  11. package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +2 -2
  12. package/dist/modules/customers/components/calendar/MonthGrid.js +1 -11
  13. package/dist/modules/customers/components/calendar/MonthGrid.js.map +2 -2
  14. package/dist/modules/customers/components/calendar/TimeGrid.js +162 -176
  15. package/dist/modules/customers/components/calendar/TimeGrid.js.map +2 -2
  16. package/dist/modules/customers/components/calendar/editor/LocationField.js +61 -14
  17. package/dist/modules/customers/components/calendar/editor/LocationField.js.map +2 -2
  18. package/dist/modules/customers/components/calendar/editor/PeopleField.js +10 -5
  19. package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
  20. package/dist/modules/customers/components/calendar/editor/PriorityField.js +85 -0
  21. package/dist/modules/customers/components/calendar/editor/PriorityField.js.map +7 -0
  22. package/dist/modules/customers/components/calendar/editor/RelatedToField.js +8 -3
  23. package/dist/modules/customers/components/calendar/editor/RelatedToField.js.map +2 -2
  24. package/dist/modules/customers/components/calendar/editor/ResourcesField.js +225 -0
  25. package/dist/modules/customers/components/calendar/editor/ResourcesField.js.map +7 -0
  26. package/dist/modules/customers/components/calendar/editor/SegmentGroup.js +12 -7
  27. package/dist/modules/customers/components/calendar/editor/SegmentGroup.js.map +2 -2
  28. package/dist/modules/customers/components/calendar/editor/inputs.js +68 -57
  29. package/dist/modules/customers/components/calendar/editor/inputs.js.map +2 -2
  30. package/dist/modules/customers/components/calendar/editor/lookups.js +82 -2
  31. package/dist/modules/customers/components/calendar/editor/lookups.js.map +2 -2
  32. package/dist/modules/customers/components/calendar/useCalendarItems.js +6 -1
  33. package/dist/modules/customers/components/calendar/useCalendarItems.js.map +2 -2
  34. package/dist/modules/customers/data/validators.js +3 -1
  35. package/dist/modules/customers/data/validators.js.map +2 -2
  36. package/dist/modules/customers/lib/calendar/editorPayload.js +53 -22
  37. package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
  38. package/dist/modules/entities/backend/entities/user/[entityId]/page.js +1 -1
  39. package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
  40. package/package.json +7 -7
  41. package/src/modules/customers/backend/calendar/page.tsx +8 -1
  42. package/src/modules/customers/components/calendar/AgendaList.tsx +0 -10
  43. package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +444 -261
  44. package/src/modules/customers/components/calendar/CalendarScreen.tsx +12 -5
  45. package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +6 -6
  46. package/src/modules/customers/components/calendar/MonthGrid.tsx +0 -11
  47. package/src/modules/customers/components/calendar/TimeGrid.tsx +1 -24
  48. package/src/modules/customers/components/calendar/editor/LocationField.tsx +64 -2
  49. package/src/modules/customers/components/calendar/editor/PeopleField.tsx +11 -4
  50. package/src/modules/customers/components/calendar/editor/PriorityField.tsx +90 -0
  51. package/src/modules/customers/components/calendar/editor/RelatedToField.tsx +8 -3
  52. package/src/modules/customers/components/calendar/editor/ResourcesField.tsx +264 -0
  53. package/src/modules/customers/components/calendar/editor/SegmentGroup.tsx +14 -6
  54. package/src/modules/customers/components/calendar/editor/inputs.tsx +91 -50
  55. package/src/modules/customers/components/calendar/editor/lookups.ts +115 -2
  56. package/src/modules/customers/components/calendar/useCalendarItems.ts +8 -1
  57. package/src/modules/customers/data/validators.ts +3 -1
  58. package/src/modules/customers/i18n/de.json +12 -2
  59. package/src/modules/customers/i18n/en.json +12 -2
  60. package/src/modules/customers/i18n/es.json +12 -2
  61. package/src/modules/customers/i18n/pl.json +12 -2
  62. package/src/modules/customers/lib/calendar/editorPayload.ts +94 -37
  63. package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +1 -1
  64. package/src/modules/entities/i18n/de.json +120 -0
  65. package/src/modules/entities/i18n/en.json +120 -0
  66. package/src/modules/entities/i18n/es.json +120 -0
  67. package/src/modules/entities/i18n/pl.json +120 -0
  68. package/dist/modules/customers/components/calendar/editor/CategoryField.js +0 -75
  69. package/dist/modules/customers/components/calendar/editor/CategoryField.js.map +0 -7
  70. package/src/modules/customers/components/calendar/editor/CategoryField.tsx +0 -79
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/calendar/CalendarEventEditor.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Calendar, X } from 'lucide-react'\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCallOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader, extractOptimisticLockConflict } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { mapCrudServerErrorToFormErrors } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Dialog, DialogContent, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { useDialogKeyHandler } from '@open-mercato/ui/hooks/useDialogKeyHandler'\nimport {\n buildEditorCategoryOptions,\n buildInteractionPayload,\n computeDurationMinutes,\n createDefaultFormState,\n defaultRepeatDaysForDateInput,\n EDITOR_KINDS,\n KIND_CONFIG,\n parseItemToFormState,\n resolveSavedOwnerUserId,\n type EditorFormState,\n type EditorKind,\n type EditorPriority,\n} from '../../lib/calendar/editorPayload'\nimport type { ConflictScope } from '../../lib/calendar/preferences'\nimport type { CalendarItem } from './types'\nimport { Field } from './editor/inputs'\nimport { SegmentGroup } from './editor/SegmentGroup'\nimport { RelatedToField } from './editor/RelatedToField'\nimport { CategoryField } from './editor/CategoryField'\nimport { RepeatField } from './editor/RepeatField'\nimport { PeopleField } from './editor/PeopleField'\nimport { ScheduleSection } from './editor/ScheduleSection'\nimport { LocationField } from './editor/LocationField'\nimport { useConflictProbe, useEditorLabelResolution } from './editor/hooks'\n\nexport interface CalendarEventEditorProps {\n open: boolean\n mode: 'create' | 'edit'\n item?: CalendarItem | null\n defaultDate?: Date\n defaultRange?: { start: Date; end: Date } | null\n typeLabels: Record<string, string>\n typeColors: Record<string, string | null>\n surfacedTypes?: string[]\n eventCategories?: string[]\n conflictScope?: ConflictScope\n currentUserId?: string | null\n onOpenChange(open: boolean): void\n onSaved(): void\n}\n\ntype FieldErrors = { title?: string; relatedTo?: string; ends?: string }\n\nconst PEOPLE_FIELD_TEXT = {\n attendees: { labelKey: 'customers.calendar.editor.attendees', label: 'Attendees', placeholderKey: 'customers.calendar.editor.addPeoplePlaceholder', placeholder: 'Add staff or customer\u2026' },\n participants: { labelKey: 'customers.calendar.editor.participants', label: 'Participants', placeholderKey: 'customers.calendar.editor.addPeoplePlaceholder', placeholder: 'Add staff or customer\u2026' },\n to: { labelKey: 'customers.calendar.editor.to', label: 'To', placeholderKey: 'customers.calendar.editor.addRecipientPlaceholder', placeholder: 'Add recipient\u2026' },\n} as const\n\nexport function CalendarEventEditor({ open, mode, item, defaultDate, defaultRange, typeLabels, typeColors, surfacedTypes, eventCategories, conflictScope, currentUserId, onOpenChange, onSaved }: CalendarEventEditorProps) {\n const t = useT()\n const locale = useLocale()\n const [form, setForm] = React.useState<EditorFormState>(() => createDefaultFormState(defaultDate ?? null, undefined, defaultRange ?? null))\n const [fieldErrors, setFieldErrors] = React.useState<FieldErrors>({})\n const [saving, setSaving] = React.useState(false)\n const openKeyRef = React.useRef<string | null>(null)\n const isEdit = mode === 'edit' && Boolean(item?.id)\n const config = KIND_CONFIG[form.kind]\n\n const update = React.useCallback((patch: Partial<EditorFormState>) => {\n setForm((previous) => ({ ...previous, ...patch }))\n }, [])\n\n React.useEffect(() => {\n if (!open) {\n openKeyRef.current = null\n return\n }\n const key = `${mode}:${item?.id ?? 'new'}`\n if (openKeyRef.current === key) return\n openKeyRef.current = key\n setForm(\n mode === 'edit' && item\n ? parseItemToFormState(item)\n : createDefaultFormState(defaultDate ?? null, undefined, defaultRange ?? null),\n )\n setFieldErrors({})\n }, [open, mode, item, defaultDate, defaultRange])\n\n useEditorLabelResolution(open, form, update)\n // Probe against the owner the interaction will actually be SAVED with so the\n // editor warning matches the grid's post-save conflict rings: tasks own via\n // their assignee, other kinds stay ownerless on create / keep the existing\n // owner on edit (conflicts then come from shared participants).\n const draftOwnerUserId = resolveSavedOwnerUserId(config, form, isEdit, item?.ownerUserId ?? null)\n // Self-exclude by the underlying interaction id (raw.id): findEditorConflictItems\n // drops candidates by raw.id, and every expanded occurrence of a recurring series\n // shares it \u2014 so the edited record never conflicts with itself. (asEditableItem\n // already normalizes a clicked occurrence's id to raw.id, so these match today;\n // raw.id keeps it correct even if a future edit path skips that normalization.)\n const conflict = useConflictProbe(open, form, config, isEdit && item ? item.raw.id : null, draftOwnerUserId, conflictScope ?? 'all', currentUserId ?? null)\n\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: 'customers-calendar-event-editor',\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const handleSave = React.useCallback(async () => {\n const errors: FieldErrors = {}\n if (!form.title.trim()) errors.title = t('customers.calendar.editor.validation.titleRequired', 'Title is required')\n if (!form.relatedTo) errors.relatedTo = t('customers.calendar.editor.validation.relatedToRequired', 'Select a person or company to link this event')\n if (config.hasEnd && !form.allDay && computeDurationMinutes(form) === null) {\n errors.ends = t('customers.calendar.editor.validation.endsBeforeStarts', 'End must be after start')\n }\n setFieldErrors(errors)\n if (Object.keys(errors).length > 0) return\n setSaving(true)\n try {\n const payload = buildInteractionPayload(form, { mode, id: item?.id })\n await runMutation({\n operation: () => {\n const call = () =>\n apiCallOrThrow('/api/customers/interactions', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n return isEdit ? withScopedApiRequestHeaders(buildOptimisticLockHeader(item?.updatedAt), call) : call()\n },\n mutationPayload: {\n operation: isEdit ? 'updateCalendarEvent' : 'createCalendarEvent',\n interactionId: item?.id ?? null,\n interactionType: form.category ?? form.kind,\n },\n context: {\n formId: 'customers-calendar-event-editor',\n resourceKind: 'customers.interaction',\n resourceId: item?.id ?? 'new',\n retryLastMutation,\n },\n })\n flash(t('customers.calendar.editor.saved', 'Event saved'), 'success')\n onOpenChange(false)\n requestAnimationFrame(() => { onSaved() })\n } catch (err) {\n // An optimistic-lock 409 is surfaced as the persistent conflict bar by\n // useGuardedMutation (surfaceRecordConflict) \u2014 close without re-flashing.\n if (extractOptimisticLockConflict(err)) {\n onOpenChange(false)\n return\n }\n const { message } = mapCrudServerErrorToFormErrors(err)\n const key = typeof message === 'string' ? message.trim() : ''\n flash(key ? t(key, key) : t('customers.calendar.editor.error', 'Failed to save event'), 'error')\n } finally {\n setSaving(false)\n }\n }, [config.hasEnd, form, isEdit, item?.id, mode, onOpenChange, onSaved, retryLastMutation, runMutation, t])\n\n const handleKeyDown = useDialogKeyHandler({ onConfirm: handleSave, disabled: saving })\n\n const categoryOptions = React.useMemo(\n () =>\n buildEditorCategoryOptions({\n typeLabels,\n surfacedTypes: surfacedTypes ?? [],\n eventCategories: eventCategories ?? [],\n selectedValue: form.category ?? form.kind,\n selectedFallbackLabel: t(`customers.calendar.editor.types.${form.kind}`, form.kind),\n }),\n [typeLabels, surfacedTypes, eventCategories, form.category, form.kind, t],\n )\n\n const titleLabel = form.kind === 'email'\n ? t('customers.calendar.editor.titleLabel.email', 'Subject')\n : form.kind === 'note'\n ? t('customers.calendar.editor.titleLabel.note', 'Note')\n : t('customers.calendar.editor.titleLabel.generic', 'Title')\n const dialogTitle = isEdit ? t('customers.calendar.editor.title.edit', 'Edit event') : t('customers.calendar.editor.title.create', 'New event')\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n onKeyDown={handleKeyDown}\n aria-describedby={undefined}\n dismissible={false}\n className=\"flex h-dvh max-h-dvh w-screen max-w-none flex-col gap-0 overflow-hidden rounded-none border-0 bg-background p-0 shadow-xl sm:h-auto sm:max-h-screen sm:w-full sm:max-w-md sm:rounded-2xl sm:border-0\"\n >\n <VisuallyHidden>\n <DialogTitle>{dialogTitle}</DialogTitle>\n </VisuallyHidden>\n <div className=\"flex shrink-0 items-center gap-3 border-b border-border bg-background py-4 pl-5 pr-4\">\n <Calendar aria-hidden className=\"size-6 shrink-0 text-foreground\" strokeWidth={1.75} />\n <p className=\"min-w-0 flex-1 text-sm font-medium leading-5 text-foreground\">{dialogTitle}</p>\n <IconButton\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onOpenChange(false)}\n aria-label={t('customers.calendar.editor.close', 'Close')}\n className=\"shrink-0 text-muted-foreground\"\n >\n <X aria-hidden className=\"size-5\" />\n </IconButton>\n </div>\n <div className=\"flex-1 overflow-y-auto\">\n <div className=\"flex flex-col items-start gap-5 px-4 py-5 sm:px-6 sm:py-6\">\n {conflict ? (\n <Alert variant=\"warning\" className=\"rounded-lg\">\n <AlertTitle>{t('customers.calendar.editor.conflictTitle', 'Calendar conflict')}</AlertTitle>\n <AlertDescription>{conflict}</AlertDescription>\n </Alert>\n ) : null}\n <SegmentGroup<EditorKind>\n ariaLabel={t('customers.calendar.editor.typeSwitcher', 'Event type')}\n value={form.kind}\n onChange={(kind) => update({ kind, category: null })}\n options={EDITOR_KINDS.map((kind) => ({ value: kind, label: t(`customers.calendar.editor.types.${kind}`, kind) }))}\n />\n <Field label={titleLabel} error={fieldErrors.title}>\n <Input\n type=\"text\"\n value={form.title}\n onChange={(event) => update({ title: event.target.value })}\n placeholder={t('customers.calendar.editor.titlePlaceholder', 'Add a title\u2026')}\n aria-label={titleLabel}\n autoFocus\n size=\"lg\"\n />\n </Field>\n <Field label={t('customers.calendar.editor.relatedTo', 'Related to')} error={fieldErrors.relatedTo}>\n <RelatedToField\n label={t('customers.calendar.editor.relatedTo', 'Related to')}\n value={form.relatedTo}\n deal={form.dealId && form.dealLabel ? { id: form.dealId, label: form.dealLabel } : null}\n onChange={(relatedTo) => update({ relatedTo })}\n onDealChange={(deal) => update({ dealId: deal?.id ?? null, dealLabel: deal?.label ?? null })}\n error={fieldErrors.relatedTo}\n />\n </Field>\n <ScheduleSection\n dateLabel={config.dateLabel}\n hasAllDay={config.hasAllDay}\n hasEnd={config.hasEnd}\n allDay={form.allDay}\n date={form.date}\n startTime={form.startTime}\n endDate={form.endDate}\n endTime={form.endTime}\n locale={locale}\n endsError={fieldErrors.ends}\n onAllDayChange={(allDay) => update({ allDay })}\n onDateChange={(date) => {\n const untouchedDefault =\n JSON.stringify(form.repeatDays) === JSON.stringify(defaultRepeatDaysForDateInput(form.date))\n update(\n untouchedDefault\n ? { date, repeatDays: defaultRepeatDaysForDateInput(date) }\n : { date },\n )\n }}\n onStartTimeChange={(startTime) => update({ startTime })}\n onEndDateChange={(endDate) => update({ endDate })}\n onEndTimeChange={(endTime) => update({ endTime })}\n />\n {config.hasRepeat ? (\n <RepeatField\n freq={form.repeatFreq}\n days={form.repeatDays}\n endType={form.repeatEndType}\n count={form.repeatCount}\n untilDate={form.repeatUntilDate}\n locale={locale}\n onFreqChange={(repeatFreq) =>\n update(\n repeatFreq === 'weekly'\n ? { repeatFreq, repeatDays: defaultRepeatDaysForDateInput(form.date) }\n : { repeatFreq },\n )}\n onToggleDay={(index) =>\n update({ repeatDays: form.repeatDays.map((active, dayIndex) => (dayIndex === index ? !active : active)) })}\n onEndTypeChange={(repeatEndType) => update({ repeatEndType })}\n onCountChange={(repeatCount) => update({ repeatCount })}\n onUntilDateChange={(repeatUntilDate) => update({ repeatUntilDate })}\n />\n ) : null}\n <Field label={t('customers.calendar.editor.category', 'Category')}>\n <CategoryField\n label={t('customers.calendar.editor.category', 'Category')}\n value={form.category ?? form.kind}\n options={categoryOptions}\n colors={typeColors}\n onChange={(category) => update({ category })}\n />\n </Field>\n {config.location ? (\n <LocationField variant={config.location} value={form.location} onChange={(location) => update({ location })} />\n ) : null}\n {config.people && config.people !== 'assignee' ? (\n <Field label={t(PEOPLE_FIELD_TEXT[config.people].labelKey, PEOPLE_FIELD_TEXT[config.people].label)}>\n <PeopleField\n mode=\"multi\"\n includeCustomers\n placeholder={t(PEOPLE_FIELD_TEXT[config.people].placeholderKey, PEOPLE_FIELD_TEXT[config.people].placeholder)}\n ariaLabel={t(PEOPLE_FIELD_TEXT[config.people].labelKey, PEOPLE_FIELD_TEXT[config.people].label)}\n value={form.participants}\n onChange={(participants) => update({ participants })}\n />\n </Field>\n ) : null}\n {config.hasPriority ? (\n <Field label={t('customers.calendar.editor.priority.label', 'Priority')}>\n <SegmentGroup<EditorPriority>\n size=\"md\"\n ariaLabel={t('customers.calendar.editor.priority.label', 'Priority')}\n value={form.priority}\n onChange={(priority) => update({ priority })}\n options={[\n { value: 'low', label: t('customers.calendar.editor.priority.low', 'Low') },\n { value: 'medium', label: t('customers.calendar.editor.priority.medium', 'Medium') },\n { value: 'high', label: t('customers.calendar.editor.priority.high', 'High') },\n ]}\n />\n </Field>\n ) : null}\n {config.people === 'assignee' ? (\n <Field label={t('customers.calendar.editor.assignee', 'Assignee')}>\n <PeopleField\n mode=\"single\"\n includeCustomers={false}\n placeholder={t('customers.calendar.editor.assigneePlaceholder', 'Assign to a team member\u2026')}\n ariaLabel={t('customers.calendar.editor.assignee', 'Assignee')}\n value={form.assigneeUserId\n ? [{ userId: form.assigneeUserId, name: form.assigneeName ?? form.assigneeUserId, isCustomer: false }]\n : []}\n onChange={(entries) => {\n const next = entries[entries.length - 1] ?? null\n update({ assigneeUserId: next?.userId ?? null, assigneeName: next?.name ?? null })\n }}\n />\n </Field>\n ) : null}\n <Field label={t('customers.calendar.editor.description', 'Description')}>\n <Textarea\n value={form.description}\n onChange={(event) => update({ description: event.target.value })}\n placeholder={t('customers.calendar.editor.descriptionPlaceholder', 'Add details\u2026')}\n aria-label={t('customers.calendar.editor.description', 'Description')}\n className=\"h-24 resize-none\"\n />\n </Field>\n </div>\n </div>\n <div className=\"flex shrink-0 items-center justify-end gap-3 border-t border-border bg-background px-5 py-4\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n >\n {t('customers.calendar.editor.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"button\"\n onClick={handleSave}\n disabled={saving}\n >\n {saving ? t('customers.calendar.editor.saving', 'Saving\u2026') : t('customers.calendar.editor.save', 'Save event')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Calendar, X } from 'lucide-react'\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { extractOptimisticLockConflict } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { CrudForm, type CrudFormGroup, type CrudFormGroupComponentProps } from '@open-mercato/ui/backend/CrudForm'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Dialog, DialogContent, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { Textarea } from '@open-mercato/ui/primitives/textarea'\nimport { useDialogKeyHandler } from '@open-mercato/ui/hooks/useDialogKeyHandler'\nimport { E } from '#generated/entities.ids.generated'\nimport {\n buildEditorTypeOptions,\n buildInteractionPayload,\n computeDurationMinutes,\n createDefaultFormState,\n defaultRepeatDaysForDateInput,\n editorKindOfInteractionType,\n KIND_CONFIG,\n parseItemToFormState,\n resolveSavedOwnerUserId,\n type EditorFormState,\n type EditorKind,\n type EditorPriority,\n} from '../../lib/calendar/editorPayload'\nimport type { ConflictScope } from '../../lib/calendar/preferences'\nimport { renderDictionaryIcon } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { normalizeCustomFieldSubmitValue } from '../detail/customFieldUtils'\nimport type { CalendarItem } from './types'\nimport { EDITOR_SCROLL_EVENT, Field } from './editor/inputs'\nimport { SegmentGroup } from './editor/SegmentGroup'\nimport { PriorityField } from './editor/PriorityField'\nimport { RelatedToField } from './editor/RelatedToField'\nimport { RepeatField } from './editor/RepeatField'\nimport { PeopleField } from './editor/PeopleField'\nimport { ResourcesField } from './editor/ResourcesField'\nimport { ScheduleSection } from './editor/ScheduleSection'\nimport { LocationField } from './editor/LocationField'\nimport { useConflictProbe, useEditorLabelResolution } from './editor/hooks'\n\nexport interface CalendarEventEditorProps {\n open: boolean\n mode: 'create' | 'edit'\n item?: CalendarItem | null\n defaultDate?: Date\n defaultRange?: { start: Date; end: Date } | null\n typeLabels: Record<string, string>\n typeIcons?: Record<string, string | null>\n conflictScope?: ConflictScope\n currentUserId?: string | null\n resourcesEnabled?: boolean\n staffEnabled?: boolean\n onOpenChange(open: boolean): void\n onSaved(): void\n}\n\nconst FORM_ID = 'customers-calendar-event-editor'\nconst INTERACTION_ENTITY_IDS = [E.customers.customer_interaction]\n\nconst PEOPLE_FIELD_TEXT = {\n attendees: { labelKey: 'customers.calendar.editor.attendees', label: 'Attendees', placeholderKey: 'customers.calendar.editor.addPeoplePlaceholder', placeholder: 'Add staff or customer\u2026' },\n participants: { labelKey: 'customers.calendar.editor.participants', label: 'Participants', placeholderKey: 'customers.calendar.editor.addPeoplePlaceholder', placeholder: 'Add staff or customer\u2026' },\n to: { labelKey: 'customers.calendar.editor.to', label: 'To', placeholderKey: 'customers.calendar.editor.addRecipientPlaceholder', placeholder: 'Add recipient\u2026' },\n} as const\n\n// CrudForm values carry the flattened EditorFormState keys (seeded via\n// initialValues) plus cf_* custom-field keys managed by CrudForm itself.\nfunction formStateOfValues(values: Record<string, unknown>): EditorFormState {\n return values as unknown as EditorFormState\n}\n\nfunction customFieldInitialValues(item: CalendarItem): Record<string, unknown> {\n const customValues = (item.raw as Record<string, unknown>).customValues\n if (!customValues || typeof customValues !== 'object' || Array.isArray(customValues)) return {}\n return Object.fromEntries(\n Object.entries(customValues as Record<string, unknown>).map(([key, value]) => [`cf_${key}`, value]),\n )\n}\n\ntype EditorBodyProps = {\n ctx: CrudFormGroupComponentProps\n open: boolean\n isEdit: boolean\n item?: CalendarItem | null\n typeLabels: Record<string, string>\n typeIcons: Record<string, string | null>\n conflictScope: ConflictScope\n currentUserId: string | null\n resourcesEnabled: boolean\n staffEnabled: boolean\n}\n\nfunction EditorBody({\n ctx,\n open,\n isEdit,\n item,\n typeLabels,\n typeIcons,\n conflictScope,\n currentUserId,\n resourcesEnabled,\n staffEnabled,\n}: EditorBodyProps) {\n const t = useT()\n const locale = useLocale()\n const { setValue, errors } = ctx\n const form = formStateOfValues(ctx.values)\n const config = KIND_CONFIG[form.kind]\n\n const update = React.useCallback(\n (patch: Partial<EditorFormState>) => {\n for (const [key, value] of Object.entries(patch)) setValue(key, value)\n },\n [setValue],\n )\n\n useEditorLabelResolution(open, form, update)\n // Probe against the owner the interaction will actually be SAVED with so the\n // editor warning matches the grid's post-save conflict rings: tasks own via\n // their assignee, other kinds stay ownerless on create / keep the existing\n // owner on edit (conflicts then come from shared participants).\n const draftOwnerUserId = resolveSavedOwnerUserId(config, form, isEdit, item?.ownerUserId ?? null)\n // Self-exclude by the underlying interaction id (raw.id): findEditorConflictItems\n // drops candidates by raw.id, and every expanded occurrence of a recurring series\n // shares it \u2014 so the edited record never conflicts with itself.\n const conflict = useConflictProbe(open, form, config, isEdit && item ? item.raw.id : null, draftOwnerUserId, conflictScope, currentUserId)\n\n const kindLabels = React.useMemo(\n () => ({\n meeting: t('customers.calendar.editor.types.meeting', 'meeting'),\n call: t('customers.calendar.editor.types.call', 'call'),\n email: t('customers.calendar.editor.types.email', 'email'),\n note: t('customers.calendar.editor.types.note', 'note'),\n event: t('customers.calendar.editor.types.event', 'event'),\n task: t('customers.calendar.editor.types.task', 'task'),\n }),\n [t],\n ) satisfies Record<EditorKind, string>\n\n const selectedType = form.category ?? form.kind\n const typeOptions = React.useMemo(\n () => buildEditorTypeOptions({ typeLabels, typeIcons, selectedValue: selectedType, kindLabels }),\n [typeLabels, typeIcons, selectedType, kindLabels],\n )\n const typeSwitcherOptions = React.useMemo(\n () =>\n typeOptions.map((option) => ({\n value: option.value,\n label: option.label,\n icon: renderDictionaryIcon(option.icon, 'h-4 w-4'),\n })),\n [typeOptions],\n )\n\n // Candidates for the Call \"insert phone from contact\" button: the linked\n // person (companies have no phone) + customer attendees. Their userId is the\n // person id, so the picker can resolve primary_phone from the people API.\n const phoneContactIds = React.useMemo(() => {\n const ids: string[] = []\n if (form.relatedTo && form.relatedTo.kind !== 'company') ids.push(form.relatedTo.id)\n for (const participant of form.participants) {\n if (participant.isCustomer) ids.push(participant.userId)\n }\n return Array.from(new Set(ids))\n }, [form.relatedTo, form.participants])\n\n const titleLabel = form.kind === 'email'\n ? t('customers.calendar.editor.titleLabel.email', 'Subject')\n : form.kind === 'note'\n ? t('customers.calendar.editor.titleLabel.note', 'Note')\n : t('customers.calendar.editor.titleLabel.generic', 'Title')\n\n return (\n // Single column on phones (full-screen sheet). On lg+ the dialog widens and\n // the fields group into two thematic columns: WHEN (schedule + repeat) on\n // the left, CONTEXT (related record, category, location) on the right;\n // people/resources and the task fields pair up below; title, description\n // and the type switcher span both columns.\n <div className=\"grid w-full grid-cols-1 items-start gap-4 lg:grid-cols-2 lg:gap-x-6\">\n {conflict ? (\n <Alert variant=\"warning\" className=\"rounded-lg lg:col-span-2\">\n <AlertTitle>{t('customers.calendar.editor.conflictTitle', 'Calendar conflict')}</AlertTitle>\n <AlertDescription>{conflict}</AlertDescription>\n </Alert>\n ) : null}\n <div className=\"w-full lg:col-span-2\">\n <SegmentGroup<string>\n ariaLabel={t('customers.calendar.editor.typeSwitcher', 'Event type')}\n value={selectedType}\n onChange={(type) => update({ kind: editorKindOfInteractionType(type), category: type })}\n options={typeSwitcherOptions}\n />\n </div>\n <Field label={titleLabel} error={errors.title} className=\"lg:col-span-2\">\n <Input\n type=\"text\"\n value={form.title}\n onChange={(event) => update({ title: event.target.value })}\n placeholder={t('customers.calendar.editor.titlePlaceholder', 'Add a title\u2026')}\n aria-label={titleLabel}\n autoFocus\n size=\"lg\"\n />\n </Field>\n <div className=\"flex w-full flex-col gap-4\">\n <ScheduleSection\n dateLabel={config.dateLabel}\n hasAllDay={config.hasAllDay}\n hasEnd={config.hasEnd}\n allDay={form.allDay}\n date={form.date}\n startTime={form.startTime}\n endDate={form.endDate}\n endTime={form.endTime}\n locale={locale}\n endsError={errors.ends}\n onAllDayChange={(allDay) => update({ allDay })}\n onDateChange={(date) => {\n const untouchedDefault =\n JSON.stringify(form.repeatDays) === JSON.stringify(defaultRepeatDaysForDateInput(form.date))\n update(\n untouchedDefault\n ? { date, repeatDays: defaultRepeatDaysForDateInput(date) }\n : { date },\n )\n }}\n onStartTimeChange={(startTime) => update({ startTime })}\n onEndDateChange={(endDate) => update({ endDate })}\n onEndTimeChange={(endTime) => update({ endTime })}\n />\n {config.hasRepeat ? (\n <RepeatField\n freq={form.repeatFreq}\n days={form.repeatDays}\n endType={form.repeatEndType}\n count={form.repeatCount}\n untilDate={form.repeatUntilDate}\n locale={locale}\n onFreqChange={(repeatFreq) =>\n update(\n repeatFreq === 'weekly'\n ? { repeatFreq, repeatDays: defaultRepeatDaysForDateInput(form.date) }\n : { repeatFreq },\n )}\n onToggleDay={(index) =>\n update({ repeatDays: form.repeatDays.map((active, dayIndex) => (dayIndex === index ? !active : active)) })}\n onEndTypeChange={(repeatEndType) => update({ repeatEndType })}\n onCountChange={(repeatCount) => update({ repeatCount })}\n onUntilDateChange={(repeatUntilDate) => update({ repeatUntilDate })}\n />\n ) : null}\n {config.people && config.people !== 'assignee' ? (\n <Field label={t(PEOPLE_FIELD_TEXT[config.people].labelKey, PEOPLE_FIELD_TEXT[config.people].label)}>\n <PeopleField\n mode=\"multi\"\n includeCustomers\n includeStaff={staffEnabled}\n placeholder={t(PEOPLE_FIELD_TEXT[config.people].placeholderKey, PEOPLE_FIELD_TEXT[config.people].placeholder)}\n ariaLabel={t(PEOPLE_FIELD_TEXT[config.people].labelKey, PEOPLE_FIELD_TEXT[config.people].label)}\n value={form.participants}\n onChange={(participants) => update({ participants })}\n />\n </Field>\n ) : null}\n {config.people === 'assignee' && staffEnabled ? (\n <Field label={t('customers.calendar.editor.assignee', 'Assignee')} error={errors.assignee}>\n <PeopleField\n mode=\"single\"\n includeCustomers={false}\n includeStaff\n placeholder={t('customers.calendar.editor.assigneePlaceholder', 'Assign to a team member\u2026')}\n ariaLabel={t('customers.calendar.editor.assignee', 'Assignee')}\n value={form.assigneeUserId\n ? [{ userId: form.assigneeUserId, name: form.assigneeName ?? form.assigneeUserId, isCustomer: false }]\n : []}\n onChange={(entries) => {\n const next = entries[entries.length - 1] ?? null\n update({ assigneeUserId: next?.userId ?? null, assigneeName: next?.name ?? null })\n }}\n />\n </Field>\n ) : null}\n </div>\n <div className=\"flex w-full flex-col gap-4\">\n <Field label={t('customers.calendar.editor.relatedTo', 'Related to')} error={errors.relatedTo}>\n <RelatedToField\n label={t('customers.calendar.editor.relatedTo', 'Related to')}\n value={form.relatedTo}\n deal={form.dealId && form.dealLabel ? { id: form.dealId, label: form.dealLabel } : null}\n onChange={(relatedTo) => update({ relatedTo })}\n onDealChange={(deal) => update({ dealId: deal?.id ?? null, dealLabel: deal?.label ?? null })}\n error={errors.relatedTo}\n />\n </Field>\n {config.location ? (\n <LocationField\n variant={config.location}\n value={form.location}\n onChange={(location) => update({ location })}\n phoneContactIds={phoneContactIds}\n />\n ) : null}\n {resourcesEnabled ? (\n <Field label={t('customers.calendar.editor.resources', 'Resources')}>\n <ResourcesField\n placeholder={t('customers.calendar.editor.resourcesPlaceholder', 'Add a resource\u2026')}\n ariaLabel={t('customers.calendar.editor.resources', 'Resources')}\n value={form.resources}\n onChange={(resources) => update({ resources })}\n />\n </Field>\n ) : null}\n {config.hasPriority ? (\n <Field label={t('customers.calendar.editor.priority.label', 'Priority')}>\n <PriorityField\n value={form.priority}\n ariaLabel={t('customers.calendar.editor.priority.label', 'Priority')}\n labels={{\n low: t('customers.calendar.editor.priority.low', 'Low'),\n medium: t('customers.calendar.editor.priority.medium', 'Medium'),\n high: t('customers.calendar.editor.priority.high', 'High'),\n }}\n onChange={(priority) => update({ priority })}\n />\n </Field>\n ) : null}\n </div>\n <Field label={t('customers.calendar.editor.description', 'Description')} className=\"lg:col-span-2\">\n <Textarea\n value={form.description}\n onChange={(event) => update({ description: event.target.value })}\n placeholder={t('customers.calendar.editor.descriptionPlaceholder', 'Add details\u2026')}\n aria-label={t('customers.calendar.editor.description', 'Description')}\n className=\"h-20 resize-none\"\n />\n </Field>\n </div>\n )\n}\n\nexport function CalendarEventEditor({\n open,\n mode,\n item,\n defaultDate,\n defaultRange,\n typeLabels,\n typeIcons,\n conflictScope,\n currentUserId,\n resourcesEnabled,\n staffEnabled,\n onOpenChange,\n onSaved,\n}: CalendarEventEditorProps) {\n const t = useT()\n const [saving, setSaving] = React.useState(false)\n const isEdit = mode === 'edit' && Boolean(item?.id)\n\n // CrudForm reads initialValues once, so every dialog open gets a fresh form\n // instance keyed by the open sequence + edited record.\n const [openSeq, setOpenSeq] = React.useState(0)\n const wasOpenRef = React.useRef(false)\n React.useEffect(() => {\n if (open && !wasOpenRef.current) setOpenSeq((seq) => seq + 1)\n wasOpenRef.current = open\n }, [open])\n const formKey = `${mode}:${item?.id ?? 'new'}:${openSeq}`\n\n const initialValues = React.useMemo<Record<string, unknown>>(() => {\n if (isEdit && item) {\n return {\n ...parseItemToFormState(item),\n ...customFieldInitialValues(item),\n id: item.id,\n updatedAt: item.updatedAt ?? undefined,\n }\n }\n return { ...createDefaultFormState(defaultDate ?? null, undefined, defaultRange ?? null) }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- openSeq re-seeds defaults per dialog open\n }, [isEdit, item, defaultDate, defaultRange, openSeq])\n\n const handleSubmit = React.useCallback(\n async (values: Record<string, unknown>) => {\n const form = formStateOfValues(values)\n const config = KIND_CONFIG[form.kind]\n const fieldErrors: Record<string, string> = {}\n if (!form.title.trim()) {\n fieldErrors.title = t('customers.calendar.editor.validation.titleRequired', 'Title is required')\n }\n if (!form.relatedTo) {\n fieldErrors.relatedTo = t('customers.calendar.editor.validation.relatedToRequired', 'Select a person or company to link this event')\n }\n if (config.hasEnd && !form.allDay && computeDurationMinutes(form) === null) {\n fieldErrors.ends = t('customers.calendar.editor.validation.endsBeforeStarts', 'End must be after start')\n }\n // A task must be assigned to a team member \u2014 surface the requirement inline\n // instead of letting the save fail with no visible reason (#3747 feedback).\n if (config.people === 'assignee' && staffEnabled !== false && !form.assigneeUserId) {\n fieldErrors.assignee = t('customers.calendar.editor.validation.assigneeRequired', 'Assign this task to a team member')\n }\n if (Object.keys(fieldErrors).length > 0) {\n throw createCrudFormError(Object.values(fieldErrors)[0], fieldErrors)\n }\n setSaving(true)\n try {\n const payload = buildInteractionPayload(form, {\n mode,\n id: item?.id,\n resourcesEnabled: resourcesEnabled === true,\n staffEnabled: staffEnabled !== false,\n })\n const custom = collectCustomFieldValues(values, {\n transform: (value) => normalizeCustomFieldSubmitValue(value),\n })\n for (const [key, value] of Object.entries(custom)) payload[`cf_${key}`] = value\n // CrudForm supplies the optimistic-lock header (auto-derived from\n // initialValues.updatedAt) via scoped request headers around onSubmit.\n await apiCallOrThrow('/api/customers/interactions', {\n method: isEdit ? 'PUT' : 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n })\n flash(t('customers.calendar.editor.saved', 'Event saved'), 'success')\n onOpenChange(false)\n requestAnimationFrame(() => { onSaved() })\n } catch (err) {\n // Surface an optimistic-lock 409 as the persistent conflict bar and\n // close \u2014 the bar renders at page level, behind the dialog overlay.\n if (extractOptimisticLockConflict(err)) {\n surfaceRecordConflict(err, t)\n onOpenChange(false)\n return\n }\n throw err\n } finally {\n setSaving(false)\n }\n },\n [isEdit, item?.id, mode, onOpenChange, onSaved, resourcesEnabled, staffEnabled, t],\n )\n\n const groups = React.useMemo<CrudFormGroup[]>(\n () => [\n {\n id: 'details',\n bare: true,\n component: (ctx) => (\n <EditorBody\n ctx={ctx}\n open={open}\n isEdit={isEdit}\n item={item}\n typeLabels={typeLabels}\n typeIcons={typeIcons ?? {}}\n conflictScope={conflictScope ?? 'all'}\n currentUserId={currentUserId ?? null}\n resourcesEnabled={resourcesEnabled === true}\n staffEnabled={staffEnabled !== false}\n />\n ),\n },\n { id: 'customFields', kind: 'customFields' },\n ],\n [open, isEdit, item, typeLabels, typeIcons, conflictScope, currentUserId, resourcesEnabled, staffEnabled],\n )\n\n const handleKeyDown = useDialogKeyHandler({\n onConfirm: () => {\n const formElement = document.getElementById(FORM_ID)\n if (formElement instanceof HTMLFormElement) formElement.requestSubmit()\n },\n disabled: saving,\n })\n\n const dialogTitle = isEdit ? t('customers.calendar.editor.title.edit', 'Edit event') : t('customers.calendar.editor.title.create', 'New event')\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n onKeyDown={handleKeyDown}\n // Only dismiss on a genuine click OUTSIDE the whole editor. Radix\n // relays a click inside the dialog (but outside an open DS\n // DatePicker/Select popover) up to the dialog as an \"interact\n // outside\" event when it dismisses that popover \u2014 without this guard\n // it would tear down the entire editor. Keep it open when the target\n // is inside the dialog body or inside any portalled popover.\n onInteractOutside={(event) => {\n const target = event.detail.originalEvent.target as HTMLElement | null\n if (target?.closest('[data-dialog-content]') || target?.closest('[data-radix-popper-content-wrapper]')) {\n event.preventDefault()\n }\n }}\n aria-describedby={undefined}\n dismissible={false}\n className=\"flex h-dvh max-h-dvh w-screen max-w-none flex-col gap-0 overflow-hidden rounded-none border-0 bg-background p-0 shadow-xl sm:h-auto sm:max-h-[calc(100dvh-4rem)] sm:w-full sm:max-w-lg sm:rounded-2xl sm:border-0 lg:max-w-3xl\"\n >\n <VisuallyHidden>\n <DialogTitle>{dialogTitle}</DialogTitle>\n </VisuallyHidden>\n <div className=\"flex shrink-0 items-center gap-3 border-b border-border bg-background py-4 pl-5 pr-4\">\n <Calendar aria-hidden className=\"size-6 shrink-0 text-foreground\" strokeWidth={1.75} />\n <p className=\"min-w-0 flex-1 text-sm font-medium leading-5 text-foreground\">{dialogTitle}</p>\n <IconButton\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onOpenChange(false)}\n aria-label={t('customers.calendar.editor.close', 'Close')}\n className=\"shrink-0 text-muted-foreground\"\n >\n <X aria-hidden className=\"size-5\" />\n </IconButton>\n </div>\n <div\n className=\"flex-1 overflow-y-auto\"\n onScroll={() => {\n // Tell the DS date/time fields to close their (controlled) popover\n // so a portalled popover doesn't float over the form or drift away\n // from its field while scrolling (#3747 feedback). Radix ignores\n // synthetic dismiss events, so the fields drive their own `open`.\n document.dispatchEvent(new CustomEvent(EDITOR_SCROLL_EVENT))\n }}\n >\n <div className=\"px-4 py-4 sm:px-6 sm:py-5\">\n <CrudForm<Record<string, unknown>>\n key={formKey}\n formId={FORM_ID}\n embedded\n hideFooterActions\n customFieldsManageMode=\"page\"\n fields={[]}\n groups={groups}\n initialValues={initialValues}\n entityIds={INTERACTION_ENTITY_IDS}\n onSubmit={handleSubmit}\n />\n </div>\n </div>\n <div className=\"flex shrink-0 items-center justify-end gap-3 border-t border-border bg-background px-5 py-4\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n >\n {t('customers.calendar.editor.cancel', 'Cancel')}\n </Button>\n <Button\n type=\"submit\"\n form={FORM_ID}\n disabled={saving}\n >\n {saving ? t('customers.calendar.editor.saving', 'Saving\u2026') : t('customers.calendar.editor.save', 'Save event')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -85,7 +85,7 @@ function resolveJoinUrl(location) {
85
85
  function asEditableItem(item) {
86
86
  return item.isRecurringOccurrence ? { ...item, id: item.raw.id } : item;
87
87
  }
88
- function CalendarScreen() {
88
+ function CalendarScreen({ resourcesEnabled = false, staffEnabled = true } = {}) {
89
89
  const t = useT();
90
90
  const [view, setView] = React.useState("week");
91
91
  const [anchor, setAnchor] = React.useState(() => /* @__PURE__ */ new Date());
@@ -112,7 +112,7 @@ function CalendarScreen() {
112
112
  () => getVisibleRange(view, anchor, agendaHorizonDays),
113
113
  [view, anchor, agendaHorizonDays]
114
114
  );
115
- const { items, isLoading, error, truncated, typeLabels, typeColors, refetch } = useCalendarItems(range);
115
+ const { items, isLoading, error, truncated, typeLabels, typeColors, typeIcons, refetch } = useCalendarItems(range);
116
116
  React.useEffect(() => {
117
117
  if (!isLoading) setHasLoadedOnce(true);
118
118
  }, [isLoading]);
@@ -500,11 +500,11 @@ function CalendarScreen() {
500
500
  defaultDate: anchor,
501
501
  defaultRange: createRange,
502
502
  typeLabels,
503
- typeColors,
504
- surfacedTypes: preferences.activityTypes,
505
- eventCategories: preferences.eventCategories,
503
+ typeIcons,
506
504
  conflictScope: preferences.conflictScope,
507
505
  currentUserId,
506
+ resourcesEnabled,
507
+ staffEnabled,
508
508
  onOpenChange: (open) => setEditor((current) => ({ ...current, open })),
509
509
  onSaved: refetch
510
510
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/calendar/CalendarScreen.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport dynamic from 'next/dynamic'\nimport { addDays } from 'date-fns/addDays'\nimport { isSameDay } from 'date-fns/isSameDay'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall, apiCallOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { matchFeature } from '@open-mercato/shared/lib/auth/featureMatch'\nimport {\n buildOptimisticLockHeader,\n extractOptimisticLockConflict,\n} from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { countByCategory } from '../../lib/calendar/categories'\nimport { findConflicts } from '../../lib/calendar/conflicts'\nimport { getVisibleRange } from '../../lib/calendar/range'\nimport { AgendaList } from './AgendaList'\nimport { CalendarFooter } from './CalendarFooter'\nimport { CalendarHeader } from './CalendarHeader'\nimport { CalendarTabs } from './CalendarTabs'\nimport { CalendarToolbar } from './CalendarToolbar'\nimport { MonthGrid } from './MonthGrid'\nimport { ShortcutsDialog } from './ShortcutsDialog'\nimport { TimeGrid } from './TimeGrid'\nimport { UpcomingCards } from './UpcomingCards'\nimport { CalendarSettingsModal } from './CalendarSettingsModal'\nimport { useCalendarPreferences } from './useCalendarPreferences'\nimport { MAX_WINDOW_ITEMS, useCalendarItems } from './useCalendarItems'\nimport type {\n CalendarFiltersValue,\n CalendarItem,\n CalendarRangePreset,\n CalendarTab,\n CalendarView,\n UpcomingCard,\n} from './types'\n\nconst CalendarEventEditor = dynamic(\n () => import('./CalendarEventEditor').then((mod) => mod.CalendarEventEditor),\n { ssr: false },\n)\n\nconst SEARCH_DEBOUNCE_MS = 200\nconst PHONE_BREAKPOINT_PX = 640\nconst HIGHLIGHT_CLEAR_MS = 3000\nconst DEFAULT_AGENDA_HORIZON_DAYS = 7\nconst UPCOMING_CARDS_COUNT = 4\nconst EMPTY_FILTERS: CalendarFiltersValue = { types: [], status: null, ownerUserId: null }\n\ntype EditorState = { open: boolean; mode: 'create' | 'edit'; item: CalendarItem | null }\n\nconst MANAGE_FEATURE = 'customers.interactions.manage'\n\nfunction useCanManageInteractions(): boolean {\n const [canManage, setCanManage] = React.useState(false)\n React.useEffect(() => {\n const controller = new AbortController()\n let cancelled = false\n apiCall<{ granted?: unknown[] }>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n signal: controller.signal,\n body: JSON.stringify({ features: [MANAGE_FEATURE] }),\n })\n .then((call) => {\n if (cancelled || !call.ok) return\n const granted = Array.isArray(call.result?.granted)\n ? call.result.granted.map((feature) => String(feature))\n : []\n setCanManage(granted.some((grantedFeature) => matchFeature(MANAGE_FEATURE, grantedFeature)))\n })\n .catch(() => {\n if (!cancelled && !controller.signal.aborted) setCanManage(false)\n })\n return () => {\n cancelled = true\n controller.abort()\n }\n }, [])\n return canManage\n}\n\nfunction buildTimezoneLabel(): string {\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone\n const offsetMinutes = -new Date().getTimezoneOffset()\n const sign = offsetMinutes >= 0 ? '+' : '-'\n const absolute = Math.abs(offsetMinutes)\n const hours = Math.floor(absolute / 60)\n const minutes = absolute % 60\n const offset = minutes > 0 ? `${sign}${hours}:${String(minutes).padStart(2, '0')}` : `${sign}${hours}`\n return `${timeZone} (GMT${offset})`\n}\n\nfunction resolveJoinUrl(location: string | null): string | null {\n const trimmed = location?.trim() ?? ''\n if (!trimmed) return null\n if (/^https?:\\/\\//i.test(trimmed)) return trimmed\n if (/^www\\./i.test(trimmed)) return `https://${trimmed}`\n return null\n}\n\nfunction asEditableItem(item: CalendarItem): CalendarItem {\n return item.isRecurringOccurrence ? { ...item, id: item.raw.id } : item\n}\n\nexport function CalendarScreen() {\n const t = useT()\n const [view, setView] = React.useState<CalendarView>('week')\n const [anchor, setAnchor] = React.useState<Date>(() => new Date())\n const [agendaHorizonDays, setAgendaHorizonDays] = React.useState(DEFAULT_AGENDA_HORIZON_DAYS)\n const [preset, setPreset] = React.useState<CalendarRangePreset | null>('thisWeek')\n\n React.useEffect(() => {\n if (window.innerWidth >= PHONE_BREAKPOINT_PX) return\n setView('day')\n setPreset(null)\n }, [])\n const [tab, setTab] = React.useState<CalendarTab>('all')\n const [searchText, setSearchText] = React.useState('')\n const [debouncedSearch, setDebouncedSearch] = React.useState('')\n const [filters, setFilters] = React.useState<CalendarFiltersValue>(EMPTY_FILTERS)\n const [editor, setEditor] = React.useState<EditorState>({ open: false, mode: 'create', item: null })\n const [editorMounted, setEditorMounted] = React.useState(false)\n const [createRange, setCreateRange] = React.useState<{ start: Date; end: Date } | null>(null)\n const [shortcutsOpen, setShortcutsOpen] = React.useState(false)\n const [settingsOpen, setSettingsOpen] = React.useState(false)\n const [highlightItemId, setHighlightItemId] = React.useState<string | null>(null)\n const [hasLoadedOnce, setHasLoadedOnce] = React.useState(false)\n const { preferences, setPreferences, hydrated: preferencesHydrated, userId: currentUserId } = useCalendarPreferences()\n\n const range = React.useMemo(\n () => getVisibleRange(view, anchor, agendaHorizonDays),\n [view, anchor, agendaHorizonDays],\n )\n const { items, isLoading, error, truncated, typeLabels, typeColors, refetch } = useCalendarItems(range)\n\n React.useEffect(() => {\n if (!isLoading) setHasLoadedOnce(true)\n }, [isLoading])\n\n React.useEffect(() => {\n const timer = window.setTimeout(() => setDebouncedSearch(searchText), SEARCH_DEBOUNCE_MS)\n return () => window.clearTimeout(timer)\n }, [searchText])\n\n React.useEffect(() => {\n if (!highlightItemId) return\n const timer = window.setTimeout(() => setHighlightItemId(null), HIGHLIGHT_CLEAR_MS)\n return () => window.clearTimeout(timer)\n }, [highlightItemId])\n\n const visibleItems = React.useMemo(\n () => items.filter((item) => item.end > range.from && item.start < range.to),\n [items, range],\n )\n\n const searchedItems = React.useMemo(() => {\n const query = debouncedSearch.trim().toLowerCase()\n if (!query) return visibleItems\n return visibleItems.filter((item) => {\n if (item.title.toLowerCase().includes(query)) return true\n if (item.location && item.location.toLowerCase().includes(query)) return true\n const rawBody = (item.raw as { body?: unknown }).body\n if (typeof rawBody === 'string' && rawBody.toLowerCase().includes(query)) return true\n return item.participants.some((participant) =>\n (participant.name ?? '').toLowerCase().includes(query),\n )\n })\n }, [visibleItems, debouncedSearch])\n\n const baseItems = React.useMemo(\n () =>\n searchedItems.filter((item) => {\n if (filters.types.length > 0 && !filters.types.includes(item.interactionType)) return false\n if (filters.status && item.status !== filters.status) return false\n if (filters.ownerUserId && item.ownerUserId !== filters.ownerUserId) return false\n if (!preferences.showCrmActivities && item.category !== 'meeting' && item.category !== 'event') return false\n return true\n }),\n [searchedItems, filters, preferences.showCrmActivities],\n )\n\n const tabCounts = React.useMemo(() => countByCategory(baseItems), [baseItems])\n\n const viewItems = React.useMemo(() => {\n if (tab === 'meetings') return baseItems.filter((item) => item.category === 'meeting')\n if (tab === 'events') return baseItems.filter((item) => item.category === 'event')\n return baseItems\n }, [baseItems, tab])\n\n const conflictMap = React.useMemo(\n () => findConflicts(baseItems, { scope: preferences.conflictScope, currentUserId }),\n [baseItems, preferences.conflictScope, currentUserId],\n )\n const conflictIds = React.useMemo(() => new Set(conflictMap.keys()), [conflictMap])\n\n const upcomingCards = React.useMemo<UpcomingCard[]>(() => {\n const now = new Date()\n const nowMs = now.getTime()\n return baseItems\n .filter((item) => item.start.getTime() >= nowMs)\n .sort((first, second) => first.start.getTime() - second.start.getTime())\n .slice(0, UPCOMING_CARDS_COUNT)\n .map((item) => {\n const conflictCount = preferences.conflictWarnings ? (conflictMap.get(item.id)?.length ?? 0) : 0\n const kind: UpcomingCard['kind'] =\n item.status === 'canceled'\n ? 'cancelled'\n : conflictCount > 0\n ? 'conflicted'\n : isSameDay(item.start, now)\n ? 'today'\n : 'future'\n return { item, kind, conflictCount }\n })\n }, [baseItems, conflictMap, preferences.conflictWarnings])\n\n const typeOptions = React.useMemo(() => {\n const values = new Set<string>(Object.keys(typeLabels))\n for (const item of items) values.add(item.interactionType)\n return [...values]\n .sort((a, b) => a.localeCompare(b))\n .map((value) => ({ value, label: typeLabels[value] ?? value }))\n }, [items, typeLabels])\n\n const ownerOptions = React.useMemo(() => {\n const participantNames = new Map<string, string>()\n for (const item of items) {\n for (const participant of item.participants) {\n if (participant.name && !participantNames.has(participant.userId)) {\n participantNames.set(participant.userId, participant.name)\n }\n }\n }\n const owners = new Map<string, string>()\n for (const item of items) {\n if (!item.ownerUserId || owners.has(item.ownerUserId)) continue\n owners.set(item.ownerUserId, participantNames.get(item.ownerUserId) ?? item.ownerUserId)\n }\n return [...owners.entries()]\n .map(([value, label]) => ({ value, label }))\n .sort((first, second) => first.label.localeCompare(second.label))\n }, [items])\n\n const timezoneLabel = React.useMemo(() => buildTimezoneLabel(), [])\n\n const canManage = useCanManageInteractions()\n\n const openCreateEditor = React.useCallback(() => {\n if (!canManage) return\n setCreateRange(null)\n setEditorMounted(true)\n setEditor({ open: true, mode: 'create', item: null })\n }, [canManage])\n\n const openEditEditor = React.useCallback(\n (item: CalendarItem) => {\n if (!canManage) return\n setCreateRange(null)\n setEditorMounted(true)\n setEditor({ open: true, mode: 'edit', item: asEditableItem(item) })\n },\n [canManage],\n )\n\n const handleCreateRange = React.useCallback(\n (start: Date, end: Date) => {\n if (!canManage) return\n setCreateRange({ start, end })\n setEditorMounted(true)\n setEditor({ open: true, mode: 'create', item: null })\n },\n [canManage],\n )\n\n const seedActivityTypes = React.useMemo(() => {\n const seen = new Set<string>()\n const labels: string[] = []\n for (const value of Object.keys(typeLabels)) {\n const label = typeLabels[value] ?? value\n if (seen.has(label)) continue\n seen.add(label)\n labels.push(label)\n }\n return labels\n }, [typeLabels])\n\n const handleToday = React.useCallback(() => {\n setAnchor(new Date())\n setPreset(null)\n }, [])\n\n const handlePresetChange = React.useCallback((next: CalendarRangePreset) => {\n setPreset(next)\n setAnchor(new Date())\n if (next === 'thisWeek') {\n setView('week')\n } else if (next === 'thisMonth') {\n setView('month')\n } else {\n setView('agenda')\n setAgendaHorizonDays(next === 'next30' ? 30 : DEFAULT_AGENDA_HORIZON_DAYS)\n }\n }, [])\n\n const handleAnchorChange = React.useCallback((date: Date) => {\n setAnchor(date)\n setPreset(null)\n }, [])\n\n const handleViewChange = React.useCallback((next: CalendarView) => {\n setView(next)\n setPreset(null)\n }, [])\n\n const handleTimeGridNavigate = React.useCallback((deltaDays: number) => {\n setAnchor((current) => addDays(current, deltaDays))\n setPreset(null)\n }, [])\n\n const handleDayOpen = React.useCallback((date: Date) => {\n setView('day')\n setAnchor(date)\n setPreset(null)\n }, [])\n\n const handleSeeConflict = React.useCallback((item: CalendarItem) => {\n setView('week')\n setAnchor(item.start)\n setPreset(null)\n setHighlightItemId(item.id)\n }, [])\n\n const handleJoin = React.useCallback((item: CalendarItem) => {\n const url = resolveJoinUrl(item.location)\n if (url) window.open(url, '_blank', 'noopener')\n }, [])\n\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: 'customers-calendar-cancel',\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const handleCancelItem = React.useCallback(\n async (item: CalendarItem) => {\n const interactionId = item.raw.id\n try {\n await runMutation({\n operation: () =>\n withScopedApiRequestHeaders(buildOptimisticLockHeader(item.updatedAt), () =>\n apiCallOrThrow('/api/customers/interactions', {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: interactionId, status: 'canceled' }),\n }),\n ),\n mutationPayload: {\n operation: 'cancelCalendarEvent',\n interactionId,\n interactionType: item.interactionType,\n },\n context: {\n formId: 'customers-calendar-cancel',\n resourceKind: 'customers.interaction',\n resourceId: interactionId,\n retryLastMutation,\n },\n })\n flash(t('customers.calendar.cards.cancelSuccess', 'Event cancelled'), 'success')\n refetch()\n } catch (err) {\n // An optimistic-lock 409 is surfaced as the persistent conflict bar by\n // useGuardedMutation (surfaceRecordConflict) \u2014 don't re-flash.\n if (extractOptimisticLockConflict(err)) return\n flash(t('customers.calendar.cards.cancelError', 'Failed to cancel event'), 'error')\n }\n },\n [refetch, retryLastMutation, runMutation, t],\n )\n\n const focusSearch = React.useCallback(() => {\n const node = document.querySelector('[data-calendar-search]')\n if (node instanceof HTMLInputElement) node.focus()\n else if (node instanceof HTMLElement) node.querySelector('input')?.focus()\n }, [])\n\n const editorOpen = editor.open\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.defaultPrevented) return\n if (event.metaKey || event.ctrlKey || event.altKey) return\n const target = event.target\n if (target instanceof HTMLElement) {\n const tag = target.tagName\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable) return\n }\n if (editorOpen) return\n switch (event.key) {\n case 't':\n case 'T':\n event.preventDefault()\n setAnchor(new Date())\n setPreset(null)\n break\n case 'd':\n case 'D':\n event.preventDefault()\n setView('day')\n setPreset(null)\n break\n case 'w':\n case 'W':\n event.preventDefault()\n setView('week')\n setPreset(null)\n break\n case 'm':\n case 'M':\n event.preventDefault()\n setView('month')\n setPreset(null)\n break\n case 'a':\n case 'A':\n event.preventDefault()\n setView('agenda')\n setPreset(null)\n break\n case 'n':\n case 'N':\n event.preventDefault()\n openCreateEditor()\n break\n case '/':\n event.preventDefault()\n focusSearch()\n break\n case '?':\n event.preventDefault()\n setShortcutsOpen((open) => !open)\n break\n case 'Escape':\n setHighlightItemId(null)\n break\n default:\n break\n }\n }\n window.addEventListener('keydown', handleKeyDown)\n return () => window.removeEventListener('keydown', handleKeyDown)\n }, [editorOpen, focusSearch, openCreateEditor])\n\n const showInitialLoading = (isLoading && !hasLoadedOnce) || !preferencesHydrated\n\n let viewArea: React.ReactNode\n if (error) {\n viewArea = (\n <ErrorMessage\n label={t('customers.calendar.errors.loadFailed', 'Failed to load calendar events.')}\n action={\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={refetch}>\n {t('customers.calendar.errors.retry', 'Retry')}\n </Button>\n }\n />\n )\n } else if (showInitialLoading) {\n viewArea = <LoadingMessage label={t('customers.calendar.loading', 'Loading calendar\u2026')} />\n } else if (view === 'month') {\n viewArea = (\n <MonthGrid anchor={anchor} items={viewItems} onItemClick={openEditEditor} onDayOpen={handleDayOpen} />\n )\n } else if (view === 'agenda') {\n viewArea = (\n <AgendaList\n anchor={anchor}\n horizonDays={agendaHorizonDays}\n items={viewItems}\n typeLabels={typeLabels}\n onItemClick={openEditEditor}\n />\n )\n } else {\n viewArea = (\n <TimeGrid\n days={view === 'day' ? 1 : 7}\n anchor={anchor}\n items={viewItems}\n conflictIds={conflictIds}\n showWeekends={preferences.showWeekends}\n showConflicts={preferences.conflictWarnings}\n aiSummaries={preferences.aiSummaries}\n canManage={canManage}\n highlightItemId={highlightItemId}\n onItemClick={openEditEditor}\n onJoin={handleJoin}\n onNavigate={handleTimeGridNavigate}\n onCreate={canManage ? openCreateEditor : undefined}\n onCreateRange={canManage ? handleCreateRange : undefined}\n />\n )\n }\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col gap-4\">\n <CalendarHeader view={view} anchor={anchor} onNewEvent={canManage ? openCreateEditor : undefined} />\n <CalendarToolbar\n view={view}\n anchor={anchor}\n range={range}\n preset={preset}\n search={searchText}\n filters={filters}\n typeOptions={typeOptions}\n ownerOptions={ownerOptions}\n onToday={handleToday}\n onPresetChange={handlePresetChange}\n onAnchorChange={handleAnchorChange}\n onSearchChange={setSearchText}\n onFiltersChange={setFilters}\n onOpenSettings={() => setSettingsOpen(true)}\n />\n <UpcomingCards\n cards={upcomingCards}\n canManage={canManage}\n onJoin={handleJoin}\n onSeeConflict={handleSeeConflict}\n onOpen={openEditEditor}\n onEdit={openEditEditor}\n onCancel={handleCancelItem}\n />\n <div className=\"flex min-h-0 flex-1 flex-col gap-3\">\n <CalendarTabs\n tab={tab}\n counts={tabCounts}\n view={view}\n onTabChange={setTab}\n onViewChange={handleViewChange}\n />\n {truncated ? (\n <p className=\"text-xs text-muted-foreground\" role=\"status\">\n {t('customers.calendar.notice.truncated', 'Showing first {count} items for this range.', {\n count: MAX_WINDOW_ITEMS,\n })}\n </p>\n ) : null}\n <div className=\"flex min-h-[560px] flex-1 flex-col [&>*]:flex-1\">{viewArea}</div>\n </div>\n <div className=\"hidden md:block\">\n <CalendarFooter timezoneLabel={timezoneLabel} onOpenShortcuts={() => setShortcutsOpen(true)} />\n </div>\n <ShortcutsDialog open={shortcutsOpen} onOpenChange={setShortcutsOpen} />\n <CalendarSettingsModal\n open={settingsOpen}\n preferences={preferences}\n seedActivityTypes={seedActivityTypes}\n onOpenChange={setSettingsOpen}\n onSave={(next) => {\n setPreferences(next)\n flash(t('customers.calendar.settings.saved', 'Calendar settings saved'), 'success')\n }}\n />\n {editorMounted ? (\n <CalendarEventEditor\n open={editor.open}\n mode={editor.mode}\n item={editor.item}\n defaultDate={anchor}\n defaultRange={createRange}\n typeLabels={typeLabels}\n typeColors={typeColors}\n surfacedTypes={preferences.activityTypes}\n eventCategories={preferences.eventCategories}\n conflictScope={preferences.conflictScope}\n currentUserId={currentUserId}\n onOpenChange={(open) => setEditor((current) => ({ ...current, open }))}\n onSaved={refetch}\n />\n ) : null}\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport dynamic from 'next/dynamic'\nimport { addDays } from 'date-fns/addDays'\nimport { isSameDay } from 'date-fns/isSameDay'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { apiCall, apiCallOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { matchFeature } from '@open-mercato/shared/lib/auth/featureMatch'\nimport {\n buildOptimisticLockHeader,\n extractOptimisticLockConflict,\n} from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { ErrorMessage, LoadingMessage } from '@open-mercato/ui/backend/detail'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { countByCategory } from '../../lib/calendar/categories'\nimport { findConflicts } from '../../lib/calendar/conflicts'\nimport { getVisibleRange } from '../../lib/calendar/range'\nimport { AgendaList } from './AgendaList'\nimport { CalendarFooter } from './CalendarFooter'\nimport { CalendarHeader } from './CalendarHeader'\nimport { CalendarTabs } from './CalendarTabs'\nimport { CalendarToolbar } from './CalendarToolbar'\nimport { MonthGrid } from './MonthGrid'\nimport { ShortcutsDialog } from './ShortcutsDialog'\nimport { TimeGrid } from './TimeGrid'\nimport { UpcomingCards } from './UpcomingCards'\nimport { CalendarSettingsModal } from './CalendarSettingsModal'\nimport { useCalendarPreferences } from './useCalendarPreferences'\nimport { MAX_WINDOW_ITEMS, useCalendarItems } from './useCalendarItems'\nimport type {\n CalendarFiltersValue,\n CalendarItem,\n CalendarRangePreset,\n CalendarTab,\n CalendarView,\n UpcomingCard,\n} from './types'\n\nconst CalendarEventEditor = dynamic(\n () => import('./CalendarEventEditor').then((mod) => mod.CalendarEventEditor),\n { ssr: false },\n)\n\nconst SEARCH_DEBOUNCE_MS = 200\nconst PHONE_BREAKPOINT_PX = 640\nconst HIGHLIGHT_CLEAR_MS = 3000\nconst DEFAULT_AGENDA_HORIZON_DAYS = 7\nconst UPCOMING_CARDS_COUNT = 4\nconst EMPTY_FILTERS: CalendarFiltersValue = { types: [], status: null, ownerUserId: null }\n\ntype EditorState = { open: boolean; mode: 'create' | 'edit'; item: CalendarItem | null }\n\nconst MANAGE_FEATURE = 'customers.interactions.manage'\n\nfunction useCanManageInteractions(): boolean {\n const [canManage, setCanManage] = React.useState(false)\n React.useEffect(() => {\n const controller = new AbortController()\n let cancelled = false\n apiCall<{ granted?: unknown[] }>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n signal: controller.signal,\n body: JSON.stringify({ features: [MANAGE_FEATURE] }),\n })\n .then((call) => {\n if (cancelled || !call.ok) return\n const granted = Array.isArray(call.result?.granted)\n ? call.result.granted.map((feature) => String(feature))\n : []\n setCanManage(granted.some((grantedFeature) => matchFeature(MANAGE_FEATURE, grantedFeature)))\n })\n .catch(() => {\n if (!cancelled && !controller.signal.aborted) setCanManage(false)\n })\n return () => {\n cancelled = true\n controller.abort()\n }\n }, [])\n return canManage\n}\n\nfunction buildTimezoneLabel(): string {\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone\n const offsetMinutes = -new Date().getTimezoneOffset()\n const sign = offsetMinutes >= 0 ? '+' : '-'\n const absolute = Math.abs(offsetMinutes)\n const hours = Math.floor(absolute / 60)\n const minutes = absolute % 60\n const offset = minutes > 0 ? `${sign}${hours}:${String(minutes).padStart(2, '0')}` : `${sign}${hours}`\n return `${timeZone} (GMT${offset})`\n}\n\nfunction resolveJoinUrl(location: string | null): string | null {\n const trimmed = location?.trim() ?? ''\n if (!trimmed) return null\n if (/^https?:\\/\\//i.test(trimmed)) return trimmed\n if (/^www\\./i.test(trimmed)) return `https://${trimmed}`\n return null\n}\n\nfunction asEditableItem(item: CalendarItem): CalendarItem {\n return item.isRecurringOccurrence ? { ...item, id: item.raw.id } : item\n}\n\nexport type CalendarScreenProps = {\n /** True when the optional resources module is loaded (server-resolved). */\n resourcesEnabled?: boolean\n /** True when the optional staff module is loaded (server-resolved). */\n staffEnabled?: boolean\n}\n\nexport function CalendarScreen({ resourcesEnabled = false, staffEnabled = true }: CalendarScreenProps = {}) {\n const t = useT()\n const [view, setView] = React.useState<CalendarView>('week')\n const [anchor, setAnchor] = React.useState<Date>(() => new Date())\n const [agendaHorizonDays, setAgendaHorizonDays] = React.useState(DEFAULT_AGENDA_HORIZON_DAYS)\n const [preset, setPreset] = React.useState<CalendarRangePreset | null>('thisWeek')\n\n React.useEffect(() => {\n if (window.innerWidth >= PHONE_BREAKPOINT_PX) return\n setView('day')\n setPreset(null)\n }, [])\n const [tab, setTab] = React.useState<CalendarTab>('all')\n const [searchText, setSearchText] = React.useState('')\n const [debouncedSearch, setDebouncedSearch] = React.useState('')\n const [filters, setFilters] = React.useState<CalendarFiltersValue>(EMPTY_FILTERS)\n const [editor, setEditor] = React.useState<EditorState>({ open: false, mode: 'create', item: null })\n const [editorMounted, setEditorMounted] = React.useState(false)\n const [createRange, setCreateRange] = React.useState<{ start: Date; end: Date } | null>(null)\n const [shortcutsOpen, setShortcutsOpen] = React.useState(false)\n const [settingsOpen, setSettingsOpen] = React.useState(false)\n const [highlightItemId, setHighlightItemId] = React.useState<string | null>(null)\n const [hasLoadedOnce, setHasLoadedOnce] = React.useState(false)\n const { preferences, setPreferences, hydrated: preferencesHydrated, userId: currentUserId } = useCalendarPreferences()\n\n const range = React.useMemo(\n () => getVisibleRange(view, anchor, agendaHorizonDays),\n [view, anchor, agendaHorizonDays],\n )\n const { items, isLoading, error, truncated, typeLabels, typeColors, typeIcons, refetch } = useCalendarItems(range)\n\n React.useEffect(() => {\n if (!isLoading) setHasLoadedOnce(true)\n }, [isLoading])\n\n React.useEffect(() => {\n const timer = window.setTimeout(() => setDebouncedSearch(searchText), SEARCH_DEBOUNCE_MS)\n return () => window.clearTimeout(timer)\n }, [searchText])\n\n React.useEffect(() => {\n if (!highlightItemId) return\n const timer = window.setTimeout(() => setHighlightItemId(null), HIGHLIGHT_CLEAR_MS)\n return () => window.clearTimeout(timer)\n }, [highlightItemId])\n\n const visibleItems = React.useMemo(\n () => items.filter((item) => item.end > range.from && item.start < range.to),\n [items, range],\n )\n\n const searchedItems = React.useMemo(() => {\n const query = debouncedSearch.trim().toLowerCase()\n if (!query) return visibleItems\n return visibleItems.filter((item) => {\n if (item.title.toLowerCase().includes(query)) return true\n if (item.location && item.location.toLowerCase().includes(query)) return true\n const rawBody = (item.raw as { body?: unknown }).body\n if (typeof rawBody === 'string' && rawBody.toLowerCase().includes(query)) return true\n return item.participants.some((participant) =>\n (participant.name ?? '').toLowerCase().includes(query),\n )\n })\n }, [visibleItems, debouncedSearch])\n\n const baseItems = React.useMemo(\n () =>\n searchedItems.filter((item) => {\n if (filters.types.length > 0 && !filters.types.includes(item.interactionType)) return false\n if (filters.status && item.status !== filters.status) return false\n if (filters.ownerUserId && item.ownerUserId !== filters.ownerUserId) return false\n if (!preferences.showCrmActivities && item.category !== 'meeting' && item.category !== 'event') return false\n return true\n }),\n [searchedItems, filters, preferences.showCrmActivities],\n )\n\n const tabCounts = React.useMemo(() => countByCategory(baseItems), [baseItems])\n\n const viewItems = React.useMemo(() => {\n if (tab === 'meetings') return baseItems.filter((item) => item.category === 'meeting')\n if (tab === 'events') return baseItems.filter((item) => item.category === 'event')\n return baseItems\n }, [baseItems, tab])\n\n const conflictMap = React.useMemo(\n () => findConflicts(baseItems, { scope: preferences.conflictScope, currentUserId }),\n [baseItems, preferences.conflictScope, currentUserId],\n )\n const conflictIds = React.useMemo(() => new Set(conflictMap.keys()), [conflictMap])\n\n const upcomingCards = React.useMemo<UpcomingCard[]>(() => {\n const now = new Date()\n const nowMs = now.getTime()\n return baseItems\n .filter((item) => item.start.getTime() >= nowMs)\n .sort((first, second) => first.start.getTime() - second.start.getTime())\n .slice(0, UPCOMING_CARDS_COUNT)\n .map((item) => {\n const conflictCount = preferences.conflictWarnings ? (conflictMap.get(item.id)?.length ?? 0) : 0\n const kind: UpcomingCard['kind'] =\n item.status === 'canceled'\n ? 'cancelled'\n : conflictCount > 0\n ? 'conflicted'\n : isSameDay(item.start, now)\n ? 'today'\n : 'future'\n return { item, kind, conflictCount }\n })\n }, [baseItems, conflictMap, preferences.conflictWarnings])\n\n const typeOptions = React.useMemo(() => {\n const values = new Set<string>(Object.keys(typeLabels))\n for (const item of items) values.add(item.interactionType)\n return [...values]\n .sort((a, b) => a.localeCompare(b))\n .map((value) => ({ value, label: typeLabels[value] ?? value }))\n }, [items, typeLabels])\n\n const ownerOptions = React.useMemo(() => {\n const participantNames = new Map<string, string>()\n for (const item of items) {\n for (const participant of item.participants) {\n if (participant.name && !participantNames.has(participant.userId)) {\n participantNames.set(participant.userId, participant.name)\n }\n }\n }\n const owners = new Map<string, string>()\n for (const item of items) {\n if (!item.ownerUserId || owners.has(item.ownerUserId)) continue\n owners.set(item.ownerUserId, participantNames.get(item.ownerUserId) ?? item.ownerUserId)\n }\n return [...owners.entries()]\n .map(([value, label]) => ({ value, label }))\n .sort((first, second) => first.label.localeCompare(second.label))\n }, [items])\n\n const timezoneLabel = React.useMemo(() => buildTimezoneLabel(), [])\n\n const canManage = useCanManageInteractions()\n\n const openCreateEditor = React.useCallback(() => {\n if (!canManage) return\n setCreateRange(null)\n setEditorMounted(true)\n setEditor({ open: true, mode: 'create', item: null })\n }, [canManage])\n\n const openEditEditor = React.useCallback(\n (item: CalendarItem) => {\n if (!canManage) return\n setCreateRange(null)\n setEditorMounted(true)\n setEditor({ open: true, mode: 'edit', item: asEditableItem(item) })\n },\n [canManage],\n )\n\n const handleCreateRange = React.useCallback(\n (start: Date, end: Date) => {\n if (!canManage) return\n setCreateRange({ start, end })\n setEditorMounted(true)\n setEditor({ open: true, mode: 'create', item: null })\n },\n [canManage],\n )\n\n const seedActivityTypes = React.useMemo(() => {\n const seen = new Set<string>()\n const labels: string[] = []\n for (const value of Object.keys(typeLabels)) {\n const label = typeLabels[value] ?? value\n if (seen.has(label)) continue\n seen.add(label)\n labels.push(label)\n }\n return labels\n }, [typeLabels])\n\n const handleToday = React.useCallback(() => {\n setAnchor(new Date())\n setPreset(null)\n }, [])\n\n const handlePresetChange = React.useCallback((next: CalendarRangePreset) => {\n setPreset(next)\n setAnchor(new Date())\n if (next === 'thisWeek') {\n setView('week')\n } else if (next === 'thisMonth') {\n setView('month')\n } else {\n setView('agenda')\n setAgendaHorizonDays(next === 'next30' ? 30 : DEFAULT_AGENDA_HORIZON_DAYS)\n }\n }, [])\n\n const handleAnchorChange = React.useCallback((date: Date) => {\n setAnchor(date)\n setPreset(null)\n }, [])\n\n const handleViewChange = React.useCallback((next: CalendarView) => {\n setView(next)\n setPreset(null)\n }, [])\n\n const handleTimeGridNavigate = React.useCallback((deltaDays: number) => {\n setAnchor((current) => addDays(current, deltaDays))\n setPreset(null)\n }, [])\n\n const handleDayOpen = React.useCallback((date: Date) => {\n setView('day')\n setAnchor(date)\n setPreset(null)\n }, [])\n\n const handleSeeConflict = React.useCallback((item: CalendarItem) => {\n setView('week')\n setAnchor(item.start)\n setPreset(null)\n setHighlightItemId(item.id)\n }, [])\n\n const handleJoin = React.useCallback((item: CalendarItem) => {\n const url = resolveJoinUrl(item.location)\n if (url) window.open(url, '_blank', 'noopener')\n }, [])\n\n const { runMutation, retryLastMutation } = useGuardedMutation<{\n formId: string\n resourceKind: string\n resourceId: string\n retryLastMutation: () => Promise<boolean>\n }>({\n contextId: 'customers-calendar-cancel',\n blockedMessage: t('ui.forms.flash.saveBlocked', 'Save blocked by validation'),\n })\n\n const handleCancelItem = React.useCallback(\n async (item: CalendarItem) => {\n const interactionId = item.raw.id\n try {\n await runMutation({\n operation: () =>\n withScopedApiRequestHeaders(buildOptimisticLockHeader(item.updatedAt), () =>\n apiCallOrThrow('/api/customers/interactions', {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id: interactionId, status: 'canceled' }),\n }),\n ),\n mutationPayload: {\n operation: 'cancelCalendarEvent',\n interactionId,\n interactionType: item.interactionType,\n },\n context: {\n formId: 'customers-calendar-cancel',\n resourceKind: 'customers.interaction',\n resourceId: interactionId,\n retryLastMutation,\n },\n })\n flash(t('customers.calendar.cards.cancelSuccess', 'Event cancelled'), 'success')\n refetch()\n } catch (err) {\n // An optimistic-lock 409 is surfaced as the persistent conflict bar by\n // useGuardedMutation (surfaceRecordConflict) \u2014 don't re-flash.\n if (extractOptimisticLockConflict(err)) return\n flash(t('customers.calendar.cards.cancelError', 'Failed to cancel event'), 'error')\n }\n },\n [refetch, retryLastMutation, runMutation, t],\n )\n\n const focusSearch = React.useCallback(() => {\n const node = document.querySelector('[data-calendar-search]')\n if (node instanceof HTMLInputElement) node.focus()\n else if (node instanceof HTMLElement) node.querySelector('input')?.focus()\n }, [])\n\n const editorOpen = editor.open\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.defaultPrevented) return\n if (event.metaKey || event.ctrlKey || event.altKey) return\n const target = event.target\n if (target instanceof HTMLElement) {\n const tag = target.tagName\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable) return\n }\n if (editorOpen) return\n switch (event.key) {\n case 't':\n case 'T':\n event.preventDefault()\n setAnchor(new Date())\n setPreset(null)\n break\n case 'd':\n case 'D':\n event.preventDefault()\n setView('day')\n setPreset(null)\n break\n case 'w':\n case 'W':\n event.preventDefault()\n setView('week')\n setPreset(null)\n break\n case 'm':\n case 'M':\n event.preventDefault()\n setView('month')\n setPreset(null)\n break\n case 'a':\n case 'A':\n event.preventDefault()\n setView('agenda')\n setPreset(null)\n break\n case 'n':\n case 'N':\n event.preventDefault()\n openCreateEditor()\n break\n case '/':\n event.preventDefault()\n focusSearch()\n break\n case '?':\n event.preventDefault()\n setShortcutsOpen((open) => !open)\n break\n case 'Escape':\n setHighlightItemId(null)\n break\n default:\n break\n }\n }\n window.addEventListener('keydown', handleKeyDown)\n return () => window.removeEventListener('keydown', handleKeyDown)\n }, [editorOpen, focusSearch, openCreateEditor])\n\n const showInitialLoading = (isLoading && !hasLoadedOnce) || !preferencesHydrated\n\n let viewArea: React.ReactNode\n if (error) {\n viewArea = (\n <ErrorMessage\n label={t('customers.calendar.errors.loadFailed', 'Failed to load calendar events.')}\n action={\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={refetch}>\n {t('customers.calendar.errors.retry', 'Retry')}\n </Button>\n }\n />\n )\n } else if (showInitialLoading) {\n viewArea = <LoadingMessage label={t('customers.calendar.loading', 'Loading calendar\u2026')} />\n } else if (view === 'month') {\n viewArea = (\n <MonthGrid anchor={anchor} items={viewItems} onItemClick={openEditEditor} onDayOpen={handleDayOpen} />\n )\n } else if (view === 'agenda') {\n viewArea = (\n <AgendaList\n anchor={anchor}\n horizonDays={agendaHorizonDays}\n items={viewItems}\n typeLabels={typeLabels}\n onItemClick={openEditEditor}\n />\n )\n } else {\n viewArea = (\n <TimeGrid\n days={view === 'day' ? 1 : 7}\n anchor={anchor}\n items={viewItems}\n conflictIds={conflictIds}\n showWeekends={preferences.showWeekends}\n showConflicts={preferences.conflictWarnings}\n aiSummaries={preferences.aiSummaries}\n canManage={canManage}\n highlightItemId={highlightItemId}\n onItemClick={openEditEditor}\n onJoin={handleJoin}\n onNavigate={handleTimeGridNavigate}\n onCreate={canManage ? openCreateEditor : undefined}\n onCreateRange={canManage ? handleCreateRange : undefined}\n />\n )\n }\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col gap-4\">\n <CalendarHeader view={view} anchor={anchor} onNewEvent={canManage ? openCreateEditor : undefined} />\n <CalendarToolbar\n view={view}\n anchor={anchor}\n range={range}\n preset={preset}\n search={searchText}\n filters={filters}\n typeOptions={typeOptions}\n ownerOptions={ownerOptions}\n onToday={handleToday}\n onPresetChange={handlePresetChange}\n onAnchorChange={handleAnchorChange}\n onSearchChange={setSearchText}\n onFiltersChange={setFilters}\n onOpenSettings={() => setSettingsOpen(true)}\n />\n <UpcomingCards\n cards={upcomingCards}\n canManage={canManage}\n onJoin={handleJoin}\n onSeeConflict={handleSeeConflict}\n onOpen={openEditEditor}\n onEdit={openEditEditor}\n onCancel={handleCancelItem}\n />\n <div className=\"flex min-h-0 flex-1 flex-col gap-3\">\n <CalendarTabs\n tab={tab}\n counts={tabCounts}\n view={view}\n onTabChange={setTab}\n onViewChange={handleViewChange}\n />\n {truncated ? (\n <p className=\"text-xs text-muted-foreground\" role=\"status\">\n {t('customers.calendar.notice.truncated', 'Showing first {count} items for this range.', {\n count: MAX_WINDOW_ITEMS,\n })}\n </p>\n ) : null}\n <div className=\"flex min-h-[560px] flex-1 flex-col [&>*]:flex-1\">{viewArea}</div>\n </div>\n <div className=\"hidden md:block\">\n <CalendarFooter timezoneLabel={timezoneLabel} onOpenShortcuts={() => setShortcutsOpen(true)} />\n </div>\n <ShortcutsDialog open={shortcutsOpen} onOpenChange={setShortcutsOpen} />\n <CalendarSettingsModal\n open={settingsOpen}\n preferences={preferences}\n seedActivityTypes={seedActivityTypes}\n onOpenChange={setSettingsOpen}\n onSave={(next) => {\n setPreferences(next)\n flash(t('customers.calendar.settings.saved', 'Calendar settings saved'), 'success')\n }}\n />\n {editorMounted ? (\n <CalendarEventEditor\n open={editor.open}\n mode={editor.mode}\n item={editor.item}\n defaultDate={anchor}\n defaultRange={createRange}\n typeLabels={typeLabels}\n typeIcons={typeIcons}\n conflictScope={preferences.conflictScope}\n currentUserId={currentUserId}\n resourcesEnabled={resourcesEnabled}\n staffEnabled={staffEnabled}\n onOpenChange={(open) => setEditor((current) => ({ ...current, open }))}\n onSaved={refetch}\n />\n ) : null}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -137,8 +137,8 @@ function CalendarSettingsModal({
137
137
  value: draft.conflictScope,
138
138
  onChange: (conflictScope) => setDraft((current) => ({ ...current, conflictScope })),
139
139
  options: [
140
- { value: "mine", label: t("customers.calendar.settings.conflictScopeMine", "My meetings only") },
141
- { value: "all", label: t("customers.calendar.settings.conflictScopeAll", "All org meetings") }
140
+ { value: "mine", label: t("customers.calendar.settings.conflictScopeMine", "My meetings") },
141
+ { value: "all", label: t("customers.calendar.settings.conflictScopeAll", "All meetings") }
142
142
  ]
143
143
  }
144
144
  )
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/calendar/CalendarSettingsModal.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Info, X } from 'lucide-react'\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Dialog, DialogContent, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { TagInput } from '@open-mercato/ui/primitives/tag-input'\nimport { SimpleTooltip } from '@open-mercato/ui/primitives/tooltip'\nimport { useDialogKeyHandler } from '@open-mercato/ui/hooks/useDialogKeyHandler'\nimport {\n CalendarPreferences,\n ConflictScope,\n MAX_ACTIVITY_TYPES,\n MAX_EVENT_CATEGORIES,\n} from '../../lib/calendar/preferences'\nimport { SegmentGroup } from './editor/SegmentGroup'\n\nexport type CalendarSettingsModalProps = {\n open: boolean\n preferences: CalendarPreferences\n seedActivityTypes: string[]\n onOpenChange(open: boolean): void\n onSave(next: CalendarPreferences): void\n}\n\ntype ToggleKey = 'showCrmActivities' | 'aiSummaries' | 'conflictWarnings' | 'showWeekends'\n\n// An empty Activity Types list is an intentional floor meaning \"surface all\n// dictionary types\" (see buildEditorCategoryOptions) rather than \"surface none\" \u2014\n// it keeps the editor's category picker usable. So when the stored list is empty\n// the modal seeds the dictionary types for display; curating a non-empty subset\n// persists and filters the editor as expected.\nfunction buildDraft(preferences: CalendarPreferences, seedActivityTypes: string[]): CalendarPreferences {\n return {\n ...preferences,\n eventCategories: [...preferences.eventCategories],\n activityTypes:\n preferences.activityTypes.length > 0\n ? [...preferences.activityTypes]\n : seedActivityTypes.slice(0, MAX_ACTIVITY_TYPES),\n }\n}\n\nexport function CalendarSettingsModal({\n open,\n preferences,\n seedActivityTypes,\n onOpenChange,\n onSave,\n}: CalendarSettingsModalProps) {\n const t = useT()\n const [draft, setDraft] = React.useState<CalendarPreferences>(() => buildDraft(preferences, seedActivityTypes))\n const openRef = React.useRef(false)\n\n React.useEffect(() => {\n if (open && !openRef.current) setDraft(buildDraft(preferences, seedActivityTypes))\n openRef.current = open\n }, [open, preferences, seedActivityTypes])\n\n const handleSave = React.useCallback(() => {\n onSave(draft)\n onOpenChange(false)\n }, [draft, onOpenChange, onSave])\n\n const handleKeyDown = useDialogKeyHandler({ onConfirm: handleSave })\n\n const toggle = (key: ToggleKey) => (checked: boolean) => setDraft((current) => ({ ...current, [key]: checked }))\n\n const toggleRows: Array<{ key: ToggleKey; label: string }> = [\n { key: 'showCrmActivities', label: t('customers.calendar.settings.showCrmActivities', 'Show CRM activities on calendar') },\n { key: 'aiSummaries', label: t('customers.calendar.settings.aiSummaries', 'AI summaries & quick actions') },\n { key: 'conflictWarnings', label: t('customers.calendar.settings.conflictWarnings', 'Conflict warnings') },\n { key: 'showWeekends', label: t('customers.calendar.settings.showWeekends', 'Show weekends') },\n ]\n\n const title = t('customers.calendar.settings.title', 'Customization')\n const removeTagLabel = React.useCallback(\n (tag: string) => t('customers.calendar.settings.removeTag', 'Remove {tag}', { tag }),\n [t],\n )\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n onKeyDown={handleKeyDown}\n aria-describedby={undefined}\n dismissible={false}\n className=\"flex w-full max-w-[400px] flex-col gap-0 overflow-hidden rounded-2xl border-0 bg-card p-0 shadow-xl\"\n >\n <VisuallyHidden>\n <DialogTitle>{title}</DialogTitle>\n </VisuallyHidden>\n <div className=\"flex shrink-0 items-start gap-3.5 border-b border-border py-4 pl-5 pr-4\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <p className=\"text-sm font-medium leading-5 text-foreground\">{title}</p>\n <p className=\"text-xs leading-4 text-muted-foreground\">\n {t('customers.calendar.settings.subtitle', 'Customise your calendar module.')}\n </p>\n </div>\n <IconButton\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onOpenChange(false)}\n aria-label={t('customers.calendar.settings.close', 'Close')}\n className=\"shrink-0 text-muted-foreground\"\n >\n <X aria-hidden className=\"size-5\" />\n </IconButton>\n </div>\n\n <div className=\"flex flex-col gap-4 p-5\">\n <SettingsTagInput\n label={t('customers.calendar.settings.eventCategories', 'Event Categories')}\n maxLabel={t('customers.calendar.settings.max', '(max. {count})', { count: MAX_EVENT_CATEGORIES })}\n hint={t(\n 'customers.calendar.settings.eventCategoriesHint',\n 'Your own grouping labels (e.g. Team Meeting, Sales Call). Offered when creating an event.',\n )}\n placeholder={t('customers.calendar.settings.addCategory', 'Add a category\u2026')}\n value={draft.eventCategories}\n maxTags={MAX_EVENT_CATEGORIES}\n removeTagLabel={removeTagLabel}\n onChange={(eventCategories) => setDraft((current) => ({ ...current, eventCategories }))}\n />\n <SettingsTagInput\n label={t('customers.calendar.settings.activityTypes', 'Activity Types')}\n maxLabel={t('customers.calendar.settings.max', '(max. {count})', { count: MAX_ACTIVITY_TYPES })}\n hint={t(\n 'customers.calendar.settings.activityTypesHint',\n 'The activity types your calendar surfaces when creating an event. Seeded from your workspace dictionary.',\n )}\n placeholder={t('customers.calendar.settings.addType', 'Add a type\u2026')}\n value={draft.activityTypes}\n maxTags={MAX_ACTIVITY_TYPES}\n removeTagLabel={removeTagLabel}\n onChange={(activityTypes) => setDraft((current) => ({ ...current, activityTypes }))}\n />\n {toggleRows.map((row) => (\n <React.Fragment key={row.key}>\n <div className=\"flex items-center gap-2\">\n <Switch\n checked={draft[row.key]}\n onCheckedChange={toggle(row.key)}\n aria-label={row.label}\n />\n <span className=\"text-sm leading-5 text-foreground\">{row.label}</span>\n </div>\n {row.key === 'conflictWarnings' && draft.conflictWarnings ? (\n <div className=\"flex flex-col gap-1.5 pl-11\">\n <span className=\"text-xs leading-4 text-muted-foreground\">\n {t(\n 'customers.calendar.settings.conflictScopeHint',\n 'Choose whose overlaps the calendar flags as conflicts.',\n )}\n </span>\n <SegmentGroup<ConflictScope>\n ariaLabel={t('customers.calendar.settings.conflictScope', 'Conflict scope')}\n value={draft.conflictScope}\n onChange={(conflictScope) => setDraft((current) => ({ ...current, conflictScope }))}\n options={[\n { value: 'mine', label: t('customers.calendar.settings.conflictScopeMine', 'My meetings only') },\n { value: 'all', label: t('customers.calendar.settings.conflictScopeAll', 'All org meetings') },\n ]}\n />\n </div>\n ) : null}\n </React.Fragment>\n ))}\n </div>\n\n <div className=\"flex shrink-0 items-center gap-3 border-t border-border px-5 py-4\">\n <Button type=\"button\" variant=\"outline\" className=\"flex-1\" onClick={() => onOpenChange(false)}>\n {t('customers.calendar.settings.cancel', 'Cancel')}\n </Button>\n <Button type=\"button\" className=\"flex-1\" onClick={handleSave}>\n {t('customers.calendar.settings.save', 'Save Changes')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n\ntype SettingsTagInputProps = {\n label: string\n maxLabel: string\n hint: string\n placeholder: string\n value: string[]\n maxTags: number\n removeTagLabel: (tag: string) => string\n onChange(value: string[]): void\n}\n\nfunction SettingsTagInput({ label, maxLabel, hint, placeholder, value, maxTags, removeTagLabel, onChange }: SettingsTagInputProps) {\n return (\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-1\">\n <span className=\"text-sm font-medium leading-5 text-foreground\">{label}</span>\n <span className=\"text-sm leading-5 text-muted-foreground\">{maxLabel}</span>\n <SimpleTooltip content={hint}>\n <span className=\"inline-flex text-muted-foreground\" tabIndex={0} role=\"img\" aria-label={hint}>\n <Info aria-hidden className=\"size-4\" />\n </span>\n </SimpleTooltip>\n </div>\n <TagInput\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n maxTags={maxTags}\n aria-label={label}\n removeTagLabel={removeTagLabel}\n />\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Info, X } from 'lucide-react'\nimport { VisuallyHidden } from '@radix-ui/react-visually-hidden'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Dialog, DialogContent, DialogTitle } from '@open-mercato/ui/primitives/dialog'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { TagInput } from '@open-mercato/ui/primitives/tag-input'\nimport { SimpleTooltip } from '@open-mercato/ui/primitives/tooltip'\nimport { useDialogKeyHandler } from '@open-mercato/ui/hooks/useDialogKeyHandler'\nimport {\n CalendarPreferences,\n ConflictScope,\n MAX_ACTIVITY_TYPES,\n MAX_EVENT_CATEGORIES,\n} from '../../lib/calendar/preferences'\nimport { SegmentGroup } from './editor/SegmentGroup'\n\nexport type CalendarSettingsModalProps = {\n open: boolean\n preferences: CalendarPreferences\n seedActivityTypes: string[]\n onOpenChange(open: boolean): void\n onSave(next: CalendarPreferences): void\n}\n\ntype ToggleKey = 'showCrmActivities' | 'aiSummaries' | 'conflictWarnings' | 'showWeekends'\n\n// An empty Activity Types list is an intentional floor meaning \"surface all\n// dictionary types\" rather than \"surface none\". When the stored list is empty\n// the modal seeds the dictionary types for display. NOTE: since the editor's\n// Category quick-pick was removed (owner feedback, #3552) these lists no longer\n// affect the event editor \u2014 the type switcher always shows the full dictionary.\nfunction buildDraft(preferences: CalendarPreferences, seedActivityTypes: string[]): CalendarPreferences {\n return {\n ...preferences,\n eventCategories: [...preferences.eventCategories],\n activityTypes:\n preferences.activityTypes.length > 0\n ? [...preferences.activityTypes]\n : seedActivityTypes.slice(0, MAX_ACTIVITY_TYPES),\n }\n}\n\nexport function CalendarSettingsModal({\n open,\n preferences,\n seedActivityTypes,\n onOpenChange,\n onSave,\n}: CalendarSettingsModalProps) {\n const t = useT()\n const [draft, setDraft] = React.useState<CalendarPreferences>(() => buildDraft(preferences, seedActivityTypes))\n const openRef = React.useRef(false)\n\n React.useEffect(() => {\n if (open && !openRef.current) setDraft(buildDraft(preferences, seedActivityTypes))\n openRef.current = open\n }, [open, preferences, seedActivityTypes])\n\n const handleSave = React.useCallback(() => {\n onSave(draft)\n onOpenChange(false)\n }, [draft, onOpenChange, onSave])\n\n const handleKeyDown = useDialogKeyHandler({ onConfirm: handleSave })\n\n const toggle = (key: ToggleKey) => (checked: boolean) => setDraft((current) => ({ ...current, [key]: checked }))\n\n const toggleRows: Array<{ key: ToggleKey; label: string }> = [\n { key: 'showCrmActivities', label: t('customers.calendar.settings.showCrmActivities', 'Show CRM activities on calendar') },\n { key: 'aiSummaries', label: t('customers.calendar.settings.aiSummaries', 'AI summaries & quick actions') },\n { key: 'conflictWarnings', label: t('customers.calendar.settings.conflictWarnings', 'Conflict warnings') },\n { key: 'showWeekends', label: t('customers.calendar.settings.showWeekends', 'Show weekends') },\n ]\n\n const title = t('customers.calendar.settings.title', 'Customization')\n const removeTagLabel = React.useCallback(\n (tag: string) => t('customers.calendar.settings.removeTag', 'Remove {tag}', { tag }),\n [t],\n )\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n onKeyDown={handleKeyDown}\n aria-describedby={undefined}\n dismissible={false}\n className=\"flex w-full max-w-[400px] flex-col gap-0 overflow-hidden rounded-2xl border-0 bg-card p-0 shadow-xl\"\n >\n <VisuallyHidden>\n <DialogTitle>{title}</DialogTitle>\n </VisuallyHidden>\n <div className=\"flex shrink-0 items-start gap-3.5 border-b border-border py-4 pl-5 pr-4\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <p className=\"text-sm font-medium leading-5 text-foreground\">{title}</p>\n <p className=\"text-xs leading-4 text-muted-foreground\">\n {t('customers.calendar.settings.subtitle', 'Customise your calendar module.')}\n </p>\n </div>\n <IconButton\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => onOpenChange(false)}\n aria-label={t('customers.calendar.settings.close', 'Close')}\n className=\"shrink-0 text-muted-foreground\"\n >\n <X aria-hidden className=\"size-5\" />\n </IconButton>\n </div>\n\n <div className=\"flex flex-col gap-4 p-5\">\n <SettingsTagInput\n label={t('customers.calendar.settings.eventCategories', 'Event Categories')}\n maxLabel={t('customers.calendar.settings.max', '(max. {count})', { count: MAX_EVENT_CATEGORIES })}\n hint={t(\n 'customers.calendar.settings.eventCategoriesHint',\n 'Your own grouping labels (e.g. Team Meeting, Sales Call). Offered when creating an event.',\n )}\n placeholder={t('customers.calendar.settings.addCategory', 'Add a category\u2026')}\n value={draft.eventCategories}\n maxTags={MAX_EVENT_CATEGORIES}\n removeTagLabel={removeTagLabel}\n onChange={(eventCategories) => setDraft((current) => ({ ...current, eventCategories }))}\n />\n <SettingsTagInput\n label={t('customers.calendar.settings.activityTypes', 'Activity Types')}\n maxLabel={t('customers.calendar.settings.max', '(max. {count})', { count: MAX_ACTIVITY_TYPES })}\n hint={t(\n 'customers.calendar.settings.activityTypesHint',\n 'The activity types your calendar surfaces when creating an event. Seeded from your workspace dictionary.',\n )}\n placeholder={t('customers.calendar.settings.addType', 'Add a type\u2026')}\n value={draft.activityTypes}\n maxTags={MAX_ACTIVITY_TYPES}\n removeTagLabel={removeTagLabel}\n onChange={(activityTypes) => setDraft((current) => ({ ...current, activityTypes }))}\n />\n {toggleRows.map((row) => (\n <React.Fragment key={row.key}>\n <div className=\"flex items-center gap-2\">\n <Switch\n checked={draft[row.key]}\n onCheckedChange={toggle(row.key)}\n aria-label={row.label}\n />\n <span className=\"text-sm leading-5 text-foreground\">{row.label}</span>\n </div>\n {row.key === 'conflictWarnings' && draft.conflictWarnings ? (\n <div className=\"flex flex-col gap-1.5 pl-11\">\n <span className=\"text-xs leading-4 text-muted-foreground\">\n {t(\n 'customers.calendar.settings.conflictScopeHint',\n 'Choose whose overlaps the calendar flags as conflicts.',\n )}\n </span>\n <SegmentGroup<ConflictScope>\n ariaLabel={t('customers.calendar.settings.conflictScope', 'Conflict scope')}\n value={draft.conflictScope}\n onChange={(conflictScope) => setDraft((current) => ({ ...current, conflictScope }))}\n options={[\n { value: 'mine', label: t('customers.calendar.settings.conflictScopeMine', 'My meetings') },\n { value: 'all', label: t('customers.calendar.settings.conflictScopeAll', 'All meetings') },\n ]}\n />\n </div>\n ) : null}\n </React.Fragment>\n ))}\n </div>\n\n <div className=\"flex shrink-0 items-center gap-3 border-t border-border px-5 py-4\">\n <Button type=\"button\" variant=\"outline\" className=\"flex-1\" onClick={() => onOpenChange(false)}>\n {t('customers.calendar.settings.cancel', 'Cancel')}\n </Button>\n <Button type=\"button\" className=\"flex-1\" onClick={handleSave}>\n {t('customers.calendar.settings.save', 'Save Changes')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n\ntype SettingsTagInputProps = {\n label: string\n maxLabel: string\n hint: string\n placeholder: string\n value: string[]\n maxTags: number\n removeTagLabel: (tag: string) => string\n onChange(value: string[]): void\n}\n\nfunction SettingsTagInput({ label, maxLabel, hint, placeholder, value, maxTags, removeTagLabel, onChange }: SettingsTagInputProps) {\n return (\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-1\">\n <span className=\"text-sm font-medium leading-5 text-foreground\">{label}</span>\n <span className=\"text-sm leading-5 text-muted-foreground\">{maxLabel}</span>\n <SimpleTooltip content={hint}>\n <span className=\"inline-flex text-muted-foreground\" tabIndex={0} role=\"img\" aria-label={hint}>\n <Info aria-hidden className=\"size-4\" />\n </span>\n </SimpleTooltip>\n </div>\n <TagInput\n value={value}\n onChange={onChange}\n placeholder={placeholder}\n maxTags={maxTags}\n aria-label={label}\n removeTagLabel={removeTagLabel}\n />\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -5,11 +5,9 @@ import { addDays } from "date-fns/addDays";
5
5
  import { format } from "date-fns/format";
6
6
  import { isSameMonth } from "date-fns/isSameMonth";
7
7
  import { isToday } from "date-fns/isToday";
8
- import { CalendarDays } from "lucide-react";
9
8
  import { useT } from "@open-mercato/shared/lib/i18n/context";
10
9
  import { cn } from "@open-mercato/shared/lib/utils";
11
10
  import { Button } from "@open-mercato/ui/primitives/button";
12
- import { EmptyState } from "@open-mercato/ui/primitives/empty-state";
13
11
  import { getVisibleRange } from "../../lib/calendar/range.js";
14
12
  import { eventDisplayTitle } from "../../lib/calendar/labels.js";
15
13
  const MAX_PILLS_PER_DAY = 2;
@@ -200,15 +198,7 @@ function MonthGrid({ anchor, items, onItemClick, onDayOpen }) {
200
198
  ))
201
199
  },
202
200
  dayKeyOf(week[0])
203
- )),
204
- items.length === 0 ? /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 z-10 flex items-center justify-center p-6", children: /* @__PURE__ */ jsx(
205
- EmptyState,
206
- {
207
- icon: /* @__PURE__ */ jsx(CalendarDays, { className: "h-6 w-6", "aria-hidden": "true" }),
208
- title: t("customers.calendar.empty.month", "Nothing scheduled this month"),
209
- className: "bg-background/90"
210
- }
211
- ) }) : null
201
+ ))
212
202
  ] });
213
203
  }
214
204
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/customers/components/calendar/MonthGrid.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { addDays } from 'date-fns/addDays'\nimport { format } from 'date-fns/format'\nimport { isSameMonth } from 'date-fns/isSameMonth'\nimport { isToday } from 'date-fns/isToday'\nimport { CalendarDays } from 'lucide-react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { getVisibleRange } from '../../lib/calendar/range'\nimport { eventDisplayTitle } from '../../lib/calendar/labels'\nimport type { CalendarItem, MonthGridProps } from './types'\n\nconst MAX_PILLS_PER_DAY = 2\nconst SOFT_TINT_ALPHA = '1A'\n\nfunction dayKeyOf(date: Date): string {\n return format(date, 'yyyy-MM-dd')\n}\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' })\n}\n\nfunction fullDateLabel(date: Date): string {\n return date.toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })\n}\n\nfunction isWeekend(date: Date): boolean {\n const weekday = date.getDay()\n return weekday === 0 || weekday === 6\n}\n\nfunction buildWeeks(anchor: Date): Date[][] {\n const range = getVisibleRange('month', anchor, 0)\n const weeks: Date[][] = []\n let cursor = range.from\n while (cursor.getTime() <= range.to.getTime()) {\n const week: Date[] = []\n for (let dayIndex = 0; dayIndex < 7; dayIndex += 1) {\n week.push(cursor)\n cursor = addDays(cursor, 1)\n }\n weeks.push(week)\n }\n return weeks\n}\n\nfunction groupItemsByDay(items: CalendarItem[]): Map<string, CalendarItem[]> {\n const sorted = [...items].sort((first, second) => first.start.getTime() - second.start.getTime())\n const byDay = new Map<string, CalendarItem[]>()\n for (const item of sorted) {\n const key = dayKeyOf(item.start)\n const bucket = byDay.get(key)\n if (bucket) bucket.push(item)\n else byDay.set(key, [item])\n }\n return byDay\n}\n\nfunction MonthPill({ item, onItemClick }: { item: CalendarItem; onItemClick: (item: CalendarItem) => void }) {\n const t = useT()\n const canceled = item.status === 'canceled'\n const title = eventDisplayTitle(item.title, t('customers.calendar.grid.untitled', 'Untitled'))\n const timeLabel = item.allDay ? '' : ` \u00B7 ${formatTime(item.start)} \u2013 ${formatTime(item.end)}`\n const tintStyle = item.color\n ? { backgroundColor: `${item.color}${SOFT_TINT_ALPHA}`, color: item.color }\n : undefined\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n aria-label={`${title}${timeLabel}`}\n onClick={(event) => {\n event.stopPropagation()\n onItemClick(item)\n }}\n className={cn(\n 'h-4 w-full min-w-0 justify-center gap-0 rounded-full p-0 pr-2',\n !item.color && 'bg-muted text-muted-foreground',\n canceled && 'opacity-60',\n )}\n style={tintStyle}\n >\n <span aria-hidden=\"true\" className=\"flex size-4 shrink-0 items-center justify-center\">\n <span\n className={cn('size-1.5 rounded-full', !item.color && 'bg-muted-foreground')}\n style={item.color ? { backgroundColor: item.color } : undefined}\n />\n </span>\n <span\n className={cn(\n 'min-w-0 truncate text-overline font-medium uppercase tracking-wide',\n canceled && 'line-through',\n )}\n >\n {title}\n </span>\n </Button>\n )\n}\n\nfunction MonthDayCell({\n day,\n anchor,\n items,\n onItemClick,\n onDayOpen,\n}: {\n day: Date\n anchor: Date\n items: CalendarItem[]\n onItemClick: (item: CalendarItem) => void\n onDayOpen: (date: Date) => void\n}) {\n const t = useT()\n const inMonth = isSameMonth(day, anchor)\n const today = isToday(day)\n const visibleItems = items.slice(0, MAX_PILLS_PER_DAY)\n const hiddenCount = items.length - visibleItems.length\n const dayLabel = fullDateLabel(day)\n return (\n <div\n className={cn(\n 'relative flex h-full min-w-0 flex-1 flex-col items-start gap-1 overflow-hidden border-r border-border p-2 text-left last:border-r-0',\n isWeekend(day) ? 'bg-muted/40' : 'bg-background',\n )}\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n aria-label={dayLabel}\n onClick={() => onDayOpen(day)}\n className=\"absolute inset-0 z-0 h-full w-full rounded-none p-0 hover:bg-muted/50\"\n >\n <span className=\"sr-only\">{dayLabel}</span>\n </Button>\n {today ? (\n <span className=\"pointer-events-none relative z-10 flex items-center justify-center rounded-full bg-primary px-1.5 py-0.5 text-xs font-semibold text-primary-foreground\">\n {day.getDate()}\n </span>\n ) : (\n <span className={cn('pointer-events-none relative z-10 text-xs font-medium', inMonth ? 'text-foreground' : 'text-muted-foreground')}>\n {day.getDate()}\n </span>\n )}\n <span className=\"relative z-20 hidden w-full flex-col gap-1 sm:flex\">\n {visibleItems.map((item) => (\n <MonthPill key={item.id} item={item} onItemClick={onItemClick} />\n ))}\n {hiddenCount > 0 ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto self-start p-0 text-overline font-medium text-muted-foreground hover:bg-transparent hover:underline\"\n onClick={(event) => {\n event.stopPropagation()\n onDayOpen(day)\n }}\n >\n {t('customers.calendar.grid.more', '+{count} more', { count: hiddenCount })}\n </Button>\n ) : null}\n </span>\n {items.length > 0 ? (\n <span aria-hidden=\"true\" className=\"pointer-events-none relative z-10 flex w-full flex-wrap items-center gap-0.5 sm:hidden\">\n {items.slice(0, 4).map((item) => (\n <span\n key={item.id}\n className={cn('size-1.5 rounded-full', !item.color && 'bg-muted-foreground')}\n style={item.color ? { backgroundColor: item.color } : undefined}\n />\n ))}\n {items.length > 4 ? (\n <span className=\"text-overline font-medium leading-none text-muted-foreground\">\n +{items.length - 4}\n </span>\n ) : null}\n </span>\n ) : null}\n </div>\n )\n}\n\nexport function MonthGrid({ anchor, items, onItemClick, onDayOpen }: MonthGridProps) {\n const t = useT()\n const weeks = React.useMemo(() => buildWeeks(anchor), [anchor])\n const itemsByDay = React.useMemo(() => groupItemsByDay(items), [items])\n return (\n <div className=\"relative flex h-full w-full flex-col overflow-hidden border border-border bg-background\">\n <div className=\"flex h-9 w-full shrink-0 border-b border-border\">\n {weeks[0]?.map((day) => {\n const label = day.toLocaleDateString(undefined, { weekday: 'short' }).toUpperCase()\n return (\n <div\n key={dayKeyOf(day)}\n className=\"flex min-w-0 flex-1 items-center justify-center border-r border-border last:border-r-0 sm:justify-start sm:pl-2.5\"\n >\n <span className=\"truncate text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n <span className=\"sm:hidden\">{label.charAt(0)}</span>\n <span className=\"hidden sm:inline\">{label}</span>\n </span>\n </div>\n )\n })}\n </div>\n {weeks.map((week) => (\n <div\n key={dayKeyOf(week[0])}\n className=\"flex w-full flex-1 border-b border-border last:border-b-0 min-h-14 sm:min-h-[86px]\"\n >\n {week.map((day) => (\n <MonthDayCell\n key={dayKeyOf(day)}\n day={day}\n anchor={anchor}\n items={itemsByDay.get(dayKeyOf(day)) ?? []}\n onItemClick={onItemClick}\n onDayOpen={onDayOpen}\n />\n ))}\n </div>\n ))}\n {items.length === 0 ? (\n <div className=\"pointer-events-none absolute inset-0 z-10 flex items-center justify-center p-6\">\n <EmptyState\n icon={<CalendarDays className=\"h-6 w-6\" aria-hidden=\"true\" />}\n title={t('customers.calendar.empty.month', 'Nothing scheduled this month')}\n className=\"bg-background/90\"\n />\n </div>\n ) : null}\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { addDays } from 'date-fns/addDays'\nimport { format } from 'date-fns/format'\nimport { isSameMonth } from 'date-fns/isSameMonth'\nimport { isToday } from 'date-fns/isToday'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { getVisibleRange } from '../../lib/calendar/range'\nimport { eventDisplayTitle } from '../../lib/calendar/labels'\nimport type { CalendarItem, MonthGridProps } from './types'\n\nconst MAX_PILLS_PER_DAY = 2\nconst SOFT_TINT_ALPHA = '1A'\n\nfunction dayKeyOf(date: Date): string {\n return format(date, 'yyyy-MM-dd')\n}\n\nfunction formatTime(date: Date): string {\n return date.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' })\n}\n\nfunction fullDateLabel(date: Date): string {\n return date.toLocaleDateString(undefined, { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })\n}\n\nfunction isWeekend(date: Date): boolean {\n const weekday = date.getDay()\n return weekday === 0 || weekday === 6\n}\n\nfunction buildWeeks(anchor: Date): Date[][] {\n const range = getVisibleRange('month', anchor, 0)\n const weeks: Date[][] = []\n let cursor = range.from\n while (cursor.getTime() <= range.to.getTime()) {\n const week: Date[] = []\n for (let dayIndex = 0; dayIndex < 7; dayIndex += 1) {\n week.push(cursor)\n cursor = addDays(cursor, 1)\n }\n weeks.push(week)\n }\n return weeks\n}\n\nfunction groupItemsByDay(items: CalendarItem[]): Map<string, CalendarItem[]> {\n const sorted = [...items].sort((first, second) => first.start.getTime() - second.start.getTime())\n const byDay = new Map<string, CalendarItem[]>()\n for (const item of sorted) {\n const key = dayKeyOf(item.start)\n const bucket = byDay.get(key)\n if (bucket) bucket.push(item)\n else byDay.set(key, [item])\n }\n return byDay\n}\n\nfunction MonthPill({ item, onItemClick }: { item: CalendarItem; onItemClick: (item: CalendarItem) => void }) {\n const t = useT()\n const canceled = item.status === 'canceled'\n const title = eventDisplayTitle(item.title, t('customers.calendar.grid.untitled', 'Untitled'))\n const timeLabel = item.allDay ? '' : ` \u00B7 ${formatTime(item.start)} \u2013 ${formatTime(item.end)}`\n const tintStyle = item.color\n ? { backgroundColor: `${item.color}${SOFT_TINT_ALPHA}`, color: item.color }\n : undefined\n return (\n <Button\n type=\"button\"\n variant=\"ghost\"\n aria-label={`${title}${timeLabel}`}\n onClick={(event) => {\n event.stopPropagation()\n onItemClick(item)\n }}\n className={cn(\n 'h-4 w-full min-w-0 justify-center gap-0 rounded-full p-0 pr-2',\n !item.color && 'bg-muted text-muted-foreground',\n canceled && 'opacity-60',\n )}\n style={tintStyle}\n >\n <span aria-hidden=\"true\" className=\"flex size-4 shrink-0 items-center justify-center\">\n <span\n className={cn('size-1.5 rounded-full', !item.color && 'bg-muted-foreground')}\n style={item.color ? { backgroundColor: item.color } : undefined}\n />\n </span>\n <span\n className={cn(\n 'min-w-0 truncate text-overline font-medium uppercase tracking-wide',\n canceled && 'line-through',\n )}\n >\n {title}\n </span>\n </Button>\n )\n}\n\nfunction MonthDayCell({\n day,\n anchor,\n items,\n onItemClick,\n onDayOpen,\n}: {\n day: Date\n anchor: Date\n items: CalendarItem[]\n onItemClick: (item: CalendarItem) => void\n onDayOpen: (date: Date) => void\n}) {\n const t = useT()\n const inMonth = isSameMonth(day, anchor)\n const today = isToday(day)\n const visibleItems = items.slice(0, MAX_PILLS_PER_DAY)\n const hiddenCount = items.length - visibleItems.length\n const dayLabel = fullDateLabel(day)\n return (\n <div\n className={cn(\n 'relative flex h-full min-w-0 flex-1 flex-col items-start gap-1 overflow-hidden border-r border-border p-2 text-left last:border-r-0',\n isWeekend(day) ? 'bg-muted/40' : 'bg-background',\n )}\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n aria-label={dayLabel}\n onClick={() => onDayOpen(day)}\n className=\"absolute inset-0 z-0 h-full w-full rounded-none p-0 hover:bg-muted/50\"\n >\n <span className=\"sr-only\">{dayLabel}</span>\n </Button>\n {today ? (\n <span className=\"pointer-events-none relative z-10 flex items-center justify-center rounded-full bg-primary px-1.5 py-0.5 text-xs font-semibold text-primary-foreground\">\n {day.getDate()}\n </span>\n ) : (\n <span className={cn('pointer-events-none relative z-10 text-xs font-medium', inMonth ? 'text-foreground' : 'text-muted-foreground')}>\n {day.getDate()}\n </span>\n )}\n <span className=\"relative z-20 hidden w-full flex-col gap-1 sm:flex\">\n {visibleItems.map((item) => (\n <MonthPill key={item.id} item={item} onItemClick={onItemClick} />\n ))}\n {hiddenCount > 0 ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-auto self-start p-0 text-overline font-medium text-muted-foreground hover:bg-transparent hover:underline\"\n onClick={(event) => {\n event.stopPropagation()\n onDayOpen(day)\n }}\n >\n {t('customers.calendar.grid.more', '+{count} more', { count: hiddenCount })}\n </Button>\n ) : null}\n </span>\n {items.length > 0 ? (\n <span aria-hidden=\"true\" className=\"pointer-events-none relative z-10 flex w-full flex-wrap items-center gap-0.5 sm:hidden\">\n {items.slice(0, 4).map((item) => (\n <span\n key={item.id}\n className={cn('size-1.5 rounded-full', !item.color && 'bg-muted-foreground')}\n style={item.color ? { backgroundColor: item.color } : undefined}\n />\n ))}\n {items.length > 4 ? (\n <span className=\"text-overline font-medium leading-none text-muted-foreground\">\n +{items.length - 4}\n </span>\n ) : null}\n </span>\n ) : null}\n </div>\n )\n}\n\nexport function MonthGrid({ anchor, items, onItemClick, onDayOpen }: MonthGridProps) {\n const t = useT()\n const weeks = React.useMemo(() => buildWeeks(anchor), [anchor])\n const itemsByDay = React.useMemo(() => groupItemsByDay(items), [items])\n return (\n <div className=\"relative flex h-full w-full flex-col overflow-hidden border border-border bg-background\">\n <div className=\"flex h-9 w-full shrink-0 border-b border-border\">\n {weeks[0]?.map((day) => {\n const label = day.toLocaleDateString(undefined, { weekday: 'short' }).toUpperCase()\n return (\n <div\n key={dayKeyOf(day)}\n className=\"flex min-w-0 flex-1 items-center justify-center border-r border-border last:border-r-0 sm:justify-start sm:pl-2.5\"\n >\n <span className=\"truncate text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n <span className=\"sm:hidden\">{label.charAt(0)}</span>\n <span className=\"hidden sm:inline\">{label}</span>\n </span>\n </div>\n )\n })}\n </div>\n {weeks.map((week) => (\n <div\n key={dayKeyOf(week[0])}\n className=\"flex w-full flex-1 border-b border-border last:border-b-0 min-h-14 sm:min-h-[86px]\"\n >\n {week.map((day) => (\n <MonthDayCell\n key={dayKeyOf(day)}\n day={day}\n anchor={anchor}\n items={itemsByDay.get(dayKeyOf(day)) ?? []}\n onItemClick={onItemClick}\n onDayOpen={onDayOpen}\n />\n ))}\n </div>\n ))}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }