@open-mercato/core 0.10.1-develop.7954.1.48da4a7d13 → 0.10.1-develop.7972.1.03f813eaaf

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 (88) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/auth/api/logout.js +3 -3
  3. package/dist/modules/auth/api/logout.js.map +2 -2
  4. package/dist/modules/auth/commands/roles.js +42 -31
  5. package/dist/modules/auth/commands/roles.js.map +2 -2
  6. package/dist/modules/communication_channels/setup.js +49 -45
  7. package/dist/modules/communication_channels/setup.js.map +2 -2
  8. package/dist/modules/customer_accounts/services/domainMappingService.js +55 -29
  9. package/dist/modules/customer_accounts/services/domainMappingService.js.map +2 -2
  10. package/dist/modules/customers/components/detail/ActivitiesSection.js +8 -3
  11. package/dist/modules/customers/components/detail/ActivitiesSection.js.map +2 -2
  12. package/dist/modules/customers/components/detail/ActivityCard.js +3 -3
  13. package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
  14. package/dist/modules/customers/components/detail/ActivityHistorySection.js +19 -7
  15. package/dist/modules/customers/components/detail/ActivityHistorySection.js.map +2 -2
  16. package/dist/modules/customers/components/detail/ActivityTimeline.js +5 -5
  17. package/dist/modules/customers/components/detail/ActivityTimeline.js.map +2 -2
  18. package/dist/modules/directory/subscribers/seedOrganizationDefaults.js +67 -0
  19. package/dist/modules/directory/subscribers/seedOrganizationDefaults.js.map +7 -0
  20. package/dist/modules/ecommerce/api/storefront/categories/[slug]/route.js +1 -1
  21. package/dist/modules/ecommerce/api/storefront/categories/[slug]/route.js.map +2 -2
  22. package/dist/modules/ecommerce/api/storefront/categories/route.js +1 -1
  23. package/dist/modules/ecommerce/api/storefront/categories/route.js.map +2 -2
  24. package/dist/modules/ecommerce/api/storefront/context/route.js +1 -1
  25. package/dist/modules/ecommerce/api/storefront/context/route.js.map +2 -2
  26. package/dist/modules/ecommerce/api/storefront/products/[idOrHandle]/route.js +1 -1
  27. package/dist/modules/ecommerce/api/storefront/products/[idOrHandle]/route.js.map +2 -2
  28. package/dist/modules/ecommerce/api/storefront/products/route.js +1 -1
  29. package/dist/modules/ecommerce/api/storefront/products/route.js.map +2 -2
  30. package/dist/modules/ecommerce/api/storefront/search/suggest/route.js +1 -1
  31. package/dist/modules/ecommerce/api/storefront/search/suggest/route.js.map +2 -2
  32. package/dist/modules/ecommerce/lib/cacheInvalidation.js +3 -0
  33. package/dist/modules/ecommerce/lib/cacheInvalidation.js.map +2 -2
  34. package/dist/modules/ecommerce/lib/cacheKeys.js +4 -0
  35. package/dist/modules/ecommerce/lib/cacheKeys.js.map +2 -2
  36. package/dist/modules/ecommerce/lib/storeContext.js +36 -12
  37. package/dist/modules/ecommerce/lib/storeContext.js.map +2 -2
  38. package/dist/modules/ecommerce/subscribers/sales-channel-cache-invalidation.js +14 -0
  39. package/dist/modules/ecommerce/subscribers/sales-channel-cache-invalidation.js.map +7 -0
  40. package/dist/modules/integrations/setup.js +34 -24
  41. package/dist/modules/integrations/setup.js.map +2 -2
  42. package/dist/modules/messages/components/MessagesInboxPageClient.js +1 -1
  43. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  44. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js +3 -3
  45. package/dist/modules/messages/components/message-detail/panels/MainMessageHeader.js.map +2 -2
  46. package/dist/modules/messages/components/message-detail/panels/body-panel.js +2 -2
  47. package/dist/modules/messages/components/message-detail/panels/body-panel.js.map +2 -2
  48. package/dist/modules/payment_gateways/setup.js +3 -0
  49. package/dist/modules/payment_gateways/setup.js.map +2 -2
  50. package/dist/modules/warranty_claims/backend/warranty_claims/[id]/page.js +30 -11
  51. package/dist/modules/warranty_claims/backend/warranty_claims/[id]/page.js.map +3 -3
  52. package/dist/modules/warranty_claims/setup.js +34 -30
  53. package/dist/modules/warranty_claims/setup.js.map +2 -2
  54. package/dist/modules/workflows/setup.js +7 -0
  55. package/dist/modules/workflows/setup.js.map +2 -2
  56. package/package.json +7 -7
  57. package/src/modules/auth/api/logout.ts +3 -3
  58. package/src/modules/auth/commands/roles.ts +43 -32
  59. package/src/modules/communication_channels/setup.ts +59 -53
  60. package/src/modules/customer_accounts/services/domainMappingService.ts +57 -29
  61. package/src/modules/customers/components/detail/ActivitiesSection.tsx +8 -3
  62. package/src/modules/customers/components/detail/ActivityCard.tsx +3 -3
  63. package/src/modules/customers/components/detail/ActivityHistorySection.tsx +20 -8
  64. package/src/modules/customers/components/detail/ActivityTimeline.tsx +7 -7
  65. package/src/modules/customers/i18n/de.json +1 -0
  66. package/src/modules/customers/i18n/en.json +1 -0
  67. package/src/modules/customers/i18n/es.json +1 -0
  68. package/src/modules/customers/i18n/ko.json +1 -0
  69. package/src/modules/customers/i18n/pl.json +1 -0
  70. package/src/modules/directory/subscribers/seedOrganizationDefaults.ts +84 -0
  71. package/src/modules/ecommerce/api/storefront/categories/[slug]/route.ts +1 -1
  72. package/src/modules/ecommerce/api/storefront/categories/route.ts +1 -1
  73. package/src/modules/ecommerce/api/storefront/context/route.ts +1 -1
  74. package/src/modules/ecommerce/api/storefront/products/[idOrHandle]/route.ts +1 -1
  75. package/src/modules/ecommerce/api/storefront/products/route.ts +1 -1
  76. package/src/modules/ecommerce/api/storefront/search/suggest/route.ts +1 -1
  77. package/src/modules/ecommerce/lib/cacheInvalidation.ts +4 -0
  78. package/src/modules/ecommerce/lib/cacheKeys.ts +4 -0
  79. package/src/modules/ecommerce/lib/storeContext.ts +56 -10
  80. package/src/modules/ecommerce/subscribers/sales-channel-cache-invalidation.ts +12 -0
  81. package/src/modules/integrations/setup.ts +41 -24
  82. package/src/modules/messages/components/MessagesInboxPageClient.tsx +1 -1
  83. package/src/modules/messages/components/message-detail/panels/MainMessageHeader.tsx +3 -3
  84. package/src/modules/messages/components/message-detail/panels/body-panel.tsx +2 -2
  85. package/src/modules/payment_gateways/setup.ts +4 -0
  86. package/src/modules/warranty_claims/backend/warranty_claims/[id]/page.tsx +55 -28
  87. package/src/modules/warranty_claims/setup.ts +40 -30
  88. package/src/modules/workflows/setup.ts +8 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/messages/components/message-detail/panels/MainMessageHeader.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { FormHeader, type ActionItem } from '@open-mercato/ui/backend/forms'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Archive, ArchiveRestore, Forward, MailMinus, MailOpen, Reply, Trash2 } from 'lucide-react'\nimport { PriorityBadge } from '../../utils/PriorityBadge'\n\ntype MainMessageHeaderProps = {\n subject: string\n priority: 'low' | 'normal' | 'high' | 'urgent'\n canReply: boolean\n canForwardAll: boolean\n conversationArchived: boolean\n conversationAllUnread: boolean\n actionsDisabled?: boolean\n activeActionId?:\n | 'forwardAll'\n | 'archiveConversation'\n | 'unarchiveConversation'\n | 'markAllUnread'\n | 'markAllRead'\n | 'deleteConversation'\n | null\n onReply: () => void\n onForwardAll: () => void\n onToggleArchiveConversation: () => void\n onToggleReadConversation: () => void\n onDeleteConversation: () => void\n}\n\nexport function MainMessageHeader(props: MainMessageHeaderProps) {\n const t = useT()\n\n const menuActions = React.useMemo<ActionItem[]>(() => [\n {\n id: 'reply',\n label: t('messages.reply', 'Reply'),\n icon: Reply,\n onSelect: props.onReply,\n disabled: props.actionsDisabled || !props.canReply,\n },\n {\n id: 'forward-all',\n label: t('messages.actions.forwardAll', 'Forward all'),\n icon: Forward,\n onSelect: props.onForwardAll,\n disabled: props.actionsDisabled || !props.canForwardAll,\n loading: props.activeActionId === 'forwardAll',\n },\n {\n id: 'archive-conversation',\n label: props.conversationArchived\n ? t('messages.actions.unarchiveConversation', 'Unarchive conversation')\n : t('messages.actions.archiveConversation', 'Archive conversation'),\n icon: props.conversationArchived ? ArchiveRestore : Archive,\n onSelect: props.onToggleArchiveConversation,\n disabled: props.actionsDisabled,\n loading: props.activeActionId === 'archiveConversation' || props.activeActionId === 'unarchiveConversation',\n },\n {\n id: 'mark-all-unread',\n label: props.conversationAllUnread\n ? t('messages.actions.markAllRead', 'Mark all read')\n : t('messages.actions.markAllUnread', 'Mark all unread'),\n icon: props.conversationAllUnread ? MailOpen : MailMinus,\n onSelect: props.onToggleReadConversation,\n disabled: props.actionsDisabled,\n loading: props.activeActionId === 'markAllUnread' || props.activeActionId === 'markAllRead',\n },\n {\n id: 'delete-conversation',\n label: t('messages.actions.deleteConversation', 'Delete conversation'),\n icon: Trash2,\n onSelect: props.onDeleteConversation,\n disabled: props.actionsDisabled,\n loading: props.activeActionId === 'deleteConversation',\n },\n ], [\n props.actionsDisabled,\n props.canForwardAll,\n props.canReply,\n props.conversationArchived,\n props.conversationAllUnread,\n props.onToggleArchiveConversation,\n props.onDeleteConversation,\n props.onForwardAll,\n props.onToggleReadConversation,\n props.onReply,\n props.activeActionId,\n t,\n ])\n\n return (\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/messages\"\n backLabel={t('messages.actions.backToList', 'Back to messages')}\n title={(\n <h1 className=\"inline-flex items-center gap-2\">\n <span className=\"truncate\">{props.subject}</span>\n <PriorityBadge priority={props.priority} />\n </h1>\n )}\n utilityActions={props.canReply ? (\n <IconButton\n type=\"button\"\n variant=\"outline\"\n size=\"default\"\n aria-label={t('messages.reply', 'Reply')}\n onClick={props.onReply}\n disabled={props.actionsDisabled || !props.canReply}\n >\n <Reply className=\"h-4 w-4\" aria-hidden />\n </IconButton>\n ) : undefined}\n menuTriggerMode=\"icon\"\n menuAriaLabel={t('messages.actions.conversationActions', 'Conversation actions')}\n menuActions={menuActions}\n />\n )\n}\n"],
5
- "mappings": ";AAoGQ,SACE,KADF;AAlGR,YAAY,WAAW;AACvB,SAAS,YAAY;AACrB,SAAS,kBAAmC;AAC5C,SAAS,kBAAkB;AAC3B,SAAS,SAAS,gBAAgB,SAAS,WAAW,UAAU,OAAO,cAAc;AACrF,SAAS,qBAAqB;AAyBvB,SAAS,kBAAkB,OAA+B;AAC/D,QAAM,IAAI,KAAK;AAEf,QAAM,cAAc,MAAM,QAAsB,MAAM;AAAA,IACpD;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,kBAAkB,OAAO;AAAA,MAClC,MAAM;AAAA,MACN,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM,mBAAmB,CAAC,MAAM;AAAA,IAC5C;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,+BAA+B,aAAa;AAAA,MACrD,MAAM;AAAA,MACN,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM,mBAAmB,CAAC,MAAM;AAAA,MAC1C,SAAS,MAAM,mBAAmB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,MAAM,uBACT,EAAE,0CAA0C,wBAAwB,IACpE,EAAE,wCAAwC,sBAAsB;AAAA,MACpE,MAAM,MAAM,uBAAuB,iBAAiB;AAAA,MACpD,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM,mBAAmB,yBAAyB,MAAM,mBAAmB;AAAA,IACtF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,MAAM,wBACT,EAAE,gCAAgC,eAAe,IACjD,EAAE,kCAAkC,iBAAiB;AAAA,MACzD,MAAM,MAAM,wBAAwB,WAAW;AAAA,MAC/C,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM,mBAAmB,mBAAmB,MAAM,mBAAmB;AAAA,IAChF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,uCAAuC,qBAAqB;AAAA,MACrE,MAAM;AAAA,MACN,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM,mBAAmB;AAAA,IACpC;AAAA,EACF,GAAG;AAAA,IACD,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,UAAS;AAAA,MACT,WAAW,EAAE,+BAA+B,kBAAkB;AAAA,MAC9D,OACE,qBAAC,QAAG,WAAU,kCACZ;AAAA,4BAAC,UAAK,WAAU,YAAY,gBAAM,SAAQ;AAAA,QAC1C,oBAAC,iBAAc,UAAU,MAAM,UAAU;AAAA,SAC3C;AAAA,MAEF,gBAAgB,MAAM,WACpB;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,cAAY,EAAE,kBAAkB,OAAO;AAAA,UACvC,SAAS,MAAM;AAAA,UACf,UAAU,MAAM,mBAAmB,CAAC,MAAM;AAAA,UAE1C,8BAAC,SAAM,WAAU,WAAU,eAAW,MAAC;AAAA;AAAA,MACzC,IACE;AAAA,MACJ,iBAAgB;AAAA,MAChB,eAAe,EAAE,wCAAwC,sBAAsB;AAAA,MAC/E;AAAA;AAAA,EACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { FormHeader, type ActionItem } from '@open-mercato/ui/backend/forms'\nimport { IconButton } from '@open-mercato/ui/primitives/icon-button'\nimport { Archive, ArchiveRestore, Forward, MailMinus, MailOpen, Reply, Trash2 } from 'lucide-react'\nimport { PriorityBadge } from '../../utils/PriorityBadge'\n\ntype MainMessageHeaderProps = {\n subject: string\n priority: 'low' | 'normal' | 'high' | 'urgent'\n canReply: boolean\n canForwardAll: boolean\n conversationArchived: boolean\n conversationAllUnread: boolean\n actionsDisabled?: boolean\n activeActionId?:\n | 'forwardAll'\n | 'archiveConversation'\n | 'unarchiveConversation'\n | 'markAllUnread'\n | 'markAllRead'\n | 'deleteConversation'\n | null\n onReply: () => void\n onForwardAll: () => void\n onToggleArchiveConversation: () => void\n onToggleReadConversation: () => void\n onDeleteConversation: () => void\n}\n\nexport function MainMessageHeader(props: MainMessageHeaderProps) {\n const t = useT()\n\n const menuActions = React.useMemo<ActionItem[]>(() => [\n {\n id: 'reply',\n label: t('messages.reply', 'Reply'),\n icon: Reply,\n onSelect: props.onReply,\n disabled: props.actionsDisabled || !props.canReply,\n },\n {\n id: 'forward-all',\n label: t('messages.actions.forwardAll', 'Forward all'),\n icon: Forward,\n onSelect: props.onForwardAll,\n disabled: props.actionsDisabled || !props.canForwardAll,\n loading: props.activeActionId === 'forwardAll',\n },\n {\n id: 'archive-conversation',\n label: props.conversationArchived\n ? t('messages.actions.unarchiveConversation', 'Unarchive conversation')\n : t('messages.actions.archiveConversation', 'Archive conversation'),\n icon: props.conversationArchived ? ArchiveRestore : Archive,\n onSelect: props.onToggleArchiveConversation,\n disabled: props.actionsDisabled,\n loading: props.activeActionId === 'archiveConversation' || props.activeActionId === 'unarchiveConversation',\n },\n {\n id: 'mark-all-unread',\n label: props.conversationAllUnread\n ? t('messages.actions.markAllRead', 'Mark all read')\n : t('messages.actions.markAllUnread', 'Mark all unread'),\n icon: props.conversationAllUnread ? MailOpen : MailMinus,\n onSelect: props.onToggleReadConversation,\n disabled: props.actionsDisabled,\n loading: props.activeActionId === 'markAllUnread' || props.activeActionId === 'markAllRead',\n },\n {\n id: 'delete-conversation',\n label: t('messages.actions.deleteConversation', 'Delete conversation'),\n icon: Trash2,\n onSelect: props.onDeleteConversation,\n disabled: props.actionsDisabled,\n loading: props.activeActionId === 'deleteConversation',\n },\n ], [\n props.actionsDisabled,\n props.canForwardAll,\n props.canReply,\n props.conversationArchived,\n props.conversationAllUnread,\n props.onToggleArchiveConversation,\n props.onDeleteConversation,\n props.onForwardAll,\n props.onToggleReadConversation,\n props.onReply,\n props.activeActionId,\n t,\n ])\n\n return (\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/messages\"\n backLabel={t('messages.actions.backToList', 'Back to messages')}\n title={(\n <h1 className=\"flex min-w-0 max-w-full flex-wrap items-center gap-2\">\n <span className=\"min-w-0 break-words\" title={props.subject}>{props.subject}</span>\n <PriorityBadge priority={props.priority} className=\"shrink-0\" />\n </h1>\n )}\n utilityActions={props.canReply ? (\n <IconButton\n type=\"button\"\n variant=\"outline\"\n size=\"default\"\n aria-label={t('messages.reply', 'Reply')}\n onClick={props.onReply}\n disabled={props.actionsDisabled || !props.canReply}\n >\n <Reply className=\"h-4 w-4\" aria-hidden />\n </IconButton>\n ) : undefined}\n menuTriggerMode=\"icon\"\n menuAriaLabel={t('messages.actions.conversationActions', 'Conversation actions')}\n menuActions={menuActions}\n />\n )\n}\n"],
5
+ "mappings": ";AAoGQ,SACE,KADF;AAlGR,YAAY,WAAW;AACvB,SAAS,YAAY;AACrB,SAAS,kBAAmC;AAC5C,SAAS,kBAAkB;AAC3B,SAAS,SAAS,gBAAgB,SAAS,WAAW,UAAU,OAAO,cAAc;AACrF,SAAS,qBAAqB;AAyBvB,SAAS,kBAAkB,OAA+B;AAC/D,QAAM,IAAI,KAAK;AAEf,QAAM,cAAc,MAAM,QAAsB,MAAM;AAAA,IACpD;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,kBAAkB,OAAO;AAAA,MAClC,MAAM;AAAA,MACN,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM,mBAAmB,CAAC,MAAM;AAAA,IAC5C;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,+BAA+B,aAAa;AAAA,MACrD,MAAM;AAAA,MACN,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM,mBAAmB,CAAC,MAAM;AAAA,MAC1C,SAAS,MAAM,mBAAmB;AAAA,IACpC;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,MAAM,uBACT,EAAE,0CAA0C,wBAAwB,IACpE,EAAE,wCAAwC,sBAAsB;AAAA,MACpE,MAAM,MAAM,uBAAuB,iBAAiB;AAAA,MACpD,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM,mBAAmB,yBAAyB,MAAM,mBAAmB;AAAA,IACtF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,MAAM,wBACT,EAAE,gCAAgC,eAAe,IACjD,EAAE,kCAAkC,iBAAiB;AAAA,MACzD,MAAM,MAAM,wBAAwB,WAAW;AAAA,MAC/C,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM,mBAAmB,mBAAmB,MAAM,mBAAmB;AAAA,IAChF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO,EAAE,uCAAuC,qBAAqB;AAAA,MACrE,MAAM;AAAA,MACN,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM,mBAAmB;AAAA,IACpC;AAAA,EACF,GAAG;AAAA,IACD,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,UAAS;AAAA,MACT,WAAW,EAAE,+BAA+B,kBAAkB;AAAA,MAC9D,OACE,qBAAC,QAAG,WAAU,wDACZ;AAAA,4BAAC,UAAK,WAAU,uBAAsB,OAAO,MAAM,SAAU,gBAAM,SAAQ;AAAA,QAC3E,oBAAC,iBAAc,UAAU,MAAM,UAAU,WAAU,YAAW;AAAA,SAChE;AAAA,MAEF,gBAAgB,MAAM,WACpB;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,cAAY,EAAE,kBAAkB,OAAO;AAAA,UACvC,SAAS,MAAM;AAAA,UACf,UAAU,MAAM,mBAAmB,CAAC,MAAM;AAAA,UAE1C,8BAAC,SAAM,WAAU,WAAU,eAAW,MAAC;AAAA;AAAA,MACzC,IACE;AAAA,MACJ,iBAAgB;AAAA,MAChB,eAAe,EAAE,wCAAwC,sBAAsB;AAAA,MAC/E;AAAA;AAAA,EACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -3,9 +3,9 @@ import { jsx } from "react/jsx-runtime";
3
3
  import { MarkdownContent } from "@open-mercato/ui/backend/markdown/MarkdownContent";
4
4
  function MessageDetailBodySection(props) {
5
5
  if (props.ContentComponent) {
6
- return /* @__PURE__ */ jsx("div", { className: "rounded border bg-muted/30 p-3", children: /* @__PURE__ */ jsx(props.ContentComponent, { ...props.contentProps }) });
6
+ return /* @__PURE__ */ jsx("div", { className: "min-w-0 max-w-full overflow-x-auto rounded border bg-muted/30 p-3 break-words", children: /* @__PURE__ */ jsx(props.ContentComponent, { ...props.contentProps }) });
7
7
  }
8
- return /* @__PURE__ */ jsx("div", { className: "rounded border bg-muted/30 p-3 text-sm whitespace-pre-wrap", children: /* @__PURE__ */ jsx(
8
+ return /* @__PURE__ */ jsx("div", { className: "min-w-0 max-w-full overflow-x-auto rounded border bg-muted/30 p-3 text-sm whitespace-pre-wrap break-words", children: /* @__PURE__ */ jsx(
9
9
  MarkdownContent,
10
10
  {
11
11
  body: props.detail.body,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/messages/components/message-detail/panels/body-panel.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { MessageContentProps } from '@open-mercato/shared/modules/messages/types'\nimport { MarkdownContent } from '@open-mercato/ui/backend/markdown/MarkdownContent'\nimport type { MessageDetail } from '../types'\n\ntype BodyPanelProps = {\n detail: MessageDetail\n contentProps: MessageContentProps\n ContentComponent: React.ComponentType<MessageContentProps> | null\n}\n\nexport function MessageDetailBodySection(props: BodyPanelProps) {\n if (props.ContentComponent) {\n return (\n <div className=\"rounded border bg-muted/30 p-3\">\n <props.ContentComponent {...props.contentProps} />\n </div>\n )\n }\n\n return (\n <div className=\"rounded border bg-muted/30 p-3 text-sm whitespace-pre-wrap\">\n <MarkdownContent\n body={props.detail.body}\n format={props.detail.bodyFormat}\n className=\"text-sm whitespace-pre-wrap [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs\"\n />\n </div>\n )\n}\n"],
5
- "mappings": ";AAiBQ;AAbR,SAAS,uBAAuB;AASzB,SAAS,yBAAyB,OAAuB;AAC9D,MAAI,MAAM,kBAAkB;AAC1B,WACE,oBAAC,SAAI,WAAU,kCACb,8BAAC,MAAM,kBAAN,EAAwB,GAAG,MAAM,cAAc,GAClD;AAAA,EAEJ;AAEA,SACE,oBAAC,SAAI,WAAU,8DACb;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,MAAM,OAAO;AAAA,MACnB,QAAQ,MAAM,OAAO;AAAA,MACrB,WAAU;AAAA;AAAA,EACZ,GACF;AAEJ;",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { MessageContentProps } from '@open-mercato/shared/modules/messages/types'\nimport { MarkdownContent } from '@open-mercato/ui/backend/markdown/MarkdownContent'\nimport type { MessageDetail } from '../types'\n\ntype BodyPanelProps = {\n detail: MessageDetail\n contentProps: MessageContentProps\n ContentComponent: React.ComponentType<MessageContentProps> | null\n}\n\nexport function MessageDetailBodySection(props: BodyPanelProps) {\n if (props.ContentComponent) {\n return (\n <div className=\"min-w-0 max-w-full overflow-x-auto rounded border bg-muted/30 p-3 break-words\">\n <props.ContentComponent {...props.contentProps} />\n </div>\n )\n }\n\n return (\n <div className=\"min-w-0 max-w-full overflow-x-auto rounded border bg-muted/30 p-3 text-sm whitespace-pre-wrap break-words\">\n <MarkdownContent\n body={props.detail.body}\n format={props.detail.bodyFormat}\n className=\"text-sm whitespace-pre-wrap [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs\"\n />\n </div>\n )\n}\n"],
5
+ "mappings": ";AAiBQ;AAbR,SAAS,uBAAuB;AASzB,SAAS,yBAAyB,OAAuB;AAC9D,MAAI,MAAM,kBAAkB;AAC1B,WACE,oBAAC,SAAI,WAAU,iFACb,8BAAC,MAAM,kBAAN,EAAwB,GAAG,MAAM,cAAc,GAClD;AAAA,EAEJ;AAEA,SACE,oBAAC,SAAI,WAAU,6GACb;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,MAAM,OAAO;AAAA,MACnB,QAAQ,MAAM,OAAO;AAAA,MACrB,WAAU;AAAA;AAAA,EACZ,GACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -49,6 +49,9 @@ const setup = {
49
49
  },
50
50
  async seedDefaults({ container, tenantId, organizationId }) {
51
51
  await ensureSessionInitializationPruneSchedule(container, { tenantId, organizationId });
52
+ },
53
+ async onOrganizationCreated({ container, tenantId, organizationId }) {
54
+ await ensureSessionInitializationPruneSchedule(container, { tenantId, organizationId });
52
55
  }
53
56
  };
54
57
  var setup_default = setup;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/payment_gateways/setup.ts"],
4
- "sourcesContent": ["import { createHash } from 'node:crypto'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { PAYMENT_SESSION_INITIALIZATION_PRUNE_QUEUE } from './lib/session-idempotency'\n\ntype SchedulerServiceLike = {\n register: (registration: Record<string, unknown>) => Promise<void>\n}\n\nconst logger = createLogger('payment_gateways')\n\nfunction stableScheduleUuid(stableKey: string): string {\n const hex = createHash('sha256').update(stableKey).digest('hex')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\nexport async function registerSessionInitializationPruneSchedule(\n container: import('awilix').AwilixContainer | undefined,\n scope: { tenantId: string; organizationId: string },\n): Promise<boolean> {\n if (!container) return false\n const cradle = container as { hasRegistration?: (name: string) => boolean }\n if (typeof cradle.hasRegistration !== 'function' || !cradle.hasRegistration('schedulerService')) {\n return false\n }\n\n const schedulerService = container.resolve('schedulerService') as SchedulerServiceLike\n await schedulerService.register({\n id: stableScheduleUuid(\n `payment_gateways:session-initialization-prune:${scope.tenantId}:${scope.organizationId}`,\n ),\n name: 'Payment-session initialization prune',\n description: 'Delete completed payment-session initialization claims after the 24-hour replay window.',\n scopeType: 'organization',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n scheduleType: 'interval',\n scheduleValue: '24h',\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: PAYMENT_SESSION_INITIALIZATION_PRUNE_QUEUE,\n targetPayload: scope,\n sourceType: 'module',\n sourceModule: 'payment_gateways',\n isEnabled: true,\n })\n return true\n}\n\nasync function ensureSessionInitializationPruneSchedule(\n container: import('awilix').AwilixContainer | undefined,\n scope: { tenantId: string; organizationId: string },\n): Promise<void> {\n try {\n await registerSessionInitializationPruneSchedule(container, scope)\n } catch (error) {\n logger.warn('Failed to register payment-session initialization prune schedule', { err: error })\n }\n}\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: ['payment_gateways.*'],\n admin: ['payment_gateways.*'],\n employee: ['payment_gateways.view'],\n },\n\n async seedDefaults({ container, tenantId, organizationId }) {\n await ensureSessionInitializationPruneSchedule(container, { tenantId, organizationId })\n },\n}\n\nexport default setup\n"],
5
- "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAE7B,SAAS,kDAAkD;AAM3D,MAAM,SAAS,aAAa,kBAAkB;AAE9C,SAAS,mBAAmB,WAA2B;AACrD,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,SAAS,EAAE,OAAO,KAAK;AAC/D,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC;AAC9G;AAEA,eAAsB,2CACpB,WACA,OACkB;AAClB,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,SAAS;AACf,MAAI,OAAO,OAAO,oBAAoB,cAAc,CAAC,OAAO,gBAAgB,kBAAkB,GAAG;AAC/F,WAAO;AAAA,EACT;AAEA,QAAM,mBAAmB,UAAU,QAAQ,kBAAkB;AAC7D,QAAM,iBAAiB,SAAS;AAAA,IAC9B,IAAI;AAAA,MACF,iDAAiD,MAAM,QAAQ,IAAI,MAAM,cAAc;AAAA,IACzF;AAAA,IACA,MAAM;AAAA,IACN,aAAa;AAAA,IACb,WAAW;AAAA,IACX,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,IACtB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,WAAW;AAAA,EACb,CAAC;AACD,SAAO;AACT;AAEA,eAAe,yCACb,WACA,OACe;AACf,MAAI;AACF,UAAM,2CAA2C,WAAW,KAAK;AAAA,EACnE,SAAS,OAAO;AACd,WAAO,KAAK,oEAAoE,EAAE,KAAK,MAAM,CAAC;AAAA,EAChG;AACF;AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,YAAY,CAAC,oBAAoB;AAAA,IACjC,OAAO,CAAC,oBAAoB;AAAA,IAC5B,UAAU,CAAC,uBAAuB;AAAA,EACpC;AAAA,EAEA,MAAM,aAAa,EAAE,WAAW,UAAU,eAAe,GAAG;AAC1D,UAAM,yCAAyC,WAAW,EAAE,UAAU,eAAe,CAAC;AAAA,EACxF;AACF;AAEA,IAAO,gBAAQ;",
4
+ "sourcesContent": ["import { createHash } from 'node:crypto'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { PAYMENT_SESSION_INITIALIZATION_PRUNE_QUEUE } from './lib/session-idempotency'\n\ntype SchedulerServiceLike = {\n register: (registration: Record<string, unknown>) => Promise<void>\n}\n\nconst logger = createLogger('payment_gateways')\n\nfunction stableScheduleUuid(stableKey: string): string {\n const hex = createHash('sha256').update(stableKey).digest('hex')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\nexport async function registerSessionInitializationPruneSchedule(\n container: import('awilix').AwilixContainer | undefined,\n scope: { tenantId: string; organizationId: string },\n): Promise<boolean> {\n if (!container) return false\n const cradle = container as { hasRegistration?: (name: string) => boolean }\n if (typeof cradle.hasRegistration !== 'function' || !cradle.hasRegistration('schedulerService')) {\n return false\n }\n\n const schedulerService = container.resolve('schedulerService') as SchedulerServiceLike\n await schedulerService.register({\n id: stableScheduleUuid(\n `payment_gateways:session-initialization-prune:${scope.tenantId}:${scope.organizationId}`,\n ),\n name: 'Payment-session initialization prune',\n description: 'Delete completed payment-session initialization claims after the 24-hour replay window.',\n scopeType: 'organization',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n scheduleType: 'interval',\n scheduleValue: '24h',\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: PAYMENT_SESSION_INITIALIZATION_PRUNE_QUEUE,\n targetPayload: scope,\n sourceType: 'module',\n sourceModule: 'payment_gateways',\n isEnabled: true,\n })\n return true\n}\n\nasync function ensureSessionInitializationPruneSchedule(\n container: import('awilix').AwilixContainer | undefined,\n scope: { tenantId: string; organizationId: string },\n): Promise<void> {\n try {\n await registerSessionInitializationPruneSchedule(container, scope)\n } catch (error) {\n logger.warn('Failed to register payment-session initialization prune schedule', { err: error })\n }\n}\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: ['payment_gateways.*'],\n admin: ['payment_gateways.*'],\n employee: ['payment_gateways.view'],\n },\n\n async seedDefaults({ container, tenantId, organizationId }) {\n await ensureSessionInitializationPruneSchedule(container, { tenantId, organizationId })\n },\n\n async onOrganizationCreated({ container, tenantId, organizationId }) {\n await ensureSessionInitializationPruneSchedule(container, { tenantId, organizationId })\n },\n}\n\nexport default setup\n"],
5
+ "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,oBAAoB;AAE7B,SAAS,kDAAkD;AAM3D,MAAM,SAAS,aAAa,kBAAkB;AAE9C,SAAS,mBAAmB,WAA2B;AACrD,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,SAAS,EAAE,OAAO,KAAK;AAC/D,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC;AAC9G;AAEA,eAAsB,2CACpB,WACA,OACkB;AAClB,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,SAAS;AACf,MAAI,OAAO,OAAO,oBAAoB,cAAc,CAAC,OAAO,gBAAgB,kBAAkB,GAAG;AAC/F,WAAO;AAAA,EACT;AAEA,QAAM,mBAAmB,UAAU,QAAQ,kBAAkB;AAC7D,QAAM,iBAAiB,SAAS;AAAA,IAC9B,IAAI;AAAA,MACF,iDAAiD,MAAM,QAAQ,IAAI,MAAM,cAAc;AAAA,IACzF;AAAA,IACA,MAAM;AAAA,IACN,aAAa;AAAA,IACb,WAAW;AAAA,IACX,UAAU,MAAM;AAAA,IAChB,gBAAgB,MAAM;AAAA,IACtB,cAAc;AAAA,IACd,eAAe;AAAA,IACf,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,WAAW;AAAA,EACb,CAAC;AACD,SAAO;AACT;AAEA,eAAe,yCACb,WACA,OACe;AACf,MAAI;AACF,UAAM,2CAA2C,WAAW,KAAK;AAAA,EACnE,SAAS,OAAO;AACd,WAAO,KAAK,oEAAoE,EAAE,KAAK,MAAM,CAAC;AAAA,EAChG;AACF;AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,YAAY,CAAC,oBAAoB;AAAA,IACjC,OAAO,CAAC,oBAAoB;AAAA,IAC5B,UAAU,CAAC,uBAAuB;AAAA,EACpC;AAAA,EAEA,MAAM,aAAa,EAAE,WAAW,UAAU,eAAe,GAAG;AAC1D,UAAM,yCAAyC,WAAW,EAAE,UAAU,eAAe,CAAC;AAAA,EACxF;AAAA,EAEA,MAAM,sBAAsB,EAAE,WAAW,UAAU,eAAe,GAAG;AACnE,UAAM,yCAAyC,WAAW,EAAE,UAAU,eAAe,CAAC;AAAA,EACxF;AACF;AAEA,IAAO,gBAAQ;",
6
6
  "names": []
7
7
  }
@@ -510,6 +510,7 @@ function WarrantyClaimDetailPage({ params }) {
510
510
  const [lineDialog, setLineDialog] = React.useState(null);
511
511
  const [defaultWarrantyMonths, setDefaultWarrantyMonths] = React.useState(null);
512
512
  const [featureAccess, setFeatureAccess] = React.useState({
513
+ attachmentsView: false,
513
514
  claimManage: false,
514
515
  claimDelete: false,
515
516
  receivingManage: false,
@@ -537,6 +538,7 @@ function WarrantyClaimDetailPage({ params }) {
537
538
  headers: { "content-type": "application/json" },
538
539
  body: JSON.stringify({
539
540
  features: [
541
+ "attachments.view",
540
542
  "warranty_claims.claim.manage",
541
543
  "warranty_claims.claim.delete",
542
544
  "warranty_claims.receiving.manage",
@@ -552,6 +554,7 @@ function WarrantyClaimDetailPage({ params }) {
552
554
  const granted = Array.isArray(call.result?.granted) ? call.result.granted : [];
553
555
  const allGranted = call.result?.ok === true;
554
556
  setFeatureAccess({
557
+ attachmentsView: allGranted || hasFeature(granted, "attachments.view"),
555
558
  claimManage: allGranted || hasFeature(granted, "warranty_claims.claim.manage"),
556
559
  claimDelete: allGranted || hasFeature(granted, "warranty_claims.claim.delete"),
557
560
  receivingManage: allGranted || hasFeature(granted, "warranty_claims.receiving.manage"),
@@ -562,6 +565,7 @@ function WarrantyClaimDetailPage({ params }) {
562
565
  }).catch(() => {
563
566
  if (!cancelled) {
564
567
  setFeatureAccess({
568
+ attachmentsView: false,
565
569
  claimManage: false,
566
570
  claimDelete: false,
567
571
  receivingManage: false,
@@ -632,7 +636,7 @@ function WarrantyClaimDetailPage({ params }) {
632
636
  setError(null);
633
637
  setNotFound(false);
634
638
  try {
635
- const [claimPayload, linesPayload, eventsPayload, riskPayload, statsPayload, attachmentsPayload] = await Promise.all([
639
+ const [claimPayload, linesPayload, eventsPayload, riskPayload, statsPayload] = await Promise.all([
636
640
  readApiResultOrThrow(
637
641
  `/api/warranty_claims?ids=${encodeURIComponent(id)}&page=1&pageSize=1`,
638
642
  void 0,
@@ -656,11 +660,6 @@ function WarrantyClaimDetailPage({ params }) {
656
660
  "/api/warranty_claims/stats",
657
661
  void 0,
658
662
  { fallback: { ok: true, result: {} } }
659
- ),
660
- readApiResultOrThrow(
661
- `/api/attachments?entityId=${encodeURIComponent("warranty_claims:warranty_claim")}&recordId=${encodeURIComponent(id)}`,
662
- void 0,
663
- { fallback: { items: [] } }
664
663
  )
665
664
  ]);
666
665
  const nextClaim = (claimPayload.items ?? []).map(normalizeClaim).find((item) => item !== null) ?? null;
@@ -676,7 +675,6 @@ function WarrantyClaimDetailPage({ params }) {
676
675
  setClaim(nextClaim);
677
676
  setLines((linesPayload.items ?? []).map(normalizeLine).filter((item) => item !== null));
678
677
  setEvents((eventsPayload.items ?? []).map(normalizeEvent).filter((item) => item !== null));
679
- setAttachmentCount(Array.isArray(attachmentsPayload.items) ? attachmentsPayload.items.length : 0);
680
678
  setRiskAssessment(normalizeRiskResponse(riskPayload));
681
679
  const nextThreshold = statsPayload?.result?.slaAtRiskThresholdPct;
682
680
  setSlaAtRiskThresholdPct(typeof nextThreshold === "number" ? nextThreshold : void 0);
@@ -689,6 +687,27 @@ function WarrantyClaimDetailPage({ params }) {
689
687
  React.useEffect(() => {
690
688
  void loadData();
691
689
  }, [loadData]);
690
+ React.useEffect(() => {
691
+ let cancelled = false;
692
+ setAttachmentCount(0);
693
+ if (!claim || claim.id !== id || !featureAccess.attachmentsView) return;
694
+ void apiCall(
695
+ `/api/attachments?entityId=${encodeURIComponent("warranty_claims:warranty_claim")}&recordId=${encodeURIComponent(claim.id)}`,
696
+ { headers: { "x-om-forbidden-redirect": "0" } },
697
+ { fallback: { items: [] } }
698
+ ).then((call) => {
699
+ if (cancelled || !call.ok) return;
700
+ setAttachmentCount(Array.isArray(call.result?.items) ? call.result.items.length : 0);
701
+ }).catch((error2) => {
702
+ getTelemetryRuntime()?.reportError(error2, {
703
+ module: "warranty_claims",
704
+ code: "warranty_claims.attachment_count_failed"
705
+ });
706
+ });
707
+ return () => {
708
+ cancelled = true;
709
+ };
710
+ }, [claim, featureAccess.attachmentsView, id, scopeVersion]);
692
711
  useAppEvent("warranty_claims.claim.*", (event) => {
693
712
  const eventClaimId = toStringOrNull(event.payload.claimId);
694
713
  if (eventClaimId === id) void loadData();
@@ -1542,7 +1561,7 @@ function WarrantyClaimDetailPage({ params }) {
1542
1561
  const tabs = [
1543
1562
  { id: "lines", label: t("warranty_claims.detail.tabs.lines"), count: lines.length },
1544
1563
  { id: "timeline", label: t("warranty_claims.detail.tabs.timeline"), count: events.length },
1545
- { id: "attachments", label: t("warranty_claims.detail.tabs.attachments"), count: attachmentCount },
1564
+ ...featureAccess.attachmentsView ? [{ id: "attachments", label: t("warranty_claims.detail.tabs.attachments"), count: attachmentCount }] : [],
1546
1565
  { id: "ai", label: t("warranty_claims.detail.tabs.ai") }
1547
1566
  ];
1548
1567
  const approvedLineCount = lines.filter((line) => line.lineStatus === "approved").length;
@@ -1656,7 +1675,7 @@ function WarrantyClaimDetailPage({ params }) {
1656
1675
  /* @__PURE__ */ jsxs(
1657
1676
  Tabs,
1658
1677
  {
1659
- value: activeTab,
1678
+ value: activeTab === "attachments" && !featureAccess.attachmentsView ? "lines" : activeTab,
1660
1679
  onValueChange: (value) => setActiveTab(value),
1661
1680
  variant: "underline",
1662
1681
  children: [
@@ -1829,7 +1848,7 @@ function WarrantyClaimDetailPage({ params }) {
1829
1848
  )
1830
1849
  ] })
1831
1850
  ] }) }),
1832
- /* @__PURE__ */ jsx(TabsContent, { value: "attachments", className: "mt-0", children: /* @__PURE__ */ jsx("div", { className: "px-8 pb-8 pt-6", children: /* @__PURE__ */ jsx(
1851
+ featureAccess.attachmentsView ? /* @__PURE__ */ jsx(TabsContent, { value: "attachments", className: "mt-0", children: /* @__PURE__ */ jsx("div", { className: "px-8 pb-8 pt-6", children: /* @__PURE__ */ jsx(
1833
1852
  AttachmentInput,
1834
1853
  {
1835
1854
  entityId: "warranty_claims:warranty_claim",
@@ -1840,7 +1859,7 @@ function WarrantyClaimDetailPage({ params }) {
1840
1859
  onCountChange: setAttachmentCount,
1841
1860
  renderItemMeta: (item) => isCustomerVisibleAttachment(item.tags) ? /* @__PURE__ */ jsx(StatusBadge, { variant: "info", children: t("warranty_claims.detail.attachments.customerVisible", "Visible to customer") }) : null
1842
1861
  }
1843
- ) }) }),
1862
+ ) }) }) : null,
1844
1863
  /* @__PURE__ */ jsx(TabsContent, { value: "ai", className: "mt-0", children: /* @__PURE__ */ jsxs("div", { className: "grid gap-4 px-8 pb-8 pt-6 xl:grid-cols-2", children: [
1845
1864
  /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border bg-card p-4", children: [
1846
1865
  /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [