@base44/app-plugin-commerce 0.7.1 → 0.8.0
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/README.md +4 -10
- package/base44/entities/commerce.ProductReview.jsonc +2 -2
- package/base44/functions/commerce/storefront-catalog/entry.ts +7 -3
- package/package.json +1 -1
- package/scripts/install.js +2 -4
- package/skills/commerce/SKILL.md +9 -3
- package/skills/commerce/docs/api-storefront.md +3 -3
- package/skills/commerce/install/01-install.md +8 -24
- package/skills/commerce/install/02-storefront.md +21 -9
- package/skills/commerce/references/admin-localization.md +95 -0
- package/skills/commerce/references/reviews.md +7 -6
- package/src/commerce/admin/README.md +36 -14
- package/src/commerce/admin/bot/StoreAdminBot.jsx +12 -11
- package/src/commerce/admin/components/AddressForm.jsx +13 -12
- package/src/commerce/admin/components/ConfirmDialog.jsx +5 -4
- package/src/commerce/admin/components/CountrySelect.jsx +12 -8
- package/src/commerce/admin/components/DataTable.jsx +3 -2
- package/src/commerce/admin/components/DateRangePicker.jsx +11 -10
- package/src/commerce/admin/components/EmptyState.jsx +2 -1
- package/src/commerce/admin/components/MediaUploader.jsx +3 -2
- package/src/commerce/admin/components/MetaDataEditor.jsx +4 -3
- package/src/commerce/admin/components/SearchSelect.jsx +4 -3
- package/src/commerce/admin/context/SettingsContext.jsx +12 -25
- package/src/commerce/admin/hooks/useMoney.js +3 -2
- package/src/commerce/admin/i18n/index.js +54 -0
- package/src/commerce/admin/i18n/locales/de.js +896 -0
- package/src/commerce/admin/i18n/locales/en.js +900 -0
- package/src/commerce/admin/i18n/locales/es.js +896 -0
- package/src/commerce/admin/i18n/locales/fr.js +896 -0
- package/src/commerce/admin/i18n/locales/ja.js +896 -0
- package/src/commerce/admin/i18n/locales/pt.js +896 -0
- package/src/commerce/admin/index.jsx +6 -30
- package/src/commerce/admin/layout/AccessDenied.jsx +8 -9
- package/src/commerce/admin/layout/AuthGuard.jsx +2 -1
- package/src/commerce/admin/layout/Sidebar.jsx +29 -18
- package/src/commerce/admin/layout/Topbar.jsx +4 -3
- package/src/commerce/admin/lib/api.js +3 -2
- package/src/commerce/admin/lib/constants.js +44 -43
- package/src/commerce/admin/lib/format.js +4 -3
- package/src/commerce/admin/lib/paths.js +2 -3
- package/src/commerce/admin/pages/Dashboard.jsx +25 -24
- package/src/commerce/admin/pages/coupons/CouponEditor.jsx +55 -57
- package/src/commerce/admin/pages/coupons/CouponsList.jsx +22 -21
- package/src/commerce/admin/pages/customers/CustomerEditor.jsx +31 -30
- package/src/commerce/admin/pages/customers/CustomersList.jsx +19 -18
- package/src/commerce/admin/pages/orders/OrderEditor.jsx +75 -71
- package/src/commerce/admin/pages/orders/OrdersList.jsx +16 -15
- package/src/commerce/admin/pages/orders/components/AddProductDialog.jsx +12 -11
- package/src/commerce/admin/pages/orders/components/DownloadPermissionsPanel.jsx +14 -13
- package/src/commerce/admin/pages/orders/components/LineItemsTable.jsx +12 -11
- package/src/commerce/admin/pages/orders/components/OrderNotesPanel.jsx +11 -10
- package/src/commerce/admin/pages/orders/components/PaymentPanel.jsx +22 -22
- package/src/commerce/admin/pages/orders/components/RefundPanel.jsx +18 -17
- package/src/commerce/admin/pages/orders/components/TotalsBox.jsx +18 -17
- package/src/commerce/admin/pages/products/Categories.jsx +14 -13
- package/src/commerce/admin/pages/products/ProductEditor.jsx +16 -15
- package/src/commerce/admin/pages/products/ProductsList.jsx +41 -36
- package/src/commerce/admin/pages/products/Reviews.jsx +54 -46
- package/src/commerce/admin/pages/products/components/AttributesSection.jsx +45 -39
- package/src/commerce/admin/pages/products/components/ProductDataPanel.jsx +8 -7
- package/src/commerce/admin/pages/products/components/PublishBox.jsx +10 -9
- package/src/commerce/admin/pages/products/components/TaxonomyPanel.jsx +18 -17
- package/src/commerce/admin/pages/products/components/tabs/DownloadsTab.jsx +11 -10
- package/src/commerce/admin/pages/products/components/tabs/LinkedTab.jsx +9 -10
- package/src/commerce/admin/pages/products/components/tabs/ModifiersTab.jsx +3 -9
- package/src/commerce/admin/pages/products/components/tabs/PriceInventoryTab.jsx +76 -78
- package/src/commerce/admin/pages/reports/Reports.jsx +33 -32
- package/src/commerce/admin/pages/settings/EmailsSettings.jsx +36 -39
- package/src/commerce/admin/pages/settings/GeneralSettings.jsx +13 -14
- package/src/commerce/admin/pages/settings/InventorySettings.jsx +12 -13
- package/src/commerce/admin/pages/settings/LocationEditor.jsx +48 -47
- package/src/commerce/admin/pages/settings/PaymentsSettings.jsx +32 -33
- package/src/commerce/admin/pages/settings/SettingsLayout.jsx +13 -12
- package/src/commerce/admin/pages/settings/ShippingTaxSettings.jsx +31 -31
- package/src/commerce/admin/pages/settings/useGroupForm.jsx +4 -3
- package/src/commerce/admin/pages/status/WebhookEditor.jsx +34 -31
- package/src/commerce/admin/pages/status/Webhooks.jsx +11 -10
- package/src/commerce/admin/routes.jsx +31 -43
- package/src/commerce/storefront/pickers.jsx +19 -5
- package/src/commerce/storefront/useCheckout.jsx +28 -3
- package/src/commerce/utils/storefront.js +49 -2
|
@@ -10,6 +10,7 @@ import { Separator } from "@/components/ui/separator";
|
|
|
10
10
|
import { Copy, Loader2, RefreshCw } from "lucide-react";
|
|
11
11
|
|
|
12
12
|
import { call, base44 } from "../../lib/api";
|
|
13
|
+
import { t } from "../../i18n";
|
|
13
14
|
import { formatDate } from "../../lib/format";
|
|
14
15
|
import { round2 } from "../../lib/order-utils";
|
|
15
16
|
import useMoney from "../../hooks/useMoney";
|
|
@@ -71,17 +72,17 @@ export default function CustomerEditor() {
|
|
|
71
72
|
|
|
72
73
|
const save = async () => {
|
|
73
74
|
if (!customer.email?.trim()) {
|
|
74
|
-
toast.error("
|
|
75
|
+
toast.error(t("customers.email_required"));
|
|
75
76
|
return;
|
|
76
77
|
}
|
|
77
78
|
setSaving(true);
|
|
78
79
|
try {
|
|
79
80
|
const saved = await call("admin-customers", "save", { customer });
|
|
80
|
-
toast.success("
|
|
81
|
+
toast.success(t("customers.saved"));
|
|
81
82
|
if (isNew && sendInvite && saved?.email) {
|
|
82
83
|
try {
|
|
83
84
|
await call("admin-customers", "invite", { email: saved.email });
|
|
84
|
-
toast.success("
|
|
85
|
+
toast.success(t("customers.invite_sent"));
|
|
85
86
|
} catch {
|
|
86
87
|
/* toast shown by call() */
|
|
87
88
|
}
|
|
@@ -99,7 +100,7 @@ export default function CustomerEditor() {
|
|
|
99
100
|
setRecalculating(true);
|
|
100
101
|
try {
|
|
101
102
|
const updated = await call("admin-customers", "recalculate-stats", { id });
|
|
102
|
-
toast.success("
|
|
103
|
+
toast.success(t("customers.stats_recalculated"));
|
|
103
104
|
if (updated) setCustomer((c) => ({ ...c, ...updated }));
|
|
104
105
|
} catch {
|
|
105
106
|
/* toast shown by call() */
|
|
@@ -112,7 +113,7 @@ export default function CustomerEditor() {
|
|
|
112
113
|
setDeleting(true);
|
|
113
114
|
try {
|
|
114
115
|
await call("admin-customers", "delete", { id, reassign_orders_to_guest: true });
|
|
115
|
-
toast.success("
|
|
116
|
+
toast.success(t("customers.deleted"));
|
|
116
117
|
navigate(href("customers"));
|
|
117
118
|
} catch {
|
|
118
119
|
setDeleting(false);
|
|
@@ -134,7 +135,7 @@ export default function CustomerEditor() {
|
|
|
134
135
|
return (
|
|
135
136
|
<div>
|
|
136
137
|
<PageHeader
|
|
137
|
-
title={isNew ? "
|
|
138
|
+
title={isNew ? t("routes.customers_new") : name || customer.email}
|
|
138
139
|
backHref={href("customers")}
|
|
139
140
|
actions={
|
|
140
141
|
<>
|
|
@@ -144,12 +145,12 @@ export default function CustomerEditor() {
|
|
|
144
145
|
className="text-destructive hover:text-destructive"
|
|
145
146
|
onClick={() => setConfirmDelete(true)}
|
|
146
147
|
>
|
|
147
|
-
|
|
148
|
+
{t("common.delete")}
|
|
148
149
|
</Button>
|
|
149
150
|
)}
|
|
150
151
|
<Button onClick={save} disabled={saving}>
|
|
151
152
|
{saving && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
|
152
|
-
{isNew ? "
|
|
153
|
+
{isNew ? t("customers.create") : t("customers.save")}
|
|
153
154
|
</Button>
|
|
154
155
|
</>
|
|
155
156
|
}
|
|
@@ -160,29 +161,29 @@ export default function CustomerEditor() {
|
|
|
160
161
|
<div className="space-y-4">
|
|
161
162
|
<Card>
|
|
162
163
|
<CardHeader className="pb-3">
|
|
163
|
-
<CardTitle className="text-base">
|
|
164
|
+
<CardTitle className="text-base">{t("customers.account")}</CardTitle>
|
|
164
165
|
</CardHeader>
|
|
165
166
|
<CardContent className="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
|
166
167
|
<div className="grid gap-1.5 sm:col-span-2">
|
|
167
|
-
<Label>
|
|
168
|
+
<Label>{t("customers.email_address_required")}</Label>
|
|
168
169
|
<Input type="email" value={customer.email} onChange={setInput("email")} />
|
|
169
170
|
</div>
|
|
170
171
|
<div className="grid gap-1.5">
|
|
171
|
-
<Label>
|
|
172
|
+
<Label>{t("address.first_name")}</Label>
|
|
172
173
|
<Input value={customer.first_name || ""} onChange={setInput("first_name")} />
|
|
173
174
|
</div>
|
|
174
175
|
<div className="grid gap-1.5">
|
|
175
|
-
<Label>
|
|
176
|
+
<Label>{t("address.last_name")}</Label>
|
|
176
177
|
<Input value={customer.last_name || ""} onChange={setInput("last_name")} />
|
|
177
178
|
</div>
|
|
178
179
|
<div className="grid gap-1.5 sm:col-span-2">
|
|
179
|
-
<Label>
|
|
180
|
+
<Label>{t("customers.username")}</Label>
|
|
180
181
|
<Input value={customer.username || ""} onChange={setInput("username")} />
|
|
181
182
|
</div>
|
|
182
183
|
{isNew && (
|
|
183
184
|
<label className="flex items-center gap-2 text-sm sm:col-span-2">
|
|
184
185
|
<Checkbox checked={sendInvite} onCheckedChange={(v) => setSendInvite(!!v)} />
|
|
185
|
-
|
|
186
|
+
{t("customers.send_invite")}
|
|
186
187
|
</label>
|
|
187
188
|
)}
|
|
188
189
|
</CardContent>
|
|
@@ -190,7 +191,7 @@ export default function CustomerEditor() {
|
|
|
190
191
|
|
|
191
192
|
<Card>
|
|
192
193
|
<CardHeader className="pb-3">
|
|
193
|
-
<CardTitle className="text-base">
|
|
194
|
+
<CardTitle className="text-base">{t("customers.billing_address")}</CardTitle>
|
|
194
195
|
</CardHeader>
|
|
195
196
|
<CardContent>
|
|
196
197
|
<AddressForm
|
|
@@ -204,7 +205,7 @@ export default function CustomerEditor() {
|
|
|
204
205
|
|
|
205
206
|
<Card>
|
|
206
207
|
<CardHeader className="flex-row items-center justify-between space-y-0 pb-3">
|
|
207
|
-
<CardTitle className="text-base">
|
|
208
|
+
<CardTitle className="text-base">{t("customers.shipping_address")}</CardTitle>
|
|
208
209
|
<Button
|
|
209
210
|
type="button"
|
|
210
211
|
variant="outline"
|
|
@@ -212,10 +213,10 @@ export default function CustomerEditor() {
|
|
|
212
213
|
onClick={() => {
|
|
213
214
|
const { email: _email, ...rest } = customer.billing || {};
|
|
214
215
|
set("shipping")(rest);
|
|
215
|
-
toast.success("
|
|
216
|
+
toast.success(t("customers.copied_from_billing"));
|
|
216
217
|
}}
|
|
217
218
|
>
|
|
218
|
-
<Copy className="mr-1 h-4 w-4" />
|
|
219
|
+
<Copy className="mr-1 h-4 w-4" /> {t("customers.copy_from_billing")}
|
|
219
220
|
</Button>
|
|
220
221
|
</CardHeader>
|
|
221
222
|
<CardContent>
|
|
@@ -230,7 +231,7 @@ export default function CustomerEditor() {
|
|
|
230
231
|
|
|
231
232
|
<Card>
|
|
232
233
|
<CardHeader className="pb-3">
|
|
233
|
-
<CardTitle className="text-base">
|
|
234
|
+
<CardTitle className="text-base">{t("customers.custom_fields")}</CardTitle>
|
|
234
235
|
</CardHeader>
|
|
235
236
|
<CardContent>
|
|
236
237
|
<MetaDataEditor value={customer.meta_data || []} onChange={set("meta_data")} />
|
|
@@ -243,7 +244,7 @@ export default function CustomerEditor() {
|
|
|
243
244
|
<div className="space-y-4">
|
|
244
245
|
<Card>
|
|
245
246
|
<CardHeader className="flex-row items-center justify-between space-y-0 pb-3">
|
|
246
|
-
<CardTitle className="text-base">
|
|
247
|
+
<CardTitle className="text-base">{t("customers.stats")}</CardTitle>
|
|
247
248
|
<Button
|
|
248
249
|
variant="ghost"
|
|
249
250
|
size="sm"
|
|
@@ -252,35 +253,35 @@ export default function CustomerEditor() {
|
|
|
252
253
|
disabled={recalculating}
|
|
253
254
|
>
|
|
254
255
|
<RefreshCw className={`mr-1 h-3.5 w-3.5 ${recalculating ? "animate-spin" : ""}`} />
|
|
255
|
-
|
|
256
|
+
{t("customers.recalculate")}
|
|
256
257
|
</Button>
|
|
257
258
|
</CardHeader>
|
|
258
259
|
<CardContent className="space-y-2 text-sm">
|
|
259
260
|
<div className="flex justify-between">
|
|
260
|
-
<span className="text-muted-foreground">
|
|
261
|
+
<span className="text-muted-foreground">{t("customers.total_spend")}</span>
|
|
261
262
|
<span className="font-medium">{money.format(customer.total_spent ?? 0)}</span>
|
|
262
263
|
</div>
|
|
263
264
|
<div className="flex justify-between">
|
|
264
|
-
<span className="text-muted-foreground">
|
|
265
|
+
<span className="text-muted-foreground">{t("routes.orders")}</span>
|
|
265
266
|
<span className="font-medium">{customer.orders_count ?? 0}</span>
|
|
266
267
|
</div>
|
|
267
268
|
<div className="flex justify-between">
|
|
268
|
-
<span className="text-muted-foreground">
|
|
269
|
+
<span className="text-muted-foreground">{t("customers.average_order_value")}</span>
|
|
269
270
|
<span className="font-medium">{money.format(aov)}</span>
|
|
270
271
|
</div>
|
|
271
272
|
{customer.is_paying_customer && (
|
|
272
|
-
<p className="pt-1 text-xs text-muted-foreground">
|
|
273
|
+
<p className="pt-1 text-xs text-muted-foreground">{t("customers.paying_customer")}</p>
|
|
273
274
|
)}
|
|
274
275
|
</CardContent>
|
|
275
276
|
</Card>
|
|
276
277
|
|
|
277
278
|
<Card>
|
|
278
279
|
<CardHeader className="pb-3">
|
|
279
|
-
<CardTitle className="text-base">
|
|
280
|
+
<CardTitle className="text-base">{t("customers.recent_orders")}</CardTitle>
|
|
280
281
|
</CardHeader>
|
|
281
282
|
<CardContent className="space-y-1">
|
|
282
283
|
{recentOrders.length === 0 && (
|
|
283
|
-
<p className="text-sm text-muted-foreground">
|
|
284
|
+
<p className="text-sm text-muted-foreground">{t("customers.no_orders_yet")}</p>
|
|
284
285
|
)}
|
|
285
286
|
{recentOrders.map((o) => (
|
|
286
287
|
<div key={o.id}>
|
|
@@ -307,9 +308,9 @@ export default function CustomerEditor() {
|
|
|
307
308
|
<ConfirmDialog
|
|
308
309
|
open={confirmDelete}
|
|
309
310
|
onOpenChange={setConfirmDelete}
|
|
310
|
-
title="
|
|
311
|
-
description="
|
|
312
|
-
confirmLabel="
|
|
311
|
+
title={t("customers.confirm_delete_title")}
|
|
312
|
+
description={t("customers.confirm_delete_description")}
|
|
313
|
+
confirmLabel={t("common.delete")}
|
|
313
314
|
loading={deleting}
|
|
314
315
|
onConfirm={doDelete}
|
|
315
316
|
/>
|
|
@@ -6,6 +6,7 @@ import { Input } from "@/components/ui/input";
|
|
|
6
6
|
import { Plus, Search, Users, Trash2, Pencil } from "lucide-react";
|
|
7
7
|
|
|
8
8
|
import { call, base44 } from "../../lib/api";
|
|
9
|
+
import { t } from "../../i18n";
|
|
9
10
|
import { countryName } from "../../lib/geo-data";
|
|
10
11
|
import usePagedList from "../../hooks/usePagedList";
|
|
11
12
|
import useDebounce from "../../hooks/useDebounce";
|
|
@@ -46,7 +47,7 @@ export default function CustomersList() {
|
|
|
46
47
|
id: pendingDelete.id,
|
|
47
48
|
reassign_orders_to_guest: true,
|
|
48
49
|
});
|
|
49
|
-
toast.success("
|
|
50
|
+
toast.success(t("customers.deleted"));
|
|
50
51
|
setPendingDelete(null);
|
|
51
52
|
list.refetch();
|
|
52
53
|
} catch {
|
|
@@ -59,7 +60,7 @@ export default function CustomersList() {
|
|
|
59
60
|
const columns = [
|
|
60
61
|
{
|
|
61
62
|
key: "name",
|
|
62
|
-
label: "
|
|
63
|
+
label: t("common.name"),
|
|
63
64
|
render: (c) => {
|
|
64
65
|
const name = [c.first_name, c.last_name].filter(Boolean).join(" ");
|
|
65
66
|
return (
|
|
@@ -71,7 +72,7 @@ export default function CustomersList() {
|
|
|
71
72
|
{name || c.email}
|
|
72
73
|
{c.is_guest && (
|
|
73
74
|
<span className="ml-2 rounded bg-muted px-1.5 py-0.5 text-[10px] uppercase text-muted-foreground">
|
|
74
|
-
|
|
75
|
+
{t("customers.guest_badge")}
|
|
75
76
|
</span>
|
|
76
77
|
)}
|
|
77
78
|
</Link>
|
|
@@ -80,7 +81,7 @@ export default function CustomersList() {
|
|
|
80
81
|
},
|
|
81
82
|
{
|
|
82
83
|
key: "email",
|
|
83
|
-
label: "
|
|
84
|
+
label: t("customers.email_username"),
|
|
84
85
|
render: (c) => (
|
|
85
86
|
<div className="min-w-0">
|
|
86
87
|
<div className="truncate">{c.email}</div>
|
|
@@ -90,7 +91,7 @@ export default function CustomersList() {
|
|
|
90
91
|
},
|
|
91
92
|
{
|
|
92
93
|
key: "location",
|
|
93
|
-
label: "
|
|
94
|
+
label: t("customers.location"),
|
|
94
95
|
render: (c) => {
|
|
95
96
|
const b = c.billing || {};
|
|
96
97
|
return [b.city, countryName(b.country)].filter(Boolean).join(", ") || "—";
|
|
@@ -98,13 +99,13 @@ export default function CustomersList() {
|
|
|
98
99
|
},
|
|
99
100
|
{
|
|
100
101
|
key: "orders_count",
|
|
101
|
-
label: "
|
|
102
|
+
label: t("routes.orders"),
|
|
102
103
|
sortable: !debouncedQuery,
|
|
103
104
|
render: (c) => c.orders_count ?? 0,
|
|
104
105
|
},
|
|
105
106
|
{
|
|
106
107
|
key: "total_spent",
|
|
107
|
-
label: "
|
|
108
|
+
label: t("customers.total_spend"),
|
|
108
109
|
sortable: !debouncedQuery,
|
|
109
110
|
render: (c) => money.format(c.total_spent ?? 0),
|
|
110
111
|
},
|
|
@@ -113,12 +114,12 @@ export default function CustomersList() {
|
|
|
113
114
|
return (
|
|
114
115
|
<div>
|
|
115
116
|
<PageHeader
|
|
116
|
-
title="
|
|
117
|
-
description="
|
|
117
|
+
title={t("routes.customers")}
|
|
118
|
+
description={t("customers.subtitle")}
|
|
118
119
|
actions={
|
|
119
120
|
<Button asChild>
|
|
120
121
|
<Link to={href("customers/new")}>
|
|
121
|
-
<Plus className="mr-1 h-4 w-4" />
|
|
122
|
+
<Plus className="mr-1 h-4 w-4" /> {t("routes.customers_new")}
|
|
122
123
|
</Link>
|
|
123
124
|
</Button>
|
|
124
125
|
}
|
|
@@ -129,7 +130,7 @@ export default function CustomersList() {
|
|
|
129
130
|
<Search className="pointer-events-none absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
|
130
131
|
<Input
|
|
131
132
|
className="pl-8"
|
|
132
|
-
placeholder="
|
|
133
|
+
placeholder={t("customers.search_placeholder")}
|
|
133
134
|
value={query}
|
|
134
135
|
onChange={(e) => setQuery(e.target.value)}
|
|
135
136
|
/>
|
|
@@ -144,23 +145,23 @@ export default function CustomersList() {
|
|
|
144
145
|
onSort={debouncedQuery ? undefined : list.setSort}
|
|
145
146
|
onRowClick={(c) => navigate(href(`customers/${c.id}`))}
|
|
146
147
|
rowActions={(c) => [
|
|
147
|
-
{ label: "
|
|
148
|
-
{ label: "
|
|
148
|
+
{ label: t("common.edit"), icon: Pencil, onClick: () => navigate(href(`customers/${c.id}`)) },
|
|
149
|
+
{ label: t("common.delete"), icon: Trash2, destructive: true, onClick: () => setPendingDelete(c) },
|
|
149
150
|
]}
|
|
150
151
|
pagination={{ page: list.page, hasNext: list.hasNext, onNext: list.next, onPrev: list.prev }}
|
|
151
152
|
empty={{
|
|
152
153
|
icon: Users,
|
|
153
|
-
title: "
|
|
154
|
-
description: "
|
|
154
|
+
title: t("customers.empty_title"),
|
|
155
|
+
description: t("customers.empty_description"),
|
|
155
156
|
}}
|
|
156
157
|
/>
|
|
157
158
|
|
|
158
159
|
<ConfirmDialog
|
|
159
160
|
open={!!pendingDelete}
|
|
160
161
|
onOpenChange={(o) => !o && setPendingDelete(null)}
|
|
161
|
-
title="
|
|
162
|
-
description="
|
|
163
|
-
confirmLabel="
|
|
162
|
+
title={t("customers.confirm_delete_title")}
|
|
163
|
+
description={t("customers.confirm_delete_description")}
|
|
164
|
+
confirmLabel={t("common.delete")}
|
|
164
165
|
loading={deleting}
|
|
165
166
|
onConfirm={doDelete}
|
|
166
167
|
/>
|