@open-mercato/core 0.6.6-develop.6089.1.a7ed560528 → 0.6.6-develop.6121.1.5797a901b3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/generated/entities/catalog_product/index.js +52 -0
- package/dist/generated/entities/catalog_product/index.js.map +2 -2
- package/dist/generated/entities/catalog_product_variant/index.js +4 -0
- package/dist/generated/entities/catalog_product_variant/index.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +28 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/catalog/api/products/route.js +103 -33
- package/dist/modules/catalog/api/products/route.js.map +2 -2
- package/dist/modules/catalog/api/variants/route.js +4 -0
- package/dist/modules/catalog/api/variants/route.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +46 -2
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +4 -0
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js +2 -0
- package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/create/page.js +42 -2
- package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
- package/dist/modules/catalog/commands/products.js +251 -14
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/commands/variants.js +72 -1
- package/dist/modules/catalog/commands/variants.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductComplianceSection.js +500 -0
- package/dist/modules/catalog/components/products/ProductComplianceSection.js.map +7 -0
- package/dist/modules/catalog/components/products/VariantBuilder.js +39 -1
- package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
- package/dist/modules/catalog/components/products/productForm.js +164 -2
- package/dist/modules/catalog/components/products/productForm.js.map +2 -2
- package/dist/modules/catalog/components/products/variantForm.js +2 -0
- package/dist/modules/catalog/components/products/variantForm.js.map +2 -2
- package/dist/modules/catalog/data/entities.js +93 -0
- package/dist/modules/catalog/data/entities.js.map +2 -2
- package/dist/modules/catalog/data/types.js +28 -0
- package/dist/modules/catalog/data/types.js.map +2 -2
- package/dist/modules/catalog/data/validators.js +100 -5
- package/dist/modules/catalog/data/validators.js.map +2 -2
- package/dist/modules/catalog/lib/gtin.js +61 -0
- package/dist/modules/catalog/lib/gtin.js.map +7 -0
- package/dist/modules/catalog/migrations/Migration20260611090000.js +17 -0
- package/dist/modules/catalog/migrations/Migration20260611090000.js.map +7 -0
- package/dist/modules/catalog/translations.js +1 -1
- package/dist/modules/catalog/translations.js.map +2 -2
- package/dist/modules/configs/api/cache/route.js +60 -10
- package/dist/modules/configs/api/cache/route.js.map +3 -3
- package/dist/modules/configs/components/CachePanel.js +52 -29
- package/dist/modules/configs/components/CachePanel.js.map +2 -2
- package/dist/modules/currencies/api/currencies/options/route.js +18 -4
- package/dist/modules/currencies/api/currencies/options/route.js.map +2 -2
- package/dist/modules/currencies/services/rateFetchingService.js +35 -18
- package/dist/modules/currencies/services/rateFetchingService.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +16 -16
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +1 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
- package/dist/modules/customers/backend/calendar/page.js +10 -0
- package/dist/modules/customers/backend/calendar/page.js.map +7 -0
- package/dist/modules/customers/backend/calendar/page.meta.js +25 -0
- package/dist/modules/customers/backend/calendar/page.meta.js.map +7 -0
- package/dist/modules/customers/cli.js +1 -0
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.js +182 -0
- package/dist/modules/customers/components/calendar/AgendaList.js.map +7 -0
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js +331 -0
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +7 -0
- package/dist/modules/customers/components/calendar/CalendarFooter.js +48 -0
- package/dist/modules/customers/components/calendar/CalendarFooter.js.map +7 -0
- package/dist/modules/customers/components/calendar/CalendarHeader.js +36 -0
- package/dist/modules/customers/components/calendar/CalendarHeader.js.map +7 -0
- package/dist/modules/customers/components/calendar/CalendarScreen.js +516 -0
- package/dist/modules/customers/components/calendar/CalendarScreen.js.map +7 -0
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +163 -0
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +7 -0
- package/dist/modules/customers/components/calendar/CalendarTabs.js +60 -0
- package/dist/modules/customers/components/calendar/CalendarTabs.js.map +7 -0
- package/dist/modules/customers/components/calendar/CalendarToolbar.js +262 -0
- package/dist/modules/customers/components/calendar/CalendarToolbar.js.map +7 -0
- package/dist/modules/customers/components/calendar/EventBlock.js +149 -0
- package/dist/modules/customers/components/calendar/EventBlock.js.map +7 -0
- package/dist/modules/customers/components/calendar/EventPeekPopover.js +72 -0
- package/dist/modules/customers/components/calendar/EventPeekPopover.js.map +7 -0
- package/dist/modules/customers/components/calendar/MonthGrid.js +214 -0
- package/dist/modules/customers/components/calendar/MonthGrid.js.map +7 -0
- package/dist/modules/customers/components/calendar/ShortcutsDialog.js +44 -0
- package/dist/modules/customers/components/calendar/ShortcutsDialog.js.map +7 -0
- package/dist/modules/customers/components/calendar/TimeGrid.js +410 -0
- package/dist/modules/customers/components/calendar/TimeGrid.js.map +7 -0
- package/dist/modules/customers/components/calendar/UpcomingCards.js +175 -0
- package/dist/modules/customers/components/calendar/UpcomingCards.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/CategoryField.js +75 -0
- package/dist/modules/customers/components/calendar/editor/CategoryField.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/LocationField.js +30 -0
- package/dist/modules/customers/components/calendar/editor/LocationField.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/PeopleField.js +135 -0
- package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/RelatedToField.js +218 -0
- package/dist/modules/customers/components/calendar/editor/RelatedToField.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/RepeatField.js +119 -0
- package/dist/modules/customers/components/calendar/editor/RepeatField.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/ScheduleSection.js +83 -0
- package/dist/modules/customers/components/calendar/editor/ScheduleSection.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/SegmentGroup.js +44 -0
- package/dist/modules/customers/components/calendar/editor/SegmentGroup.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/hooks.js +132 -0
- package/dist/modules/customers/components/calendar/editor/hooks.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/inputs.js +160 -0
- package/dist/modules/customers/components/calendar/editor/inputs.js.map +7 -0
- package/dist/modules/customers/components/calendar/editor/lookups.js +107 -0
- package/dist/modules/customers/components/calendar/editor/lookups.js.map +7 -0
- package/dist/modules/customers/components/calendar/types.js +30 -0
- package/dist/modules/customers/components/calendar/types.js.map +7 -0
- package/dist/modules/customers/components/calendar/useCalendarItems.js +131 -0
- package/dist/modules/customers/components/calendar/useCalendarItems.js.map +7 -0
- package/dist/modules/customers/components/calendar/useCalendarPreferences.js +41 -0
- package/dist/modules/customers/components/calendar/useCalendarPreferences.js.map +7 -0
- package/dist/modules/customers/lib/calendar/categories.js +28 -0
- package/dist/modules/customers/lib/calendar/categories.js.map +7 -0
- package/dist/modules/customers/lib/calendar/conflicts.js +72 -0
- package/dist/modules/customers/lib/calendar/conflicts.js.map +7 -0
- package/dist/modules/customers/lib/calendar/editorPayload.js +271 -0
- package/dist/modules/customers/lib/calendar/editorPayload.js.map +7 -0
- package/dist/modules/customers/lib/calendar/grid.js +48 -0
- package/dist/modules/customers/lib/calendar/grid.js.map +7 -0
- package/dist/modules/customers/lib/calendar/layout.js +39 -0
- package/dist/modules/customers/lib/calendar/layout.js.map +7 -0
- package/dist/modules/customers/lib/calendar/mapItem.js +79 -0
- package/dist/modules/customers/lib/calendar/mapItem.js.map +7 -0
- package/dist/modules/customers/lib/calendar/preferences.js +71 -0
- package/dist/modules/customers/lib/calendar/preferences.js.map +7 -0
- package/dist/modules/customers/lib/calendar/range.js +46 -0
- package/dist/modules/customers/lib/calendar/range.js.map +7 -0
- package/dist/modules/customers/lib/calendar/recurrence.js +113 -0
- package/dist/modules/customers/lib/calendar/recurrence.js.map +7 -0
- package/dist/modules/dashboards/services/widgetDataService.js +5 -5
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +61 -1
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +33 -1
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/route.js +61 -1
- package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
- package/dist/modules/dictionaries/api/route.js +33 -1
- package/dist/modules/dictionaries/api/route.js.map +2 -2
- package/dist/modules/feature_toggles/lib/queries.js +36 -52
- package/dist/modules/feature_toggles/lib/queries.js.map +2 -2
- package/dist/modules/messages/commands/actions.js +81 -9
- package/dist/modules/messages/commands/actions.js.map +2 -2
- package/dist/modules/perspectives/api/[tableId]/[perspectiveId]/route.js +32 -1
- package/dist/modules/perspectives/api/[tableId]/[perspectiveId]/route.js.map +2 -2
- package/dist/modules/perspectives/api/[tableId]/roles/[roleId]/route.js +32 -1
- package/dist/modules/perspectives/api/[tableId]/roles/[roleId]/route.js.map +2 -2
- package/dist/modules/perspectives/api/[tableId]/route.js +73 -2
- package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
- package/dist/modules/perspectives/services/perspectiveService.js +5 -3
- package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
- package/dist/modules/planner/api/access.js +9 -0
- package/dist/modules/planner/api/access.js.map +2 -2
- package/dist/modules/planner/api/availability-date-specific.js +22 -1
- package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
- package/dist/modules/planner/api/availability-weekly.js +22 -1
- package/dist/modules/planner/api/availability-weekly.js.map +2 -2
- package/dist/modules/resources/api/resources/tags/assign/route.js +39 -0
- package/dist/modules/resources/api/resources/tags/assign/route.js.map +2 -2
- package/dist/modules/resources/api/resources/tags/unassign/route.js +39 -0
- package/dist/modules/resources/api/resources/tags/unassign/route.js.map +2 -2
- package/dist/modules/sales/api/settings/document-numbers/route.js +33 -1
- package/dist/modules/sales/api/settings/document-numbers/route.js.map +2 -2
- package/dist/modules/sales/api/settings/order-editing/route.js +35 -3
- package/dist/modules/sales/api/settings/order-editing/route.js.map +2 -2
- package/dist/modules/staff/api/leave-requests/accept/route.js +41 -0
- package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
- package/dist/modules/staff/api/leave-requests/reject/route.js +41 -0
- package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/self/route.js +40 -0
- package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/tags/assign/route.js +41 -0
- package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
- package/dist/modules/staff/api/team-members/tags/unassign/route.js +41 -0
- package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
- package/dist/modules/translations/api/[entityType]/[entityId]/route.js +61 -1
- package/dist/modules/translations/api/[entityType]/[entityId]/route.js.map +2 -2
- package/dist/modules/translations/api/context.js +7 -0
- package/dist/modules/translations/api/context.js.map +2 -2
- package/dist/modules/translations/api/put/locales.js +33 -1
- package/dist/modules/translations/api/put/locales.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +6 -7
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.js.map +1 -1
- package/dist/modules/workflows/components/EdgeEditDialog.js.map +1 -1
- package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js.map +1 -1
- package/dist/modules/workflows/components/NodeEditDialog.js.map +1 -1
- package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +1 -1
- package/dist/modules/workflows/components/WorkflowGraph.js.map +1 -1
- package/dist/modules/workflows/components/WorkflowGraphImpl.js +17 -9
- package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
- package/dist/modules/workflows/components/mobile/MobileVisualEditor.js.map +1 -1
- package/dist/modules/workflows/frontend/checkout-demo/deriveCurrentStep.js +8 -0
- package/dist/modules/workflows/frontend/checkout-demo/deriveCurrentStep.js.map +7 -0
- package/dist/modules/workflows/frontend/checkout-demo/page.js +2 -20
- package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
- package/dist/modules/workflows/lib/graph-utils.js +8 -0
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/generated/entities/catalog_product/index.ts +26 -0
- package/generated/entities/catalog_product_variant/index.ts +2 -0
- package/generated/entity-fields-registry.ts +28 -0
- package/package.json +7 -7
- package/src/modules/catalog/api/products/route.ts +123 -39
- package/src/modules/catalog/api/variants/route.ts +4 -0
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +43 -0
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +14 -0
- package/src/modules/catalog/backend/catalog/products/[productId]/variants/create/page.tsx +2 -0
- package/src/modules/catalog/backend/catalog/products/create/page.tsx +41 -0
- package/src/modules/catalog/commands/products.ts +307 -2
- package/src/modules/catalog/commands/variants.ts +90 -1
- package/src/modules/catalog/components/products/ProductComplianceSection.tsx +497 -0
- package/src/modules/catalog/components/products/VariantBuilder.tsx +43 -0
- package/src/modules/catalog/components/products/productForm.ts +262 -0
- package/src/modules/catalog/components/products/variantForm.ts +4 -0
- package/src/modules/catalog/data/entities.ts +97 -0
- package/src/modules/catalog/data/types.ts +36 -0
- package/src/modules/catalog/data/validators.ts +159 -3
- package/src/modules/catalog/i18n/de.json +64 -0
- package/src/modules/catalog/i18n/en.json +64 -0
- package/src/modules/catalog/i18n/es.json +64 -0
- package/src/modules/catalog/i18n/pl.json +64 -0
- package/src/modules/catalog/lib/gtin.ts +66 -0
- package/src/modules/catalog/migrations/.snapshot-open-mercato.json +457 -0
- package/src/modules/catalog/migrations/Migration20260611090000.ts +17 -0
- package/src/modules/catalog/translations.ts +1 -1
- package/src/modules/configs/api/cache/route.ts +72 -10
- package/src/modules/configs/components/CachePanel.tsx +59 -29
- package/src/modules/currencies/api/currencies/options/route.ts +22 -4
- package/src/modules/currencies/services/rateFetchingService.ts +63 -26
- package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +18 -18
- package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +1 -1
- package/src/modules/customer_accounts/i18n/de.json +1 -1
- package/src/modules/customer_accounts/i18n/en.json +1 -1
- package/src/modules/customer_accounts/i18n/es.json +1 -1
- package/src/modules/customer_accounts/i18n/pl.json +1 -1
- package/src/modules/customers/backend/calendar/page.meta.ts +23 -0
- package/src/modules/customers/backend/calendar/page.tsx +12 -0
- package/src/modules/customers/cli.ts +1 -0
- package/src/modules/customers/components/calendar/AgendaList.tsx +219 -0
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +386 -0
- package/src/modules/customers/components/calendar/CalendarFooter.tsx +61 -0
- package/src/modules/customers/components/calendar/CalendarHeader.tsx +40 -0
- package/src/modules/customers/components/calendar/CalendarScreen.tsx +590 -0
- package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +207 -0
- package/src/modules/customers/components/calendar/CalendarTabs.tsx +63 -0
- package/src/modules/customers/components/calendar/CalendarToolbar.tsx +295 -0
- package/src/modules/customers/components/calendar/EventBlock.tsx +205 -0
- package/src/modules/customers/components/calendar/EventPeekPopover.tsx +100 -0
- package/src/modules/customers/components/calendar/MonthGrid.tsx +236 -0
- package/src/modules/customers/components/calendar/ShortcutsDialog.tsx +57 -0
- package/src/modules/customers/components/calendar/TimeGrid.tsx +510 -0
- package/src/modules/customers/components/calendar/UpcomingCards.tsx +220 -0
- package/src/modules/customers/components/calendar/editor/CategoryField.tsx +79 -0
- package/src/modules/customers/components/calendar/editor/LocationField.tsx +37 -0
- package/src/modules/customers/components/calendar/editor/PeopleField.tsx +148 -0
- package/src/modules/customers/components/calendar/editor/RelatedToField.tsx +242 -0
- package/src/modules/customers/components/calendar/editor/RepeatField.tsx +132 -0
- package/src/modules/customers/components/calendar/editor/ScheduleSection.tsx +110 -0
- package/src/modules/customers/components/calendar/editor/SegmentGroup.tsx +50 -0
- package/src/modules/customers/components/calendar/editor/hooks.ts +162 -0
- package/src/modules/customers/components/calendar/editor/inputs.tsx +158 -0
- package/src/modules/customers/components/calendar/editor/lookups.ts +160 -0
- package/src/modules/customers/components/calendar/types.ts +163 -0
- package/src/modules/customers/components/calendar/useCalendarItems.ts +162 -0
- package/src/modules/customers/components/calendar/useCalendarPreferences.ts +52 -0
- package/src/modules/customers/i18n/de.json +195 -0
- package/src/modules/customers/i18n/en.json +195 -0
- package/src/modules/customers/i18n/es.json +195 -0
- package/src/modules/customers/i18n/pl.json +195 -0
- package/src/modules/customers/lib/calendar/categories.ts +26 -0
- package/src/modules/customers/lib/calendar/conflicts.ts +117 -0
- package/src/modules/customers/lib/calendar/editorPayload.ts +388 -0
- package/src/modules/customers/lib/calendar/grid.ts +50 -0
- package/src/modules/customers/lib/calendar/layout.ts +47 -0
- package/src/modules/customers/lib/calendar/mapItem.ts +94 -0
- package/src/modules/customers/lib/calendar/preferences.ts +95 -0
- package/src/modules/customers/lib/calendar/range.ts +45 -0
- package/src/modules/customers/lib/calendar/recurrence.ts +137 -0
- package/src/modules/dashboards/services/widgetDataService.ts +8 -6
- package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +61 -1
- package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +33 -1
- package/src/modules/dictionaries/api/[dictionaryId]/route.ts +65 -1
- package/src/modules/dictionaries/api/route.ts +36 -1
- package/src/modules/feature_toggles/lib/queries.ts +41 -60
- package/src/modules/messages/commands/actions.ts +100 -7
- package/src/modules/perspectives/api/[tableId]/[perspectiveId]/route.ts +34 -1
- package/src/modules/perspectives/api/[tableId]/roles/[roleId]/route.ts +34 -1
- package/src/modules/perspectives/api/[tableId]/route.ts +107 -32
- package/src/modules/perspectives/services/perspectiveService.ts +9 -5
- package/src/modules/planner/api/access.ts +9 -0
- package/src/modules/planner/api/availability-date-specific.ts +22 -1
- package/src/modules/planner/api/availability-weekly.ts +22 -1
- package/src/modules/resources/api/resources/tags/assign/route.ts +42 -0
- package/src/modules/resources/api/resources/tags/unassign/route.ts +42 -0
- package/src/modules/sales/api/settings/document-numbers/route.ts +35 -1
- package/src/modules/sales/api/settings/order-editing/route.ts +37 -3
- package/src/modules/staff/api/leave-requests/accept/route.ts +45 -0
- package/src/modules/staff/api/leave-requests/reject/route.ts +45 -0
- package/src/modules/staff/api/team-members/self/route.ts +43 -0
- package/src/modules/staff/api/team-members/tags/assign/route.ts +45 -0
- package/src/modules/staff/api/team-members/tags/unassign/route.ts +45 -0
- package/src/modules/translations/api/[entityType]/[entityId]/route.ts +65 -1
- package/src/modules/translations/api/context.ts +7 -0
- package/src/modules/translations/api/put/locales.ts +35 -1
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +11 -9
- package/src/modules/workflows/backend/instances/[id]/page.tsx +1 -1
- package/src/modules/workflows/components/EdgeEditDialog.tsx +1 -1
- package/src/modules/workflows/components/EdgeEditDialogCrudForm.tsx +1 -1
- package/src/modules/workflows/components/NodeEditDialog.tsx +1 -1
- package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +1 -1
- package/src/modules/workflows/components/WorkflowGraph.tsx +2 -2
- package/src/modules/workflows/components/WorkflowGraphImpl.tsx +27 -13
- package/src/modules/workflows/components/mobile/MobileVisualEditor.tsx +3 -3
- package/src/modules/workflows/frontend/checkout-demo/deriveCurrentStep.ts +12 -0
- package/src/modules/workflows/frontend/checkout-demo/page.tsx +3 -23
- package/src/modules/workflows/lib/graph-utils.ts +21 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/customers/components/calendar/CalendarToolbar.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { format } from 'date-fns/format'\nimport { CalendarRange, ListFilter, Settings } from 'lucide-react'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Calendar } from '@open-mercato/ui/primitives/calendar'\nimport { CheckboxField } from '@open-mercato/ui/primitives/checkbox-field'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Kbd } from '@open-mercato/ui/primitives/kbd'\nimport { Popover, PopoverContent, PopoverTrigger } from '@open-mercato/ui/primitives/popover'\nimport { SearchInput } from '@open-mercato/ui/primitives/search-input'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type {\n CalendarFiltersValue,\n CalendarRangePreset,\n CalendarToolbarProps,\n} from './types'\n\nconst RANGE_PRESETS: CalendarRangePreset[] = ['thisWeek', 'next7', 'thisMonth', 'next30']\n\nconst STATUS_OPTIONS = ['planned', 'done', 'canceled'] as const\n\nconst ALL_OPTION = 'all'\n\nconst EMPTY_FILTERS: CalendarFiltersValue = { types: [], status: null, ownerUserId: null }\n\nfunction formatRangeLabel(from: Date, to: Date): string {\n return `${format(from, 'MMM dd')} \u2013 ${format(to, 'MMM dd, yyyy')}`\n}\n\nexport function CalendarToolbar(props: CalendarToolbarProps) {\n const {\n anchor,\n range,\n preset,\n search,\n filters,\n typeOptions,\n ownerOptions,\n onToday,\n onPresetChange,\n onAnchorChange,\n onSearchChange,\n onFiltersChange,\n onOpenSettings,\n } = props\n const t = useT()\n const [rangeOpen, setRangeOpen] = React.useState(false)\n const [filtersOpen, setFiltersOpen] = React.useState(false)\n const [pendingFilters, setPendingFilters] = React.useState<CalendarFiltersValue>(filters)\n\n const presetLabels: Record<CalendarRangePreset, string> = {\n thisWeek: t('customers.calendar.toolbar.presets.thisWeek', 'This week'),\n next7: t('customers.calendar.toolbar.presets.next7', 'Next 7 days'),\n thisMonth: t('customers.calendar.toolbar.presets.thisMonth', 'This month'),\n next30: t('customers.calendar.toolbar.presets.next30', 'Next 30 days'),\n }\n\n const activeFilterCount =\n filters.types.length + (filters.status ? 1 : 0) + (filters.ownerUserId ? 1 : 0)\n\n const handleFiltersOpenChange = (open: boolean) => {\n if (open) setPendingFilters(filters)\n setFiltersOpen(open)\n }\n\n const applyFilters = () => {\n onFiltersChange(pendingFilters)\n setFiltersOpen(false)\n }\n\n const clearFilters = () => {\n setPendingFilters(EMPTY_FILTERS)\n onFiltersChange(EMPTY_FILTERS)\n setFiltersOpen(false)\n }\n\n const togglePendingType = (value: string, checked: boolean) => {\n setPendingFilters((current) => ({\n ...current,\n types: checked\n ? [...current.types, value]\n : current.types.filter((entry) => entry !== value),\n }))\n }\n\n return (\n <div className=\"flex flex-wrap items-center gap-2 sm:gap-3\">\n <div className=\"flex min-w-0 flex-wrap items-center gap-2 sm:gap-3\">\n <Button type=\"button\" variant=\"outline\" onClick={onToday}>\n {t('customers.calendar.toolbar.today', 'Today')}\n </Button>\n <div className=\"flex min-w-0 items-center\">\n <Select\n value={preset ?? ''}\n onValueChange={(value) => onPresetChange(value as CalendarRangePreset)}\n >\n <SelectTrigger\n className=\"hidden w-auto min-w-32 rounded-r-none sm:flex\"\n aria-label={t('customers.calendar.toolbar.presetLabel', 'Date range preset')}\n >\n <SelectValue\n placeholder={t('customers.calendar.toolbar.presetPlaceholder', 'Custom range')}\n />\n </SelectTrigger>\n <SelectContent>\n {RANGE_PRESETS.map((value) => (\n <SelectItem key={value} value={value}>\n {presetLabels[value]}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Popover open={rangeOpen} onOpenChange={setRangeOpen}>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"min-w-0 text-muted-foreground sm:-ml-px sm:rounded-l-none\"\n >\n <CalendarRange aria-hidden=\"true\" />\n <span className=\"truncate\">{formatRangeLabel(range.from, range.to)}</span>\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-auto min-w-0 p-2\">\n <Calendar\n mode=\"single\"\n selected={anchor}\n defaultMonth={anchor}\n onSelect={(date) => {\n if (!date) return\n onAnchorChange(date)\n setRangeOpen(false)\n }}\n />\n </PopoverContent>\n </Popover>\n </div>\n </div>\n <div className=\"flex w-full min-w-0 items-center gap-2 sm:ml-auto sm:w-auto sm:flex-none sm:gap-3\">\n <div className=\"relative min-w-0 flex-1 sm:w-72 sm:flex-none\">\n <SearchInput\n value={search}\n onChange={onSearchChange}\n placeholder={t('customers.calendar.toolbar.searchPlaceholder', 'Search\u2026')}\n aria-label={t('customers.calendar.toolbar.searchPlaceholder', 'Search\u2026')}\n data-calendar-search=\"\"\n />\n {search.length === 0 ? (\n <Kbd className=\"pointer-events-none absolute right-2 top-1/2 hidden -translate-y-1/2 sm:inline-flex\">/</Kbd>\n ) : null}\n </div>\n <Popover open={filtersOpen} onOpenChange={handleFiltersOpenChange}>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"outline\"\n aria-label={t('customers.calendar.toolbar.filters.label', 'Filter')}\n >\n <ListFilter aria-hidden=\"true\" />\n <span className=\"hidden sm:inline\">\n {t('customers.calendar.toolbar.filters.label', 'Filter')}\n </span>\n {activeFilterCount > 0 ? (\n <Badge variant=\"secondary\" size=\"sm\">\n {activeFilterCount}\n </Badge>\n ) : null}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n className=\"w-72 p-3\"\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n applyFilters()\n }\n }}\n >\n <div className=\"flex flex-col gap-4\">\n {typeOptions.length > 0 ? (\n <fieldset className=\"flex flex-col gap-2\">\n <legend className=\"pb-1 text-overline font-semibold uppercase tracking-widest text-muted-foreground\">\n {t('customers.calendar.toolbar.filters.types', 'Type')}\n </legend>\n {typeOptions.map((option) => (\n <CheckboxField\n key={option.value}\n label={option.label}\n size=\"sm\"\n checked={pendingFilters.types.includes(option.value)}\n onCheckedChange={(checked) =>\n togglePendingType(option.value, checked === true)\n }\n />\n ))}\n </fieldset>\n ) : null}\n <div className=\"flex flex-col gap-1.5\">\n <span className=\"text-overline font-semibold uppercase tracking-widest text-muted-foreground\">\n {t('customers.calendar.toolbar.filters.status', 'Status')}\n </span>\n <Select\n value={pendingFilters.status ?? ALL_OPTION}\n onValueChange={(value) =>\n setPendingFilters((current) => ({\n ...current,\n status: value === ALL_OPTION ? null : value,\n }))\n }\n >\n <SelectTrigger\n size=\"sm\"\n aria-label={t('customers.calendar.toolbar.filters.status', 'Status')}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL_OPTION}>\n {t('customers.calendar.toolbar.filters.allStatuses', 'All statuses')}\n </SelectItem>\n {STATUS_OPTIONS.map((status) => (\n <SelectItem key={status} value={status}>\n {t(`customers.calendar.toolbar.filters.statuses.${status}`, status)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {ownerOptions.length > 0 ? (\n <div className=\"flex flex-col gap-1.5\">\n <span className=\"text-overline font-semibold uppercase tracking-widest text-muted-foreground\">\n {t('customers.calendar.toolbar.filters.owner', 'Owner')}\n </span>\n <Select\n value={pendingFilters.ownerUserId ?? ALL_OPTION}\n onValueChange={(value) =>\n setPendingFilters((current) => ({\n ...current,\n ownerUserId: value === ALL_OPTION ? null : value,\n }))\n }\n >\n <SelectTrigger\n size=\"sm\"\n aria-label={t('customers.calendar.toolbar.filters.owner', 'Owner')}\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={ALL_OPTION}>\n {t('customers.calendar.toolbar.filters.allOwners', 'All owners')}\n </SelectItem>\n {ownerOptions.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : null}\n <div className=\"flex items-center justify-end gap-2 border-t pt-3\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={clearFilters}>\n {t('customers.calendar.toolbar.filters.clear', 'Clear')}\n </Button>\n <Button type=\"button\" size=\"sm\" onClick={applyFilters}>\n {t('customers.calendar.toolbar.filters.apply', 'Apply')}\n </Button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n <IconButton\n type=\"button\"\n variant=\"outline\"\n aria-label={t('customers.calendar.toolbar.settings', 'Calendar settings')}\n onClick={onOpenSettings}\n >\n <Settings aria-hidden />\n </IconButton>\n </div>\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Globe, MapPin } from "lucide-react";
|
|
5
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
6
|
+
import { useLocale, useT } from "@open-mercato/shared/lib/i18n/context";
|
|
7
|
+
import { Avatar, AvatarStack } from "@open-mercato/ui/primitives/avatar";
|
|
8
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
9
|
+
const SHOW_TIME_MIN_HEIGHT_PX = 44;
|
|
10
|
+
const SHOW_META_MIN_HEIGHT_PX = 96;
|
|
11
|
+
const WRAP_TITLE_MIN_HEIGHT_PX = 128;
|
|
12
|
+
const MAX_VISIBLE_AVATARS = 3;
|
|
13
|
+
const PLATFORM_LABELS = {
|
|
14
|
+
zoom: { key: "customers.calendar.platform.zoom", fallback: "Zoom" },
|
|
15
|
+
meet: { key: "customers.calendar.platform.meet", fallback: "Meet" },
|
|
16
|
+
slack: { key: "customers.calendar.platform.slack", fallback: "Slack" },
|
|
17
|
+
teams: { key: "customers.calendar.platform.teams", fallback: "Teams" }
|
|
18
|
+
};
|
|
19
|
+
function softTintStyle(color) {
|
|
20
|
+
if (/^#[0-9a-fA-F]{6}$/.test(color)) return { backgroundColor: `${color}1A` };
|
|
21
|
+
return { backgroundColor: `color-mix(in srgb, ${color} 10%, transparent)` };
|
|
22
|
+
}
|
|
23
|
+
function resolveEventTone(item, nowMs) {
|
|
24
|
+
if (item.status === "canceled") {
|
|
25
|
+
return {
|
|
26
|
+
surfaceClassName: "bg-muted/60",
|
|
27
|
+
titleClassName: "text-muted-foreground line-through",
|
|
28
|
+
subClassName: "text-muted-foreground/70"
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
if (item.status === "done" || item.end.getTime() < nowMs) {
|
|
32
|
+
return {
|
|
33
|
+
surfaceClassName: "bg-muted",
|
|
34
|
+
titleClassName: "text-muted-foreground",
|
|
35
|
+
subClassName: "text-muted-foreground"
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (item.color) {
|
|
39
|
+
return {
|
|
40
|
+
surfaceClassName: "",
|
|
41
|
+
titleClassName: "text-foreground",
|
|
42
|
+
subClassName: "text-muted-foreground",
|
|
43
|
+
style: softTintStyle(item.color)
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
surfaceClassName: "bg-muted/60",
|
|
48
|
+
titleClassName: "text-foreground",
|
|
49
|
+
subClassName: "text-muted-foreground"
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function formatTimeRange(locale, start, end) {
|
|
53
|
+
const formatter = new Intl.DateTimeFormat(locale, { hour: "numeric", minute: "2-digit" });
|
|
54
|
+
try {
|
|
55
|
+
return formatter.formatRange(start, end);
|
|
56
|
+
} catch {
|
|
57
|
+
return `${formatter.format(start)} - ${formatter.format(end)}`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function participantLabel(participant) {
|
|
61
|
+
return participant.name ?? participant.email ?? "?";
|
|
62
|
+
}
|
|
63
|
+
function LocationMeta({ item, subClassName, accentColor }) {
|
|
64
|
+
const t = useT();
|
|
65
|
+
if (!item.location || !item.locationKind) return null;
|
|
66
|
+
const iconStyle = accentColor ? { color: accentColor } : void 0;
|
|
67
|
+
if (item.locationKind === "platform" && item.platform) {
|
|
68
|
+
const platform = PLATFORM_LABELS[item.platform];
|
|
69
|
+
return /* @__PURE__ */ jsx("span", { className: cn("truncate text-xs", subClassName), children: t("customers.calendar.grid.onPlatform", "on {platform}", { platform: t(platform.key, platform.fallback) }) });
|
|
70
|
+
}
|
|
71
|
+
if (item.locationKind === "url") {
|
|
72
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
73
|
+
/* @__PURE__ */ jsx(Globe, { className: cn("size-4 shrink-0", !accentColor && subClassName), style: iconStyle, "aria-hidden": true }),
|
|
74
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-xs text-foreground", children: item.location })
|
|
75
|
+
] });
|
|
76
|
+
}
|
|
77
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
78
|
+
/* @__PURE__ */ jsx(MapPin, { className: cn("size-4 shrink-0", !accentColor && subClassName), style: iconStyle, "aria-hidden": true }),
|
|
79
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-xs text-foreground", children: t("customers.calendar.grid.venue", "Venue: {name}", { name: item.location }) })
|
|
80
|
+
] });
|
|
81
|
+
}
|
|
82
|
+
const EventBlock = React.forwardRef(function EventBlock2({
|
|
83
|
+
item,
|
|
84
|
+
top,
|
|
85
|
+
height,
|
|
86
|
+
insetInlineStart,
|
|
87
|
+
width,
|
|
88
|
+
conflicted,
|
|
89
|
+
highlighted,
|
|
90
|
+
selected,
|
|
91
|
+
nowMs,
|
|
92
|
+
className,
|
|
93
|
+
...buttonProps
|
|
94
|
+
}, ref) {
|
|
95
|
+
const t = useT();
|
|
96
|
+
const locale = useLocale();
|
|
97
|
+
const tone = resolveEventTone(item, nowMs);
|
|
98
|
+
const title = item.title || t("customers.calendar.grid.untitled", "Untitled");
|
|
99
|
+
const timeRange = formatTimeRange(locale, item.start, item.end);
|
|
100
|
+
const showTime = height >= SHOW_TIME_MIN_HEIGHT_PX;
|
|
101
|
+
const wrapTitle = height >= WRAP_TITLE_MIN_HEIGHT_PX;
|
|
102
|
+
const hasMetaContent = item.participants.length > 0 || item.location !== null && item.locationKind !== null;
|
|
103
|
+
const showMeta = height >= SHOW_META_MIN_HEIGHT_PX && hasMetaContent;
|
|
104
|
+
const visibleParticipants = item.participants.slice(0, MAX_VISIBLE_AVATARS);
|
|
105
|
+
const overflowCount = item.participants.length - visibleParticipants.length;
|
|
106
|
+
return /* @__PURE__ */ jsxs(
|
|
107
|
+
Button,
|
|
108
|
+
{
|
|
109
|
+
ref,
|
|
110
|
+
type: "button",
|
|
111
|
+
variant: "ghost",
|
|
112
|
+
"aria-label": `${title}, ${timeRange}`,
|
|
113
|
+
className: cn(
|
|
114
|
+
"pointer-events-auto absolute h-auto flex-col items-start justify-start gap-1 whitespace-normal overflow-hidden rounded-md px-1.5 text-start outline-none hover:bg-muted/70 sm:px-3",
|
|
115
|
+
height >= SHOW_TIME_MIN_HEIGHT_PX ? "py-1 sm:py-2" : "py-0.5 sm:py-1",
|
|
116
|
+
tone.surfaceClassName,
|
|
117
|
+
conflicted && "ring-1 ring-status-warning-icon",
|
|
118
|
+
selected && "shadow-md ring-2 ring-foreground",
|
|
119
|
+
highlighted && "motion-safe:animate-pulse",
|
|
120
|
+
conflicted || highlighted || selected ? "z-30" : "z-10",
|
|
121
|
+
"focus-visible:z-30 focus-visible:ring-2 focus-visible:ring-ring",
|
|
122
|
+
className
|
|
123
|
+
),
|
|
124
|
+
style: { top, height, insetInlineStart, width, ...tone.style },
|
|
125
|
+
...buttonProps,
|
|
126
|
+
children: [
|
|
127
|
+
/* @__PURE__ */ jsx("span", { className: cn("w-full text-xs font-medium leading-4", wrapTitle ? "line-clamp-2" : "truncate", tone.titleClassName), children: title }),
|
|
128
|
+
showTime ? /* @__PURE__ */ jsx("span", { className: cn("w-full truncate text-overline uppercase tracking-wide", tone.subClassName), children: timeRange }) : null,
|
|
129
|
+
showMeta ? /* @__PURE__ */ jsxs("span", { className: "mt-auto flex w-full min-w-0 items-center gap-1.5", children: [
|
|
130
|
+
visibleParticipants.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
131
|
+
/* @__PURE__ */ jsx(AvatarStack, { size: "xs", max: MAX_VISIBLE_AVATARS, className: "shrink-0 gap-px [&>*:not(:first-child)]:-ml-1", children: visibleParticipants.map((participant) => /* @__PURE__ */ jsx(Avatar, { size: "xs", label: participantLabel(participant) }, participant.userId)) }),
|
|
132
|
+
overflowCount > 0 ? /* @__PURE__ */ jsxs("span", { className: cn("shrink-0 text-xs", tone.subClassName), children: [
|
|
133
|
+
"+",
|
|
134
|
+
overflowCount
|
|
135
|
+
] }) : null
|
|
136
|
+
] }) : null,
|
|
137
|
+
/* @__PURE__ */ jsx("span", { className: "ms-auto flex min-w-0 items-center gap-1.5", children: /* @__PURE__ */ jsx(LocationMeta, { item, subClassName: tone.subClassName, accentColor: item.color }) })
|
|
138
|
+
] }) : null
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
EventBlock.displayName = "EventBlock";
|
|
144
|
+
export {
|
|
145
|
+
EventBlock,
|
|
146
|
+
formatTimeRange,
|
|
147
|
+
resolveEventTone
|
|
148
|
+
};
|
|
149
|
+
//# sourceMappingURL=EventBlock.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/customers/components/calendar/EventBlock.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Globe, MapPin } from 'lucide-react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Avatar, AvatarStack } from '@open-mercato/ui/primitives/avatar'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport type { CalendarItem, CalendarPlatform } from './types'\n\nconst SHOW_TIME_MIN_HEIGHT_PX = 44\nconst SHOW_META_MIN_HEIGHT_PX = 96\nconst WRAP_TITLE_MIN_HEIGHT_PX = 128\nconst MAX_VISIBLE_AVATARS = 3\n\nconst PLATFORM_LABELS: Record<CalendarPlatform, { key: string; fallback: string }> = {\n zoom: { key: 'customers.calendar.platform.zoom', fallback: 'Zoom' },\n meet: { key: 'customers.calendar.platform.meet', fallback: 'Meet' },\n slack: { key: 'customers.calendar.platform.slack', fallback: 'Slack' },\n teams: { key: 'customers.calendar.platform.teams', fallback: 'Teams' },\n}\n\nexport type EventTone = {\n surfaceClassName: string\n titleClassName: string\n subClassName: string\n style?: React.CSSProperties\n}\n\nfunction softTintStyle(color: string): React.CSSProperties {\n if (/^#[0-9a-fA-F]{6}$/.test(color)) return { backgroundColor: `${color}1A` }\n return { backgroundColor: `color-mix(in srgb, ${color} 10%, transparent)` }\n}\n\nexport function resolveEventTone(item: CalendarItem, nowMs: number): EventTone {\n if (item.status === 'canceled') {\n return {\n surfaceClassName: 'bg-muted/60',\n titleClassName: 'text-muted-foreground line-through',\n subClassName: 'text-muted-foreground/70',\n }\n }\n if (item.status === 'done' || item.end.getTime() < nowMs) {\n return {\n surfaceClassName: 'bg-muted',\n titleClassName: 'text-muted-foreground',\n subClassName: 'text-muted-foreground',\n }\n }\n if (item.color) {\n return {\n surfaceClassName: '',\n titleClassName: 'text-foreground',\n subClassName: 'text-muted-foreground',\n style: softTintStyle(item.color),\n }\n }\n return {\n surfaceClassName: 'bg-muted/60',\n titleClassName: 'text-foreground',\n subClassName: 'text-muted-foreground',\n }\n}\n\nexport function formatTimeRange(locale: string, start: Date, end: Date): string {\n const formatter = new Intl.DateTimeFormat(locale, { hour: 'numeric', minute: '2-digit' })\n try {\n return formatter.formatRange(start, end)\n } catch {\n return `${formatter.format(start)} - ${formatter.format(end)}`\n }\n}\n\nfunction participantLabel(participant: CalendarItem['participants'][number]): string {\n return participant.name ?? participant.email ?? '?'\n}\n\ntype LocationMetaProps = {\n item: CalendarItem\n subClassName: string\n accentColor: string | null\n}\n\nfunction LocationMeta({ item, subClassName, accentColor }: LocationMetaProps) {\n const t = useT()\n if (!item.location || !item.locationKind) return null\n const iconStyle = accentColor ? { color: accentColor } : undefined\n if (item.locationKind === 'platform' && item.platform) {\n const platform = PLATFORM_LABELS[item.platform]\n return (\n <span className={cn('truncate text-xs', subClassName)}>\n {t('customers.calendar.grid.onPlatform', 'on {platform}', { platform: t(platform.key, platform.fallback) })}\n </span>\n )\n }\n if (item.locationKind === 'url') {\n return (\n <>\n <Globe className={cn('size-4 shrink-0', !accentColor && subClassName)} style={iconStyle} aria-hidden />\n <span className=\"truncate text-xs text-foreground\">{item.location}</span>\n </>\n )\n }\n return (\n <>\n <MapPin className={cn('size-4 shrink-0', !accentColor && subClassName)} style={iconStyle} aria-hidden />\n <span className=\"truncate text-xs text-foreground\">\n {t('customers.calendar.grid.venue', 'Venue: {name}', { name: item.location })}\n </span>\n </>\n )\n}\n\nexport type EventBlockProps = {\n item: CalendarItem\n top: number\n height: number\n insetInlineStart: string\n width: string\n conflicted: boolean\n highlighted: boolean\n selected?: boolean\n nowMs: number\n} & Omit<React.ComponentProps<typeof Button>, 'style' | 'children'>\n\nexport const EventBlock = React.forwardRef<HTMLButtonElement, EventBlockProps>(function EventBlock(\n {\n item,\n top,\n height,\n insetInlineStart,\n width,\n conflicted,\n highlighted,\n selected,\n nowMs,\n className,\n ...buttonProps\n },\n ref,\n) {\n const t = useT()\n const locale = useLocale()\n const tone = resolveEventTone(item, nowMs)\n const title = item.title || t('customers.calendar.grid.untitled', 'Untitled')\n const timeRange = formatTimeRange(locale, item.start, item.end)\n const showTime = height >= SHOW_TIME_MIN_HEIGHT_PX\n const wrapTitle = height >= WRAP_TITLE_MIN_HEIGHT_PX\n const hasMetaContent = item.participants.length > 0 || (item.location !== null && item.locationKind !== null)\n const showMeta = height >= SHOW_META_MIN_HEIGHT_PX && hasMetaContent\n const visibleParticipants = item.participants.slice(0, MAX_VISIBLE_AVATARS)\n const overflowCount = item.participants.length - visibleParticipants.length\n\n return (\n <Button\n ref={ref}\n type=\"button\"\n variant=\"ghost\"\n aria-label={`${title}, ${timeRange}`}\n className={cn(\n 'pointer-events-auto absolute h-auto flex-col items-start justify-start gap-1 whitespace-normal overflow-hidden rounded-md px-1.5 text-start outline-none hover:bg-muted/70 sm:px-3',\n height >= SHOW_TIME_MIN_HEIGHT_PX ? 'py-1 sm:py-2' : 'py-0.5 sm:py-1',\n tone.surfaceClassName,\n conflicted && 'ring-1 ring-status-warning-icon',\n selected && 'shadow-md ring-2 ring-foreground',\n highlighted && 'motion-safe:animate-pulse',\n conflicted || highlighted || selected ? 'z-30' : 'z-10',\n 'focus-visible:z-30 focus-visible:ring-2 focus-visible:ring-ring',\n className,\n )}\n style={{ top, height, insetInlineStart, width, ...tone.style }}\n {...buttonProps}\n >\n <span className={cn('w-full text-xs font-medium leading-4', wrapTitle ? 'line-clamp-2' : 'truncate', tone.titleClassName)}>\n {title}\n </span>\n {showTime ? (\n <span className={cn('w-full truncate text-overline uppercase tracking-wide', tone.subClassName)}>\n {timeRange}\n </span>\n ) : null}\n {showMeta ? (\n <span className=\"mt-auto flex w-full min-w-0 items-center gap-1.5\">\n {visibleParticipants.length > 0 ? (\n <>\n <AvatarStack size=\"xs\" max={MAX_VISIBLE_AVATARS} className=\"shrink-0 gap-px [&>*:not(:first-child)]:-ml-1\">\n {visibleParticipants.map((participant) => (\n <Avatar key={participant.userId} size=\"xs\" label={participantLabel(participant)} />\n ))}\n </AvatarStack>\n {overflowCount > 0 ? (\n <span className={cn('shrink-0 text-xs', tone.subClassName)}>+{overflowCount}</span>\n ) : null}\n </>\n ) : null}\n <span className=\"ms-auto flex min-w-0 items-center gap-1.5\">\n <LocationMeta item={item} subClassName={tone.subClassName} accentColor={item.color} />\n </span>\n </span>\n ) : null}\n </Button>\n )\n})\n\nEventBlock.displayName = 'EventBlock'\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["EventBlock"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Sparkles } from "lucide-react";
|
|
5
|
+
import { useLocale, useT } from "@open-mercato/shared/lib/i18n/context";
|
|
6
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
7
|
+
import { Popover, PopoverContent, PopoverTrigger } from "@open-mercato/ui/primitives/popover";
|
|
8
|
+
import { formatTimeRange } from "./EventBlock.js";
|
|
9
|
+
const PLATFORM_FULL_LABELS = {
|
|
10
|
+
zoom: { key: "customers.calendar.platformFull.zoom", fallback: "Zoom" },
|
|
11
|
+
meet: { key: "customers.calendar.platformFull.meet", fallback: "Google Meet" },
|
|
12
|
+
slack: { key: "customers.calendar.platformFull.slack", fallback: "Slack" },
|
|
13
|
+
teams: { key: "customers.calendar.platformFull.teams", fallback: "Microsoft Teams" }
|
|
14
|
+
};
|
|
15
|
+
function EventPeekPopover({
|
|
16
|
+
item,
|
|
17
|
+
open,
|
|
18
|
+
joinUrl,
|
|
19
|
+
aiSummaries,
|
|
20
|
+
onOpenChange,
|
|
21
|
+
onJoin,
|
|
22
|
+
onEdit,
|
|
23
|
+
children
|
|
24
|
+
}) {
|
|
25
|
+
const t = useT();
|
|
26
|
+
const locale = useLocale();
|
|
27
|
+
const title = item.title || t("customers.calendar.grid.untitled", "Untitled");
|
|
28
|
+
const dateLabel = React.useMemo(
|
|
29
|
+
() => new Intl.DateTimeFormat(locale, { weekday: "short", month: "short", day: "numeric" }).format(item.start),
|
|
30
|
+
[locale, item.start]
|
|
31
|
+
);
|
|
32
|
+
const timeRange = item.allDay ? t("customers.calendar.grid.allDay", "All day") : formatTimeRange(locale, item.start, item.end);
|
|
33
|
+
const attendeeCount = item.participants.length;
|
|
34
|
+
const attendeesLabel = attendeeCount === 1 ? t("customers.calendar.peek.attendee", "1 attendee") : t("customers.calendar.peek.attendees", "{count} attendees", { count: attendeeCount });
|
|
35
|
+
const platformLabel = item.locationKind === "platform" && item.platform ? t(PLATFORM_FULL_LABELS[item.platform].key, PLATFORM_FULL_LABELS[item.platform].fallback) : null;
|
|
36
|
+
const metaParts = [platformLabel, attendeeCount > 0 ? attendeesLabel : null].filter(
|
|
37
|
+
(part) => Boolean(part)
|
|
38
|
+
);
|
|
39
|
+
const showSummary = aiSummaries && metaParts.length > 0;
|
|
40
|
+
const showJoin = aiSummaries && Boolean(joinUrl);
|
|
41
|
+
return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange, children: [
|
|
42
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children }),
|
|
43
|
+
/* @__PURE__ */ jsx(PopoverContent, { align: "start", side: "right", sideOffset: 8, className: "w-56 p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
44
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold leading-5 text-foreground", children: title }),
|
|
45
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs leading-4 text-muted-foreground", children: `${dateLabel} \xB7 ${timeRange}` }),
|
|
46
|
+
showSummary ? /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1 text-xs leading-4 text-muted-foreground", children: [
|
|
47
|
+
/* @__PURE__ */ jsx(Sparkles, { "aria-hidden": true, className: "size-3.5 shrink-0" }),
|
|
48
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: metaParts.join(" \xB7 ") })
|
|
49
|
+
] }) : null,
|
|
50
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pt-1", children: [
|
|
51
|
+
showJoin ? /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => onJoin(item), children: t("customers.calendar.peek.join", "Join") }) : null,
|
|
52
|
+
/* @__PURE__ */ jsx(
|
|
53
|
+
Button,
|
|
54
|
+
{
|
|
55
|
+
type: "button",
|
|
56
|
+
size: "sm",
|
|
57
|
+
variant: "secondary",
|
|
58
|
+
onClick: () => {
|
|
59
|
+
onOpenChange(false);
|
|
60
|
+
onEdit(item);
|
|
61
|
+
},
|
|
62
|
+
children: t("customers.calendar.peek.edit", "Edit")
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
] })
|
|
66
|
+
] }) })
|
|
67
|
+
] });
|
|
68
|
+
}
|
|
69
|
+
export {
|
|
70
|
+
EventPeekPopover
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=EventPeekPopover.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/customers/components/calendar/EventPeekPopover.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Sparkles } from 'lucide-react'\nimport { useLocale, useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Popover, PopoverContent, PopoverTrigger } from '@open-mercato/ui/primitives/popover'\nimport { formatTimeRange } from './EventBlock'\nimport type { CalendarItem, CalendarPlatform } from './types'\n\nconst PLATFORM_FULL_LABELS: Record<CalendarPlatform, { key: string; fallback: string }> = {\n zoom: { key: 'customers.calendar.platformFull.zoom', fallback: 'Zoom' },\n meet: { key: 'customers.calendar.platformFull.meet', fallback: 'Google Meet' },\n slack: { key: 'customers.calendar.platformFull.slack', fallback: 'Slack' },\n teams: { key: 'customers.calendar.platformFull.teams', fallback: 'Microsoft Teams' },\n}\n\nexport type EventPeekPopoverProps = {\n item: CalendarItem\n open: boolean\n joinUrl: string | null\n aiSummaries: boolean\n onOpenChange(open: boolean): void\n onJoin(item: CalendarItem): void\n onEdit(item: CalendarItem): void\n children: React.ReactNode\n}\n\nexport function EventPeekPopover({\n item,\n open,\n joinUrl,\n aiSummaries,\n onOpenChange,\n onJoin,\n onEdit,\n children,\n}: EventPeekPopoverProps) {\n const t = useT()\n const locale = useLocale()\n const title = item.title || t('customers.calendar.grid.untitled', 'Untitled')\n const dateLabel = React.useMemo(\n () => new Intl.DateTimeFormat(locale, { weekday: 'short', month: 'short', day: 'numeric' }).format(item.start),\n [locale, item.start],\n )\n const timeRange = item.allDay\n ? t('customers.calendar.grid.allDay', 'All day')\n : formatTimeRange(locale, item.start, item.end)\n\n const attendeeCount = item.participants.length\n const attendeesLabel =\n attendeeCount === 1\n ? t('customers.calendar.peek.attendee', '1 attendee')\n : t('customers.calendar.peek.attendees', '{count} attendees', { count: attendeeCount })\n const platformLabel =\n item.locationKind === 'platform' && item.platform\n ? t(PLATFORM_FULL_LABELS[item.platform].key, PLATFORM_FULL_LABELS[item.platform].fallback)\n : null\n const metaParts = [platformLabel, attendeeCount > 0 ? attendeesLabel : null].filter(\n (part): part is string => Boolean(part),\n )\n const showSummary = aiSummaries && metaParts.length > 0\n const showJoin = aiSummaries && Boolean(joinUrl)\n\n return (\n <Popover open={open} onOpenChange={onOpenChange}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent align=\"start\" side=\"right\" sideOffset={8} className=\"w-56 p-3\">\n <div className=\"flex flex-col gap-2\">\n <p className=\"text-sm font-semibold leading-5 text-foreground\">{title}</p>\n <p className=\"text-xs leading-4 text-muted-foreground\">{`${dateLabel} \u00B7 ${timeRange}`}</p>\n {showSummary ? (\n <p className=\"flex items-center gap-1 text-xs leading-4 text-muted-foreground\">\n <Sparkles aria-hidden className=\"size-3.5 shrink-0\" />\n <span className=\"truncate\">{metaParts.join(' \u00B7 ')}</span>\n </p>\n ) : null}\n <div className=\"flex items-center gap-2 pt-1\">\n {showJoin ? (\n <Button type=\"button\" size=\"sm\" onClick={() => onJoin(item)}>\n {t('customers.calendar.peek.join', 'Join')}\n </Button>\n ) : null}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => {\n onOpenChange(false)\n onEdit(item)\n }}\n >\n {t('customers.calendar.peek.edit', 'Edit')}\n </Button>\n </div>\n </div>\n </PopoverContent>\n </Popover>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAkEM,cAMM,YANN;AAhEN,YAAY,WAAW;AACvB,SAAS,gBAAgB;AACzB,SAAS,WAAW,YAAY;AAChC,SAAS,cAAc;AACvB,SAAS,SAAS,gBAAgB,sBAAsB;AACxD,SAAS,uBAAuB;AAGhC,MAAM,uBAAoF;AAAA,EACxF,MAAM,EAAE,KAAK,wCAAwC,UAAU,OAAO;AAAA,EACtE,MAAM,EAAE,KAAK,wCAAwC,UAAU,cAAc;AAAA,EAC7E,OAAO,EAAE,KAAK,yCAAyC,UAAU,QAAQ;AAAA,EACzE,OAAO,EAAE,KAAK,yCAAyC,UAAU,kBAAkB;AACrF;AAaO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,QAAQ,KAAK,SAAS,EAAE,oCAAoC,UAAU;AAC5E,QAAM,YAAY,MAAM;AAAA,IACtB,MAAM,IAAI,KAAK,eAAe,QAAQ,EAAE,SAAS,SAAS,OAAO,SAAS,KAAK,UAAU,CAAC,EAAE,OAAO,KAAK,KAAK;AAAA,IAC7G,CAAC,QAAQ,KAAK,KAAK;AAAA,EACrB;AACA,QAAM,YAAY,KAAK,SACnB,EAAE,kCAAkC,SAAS,IAC7C,gBAAgB,QAAQ,KAAK,OAAO,KAAK,GAAG;AAEhD,QAAM,gBAAgB,KAAK,aAAa;AACxC,QAAM,iBACJ,kBAAkB,IACd,EAAE,oCAAoC,YAAY,IAClD,EAAE,qCAAqC,qBAAqB,EAAE,OAAO,cAAc,CAAC;AAC1F,QAAM,gBACJ,KAAK,iBAAiB,cAAc,KAAK,WACrC,EAAE,qBAAqB,KAAK,QAAQ,EAAE,KAAK,qBAAqB,KAAK,QAAQ,EAAE,QAAQ,IACvF;AACN,QAAM,YAAY,CAAC,eAAe,gBAAgB,IAAI,iBAAiB,IAAI,EAAE;AAAA,IAC3E,CAAC,SAAyB,QAAQ,IAAI;AAAA,EACxC;AACA,QAAM,cAAc,eAAe,UAAU,SAAS;AACtD,QAAM,WAAW,eAAe,QAAQ,OAAO;AAE/C,SACE,qBAAC,WAAQ,MAAY,cACnB;AAAA,wBAAC,kBAAe,SAAO,MAAE,UAAS;AAAA,IAClC,oBAAC,kBAAe,OAAM,SAAQ,MAAK,SAAQ,YAAY,GAAG,WAAU,YAClE,+BAAC,SAAI,WAAU,uBACb;AAAA,0BAAC,OAAE,WAAU,mDAAmD,iBAAM;AAAA,MACtE,oBAAC,OAAE,WAAU,2CAA2C,aAAG,SAAS,SAAM,SAAS,IAAG;AAAA,MACrF,cACC,qBAAC,OAAE,WAAU,mEACX;AAAA,4BAAC,YAAS,eAAW,MAAC,WAAU,qBAAoB;AAAA,QACpD,oBAAC,UAAK,WAAU,YAAY,oBAAU,KAAK,QAAK,GAAE;AAAA,SACpD,IACE;AAAA,MACJ,qBAAC,SAAI,WAAU,gCACZ;AAAA,mBACC,oBAAC,UAAO,MAAK,UAAS,MAAK,MAAK,SAAS,MAAM,OAAO,IAAI,GACvD,YAAE,gCAAgC,MAAM,GAC3C,IACE;AAAA,QACJ;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,SAAS,MAAM;AACb,2BAAa,KAAK;AAClB,qBAAO,IAAI;AAAA,YACb;AAAA,YAEC,YAAE,gCAAgC,MAAM;AAAA;AAAA,QAC3C;AAAA,SACF;AAAA,OACF,GACF;AAAA,KACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { addDays } from "date-fns/addDays";
|
|
5
|
+
import { format } from "date-fns/format";
|
|
6
|
+
import { isSameMonth } from "date-fns/isSameMonth";
|
|
7
|
+
import { isToday } from "date-fns/isToday";
|
|
8
|
+
import { CalendarDays } from "lucide-react";
|
|
9
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
10
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
11
|
+
import { Button } from "@open-mercato/ui/primitives/button";
|
|
12
|
+
import { EmptyState } from "@open-mercato/ui/primitives/empty-state";
|
|
13
|
+
import { getVisibleRange } from "../../lib/calendar/range.js";
|
|
14
|
+
const MAX_PILLS_PER_DAY = 2;
|
|
15
|
+
const SOFT_TINT_ALPHA = "1A";
|
|
16
|
+
function dayKeyOf(date) {
|
|
17
|
+
return format(date, "yyyy-MM-dd");
|
|
18
|
+
}
|
|
19
|
+
function formatTime(date) {
|
|
20
|
+
return date.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
|
|
21
|
+
}
|
|
22
|
+
function fullDateLabel(date) {
|
|
23
|
+
return date.toLocaleDateString(void 0, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
|
|
24
|
+
}
|
|
25
|
+
function isWeekend(date) {
|
|
26
|
+
const weekday = date.getDay();
|
|
27
|
+
return weekday === 0 || weekday === 6;
|
|
28
|
+
}
|
|
29
|
+
function buildWeeks(anchor) {
|
|
30
|
+
const range = getVisibleRange("month", anchor, 0);
|
|
31
|
+
const weeks = [];
|
|
32
|
+
let cursor = range.from;
|
|
33
|
+
while (cursor.getTime() <= range.to.getTime()) {
|
|
34
|
+
const week = [];
|
|
35
|
+
for (let dayIndex = 0; dayIndex < 7; dayIndex += 1) {
|
|
36
|
+
week.push(cursor);
|
|
37
|
+
cursor = addDays(cursor, 1);
|
|
38
|
+
}
|
|
39
|
+
weeks.push(week);
|
|
40
|
+
}
|
|
41
|
+
return weeks;
|
|
42
|
+
}
|
|
43
|
+
function groupItemsByDay(items) {
|
|
44
|
+
const sorted = [...items].sort((first, second) => first.start.getTime() - second.start.getTime());
|
|
45
|
+
const byDay = /* @__PURE__ */ new Map();
|
|
46
|
+
for (const item of sorted) {
|
|
47
|
+
const key = dayKeyOf(item.start);
|
|
48
|
+
const bucket = byDay.get(key);
|
|
49
|
+
if (bucket) bucket.push(item);
|
|
50
|
+
else byDay.set(key, [item]);
|
|
51
|
+
}
|
|
52
|
+
return byDay;
|
|
53
|
+
}
|
|
54
|
+
function MonthPill({ item, onItemClick }) {
|
|
55
|
+
const canceled = item.status === "canceled";
|
|
56
|
+
const timeLabel = item.allDay ? "" : ` \xB7 ${formatTime(item.start)} \u2013 ${formatTime(item.end)}`;
|
|
57
|
+
const tintStyle = item.color ? { backgroundColor: `${item.color}${SOFT_TINT_ALPHA}`, color: item.color } : void 0;
|
|
58
|
+
return /* @__PURE__ */ jsxs(
|
|
59
|
+
Button,
|
|
60
|
+
{
|
|
61
|
+
type: "button",
|
|
62
|
+
variant: "ghost",
|
|
63
|
+
"aria-label": `${item.title}${timeLabel}`,
|
|
64
|
+
onClick: (event) => {
|
|
65
|
+
event.stopPropagation();
|
|
66
|
+
onItemClick(item);
|
|
67
|
+
},
|
|
68
|
+
className: cn(
|
|
69
|
+
"h-4 w-full min-w-0 justify-center gap-0 rounded-full p-0 pr-2",
|
|
70
|
+
!item.color && "bg-muted text-muted-foreground",
|
|
71
|
+
canceled && "opacity-60"
|
|
72
|
+
),
|
|
73
|
+
style: tintStyle,
|
|
74
|
+
children: [
|
|
75
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "flex size-4 shrink-0 items-center justify-center", children: /* @__PURE__ */ jsx(
|
|
76
|
+
"span",
|
|
77
|
+
{
|
|
78
|
+
className: cn("size-1.5 rounded-full", !item.color && "bg-muted-foreground"),
|
|
79
|
+
style: item.color ? { backgroundColor: item.color } : void 0
|
|
80
|
+
}
|
|
81
|
+
) }),
|
|
82
|
+
/* @__PURE__ */ jsx(
|
|
83
|
+
"span",
|
|
84
|
+
{
|
|
85
|
+
className: cn(
|
|
86
|
+
"min-w-0 truncate text-overline font-medium uppercase tracking-wide",
|
|
87
|
+
canceled && "line-through"
|
|
88
|
+
),
|
|
89
|
+
children: item.title
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
function MonthDayCell({
|
|
97
|
+
day,
|
|
98
|
+
anchor,
|
|
99
|
+
items,
|
|
100
|
+
onItemClick,
|
|
101
|
+
onDayOpen
|
|
102
|
+
}) {
|
|
103
|
+
const t = useT();
|
|
104
|
+
const inMonth = isSameMonth(day, anchor);
|
|
105
|
+
const today = isToday(day);
|
|
106
|
+
const visibleItems = items.slice(0, MAX_PILLS_PER_DAY);
|
|
107
|
+
const hiddenCount = items.length - visibleItems.length;
|
|
108
|
+
const dayLabel = fullDateLabel(day);
|
|
109
|
+
return /* @__PURE__ */ jsxs(
|
|
110
|
+
"div",
|
|
111
|
+
{
|
|
112
|
+
className: cn(
|
|
113
|
+
"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",
|
|
114
|
+
isWeekend(day) ? "bg-muted/40" : "bg-background"
|
|
115
|
+
),
|
|
116
|
+
children: [
|
|
117
|
+
/* @__PURE__ */ jsx(
|
|
118
|
+
Button,
|
|
119
|
+
{
|
|
120
|
+
type: "button",
|
|
121
|
+
variant: "ghost",
|
|
122
|
+
"aria-label": dayLabel,
|
|
123
|
+
onClick: () => onDayOpen(day),
|
|
124
|
+
className: "absolute inset-0 z-0 h-full w-full rounded-none p-0 hover:bg-muted/50",
|
|
125
|
+
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: dayLabel })
|
|
126
|
+
}
|
|
127
|
+
),
|
|
128
|
+
today ? /* @__PURE__ */ jsx("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", children: day.getDate() }) : /* @__PURE__ */ jsx("span", { className: cn("pointer-events-none relative z-10 text-xs font-medium", inMonth ? "text-foreground" : "text-muted-foreground"), children: day.getDate() }),
|
|
129
|
+
/* @__PURE__ */ jsxs("span", { className: "relative z-20 hidden w-full flex-col gap-1 sm:flex", children: [
|
|
130
|
+
visibleItems.map((item) => /* @__PURE__ */ jsx(MonthPill, { item, onItemClick }, item.id)),
|
|
131
|
+
hiddenCount > 0 ? /* @__PURE__ */ jsx(
|
|
132
|
+
Button,
|
|
133
|
+
{
|
|
134
|
+
type: "button",
|
|
135
|
+
variant: "ghost",
|
|
136
|
+
size: "sm",
|
|
137
|
+
className: "h-auto self-start p-0 text-overline font-medium text-muted-foreground hover:bg-transparent hover:underline",
|
|
138
|
+
onClick: (event) => {
|
|
139
|
+
event.stopPropagation();
|
|
140
|
+
onDayOpen(day);
|
|
141
|
+
},
|
|
142
|
+
children: t("customers.calendar.grid.more", "+{count} more", { count: hiddenCount })
|
|
143
|
+
}
|
|
144
|
+
) : null
|
|
145
|
+
] }),
|
|
146
|
+
items.length > 0 ? /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "pointer-events-none relative z-10 flex w-full flex-wrap items-center gap-0.5 sm:hidden", children: [
|
|
147
|
+
items.slice(0, 4).map((item) => /* @__PURE__ */ jsx(
|
|
148
|
+
"span",
|
|
149
|
+
{
|
|
150
|
+
className: cn("size-1.5 rounded-full", !item.color && "bg-muted-foreground"),
|
|
151
|
+
style: item.color ? { backgroundColor: item.color } : void 0
|
|
152
|
+
},
|
|
153
|
+
item.id
|
|
154
|
+
)),
|
|
155
|
+
items.length > 4 ? /* @__PURE__ */ jsxs("span", { className: "text-overline font-medium leading-none text-muted-foreground", children: [
|
|
156
|
+
"+",
|
|
157
|
+
items.length - 4
|
|
158
|
+
] }) : null
|
|
159
|
+
] }) : null
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
function MonthGrid({ anchor, items, onItemClick, onDayOpen }) {
|
|
165
|
+
const t = useT();
|
|
166
|
+
const weeks = React.useMemo(() => buildWeeks(anchor), [anchor]);
|
|
167
|
+
const itemsByDay = React.useMemo(() => groupItemsByDay(items), [items]);
|
|
168
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden border border-border bg-background", children: [
|
|
169
|
+
/* @__PURE__ */ jsx("div", { className: "flex h-9 w-full shrink-0 border-b border-border", children: weeks[0]?.map((day) => {
|
|
170
|
+
const label = day.toLocaleDateString(void 0, { weekday: "short" }).toUpperCase();
|
|
171
|
+
return /* @__PURE__ */ jsx(
|
|
172
|
+
"div",
|
|
173
|
+
{
|
|
174
|
+
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",
|
|
175
|
+
children: /* @__PURE__ */ jsxs("span", { className: "truncate text-overline font-medium uppercase tracking-widest text-muted-foreground", children: [
|
|
176
|
+
/* @__PURE__ */ jsx("span", { className: "sm:hidden", children: label.charAt(0) }),
|
|
177
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: label })
|
|
178
|
+
] })
|
|
179
|
+
},
|
|
180
|
+
dayKeyOf(day)
|
|
181
|
+
);
|
|
182
|
+
}) }),
|
|
183
|
+
weeks.map((week) => /* @__PURE__ */ jsx(
|
|
184
|
+
"div",
|
|
185
|
+
{
|
|
186
|
+
className: "flex w-full flex-1 border-b border-border last:border-b-0 min-h-14 sm:min-h-[86px]",
|
|
187
|
+
children: week.map((day) => /* @__PURE__ */ jsx(
|
|
188
|
+
MonthDayCell,
|
|
189
|
+
{
|
|
190
|
+
day,
|
|
191
|
+
anchor,
|
|
192
|
+
items: itemsByDay.get(dayKeyOf(day)) ?? [],
|
|
193
|
+
onItemClick,
|
|
194
|
+
onDayOpen
|
|
195
|
+
},
|
|
196
|
+
dayKeyOf(day)
|
|
197
|
+
))
|
|
198
|
+
},
|
|
199
|
+
dayKeyOf(week[0])
|
|
200
|
+
)),
|
|
201
|
+
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(
|
|
202
|
+
EmptyState,
|
|
203
|
+
{
|
|
204
|
+
icon: /* @__PURE__ */ jsx(CalendarDays, { className: "h-6 w-6", "aria-hidden": "true" }),
|
|
205
|
+
title: t("customers.calendar.empty.month", "Nothing scheduled this month"),
|
|
206
|
+
className: "bg-background/90"
|
|
207
|
+
}
|
|
208
|
+
) }) : null
|
|
209
|
+
] });
|
|
210
|
+
}
|
|
211
|
+
export {
|
|
212
|
+
MonthGrid
|
|
213
|
+
};
|
|
214
|
+
//# sourceMappingURL=MonthGrid.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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 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 canceled = item.status === 'canceled'\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={`${item.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 {item.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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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import {
|
|
4
|
+
Dialog,
|
|
5
|
+
DialogContent,
|
|
6
|
+
DialogDescription,
|
|
7
|
+
DialogHeader,
|
|
8
|
+
DialogTitle
|
|
9
|
+
} from "@open-mercato/ui/primitives/dialog";
|
|
10
|
+
import { Kbd } from "@open-mercato/ui/primitives/kbd";
|
|
11
|
+
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
12
|
+
import { CALENDAR_SHORTCUTS } from "./CalendarFooter.js";
|
|
13
|
+
function ShortcutsDialog({ open, onOpenChange }) {
|
|
14
|
+
const t = useT();
|
|
15
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
16
|
+
DialogContent,
|
|
17
|
+
{
|
|
18
|
+
size: "sm",
|
|
19
|
+
onKeyDown: (event) => {
|
|
20
|
+
if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
onOpenChange(false);
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
children: [
|
|
26
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
27
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: t("customers.calendar.shortcuts.title", "Keyboard shortcuts") }),
|
|
28
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: t(
|
|
29
|
+
"customers.calendar.shortcuts.description",
|
|
30
|
+
"Navigate the calendar faster with these keys."
|
|
31
|
+
) })
|
|
32
|
+
] }),
|
|
33
|
+
/* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: CALENDAR_SHORTCUTS.map((shortcut) => /* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between gap-3", children: [
|
|
34
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: t(shortcut.labelKey, shortcut.fallback) }),
|
|
35
|
+
/* @__PURE__ */ jsx(Kbd, { children: shortcut.key })
|
|
36
|
+
] }, shortcut.key)) })
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
) });
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
ShortcutsDialog
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=ShortcutsDialog.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/customers/components/calendar/ShortcutsDialog.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n} from '@open-mercato/ui/primitives/dialog'\nimport { Kbd } from '@open-mercato/ui/primitives/kbd'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { CALENDAR_SHORTCUTS } from './CalendarFooter'\n\nexport type ShortcutsDialogProps = {\n open: boolean\n onOpenChange(open: boolean): void\n}\n\nexport function ShortcutsDialog({ open, onOpenChange }: ShortcutsDialogProps) {\n const t = useT()\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n size=\"sm\"\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n onOpenChange(false)\n }\n }}\n >\n <DialogHeader>\n <DialogTitle>\n {t('customers.calendar.shortcuts.title', 'Keyboard shortcuts')}\n </DialogTitle>\n <DialogDescription>\n {t(\n 'customers.calendar.shortcuts.description',\n 'Navigate the calendar faster with these keys.',\n )}\n </DialogDescription>\n </DialogHeader>\n <ul className=\"flex flex-col gap-2\">\n {CALENDAR_SHORTCUTS.map((shortcut) => (\n <li key={shortcut.key} className=\"flex items-center justify-between gap-3\">\n <span className=\"text-sm text-muted-foreground\">\n {t(shortcut.labelKey, shortcut.fallback)}\n </span>\n <Kbd>{shortcut.key}</Kbd>\n </li>\n ))}\n </ul>\n </DialogContent>\n </Dialog>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAgCQ,SACE,KADF;AA7BR;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW;AACpB,SAAS,YAAY;AACrB,SAAS,0BAA0B;AAO5B,SAAS,gBAAgB,EAAE,MAAM,aAAa,GAAyB;AAC5E,QAAM,IAAI,KAAK;AACf,SACE,oBAAC,UAAO,MAAY,cAClB;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW,CAAC,UAAU;AACpB,YAAI,MAAM,QAAQ,YAAY,MAAM,WAAW,MAAM,UAAU;AAC7D,gBAAM,eAAe;AACrB,uBAAa,KAAK;AAAA,QACpB;AAAA,MACF;AAAA,MAEA;AAAA,6BAAC,gBACC;AAAA,8BAAC,eACE,YAAE,sCAAsC,oBAAoB,GAC/D;AAAA,UACA,oBAAC,qBACE;AAAA,YACC;AAAA,YACA;AAAA,UACF,GACF;AAAA,WACF;AAAA,QACA,oBAAC,QAAG,WAAU,uBACX,6BAAmB,IAAI,CAAC,aACvB,qBAAC,QAAsB,WAAU,2CAC/B;AAAA,8BAAC,UAAK,WAAU,iCACb,YAAE,SAAS,UAAU,SAAS,QAAQ,GACzC;AAAA,UACA,oBAAC,OAAK,mBAAS,KAAI;AAAA,aAJZ,SAAS,GAKlB,CACD,GACH;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|