@base44/app-plugin-commerce 0.1.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/LICENSE +21 -0
- package/README.md +117 -0
- package/base44/agents/commerce/StoreAdmin.jsonc +64 -0
- package/base44/entities/commerce.Cart.jsonc +73 -0
- package/base44/entities/commerce.Coupon.jsonc +113 -0
- package/base44/entities/commerce.Customer.jsonc +96 -0
- package/base44/entities/commerce.DownloadPermission.jsonc +54 -0
- package/base44/entities/commerce.EmailLog.jsonc +43 -0
- package/base44/entities/commerce.Order.jsonc +287 -0
- package/base44/entities/commerce.OrderNote.jsonc +31 -0
- package/base44/entities/commerce.OrderRefund.jsonc +64 -0
- package/base44/entities/commerce.PaymentGateway.jsonc +48 -0
- package/base44/entities/commerce.Product.jsonc +291 -0
- package/base44/entities/commerce.ProductAttribute.jsonc +39 -0
- package/base44/entities/commerce.ProductAttributeTerm.jsonc +38 -0
- package/base44/entities/commerce.ProductCategory.jsonc +51 -0
- package/base44/entities/commerce.ProductReview.jsonc +48 -0
- package/base44/entities/commerce.ProductTag.jsonc +30 -0
- package/base44/entities/commerce.ProductVariation.jsonc +167 -0
- package/base44/entities/commerce.ShippingClass.jsonc +30 -0
- package/base44/entities/commerce.ShippingZone.jsonc +41 -0
- package/base44/entities/commerce.ShippingZoneMethod.jsonc +84 -0
- package/base44/entities/commerce.StoreSettings.jsonc +23 -0
- package/base44/entities/commerce.TaxClass.jsonc +23 -0
- package/base44/entities/commerce.TaxRate.jsonc +68 -0
- package/base44/entities/commerce.Webhook.jsonc +57 -0
- package/base44/entities/commerce.WebhookDelivery.jsonc +45 -0
- package/base44/functions/commerce/admin-coupons/entry.ts +100 -0
- package/base44/functions/commerce/admin-customers/entry.ts +141 -0
- package/base44/functions/commerce/admin-orders/entry.ts +396 -0
- package/base44/functions/commerce/admin-orders/helpers.ts +246 -0
- package/base44/functions/commerce/admin-products/entry.ts +506 -0
- package/base44/functions/commerce/admin-refunds/entry.ts +158 -0
- package/base44/functions/commerce/admin-reports/entry.ts +283 -0
- package/base44/functions/commerce/admin-reviews/entry.ts +66 -0
- package/base44/functions/commerce/admin-tools/entry.ts +261 -0
- package/base44/functions/commerce/admin-webhooks/entry.ts +52 -0
- package/base44/functions/commerce/payment-webhook/entry.ts +135 -0
- package/base44/functions/commerce/payments/entry.ts +238 -0
- package/base44/functions/commerce/seed-store/defaults.ts +162 -0
- package/base44/functions/commerce/seed-store/entry.ts +310 -0
- package/base44/functions/commerce/seed-store/sample-data.ts +349 -0
- package/base44/functions/commerce/storefront-account/entry.ts +207 -0
- package/base44/functions/commerce/storefront-cart/cart-pricing.ts +258 -0
- package/base44/functions/commerce/storefront-cart/entry.ts +283 -0
- package/base44/functions/commerce/storefront-catalog/entry.ts +459 -0
- package/base44/functions/commerce/storefront-checkout/cart-pricing.ts +258 -0
- package/base44/functions/commerce/storefront-checkout/entry.ts +485 -0
- package/base44/shared/commerce/auth.ts +60 -0
- package/base44/shared/commerce/coupons.ts +257 -0
- package/base44/shared/commerce/data/continents.ts +75 -0
- package/base44/shared/commerce/data/countries.ts +307 -0
- package/base44/shared/commerce/data/currencies.ts +46 -0
- package/base44/shared/commerce/email-templates.ts +240 -0
- package/base44/shared/commerce/emails.ts +225 -0
- package/base44/shared/commerce/money.ts +66 -0
- package/base44/shared/commerce/orders.ts +251 -0
- package/base44/shared/commerce/payments.ts +495 -0
- package/base44/shared/commerce/reviews.ts +36 -0
- package/base44/shared/commerce/scan.ts +57 -0
- package/base44/shared/commerce/sequence.ts +35 -0
- package/base44/shared/commerce/settings.ts +57 -0
- package/base44/shared/commerce/shipping.ts +215 -0
- package/base44/shared/commerce/stock.ts +227 -0
- package/base44/shared/commerce/stripe.ts +463 -0
- package/base44/shared/commerce/tax.ts +136 -0
- package/base44/shared/commerce/totals.ts +314 -0
- package/base44/shared/commerce/webhooks.ts +116 -0
- package/package.json +37 -0
- package/scripts/install.js +156 -0
- package/skills/commerce/SKILL.md +62 -0
- package/skills/commerce/docs/api-admin.md +186 -0
- package/skills/commerce/docs/api-storefront.md +408 -0
- package/skills/commerce/installation-guidelines.md +91 -0
- package/skills/commerce/post-installation.md +157 -0
- package/skills/commerce/references/emails.md +13 -0
- package/skills/commerce/references/guest-access-security.md +18 -0
- package/skills/commerce/references/limits-and-performance.md +16 -0
- package/skills/commerce/references/media-and-downloads.md +4 -0
- package/skills/commerce/references/online-payments.md +201 -0
- package/skills/commerce/references/product-render.md +87 -0
- package/skills/commerce/references/scheduled-work.md +19 -0
- package/skills/commerce/references/storefront-product-page.md +83 -0
- package/skills/commerce/references/webhooks.md +8 -0
- package/src/commerce/admin/README.md +107 -0
- package/src/commerce/admin/bot/Markdown.jsx +138 -0
- package/src/commerce/admin/bot/StoreAdminBot.jsx +249 -0
- package/src/commerce/admin/bot/pipe-tables.js +116 -0
- package/src/commerce/admin/components/AddressForm.jsx +78 -0
- package/src/commerce/admin/components/ConfirmDialog.jsx +52 -0
- package/src/commerce/admin/components/CountrySelect.jsx +81 -0
- package/src/commerce/admin/components/DataTable.jsx +192 -0
- package/src/commerce/admin/components/DateRangePicker.jsx +91 -0
- package/src/commerce/admin/components/EmptyState.jsx +17 -0
- package/src/commerce/admin/components/MediaUploader.jsx +116 -0
- package/src/commerce/admin/components/MetaDataEditor.jsx +45 -0
- package/src/commerce/admin/components/MoneyInput.jsx +50 -0
- package/src/commerce/admin/components/PageHeader.jsx +29 -0
- package/src/commerce/admin/components/RichTextarea.jsx +21 -0
- package/src/commerce/admin/components/SearchSelect.jsx +142 -0
- package/src/commerce/admin/components/StatusBadge.jsx +17 -0
- package/src/commerce/admin/context/BasePathContext.jsx +26 -0
- package/src/commerce/admin/context/SettingsContext.jsx +207 -0
- package/src/commerce/admin/hooks/useAsync.js +46 -0
- package/src/commerce/admin/hooks/useDebounce.js +11 -0
- package/src/commerce/admin/hooks/useMoney.js +52 -0
- package/src/commerce/admin/hooks/usePagedList.js +83 -0
- package/src/commerce/admin/hooks/usePaymentProvider.js +27 -0
- package/src/commerce/admin/hooks/useRealtime.js +129 -0
- package/src/commerce/admin/index.jsx +34 -0
- package/src/commerce/admin/layout/AccessDenied.jsx +54 -0
- package/src/commerce/admin/layout/AdminLayout.jsx +33 -0
- package/src/commerce/admin/layout/AuthGuard.jsx +84 -0
- package/src/commerce/admin/layout/Sidebar.jsx +130 -0
- package/src/commerce/admin/layout/Topbar.jsx +94 -0
- package/src/commerce/admin/lib/api.js +55 -0
- package/src/commerce/admin/lib/constants.js +157 -0
- package/src/commerce/admin/lib/format.js +27 -0
- package/src/commerce/admin/lib/geo-data.js +125 -0
- package/src/commerce/admin/lib/order-utils.js +147 -0
- package/src/commerce/admin/lib/paths.js +35 -0
- package/src/commerce/admin/lib/product-utils.js +55 -0
- package/src/commerce/admin/pages/Dashboard.jsx +245 -0
- package/src/commerce/admin/pages/coupons/CouponEditor.jsx +565 -0
- package/src/commerce/admin/pages/coupons/CouponsList.jsx +172 -0
- package/src/commerce/admin/pages/customers/CustomerEditor.jsx +318 -0
- package/src/commerce/admin/pages/customers/CustomersList.jsx +169 -0
- package/src/commerce/admin/pages/orders/OrderEditor.jsx +952 -0
- package/src/commerce/admin/pages/orders/OrdersList.jsx +227 -0
- package/src/commerce/admin/pages/orders/components/AddProductDialog.jsx +149 -0
- package/src/commerce/admin/pages/orders/components/DownloadPermissionsPanel.jsx +119 -0
- package/src/commerce/admin/pages/orders/components/LineItemsTable.jsx +208 -0
- package/src/commerce/admin/pages/orders/components/OrderNotesPanel.jsx +123 -0
- package/src/commerce/admin/pages/orders/components/PaymentPanel.jsx +199 -0
- package/src/commerce/admin/pages/orders/components/RefundPanel.jsx +239 -0
- package/src/commerce/admin/pages/orders/components/TotalsBox.jsx +52 -0
- package/src/commerce/admin/pages/products/AttributeTerms.jsx +180 -0
- package/src/commerce/admin/pages/products/Attributes.jsx +183 -0
- package/src/commerce/admin/pages/products/Categories.jsx +236 -0
- package/src/commerce/admin/pages/products/ProductEditor.jsx +267 -0
- package/src/commerce/admin/pages/products/ProductsList.jsx +391 -0
- package/src/commerce/admin/pages/products/Reviews.jsx +255 -0
- package/src/commerce/admin/pages/products/Tags.jsx +150 -0
- package/src/commerce/admin/pages/products/components/ProductDataPanel.jsx +132 -0
- package/src/commerce/admin/pages/products/components/PublishBox.jsx +101 -0
- package/src/commerce/admin/pages/products/components/TaxonomyPanel.jsx +243 -0
- package/src/commerce/admin/pages/products/components/tabs/AdvancedTab.jsx +48 -0
- package/src/commerce/admin/pages/products/components/tabs/AttributesTab.jsx +208 -0
- package/src/commerce/admin/pages/products/components/tabs/DownloadsTab.jsx +91 -0
- package/src/commerce/admin/pages/products/components/tabs/ExternalTab.jsx +41 -0
- package/src/commerce/admin/pages/products/components/tabs/GeneralTab.jsx +103 -0
- package/src/commerce/admin/pages/products/components/tabs/InventoryTab.jsx +93 -0
- package/src/commerce/admin/pages/products/components/tabs/LinkedTab.jsx +102 -0
- package/src/commerce/admin/pages/products/components/tabs/ShippingTab.jsx +86 -0
- package/src/commerce/admin/pages/products/components/tabs/VariationsTab.jsx +377 -0
- package/src/commerce/admin/pages/reports/Reports.jsx +416 -0
- package/src/commerce/admin/pages/settings/EmailsSettings.jsx +240 -0
- package/src/commerce/admin/pages/settings/GeneralSettings.jsx +232 -0
- package/src/commerce/admin/pages/settings/InventorySettings.jsx +146 -0
- package/src/commerce/admin/pages/settings/PaymentsSettings.jsx +260 -0
- package/src/commerce/admin/pages/settings/ProductsSettings.jsx +118 -0
- package/src/commerce/admin/pages/settings/SettingsLayout.jsx +53 -0
- package/src/commerce/admin/pages/settings/ShippingSettings.jsx +304 -0
- package/src/commerce/admin/pages/settings/ShippingZoneEditor.jsx +514 -0
- package/src/commerce/admin/pages/settings/TaxRatesTable.jsx +231 -0
- package/src/commerce/admin/pages/settings/TaxSettings.jsx +281 -0
- package/src/commerce/admin/pages/settings/useGroupForm.jsx +76 -0
- package/src/commerce/admin/pages/status/WebhookEditor.jsx +296 -0
- package/src/commerce/admin/pages/status/Webhooks.jsx +53 -0
- package/src/commerce/admin/routes.jsx +151 -0
- package/src/commerce/utils/index.js +19 -0
- package/src/commerce/utils/shipping-promos.js +99 -0
- package/src/commerce/utils/variants.js +411 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
+
import { NavLink, useLocation } from "react-router-dom";
|
|
3
|
+
import { Badge } from "@/components/ui/badge";
|
|
4
|
+
import {
|
|
5
|
+
BadgePercent,
|
|
6
|
+
BarChart3,
|
|
7
|
+
LayoutDashboard,
|
|
8
|
+
Package,
|
|
9
|
+
Settings,
|
|
10
|
+
ShoppingCart,
|
|
11
|
+
Sparkles,
|
|
12
|
+
Users,
|
|
13
|
+
Webhook,
|
|
14
|
+
} from "lucide-react";
|
|
15
|
+
import { call } from "../lib/api";
|
|
16
|
+
import { useAdminHref } from "../context/BasePathContext";
|
|
17
|
+
|
|
18
|
+
const NAV = [
|
|
19
|
+
{ items: [{ label: "Dashboard", path: "", icon: LayoutDashboard, end: true }] },
|
|
20
|
+
{
|
|
21
|
+
items: [
|
|
22
|
+
{ label: "Orders", path: "orders", icon: ShoppingCart, badge: "processing" },
|
|
23
|
+
{ label: "Customers", path: "customers", icon: Users },
|
|
24
|
+
{ label: "Reports", path: "reports", icon: BarChart3 },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
title: "Products",
|
|
29
|
+
icon: Package,
|
|
30
|
+
items: [
|
|
31
|
+
{ label: "All Products", path: "products", end: true },
|
|
32
|
+
{ label: "Categories", path: "products/categories" },
|
|
33
|
+
{ label: "Tags", path: "products/tags" },
|
|
34
|
+
{ label: "Attributes", path: "products/attributes" },
|
|
35
|
+
{ label: "Reviews", path: "products/reviews" },
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
title: "Marketing",
|
|
40
|
+
icon: BadgePercent,
|
|
41
|
+
items: [{ label: "Coupons", path: "coupons" }],
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
items: [{ label: "Settings", path: "settings", icon: Settings }],
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: "Status",
|
|
48
|
+
icon: Webhook,
|
|
49
|
+
items: [{ label: "Webhooks", path: "webhooks" }],
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
/** Left navigation. `onNavigate` closes the mobile sheet; `onOpenBot` opens the StoreAdmin bot panel. */
|
|
54
|
+
export default function Sidebar({ onNavigate, onOpenBot }) {
|
|
55
|
+
const href = useAdminHref();
|
|
56
|
+
const location = useLocation();
|
|
57
|
+
const [processingCount, setProcessingCount] = useState(null);
|
|
58
|
+
const lastFetch = useRef(0);
|
|
59
|
+
|
|
60
|
+
// Non-blocking processing-orders badge; refresh at most every 15s on navigation.
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
const now = Date.now();
|
|
63
|
+
if (now - lastFetch.current < 15000) return;
|
|
64
|
+
lastFetch.current = now;
|
|
65
|
+
call("admin-orders", "status-counts", {}, { silent: true })
|
|
66
|
+
.then((counts) => setProcessingCount(counts?.processing ?? 0))
|
|
67
|
+
.catch(() => {});
|
|
68
|
+
}, [location.pathname]);
|
|
69
|
+
|
|
70
|
+
const linkClass = ({ isActive }) =>
|
|
71
|
+
`flex items-center gap-2.5 rounded-md px-3 py-2 text-sm transition-colors ${
|
|
72
|
+
isActive
|
|
73
|
+
? "bg-primary/10 font-medium text-primary"
|
|
74
|
+
: "text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
75
|
+
}`;
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<div className="flex h-full flex-col">
|
|
79
|
+
<div className="flex h-14 items-center gap-2 border-b px-4">
|
|
80
|
+
<Package className="h-5 w-5 text-primary" />
|
|
81
|
+
<span className="font-semibold">Store Admin</span>
|
|
82
|
+
</div>
|
|
83
|
+
<nav className="flex-1 space-y-4 overflow-y-auto p-3">
|
|
84
|
+
{NAV.map((group, gi) => (
|
|
85
|
+
<div key={gi}>
|
|
86
|
+
{group.title && (
|
|
87
|
+
<div className="mb-1 px-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground/70">
|
|
88
|
+
{group.title}
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
<div className="space-y-0.5">
|
|
92
|
+
{group.items.map((item) => {
|
|
93
|
+
const Icon = item.icon;
|
|
94
|
+
return (
|
|
95
|
+
<NavLink
|
|
96
|
+
key={item.path}
|
|
97
|
+
to={href(item.path)}
|
|
98
|
+
end={item.end}
|
|
99
|
+
className={linkClass}
|
|
100
|
+
onClick={onNavigate}
|
|
101
|
+
>
|
|
102
|
+
{Icon && <Icon className="h-4 w-4 shrink-0" />}
|
|
103
|
+
<span className="flex-1">{item.label}</span>
|
|
104
|
+
{item.badge === "processing" && processingCount > 0 && (
|
|
105
|
+
<Badge variant="secondary" className="h-5 min-w-5 justify-center px-1.5">
|
|
106
|
+
{processingCount}
|
|
107
|
+
</Badge>
|
|
108
|
+
)}
|
|
109
|
+
</NavLink>
|
|
110
|
+
);
|
|
111
|
+
})}
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
))}
|
|
115
|
+
</nav>
|
|
116
|
+
{onOpenBot && (
|
|
117
|
+
<div className="border-t p-3">
|
|
118
|
+
<button
|
|
119
|
+
type="button"
|
|
120
|
+
onClick={onOpenBot}
|
|
121
|
+
className="flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
|
122
|
+
>
|
|
123
|
+
<Sparkles className="h-4 w-4 shrink-0 text-primary" />
|
|
124
|
+
<span className="flex-1 text-left">StoreAdmin bot</span>
|
|
125
|
+
</button>
|
|
126
|
+
</div>
|
|
127
|
+
)}
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Link, useLocation } from "react-router-dom";
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
import {
|
|
5
|
+
DropdownMenu,
|
|
6
|
+
DropdownMenuContent,
|
|
7
|
+
DropdownMenuItem,
|
|
8
|
+
DropdownMenuLabel,
|
|
9
|
+
DropdownMenuSeparator,
|
|
10
|
+
DropdownMenuTrigger,
|
|
11
|
+
} from "@/components/ui/dropdown-menu";
|
|
12
|
+
import { ChevronRight, LogOut, Menu, UserCircle } from "lucide-react";
|
|
13
|
+
import { base44 } from "../lib/api";
|
|
14
|
+
import { useAuth } from "./AuthGuard";
|
|
15
|
+
import { useBasePath, useAdminHref } from "../context/BasePathContext";
|
|
16
|
+
import { ADMIN_ROUTES } from "../routes";
|
|
17
|
+
|
|
18
|
+
/** Match an internal path (no leading slash) against ADMIN_ROUTES patterns. */
|
|
19
|
+
function matchRoute(path) {
|
|
20
|
+
const segs = path.split("/").filter(Boolean);
|
|
21
|
+
return ADMIN_ROUTES.find((r) => {
|
|
22
|
+
const pSegs = r.path.split("/").filter(Boolean);
|
|
23
|
+
if (pSegs.length !== segs.length) return false;
|
|
24
|
+
return pSegs.every((p, i) => p.startsWith(":") || p === segs[i]);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function useBreadcrumbs() {
|
|
29
|
+
const { pathname } = useLocation();
|
|
30
|
+
const base = useBasePath();
|
|
31
|
+
const rel = pathname.startsWith(base) ? pathname.slice(base.length) : pathname;
|
|
32
|
+
const segs = rel.split("/").filter(Boolean);
|
|
33
|
+
const crumbs = [{ label: "Dashboard", path: "" }];
|
|
34
|
+
segs.forEach((seg, i) => {
|
|
35
|
+
const prefix = segs.slice(0, i + 1).join("/");
|
|
36
|
+
const route = matchRoute(prefix);
|
|
37
|
+
crumbs.push({
|
|
38
|
+
label: route?.label || decodeURIComponent(seg),
|
|
39
|
+
path: prefix,
|
|
40
|
+
last: i === segs.length - 1,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
return crumbs;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Top bar: mobile menu button, breadcrumbs, user menu. */
|
|
47
|
+
export default function Topbar({ onMenuClick }) {
|
|
48
|
+
const user = useAuth();
|
|
49
|
+
const href = useAdminHref();
|
|
50
|
+
const crumbs = useBreadcrumbs();
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<header className="sticky top-0 z-10 flex h-14 items-center gap-3 border-b bg-background px-4">
|
|
54
|
+
<Button variant="ghost" size="icon" className="lg:hidden" onClick={onMenuClick}>
|
|
55
|
+
<Menu className="h-5 w-5" />
|
|
56
|
+
</Button>
|
|
57
|
+
<nav className="flex min-w-0 flex-1 items-center gap-1 text-sm">
|
|
58
|
+
{crumbs.map((crumb, i) => (
|
|
59
|
+
<React.Fragment key={i}>
|
|
60
|
+
{i > 0 && <ChevronRight className="h-3.5 w-3.5 shrink-0 text-muted-foreground/50" />}
|
|
61
|
+
{crumb.last || i === crumbs.length - 1 ? (
|
|
62
|
+
<span className="truncate font-medium">{crumb.label}</span>
|
|
63
|
+
) : (
|
|
64
|
+
<Link
|
|
65
|
+
to={href(crumb.path)}
|
|
66
|
+
className="shrink-0 text-muted-foreground hover:text-foreground"
|
|
67
|
+
>
|
|
68
|
+
{crumb.label}
|
|
69
|
+
</Link>
|
|
70
|
+
)}
|
|
71
|
+
</React.Fragment>
|
|
72
|
+
))}
|
|
73
|
+
</nav>
|
|
74
|
+
<DropdownMenu>
|
|
75
|
+
<DropdownMenuTrigger asChild>
|
|
76
|
+
<Button variant="ghost" size="sm" className="gap-2">
|
|
77
|
+
<UserCircle className="h-5 w-5" />
|
|
78
|
+
<span className="hidden max-w-40 truncate sm:inline">{user?.email}</span>
|
|
79
|
+
</Button>
|
|
80
|
+
</DropdownMenuTrigger>
|
|
81
|
+
<DropdownMenuContent align="end">
|
|
82
|
+
<DropdownMenuLabel className="font-normal">
|
|
83
|
+
<div className="text-sm font-medium">{user?.full_name || "Administrator"}</div>
|
|
84
|
+
<div className="text-xs text-muted-foreground">{user?.email}</div>
|
|
85
|
+
</DropdownMenuLabel>
|
|
86
|
+
<DropdownMenuSeparator />
|
|
87
|
+
<DropdownMenuItem onClick={() => base44.auth.logout()}>
|
|
88
|
+
<LogOut className="mr-2 h-4 w-4" /> Sign out
|
|
89
|
+
</DropdownMenuItem>
|
|
90
|
+
</DropdownMenuContent>
|
|
91
|
+
</DropdownMenu>
|
|
92
|
+
</header>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single touchpoint for the Base44 SDK client and backend-function calls.
|
|
3
|
+
*
|
|
4
|
+
* Expects your app to export the client as a named `base44` export, as
|
|
5
|
+
* Base44's default `src/api/base44Client.js` does. If your app uses a
|
|
6
|
+
* default export instead, this import is the ONLY line you need to adjust.
|
|
7
|
+
* (A static "named-or-default" probe is not possible here: referencing an
|
|
8
|
+
* export the module doesn't have is a hard error at build time.)
|
|
9
|
+
*/
|
|
10
|
+
import { base44 } from "@/api/base44Client";
|
|
11
|
+
import { toast } from "sonner";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Invoke a backend function using the template's `{action, ...payload}` convention.
|
|
15
|
+
*
|
|
16
|
+
* - Returns the unwrapped `data` when the function responds with the
|
|
17
|
+
* `{success, data}` envelope, otherwise the raw response body.
|
|
18
|
+
* - On failure: shows an error toast (unless `opts.silent`) and rethrows an
|
|
19
|
+
* Error carrying `.code` and `.details` from the function's error body.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} fn - function name without the "commerce/" prefix, e.g.
|
|
22
|
+
* "admin-orders" (invoked as "commerce/admin-orders" — the prefix is added here)
|
|
23
|
+
* @param {string|null} action - action name, e.g. "status-counts" (null = send payload as-is)
|
|
24
|
+
* @param {object} payload
|
|
25
|
+
* @param {{silent?: boolean}} opts
|
|
26
|
+
*/
|
|
27
|
+
export async function call(fn, action, payload = {}, opts = {}) {
|
|
28
|
+
try {
|
|
29
|
+
const body = action ? { action, ...payload } : { ...payload };
|
|
30
|
+
const res = await base44.functions.invoke(`commerce/${fn}`, body);
|
|
31
|
+
const data = res?.data;
|
|
32
|
+
if (data && typeof data === "object" && "success" in data) {
|
|
33
|
+
if (data.success === false) {
|
|
34
|
+
throw Object.assign(new Error(data.error || "Request failed"), {
|
|
35
|
+
code: data.code,
|
|
36
|
+
details: data,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return "data" in data ? data.data : data;
|
|
40
|
+
}
|
|
41
|
+
return data;
|
|
42
|
+
} catch (err) {
|
|
43
|
+
const body = err.response?.data;
|
|
44
|
+
const message = body?.error || err.message || "Request failed";
|
|
45
|
+
const wrapped = Object.assign(new Error(message), {
|
|
46
|
+
code: body?.code || err.code,
|
|
47
|
+
details: body || err.details || null,
|
|
48
|
+
status: err.response?.status,
|
|
49
|
+
});
|
|
50
|
+
if (!opts.silent) toast.error(message);
|
|
51
|
+
throw wrapped;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { base44 };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/** Shared enums, labels and badge colors for the admin UI. */
|
|
2
|
+
|
|
3
|
+
export const ORDER_STATUSES = [
|
|
4
|
+
{ value: "pending", label: "Pending payment", color: "bg-amber-100 text-amber-800 border-amber-200" },
|
|
5
|
+
{ value: "processing", label: "Processing", color: "bg-green-100 text-green-800 border-green-200" },
|
|
6
|
+
{ value: "on-hold", label: "On hold", color: "bg-orange-100 text-orange-800 border-orange-200" },
|
|
7
|
+
{ value: "completed", label: "Completed", color: "bg-blue-100 text-blue-800 border-blue-200" },
|
|
8
|
+
{ value: "cancelled", label: "Cancelled", color: "bg-gray-100 text-gray-700 border-gray-200" },
|
|
9
|
+
{ value: "refunded", label: "Refunded", color: "bg-slate-100 text-slate-700 border-slate-200" },
|
|
10
|
+
{ value: "failed", label: "Failed", color: "bg-red-100 text-red-800 border-red-200" },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
export const PRODUCT_STATUSES = [
|
|
14
|
+
{ value: "draft", label: "Draft", color: "bg-gray-100 text-gray-700 border-gray-200" },
|
|
15
|
+
{ value: "pending", label: "Pending review", color: "bg-amber-100 text-amber-800 border-amber-200" },
|
|
16
|
+
{ value: "private", label: "Private", color: "bg-slate-100 text-slate-700 border-slate-200" },
|
|
17
|
+
{ value: "publish", label: "Published", color: "bg-green-100 text-green-800 border-green-200" },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
export const PRODUCT_TYPES = [
|
|
21
|
+
{ value: "simple", label: "Simple product" },
|
|
22
|
+
{ value: "grouped", label: "Grouped product" },
|
|
23
|
+
{ value: "external", label: "External/Affiliate product" },
|
|
24
|
+
{ value: "variable", label: "Variable product" },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export const CATALOG_VISIBILITIES = [
|
|
28
|
+
{ value: "visible", label: "Shop and search results" },
|
|
29
|
+
{ value: "catalog", label: "Shop only" },
|
|
30
|
+
{ value: "search", label: "Search results only" },
|
|
31
|
+
{ value: "hidden", label: "Hidden" },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
export const STOCK_STATUSES = [
|
|
35
|
+
{ value: "instock", label: "In stock", color: "bg-green-100 text-green-800 border-green-200" },
|
|
36
|
+
{ value: "outofstock", label: "Out of stock", color: "bg-red-100 text-red-800 border-red-200" },
|
|
37
|
+
{ value: "onbackorder", label: "On backorder", color: "bg-amber-100 text-amber-800 border-amber-200" },
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
export const BACKORDER_OPTIONS = [
|
|
41
|
+
{ value: "no", label: "Do not allow" },
|
|
42
|
+
{ value: "notify", label: "Allow, but notify customer" },
|
|
43
|
+
{ value: "yes", label: "Allow" },
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
export const TAX_STATUSES = [
|
|
47
|
+
{ value: "taxable", label: "Taxable" },
|
|
48
|
+
{ value: "shipping", label: "Shipping only" },
|
|
49
|
+
{ value: "none", label: "None" },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
export const COUPON_TYPES = [
|
|
53
|
+
{ value: "percent", label: "Percentage discount" },
|
|
54
|
+
{ value: "fixed_cart", label: "Fixed cart discount" },
|
|
55
|
+
{ value: "fixed_product", label: "Fixed product discount" },
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
export const REVIEW_STATUSES = [
|
|
59
|
+
{ value: "approved", label: "Approved", color: "bg-green-100 text-green-800 border-green-200" },
|
|
60
|
+
{ value: "hold", label: "Pending", color: "bg-amber-100 text-amber-800 border-amber-200" },
|
|
61
|
+
{ value: "spam", label: "Spam", color: "bg-red-100 text-red-800 border-red-200" },
|
|
62
|
+
{ value: "trash", label: "Trash", color: "bg-gray-100 text-gray-700 border-gray-200" },
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
export const WEBHOOK_STATUSES = [
|
|
66
|
+
{ value: "active", label: "Active", color: "bg-green-100 text-green-800 border-green-200" },
|
|
67
|
+
{ value: "paused", label: "Paused", color: "bg-amber-100 text-amber-800 border-amber-200" },
|
|
68
|
+
{ value: "disabled", label: "Disabled", color: "bg-gray-100 text-gray-700 border-gray-200" },
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
export const WEBHOOK_TOPICS = [
|
|
72
|
+
"order.created", "order.updated", "order.deleted", "order.restored",
|
|
73
|
+
"product.created", "product.updated", "product.deleted", "product.restored",
|
|
74
|
+
"customer.created", "customer.updated", "customer.deleted",
|
|
75
|
+
"coupon.created", "coupon.updated", "coupon.deleted",
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
export const SHIPPING_METHOD_TYPES = [
|
|
79
|
+
{ value: "flat_rate", label: "Flat rate" },
|
|
80
|
+
{ value: "free_shipping", label: "Free shipping" },
|
|
81
|
+
{ value: "local_pickup", label: "Local pickup" },
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
export const FREE_SHIPPING_REQUIRES = [
|
|
85
|
+
{ value: "", label: "No requirement" },
|
|
86
|
+
{ value: "coupon", label: "A valid free shipping coupon" },
|
|
87
|
+
{ value: "min_amount", label: "A minimum order amount" },
|
|
88
|
+
{ value: "either", label: "A minimum order amount OR a coupon" },
|
|
89
|
+
{ value: "both", label: "A minimum order amount AND a coupon" },
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The 11 transactional emails.
|
|
94
|
+
* `recipient: "admin"` emails expose a Recipient override in the Emails settings.
|
|
95
|
+
* `managed_by_auth` emails are handled by Base44 auth, not this template.
|
|
96
|
+
*/
|
|
97
|
+
export const EMAIL_TYPES = [
|
|
98
|
+
{ id: "new_order", label: "New order", recipient: "admin" },
|
|
99
|
+
{ id: "cancelled_order", label: "Cancelled order", recipient: "admin" },
|
|
100
|
+
{ id: "failed_order", label: "Failed order", recipient: "admin" },
|
|
101
|
+
{ id: "on_hold_order", label: "Order on-hold", recipient: "customer" },
|
|
102
|
+
{ id: "processing_order", label: "Processing order", recipient: "customer" },
|
|
103
|
+
{ id: "completed_order", label: "Completed order", recipient: "customer" },
|
|
104
|
+
{ id: "refunded_order", label: "Refunded order", recipient: "customer" },
|
|
105
|
+
{ id: "customer_invoice", label: "Customer invoice / Order details", recipient: "customer", manual: true },
|
|
106
|
+
{ id: "customer_note", label: "Customer note", recipient: "customer" },
|
|
107
|
+
{ id: "reset_password", label: "Reset password", recipient: "customer", managed_by_auth: true },
|
|
108
|
+
{ id: "new_account", label: "New account", recipient: "customer", managed_by_auth: true },
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
export const CURRENCIES = [
|
|
112
|
+
{ code: "USD", name: "US Dollar", symbol: "$", decimals: 2 },
|
|
113
|
+
{ code: "EUR", name: "Euro", symbol: "€", decimals: 2 },
|
|
114
|
+
{ code: "GBP", name: "Pound Sterling", symbol: "£", decimals: 2 },
|
|
115
|
+
{ code: "JPY", name: "Japanese Yen", symbol: "¥", decimals: 0 },
|
|
116
|
+
{ code: "CNY", name: "Chinese Yuan", symbol: "¥", decimals: 2 },
|
|
117
|
+
{ code: "AUD", name: "Australian Dollar", symbol: "A$", decimals: 2 },
|
|
118
|
+
{ code: "CAD", name: "Canadian Dollar", symbol: "C$", decimals: 2 },
|
|
119
|
+
{ code: "CHF", name: "Swiss Franc", symbol: "CHF", decimals: 2 },
|
|
120
|
+
{ code: "HKD", name: "Hong Kong Dollar", symbol: "HK$", decimals: 2 },
|
|
121
|
+
{ code: "SGD", name: "Singapore Dollar", symbol: "S$", decimals: 2 },
|
|
122
|
+
{ code: "SEK", name: "Swedish Krona", symbol: "kr", decimals: 2 },
|
|
123
|
+
{ code: "NOK", name: "Norwegian Krone", symbol: "kr", decimals: 2 },
|
|
124
|
+
{ code: "DKK", name: "Danish Krone", symbol: "kr", decimals: 2 },
|
|
125
|
+
{ code: "NZD", name: "New Zealand Dollar", symbol: "NZ$", decimals: 2 },
|
|
126
|
+
{ code: "MXN", name: "Mexican Peso", symbol: "$", decimals: 2 },
|
|
127
|
+
{ code: "BRL", name: "Brazilian Real", symbol: "R$", decimals: 2 },
|
|
128
|
+
{ code: "INR", name: "Indian Rupee", symbol: "₹", decimals: 2 },
|
|
129
|
+
{ code: "KRW", name: "South Korean Won", symbol: "₩", decimals: 0 },
|
|
130
|
+
{ code: "TRY", name: "Turkish Lira", symbol: "₺", decimals: 2 },
|
|
131
|
+
{ code: "ZAR", name: "South African Rand", symbol: "R", decimals: 2 },
|
|
132
|
+
{ code: "PLN", name: "Polish Złoty", symbol: "zł", decimals: 2 },
|
|
133
|
+
{ code: "CZK", name: "Czech Koruna", symbol: "Kč", decimals: 2 },
|
|
134
|
+
{ code: "HUF", name: "Hungarian Forint", symbol: "Ft", decimals: 0 },
|
|
135
|
+
{ code: "ILS", name: "Israeli New Shekel", symbol: "₪", decimals: 2 },
|
|
136
|
+
{ code: "AED", name: "UAE Dirham", symbol: "د.إ", decimals: 2 },
|
|
137
|
+
{ code: "SAR", name: "Saudi Riyal", symbol: "﷼", decimals: 2 },
|
|
138
|
+
{ code: "THB", name: "Thai Baht", symbol: "฿", decimals: 2 },
|
|
139
|
+
{ code: "MYR", name: "Malaysian Ringgit", symbol: "RM", decimals: 2 },
|
|
140
|
+
{ code: "PHP", name: "Philippine Peso", symbol: "₱", decimals: 2 },
|
|
141
|
+
{ code: "IDR", name: "Indonesian Rupiah", symbol: "Rp", decimals: 0 },
|
|
142
|
+
{ code: "VND", name: "Vietnamese Dong", symbol: "₫", decimals: 0 },
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
export const CURRENCY_POSITIONS = [
|
|
146
|
+
{ value: "left", label: "Left ($99.99)" },
|
|
147
|
+
{ value: "right", label: "Right (99.99$)" },
|
|
148
|
+
{ value: "left_space", label: "Left with space ($ 99.99)" },
|
|
149
|
+
{ value: "right_space", label: "Right with space (99.99 $)" },
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
export const WEIGHT_UNITS = ["kg", "g", "lbs", "oz"];
|
|
153
|
+
export const DIMENSION_UNITS = ["cm", "m", "mm", "in", "yd"];
|
|
154
|
+
|
|
155
|
+
export function statusMeta(list, value) {
|
|
156
|
+
return list.find((s) => s.value === value) || { value, label: value || "—", color: "bg-gray-100 text-gray-700 border-gray-200" };
|
|
157
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Date/text formatting helpers. */
|
|
2
|
+
|
|
3
|
+
export function formatDate(iso) {
|
|
4
|
+
if (!iso) return "—";
|
|
5
|
+
const d = new Date(iso);
|
|
6
|
+
if (isNaN(d)) return "—";
|
|
7
|
+
return d.toLocaleDateString(undefined, { year: "numeric", month: "short", day: "numeric" });
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function formatDateTime(iso) {
|
|
11
|
+
if (!iso) return "—";
|
|
12
|
+
const d = new Date(iso);
|
|
13
|
+
if (isNaN(d)) return "—";
|
|
14
|
+
return d.toLocaleString(undefined, {
|
|
15
|
+
year: "numeric",
|
|
16
|
+
month: "short",
|
|
17
|
+
day: "numeric",
|
|
18
|
+
hour: "2-digit",
|
|
19
|
+
minute: "2-digit",
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function truncate(str, n = 80) {
|
|
24
|
+
if (!str) return "";
|
|
25
|
+
const s = String(str).replace(/<[^>]*>/g, "");
|
|
26
|
+
return s.length > n ? s.slice(0, n - 1) + "…" : s;
|
|
27
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static geographic reference data for pickers (mirror of base44/shared/commerce/data/*.ts).
|
|
3
|
+
* Countries: ISO 3166-1 alpha-2. States included for US / CA / AU; other
|
|
4
|
+
* countries accept free-text state input in AddressForm.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const c = (code, name, states) => (states ? { code, name, states } : { code, name });
|
|
8
|
+
const s = (code, name) => ({ code, name });
|
|
9
|
+
|
|
10
|
+
export const US_STATES = [
|
|
11
|
+
s("AL", "Alabama"), s("AK", "Alaska"), s("AZ", "Arizona"), s("AR", "Arkansas"),
|
|
12
|
+
s("CA", "California"), s("CO", "Colorado"), s("CT", "Connecticut"), s("DE", "Delaware"),
|
|
13
|
+
s("DC", "District of Columbia"), s("FL", "Florida"), s("GA", "Georgia"), s("HI", "Hawaii"),
|
|
14
|
+
s("ID", "Idaho"), s("IL", "Illinois"), s("IN", "Indiana"), s("IA", "Iowa"),
|
|
15
|
+
s("KS", "Kansas"), s("KY", "Kentucky"), s("LA", "Louisiana"), s("ME", "Maine"),
|
|
16
|
+
s("MD", "Maryland"), s("MA", "Massachusetts"), s("MI", "Michigan"), s("MN", "Minnesota"),
|
|
17
|
+
s("MS", "Mississippi"), s("MO", "Missouri"), s("MT", "Montana"), s("NE", "Nebraska"),
|
|
18
|
+
s("NV", "Nevada"), s("NH", "New Hampshire"), s("NJ", "New Jersey"), s("NM", "New Mexico"),
|
|
19
|
+
s("NY", "New York"), s("NC", "North Carolina"), s("ND", "North Dakota"), s("OH", "Ohio"),
|
|
20
|
+
s("OK", "Oklahoma"), s("OR", "Oregon"), s("PA", "Pennsylvania"), s("RI", "Rhode Island"),
|
|
21
|
+
s("SC", "South Carolina"), s("SD", "South Dakota"), s("TN", "Tennessee"), s("TX", "Texas"),
|
|
22
|
+
s("UT", "Utah"), s("VT", "Vermont"), s("VA", "Virginia"), s("WA", "Washington"),
|
|
23
|
+
s("WV", "West Virginia"), s("WI", "Wisconsin"), s("WY", "Wyoming"),
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export const CA_PROVINCES = [
|
|
27
|
+
s("AB", "Alberta"), s("BC", "British Columbia"), s("MB", "Manitoba"),
|
|
28
|
+
s("NB", "New Brunswick"), s("NL", "Newfoundland and Labrador"), s("NT", "Northwest Territories"),
|
|
29
|
+
s("NS", "Nova Scotia"), s("NU", "Nunavut"), s("ON", "Ontario"),
|
|
30
|
+
s("PE", "Prince Edward Island"), s("QC", "Quebec"), s("SK", "Saskatchewan"), s("YT", "Yukon"),
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
export const AU_STATES = [
|
|
34
|
+
s("ACT", "Australian Capital Territory"), s("NSW", "New South Wales"),
|
|
35
|
+
s("NT", "Northern Territory"), s("QLD", "Queensland"), s("SA", "South Australia"),
|
|
36
|
+
s("TAS", "Tasmania"), s("VIC", "Victoria"), s("WA", "Western Australia"),
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
export const COUNTRIES = [
|
|
40
|
+
c("AF", "Afghanistan"), c("AX", "Åland Islands"), c("AL", "Albania"), c("DZ", "Algeria"),
|
|
41
|
+
c("AS", "American Samoa"), c("AD", "Andorra"), c("AO", "Angola"), c("AI", "Anguilla"),
|
|
42
|
+
c("AQ", "Antarctica"), c("AG", "Antigua and Barbuda"), c("AR", "Argentina"), c("AM", "Armenia"),
|
|
43
|
+
c("AW", "Aruba"), c("AU", "Australia", AU_STATES), c("AT", "Austria"), c("AZ", "Azerbaijan"),
|
|
44
|
+
c("BS", "Bahamas"), c("BH", "Bahrain"), c("BD", "Bangladesh"), c("BB", "Barbados"),
|
|
45
|
+
c("BY", "Belarus"), c("BE", "Belgium"), c("BZ", "Belize"), c("BJ", "Benin"),
|
|
46
|
+
c("BM", "Bermuda"), c("BT", "Bhutan"), c("BO", "Bolivia"), c("BQ", "Bonaire, Sint Eustatius and Saba"),
|
|
47
|
+
c("BA", "Bosnia and Herzegovina"), c("BW", "Botswana"), c("BV", "Bouvet Island"), c("BR", "Brazil"),
|
|
48
|
+
c("IO", "British Indian Ocean Territory"), c("BN", "Brunei Darussalam"), c("BG", "Bulgaria"), c("BF", "Burkina Faso"),
|
|
49
|
+
c("BI", "Burundi"), c("CV", "Cabo Verde"), c("KH", "Cambodia"), c("CM", "Cameroon"),
|
|
50
|
+
c("CA", "Canada", CA_PROVINCES), c("KY", "Cayman Islands"), c("CF", "Central African Republic"), c("TD", "Chad"),
|
|
51
|
+
c("CL", "Chile"), c("CN", "China"), c("CX", "Christmas Island"), c("CC", "Cocos (Keeling) Islands"),
|
|
52
|
+
c("CO", "Colombia"), c("KM", "Comoros"), c("CG", "Congo"), c("CD", "Congo, Democratic Republic of the"),
|
|
53
|
+
c("CK", "Cook Islands"), c("CR", "Costa Rica"), c("CI", "Côte d'Ivoire"), c("HR", "Croatia"),
|
|
54
|
+
c("CU", "Cuba"), c("CW", "Curaçao"), c("CY", "Cyprus"), c("CZ", "Czechia"),
|
|
55
|
+
c("DK", "Denmark"), c("DJ", "Djibouti"), c("DM", "Dominica"), c("DO", "Dominican Republic"),
|
|
56
|
+
c("EC", "Ecuador"), c("EG", "Egypt"), c("SV", "El Salvador"), c("GQ", "Equatorial Guinea"),
|
|
57
|
+
c("ER", "Eritrea"), c("EE", "Estonia"), c("SZ", "Eswatini"), c("ET", "Ethiopia"),
|
|
58
|
+
c("FK", "Falkland Islands"), c("FO", "Faroe Islands"), c("FJ", "Fiji"), c("FI", "Finland"),
|
|
59
|
+
c("FR", "France"), c("GF", "French Guiana"), c("PF", "French Polynesia"), c("TF", "French Southern Territories"),
|
|
60
|
+
c("GA", "Gabon"), c("GM", "Gambia"), c("GE", "Georgia"), c("DE", "Germany"),
|
|
61
|
+
c("GH", "Ghana"), c("GI", "Gibraltar"), c("GR", "Greece"), c("GL", "Greenland"),
|
|
62
|
+
c("GD", "Grenada"), c("GP", "Guadeloupe"), c("GU", "Guam"), c("GT", "Guatemala"),
|
|
63
|
+
c("GG", "Guernsey"), c("GN", "Guinea"), c("GW", "Guinea-Bissau"), c("GY", "Guyana"),
|
|
64
|
+
c("HT", "Haiti"), c("HM", "Heard Island and McDonald Islands"), c("VA", "Holy See"), c("HN", "Honduras"),
|
|
65
|
+
c("HK", "Hong Kong"), c("HU", "Hungary"), c("IS", "Iceland"), c("IN", "India"),
|
|
66
|
+
c("ID", "Indonesia"), c("IR", "Iran"), c("IQ", "Iraq"), c("IE", "Ireland"),
|
|
67
|
+
c("IM", "Isle of Man"), c("IL", "Israel"), c("IT", "Italy"), c("JM", "Jamaica"),
|
|
68
|
+
c("JP", "Japan"), c("JE", "Jersey"), c("JO", "Jordan"), c("KZ", "Kazakhstan"),
|
|
69
|
+
c("KE", "Kenya"), c("KI", "Kiribati"), c("KP", "Korea, North"), c("KR", "Korea, South"),
|
|
70
|
+
c("KW", "Kuwait"), c("KG", "Kyrgyzstan"), c("LA", "Lao People's Democratic Republic"), c("LV", "Latvia"),
|
|
71
|
+
c("LB", "Lebanon"), c("LS", "Lesotho"), c("LR", "Liberia"), c("LY", "Libya"),
|
|
72
|
+
c("LI", "Liechtenstein"), c("LT", "Lithuania"), c("LU", "Luxembourg"), c("MO", "Macao"),
|
|
73
|
+
c("MG", "Madagascar"), c("MW", "Malawi"), c("MY", "Malaysia"), c("MV", "Maldives"),
|
|
74
|
+
c("ML", "Mali"), c("MT", "Malta"), c("MH", "Marshall Islands"), c("MQ", "Martinique"),
|
|
75
|
+
c("MR", "Mauritania"), c("MU", "Mauritius"), c("YT", "Mayotte"), c("MX", "Mexico"),
|
|
76
|
+
c("FM", "Micronesia"), c("MD", "Moldova"), c("MC", "Monaco"), c("MN", "Mongolia"),
|
|
77
|
+
c("ME", "Montenegro"), c("MS", "Montserrat"), c("MA", "Morocco"), c("MZ", "Mozambique"),
|
|
78
|
+
c("MM", "Myanmar"), c("NA", "Namibia"), c("NR", "Nauru"), c("NP", "Nepal"),
|
|
79
|
+
c("NL", "Netherlands"), c("NC", "New Caledonia"), c("NZ", "New Zealand"), c("NI", "Nicaragua"),
|
|
80
|
+
c("NE", "Niger"), c("NG", "Nigeria"), c("NU", "Niue"), c("NF", "Norfolk Island"),
|
|
81
|
+
c("MK", "North Macedonia"), c("MP", "Northern Mariana Islands"), c("NO", "Norway"), c("OM", "Oman"),
|
|
82
|
+
c("PK", "Pakistan"), c("PW", "Palau"), c("PS", "Palestine, State of"), c("PA", "Panama"),
|
|
83
|
+
c("PG", "Papua New Guinea"), c("PY", "Paraguay"), c("PE", "Peru"), c("PH", "Philippines"),
|
|
84
|
+
c("PN", "Pitcairn"), c("PL", "Poland"), c("PT", "Portugal"), c("PR", "Puerto Rico"),
|
|
85
|
+
c("QA", "Qatar"), c("RE", "Réunion"), c("RO", "Romania"), c("RU", "Russian Federation"),
|
|
86
|
+
c("RW", "Rwanda"), c("BL", "Saint Barthélemy"), c("SH", "Saint Helena"), c("KN", "Saint Kitts and Nevis"),
|
|
87
|
+
c("LC", "Saint Lucia"), c("MF", "Saint Martin (French part)"), c("PM", "Saint Pierre and Miquelon"), c("VC", "Saint Vincent and the Grenadines"),
|
|
88
|
+
c("WS", "Samoa"), c("SM", "San Marino"), c("ST", "Sao Tome and Principe"), c("SA", "Saudi Arabia"),
|
|
89
|
+
c("SN", "Senegal"), c("RS", "Serbia"), c("SC", "Seychelles"), c("SL", "Sierra Leone"),
|
|
90
|
+
c("SG", "Singapore"), c("SX", "Sint Maarten (Dutch part)"), c("SK", "Slovakia"), c("SI", "Slovenia"),
|
|
91
|
+
c("SB", "Solomon Islands"), c("SO", "Somalia"), c("ZA", "South Africa"), c("GS", "South Georgia and the South Sandwich Islands"),
|
|
92
|
+
c("SS", "South Sudan"), c("ES", "Spain"), c("LK", "Sri Lanka"), c("SD", "Sudan"),
|
|
93
|
+
c("SR", "Suriname"), c("SJ", "Svalbard and Jan Mayen"), c("SE", "Sweden"), c("CH", "Switzerland"),
|
|
94
|
+
c("SY", "Syrian Arab Republic"), c("TW", "Taiwan"), c("TJ", "Tajikistan"), c("TZ", "Tanzania"),
|
|
95
|
+
c("TH", "Thailand"), c("TL", "Timor-Leste"), c("TG", "Togo"), c("TK", "Tokelau"),
|
|
96
|
+
c("TO", "Tonga"), c("TT", "Trinidad and Tobago"), c("TN", "Tunisia"), c("TR", "Türkiye"),
|
|
97
|
+
c("TM", "Turkmenistan"), c("TC", "Turks and Caicos Islands"), c("TV", "Tuvalu"), c("UG", "Uganda"),
|
|
98
|
+
c("UA", "Ukraine"), c("AE", "United Arab Emirates"), c("GB", "United Kingdom"), c("US", "United States", US_STATES),
|
|
99
|
+
c("UM", "United States Minor Outlying Islands"), c("UY", "Uruguay"), c("UZ", "Uzbekistan"), c("VU", "Vanuatu"),
|
|
100
|
+
c("VE", "Venezuela"), c("VN", "Viet Nam"), c("VG", "Virgin Islands (British)"), c("VI", "Virgin Islands (U.S.)"),
|
|
101
|
+
c("WF", "Wallis and Futuna"), c("EH", "Western Sahara"), c("YE", "Yemen"), c("ZM", "Zambia"),
|
|
102
|
+
c("ZW", "Zimbabwe"),
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
export const CONTINENTS = [
|
|
106
|
+
{ code: "AF", name: "Africa", countries: ["DZ","AO","BJ","BW","BF","BI","CV","CM","CF","TD","KM","CG","CD","CI","DJ","EG","GQ","ER","SZ","ET","GA","GM","GH","GN","GW","KE","LS","LR","LY","MG","MW","ML","MR","MU","YT","MA","MZ","NA","NE","NG","RE","RW","SH","ST","SN","SC","SL","SO","ZA","SS","SD","TZ","TG","TN","UG","EH","ZM","ZW"] },
|
|
107
|
+
{ code: "AN", name: "Antarctica", countries: ["AQ","BV","GS","HM","TF"] },
|
|
108
|
+
{ code: "AS", name: "Asia", countries: ["AF","AM","AZ","BH","BD","BT","BN","KH","CN","CY","GE","HK","IN","ID","IR","IQ","IL","JP","JO","KZ","KP","KR","KW","KG","LA","LB","MO","MY","MV","MN","MM","NP","OM","PK","PS","PH","QA","SA","SG","LK","SY","TW","TJ","TH","TL","TR","TM","AE","UZ","VN","YE"] },
|
|
109
|
+
{ code: "EU", name: "Europe", countries: ["AX","AL","AD","AT","BY","BE","BA","BG","HR","CZ","DK","EE","FO","FI","FR","DE","GI","GR","GG","VA","HU","IS","IE","IM","IT","JE","LV","LI","LT","LU","MT","MD","MC","ME","NL","MK","NO","PL","PT","RO","RU","SM","RS","SK","SI","ES","SJ","SE","CH","UA","GB"] },
|
|
110
|
+
{ code: "NA", name: "North America", countries: ["AI","AG","AW","BS","BB","BZ","BM","BQ","CA","KY","CR","CU","CW","DM","DO","SV","GL","GD","GP","GT","HT","HN","JM","MQ","MX","MS","NI","PA","PR","BL","KN","LC","MF","PM","VC","SX","TT","TC","US","UM","VG","VI"] },
|
|
111
|
+
{ code: "OC", name: "Oceania", countries: ["AS","AU","CX","CC","CK","FJ","PF","GU","KI","MH","FM","NR","NC","NZ","NU","NF","MP","PW","PG","PN","WS","SB","TK","TO","TV","VU","WF"] },
|
|
112
|
+
{ code: "SA", name: "South America", countries: ["AR","BO","BR","CL","CO","EC","FK","GF","GY","PY","PE","SR","UY","VE"] },
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
export function countryByCode(code) {
|
|
116
|
+
return COUNTRIES.find((x) => x.code === code) || null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function countryName(code) {
|
|
120
|
+
return countryByCode(code)?.name || code || "";
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function statesFor(code) {
|
|
124
|
+
return countryByCode(code)?.states || null;
|
|
125
|
+
}
|