"use client"; /* eslint-disable react-hooks/set-state-in-effect */ import NextImage from "next/image"; import { useState, useEffect, useRef } from "react"; import { getBrandSettings, saveBrandSettings, uploadBrandLogo, uploadOlatheSweetLogo, uploadOlatheSweetLogoDark, type BrandSettings, } from "@/actions/brand-settings"; import { AdminInput, AdminTextInput, AdminTextarea, AdminSelect } from "./design-system"; type Props = { settings: BrandSettings | null; brandId: string; brandName: string; brands?: { id: string; name: string }[]; isPlatformAdmin?: boolean; }; export default function BrandSettingsForm({ settings, brandId: initialBrandId, brandName: initialBrandName, brands = [], isPlatformAdmin = false, }: Props) { const [activeBrandId, setActiveBrandId] = useState(initialBrandId); const [activeBrandName, setActiveBrandName] = useState(initialBrandName); const [legalBusinessName, setLegalBusinessName] = useState(settings?.legal_business_name ?? ""); const [phone, setPhone] = useState(settings?.phone ?? ""); const [email, setEmail] = useState(settings?.email ?? ""); const [websiteUrl, setWebsiteUrl] = useState(settings?.website_url ?? ""); const [streetAddress, setStreetAddress] = useState(settings?.street_address ?? ""); const [city, setCity] = useState(settings?.city ?? ""); const [state, setState] = useState(settings?.state ?? ""); const [postalCode, setPostalCode] = useState(settings?.postal_code ?? ""); const [country, setCountry] = useState(settings?.country ?? "US"); const [logoUrl, setLogoUrl] = useState(settings?.logo_url ?? ""); const [logoUrlDark, setLogoUrlDark] = useState(settings?.logo_url_dark ?? ""); const [olatheSweetLogoUrl, setOlatheSweetLogoUrl] = useState(settings?.olathe_sweet_logo_url ?? ""); const [olatheSweetLogoUrlDark, setOlatheSweetLogoUrlDark] = useState(settings?.olathe_sweet_logo_url_dark ?? ""); const [defaultEmailSignature, setDefaultEmailSignature] = useState( settings?.default_email_signature ?? "" ); const [invoiceFooterNotes, setInvoiceFooterNotes] = useState( settings?.invoice_footer_notes ?? "" ); // Storefront customization fields const [heroTagline, setHeroTagline] = useState(settings?.hero_tagline ?? ""); const [aboutHeadline, setAboutHeadline] = useState(settings?.about_headline ?? ""); const [aboutSubheadline, setAboutSubheadline] = useState(settings?.about_subheadline ?? ""); const [customFooterText, setCustomFooterText] = useState(settings?.custom_footer_text ?? ""); const [showWholesaleLink, setShowWholesaleLink] = useState(settings?.show_wholesale_link ?? true); const [showZipSearch, setShowZipSearch] = useState(settings?.show_zip_search ?? true); const [showSchedulePdf, setShowSchedulePdf] = useState(settings?.show_schedule_pdf ?? true); const [showTextAlerts, setShowTextAlerts] = useState(settings?.show_text_alerts ?? false); const [schedulePdfNotes, setSchedulePdfNotes] = useState(settings?.schedule_pdf_notes ?? ""); const [heroImageUrl, setHeroImageUrl] = useState(settings?.hero_image_url ?? ""); const [brandPrimaryColor, setBrandPrimaryColor] = useState(settings?.brand_primary_color ?? "#16a34a"); const [brandSecondaryColor, setBrandSecondaryColor] = useState(settings?.brand_secondary_color ?? "#f5f5f4"); const [brandBgColor, setBrandBgColor] = useState(settings?.brand_bg_color ?? "#fafaf9"); const [brandTextColor, setBrandTextColor] = useState(settings?.brand_text_color ?? "#1c1917"); // Tax settings const [collectSalesTax, setCollectSalesTax] = useState(settings?.collect_sales_tax ?? false); const [nexusStates, setNexusStates] = useState(settings?.nexus_states ?? ["CO"]); const [saving, setSaving] = useState(false); const [saved, setSaved] = useState(false); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); // Reload settings when brand changes (platform admin) useEffect(() => { if (!isPlatformAdmin) return; setLoading(true); getBrandSettings(activeBrandId).then((result) => { setLoading(false); if (result.success && result.settings) { const s = result.settings; setLegalBusinessName(s.legal_business_name ?? ""); setPhone(s.phone ?? ""); setEmail(s.email ?? ""); setWebsiteUrl(s.website_url ?? ""); setStreetAddress(s.street_address ?? ""); setCity(s.city ?? ""); setState(s.state ?? ""); setPostalCode(s.postal_code ?? ""); setCountry(s.country ?? "US"); setLogoUrl(s.logo_url ?? ""); setLogoUrlDark(s.logo_url_dark ?? ""); setOlatheSweetLogoUrl(s.olathe_sweet_logo_url ?? ""); setOlatheSweetLogoUrlDark(s.olathe_sweet_logo_url_dark ?? ""); setDefaultEmailSignature(s.default_email_signature ?? ""); setInvoiceFooterNotes(s.invoice_footer_notes ?? ""); setHeroTagline(s.hero_tagline ?? ""); setAboutHeadline(s.about_headline ?? ""); setAboutSubheadline(s.about_subheadline ?? ""); setCustomFooterText(s.custom_footer_text ?? ""); setShowWholesaleLink(s.show_wholesale_link ?? true); setShowZipSearch(s.show_zip_search ?? true); setShowSchedulePdf(s.show_schedule_pdf ?? true); setShowTextAlerts(s.show_text_alerts ?? false); setSchedulePdfNotes(s.schedule_pdf_notes ?? ""); setHeroImageUrl(s.hero_image_url ?? ""); setBrandPrimaryColor(s.brand_primary_color ?? "#16a34a"); setBrandSecondaryColor(s.brand_secondary_color ?? "#f5f5f4"); setBrandBgColor(s.brand_bg_color ?? "#fafaf9"); setBrandTextColor(s.brand_text_color ?? "#1c1917"); setCollectSalesTax(s.collect_sales_tax ?? false); setNexusStates(s.nexus_states ?? ["CO"]); setActiveBrandName(s.brand_name ?? ""); } else { setLegalBusinessName(""); setPhone(""); setEmail(""); setWebsiteUrl(""); setStreetAddress(""); setCity(""); setState(""); setPostalCode(""); setCountry("US"); setLogoUrl(""); setLogoUrlDark(""); setOlatheSweetLogoUrl(""); setOlatheSweetLogoUrlDark(""); setDefaultEmailSignature(""); setInvoiceFooterNotes(""); setHeroTagline(""); setAboutHeadline(""); setAboutSubheadline(""); setCustomFooterText(""); setShowWholesaleLink(true); setShowZipSearch(true); setShowSchedulePdf(true); setShowTextAlerts(false); setSchedulePdfNotes(""); setHeroImageUrl(""); setBrandPrimaryColor("#16a34a"); setBrandSecondaryColor("#f5f5f4"); setBrandBgColor("#fafaf9"); setBrandTextColor("#1c1917"); setCollectSalesTax(false); setNexusStates(["CO"]); } }); }, [activeBrandId, isPlatformAdmin]); async function handleSave(e: React.FormEvent) { e.preventDefault(); setSaving(true); setError(null); setSaved(false); const result = await saveBrandSettings({ brandId: activeBrandId, legalBusinessName: legalBusinessName || undefined, phone: phone || undefined, email: email || undefined, websiteUrl: websiteUrl || undefined, streetAddress: streetAddress || undefined, city: city || undefined, state: state || undefined, postalCode: postalCode || undefined, country: country || undefined, logoUrl: logoUrl || undefined, logoUrlDark: logoUrlDark || undefined, olatheSweetLogoUrl: olatheSweetLogoUrl || undefined, olatheSweetLogoUrlDark: olatheSweetLogoUrlDark || undefined, defaultEmailSignature: defaultEmailSignature || undefined, invoiceFooterNotes: invoiceFooterNotes || undefined, heroTagline: heroTagline || undefined, aboutHeadline: aboutHeadline || undefined, aboutSubheadline: aboutSubheadline || undefined, customFooterText: customFooterText || undefined, showWholesaleLink: showWholesaleLink, showZipSearch: showZipSearch, showSchedulePdf: showSchedulePdf, showTextAlerts: showTextAlerts, schedulePdfNotes: schedulePdfNotes || undefined, heroImageUrl: heroImageUrl || undefined, brandPrimaryColor: brandPrimaryColor || undefined, brandSecondaryColor: brandSecondaryColor || undefined, brandBgColor: brandBgColor || undefined, brandTextColor: brandTextColor || undefined, collectSalesTax, nexusStates, }); setSaving(false); if (!result.success) { setError(result.error ?? "Failed to save"); } else { setSaved(true); setTimeout(() => setSaved(false), 3000); } } return (
{/* Platform admin brand picker */} {isPlatformAdmin && brands.length > 0 && ( setActiveBrandId(e.target.value)} options={brands.map((b) => ({ value: b.id, label: b.name }))} /> )} {error && (
{error}
)} {saved && (
Brand settings saved.
)} {/* Company Info */}

Company Information

Primary contact and business details for this brand.

setLegalBusinessName(e.target.value)} placeholder="Tuxedo Corn LLC" /> setPhone(e.target.value)} placeholder="(772) 555-0100" /> setEmail(e.target.value)} placeholder="orders@tuxedocorn.com" /> setWebsiteUrl(e.target.value)} placeholder="https://tuxedocorn.com" />
{/* Address */}

Business Address

Used on invoices and shipping labels.

setStreetAddress(e.target.value)} placeholder="1234 Farm Road" />
setCity(e.target.value)} placeholder="Stuart" />
setState(e.target.value)} placeholder="FL" maxLength={2} /> setPostalCode(e.target.value)} placeholder="34994" />
setCountry(e.target.value)} options={[ { value: "US", label: "United States" }, { value: "CA", label: "Canada" }, ]} />
{/* Brand Logos */}

Brand Logos

Upload your brand logos to Supabase Storage. Recommended: 1200×400px max, 5MB max (ideally under 2MB for faster loading).

{/* Primary Logo */} setLogoUrl(url)} /> {/* Dark Logo */} setLogoUrlDark(url)} isDark />
{/* Olathe Sweet Logos — two variants */}

Olathe Sweet™ Logo

The mountain & wagon wheel mark — use the light version on dark backgrounds, dark/white version on light backgrounds. Shown in hero, About page, and product cards.

setOlatheSweetLogoUrl(url)} isOlatheSweetLight /> setOlatheSweetLogoUrlDark(url)} isOlatheSweetDark />
{/* Email & Invoice branding */}

Email & Invoice Branding

Used in email signatures, invoice footers, and customer-facing documents.

setDefaultEmailSignature(e.target.value)} rows={3} placeholder={"The Tuxedo Corn Team\norders@tuxedocorn.com | (772) 555-0100\nFresh from Florida since 1987"} /> setInvoiceFooterNotes(e.target.value)} rows={2} placeholder={"Thank you for your order! Pickup available at our farm stand.\nQuestions? Call (772) 555-0100 or email orders@tuxedocorn.com"} />
{/* Storefront Customization */}

Storefront Customization

Controls what appears on your public storefront homepage.

setHeroTagline(e.target.value)} placeholder="Fresh citrus delivered to stops near you." /> setHeroImageUrl(e.target.value)} placeholder="https://cdn.example.com/hero-corn-field.jpg" /> {heroImageUrl && (
)} setAboutHeadline(e.target.value)} placeholder="Our Story" /> setAboutSubheadline(e.target.value)} placeholder="Growing citrus in the Indian River region since 1985." /> setCustomFooterText(e.target.value)} rows={2} placeholder="Fresh from Florida — Ships Sept through May" />
{/* Brand Colors */}

Brand Colors

Customize your storefront accent and background colors. Use hex codes (e.g. #e11d48).

setBrandPrimaryColor(e.target.value)} className="w-10 h-10 rounded-lg border border-zinc-600 cursor-pointer" /> setBrandPrimaryColor(e.target.value)} className="flex-1 rounded-xl border border-zinc-600 bg-zinc-800 px-3 py-2 text-sm text-zinc-100 outline-none focus:border-emerald-500 font-mono" placeholder="#16a34a" />

Buttons, badges, links

setBrandTextColor(e.target.value)} className="w-10 h-10 rounded-lg border border-zinc-600 cursor-pointer" /> setBrandTextColor(e.target.value)} className="flex-1 rounded-xl border border-zinc-600 bg-zinc-800 px-3 py-2 text-sm text-zinc-100 outline-none focus:border-emerald-500 font-mono" placeholder="#1c1917" />

Headlines, body text

setBrandBgColor(e.target.value)} className="w-10 h-10 rounded-lg border border-zinc-600 cursor-pointer" /> setBrandBgColor(e.target.value)} className="flex-1 rounded-xl border border-zinc-600 bg-zinc-800 px-3 py-2 text-sm text-zinc-100 outline-none focus:border-emerald-500 font-mono" placeholder="#fafaf9" />

Page background (light mode)

setBrandSecondaryColor(e.target.value)} className="w-10 h-10 rounded-lg border border-zinc-600 cursor-pointer" /> setBrandSecondaryColor(e.target.value)} className="flex-1 rounded-xl border border-zinc-600 bg-zinc-800 px-3 py-2 text-sm text-zinc-100 outline-none focus:border-emerald-500 font-mono" placeholder="#f5f5f4" />

Hover states, highlights

Preview

A
A
Button
Outline
Secondary
{/* Tax Settings */}

Tax Settings

Configure automatic sales tax collection via Stripe Tax. Tax is only calculated for ship orders shipping to your nexus states.

{collectSalesTax && (

States where you have tax nexus (physical presence). Stripe Tax will calculate tax for ship orders to these states.

)}
{/* Feature Toggles */}

Feature Toggles

Show or hide features on your public storefront.

setSchedulePdfNotes(e.target.value)} rows={1} placeholder="All orders prepaid. No refunds on unpicked orders." />
{loading ? (
Loading settings...
) : ( )} ); } // ── Feature Toggle Component ───────────────────────────────────────────────── function FeatureToggle({ label, description, checked, onChange, }: { label: string; description: string; checked: boolean; onChange: (val: boolean) => void; }) { return (

{label}

{description}

); } // ── Nexus States Input Component ────────────────────────────────────────────── const US_STATES = [ "AL","AK","AZ","AR","CA","CO","CT","DE","FL","GA", "HI","ID","IL","IN","IA","KS","KY","LA","ME","MD", "MA","MI","MN","MS","MO","MT","NE","NV","NH","NJ", "NM","NY","NC","ND","OH","OK","OR","PA","RI","SC", "SD","TN","TX","UT","VT","VA","WA","WV","WI","WY", ]; function NexusStateInput({ value, onChange, }: { value: string[]; onChange: (v: string[]) => void; }) { const [input, setInput] = useState(""); function addState(code: string) { const upper = code.toUpperCase().trim(); if (US_STATES.includes(upper) && !value.includes(upper)) { onChange([...value, upper]); } setInput(""); } function removeState(code: string) { onChange(value.filter((s) => s !== code)); } function handleKeyDown(e: React.KeyboardEvent) { if (e.key === "Enter" || e.key === ",") { e.preventDefault(); if (input.trim()) addState(input); } } return (
{value.map((code) => ( {code} ))}
setInput(e.target.value)} onKeyDown={handleKeyDown} placeholder="Type state code (e.g. CO) and press Enter" maxLength={2} /> { if (e.target.value) addState(e.target.value); }} options={[ { value: "", label: "Add state" }, ...US_STATES.filter((s) => !value.includes(s)).map((s) => ({ value: s, label: s })), ]} />
); } // ── Logo Upload Component ──────────────────────────────────────────────────── type LogoUploadFieldProps = { label: string; hint: string; value: string; previewBg: string; brandId: string; onUpload: (url: string) => void; isDark?: boolean; isOlatheSweetLight?: boolean; isOlatheSweetDark?: boolean; }; export function LogoUploadField({ label, hint, value, previewBg, brandId, onUpload, isDark = false, isOlatheSweetLight = false, isOlatheSweetDark = false, }: LogoUploadFieldProps) { const [uploading, setUploading] = useState(false); const [dragOver, setDragOver] = useState(false); const [error, setError] = useState(null); const inputRef = useRef(null); async function handleFile(file: File) { setError(null); setUploading(true); let result; if (isOlatheSweetLight) { result = await uploadOlatheSweetLogo(brandId, file); } else if (isOlatheSweetDark) { result = await uploadOlatheSweetLogoDark(brandId, file); } else { result = await uploadBrandLogo(brandId, file, isDark); } setUploading(false); if (result.success) { onUpload(result.logoUrl); } else { setError(result.error ?? "Upload failed"); } } function handleDrop(e: React.DragEvent) { e.preventDefault(); setDragOver(false); const file = e.dataTransfer.files[0]; if (file) handleFile(file); } function handleChange(e: React.ChangeEvent) { const file = e.target.files?.[0]; if (file) handleFile(file); } return (

{ e.preventDefault(); setDragOver(true); }} onDragLeave={() => setDragOver(false)} onDrop={handleDrop} onClick={() => inputRef.current?.click()} className={` relative flex flex-col items-center justify-center gap-2 rounded-xl border-2 border-dashed p-6 cursor-pointer transition-colors ${dragOver ? "border-emerald-500 bg-emerald-950/30" : "border-zinc-600 hover:border-zinc-500 hover:bg-zinc-800/50"} ${uploading ? "opacity-50 pointer-events-none" : ""} `} > {uploading ? ( <>
Uploading... ) : value ? ( <> Click or drop to replace ) : ( <> Drag & drop or click to upload PNG, JPEG, WebP · 1200×400px max · max 5MB (ideally under 2MB) )}
{error &&

{error}

} {value && (

Preview

)}
); }