@rovela-ai/sdk 0.9.0 → 0.9.2
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.
|
@@ -23,7 +23,7 @@ export function GroupVisibilityPicker({ value, onChange, noun = 'option', classN
|
|
|
23
23
|
: selectedNames.length > 0
|
|
24
24
|
? selectedNames.join(', ')
|
|
25
25
|
: `${value.length} group${value.length === 1 ? '' : 's'}`;
|
|
26
|
-
return (_jsxs("div", { className: className, children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center gap-1.5 text-left text-xs text-[hsl(var(--admin-foreground-muted))] hover:text-[hsl(var(--admin-foreground))]", "aria-expanded": open, children: [_jsx(ChevronRight, { className: `h-3 w-3 shrink-0 transition-transform ${open ? 'rotate-90' : ''}` }), _jsx(Users, { className: "h-3 w-3 shrink-0" }), _jsxs("span", { children: ["Visibility: ", _jsx("span", { className: "font-medium", children: summary })] })] }), open && (_jsxs("div", { className: "mt-2 space-y-2 rounded-
|
|
26
|
+
return (_jsxs("div", { className: className, children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex w-full items-center gap-1.5 text-left text-xs text-[hsl(var(--admin-foreground-muted))] hover:text-[hsl(var(--admin-foreground))]", "aria-expanded": open, children: [_jsx(ChevronRight, { className: `h-3 w-3 shrink-0 transition-transform ${open ? 'rotate-90' : ''}` }), _jsx(Users, { className: "h-3 w-3 shrink-0" }), _jsxs("span", { children: ["Visibility: ", _jsx("span", { className: "font-medium", children: summary })] })] }), open && (_jsxs("div", { className: "mt-2 space-y-2 rounded-lg border border-[hsl(var(--admin-border))] p-4", children: [_jsxs("p", { className: "text-xs text-[hsl(var(--admin-foreground-muted))]", children: ["Restrict this ", noun, " to specific customer groups. With nothing selected, everyone sees it \u2014 including guests."] }), groups.length === 0 ? (_jsx("p", { className: "text-xs text-[hsl(var(--admin-foreground-muted))]", children: "No customer groups yet \u2014 create them from Customers \u2192 Manage groups." })) : (_jsx("div", { className: "flex flex-wrap gap-x-4 gap-y-2", children: groups.map((g) => (_jsxs("label", { className: "flex items-center gap-2 text-sm", children: [_jsx("input", { type: "checkbox", className: "admin-checkbox", checked: value.includes(g.id), onChange: (e) => onChange(e.target.checked
|
|
27
27
|
? [...value, g.id]
|
|
28
28
|
: value.filter((x) => x !== g.id)) }), g.name] }, g.id))) })), value.length > 0 && (_jsx("button", { type: "button", onClick: () => onChange([]), className: "admin-action-link text-xs", children: "Reset to everyone" }))] }))] }));
|
|
29
29
|
}
|
|
@@ -191,7 +191,7 @@ export function LocationsManager({ className = '' }) {
|
|
|
191
191
|
setDeleteError(res.error || 'Failed to delete the location');
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
-
return (_jsxs("div", { className: `admin-card ${className}`, children: [_jsx("div", { className: "admin-card-header", children: _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(MapPin, { className: "h-5 w-5 text-[hsl(var(--admin-primary))]" }), _jsx("h2", { className: "text-lg font-semibold text-[hsl(var(--admin-foreground))]", children: "Locations" })] }), editing === null && (_jsxs("button", { type: "button", onClick: startCreate, className: "admin-btn admin-btn-primary admin-btn-sm inline-flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add location"] }))] }) }), _jsxs("div", { className: "p-6", children: [_jsx("p", { className: "mb-4 text-sm text-[hsl(var(--admin-foreground-muted))]", children: "Your physical shops. Locations with pickup enabled appear at checkout as \u201CPick up in store\u201D \u2014 customers choose one instead of entering a shipping address, and you hand the order over on site." }), (error || actionError) && (_jsx("div", { className: "admin-alert-inline admin-alert-inline-error mb-4", children: actionError || error })), editing !== null ? (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-name", children: "Name" }), _jsx("input", { id: "loc-name", className: "admin-input w-full", value: form.name, onChange: (e) => set({ name: e.target.value }), placeholder: "e.g. Paris \u2014 Bastille", maxLength: 255 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-description", children: "Description (optional)" }), _jsx("textarea", { id: "loc-description", className: "admin-input w-full", rows: 2, value: form.description, onChange: (e) => set({ description: e.target.value }), placeholder: "Shown to customers when they pick this store", maxLength: 2000 })] })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: "Address" }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "sm:col-span-2", children: [_jsx("label", { className: "admin-label", htmlFor: "loc-address1", children: "Address line 1" }), _jsx("input", { id: "loc-address1", className: "admin-input w-full", value: form.address1, onChange: (e) => set({ address1: e.target.value }), maxLength: 255 })] }), _jsxs("div", { className: "sm:col-span-2", children: [_jsx("label", { className: "admin-label", htmlFor: "loc-address2", children: "Address line 2 (optional)" }), _jsx("input", { id: "loc-address2", className: "admin-input w-full", value: form.address2, onChange: (e) => set({ address2: e.target.value }), maxLength: 255 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-city", children: "City" }), _jsx("input", { id: "loc-city", className: "admin-input w-full", value: form.city, onChange: (e) => set({ city: e.target.value }), maxLength: 100 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-postal", children: "Postal code" }), _jsx("input", { id: "loc-postal", className: "admin-input w-full", value: form.postalCode, onChange: (e) => set({ postalCode: e.target.value }), maxLength: 20 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-state", children: "State / region (optional)" }), _jsx("input", { id: "loc-state", className: "admin-input w-full", value: form.state, onChange: (e) => set({ state: e.target.value }), maxLength: 100 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-country", children: "Country" }), _jsxs("select", { id: "loc-country", className: "admin-input w-full", value: form.country, onChange: (e) => set({ country: e.target.value }), children: [_jsx("option", { value: "", children: "\u2014" }), countryOptions.map((c) => (_jsx("option", { value: c.code, children: c.name }, c.code)))] })] })] })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: "Contact" }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-phone", children: "Phone (optional)" }), _jsx("input", { id: "loc-phone", className: "admin-input w-full", value: form.phone, onChange: (e) => set({ phone: e.target.value }), maxLength: 50 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-email", children: "Email (optional)" }), _jsx("input", { id: "loc-email", type: "email", className: "admin-input w-full", value: form.email, onChange: (e) => set({ email: e.target.value }), maxLength: 255 })] })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("h3", { className: "text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: "Photo (optional)" }), _jsx("div", { className: "max-w-md", children: _jsx(ImageUpload, { value: form.imageUrl || null, onChange: (url) => set({ imageUrl: url ?? '' }), folder: "locations", entityId: editing === 'new' ? 'new' : editing, placeholder: "Upload a storefront photo" }) })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("h3", { className: "flex items-center gap-1.5 text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: [_jsx(Clock, { className: "h-4 w-4" }), "Opening hours"] }), _jsx("button", { type: "button", onClick: copyMondayToAll, className: "admin-action-link text-xs", children: "Apply Monday to all days" })] }), _jsx("div", { className: "space-y-2", children: form.openingHours.map((h) => (_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsx("span", { className: "w-24 text-sm text-[hsl(var(--admin-foreground))]", children: DAY_LABELS[h.day] }), _jsxs("label", { className: "flex items-center gap-1.5 text-xs text-[hsl(var(--admin-foreground-muted))]", children: [_jsx("input", { type: "checkbox", className: "admin-checkbox", checked: h.closed, onChange: (e) => setDay(h.day, { closed: e.target.checked }) }), "Closed"] }), !h.closed && (_jsxs(_Fragment, { children: [_jsxs("select", { className: "admin-input w-24", value: h.open ?? '', onChange: (e) => setDay(h.day, { open: e.target.value }), "aria-label": `${DAY_LABELS[h.day]} opening time`, children: [_jsx("option", { value: "", children: "\u2014" }), TIME_OPTIONS.map((t) => (_jsx("option", { value: t.value, children: t.label }, t.value)))] }), _jsx("span", { className: "text-xs text-[hsl(var(--admin-foreground-muted))]", children: "to" }), _jsxs("select", { className: "admin-input w-24", value: h.close ?? '', onChange: (e) => setDay(h.day, { close: e.target.value }), "aria-label": `${DAY_LABELS[h.day]} closing time`, children: [_jsx("option", { value: "", children: "\u2014" }), TIME_OPTIONS.map((t) => (_jsx("option", { value: t.value, children: t.label }, t.value)))] })] }))] }, h.day))) })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: "Click & collect" }), _jsxs("label", { className: "flex items-center gap-2 text-sm text-[hsl(var(--admin-foreground))]", children: [_jsx("input", { type: "checkbox", className: "admin-checkbox", checked: form.pickupEnabled, onChange: (e) => set({ pickupEnabled: e.target.checked }) }), "Offer in-store pickup at this location"] }), form.pickupEnabled && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "max-w-xs", children: [_jsx("label", { className: "admin-label", children: "Preparation time" }), _jsx(AdminSelect, { value: form.preparationTime, onChange: (value) => set({ preparationTime: value }), options: PREP_TIME_OPTIONS })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-instructions", children: "Pickup instructions (optional)" }), _jsx("textarea", { id: "loc-instructions", className: "admin-input w-full", rows: 2, value: form.pickupInstructions, onChange: (e) => set({ pickupInstructions: e.target.value }), placeholder: "Sent in the \u201Cready for pickup\u201D email, e.g. which counter to visit and what to bring", maxLength: 2000 })] })] }))] }), _jsxs("label", { className: "flex items-center gap-2 text-sm text-[hsl(var(--admin-foreground))]", children: [_jsx("input", { type: "checkbox", className: "admin-checkbox", checked: form.isActive, onChange: (e) => set({ isActive: e.target.checked }) }), "Active"] }), _jsxs("div", { className: "flex items-center gap-2 border-t border-[hsl(var(--admin-border))] pt-4", children: [_jsx("button", { type: "button", onClick: handleSave, disabled: isSaving, className: "admin-btn admin-btn-primary disabled:opacity-50", children: isSaving ? 'Saving…' : editing === 'new' ? 'Create location' : 'Save changes' }), _jsx("button", { type: "button", onClick: () => setEditing(null), disabled: isSaving, className: "admin-btn admin-btn-secondary", children: "Cancel" })] })] })) : isLoading && locations.length === 0 ? (_jsx("div", { className: "space-y-3", children: Array.from({ length: 2 }).map((_, i) => (_jsx("div", { className: "admin-skeleton h-16 w-full rounded" }, i))) })) : locations.length === 0 ? (_jsxs("div", { className: "admin-empty-state py-12 text-center", children: [_jsx(Store, { className: "mx-auto h-8 w-8 admin-empty-icon" }), _jsx("p", { className: "mt-2 admin-empty-text text-sm", children: "No locations yet. Add your first shop to offer in-store pickup." })] })) : (_jsx("ul", { className: "divide-y divide-[hsl(var(--admin-border))]", children: locations.map((l) => (_jsx("li", { className: "py-3", children: _jsxs("div", { className: "flex items-start gap-3", children: [l.imageUrl ? (
|
|
194
|
+
return (_jsxs("div", { className: `admin-card ${className}`, children: [_jsx("div", { className: "admin-card-header", children: _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(MapPin, { className: "h-5 w-5 text-[hsl(var(--admin-primary))]" }), _jsx("h2", { className: "text-lg font-semibold text-[hsl(var(--admin-foreground))]", children: "Locations" })] }), editing === null && (_jsxs("button", { type: "button", onClick: startCreate, className: "admin-btn admin-btn-primary admin-btn-sm inline-flex items-center gap-1.5", children: [_jsx(Plus, { className: "h-4 w-4" }), "Add location"] }))] }) }), _jsxs("div", { className: "p-6", children: [_jsx("p", { className: "mb-4 text-sm text-[hsl(var(--admin-foreground-muted))]", children: "Your physical shops. Locations with pickup enabled appear at checkout as \u201CPick up in store\u201D \u2014 customers choose one instead of entering a shipping address, and you hand the order over on site." }), (error || actionError) && (_jsx("div", { className: "admin-alert-inline admin-alert-inline-error mb-4", children: actionError || error })), editing !== null ? (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-name", children: "Name" }), _jsx("input", { id: "loc-name", className: "admin-input w-full", value: form.name, onChange: (e) => set({ name: e.target.value }), placeholder: "e.g. Paris \u2014 Bastille", maxLength: 255 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-description", children: "Description (optional)" }), _jsx("textarea", { id: "loc-description", className: "admin-input w-full", rows: 3, value: form.description, onChange: (e) => set({ description: e.target.value }), placeholder: "Shown to customers when they pick this store", maxLength: 2000 })] })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: "Address" }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { className: "sm:col-span-2", children: [_jsx("label", { className: "admin-label", htmlFor: "loc-address1", children: "Address line 1" }), _jsx("input", { id: "loc-address1", className: "admin-input w-full", value: form.address1, onChange: (e) => set({ address1: e.target.value }), maxLength: 255 })] }), _jsxs("div", { className: "sm:col-span-2", children: [_jsx("label", { className: "admin-label", htmlFor: "loc-address2", children: "Address line 2 (optional)" }), _jsx("input", { id: "loc-address2", className: "admin-input w-full", value: form.address2, onChange: (e) => set({ address2: e.target.value }), maxLength: 255 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-city", children: "City" }), _jsx("input", { id: "loc-city", className: "admin-input w-full", value: form.city, onChange: (e) => set({ city: e.target.value }), maxLength: 100 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-postal", children: "Postal code" }), _jsx("input", { id: "loc-postal", className: "admin-input w-full", value: form.postalCode, onChange: (e) => set({ postalCode: e.target.value }), maxLength: 20 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-state", children: "State / region (optional)" }), _jsx("input", { id: "loc-state", className: "admin-input w-full", value: form.state, onChange: (e) => set({ state: e.target.value }), maxLength: 100 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-country", children: "Country" }), _jsxs("select", { id: "loc-country", className: "admin-input w-full", value: form.country, onChange: (e) => set({ country: e.target.value }), children: [_jsx("option", { value: "", children: "\u2014" }), countryOptions.map((c) => (_jsx("option", { value: c.code, children: c.name }, c.code)))] })] })] })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: "Contact" }), _jsxs("div", { className: "grid gap-4 sm:grid-cols-2", children: [_jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-phone", children: "Phone (optional)" }), _jsx("input", { id: "loc-phone", className: "admin-input w-full", value: form.phone, onChange: (e) => set({ phone: e.target.value }), maxLength: 50 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-email", children: "Email (optional)" }), _jsx("input", { id: "loc-email", type: "email", className: "admin-input w-full", value: form.email, onChange: (e) => set({ email: e.target.value }), maxLength: 255 })] })] })] }), _jsxs("div", { className: "space-y-2", children: [_jsx("h3", { className: "text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: "Photo (optional)" }), _jsx("div", { className: "max-w-md", children: _jsx(ImageUpload, { value: form.imageUrl || null, onChange: (url) => set({ imageUrl: url ?? '' }), folder: "locations", entityId: editing === 'new' ? 'new' : editing, placeholder: "Upload a storefront photo" }) })] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("h3", { className: "flex items-center gap-1.5 text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: [_jsx(Clock, { className: "h-4 w-4" }), "Opening hours"] }), _jsx("button", { type: "button", onClick: copyMondayToAll, className: "admin-action-link text-xs", children: "Apply Monday to all days" })] }), _jsx("div", { className: "space-y-2", children: form.openingHours.map((h) => (_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsx("span", { className: "w-24 text-sm text-[hsl(var(--admin-foreground))]", children: DAY_LABELS[h.day] }), _jsxs("label", { className: "flex items-center gap-1.5 text-xs text-[hsl(var(--admin-foreground-muted))]", children: [_jsx("input", { type: "checkbox", className: "admin-checkbox", checked: h.closed, onChange: (e) => setDay(h.day, { closed: e.target.checked }) }), "Closed"] }), !h.closed && (_jsxs(_Fragment, { children: [_jsxs("select", { className: "admin-input w-24", value: h.open ?? '', onChange: (e) => setDay(h.day, { open: e.target.value }), "aria-label": `${DAY_LABELS[h.day]} opening time`, children: [_jsx("option", { value: "", children: "\u2014" }), TIME_OPTIONS.map((t) => (_jsx("option", { value: t.value, children: t.label }, t.value)))] }), _jsx("span", { className: "text-xs text-[hsl(var(--admin-foreground-muted))]", children: "to" }), _jsxs("select", { className: "admin-input w-24", value: h.close ?? '', onChange: (e) => setDay(h.day, { close: e.target.value }), "aria-label": `${DAY_LABELS[h.day]} closing time`, children: [_jsx("option", { value: "", children: "\u2014" }), TIME_OPTIONS.map((t) => (_jsx("option", { value: t.value, children: t.label }, t.value)))] })] }))] }, h.day))) })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-sm font-semibold text-[hsl(var(--admin-foreground))]", children: "Click & collect" }), _jsxs("label", { className: "flex items-center gap-2 text-sm text-[hsl(var(--admin-foreground))]", children: [_jsx("input", { type: "checkbox", className: "admin-checkbox", checked: form.pickupEnabled, onChange: (e) => set({ pickupEnabled: e.target.checked }) }), "Offer in-store pickup at this location"] }), form.pickupEnabled && (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "max-w-xs", children: [_jsx("label", { className: "admin-label", children: "Preparation time" }), _jsx(AdminSelect, { value: form.preparationTime, onChange: (value) => set({ preparationTime: value }), options: PREP_TIME_OPTIONS })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", htmlFor: "loc-instructions", children: "Pickup instructions (optional)" }), _jsx("textarea", { id: "loc-instructions", className: "admin-input w-full", rows: 4, value: form.pickupInstructions, onChange: (e) => set({ pickupInstructions: e.target.value }), placeholder: "Sent in the \u201Cready for pickup\u201D email, e.g. which counter to visit and what to bring", maxLength: 2000 })] })] }))] }), _jsxs("label", { className: "flex items-center gap-2 text-sm text-[hsl(var(--admin-foreground))]", children: [_jsx("input", { type: "checkbox", className: "admin-checkbox", checked: form.isActive, onChange: (e) => set({ isActive: e.target.checked }) }), "Active"] }), _jsxs("div", { className: "flex items-center gap-2 border-t border-[hsl(var(--admin-border))] pt-4", children: [_jsx("button", { type: "button", onClick: handleSave, disabled: isSaving, className: "admin-btn admin-btn-primary disabled:opacity-50", children: isSaving ? 'Saving…' : editing === 'new' ? 'Create location' : 'Save changes' }), _jsx("button", { type: "button", onClick: () => setEditing(null), disabled: isSaving, className: "admin-btn admin-btn-secondary", children: "Cancel" })] })] })) : isLoading && locations.length === 0 ? (_jsx("div", { className: "space-y-3", children: Array.from({ length: 2 }).map((_, i) => (_jsx("div", { className: "admin-skeleton h-16 w-full rounded" }, i))) })) : locations.length === 0 ? (_jsxs("div", { className: "admin-empty-state py-12 text-center", children: [_jsx(Store, { className: "mx-auto h-8 w-8 admin-empty-icon" }), _jsx("p", { className: "mt-2 admin-empty-text text-sm", children: "No locations yet. Add your first shop to offer in-store pickup." })] })) : (_jsx("ul", { className: "divide-y divide-[hsl(var(--admin-border))]", children: locations.map((l) => (_jsx("li", { className: "py-3", children: _jsxs("div", { className: "flex items-start gap-3", children: [l.imageUrl ? (
|
|
195
195
|
// 48px admin-only thumbnail; next/image perf wins don't apply here
|
|
196
196
|
// eslint-disable-next-line @next/next/no-img-element
|
|
197
197
|
_jsx("img", { src: l.imageUrl, alt: l.name, className: "h-12 w-12 shrink-0 rounded object-cover" })) : (_jsx("div", { className: "admin-image-placeholder flex h-12 w-12 shrink-0 items-center justify-center rounded", children: _jsx(Store, { className: "h-5 w-5", strokeWidth: 1.5 }) })), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("p", { className: "font-medium text-[hsl(var(--admin-foreground))]", children: l.name }), l.pickupEnabled && (_jsx("span", { className: "admin-badge admin-badge-paid", children: "Pickup" })), !l.isActive && (_jsx("span", { className: "admin-badge admin-badge-neutral", children: "Inactive" }))] }), _jsx("p", { className: "mt-0.5 truncate text-sm text-[hsl(var(--admin-foreground-muted))]", children: addressSummary(l) || 'No address yet' }), l.preparationTime && (_jsxs("p", { className: "mt-0.5 text-xs text-[hsl(var(--admin-foreground-muted))]", children: ["Usually ready in ", l.preparationTime] }))] }), _jsxs("div", { className: "flex shrink-0 items-center gap-3 whitespace-nowrap", children: [_jsxs("label", { className: "flex items-center gap-1.5 text-xs text-[hsl(var(--admin-foreground-muted))]", children: [_jsx("input", { type: "checkbox", className: "admin-checkbox", checked: l.isActive, onChange: () => handleToggleActive(l) }), "Active"] }), _jsxs("button", { onClick: () => startEdit(l), className: "admin-action-link inline-flex items-center gap-1", children: [_jsx(Pencil, { className: "h-3 w-3" }), "Edit"] }), _jsxs("button", { onClick: () => {
|
|
@@ -87,10 +87,10 @@ export function PaymentMethodsManager({ className = '' }) {
|
|
|
87
87
|
return (_jsxs("div", { className: `admin-card ${className}`, children: [_jsx("div", { className: "admin-card-header", children: _jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Wallet, { className: "h-5 w-5 text-[hsl(var(--admin-primary))]" }), _jsx("h2", { className: "text-lg font-semibold text-[hsl(var(--admin-foreground))]", children: "Payment Methods" })] }), !showCreate && (_jsxs("button", { type: "button", onClick: () => {
|
|
88
88
|
setActionError(null);
|
|
89
89
|
setShowCreate(true);
|
|
90
|
-
}, className: "admin-btn admin-btn-secondary admin-btn-sm inline-flex items-center gap-1", children: [_jsx(Plus, { className: "h-3 w-3" }), "Add method"] }))] }) }), _jsxs("div", { className: "admin-card-body", children: [_jsxs("p", { className: "mb-4 text-sm text-[hsl(var(--admin-foreground-muted))]", children: ["Offer payment options beyond card payments \u2014 cash on delivery, bank wire, check\u2026 Orders placed with these methods start as ", _jsx("strong", { children: "Pending" }), "; mark them", _jsx("strong", { children: " Paid" }), " from the order page once you receive the money. Instructions are shown to the customer in their order confirmation email."] }), (error || actionError) && (_jsx("div", { className: "admin-alert-inline admin-alert-inline-error mb-4", children: actionError || error })), showCreate && (_jsxs("div", { className: "mb-4 space-y-3 rounded-lg border border-[hsl(var(--admin-border))] p-4", children: [_jsxs("div", { children: [_jsx("label", { className: "admin-label", children: "Name" }), _jsx("input", { className: "admin-input w-full", value: createForm.name, onChange: (e) => setCreateForm({ ...createForm, name: e.target.value }), placeholder: "e.g. Cash on delivery, Bank transfer", maxLength: 100 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", children: "Customer instructions (optional)" }), _jsx("textarea", { className: "admin-input w-full", rows:
|
|
90
|
+
}, className: "admin-btn admin-btn-secondary admin-btn-sm inline-flex items-center gap-1", children: [_jsx(Plus, { className: "h-3 w-3" }), "Add method"] }))] }) }), _jsxs("div", { className: "admin-card-body", children: [_jsxs("p", { className: "mb-4 text-sm text-[hsl(var(--admin-foreground-muted))]", children: ["Offer payment options beyond card payments \u2014 cash on delivery, bank wire, check\u2026 Orders placed with these methods start as ", _jsx("strong", { children: "Pending" }), "; mark them", _jsx("strong", { children: " Paid" }), " from the order page once you receive the money. Instructions are shown to the customer in their order confirmation email."] }), (error || actionError) && (_jsx("div", { className: "admin-alert-inline admin-alert-inline-error mb-4", children: actionError || error })), showCreate && (_jsxs("div", { className: "mb-4 space-y-3 rounded-lg border border-[hsl(var(--admin-border))] p-4", children: [_jsxs("div", { children: [_jsx("label", { className: "admin-label", children: "Name" }), _jsx("input", { className: "admin-input w-full", value: createForm.name, onChange: (e) => setCreateForm({ ...createForm, name: e.target.value }), placeholder: "e.g. Cash on delivery, Bank transfer", maxLength: 100 })] }), _jsxs("div", { children: [_jsx("label", { className: "admin-label", children: "Customer instructions (optional)" }), _jsx("textarea", { className: "admin-input w-full", rows: 6, value: createForm.instructions, onChange: (e) => setCreateForm({ ...createForm, instructions: e.target.value }), placeholder: "Shown in the order confirmation email \u2014 e.g. bank details for a wire transfer." })] }), _jsx(GroupVisibilityPicker, { value: createForm.visibleToGroups, onChange: (groupIds) => setCreateForm({ ...createForm, visibleToGroups: groupIds }), noun: "payment method" }), _jsxs("div", { className: "flex gap-2", children: [_jsxs("button", { onClick: handleCreate, disabled: isCreating || !createForm.name.trim(), className: "admin-btn admin-btn-primary admin-btn-sm inline-flex items-center gap-1 disabled:opacity-50", children: [_jsx(Check, { className: "h-3 w-3" }), isCreating ? 'Adding…' : 'Add method'] }), _jsxs("button", { onClick: () => {
|
|
91
91
|
setShowCreate(false);
|
|
92
92
|
setCreateForm(EMPTY_FORM);
|
|
93
|
-
}, disabled: isCreating, className: "admin-btn admin-btn-secondary admin-btn-sm inline-flex items-center gap-1", children: [_jsx(X, { className: "h-3 w-3" }), "Cancel"] })] })] })), isLoading ? (_jsx("div", { className: "space-y-2", children: Array.from({ length: 2 }).map((_, i) => (_jsx("div", { className: "admin-skeleton admin-skeleton-lg w-full rounded" }, i))) })) : methods.length === 0 ? (!showCreate && (_jsx("p", { className: "text-sm text-[hsl(var(--admin-foreground-muted))]", children: "No custom payment methods yet. Card payments via Stripe stay available either way." }))) : (_jsx("ul", { className: "divide-y divide-[hsl(var(--admin-border))]", children: methods.map((method) => (_jsx("li", { className: "py-3", children: editingId === method.id ? (_jsxs("div", { className: "space-y-3", children: [_jsx("input", { className: "admin-input w-full", value: editForm.name, onChange: (e) => setEditForm({ ...editForm, name: e.target.value }), maxLength: 100 }), _jsx("textarea", { className: "admin-input w-full", rows:
|
|
93
|
+
}, disabled: isCreating, className: "admin-btn admin-btn-secondary admin-btn-sm inline-flex items-center gap-1", children: [_jsx(X, { className: "h-3 w-3" }), "Cancel"] })] })] })), isLoading ? (_jsx("div", { className: "space-y-2", children: Array.from({ length: 2 }).map((_, i) => (_jsx("div", { className: "admin-skeleton admin-skeleton-lg w-full rounded" }, i))) })) : methods.length === 0 ? (!showCreate && (_jsx("p", { className: "text-sm text-[hsl(var(--admin-foreground-muted))]", children: "No custom payment methods yet. Card payments via Stripe stay available either way." }))) : (_jsx("ul", { className: "divide-y divide-[hsl(var(--admin-border))]", children: methods.map((method) => (_jsx("li", { className: "py-3", children: editingId === method.id ? (_jsxs("div", { className: "space-y-3", children: [_jsx("input", { className: "admin-input w-full", value: editForm.name, onChange: (e) => setEditForm({ ...editForm, name: e.target.value }), maxLength: 100 }), _jsx("textarea", { className: "admin-input w-full", rows: 6, value: editForm.instructions, onChange: (e) => setEditForm({ ...editForm, instructions: e.target.value }), placeholder: "Customer instructions (optional)" }), _jsx(GroupVisibilityPicker, { value: editForm.visibleToGroups, onChange: (groupIds) => setEditForm({ ...editForm, visibleToGroups: groupIds }), noun: "payment method" }), _jsxs("div", { className: "flex gap-2", children: [_jsxs("button", { onClick: handleSaveEdit, disabled: isSavingEdit || !editForm.name.trim(), className: "admin-btn admin-btn-primary admin-btn-sm inline-flex items-center gap-1 disabled:opacity-50", children: [_jsx(Check, { className: "h-3 w-3" }), "Save"] }), _jsxs("button", { onClick: () => setEditingId(null), disabled: isSavingEdit, className: "admin-btn admin-btn-secondary admin-btn-sm inline-flex items-center gap-1", children: [_jsx(X, { className: "h-3 w-3" }), "Cancel"] })] })] })) : (_jsxs("div", { className: "flex items-start gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("p", { className: "font-medium text-[hsl(var(--admin-foreground))]", children: method.name }), !method.enabled && (_jsx("span", { className: "admin-badge admin-badge-neutral", children: "Disabled" })), (method.visibleToGroups?.length ?? 0) > 0 && (_jsx("span", { className: "admin-badge admin-badge-neutral", children: "Group-only" }))] }), method.instructions && (_jsx("p", { className: "mt-0.5 line-clamp-2 text-sm text-[hsl(var(--admin-foreground-muted))]", children: method.instructions }))] }), _jsxs("div", { className: "flex shrink-0 items-center gap-3 whitespace-nowrap", children: [_jsxs("label", { className: "flex items-center gap-1.5 text-xs text-[hsl(var(--admin-foreground-muted))]", children: [_jsx("input", { type: "checkbox", className: "admin-checkbox", checked: method.enabled, onChange: () => handleToggleEnabled(method) }), "Enabled"] }), _jsxs("button", { onClick: () => {
|
|
94
94
|
setEditingId(method.id);
|
|
95
95
|
setEditForm({
|
|
96
96
|
name: method.name,
|
|
@@ -679,6 +679,16 @@
|
|
|
679
679
|
transition: var(--admin-transition-colors), var(--admin-transition-shadow);
|
|
680
680
|
}
|
|
681
681
|
|
|
682
|
+
/* Textareas must size from their `rows` attribute — the fixed 40px height
|
|
683
|
+
above silently squashed every multi-line field (wire instructions, pickup
|
|
684
|
+
instructions, descriptions…) to a single line. */
|
|
685
|
+
.rovela-admin-theme textarea.admin-input {
|
|
686
|
+
height: auto;
|
|
687
|
+
min-height: 2.5rem;
|
|
688
|
+
padding: var(--admin-space-2) var(--admin-space-3);
|
|
689
|
+
resize: vertical;
|
|
690
|
+
}
|
|
691
|
+
|
|
682
692
|
.rovela-admin-theme .admin-input::placeholder {
|
|
683
693
|
color: hsl(var(--admin-foreground-subtle));
|
|
684
694
|
}
|