@open-mercato/core 0.6.1-develop.3246.1.dbef9d7392 → 0.6.1-develop.3260.1.dc719cac84

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 (130) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/helpers/integration/authFixtures.js.map +1 -1
  3. package/dist/helpers/integration/authUi.js +10 -2
  4. package/dist/helpers/integration/authUi.js.map +2 -2
  5. package/dist/helpers/integration/salesUi.js +3 -1
  6. package/dist/helpers/integration/salesUi.js.map +2 -2
  7. package/dist/modules/api_docs/frontend/docs/api/Explorer.js +10 -1
  8. package/dist/modules/api_docs/frontend/docs/api/Explorer.js.map +2 -2
  9. package/dist/modules/audit_logs/lib/display-helpers.js +28 -27
  10. package/dist/modules/audit_logs/lib/display-helpers.js.map +2 -2
  11. package/dist/modules/auth/api/users/route.js +21 -3
  12. package/dist/modules/auth/api/users/route.js.map +2 -2
  13. package/dist/modules/auth/backend/users/[id]/edit/page.js +6 -1
  14. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  15. package/dist/modules/auth/backend/users/create/page.js +4 -1
  16. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  17. package/dist/modules/auth/backend/users/page.js +56 -2
  18. package/dist/modules/auth/backend/users/page.js.map +3 -3
  19. package/dist/modules/auth/commands/users.js +14 -0
  20. package/dist/modules/auth/commands/users.js.map +2 -2
  21. package/dist/modules/auth/data/validators.js +8 -0
  22. package/dist/modules/auth/data/validators.js.map +2 -2
  23. package/dist/modules/catalog/ai-agents.js +4 -0
  24. package/dist/modules/catalog/ai-agents.js.map +2 -2
  25. package/dist/modules/customers/ai-agents.js.map +2 -2
  26. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +1 -1
  27. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  28. package/dist/modules/customers/backend/customers/deals/[id]/page.js +15 -9
  29. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  30. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +26 -3
  31. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  32. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +1 -1
  33. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  34. package/dist/modules/customers/components/PipelineSettings.js +108 -99
  35. package/dist/modules/customers/components/PipelineSettings.js.map +2 -2
  36. package/dist/modules/customers/components/detail/AssignRoleDialog.js +13 -5
  37. package/dist/modules/customers/components/detail/AssignRoleDialog.js.map +2 -2
  38. package/dist/modules/customers/components/detail/EntityTagsDialog.js +10 -2
  39. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
  40. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +15 -8
  41. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
  42. package/dist/modules/customers/components/detail/RolesSection.js +35 -22
  43. package/dist/modules/customers/components/detail/RolesSection.js.map +2 -2
  44. package/dist/modules/customers/components/detail/TasksSection.js +2 -2
  45. package/dist/modules/customers/components/detail/TasksSection.js.map +2 -2
  46. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js +73 -64
  47. package/dist/modules/customers/components/detail/schedule/DateTimeFields.js.map +2 -2
  48. package/dist/modules/customers/components/linking/LinkEntityDialog.js +11 -2
  49. package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +2 -2
  50. package/dist/modules/data_sync/backend/data-sync/page.js +2 -9
  51. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  52. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +14 -29
  53. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
  54. package/dist/modules/dictionaries/components/DictionariesManager.js +10 -2
  55. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  56. package/dist/modules/entities/components/EncryptionManager.js +40 -17
  57. package/dist/modules/entities/components/EncryptionManager.js.map +2 -2
  58. package/dist/modules/inbox_ops/lib/llmProvider.js.map +2 -2
  59. package/dist/modules/integrations/backend/integrations/[id]/page.js +79 -95
  60. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  61. package/dist/modules/payment_gateways/backend/payment-gateways/page.js +49 -70
  62. package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
  63. package/dist/modules/planner/components/AvailabilityRuleSetForm.js +1 -1
  64. package/dist/modules/planner/components/AvailabilityRuleSetForm.js.map +1 -1
  65. package/dist/modules/planner/components/AvailabilityRulesEditor.js +19 -19
  66. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  67. package/dist/modules/resources/components/ResourceCrudForm.js +1 -1
  68. package/dist/modules/resources/components/ResourceCrudForm.js.map +1 -1
  69. package/dist/modules/resources/components/ResourceTypeCrudForm.js +1 -1
  70. package/dist/modules/resources/components/ResourceTypeCrudForm.js.map +2 -2
  71. package/dist/modules/sales/components/documents/ReturnDialog.js +11 -8
  72. package/dist/modules/sales/components/documents/ReturnDialog.js.map +2 -2
  73. package/dist/modules/staff/backend/staff/profile/create/page.js +1 -1
  74. package/dist/modules/staff/backend/staff/profile/create/page.js.map +2 -2
  75. package/dist/modules/staff/components/TeamForm.js +1 -1
  76. package/dist/modules/staff/components/TeamForm.js.map +2 -2
  77. package/dist/modules/staff/components/TeamMemberForm.js +1 -1
  78. package/dist/modules/staff/components/TeamMemberForm.js.map +1 -1
  79. package/dist/modules/staff/components/TeamRoleForm.js +1 -1
  80. package/dist/modules/staff/components/TeamRoleForm.js.map +2 -2
  81. package/package.json +5 -5
  82. package/src/helpers/integration/authFixtures.ts +1 -1
  83. package/src/helpers/integration/authUi.ts +11 -2
  84. package/src/helpers/integration/salesUi.ts +10 -1
  85. package/src/modules/api_docs/frontend/docs/api/Explorer.tsx +7 -3
  86. package/src/modules/audit_logs/lib/display-helpers.tsx +22 -14
  87. package/src/modules/auth/api/users/route.ts +22 -3
  88. package/src/modules/auth/backend/users/[id]/edit/page.tsx +9 -1
  89. package/src/modules/auth/backend/users/create/page.tsx +6 -2
  90. package/src/modules/auth/backend/users/page.tsx +60 -3
  91. package/src/modules/auth/commands/users.ts +15 -0
  92. package/src/modules/auth/data/validators.ts +8 -0
  93. package/src/modules/auth/i18n/de.json +4 -0
  94. package/src/modules/auth/i18n/en.json +4 -0
  95. package/src/modules/auth/i18n/es.json +4 -0
  96. package/src/modules/auth/i18n/pl.json +4 -0
  97. package/src/modules/catalog/ai-agents.ts +8 -49
  98. package/src/modules/customers/ai-agents.ts +4 -51
  99. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +1 -1
  100. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +12 -13
  101. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +17 -13
  102. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +1 -1
  103. package/src/modules/customers/components/PipelineSettings.tsx +95 -95
  104. package/src/modules/customers/components/detail/AssignRoleDialog.tsx +7 -4
  105. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +13 -8
  106. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +16 -12
  107. package/src/modules/customers/components/detail/RolesSection.tsx +34 -31
  108. package/src/modules/customers/components/detail/TasksSection.tsx +16 -8
  109. package/src/modules/customers/components/detail/schedule/DateTimeFields.tsx +77 -51
  110. package/src/modules/customers/components/linking/LinkEntityDialog.tsx +7 -3
  111. package/src/modules/data_sync/backend/data-sync/page.tsx +4 -7
  112. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +19 -54
  113. package/src/modules/dictionaries/components/DictionariesManager.tsx +7 -4
  114. package/src/modules/entities/components/EncryptionManager.tsx +50 -21
  115. package/src/modules/inbox_ops/lib/llmProvider.ts +10 -0
  116. package/src/modules/integrations/backend/integrations/[id]/page.tsx +101 -146
  117. package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +60 -103
  118. package/src/modules/planner/components/AvailabilityRuleSetForm.tsx +1 -1
  119. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +17 -17
  120. package/src/modules/resources/components/ResourceCrudForm.tsx +1 -1
  121. package/src/modules/resources/components/ResourceTypeCrudForm.tsx +1 -1
  122. package/src/modules/sales/components/documents/ReturnDialog.tsx +10 -7
  123. package/src/modules/sales/i18n/de.json +2 -0
  124. package/src/modules/sales/i18n/en.json +2 -0
  125. package/src/modules/sales/i18n/es.json +2 -0
  126. package/src/modules/sales/i18n/pl.json +2 -0
  127. package/src/modules/staff/backend/staff/profile/create/page.tsx +1 -1
  128. package/src/modules/staff/components/TeamForm.tsx +1 -1
  129. package/src/modules/staff/components/TeamMemberForm.tsx +1 -1
  130. package/src/modules/staff/components/TeamRoleForm.tsx +1 -1
@@ -18,7 +18,8 @@ import { Badge } from '@open-mercato/ui/primitives/badge'
18
18
  import { Button } from '@open-mercato/ui/primitives/button'
19
19
  import { Card, CardContent, CardHeader, CardTitle } from '@open-mercato/ui/primitives/card'
20
20
  import { Spinner } from '@open-mercato/ui/primitives/spinner'
21
- import { ChevronDown, ChevronRight, CreditCard, HandCoins, RefreshCw, Webhook } from 'lucide-react'
21
+ import { LogList, type LogListEntry } from '@open-mercato/ui/backend/LogList'
22
+ import { CreditCard, HandCoins, RefreshCw, Webhook } from 'lucide-react'
22
23
 
23
24
  type TransactionRow = {
24
25
  id: string
@@ -102,12 +103,6 @@ const STATUS_STYLES: Record<string, string> = {
102
103
  unknown: 'bg-purple-100 text-purple-800',
103
104
  }
104
105
 
105
- const LOG_LEVEL_STYLES: Record<string, string> = {
106
- info: 'bg-blue-100 text-blue-800',
107
- warn: 'bg-yellow-100 text-yellow-800',
108
- error: 'bg-red-100 text-red-800',
109
- }
110
-
111
106
  function formatDateTime(value: string | null | undefined): string {
112
107
  if (!value) return '—'
113
108
  const parsed = new Date(value)
@@ -194,7 +189,6 @@ export default function PaymentTransactionsPage() {
194
189
  const [detail, setDetail] = React.useState<TransactionDetail | null>(null)
195
190
  const [isLoadingDetail, setIsLoadingDetail] = React.useState(false)
196
191
  const [detailError, setDetailError] = React.useState<string | null>(null)
197
- const [expandedLogId, setExpandedLogId] = React.useState<string | null>(null)
198
192
  const [isRefreshingStatus, setIsRefreshingStatus] = React.useState(false)
199
193
  const [isCapturing, setIsCapturing] = React.useState(false)
200
194
  const { runMutation } = useGuardedMutation<{
@@ -249,7 +243,6 @@ export default function PaymentTransactionsPage() {
249
243
  const call = await apiCall<TransactionDetail>(`/api/payment_gateways/transactions/${encodeURIComponent(transactionId)}`, undefined, { fallback: null })
250
244
  if (call.ok && call.result) {
251
245
  setDetail(call.result)
252
- setExpandedLogId((current) => (current && call.result?.logs.some((log) => log.id === current) ? current : null))
253
246
  } else {
254
247
  setDetail(null)
255
248
  setDetailError(t('payment_gateways.transactions.error.loadDetail', 'Failed to load transaction details'))
@@ -610,100 +603,64 @@ export default function PaymentTransactionsPage() {
610
603
 
611
604
  <section className="space-y-3">
612
605
  <h3 className="text-sm font-semibold">{t('payment_gateways.transactions.detail.logs', 'Gateway logs')}</h3>
613
- {detail.logs.length === 0 ? (
614
- <p className="text-sm text-muted-foreground">{t('payment_gateways.transactions.detail.logsEmpty', 'No transaction-scoped logs are available yet.')}</p>
615
- ) : (
616
- <div className="overflow-hidden rounded-lg border">
617
- <table className="w-full text-sm">
618
- <thead>
619
- <tr className="border-b bg-muted/50">
620
- <th className="px-4 py-2 text-left font-medium">{t('payment_gateways.transactions.columns.time', 'Time')}</th>
621
- <th className="px-4 py-2 text-left font-medium">{t('payment_gateways.transactions.columns.level', 'Level')}</th>
622
- <th className="px-4 py-2 text-left font-medium">{t('payment_gateways.transactions.columns.message', 'Message')}</th>
623
- </tr>
624
- </thead>
625
- <tbody>
626
- {detail.logs.map((log) => {
627
- const isExpanded = expandedLogId === log.id
628
- const metadataEntries = [
629
- [t('payment_gateways.transactions.log.time', 'Time'), formatDateTime(log.createdAt)],
630
- [t('payment_gateways.transactions.log.level', 'Level'), t(`payment_gateways.transactions.level.${log.level}`, log.level)],
631
- [t('payment_gateways.transactions.log.code', 'Code'), log.code ?? null],
632
- [t('payment_gateways.transactions.log.runId', 'Run ID'), log.runId ?? null],
633
- [t('payment_gateways.transactions.log.entityType', 'Entity Type'), log.scopeEntityType ?? null],
634
- [t('payment_gateways.transactions.log.entityId', 'Entity ID'), log.scopeEntityId ?? null],
635
- ].filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1].trim().length > 0)
636
- const { inlineEntries, nestedEntries } = splitLogPayload(log.payload)
637
-
638
- return (
639
- <React.Fragment key={log.id}>
640
- <tr className="border-b last:border-0">
641
- <td className="whitespace-nowrap px-4 py-2 text-muted-foreground">{formatDateTime(log.createdAt)}</td>
642
- <td className="px-4 py-2">
643
- <Badge variant="secondary" className={LOG_LEVEL_STYLES[log.level] ?? ''}>
644
- {t(`payment_gateways.transactions.level.${log.level}`, log.level)}
645
- </Badge>
646
- </td>
647
- <td className="px-4 py-2">
648
- <Button
649
- type="button"
650
- variant="ghost"
651
- size="sm"
652
- className="h-auto w-full justify-start gap-2 px-0 py-0 text-left hover:bg-transparent"
653
- onClick={() => setExpandedLogId((current) => current === log.id ? null : log.id)}
654
- >
655
- {isExpanded ? <ChevronDown className="h-4 w-4 shrink-0" /> : <ChevronRight className="h-4 w-4 shrink-0" />}
656
- <span className="truncate">{log.message}</span>
657
- </Button>
658
- </td>
659
- </tr>
660
- {isExpanded ? (
661
- <tr className="border-b bg-muted/30 last:border-0">
662
- <td colSpan={3} className="px-4 py-4">
663
- <div className="space-y-4 rounded-lg border bg-card p-4">
664
- {metadataEntries.length > 0 ? (
665
- <dl className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
666
- {metadataEntries.map(([label, value]) => (
667
- <div key={label} className="rounded-md border bg-muted/30 px-3 py-2">
668
- <dt className="text-overline font-medium uppercase tracking-wide text-muted-foreground">{label}</dt>
669
- <dd className="mt-1 break-all text-sm">{value}</dd>
670
- </div>
671
- ))}
672
- </dl>
673
- ) : null}
674
- {inlineEntries.length > 0 ? (
675
- <dl className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
676
- {inlineEntries.map(([key, value]) => (
677
- <div key={key} className="rounded-md border bg-muted/30 px-3 py-2">
678
- <dt className="text-overline font-medium uppercase tracking-wide text-muted-foreground">{formatLogDetailLabel(key)}</dt>
679
- <dd className="mt-1 break-words text-sm">{formatLogPrimitiveValue(value)}</dd>
680
- </div>
681
- ))}
682
- </dl>
683
- ) : null}
684
- {nestedEntries.map(([key, value]) => (
685
- <JsonDisplay
686
- key={key}
687
- data={value}
688
- title={formatLogDetailLabel(key)}
689
- defaultExpanded
690
- maxInitialDepth={1}
691
- theme="dark"
692
- maxHeight="16rem"
693
- className="p-4"
694
- />
695
- ))}
696
- </div>
697
- </td>
698
- </tr>
699
- ) : null}
700
- </React.Fragment>
701
- )
702
- })}
703
- </tbody>
704
- </table>
705
- </div>
706
- )}
606
+ <LogList
607
+ entries={detail.logs.map<LogListEntry>((log) => {
608
+ const metadataEntries = [
609
+ [t('payment_gateways.transactions.log.time', 'Time'), formatDateTime(log.createdAt)],
610
+ [t('payment_gateways.transactions.log.level', 'Level'), t(`payment_gateways.transactions.level.${log.level}`, log.level)],
611
+ [t('payment_gateways.transactions.log.code', 'Code'), log.code ?? null],
612
+ [t('payment_gateways.transactions.log.runId', 'Run ID'), log.runId ?? null],
613
+ [t('payment_gateways.transactions.log.entityType', 'Entity Type'), log.scopeEntityType ?? null],
614
+ [t('payment_gateways.transactions.log.entityId', 'Entity ID'), log.scopeEntityId ?? null],
615
+ ].filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1].trim().length > 0)
616
+ const { inlineEntries, nestedEntries } = splitLogPayload(log.payload)
617
+
618
+ return {
619
+ id: log.id,
620
+ time: formatDateTime(log.createdAt),
621
+ level: log.level,
622
+ levelLabel: t(`payment_gateways.transactions.level.${log.level}`, log.level),
623
+ message: log.message,
624
+ body: (
625
+ <div className="space-y-4">
626
+ {metadataEntries.length > 0 ? (
627
+ <dl className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
628
+ {metadataEntries.map(([label, value]) => (
629
+ <div key={label} className="rounded-md border bg-muted/30 px-3 py-2">
630
+ <dt className="text-overline font-medium uppercase tracking-wide text-muted-foreground">{label}</dt>
631
+ <dd className="mt-1 break-all text-sm">{value}</dd>
632
+ </div>
633
+ ))}
634
+ </dl>
635
+ ) : null}
636
+ {inlineEntries.length > 0 ? (
637
+ <dl className="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
638
+ {inlineEntries.map(([key, value]) => (
639
+ <div key={key} className="rounded-md border bg-muted/30 px-3 py-2">
640
+ <dt className="text-overline font-medium uppercase tracking-wide text-muted-foreground">{formatLogDetailLabel(key)}</dt>
641
+ <dd className="mt-1 break-words text-sm">{formatLogPrimitiveValue(value)}</dd>
642
+ </div>
643
+ ))}
644
+ </dl>
645
+ ) : null}
646
+ {nestedEntries.map(([key, value]) => (
647
+ <JsonDisplay
648
+ key={key}
649
+ data={value}
650
+ title={formatLogDetailLabel(key)}
651
+ defaultExpanded
652
+ maxInitialDepth={1}
653
+ theme="dark"
654
+ maxHeight="16rem"
655
+ className="p-4"
656
+ />
657
+ ))}
658
+ </div>
659
+ ),
660
+ }
661
+ })}
662
+ emptyMessage={t('payment_gateways.transactions.detail.logsEmpty', 'No transaction-scoped logs are available yet.')}
663
+ />
707
664
  </section>
708
665
  </div>
709
666
 
@@ -73,7 +73,7 @@ export function AvailabilityRuleSetForm(props: AvailabilityRuleSetFormProps) {
73
73
  id: 'description',
74
74
  label: translate('planner.availabilityRuleSets.form.fields.description', 'Description'),
75
75
  type: 'richtext',
76
- editor: 'uiw',
76
+ editor: 'html',
77
77
  },
78
78
  ], [translate])
79
79
 
@@ -18,7 +18,7 @@ import { apiCall, apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
18
18
  import { createCrud, deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'
19
19
  import { flash } from '@open-mercato/ui/backend/FlashMessages'
20
20
  import { Spinner } from '@open-mercato/ui/primitives/spinner'
21
- import { ComboboxInput } from '@open-mercato/ui/backend/inputs'
21
+ import { ComboboxInput, TimePicker } from '@open-mercato/ui/backend/inputs'
22
22
  import { DictionaryEntrySelect, type DictionarySelectLabels } from '@open-mercato/core/modules/dictionaries/components/DictionaryEntrySelect'
23
23
  import {
24
24
  createUnavailabilityReasonEntry,
@@ -1425,20 +1425,20 @@ export function AvailabilityRulesEditor({
1425
1425
  return (
1426
1426
  <div key={`${day.code}-${windowIndex}`} className="space-y-1">
1427
1427
  <div className="flex flex-wrap items-center gap-2">
1428
- <Input
1429
- type="time"
1428
+ <TimePicker
1430
1429
  value={window.start}
1431
- onChange={(event) => handleWeeklyWindowChange(index, windowIndex, { ...window, start: event.target.value })}
1432
- className={`h-9 w-[120px] ${errorClass}`}
1430
+ onChange={(value) => handleWeeklyWindowChange(index, windowIndex, { ...window, start: value ?? '' })}
1431
+ className={`w-[120px] ${errorClass}`}
1433
1432
  disabled={usingRuleSet || isReadOnly}
1433
+ showClearButton={false}
1434
1434
  />
1435
1435
  <span className="text-sm text-muted-foreground">-</span>
1436
- <Input
1437
- type="time"
1436
+ <TimePicker
1438
1437
  value={window.end}
1439
- onChange={(event) => handleWeeklyWindowChange(index, windowIndex, { ...window, end: event.target.value })}
1440
- className={`h-9 w-[120px] ${errorClass}`}
1438
+ onChange={(value) => handleWeeklyWindowChange(index, windowIndex, { ...window, end: value ?? '' })}
1439
+ className={`w-[120px] ${errorClass}`}
1441
1440
  disabled={usingRuleSet || isReadOnly}
1441
+ showClearButton={false}
1442
1442
  />
1443
1443
  <Button
1444
1444
  type="button"
@@ -1753,18 +1753,18 @@ export function AvailabilityRulesEditor({
1753
1753
  return (
1754
1754
  <div key={`${index}-${window.start}`} className="space-y-1">
1755
1755
  <div className="flex flex-wrap items-center gap-2">
1756
- <Input
1757
- type="time"
1756
+ <TimePicker
1758
1757
  value={window.start}
1759
- onChange={(event) => handleEditorWindowChange(index, { ...window, start: event.target.value })}
1760
- className={`h-9 w-[120px] ${errorClass}`}
1758
+ onChange={(value) => handleEditorWindowChange(index, { ...window, start: value ?? '' })}
1759
+ className={`w-[120px] ${errorClass}`}
1760
+ showClearButton={false}
1761
1761
  />
1762
1762
  <span className="text-sm text-muted-foreground">-</span>
1763
- <Input
1764
- type="time"
1763
+ <TimePicker
1765
1764
  value={window.end}
1766
- onChange={(event) => handleEditorWindowChange(index, { ...window, end: event.target.value })}
1767
- className={`h-9 w-[120px] ${errorClass}`}
1765
+ onChange={(value) => handleEditorWindowChange(index, { ...window, end: value ?? '' })}
1766
+ className={`w-[120px] ${errorClass}`}
1767
+ showClearButton={false}
1768
1768
  />
1769
1769
  <Button
1770
1770
  type="button"
@@ -131,7 +131,7 @@ export function useResourcesResourceFormConfig(options: {
131
131
  id: 'description',
132
132
  label: t('resources.resources.form.fields.description', 'Description'),
133
133
  type: 'richtext',
134
- editor: 'uiw',
134
+ editor: 'html',
135
135
  },
136
136
  {
137
137
  id: 'resourceTypeId',
@@ -78,7 +78,7 @@ export function ResourceTypeCrudForm({
78
78
 
79
79
  const fields = React.useMemo<CrudField[]>(() => [
80
80
  { id: 'name', label: t('resources.resourceTypes.form.name', 'Name'), type: 'text', required: true },
81
- { id: 'description', label: t('resources.resourceTypes.form.description', 'Description'), type: 'richtext' },
81
+ { id: 'description', label: t('resources.resourceTypes.form.description', 'Description'), type: 'richtext', editor: 'html' },
82
82
  {
83
83
  id: 'appearance',
84
84
  label: t('resources.resourceTypes.form.appearance.label', 'Appearance'),
@@ -3,6 +3,7 @@
3
3
  import * as React from 'react'
4
4
  import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@open-mercato/ui/primitives/dialog'
5
5
  import { Input } from '@open-mercato/ui/primitives/input'
6
+ import { CounterInput } from '@open-mercato/ui/primitives/counter-input'
6
7
  import { Textarea } from '@open-mercato/ui/primitives/textarea'
7
8
  import { Label } from '@open-mercato/ui/primitives/label'
8
9
  import { Button } from '@open-mercato/ui/primitives/button'
@@ -173,19 +174,21 @@ export function ReturnDialog({ open, orderId, lines, onClose, onSaved }: ReturnD
173
174
  <Label className="sr-only" htmlFor={`return-qty-${line.id}`}>
174
175
  {t('sales.returns.quantity', 'Quantity')}
175
176
  </Label>
176
- <Input
177
+ <CounterInput
177
178
  id={`return-qty-${line.id}`}
178
- type="number"
179
- inputMode="numeric"
180
179
  min={1}
181
180
  max={line.available}
182
181
  step={1}
183
182
  placeholder="0"
184
- value={value}
185
- onChange={(e) => {
186
- const next = e.target.value.replace(/[^0-9]/g, '')
187
- setQuantities((prev) => ({ ...prev, [line.id]: next }))
183
+ value={value === '' ? null : Number(value)}
184
+ onChange={(next) => {
185
+ setQuantities((prev) => ({
186
+ ...prev,
187
+ [line.id]: next === null ? '' : String(next),
188
+ }))
188
189
  }}
190
+ decrementAriaLabel={t('sales.returns.qty.decrease', 'Decrease quantity')}
191
+ incrementAriaLabel={t('sales.returns.qty.increase', 'Increase quantity')}
189
192
  />
190
193
  </div>
191
194
  </div>
@@ -1297,6 +1297,8 @@
1297
1297
  "sales.returns.notes": "Notizen",
1298
1298
  "sales.returns.notes.placeholder": "Optional",
1299
1299
  "sales.returns.orderMissing": "Bestellung nicht gefunden.",
1300
+ "sales.returns.qty.decrease": "Menge verringern",
1301
+ "sales.returns.qty.increase": "Menge erhöhen",
1300
1302
  "sales.returns.quantity": "Menge",
1301
1303
  "sales.returns.quantityExceeded": "Es kann nicht mehr als die verbleibende Menge zurückgegeben werden.",
1302
1304
  "sales.returns.reason": "Grund",
@@ -1297,6 +1297,8 @@
1297
1297
  "sales.returns.notes": "Notes",
1298
1298
  "sales.returns.notes.placeholder": "Optional",
1299
1299
  "sales.returns.orderMissing": "Order not found.",
1300
+ "sales.returns.qty.decrease": "Decrease quantity",
1301
+ "sales.returns.qty.increase": "Increase quantity",
1300
1302
  "sales.returns.quantity": "Quantity",
1301
1303
  "sales.returns.quantityExceeded": "Cannot return more than the remaining quantity.",
1302
1304
  "sales.returns.reason": "Reason",
@@ -1297,6 +1297,8 @@
1297
1297
  "sales.returns.notes": "Notas",
1298
1298
  "sales.returns.notes.placeholder": "Opcional",
1299
1299
  "sales.returns.orderMissing": "Pedido no encontrado.",
1300
+ "sales.returns.qty.decrease": "Disminuir cantidad",
1301
+ "sales.returns.qty.increase": "Aumentar cantidad",
1300
1302
  "sales.returns.quantity": "Cantidad",
1301
1303
  "sales.returns.quantityExceeded": "No se puede devolver más que la cantidad restante.",
1302
1304
  "sales.returns.reason": "Motivo",
@@ -1297,6 +1297,8 @@
1297
1297
  "sales.returns.notes": "Notatki",
1298
1298
  "sales.returns.notes.placeholder": "Opcjonalne",
1299
1299
  "sales.returns.orderMissing": "Nie znaleziono zamówienia.",
1300
+ "sales.returns.qty.decrease": "Zmniejsz ilość",
1301
+ "sales.returns.qty.increase": "Zwiększ ilość",
1300
1302
  "sales.returns.quantity": "Ilość",
1301
1303
  "sales.returns.quantityExceeded": "Nie można zwrócić więcej niż pozostała ilość.",
1302
1304
  "sales.returns.reason": "Powód",
@@ -53,7 +53,7 @@ export default function StaffProfileCreatePage() {
53
53
 
54
54
  const fields = React.useMemo<CrudField[]>(() => ([
55
55
  { id: 'displayName', label: t('staff.teamMembers.form.fields.displayName', 'Display name'), type: 'text', required: true },
56
- { id: 'description', label: t('staff.teamMembers.form.fields.description', 'Description'), type: 'richtext', editor: 'uiw' },
56
+ { id: 'description', label: t('staff.teamMembers.form.fields.description', 'Description'), type: 'richtext', editor: 'html' },
57
57
  ]), [t])
58
58
 
59
59
  const handleSubmit = React.useCallback(async (values: SelfProfileValues) => {
@@ -67,7 +67,7 @@ export function TeamForm(props: TeamFormProps) {
67
67
 
68
68
  const fields = React.useMemo<CrudField[]>(() => [
69
69
  { id: 'name', label: t('staff.teams.form.fields.name', 'Name'), type: 'text', required: true },
70
- { id: 'description', label: t('staff.teams.form.fields.description', 'Description'), type: 'richtext' },
70
+ { id: 'description', label: t('staff.teams.form.fields.description', 'Description'), type: 'richtext', editor: 'html' },
71
71
  { id: 'isActive', label: t('staff.teams.form.fields.active', 'Active'), type: 'checkbox' },
72
72
  ], [t])
73
73
 
@@ -343,7 +343,7 @@ export function TeamMemberForm(props: TeamMemberFormProps) {
343
343
  id: 'description',
344
344
  label: translate('staff.teamMembers.form.fields.description', 'Description'),
345
345
  type: 'richtext',
346
- editor: 'uiw',
346
+ editor: 'html',
347
347
  },
348
348
  {
349
349
  id: 'roleIds',
@@ -110,7 +110,7 @@ export function TeamRoleForm(props: TeamRoleFormProps) {
110
110
  }
111
111
  base.push(
112
112
  { id: 'name', label: t('staff.teamRoles.form.fields.name', 'Name'), type: 'text', required: true },
113
- { id: 'description', label: t('staff.teamRoles.form.fields.description', 'Description'), type: 'richtext' },
113
+ { id: 'description', label: t('staff.teamRoles.form.fields.description', 'Description'), type: 'richtext', editor: 'html' },
114
114
  {
115
115
  id: 'appearance',
116
116
  label: t('staff.teamRoles.form.appearance.label', 'Appearance'),