@spree/dashboard-ui 6.0.2 → 6.0.4
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/package.json +20 -19
- package/src/index.ts +5 -0
- package/src/lib/field-trigger.ts +10 -0
- package/src/lib/same-rich-text.ts +12 -3
- package/src/lib/utils.ts +14 -1
- package/src/spree/address-block.tsx +3 -3
- package/src/spree/address-book-row.tsx +88 -0
- package/src/spree/bulk-price-table.tsx +3 -3
- package/src/spree/claim-resolve-dialog.tsx +1 -1
- package/src/spree/collapsible-card.tsx +2 -2
- package/src/spree/color-picker.tsx +1 -1
- package/src/spree/currency-label.tsx +71 -0
- package/src/spree/data-grid/cells.tsx +2 -2
- package/src/spree/data-grid/data-grid.tsx +2 -2
- package/src/spree/delivery-form-dialog.tsx +1 -1
- package/src/spree/drag-handle.tsx +1 -1
- package/src/spree/editable-note-card.tsx +2 -2
- package/src/spree/form-actions.tsx +32 -10
- package/src/spree/fulfill-items-form.tsx +20 -22
- package/src/spree/fulfillment-edit-dialog.tsx +1 -1
- package/src/spree/fulfillment-item-list.tsx +87 -28
- package/src/spree/fulfillment-panel.tsx +2 -2
- package/src/spree/icons.ts +8 -0
- package/src/spree/json-preview-drawer.tsx +32 -7
- package/src/spree/json-value-view.tsx +14 -4
- package/src/spree/label-upload-dialog.tsx +1 -1
- package/src/spree/language-menu-items.tsx +1 -1
- package/src/spree/metadata/metadata-card.tsx +2 -2
- package/src/spree/order-cancel-dialog.tsx +3 -3
- package/src/spree/post-sale-create-dialogs.tsx +36 -33
- package/src/spree/post-sale-fields.tsx +30 -1
- package/src/spree/product-identity.tsx +74 -0
- package/src/spree/product-membership-list.tsx +79 -41
- package/src/spree/products/status-card.tsx +1 -1
- package/src/spree/quantity-tier-editor.tsx +1 -1
- package/src/spree/return-dialogs.tsx +2 -2
- package/src/spree/search-input.tsx +3 -1
- package/src/spree/secret-input.tsx +1 -1
- package/src/spree/section.tsx +55 -0
- package/src/spree/stat-item.tsx +27 -0
- package/src/spree/tax-identifiers-card.tsx +117 -76
- package/src/spree/theme-toggle.tsx +1 -1
- package/src/spree/wizard.tsx +2 -2
- package/src/styles.css +226 -120
- package/src/ui/alert.tsx +20 -17
- package/src/ui/attachment.tsx +1 -1
- package/src/ui/avatar.tsx +2 -2
- package/src/ui/badge.tsx +1 -1
- package/src/ui/breadcrumb.tsx +1 -1
- package/src/ui/button.tsx +14 -11
- package/src/ui/calendar.tsx +2 -2
- package/src/ui/card.tsx +14 -37
- package/src/ui/chart.tsx +1 -1
- package/src/ui/checkbox.tsx +2 -2
- package/src/ui/code-editor.tsx +6 -2
- package/src/ui/collapsible.tsx +21 -2
- package/src/ui/combobox.tsx +12 -16
- package/src/ui/command.tsx +8 -6
- package/src/ui/context-menu.tsx +1 -1
- package/src/ui/data-table.tsx +58 -15
- package/src/ui/date-picker.tsx +3 -3
- package/src/ui/date-range-panel.tsx +102 -0
- package/src/ui/date-range-picker.tsx +33 -72
- package/src/ui/dialog.tsx +3 -3
- package/src/ui/dropdown-menu.tsx +6 -6
- package/src/ui/empty.tsx +3 -3
- package/src/ui/field.tsx +33 -12
- package/src/ui/input-group.tsx +17 -6
- package/src/ui/input.tsx +148 -4
- package/src/ui/item.tsx +7 -4
- package/src/ui/label.tsx +1 -1
- package/src/ui/media-preview.tsx +40 -5
- package/src/ui/pagination.tsx +16 -4
- package/src/ui/progress.tsx +2 -2
- package/src/ui/radio-group.tsx +2 -2
- package/src/ui/rich-text-editor.tsx +3 -3
- package/src/ui/select.tsx +7 -16
- package/src/ui/sheet.tsx +13 -5
- package/src/ui/sidebar.tsx +5 -5
- package/src/ui/switch.tsx +8 -2
- package/src/ui/tabs.tsx +45 -9
- package/src/ui/textarea.tsx +1 -1
- package/src/ui/toast.tsx +2 -2
- package/src/ui/tooltip.tsx +1 -1
|
@@ -5,28 +5,24 @@ import {
|
|
|
5
5
|
Badge,
|
|
6
6
|
Button,
|
|
7
7
|
Card,
|
|
8
|
-
CardAction,
|
|
9
8
|
CardContent,
|
|
10
|
-
CardHeader,
|
|
11
|
-
CardTitle,
|
|
12
9
|
Combobox,
|
|
13
10
|
ComboboxContent,
|
|
14
11
|
ComboboxEmpty,
|
|
15
12
|
ComboboxInput,
|
|
16
13
|
ComboboxItem,
|
|
17
14
|
ComboboxList,
|
|
15
|
+
Empty,
|
|
16
|
+
EmptyHeader,
|
|
17
|
+
EmptyMedia,
|
|
18
|
+
EmptyTitle,
|
|
18
19
|
Field,
|
|
19
20
|
FieldDescription,
|
|
20
21
|
FieldError,
|
|
21
22
|
FieldGroup,
|
|
22
23
|
FieldLabel,
|
|
23
24
|
Input,
|
|
24
|
-
|
|
25
|
-
ItemActions,
|
|
26
|
-
ItemContent,
|
|
27
|
-
ItemDescription,
|
|
28
|
-
ItemGroup,
|
|
29
|
-
ItemTitle,
|
|
25
|
+
InputGroupAddon,
|
|
30
26
|
RelativeTime,
|
|
31
27
|
RowActions,
|
|
32
28
|
Sheet,
|
|
@@ -38,7 +34,10 @@ import {
|
|
|
38
34
|
StatusBadge,
|
|
39
35
|
useConfirm,
|
|
40
36
|
} from '../index'
|
|
41
|
-
import {
|
|
37
|
+
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../ui/data-table'
|
|
38
|
+
import { CountryFlag } from './country-flag'
|
|
39
|
+
import { BadgeCheckIcon, FileTextIcon, PlusIcon } from './icons'
|
|
40
|
+
import { Section, SectionActions, SectionHeader, SectionTitle } from './section'
|
|
42
41
|
|
|
43
42
|
/** One selectable registration kind. */
|
|
44
43
|
interface KindOption {
|
|
@@ -79,6 +78,15 @@ const TAX_IDENTIFIER_DEFAULTS: TaxIdentifierFormValues = { kind: '', value: '' }
|
|
|
79
78
|
*/
|
|
80
79
|
export const TAX_IDENTIFIER_KINDS = ['eu_vat', 'gb_vat', 'ch_vat', 'au_abn', 'us_ein'] as const
|
|
81
80
|
|
|
81
|
+
/**
|
|
82
|
+
* The flag of the registry a kind belongs to: the region code that opens it
|
|
83
|
+
* (`eu_vat` → EU, `gb_vat` → GB), which also covers a plugin's kind named the
|
|
84
|
+
* same way (`nz_gst`). A kind with no such prefix gets no flag.
|
|
85
|
+
*/
|
|
86
|
+
export function taxIdentifierKindFlag(kind: string): string | null {
|
|
87
|
+
return /^([a-z]{2})_/.exec(kind)?.[1] ?? null
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
/**
|
|
83
91
|
* Mutations differ by owner (a company's registrations hang off the company,
|
|
84
92
|
* a customer's off the customer) while the panel itself does not — so the
|
|
@@ -131,43 +139,64 @@ export function TaxIdentifiersCard({
|
|
|
131
139
|
}
|
|
132
140
|
|
|
133
141
|
return (
|
|
134
|
-
<
|
|
135
|
-
<
|
|
136
|
-
<
|
|
142
|
+
<Section>
|
|
143
|
+
<SectionHeader>
|
|
144
|
+
<SectionTitle>
|
|
145
|
+
<FileTextIcon />
|
|
137
146
|
{t('admin.tax_identifiers.title')}
|
|
138
147
|
{identifiers.length > 0 && <Badge variant="outline">{identifiers.length}</Badge>}
|
|
139
|
-
</
|
|
148
|
+
</SectionTitle>
|
|
140
149
|
{canEdit && (
|
|
141
|
-
<
|
|
150
|
+
<SectionActions>
|
|
142
151
|
<Button size="sm" variant="outline" onClick={() => setAddOpen(true)}>
|
|
143
152
|
<PlusIcon className="size-4" />
|
|
144
153
|
{t('admin.tax_identifiers.add_cta')}
|
|
145
154
|
</Button>
|
|
146
|
-
</
|
|
155
|
+
</SectionActions>
|
|
147
156
|
)}
|
|
148
|
-
</
|
|
157
|
+
</SectionHeader>
|
|
149
158
|
|
|
150
|
-
{isLoading ? (
|
|
151
|
-
<
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
159
|
+
{isLoading || identifiers.length === 0 ? (
|
|
160
|
+
<Card>
|
|
161
|
+
<CardContent>
|
|
162
|
+
{isLoading ? (
|
|
163
|
+
<p className="text-muted-foreground text-base">{t('admin.common.loading')}</p>
|
|
164
|
+
) : (
|
|
165
|
+
<Empty className="p-4">
|
|
166
|
+
<EmptyHeader>
|
|
167
|
+
<EmptyMedia variant="icon">
|
|
168
|
+
<FileTextIcon />
|
|
169
|
+
</EmptyMedia>
|
|
170
|
+
<EmptyTitle>{t('admin.tax_identifiers.empty')}</EmptyTitle>
|
|
171
|
+
</EmptyHeader>
|
|
172
|
+
</Empty>
|
|
173
|
+
)}
|
|
174
|
+
</CardContent>
|
|
175
|
+
</Card>
|
|
158
176
|
) : (
|
|
159
|
-
<
|
|
160
|
-
<
|
|
161
|
-
|
|
162
|
-
<
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
177
|
+
<Card>
|
|
178
|
+
<Table roundedTop>
|
|
179
|
+
<TableHeader>
|
|
180
|
+
<TableRow>
|
|
181
|
+
<TableHead>{t('admin.fields.tax_identifier.value.label')}</TableHead>
|
|
182
|
+
<TableHead>{t('admin.fields.tax_identifier.kind.label')}</TableHead>
|
|
183
|
+
<TableHead>{t('admin.fields.status.label')}</TableHead>
|
|
184
|
+
{canEdit && <TableHead className="w-10" />}
|
|
185
|
+
</TableRow>
|
|
186
|
+
</TableHeader>
|
|
187
|
+
<TableBody>
|
|
188
|
+
{identifiers.map((identifier) => (
|
|
189
|
+
<TableRow key={identifier.id}>
|
|
190
|
+
<TableCell className="font-medium tabular-nums">{identifier.value}</TableCell>
|
|
191
|
+
<TableCell>
|
|
192
|
+
<span className="inline-flex items-center gap-2 whitespace-nowrap">
|
|
193
|
+
<TaxIdentifierKindFlag kind={identifier.kind} />
|
|
167
194
|
{t(`admin.tax_identifiers.kinds.${identifier.kind}`, {
|
|
168
195
|
defaultValue: identifier.kind,
|
|
169
196
|
})}
|
|
170
|
-
</
|
|
197
|
+
</span>
|
|
198
|
+
</TableCell>
|
|
199
|
+
<TableCell>
|
|
171
200
|
{identifier.validation_status ? (
|
|
172
201
|
<StatusBadge
|
|
173
202
|
status={identifier.validation_status}
|
|
@@ -181,47 +210,47 @@ export function TaxIdentifiersCard({
|
|
|
181
210
|
{t('admin.tax_identifiers.validation_status.not_checked')}
|
|
182
211
|
</Badge>
|
|
183
212
|
)}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
213
|
+
{identifier.validated_at && (
|
|
214
|
+
<div className="text-muted-foreground text-xs">
|
|
215
|
+
<RelativeTime
|
|
216
|
+
iso={identifier.validated_at}
|
|
217
|
+
prefix={t('admin.tax_identifiers.checked_prefix')}
|
|
218
|
+
/>
|
|
219
|
+
</div>
|
|
220
|
+
)}
|
|
221
|
+
{!identifier.validatable && (
|
|
222
|
+
<div className="text-muted-foreground text-xs">
|
|
223
|
+
{t('admin.tax_identifiers.not_validatable')}
|
|
224
|
+
</div>
|
|
225
|
+
)}
|
|
226
|
+
</TableCell>
|
|
227
|
+
{canEdit && (
|
|
228
|
+
<TableCell className="w-10 text-right">
|
|
229
|
+
<RowActions
|
|
230
|
+
actions={[
|
|
231
|
+
{
|
|
232
|
+
key: 'validate',
|
|
233
|
+
label: t('admin.tax_identifiers.validate_action'),
|
|
234
|
+
icon: <BadgeCheckIcon className="size-4" />,
|
|
235
|
+
disabled: !identifier.validatable || mutations.isValidating,
|
|
236
|
+
onSelect: () =>
|
|
237
|
+
mutations.validate(identifier.id).catch(() => undefined),
|
|
238
|
+
},
|
|
239
|
+
{ key: 'edit', onSelect: () => setEditing(identifier) },
|
|
240
|
+
{
|
|
241
|
+
key: 'delete',
|
|
242
|
+
destructive: true,
|
|
243
|
+
onSelect: () => handleDelete(identifier),
|
|
244
|
+
},
|
|
245
|
+
]}
|
|
190
246
|
/>
|
|
191
|
-
</
|
|
192
|
-
)}
|
|
193
|
-
{!identifier.validatable && (
|
|
194
|
-
<ItemDescription className="text-xs">
|
|
195
|
-
{t('admin.tax_identifiers.not_validatable')}
|
|
196
|
-
</ItemDescription>
|
|
247
|
+
</TableCell>
|
|
197
248
|
)}
|
|
198
|
-
</
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
actions={[
|
|
204
|
-
{
|
|
205
|
-
key: 'validate',
|
|
206
|
-
label: t('admin.tax_identifiers.validate_action'),
|
|
207
|
-
icon: <BadgeCheckIcon className="size-4" />,
|
|
208
|
-
disabled: !identifier.validatable || mutations.isValidating,
|
|
209
|
-
onSelect: () => mutations.validate(identifier.id).catch(() => undefined),
|
|
210
|
-
},
|
|
211
|
-
{ key: 'edit', onSelect: () => setEditing(identifier) },
|
|
212
|
-
{
|
|
213
|
-
key: 'delete',
|
|
214
|
-
destructive: true,
|
|
215
|
-
onSelect: () => handleDelete(identifier),
|
|
216
|
-
},
|
|
217
|
-
]}
|
|
218
|
-
/>
|
|
219
|
-
</ItemActions>
|
|
220
|
-
)}
|
|
221
|
-
</Item>
|
|
222
|
-
))}
|
|
223
|
-
</ItemGroup>
|
|
224
|
-
</CardContent>
|
|
249
|
+
</TableRow>
|
|
250
|
+
))}
|
|
251
|
+
</TableBody>
|
|
252
|
+
</Table>
|
|
253
|
+
</Card>
|
|
225
254
|
)}
|
|
226
255
|
|
|
227
256
|
{addOpen && (
|
|
@@ -243,7 +272,7 @@ export function TaxIdentifiersCard({
|
|
|
243
272
|
onSubmit={(params) => mutations.update(editing.id, params)}
|
|
244
273
|
/>
|
|
245
274
|
)}
|
|
246
|
-
</
|
|
275
|
+
</Section>
|
|
247
276
|
)
|
|
248
277
|
}
|
|
249
278
|
|
|
@@ -311,7 +340,7 @@ function TaxIdentifierSheet({
|
|
|
311
340
|
<div className="flex flex-1 flex-col gap-4 overflow-y-auto p-4">
|
|
312
341
|
<FieldGroup>
|
|
313
342
|
{errors.root?.message && !rootIsRepeated && (
|
|
314
|
-
<p className="text-destructive text-
|
|
343
|
+
<p className="text-destructive text-base" role="alert">
|
|
315
344
|
{errors.root.message}
|
|
316
345
|
</p>
|
|
317
346
|
)}
|
|
@@ -356,12 +385,19 @@ function TaxIdentifierSheet({
|
|
|
356
385
|
<ComboboxInput
|
|
357
386
|
id="tax-identifier-kind"
|
|
358
387
|
placeholder={t('admin.tax_identifiers.select_kind')}
|
|
359
|
-
|
|
388
|
+
>
|
|
389
|
+
{field.value && taxIdentifierKindFlag(field.value) && (
|
|
390
|
+
<InputGroupAddon align="inline-start">
|
|
391
|
+
<TaxIdentifierKindFlag kind={field.value} />
|
|
392
|
+
</InputGroupAddon>
|
|
393
|
+
)}
|
|
394
|
+
</ComboboxInput>
|
|
360
395
|
<ComboboxContent>
|
|
361
396
|
<ComboboxEmpty>{t('admin.common.no_results')}</ComboboxEmpty>
|
|
362
397
|
<ComboboxList>
|
|
363
398
|
{(option: KindOption) => (
|
|
364
399
|
<ComboboxItem key={option.value} value={option}>
|
|
400
|
+
<TaxIdentifierKindFlag kind={option.value} />
|
|
365
401
|
{option.label}
|
|
366
402
|
</ComboboxItem>
|
|
367
403
|
)}
|
|
@@ -409,3 +445,8 @@ function TaxIdentifierSheet({
|
|
|
409
445
|
</Sheet>
|
|
410
446
|
)
|
|
411
447
|
}
|
|
448
|
+
|
|
449
|
+
function TaxIdentifierKindFlag({ kind }: { kind: string }) {
|
|
450
|
+
const iso = taxIdentifierKindFlag(kind)
|
|
451
|
+
return iso ? <CountryFlag iso={iso} /> : null
|
|
452
|
+
}
|
|
@@ -21,7 +21,7 @@ export function ThemeMenuItems() {
|
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<div className="flex items-center justify-between gap-2 px-2.5 py-1.5">
|
|
24
|
-
<span className="text-
|
|
24
|
+
<span className="text-base text-foreground">{t('admin.components.theme_toggle.label')}</span>
|
|
25
25
|
<div className="flex items-center gap-0.5 rounded-lg border border-border bg-muted/40 p-0.5">
|
|
26
26
|
{OPTIONS.map(({ value, icon: Icon, labelKey }) => {
|
|
27
27
|
const active = mode === value
|
package/src/spree/wizard.tsx
CHANGED
|
@@ -84,7 +84,7 @@ export function WizardProgress({ steps, current, onStepSelect, className }: Wiza
|
|
|
84
84
|
tabIndex={navigable ? undefined : -1}
|
|
85
85
|
aria-current={state === 'current' ? 'step' : undefined}
|
|
86
86
|
className={cn(
|
|
87
|
-
'min-w-0 pb-7 text-left text-
|
|
87
|
+
'min-w-0 pb-7 text-left text-base leading-none',
|
|
88
88
|
navigable && 'cursor-pointer hover:text-foreground',
|
|
89
89
|
state === 'current' ? 'font-medium text-foreground' : 'text-muted-foreground',
|
|
90
90
|
last && 'pb-0',
|
|
@@ -195,7 +195,7 @@ export function Wizard({
|
|
|
195
195
|
{subtitle ? (
|
|
196
196
|
<>
|
|
197
197
|
<span aria-hidden className="h-4 w-px shrink-0 bg-border" />
|
|
198
|
-
<span className="truncate text-muted-foreground text-
|
|
198
|
+
<span className="truncate text-muted-foreground text-base">{subtitle}</span>
|
|
199
199
|
</>
|
|
200
200
|
) : null}
|
|
201
201
|
</div>
|