@mohasinac/appkit 4.18.0 → 4.20.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/dist/_internal/client/features/lottery/LotteryAdminEditView.js +3 -1
- package/dist/_internal/client/features/lottery/LotteryPullForm.js +3 -1
- package/dist/_internal/shared/features/lottery/config-form.d.ts +58 -0
- package/dist/_internal/shared/features/lottery/config-form.js +71 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.js +3 -0
- package/dist/features/account/schemas/index.d.ts +23 -0
- package/dist/features/account/schemas/index.js +21 -0
- package/dist/features/admin/components/AdminSiteSettingsView.js +8 -6
- package/dist/features/admin/components/AdminUserEditorView.js +14 -12
- package/dist/features/admin/schemas/admin-user-form.d.ts +82 -0
- package/dist/features/admin/schemas/admin-user-form.js +102 -0
- package/dist/features/admin/schemas/site-settings-form.d.ts +309 -0
- package/dist/features/admin/schemas/site-settings-form.js +159 -0
- package/dist/features/auctions/components/PlaceBidFormClient.js +3 -2
- package/dist/features/seller/components/SellerProductShell.js +107 -71
- package/dist/features/seller/components/SellerShippingView.js +21 -18
- package/dist/features/seller/components/SellerStorefrontView.js +21 -19
- package/dist/features/shell/FormShell.d.ts +4 -4
- package/dist/features/shell/FormShell.js +1 -1
- package/dist/features/shell/index.d.ts +0 -2
- package/dist/features/shell/index.js +0 -1
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +24 -0
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +4 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +5 -3
- package/dist/schemas/registry.d.ts +682 -0
- package/dist/schemas/registry.js +22 -0
- package/package.json +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useEffect,
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { StackedViewShell } from "../../../ui";
|
|
6
6
|
import { Alert, Div, FormField, FormGroup, Heading, Stack, Text, Toggle, } from "../../../ui";
|
|
7
7
|
import { FormShellContext, useFormShellState, applyZodIssues, FormErrorSummary } from "../../../ui/forms";
|
|
8
8
|
import { ImageUpload, useMediaUpload } from "../../media";
|
|
9
|
-
import {
|
|
9
|
+
import { SectionForm, useSectionFormNav, useFormShell } from "../../shell";
|
|
10
10
|
// Small local schema for the storefront form-input shape (not the broader
|
|
11
11
|
// `sellerStoreSchema`, which requires id/storeSlug/ownerId/status/createdAt —
|
|
12
12
|
// fields this editable draft never has, so applying it directly would show
|
|
@@ -23,14 +23,8 @@ export function SellerStorefrontView({ initialValues, onSave, isLoading = false,
|
|
|
23
23
|
const [draft, setDraft] = useState(initialValues ?? {});
|
|
24
24
|
const [saving, setSaving] = useState(false);
|
|
25
25
|
const [saved, setSaved] = useState(false);
|
|
26
|
-
const [currentStep, setCurrentStep] = useState(0);
|
|
27
26
|
const { markDirty, markClean } = useFormShell();
|
|
28
27
|
const { upload } = useMediaUpload();
|
|
29
|
-
const { shellCtx, setFieldError, clearErrors, validate } = useFormShellState(storefrontDraftSchema);
|
|
30
|
-
useEffect(() => {
|
|
31
|
-
validate(draft);
|
|
32
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
33
|
-
}, [draft, validate]);
|
|
34
28
|
const update = useCallback((partial) => {
|
|
35
29
|
setDraft((prev) => ({ ...prev, ...partial }));
|
|
36
30
|
markDirty();
|
|
@@ -54,39 +48,47 @@ export function SellerStorefrontView({ initialValues, onSave, isLoading = false,
|
|
|
54
48
|
}
|
|
55
49
|
};
|
|
56
50
|
const busy = saving || isLoading;
|
|
57
|
-
const
|
|
51
|
+
const sections = [
|
|
58
52
|
{
|
|
53
|
+
id: "store-identity",
|
|
59
54
|
label: "Store Identity",
|
|
55
|
+
required: true,
|
|
56
|
+
quick: true,
|
|
60
57
|
fields: ["storeName", "storeDescription", "storeCategory", "bio"],
|
|
61
|
-
validate: (values) => !values.storeName?.trim() ? "Store name is required" : null,
|
|
62
58
|
render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Store Identity" }), _jsx(FormField, { name: "storeName", label: "Store Name", type: "text", value: values.storeName ?? "", onChange: (v) => onChange({ storeName: v }), placeholder: "e.g. Pok\u00E9mon Palace", disabled: busy }), _jsx(FormField, { name: "storeCategory", label: "Store Category", type: "text", value: values.storeCategory ?? "", onChange: (v) => onChange({ storeCategory: v }), placeholder: "e.g. Trading Cards, Action Figures", disabled: busy }), _jsx(FormField, { name: "bio", label: "Short Bio (shown in search results)", type: "textarea", value: values.bio ?? "", onChange: (v) => onChange({ bio: v }), placeholder: "One-liner about your store (max 300 chars)", disabled: busy }), _jsx(FormField, { name: "storeDescription", label: "Full Description", type: "textarea", value: values.storeDescription ?? "", onChange: (v) => onChange({ storeDescription: v }), placeholder: "Detailed store description shown on your public store page\u2026", disabled: busy })] })),
|
|
63
59
|
},
|
|
64
60
|
{
|
|
61
|
+
id: "branding",
|
|
65
62
|
label: "Branding",
|
|
66
63
|
fields: ["storeLogoURL", "storeBannerURL"],
|
|
67
64
|
render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Branding" }), _jsxs(FormGroup, { columns: 2, children: [_jsx(ImageUpload, { label: "Store Logo", currentImage: values.storeLogoURL, onUpload: (file) => upload(file, "stores", true, { type: "store-logo", store: storeSlug }), onChange: (url) => onChange({ storeLogoURL: url }), helperText: "Square image, min 200\u00D7200px" }), _jsx(ImageUpload, { label: "Store Banner", currentImage: values.storeBannerURL, onUpload: (file) => upload(file, "stores", true, { type: "store-banner", store: storeSlug }), onChange: (url) => onChange({ storeBannerURL: url }), helperText: "Recommended: 1200\u00D7300px" })] })] })),
|
|
68
65
|
},
|
|
69
66
|
{
|
|
67
|
+
id: "policies",
|
|
70
68
|
label: "Policies",
|
|
71
69
|
fields: ["returnPolicy", "shippingPolicy"],
|
|
72
70
|
render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Policies" }), _jsx(FormField, { name: "returnPolicy", label: "Return Policy", type: "textarea", value: values.returnPolicy ?? "", onChange: (v) => onChange({ returnPolicy: v }), placeholder: "Describe your return policy\u2026", disabled: busy }), _jsx(FormField, { name: "shippingPolicy", label: "Shipping Policy", type: "textarea", value: values.shippingPolicy ?? "", onChange: (v) => onChange({ shippingPolicy: v }), placeholder: "How and when you ship orders\u2026", disabled: busy })] })),
|
|
73
71
|
},
|
|
74
72
|
{
|
|
73
|
+
id: "contact-visibility",
|
|
75
74
|
label: "Contact & Visibility",
|
|
76
75
|
fields: ["website", "location", "socialLinks", "isPublic", "isVacationMode", "vacationMessage"],
|
|
77
76
|
render: ({ values, onChange }) => (_jsxs(Stack, { gap: "md", children: [_jsx(Heading, { level: 3, className: "mb-2", children: "Contact & Social" }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "website", label: "Website", type: "text", value: values.website ?? "", onChange: (v) => onChange({ website: v }), placeholder: "https://example.com", disabled: busy }), _jsx(FormField, { name: "location", label: "Location", type: "text", value: values.location ?? "", onChange: (v) => onChange({ location: v }), placeholder: "e.g. Mumbai, India", disabled: busy })] }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "twitter", label: "Twitter / X URL", type: "text", value: values.socialLinks?.twitter ?? "", onChange: (v) => onChange({ socialLinks: { ...values.socialLinks, twitter: v } }), placeholder: "https://twitter.com/...", disabled: busy }), _jsx(FormField, { name: "instagram", label: "Instagram URL", type: "text", value: values.socialLinks?.instagram ?? "", onChange: (v) => onChange({ socialLinks: { ...values.socialLinks, instagram: v } }), placeholder: "https://instagram.com/...", disabled: busy })] }), _jsxs(FormGroup, { columns: 2, children: [_jsx(FormField, { name: "facebook", label: "Facebook URL", type: "text", value: values.socialLinks?.facebook ?? "", onChange: (v) => onChange({ socialLinks: { ...values.socialLinks, facebook: v } }), placeholder: "https://facebook.com/...", disabled: busy }), _jsx(FormField, { name: "linkedin", label: "LinkedIn URL", type: "text", value: values.socialLinks?.linkedin ?? "", onChange: (v) => onChange({ socialLinks: { ...values.socialLinks, linkedin: v } }), placeholder: "https://linkedin.com/...", disabled: busy })] }), _jsx(Heading, { level: 4, className: "mt-4 mb-2", children: "Visibility" }), _jsx(Toggle, { checked: values.isPublic !== false, onChange: (checked) => onChange({ isPublic: checked }), label: "Make store public \u2014 visible to all buyers", disabled: busy }), values.isPublic === false && (_jsx(Text, { className: "text-[var(--appkit-color-text-muted)]", size: "sm", children: "Your store is hidden. Existing orders are unaffected." })), _jsx(Heading, { level: 4, className: "mt-4 mb-2", children: "Vacation Mode" }), _jsx(Toggle, { checked: !!values.isVacationMode, onChange: (checked) => onChange({ isVacationMode: checked }), label: "Enable vacation mode \u2014 your store will show a notice to buyers", disabled: busy }), values.isVacationMode && (_jsx(FormField, { name: "vacationMessage", label: "Vacation Message", type: "textarea", value: values.vacationMessage ?? "", onChange: (v) => onChange({ vacationMessage: v }), placeholder: "I'm away until\u2026 Orders placed now will ship when I return.", disabled: busy }))] })),
|
|
78
77
|
},
|
|
79
78
|
];
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
/*
|
|
80
|
+
* `useSectionFormNav` replaces the hand-rolled fieldToStepIndex map and the
|
|
81
|
+
* manually-composed wizardShellCtx. The old `useMemo(..., [steps.length])`
|
|
82
|
+
* meant a step whose FIELDS changed without changing the COUNT never
|
|
83
|
+
* recomputed its map, so the error summary could jump to the wrong step.
|
|
84
|
+
*/
|
|
85
|
+
const { openIds, setOpenIds, goToSection, fieldToSectionIndex, sectionMeta } = useSectionFormNav(sections, draft);
|
|
86
|
+
const { shellCtx, setFieldError, clearErrors, validate } = useFormShellState(storefrontDraftSchema, { sections: sectionMeta, onGoToSection: goToSection, fieldToSectionIndex });
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
validate(draft);
|
|
86
89
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
87
|
-
}, [
|
|
88
|
-
const wizardShellCtx = useMemo(() => ({ ...shellCtx, fieldToStepIndex, goToStep: (n) => setCurrentStep(n) }), [shellCtx, fieldToStepIndex, setCurrentStep]);
|
|
90
|
+
}, [draft, validate]);
|
|
89
91
|
return (_jsx(StackedViewShell, { portal: "seller", title: "Storefront Settings", sections: [
|
|
90
|
-
_jsxs(Div, { children: [saved && (_jsx(Alert, { variant: "success", className: "mb-6", children: "Changes saved successfully." })), _jsxs(FormShellContext.Provider, { value:
|
|
92
|
+
_jsxs(Div, { children: [saved && (_jsx(Alert, { variant: "success", className: "mb-6", children: "Changes saved successfully." })), _jsxs(FormShellContext.Provider, { value: shellCtx, children: [_jsx(FormErrorSummary, {}), _jsx(SectionForm, { sections: sections, values: draft, onChange: update, onSubmit: handleSave, schema: storefrontDraftSchema, openIds: openIds, onOpenChange: setOpenIds, submitLabel: "Save Storefront", isLoading: busy })] })] }, "stepform"),
|
|
91
93
|
] }));
|
|
92
94
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
/**
|
|
3
3
|
* Carries the `schema` prop passed to `<FormShell>` down to any nested
|
|
4
|
-
* `<
|
|
4
|
+
* `<SectionForm>` that doesn't declare its own `schema`/`SectionDef.schema` —
|
|
5
5
|
* `FormShell` (chrome) has no form values of its own to validate, so it
|
|
6
6
|
* can't run `.safeParse()` itself; this is what makes the prop load-bearing
|
|
7
7
|
* instead of silently discarded.
|
|
@@ -18,7 +18,7 @@ export interface FormShellProps {
|
|
|
18
18
|
breadcrumb?: string;
|
|
19
19
|
isDirty?: boolean;
|
|
20
20
|
isLoading?: boolean;
|
|
21
|
-
/** Left-nav anchor sections
|
|
21
|
+
/** Left-nav anchor sections. */
|
|
22
22
|
sections?: FormShellSection[];
|
|
23
23
|
onSaveDraft?: () => void | Promise<void>;
|
|
24
24
|
onPublish?: () => void | Promise<void>;
|
|
@@ -52,8 +52,8 @@ export interface FormShellProps {
|
|
|
52
52
|
/**
|
|
53
53
|
* Zod schema covering the form's fields. `FormShell` has no form values of
|
|
54
54
|
* its own, so it can't `.safeParse()` this directly — instead it provides
|
|
55
|
-
* the schema via `FormSchemaContext` to any nested `<
|
|
56
|
-
* doesn't declare its own `schema`/`
|
|
55
|
+
* the schema via `FormSchemaContext` to any nested `<SectionForm>` that
|
|
56
|
+
* doesn't declare its own `schema`/`SectionDef.schema`, so existing
|
|
57
57
|
* `<FormShell schema={x}>` call sites start validating with zero changes.
|
|
58
58
|
* `audit-form-schema` requires every callsite to declare one.
|
|
59
59
|
*/
|
|
@@ -9,7 +9,7 @@ import { FORM_ACTION_META, FORM_ACTION_ID } from "../products/constants/action-d
|
|
|
9
9
|
import { Div, Row, Span, Stack, Text } from "../../ui";
|
|
10
10
|
/**
|
|
11
11
|
* Carries the `schema` prop passed to `<FormShell>` down to any nested
|
|
12
|
-
* `<
|
|
12
|
+
* `<SectionForm>` that doesn't declare its own `schema`/`SectionDef.schema` —
|
|
13
13
|
* `FormShell` (chrome) has no form values of its own to validate, so it
|
|
14
14
|
* can't run `.safeParse()` itself; this is what makes the prop load-bearing
|
|
15
15
|
* instead of silently discarded.
|
|
@@ -4,8 +4,6 @@ export type { CommandPaletteGroup, CommandPaletteProps } from "./CommandPalette"
|
|
|
4
4
|
export { CommandPalette, useCommandPaletteHotkey } from "./CommandPalette";
|
|
5
5
|
export type { QuickFieldType, QuickFieldDef, QuickFormDrawerProps } from "./QuickFormDrawer";
|
|
6
6
|
export { QuickFormDrawer } from "./QuickFormDrawer";
|
|
7
|
-
export type { StepDef, StepFormProps, StepFormActionsProps } from "./StepForm";
|
|
8
|
-
export { StepForm, StepFormActions, StepIndicator } from "./StepForm";
|
|
9
7
|
export type { SectionDef, SectionFormProps, UseSectionFormNavResult, } from "./SectionForm";
|
|
10
8
|
export { SectionForm, useSectionFormNav, orderSections, buildFieldToSectionIndex, sectionAnchorId, } from "./SectionForm";
|
|
11
9
|
export type { EntityFormDefinition } from "./entity-form";
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { FormShell, useFormShell, FormSchemaContext } from "./FormShell";
|
|
2
2
|
export { CommandPalette, useCommandPaletteHotkey } from "./CommandPalette";
|
|
3
3
|
export { QuickFormDrawer } from "./QuickFormDrawer";
|
|
4
|
-
export { StepForm, StepFormActions, StepIndicator } from "./StepForm";
|
|
5
4
|
export { SectionForm, useSectionFormNav, orderSections, buildFieldToSectionIndex, sectionAnchorId, } from "./SectionForm";
|
|
6
5
|
export { deriveQuickFields, deriveQuickFieldNames, allDefinitionFields, applyDerive, assertNoDeriveCollision, humaniseFieldName, } from "./entity-form";
|
|
7
6
|
export { ui, annotate, ROW_COLUMNS, inferFieldUiMeta, resolveFieldUiMeta, unwrapSchema, schemaEnumOptions, schemaIsOptional, objectShape, } from "./field-ui-meta";
|
|
@@ -3083,6 +3083,30 @@ const rawTesterChecklistItems = [
|
|
|
3083
3083
|
description: "Both PATCH routes previously spread the raw request body into Firestore with no schema, so any key and any status string could be written. Confirm the normal Take / Action / Dismiss and Approve / Reject flows still all work — that is what the tightening must not have broken.",
|
|
3084
3084
|
href: "/admin/reports",
|
|
3085
3085
|
},
|
|
3086
|
+
{
|
|
3087
|
+
key: "listing-form-every-section-reachable",
|
|
3088
|
+
label: "Creating a listing shows ALL sections at once — you can open Pricing before finishing Basic, and nothing blocks you",
|
|
3089
|
+
description: "The last step wizard was removed 2026-08-26. It gated Next on the current step's validate, so a seller who could not satisfy step 2 could not reach step 5 to find out what else was needed. Open /store/products/new, expand a later section immediately, and confirm it opens. The required section (Basic) stays open and cannot be collapsed.",
|
|
3090
|
+
href: "/store/products/new",
|
|
3091
|
+
},
|
|
3092
|
+
{
|
|
3093
|
+
key: "listing-form-errors-land-on-fields",
|
|
3094
|
+
label: "Publishing an incomplete listing puts each error on ITS OWN FIELD, and the summary links jump to that section",
|
|
3095
|
+
description: "The per-step validate callbacks returned a single string rendered as one banner over the whole step. They are per-section Zod schemas now, so a missing auction start bid reports on the start-bid field. Press Publish with several sections incomplete and confirm each message appears beside its input, and that clicking an entry in the summary opens the right section.",
|
|
3096
|
+
href: "/store/products/new",
|
|
3097
|
+
},
|
|
3098
|
+
{
|
|
3099
|
+
key: "listing-form-save-draft-anywhere",
|
|
3100
|
+
label: "\"Save as draft & finish later\" is available from any section, not only the first",
|
|
3101
|
+
description: "It used to be gated on `currentStep === 0`, which was a wizard artefact — a draft is a draft whichever section you are looking at. Fill in a title, scroll to a later section, and confirm the button is still there and still saves.",
|
|
3102
|
+
href: "/store/products/new",
|
|
3103
|
+
},
|
|
3104
|
+
{
|
|
3105
|
+
key: "seller-shipping-storefront-sections",
|
|
3106
|
+
label: "Shipping Configuration and Storefront Settings are collapsible sections with one Save at the bottom — no Next/Back",
|
|
3107
|
+
description: "Both were 3- and 4-step wizards until 2026-08-26. Check that every section is reachable immediately, that the error summary jumps to the right one, and that a single Save covers whichever sections you edited.",
|
|
3108
|
+
href: "/store/shipping",
|
|
3109
|
+
},
|
|
3086
3110
|
{
|
|
3087
3111
|
key: "admin-tables-render-badges-not-text",
|
|
3088
3112
|
label: "Admin list tables show a coloured STATUS BADGE, a thumbnail and formatted money — not raw text",
|
|
@@ -16,6 +16,8 @@ import { apiClient } from "../../../http";
|
|
|
16
16
|
import { WHATSAPP_SELLER_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
17
17
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
18
18
|
import { buildPurchaseAnnouncementMessage } from "../helpers/whatsapp";
|
|
19
|
+
import { whatsappSettingsSchema } from "../../admin/schemas/admin-user-form";
|
|
20
|
+
import { FormErrorSummary } from "../../../ui/forms/FormErrorSummary";
|
|
19
21
|
// ---------------------------------------------------------------------------
|
|
20
22
|
// Sub-components
|
|
21
23
|
// ---------------------------------------------------------------------------
|
|
@@ -187,10 +189,10 @@ export function SellerWhatsAppSettingsView({ hasCapability }) {
|
|
|
187
189
|
? cfg?.connected === true
|
|
188
190
|
: Boolean(cfg?.[step.checkKey]);
|
|
189
191
|
return (_jsxs(Row, { gap: "sm", align: "start", children: [_jsx(Row, { textWeight: "bold", textSize: "xs", className: `flex-shrink-0 w-6 h-6 mt-0.5 ${done ? "bg-[var(--appkit-color-success)] text-white" : "bg-[var(--appkit-color-surface-elevated)] text-[var(--appkit-color-text-muted)] dark:text-[var(--appkit-color-text-faint)]"}`, align: "center", justify: "center", rounded: "full", children: done ? "✓" : step.n }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", weight: "medium", color: "primary", children: step.title }), _jsx(Text, { className: "mt-0.5", color: "muted", size: "xs", children: step.body })] })] }, step.n));
|
|
190
|
-
}) })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsx(Heading, { level: 2, size: "sm", weight: "semibold", color: "primary", children: "Connection" }), isLoading ? null : cfg?.connected ? (_jsx(Badge, { variant: "success", children: "Connected" })) : (_jsx(Badge, { variant: "default", children: "Not configured" }))] }), _jsxs(Form, { onSubmit: (e) => {
|
|
192
|
+
}) })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsx(Heading, { level: 2, size: "sm", weight: "semibold", color: "primary", children: "Connection" }), isLoading ? null : cfg?.connected ? (_jsx(Badge, { variant: "success", children: "Connected" })) : (_jsx(Badge, { variant: "default", children: "Not configured" }))] }), _jsxs(Form, { schema: whatsappSettingsSchema, onSubmit: (e) => {
|
|
191
193
|
e.preventDefault();
|
|
192
194
|
saveMutation.mutate();
|
|
193
|
-
}, spacing: "md", children: [_jsx(Input, { label: "WhatsApp Business Phone Number", value: phoneNumber, onChange: (e) => setPhoneNumber(e.target.value), placeholder: "919876543210", helperText: "Digits only, include country code (e.g. 91 for India)" }), _jsx(Input, { label: "WABA ID (WhatsApp Business Account ID)", value: wabaId, onChange: (e) => setWabaId(e.target.value), placeholder: "123456789012345", helperText: "From Meta Business Manager \u2192 WhatsApp Accounts" }), _jsx(Input, { label: "Catalog ID", value: catalogId, onChange: (e) => setCatalogId(e.target.value), placeholder: "987654321098765", helperText: "From Meta Commerce Manager \u2192 Catalogs" }), _jsx(MaskedTokenInput, { label: "System User Access Token", value: accessToken, onChange: setAccessToken, placeholder: "EAAxxxxxxxx\u2026", helperText: "Long-lived token with WhatsApp Business permissions" }), _jsx(FormActions, { align: "right", children: _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: saveMutation.isPending, children: saveMutation.isPending ? "Saving…" : ACTIONS.STORE["whatsapp-connect"].label }) })] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "mb-4", color: "primary", size: "sm", weight: "semibold", children: "Catalog Sync" }), _jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsxs(Div, { children: [_jsx(Text, { size: "sm", color: "muted", children: "Enable catalog sync" }), _jsx(Text, { size: "xs", color: "muted", children: "When enabled, your published standard products can be synced to WhatsApp." })] }), _jsx(Toggle, { checked: syncEnabled, onChange: setSyncEnabled, disabled: !cfg?.connected })] }), cfg?.lastCatalogSyncAt && (_jsxs(Row, { color: "muted", textSize: "xs", gap: "sm", align: "center", className: "mb-3", children: [_jsxs(Text, { children: ["Last sync: ", new Date(cfg.lastCatalogSyncAt).toLocaleString("en-IN")] }), cfg.lastSyncCount !== undefined && _jsxs(Text, { children: ["\u00B7 ", cfg.lastSyncCount, " products"] }), cfg.lastSyncStatus && (_jsx(Badge, { variant: STATUS_VARIANT[cfg.lastSyncStatus] ?? "default", children: cfg.lastSyncStatus }))] })), _jsx(Text, { className: "mb-3", color: "faint", size: "xs", children: "Only published standard products are synced. Auctions and pre-orders are excluded. Batches of up to 50 products per call." }), _jsxs(Row, { gap: "3", children: [_jsx(Button, { onClick: () => syncMutation.mutate(), isLoading: syncMutation.isPending, disabled: !cfg?.connected || !syncEnabled || syncMutation.isPending, variant: "secondary", children: syncMutation.isPending ? "Syncing…" : ACTIONS.STORE["whatsapp-catalog-sync"].label }), _jsx(Button, { onClick: () => void startImport(), isLoading: importing, disabled: !cfg?.connected || !syncEnabled || importing, variant: "secondary", children: importing ? "Importing…" : ACTIONS.STORE["whatsapp-catalog-import"].label })] }), _jsxs(Text, { className: "mt-3", color: "faint", size: "xs", children: [_jsx(Span, { weight: "bold", children: "Push" }), " sends your published standard products to WhatsApp.", " ", _jsx(Span, { weight: "bold", children: "Import" }), " creates draft products from your WhatsApp catalog. Products are matched by slug in the description field."] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "mb-2", color: "primary", size: "sm", weight: "semibold", children: "Purchase Announcement Preview" }), _jsx(Text, { className: "mb-3", color: "muted", size: "xs", children: "This message is sent automatically to your phone and the platform admin when a new order is placed." }), _jsx(Div, { textSize: "sm", className: "font-mono", color: "primary", surface: "muted", padding: "inline", rounded: "lg", children: buildPurchaseAnnouncementMessage({
|
|
195
|
+
}, spacing: "md", children: [_jsx(FormErrorSummary, {}), _jsx(Input, { label: "WhatsApp Business Phone Number", value: phoneNumber, onChange: (e) => setPhoneNumber(e.target.value), placeholder: "919876543210", helperText: "Digits only, include country code (e.g. 91 for India)" }), _jsx(Input, { label: "WABA ID (WhatsApp Business Account ID)", value: wabaId, onChange: (e) => setWabaId(e.target.value), placeholder: "123456789012345", helperText: "From Meta Business Manager \u2192 WhatsApp Accounts" }), _jsx(Input, { label: "Catalog ID", value: catalogId, onChange: (e) => setCatalogId(e.target.value), placeholder: "987654321098765", helperText: "From Meta Commerce Manager \u2192 Catalogs" }), _jsx(MaskedTokenInput, { label: "System User Access Token", value: accessToken, onChange: setAccessToken, placeholder: "EAAxxxxxxxx\u2026", helperText: "Long-lived token with WhatsApp Business permissions" }), _jsx(FormActions, { align: "right", children: _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: saveMutation.isPending, children: saveMutation.isPending ? "Saving…" : ACTIONS.STORE["whatsapp-connect"].label }) })] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "mb-4", color: "primary", size: "sm", weight: "semibold", children: "Catalog Sync" }), _jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsxs(Div, { children: [_jsx(Text, { size: "sm", color: "muted", children: "Enable catalog sync" }), _jsx(Text, { size: "xs", color: "muted", children: "When enabled, your published standard products can be synced to WhatsApp." })] }), _jsx(Toggle, { checked: syncEnabled, onChange: setSyncEnabled, disabled: !cfg?.connected })] }), cfg?.lastCatalogSyncAt && (_jsxs(Row, { color: "muted", textSize: "xs", gap: "sm", align: "center", className: "mb-3", children: [_jsxs(Text, { children: ["Last sync: ", new Date(cfg.lastCatalogSyncAt).toLocaleString("en-IN")] }), cfg.lastSyncCount !== undefined && _jsxs(Text, { children: ["\u00B7 ", cfg.lastSyncCount, " products"] }), cfg.lastSyncStatus && (_jsx(Badge, { variant: STATUS_VARIANT[cfg.lastSyncStatus] ?? "default", children: cfg.lastSyncStatus }))] })), _jsx(Text, { className: "mb-3", color: "faint", size: "xs", children: "Only published standard products are synced. Auctions and pre-orders are excluded. Batches of up to 50 products per call." }), _jsxs(Row, { gap: "3", children: [_jsx(Button, { onClick: () => syncMutation.mutate(), isLoading: syncMutation.isPending, disabled: !cfg?.connected || !syncEnabled || syncMutation.isPending, variant: "secondary", children: syncMutation.isPending ? "Syncing…" : ACTIONS.STORE["whatsapp-catalog-sync"].label }), _jsx(Button, { onClick: () => void startImport(), isLoading: importing, disabled: !cfg?.connected || !syncEnabled || importing, variant: "secondary", children: importing ? "Importing…" : ACTIONS.STORE["whatsapp-catalog-import"].label })] }), _jsxs(Text, { className: "mt-3", color: "faint", size: "xs", children: [_jsx(Span, { weight: "bold", children: "Push" }), " sends your published standard products to WhatsApp.", " ", _jsx(Span, { weight: "bold", children: "Import" }), " creates draft products from your WhatsApp catalog. Products are matched by slug in the description field."] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "mb-2", color: "primary", size: "sm", weight: "semibold", children: "Purchase Announcement Preview" }), _jsx(Text, { className: "mb-3", color: "muted", size: "xs", children: "This message is sent automatically to your phone and the platform admin when a new order is placed." }), _jsx(Div, { textSize: "sm", className: "font-mono", color: "primary", surface: "muted", padding: "inline", rounded: "lg", children: buildPurchaseAnnouncementMessage({
|
|
194
196
|
buyerName: "Ravi K.",
|
|
195
197
|
firstItemName: "Charizard PSA 9",
|
|
196
198
|
additionalItemCount: 2,
|
package/dist/index.d.ts
CHANGED
|
@@ -3203,8 +3203,6 @@ export { CommandPalette, useCommandPaletteHotkey } from "./features/shell/index"
|
|
|
3203
3203
|
export type { CommandPaletteGroup, CommandPaletteProps } from "./features/shell/index";
|
|
3204
3204
|
export { QuickFormDrawer } from "./features/shell/index";
|
|
3205
3205
|
export type { QuickFieldType, QuickFieldDef, QuickFormDrawerProps } from "./features/shell/index";
|
|
3206
|
-
export { StepForm, StepFormActions, StepIndicator } from "./features/shell/index";
|
|
3207
|
-
export type { StepDef, StepFormProps, StepFormActionsProps } from "./features/shell/index";
|
|
3208
3206
|
export { SectionForm, useSectionFormNav, orderSections, buildFieldToSectionIndex, sectionAnchorId, } from "./features/shell/index";
|
|
3209
3207
|
export type { SectionDef, SectionFormProps, UseSectionFormNavResult } from "./features/shell/index";
|
|
3210
3208
|
export { deriveQuickFields, deriveQuickFieldNames, allDefinitionFields, applyDerive, assertNoDeriveCollision, humaniseFieldName, } from "./features/shell/index";
|
|
@@ -3291,3 +3289,6 @@ export { scamReportFormSchema } from "./features/scams/schemas/report-form";
|
|
|
3291
3289
|
export { sublistingCategoryFormSchema } from "./features/store-extensions/schemas/sublisting-category-form";
|
|
3292
3290
|
export { adminAddressFormSchema, adminStoreUpdateSchema, announcementBarSchema, } from "./features/admin/schemas/admin-editor-forms";
|
|
3293
3291
|
export { adminOrderUpdateSchema, employeeInviteSchema, hardBanReasonSchema, featureFlagsUpdateSchema, adminAdFormSchema, } from "./features/admin/schemas/admin-ops-forms";
|
|
3292
|
+
export { changeEmailSchema } from "./features/account/schemas/index";
|
|
3293
|
+
export { adminUserUpdateSchema, whatsappSettingsSchema, lotteryPullSchema, } from "./features/admin/schemas/admin-user-form";
|
|
3294
|
+
export { siteSettingsFormSchema } from "./features/admin/schemas/site-settings-form";
|
package/dist/index.js
CHANGED
|
@@ -5608,9 +5608,8 @@ export { FormShell, useFormShell } from "./features/shell/index";
|
|
|
5608
5608
|
export { CommandPalette, useCommandPaletteHotkey } from "./features/shell/index";
|
|
5609
5609
|
// [CLIENT] QuickFormDrawer â€" 40% desktop / 100% mobile auto-rendered field drawer.
|
|
5610
5610
|
export { QuickFormDrawer } from "./features/shell/index";
|
|
5611
|
-
// [CLIENT]
|
|
5612
|
-
|
|
5613
|
-
// [CLIENT] SectionForm — collapsible-section form engine replacing StepForm.
|
|
5611
|
+
// [CLIENT] SectionForm — collapsible-section form engine. Replaced StepForm,
|
|
5612
|
+
// which was deleted 2026-08-26.
|
|
5614
5613
|
// Required section first and always open, one shared submit at the bottom, no
|
|
5615
5614
|
// per-section gate blocking a later section.
|
|
5616
5615
|
export { SectionForm, useSectionFormNav, orderSections, buildFieldToSectionIndex, sectionAnchorId, } from "./features/shell/index";
|
|
@@ -5700,3 +5699,6 @@ export { scamReportFormSchema } from "./features/scams/schemas/report-form";
|
|
|
5700
5699
|
export { sublistingCategoryFormSchema } from "./features/store-extensions/schemas/sublisting-category-form";
|
|
5701
5700
|
export { adminAddressFormSchema, adminStoreUpdateSchema, announcementBarSchema, } from "./features/admin/schemas/admin-editor-forms";
|
|
5702
5701
|
export { adminOrderUpdateSchema, employeeInviteSchema, hardBanReasonSchema, featureFlagsUpdateSchema, adminAdFormSchema, } from "./features/admin/schemas/admin-ops-forms";
|
|
5702
|
+
export { changeEmailSchema } from "./features/account/schemas/index";
|
|
5703
|
+
export { adminUserUpdateSchema, whatsappSettingsSchema, lotteryPullSchema, } from "./features/admin/schemas/admin-user-form";
|
|
5704
|
+
export { siteSettingsFormSchema } from "./features/admin/schemas/site-settings-form";
|