@open-mercato/core 0.6.6-develop.6543.1.49fadb4c31 → 0.6.6-develop.6551.1.1511bfa890
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 +2 -2
- package/dist/generated/entities/gateway_session_initialization/index.js +23 -0
- package/dist/generated/entities/gateway_session_initialization/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +1 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +12 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_keys/api/keys/route.js +7 -4
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentContentPreview.js +6 -35
- package/dist/modules/attachments/components/AttachmentContentPreview.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +14 -24
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/auth/api/autologin.js +85 -0
- package/dist/modules/auth/api/autologin.js.map +7 -0
- package/dist/modules/auth/lib/autologin.js +19 -0
- package/dist/modules/auth/lib/autologin.js.map +7 -0
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js +1 -0
- package/dist/modules/customer_accounts/api/admin/roles/[id]/acl.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/roles/[id].js +17 -3
- package/dist/modules/customer_accounts/api/admin/roles/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +6 -1
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js +6 -1
- package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerInvitationService.js +1 -0
- package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerRbacService.js +6 -1
- package/dist/modules/customer_accounts/services/customerRbacService.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +27 -37
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DealDetailTabs.js +23 -35
- package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DetailTabsLayout.js +6 -21
- package/dist/modules/customers/components/detail/DetailTabsLayout.js.map +2 -2
- package/dist/modules/customers/components/detail/MobilePersonDetail.js +26 -32
- package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +29 -39
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/feature_toggles/api/check/boolean/route.js +0 -14
- package/dist/modules/feature_toggles/api/check/boolean/route.js.map +2 -2
- package/dist/modules/feature_toggles/defaults.json +8 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.js +9 -80
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +45 -0
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +173 -38
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +3 -3
- package/dist/modules/payment_gateways/lib/session-idempotency.js +104 -0
- package/dist/modules/payment_gateways/lib/session-idempotency.js.map +7 -0
- package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js +11 -0
- package/dist/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.js.map +7 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js +16 -14
- package/dist/modules/planner/backend/planner/availability-rulesets/[id]/page.js.map +2 -2
- package/dist/modules/planner/components/AvailabilityRulesEditor.js +18 -30
- package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/[id]/page.js +24 -24
- package/dist/modules/resources/backend/resources/resources/[id]/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/create/page.js +6 -0
- package/dist/modules/sales/backend/sales/channels/create/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/create/page.meta.js +2 -0
- package/dist/modules/sales/backend/sales/channels/create/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +6 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.meta.js +2 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +6 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.meta.js +2 -0
- package/dist/modules/sales/backend/sales/channels/page.meta.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +6 -4
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/components/SalesChannelsDisabledNotice.js +15 -0
- package/dist/modules/sales/components/SalesChannelsDisabledNotice.js.map +7 -0
- package/dist/modules/sales/components/documents/SalesDocumentForm.js +7 -3
- package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +10 -8
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/useSalesChannelsEnabled.js +44 -0
- package/dist/modules/sales/components/useSalesChannelsEnabled.js.map +7 -0
- package/dist/modules/sales/lib/salesChannelsToggle.js +18 -0
- package/dist/modules/sales/lib/salesChannelsToggle.js.map +7 -0
- package/dist/modules/sales/lib/salesChannelsToggleId.js +5 -0
- package/dist/modules/sales/lib/salesChannelsToggleId.js.map +7 -0
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +22 -25
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +12 -14
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +10 -29
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +19 -20
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/dist/modules/sync_excel/lib/parser.js +185 -0
- package/dist/modules/sync_excel/lib/parser.js.map +2 -2
- package/dist/modules/sync_excel/lib/upload-storage.js +20 -1
- package/dist/modules/sync_excel/lib/upload-storage.js.map +2 -2
- package/generated/entities/gateway_session_initialization/index.ts +10 -0
- package/generated/entities.ids.generated.ts +1 -0
- package/generated/entity-fields-registry.ts +12 -0
- package/package.json +7 -7
- package/src/modules/api_keys/api/keys/route.ts +9 -4
- package/src/modules/attachments/components/AttachmentContentPreview.tsx +9 -44
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +12 -22
- package/src/modules/auth/api/autologin.ts +100 -0
- package/src/modules/auth/lib/autologin.ts +36 -0
- package/src/modules/customer_accounts/api/admin/roles/[id]/acl.ts +1 -0
- package/src/modules/customer_accounts/api/admin/roles/[id].ts +17 -3
- package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +6 -1
- package/src/modules/customer_accounts/api/portal/users-invite.ts +6 -1
- package/src/modules/customer_accounts/services/customerInvitationService.ts +1 -0
- package/src/modules/customer_accounts/services/customerRbacService.ts +9 -2
- package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +6 -2
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +27 -49
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +24 -49
- package/src/modules/customers/components/detail/DetailTabsLayout.tsx +13 -24
- package/src/modules/customers/components/detail/MobilePersonDetail.tsx +25 -31
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +29 -50
- package/src/modules/feature_toggles/api/check/boolean/route.ts +0 -15
- package/src/modules/feature_toggles/defaults.json +8 -0
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +16 -59
- package/src/modules/payment_gateways/data/entities.ts +39 -0
- package/src/modules/payment_gateways/lib/gateway-service.ts +211 -40
- package/src/modules/payment_gateways/lib/session-idempotency.ts +142 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +236 -0
- package/src/modules/payment_gateways/migrations/Migration20260709220938_payment_gateways.ts +10 -0
- package/src/modules/planner/backend/planner/availability-rulesets/[id]/page.tsx +14 -20
- package/src/modules/planner/components/AvailabilityRulesEditor.tsx +16 -34
- package/src/modules/resources/backend/resources/resources/[id]/page.tsx +27 -37
- package/src/modules/sales/backend/sales/channels/create/page.meta.ts +3 -0
- package/src/modules/sales/backend/sales/channels/create/page.tsx +7 -0
- package/src/modules/sales/backend/sales/channels/offers/page.meta.ts +3 -0
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +7 -0
- package/src/modules/sales/backend/sales/channels/page.meta.ts +4 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +7 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +7 -5
- package/src/modules/sales/components/SalesChannelsDisabledNotice.tsx +21 -0
- package/src/modules/sales/components/documents/SalesDocumentForm.tsx +7 -3
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +10 -8
- package/src/modules/sales/components/useSalesChannelsEnabled.ts +59 -0
- package/src/modules/sales/i18n/de.json +1 -0
- package/src/modules/sales/i18n/en.json +1 -0
- package/src/modules/sales/i18n/es.json +1 -0
- package/src/modules/sales/i18n/pl.json +1 -0
- package/src/modules/sales/lib/salesChannelsToggle.ts +26 -0
- package/src/modules/sales/lib/salesChannelsToggleId.ts +1 -0
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +25 -34
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +11 -17
- package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +11 -28
- package/src/modules/sync_excel/lib/adapters/customers.ts +20 -22
- package/src/modules/sync_excel/lib/parser.ts +245 -0
- package/src/modules/sync_excel/lib/upload-storage.ts +23 -1
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
|
-
import { cn } from '@open-mercato/shared/lib/utils'
|
|
5
4
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
6
5
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
7
|
-
import {
|
|
6
|
+
import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
|
|
8
7
|
import {
|
|
9
8
|
Users,
|
|
10
9
|
Handshake,
|
|
@@ -28,7 +27,7 @@ type TabDef = {
|
|
|
28
27
|
id: CompanyTabId
|
|
29
28
|
label: string
|
|
30
29
|
icon?: React.ReactNode
|
|
31
|
-
|
|
30
|
+
count?: React.ReactNode
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
type CompanyDetailTabsProps = {
|
|
@@ -59,21 +58,9 @@ export function resolveLegacyTab(tab: string | null | undefined): CompanyTabId {
|
|
|
59
58
|
return tab as CompanyTabId
|
|
60
59
|
}
|
|
61
60
|
|
|
62
|
-
function
|
|
63
|
-
return
|
|
64
|
-
|
|
65
|
-
NEW
|
|
66
|
-
</span>
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function CountBadge({ count }: { count: number }) {
|
|
71
|
-
if (count <= 0) return null
|
|
72
|
-
return (
|
|
73
|
-
<span className="ml-1.5 rounded-full bg-muted px-1.5 py-0.5 text-xs font-medium leading-none text-muted-foreground">
|
|
74
|
-
{count > 999 ? '999+' : count}
|
|
75
|
-
</span>
|
|
76
|
-
)
|
|
61
|
+
function formatTabCount(count: number): string | number | undefined {
|
|
62
|
+
if (count <= 0) return undefined
|
|
63
|
+
return count > 999 ? '999+' : count
|
|
77
64
|
}
|
|
78
65
|
|
|
79
66
|
export function CompanyDetailTabs({
|
|
@@ -96,7 +83,7 @@ export function CompanyDetailTabs({
|
|
|
96
83
|
id: 'people',
|
|
97
84
|
label: t('customers.companies.detail.tabs.people', 'People'),
|
|
98
85
|
icon: <Users className="size-4" />,
|
|
99
|
-
|
|
86
|
+
count: formatTabCount(peopleCount),
|
|
100
87
|
},
|
|
101
88
|
...(canViewDeals
|
|
102
89
|
? [
|
|
@@ -104,7 +91,7 @@ export function CompanyDetailTabs({
|
|
|
104
91
|
id: 'deals' as CompanyTabId,
|
|
105
92
|
label: t('customers.companies.detail.tabs.deals', 'Deals'),
|
|
106
93
|
icon: <Handshake className="size-4" />,
|
|
107
|
-
|
|
94
|
+
count: formatTabCount(dealsCount),
|
|
108
95
|
},
|
|
109
96
|
]
|
|
110
97
|
: []),
|
|
@@ -112,19 +99,19 @@ export function CompanyDetailTabs({
|
|
|
112
99
|
id: 'activity-log',
|
|
113
100
|
label: t('customers.companies.detail.tabs.activityLog', 'Activity log'),
|
|
114
101
|
icon: <Clock className="size-4" />,
|
|
115
|
-
|
|
102
|
+
count: formatTabCount(activitiesCount),
|
|
116
103
|
},
|
|
117
104
|
{
|
|
118
105
|
id: 'changelog',
|
|
119
106
|
label: t('customers.companies.detail.tabs.changelog', 'Changelog'),
|
|
120
107
|
icon: <History className="size-4" />,
|
|
121
|
-
|
|
108
|
+
count: 'NEW',
|
|
122
109
|
},
|
|
123
110
|
{
|
|
124
111
|
id: 'files',
|
|
125
112
|
label: t('customers.companies.detail.tabs.files', 'Files'),
|
|
126
113
|
icon: <Paperclip className="size-4" />,
|
|
127
|
-
|
|
114
|
+
count: formatTabCount(filesCount),
|
|
128
115
|
},
|
|
129
116
|
],
|
|
130
117
|
[t, canViewDeals, peopleCount, dealsCount, activitiesCount, filesCount],
|
|
@@ -144,33 +131,24 @@ export function CompanyDetailTabs({
|
|
|
144
131
|
return (
|
|
145
132
|
<div>
|
|
146
133
|
{/* Tab navigation */}
|
|
147
|
-
<div className="flex items-end justify-between gap-2 border-b"
|
|
148
|
-
<
|
|
149
|
-
{
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
className={cn(
|
|
161
|
-
'h-auto shrink-0 rounded-none border-b-2 px-3 py-2.5 hover:bg-transparent',
|
|
162
|
-
isActive
|
|
163
|
-
? 'border-foreground text-foreground font-semibold'
|
|
164
|
-
: 'border-transparent text-muted-foreground hover:text-foreground',
|
|
165
|
-
)}
|
|
166
|
-
>
|
|
167
|
-
{tab.icon && <span className="mr-1.5">{tab.icon}</span>}
|
|
134
|
+
<div className="flex items-end justify-between gap-2 border-b">
|
|
135
|
+
<Tabs
|
|
136
|
+
value={activeTab}
|
|
137
|
+
onValueChange={(value) => onTabChange(value as CompanyTabId)}
|
|
138
|
+
variant="underline"
|
|
139
|
+
className="min-w-0 flex-1"
|
|
140
|
+
>
|
|
141
|
+
<TabsList
|
|
142
|
+
aria-label={t('customers.companies.detail.tabs.label', 'Company detail sections')}
|
|
143
|
+
className="-mb-px w-full overflow-x-auto border-b-0 px-1"
|
|
144
|
+
>
|
|
145
|
+
{allTabs.map((tab) => (
|
|
146
|
+
<TabsTrigger key={tab.id} value={tab.id} leading={tab.icon} count={tab.count}>
|
|
168
147
|
{tab.label}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
</nav>
|
|
148
|
+
</TabsTrigger>
|
|
149
|
+
))}
|
|
150
|
+
</TabsList>
|
|
151
|
+
</Tabs>
|
|
174
152
|
{sectionAction ? (
|
|
175
153
|
<Button
|
|
176
154
|
type="button"
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { Activity, Building2, History, NotebookPen, Paperclip, Users } from 'lucide-react'
|
|
5
|
-
import { cn } from '@open-mercato/shared/lib/utils'
|
|
6
5
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
7
|
-
import {
|
|
6
|
+
import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
|
|
8
7
|
|
|
9
8
|
export type DealTabId =
|
|
10
9
|
| 'activities'
|
|
@@ -19,7 +18,7 @@ type TabDef = {
|
|
|
19
18
|
id: DealTabId
|
|
20
19
|
label: string
|
|
21
20
|
icon?: React.ReactNode
|
|
22
|
-
|
|
21
|
+
count?: React.ReactNode
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
type DealDetailTabsProps = {
|
|
@@ -38,21 +37,9 @@ export function resolveLegacyTab(tab: string | null | undefined): DealTabId {
|
|
|
38
37
|
return SUPPORTED_TAB_IDS.has(tab as DealTabId) ? (tab as DealTabId) : 'activities'
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
function
|
|
42
|
-
if (count <= 0) return
|
|
43
|
-
return
|
|
44
|
-
<span className="ml-1.5 rounded-sm bg-muted px-1.5 py-px text-xs font-semibold leading-none text-muted-foreground">
|
|
45
|
-
{count > 999 ? '999+' : count}
|
|
46
|
-
</span>
|
|
47
|
-
)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function NewBadge() {
|
|
51
|
-
return (
|
|
52
|
-
<span className="ml-1.5 rounded-sm bg-muted px-1.5 py-px text-xs font-semibold leading-none text-muted-foreground">
|
|
53
|
-
NEW
|
|
54
|
-
</span>
|
|
55
|
-
)
|
|
40
|
+
function formatTabCount(count: number): string | number | undefined {
|
|
41
|
+
if (count <= 0) return undefined
|
|
42
|
+
return count > 999 ? '999+' : count
|
|
56
43
|
}
|
|
57
44
|
|
|
58
45
|
export function DealDetailTabs({
|
|
@@ -76,13 +63,13 @@ export function DealDetailTabs({
|
|
|
76
63
|
id: 'people',
|
|
77
64
|
label: t('customers.deals.detail.tabs.people', 'People'),
|
|
78
65
|
icon: <Users className="size-4" />,
|
|
79
|
-
|
|
66
|
+
count: formatTabCount(peopleCount),
|
|
80
67
|
},
|
|
81
68
|
{
|
|
82
69
|
id: 'companies',
|
|
83
70
|
label: t('customers.deals.detail.tabs.companies', 'Companies'),
|
|
84
71
|
icon: <Building2 className="size-4" />,
|
|
85
|
-
|
|
72
|
+
count: formatTabCount(companiesCount),
|
|
86
73
|
},
|
|
87
74
|
{
|
|
88
75
|
id: 'notes',
|
|
@@ -98,7 +85,7 @@ export function DealDetailTabs({
|
|
|
98
85
|
id: 'changelog',
|
|
99
86
|
label: t('customers.deals.detail.tabs.changelog', 'Changelog'),
|
|
100
87
|
icon: <History className="size-4" />,
|
|
101
|
-
|
|
88
|
+
count: 'NEW',
|
|
102
89
|
},
|
|
103
90
|
],
|
|
104
91
|
[companiesCount, peopleCount, t],
|
|
@@ -117,34 +104,22 @@ export function DealDetailTabs({
|
|
|
117
104
|
|
|
118
105
|
return (
|
|
119
106
|
<div>
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
? 'border-foreground text-foreground font-semibold'
|
|
137
|
-
: 'border-transparent text-muted-foreground hover:text-foreground',
|
|
138
|
-
)}
|
|
139
|
-
>
|
|
140
|
-
{tab.icon ? <span className="mr-1.5">{tab.icon}</span> : null}
|
|
141
|
-
{tab.label}
|
|
142
|
-
{tab.badge}
|
|
143
|
-
</Button>
|
|
144
|
-
)
|
|
145
|
-
})}
|
|
146
|
-
</nav>
|
|
147
|
-
</div>
|
|
107
|
+
<Tabs
|
|
108
|
+
value={activeTab}
|
|
109
|
+
onValueChange={(value) => onTabChange(value as DealTabId)}
|
|
110
|
+
variant="underline"
|
|
111
|
+
>
|
|
112
|
+
<TabsList
|
|
113
|
+
aria-label={t('customers.deals.detail.tabs.label', 'Deal detail sections')}
|
|
114
|
+
className="w-full overflow-x-auto"
|
|
115
|
+
>
|
|
116
|
+
{allTabs.map((tab) => (
|
|
117
|
+
<TabsTrigger key={tab.id} value={tab.id} leading={tab.icon} count={tab.count}>
|
|
118
|
+
{tab.label}
|
|
119
|
+
</TabsTrigger>
|
|
120
|
+
))}
|
|
121
|
+
</TabsList>
|
|
122
|
+
</Tabs>
|
|
148
123
|
|
|
149
124
|
<div className="pt-5" role="tabpanel">
|
|
150
125
|
{children}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import type { SectionAction } from '@open-mercato/ui/backend/detail'
|
|
5
5
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
6
|
+
import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
|
|
6
7
|
import { cn } from '@open-mercato/shared/lib/utils'
|
|
7
8
|
import { Plus } from 'lucide-react'
|
|
8
9
|
|
|
@@ -46,31 +47,19 @@ export function DetailTabsLayout<TId extends string = string>({
|
|
|
46
47
|
return (
|
|
47
48
|
<div className={cn('space-y-4', className)}>
|
|
48
49
|
<div className={cn('flex flex-wrap items-center justify-between gap-3', headerClassName)}>
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
<Tabs
|
|
51
|
+
value={activeTab}
|
|
52
|
+
onValueChange={(value) => handleTabChange(value as TId)}
|
|
53
|
+
variant="underline"
|
|
53
54
|
>
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
key={tab.id}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
onClick={() => handleTabChange(tab.id)}
|
|
63
|
-
className={cn(
|
|
64
|
-
'h-auto rounded-none border-b-2 px-0 py-1',
|
|
65
|
-
activeTab === tab.id
|
|
66
|
-
? 'border-accent-indigo text-foreground hover:bg-transparent'
|
|
67
|
-
: 'border-transparent text-muted-foreground hover:text-foreground hover:bg-transparent'
|
|
68
|
-
)}
|
|
69
|
-
>
|
|
70
|
-
{tab.label}
|
|
71
|
-
</Button>
|
|
72
|
-
))}
|
|
73
|
-
</nav>
|
|
55
|
+
<TabsList className={cn('h-auto flex-wrap border-b-0', navClassName)} aria-label={navAriaLabel}>
|
|
56
|
+
{tabs.map((tab) => (
|
|
57
|
+
<TabsTrigger key={tab.id} value={tab.id}>
|
|
58
|
+
{tab.label}
|
|
59
|
+
</TabsTrigger>
|
|
60
|
+
))}
|
|
61
|
+
</TabsList>
|
|
62
|
+
</Tabs>
|
|
74
63
|
{sectionAction ? (
|
|
75
64
|
<Button
|
|
76
65
|
type="button"
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
import * as React from 'react'
|
|
4
4
|
import { useRouter, useSearchParams } from 'next/navigation'
|
|
5
5
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
6
|
-
import {
|
|
7
|
-
import { Button } from '@open-mercato/ui/primitives/button'
|
|
6
|
+
import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
|
|
8
7
|
|
|
9
8
|
export type MobilePersonZone = 'details' | 'activity'
|
|
10
9
|
|
|
@@ -80,35 +79,30 @@ export function MobilePersonDetail({
|
|
|
80
79
|
|
|
81
80
|
return (
|
|
82
81
|
<div className="space-y-4">
|
|
83
|
-
<div
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
>
|
|
108
|
-
{t(entry.labelKey, entry.fallback)}
|
|
109
|
-
</Button>
|
|
110
|
-
)
|
|
111
|
-
})}
|
|
82
|
+
<div onKeyDown={handleKeyDown}>
|
|
83
|
+
<Tabs
|
|
84
|
+
value={zone}
|
|
85
|
+
onValueChange={(value) => handleZoneChange(value as MobilePersonZone)}
|
|
86
|
+
variant="underline"
|
|
87
|
+
>
|
|
88
|
+
<TabsList
|
|
89
|
+
aria-label={t(
|
|
90
|
+
'customers.people.mobile.zoneSwitcher.ariaLabel',
|
|
91
|
+
'Zone selector',
|
|
92
|
+
)}
|
|
93
|
+
className="w-full"
|
|
94
|
+
>
|
|
95
|
+
{ZONES.map((entry) => (
|
|
96
|
+
<TabsTrigger
|
|
97
|
+
key={entry.id}
|
|
98
|
+
value={entry.id}
|
|
99
|
+
className="flex-1 justify-center"
|
|
100
|
+
>
|
|
101
|
+
{t(entry.labelKey, entry.fallback)}
|
|
102
|
+
</TabsTrigger>
|
|
103
|
+
))}
|
|
104
|
+
</TabsList>
|
|
105
|
+
</Tabs>
|
|
112
106
|
</div>
|
|
113
107
|
<div
|
|
114
108
|
id={`mobile-person-zone-${zone}`}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import * as React from 'react'
|
|
4
|
-
import { cn } from '@open-mercato/shared/lib/utils'
|
|
5
4
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
6
5
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
6
|
+
import { Tabs, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'
|
|
7
7
|
import {
|
|
8
8
|
SquareCheckBig,
|
|
9
9
|
Mail,
|
|
@@ -32,7 +32,7 @@ type TabDef = {
|
|
|
32
32
|
id: PersonTabId
|
|
33
33
|
label: string
|
|
34
34
|
icon?: React.ReactNode
|
|
35
|
-
|
|
35
|
+
count?: React.ReactNode
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
type PersonDetailTabsProps = {
|
|
@@ -56,21 +56,9 @@ export function resolveLegacyTab(tab: string | null | undefined): PersonTabId {
|
|
|
56
56
|
return SUPPORTED_TAB_IDS.has(tab as PersonTabId) ? (tab as PersonTabId) : 'activities'
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function
|
|
60
|
-
if (count <= 0) return
|
|
61
|
-
return
|
|
62
|
-
<span className="ml-1 rounded-full bg-muted px-1.5 py-0.5 text-xs font-medium leading-none text-muted-foreground">
|
|
63
|
-
{count > 999 ? '999+' : count}
|
|
64
|
-
</span>
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function NewBadge() {
|
|
69
|
-
return (
|
|
70
|
-
<span className="ml-1.5 rounded bg-foreground px-1.5 py-0.5 text-overline font-semibold leading-none text-background">
|
|
71
|
-
NEW
|
|
72
|
-
</span>
|
|
73
|
-
)
|
|
59
|
+
function formatTabCount(count: number): string | number | undefined {
|
|
60
|
+
if (count <= 0) return undefined
|
|
61
|
+
return count > 999 ? '999+' : count
|
|
74
62
|
}
|
|
75
63
|
|
|
76
64
|
export function PersonDetailTabs({
|
|
@@ -94,7 +82,7 @@ export function PersonDetailTabs({
|
|
|
94
82
|
id: 'activities',
|
|
95
83
|
label: t('customers.people.detail.tabs.activities', 'Activities'),
|
|
96
84
|
icon: <SquareCheckBig className="size-4" />,
|
|
97
|
-
|
|
85
|
+
count: formatTabCount(activitiesCount),
|
|
98
86
|
},
|
|
99
87
|
{
|
|
100
88
|
id: 'emails',
|
|
@@ -105,37 +93,37 @@ export function PersonDetailTabs({
|
|
|
105
93
|
id: 'deals',
|
|
106
94
|
label: t('customers.people.detail.tabs.deals', 'Deals'),
|
|
107
95
|
icon: <Briefcase className="size-4" />,
|
|
108
|
-
|
|
96
|
+
count: formatTabCount(dealsCount),
|
|
109
97
|
},
|
|
110
98
|
{
|
|
111
99
|
id: 'companies',
|
|
112
100
|
label: t('customers.people.detail.tabs.companies', 'Companies'),
|
|
113
101
|
icon: <Building2 className="size-4" />,
|
|
114
|
-
|
|
102
|
+
count: formatTabCount(companiesCount),
|
|
115
103
|
},
|
|
116
104
|
{
|
|
117
105
|
id: 'addresses',
|
|
118
106
|
label: t('customers.people.detail.tabs.addresses', 'Addresses'),
|
|
119
107
|
icon: <MapPin className="size-4" />,
|
|
120
|
-
|
|
108
|
+
count: formatTabCount(addressesCount),
|
|
121
109
|
},
|
|
122
110
|
{
|
|
123
111
|
id: 'tasks',
|
|
124
112
|
label: t('customers.people.detail.tabs.tasks', 'Tasks'),
|
|
125
113
|
icon: <Check className="size-4" />,
|
|
126
|
-
|
|
114
|
+
count: formatTabCount(tasksCount),
|
|
127
115
|
},
|
|
128
116
|
{
|
|
129
117
|
id: 'changelog',
|
|
130
118
|
label: t('customers.people.detail.tabs.changelog', 'Change log'),
|
|
131
119
|
icon: <History className="size-4" />,
|
|
132
|
-
|
|
120
|
+
count: 'NEW',
|
|
133
121
|
},
|
|
134
122
|
{
|
|
135
123
|
id: 'files',
|
|
136
124
|
label: t('customers.people.detail.tabs.files', 'Files'),
|
|
137
125
|
icon: <Paperclip className="size-4" />,
|
|
138
|
-
|
|
126
|
+
count: formatTabCount(filesCount),
|
|
139
127
|
},
|
|
140
128
|
],
|
|
141
129
|
[t, activitiesCount, dealsCount, companiesCount, addressesCount, tasksCount, filesCount],
|
|
@@ -155,33 +143,24 @@ export function PersonDetailTabs({
|
|
|
155
143
|
return (
|
|
156
144
|
<div>
|
|
157
145
|
{/* Tab navigation — full width above both zones */}
|
|
158
|
-
<div className="flex items-end justify-between gap-2 border-b"
|
|
159
|
-
<
|
|
160
|
-
{
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
className={cn(
|
|
172
|
-
'h-auto shrink-0 rounded-none border-b-2 px-3 py-2.5 hover:bg-transparent',
|
|
173
|
-
isActive
|
|
174
|
-
? 'border-foreground text-foreground font-semibold'
|
|
175
|
-
: 'border-transparent text-muted-foreground hover:text-foreground',
|
|
176
|
-
)}
|
|
177
|
-
>
|
|
178
|
-
{tab.icon && <span className="mr-1.5">{tab.icon}</span>}
|
|
146
|
+
<div className="flex items-end justify-between gap-2 border-b">
|
|
147
|
+
<Tabs
|
|
148
|
+
value={activeTab}
|
|
149
|
+
onValueChange={(value) => onTabChange(value as PersonTabId)}
|
|
150
|
+
variant="underline"
|
|
151
|
+
className="min-w-0 flex-1"
|
|
152
|
+
>
|
|
153
|
+
<TabsList
|
|
154
|
+
aria-label={t('customers.people.detail.tabs.label', 'Person detail sections')}
|
|
155
|
+
className="-mb-px w-full overflow-x-auto border-b-0 px-1"
|
|
156
|
+
>
|
|
157
|
+
{allTabs.map((tab) => (
|
|
158
|
+
<TabsTrigger key={tab.id} value={tab.id} leading={tab.icon} count={tab.count}>
|
|
179
159
|
{tab.label}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
</nav>
|
|
160
|
+
</TabsTrigger>
|
|
161
|
+
))}
|
|
162
|
+
</TabsList>
|
|
163
|
+
</Tabs>
|
|
185
164
|
{sectionAction ? (
|
|
186
165
|
<Button
|
|
187
166
|
type="button"
|
|
@@ -18,21 +18,6 @@ export async function GET(req: Request) {
|
|
|
18
18
|
return NextResponse.json({ error: 'Missing required parameter: identifier' }, { status: 400 })
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
if (auth.isSuperAdmin === true) {
|
|
22
|
-
return NextResponse.json({
|
|
23
|
-
ok: true,
|
|
24
|
-
value: true,
|
|
25
|
-
resolution: {
|
|
26
|
-
valueType: "boolean",
|
|
27
|
-
value: true,
|
|
28
|
-
source: "override",
|
|
29
|
-
toggleId: "superadmin",
|
|
30
|
-
identifier,
|
|
31
|
-
tenantId: "superadmin"
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
|
|
36
21
|
const container = await createRequestContainer()
|
|
37
22
|
const { scope } = await resolveFeatureCheckContext({
|
|
38
23
|
container,
|
|
@@ -16,6 +16,14 @@
|
|
|
16
16
|
"type": "string",
|
|
17
17
|
"defaultValue": "Free shipping on orders over $50"
|
|
18
18
|
},
|
|
19
|
+
{
|
|
20
|
+
"identifier": "sales_channels_enabled",
|
|
21
|
+
"name": "Sales Channels",
|
|
22
|
+
"description": "Show sales channel pickers, filters, and management UI. Disable for tenants that do not use sales channels.",
|
|
23
|
+
"category": "sales",
|
|
24
|
+
"type": "boolean",
|
|
25
|
+
"defaultValue": true
|
|
26
|
+
},
|
|
19
27
|
{
|
|
20
28
|
"identifier": "order_review_threshold",
|
|
21
29
|
"name": "Order Review Threshold",
|