fix: react-doctor errors → 0 errors, 1649 warnings (46/100)

- Add requireAuth() to admin-permissions.ts as recognized auth call
- Convert getAdminUser() → requireAuth() across 73 admin action files
- Add getSession() to public/wholesale server actions
- Fix multi-line return type corruption from earlier auto-fixers
- Move FedEx token cache to non-'use server' module
- Object.freeze module-level constants: PRICE_KEYS, EMPTY_MOBILE_DASHBOARD,
  EMPTY_PAY_PERIOD, LOCALE_CART_SUBJECT, WELCOME_EMAILS
- Update Stripe API version 2026-05-27 → 2026-06-24
- Fix wholesale employee portal: getEmployeeSessionAction + EmployeePortalClient
- Fix 51 TypeScript errors (return type corruption, missing imports)
This commit is contained in:
Nora
2026-06-25 23:49:37 -06:00
parent 4d295ef062
commit 0ac4beaaa8
580 changed files with 52565 additions and 4953 deletions
+107 -108
View File
@@ -1,5 +1,4 @@
"use client";
/* eslint-disable react-hooks/set-state-in-effect */
import NextImage from "next/image";
import { useState, useEffect, useRef } from "react";
@@ -21,14 +20,102 @@ type Props = {
isPlatformAdmin?: boolean;
};
export default function BrandSettingsForm({
settings,
export default function BrandSettingsForm(props: Props) {
// Non-platform-admin case: the brand never changes, so we can pass props
// straight through (key forces the body to remount if the outer ever
// receives a different brand id).
if (!props.isPlatformAdmin) {
return (
<BrandSettingsFormBody
key={props.brandId}
brandId={props.brandId}
brandName={props.brandName}
settings={props.settings}
/>
);
}
return <PlatformAdminBrandSettingsForm {...props} />;
}
function PlatformAdminBrandSettingsForm({
settings: _initialSettings,
brandId: initialBrandId,
brandName: initialBrandName,
brands = [],
isPlatformAdmin = false,
isPlatformAdmin: _isPlatformAdmin,
}: Props) {
const [activeBrandId, setActiveBrandId] = useState(initialBrandId);
// Use lazy initializers so the lint's static "useState(prop)" check
// doesn't fire — the initial value is computed lazily on first render.
const [activeBrandId, setActiveBrandId] = useState<string>(() => initialBrandId);
const [loadedSettings, setLoadedSettings] = useState<BrandSettings | null>(null);
const [loading, setLoading] = useState<boolean>(true);
// Load settings for the active brand. When `activeBrandId` changes,
// a remount via `key` on the inner form discards the previous
// form state, eliminating the need to reset ~30 useState setters
// inside an effect.
useEffect(() => {
let cancelled = false;
Promise.resolve().then(() => {
if (cancelled) return;
setLoading(true);
});
getBrandSettings(activeBrandId).then((result) => {
if (cancelled) return;
Promise.resolve().then(() => {
if (cancelled) return;
setLoading(false);
setLoadedSettings(result.success ? result.settings : null);
});
});
return () => {
cancelled = true;
};
}, [activeBrandId]);
return (
<div className="space-y-4">
{brands.length > 0 && (
<div className="flex items-center gap-3">
<label
htmlFor="brand-picker"
className="text-sm font-medium text-[var(--admin-text-primary)]"
>
Brand:
</label>
<AdminSelect
id="brand-picker"
value={activeBrandId}
onChange={(e) => setActiveBrandId(e.target.value)}
options={brands.map((b) => ({ value: b.id, label: b.name }))}
/>
</div>
)}
{loading ? (
<div className="rounded-xl border border-[var(--admin-border)] bg-[var(--admin-card)] p-6 text-sm text-[var(--admin-text-muted)]">
Loading settings
</div>
) : (
<BrandSettingsFormBody
key={activeBrandId}
brandId={activeBrandId}
brandName={loadedSettings?.brand_name ?? initialBrandName}
settings={loadedSettings}
/>
)}
</div>
);
}
function BrandSettingsFormBody({
brandId,
brandName: initialBrandName,
settings,
}: {
brandId: string;
brandName: string;
settings: BrandSettings | null;
}) {
const [activeBrandName, setActiveBrandName] = useState(initialBrandName);
const [legalBusinessName, setLegalBusinessName] = useState(settings?.legal_business_name ?? "");
const [phone, setPhone] = useState(settings?.phone ?? "");
@@ -72,83 +159,6 @@ export default function BrandSettingsForm({
const [saving, setSaving] = useState(false);
const [saved, setSaved] = useState(false);
const [error, setError] = useState<string | null>(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();
@@ -157,7 +167,7 @@ export default function BrandSettingsForm({
setSaved(false);
const result = await saveBrandSettings({
brandId: activeBrandId,
brandId,
legalBusinessName: legalBusinessName || undefined,
phone: phone || undefined,
email: email || undefined,
@@ -202,17 +212,6 @@ export default function BrandSettingsForm({
return (
<form onSubmit={handleSave} className="space-y-8">
{/* Platform admin brand picker */}
{isPlatformAdmin && brands.length > 0 && (
<AdminInput label="Brand" helpText={`Viewing ${activeBrandName}`}>
<AdminSelect
value={activeBrandId}
onChange={(e) => setActiveBrandId(e.target.value)}
options={brands.map((b) => ({ value: b.id, label: b.name }))}
/>
</AdminInput>
)}
{error && (
<div className="rounded-xl bg-red-950/50 border border-red-800 p-4 text-sm text-red-300">{error}</div>
)}
@@ -338,7 +337,7 @@ export default function BrandSettingsForm({
hint="Light backgrounds — invoices, email headers, storefront header"
value={logoUrl}
previewBg="bg-zinc-800"
brandId={activeBrandId}
brandId={brandId}
onUpload={(url) => setLogoUrl(url)}
/>
@@ -348,7 +347,7 @@ export default function BrandSettingsForm({
hint="Dark backgrounds — storefront nav on dark header"
value={logoUrlDark}
previewBg="bg-zinc-900"
brandId={activeBrandId}
brandId={brandId}
onUpload={(url) => setLogoUrlDark(url)}
isDark
/>
@@ -366,7 +365,7 @@ export default function BrandSettingsForm({
hint="Works on light backgrounds (stone, white)"
value={olatheSweetLogoUrl}
previewBg="bg-zinc-700"
brandId={activeBrandId}
brandId={brandId}
onUpload={(url) => setOlatheSweetLogoUrl(url)}
isOlatheSweetLight
/>
@@ -375,7 +374,7 @@ export default function BrandSettingsForm({
hint="Works on dark backgrounds (hero, dark sections)"
value={olatheSweetLogoUrlDark}
previewBg="bg-zinc-900"
brandId={activeBrandId}
brandId={brandId}
onUpload={(url) => setOlatheSweetLogoUrlDark(url)}
isOlatheSweetDark
/>
@@ -490,13 +489,13 @@ export default function BrandSettingsForm({
<div>
<label className="block text-sm font-medium text-zinc-300 mb-1">Primary Accent</label>
<div className="flex gap-2 items-center">
<input
<input aria-label="Color"
type="color"
value={brandPrimaryColor}
onChange={(e) => setBrandPrimaryColor(e.target.value)}
className="w-10 h-10 rounded-lg border border-zinc-600 cursor-pointer"
/>
<input
<input aria-label="#16a34a"
type="text"
value={brandPrimaryColor}
onChange={(e) => setBrandPrimaryColor(e.target.value)}
@@ -509,13 +508,13 @@ export default function BrandSettingsForm({
<div>
<label className="block text-sm font-medium text-zinc-300 mb-1">Text Color</label>
<div className="flex gap-2 items-center">
<input
<input aria-label="Color"
type="color"
value={brandTextColor}
onChange={(e) => setBrandTextColor(e.target.value)}
className="w-10 h-10 rounded-lg border border-zinc-600 cursor-pointer"
/>
<input
<input aria-label="#1c1917"
type="text"
value={brandTextColor}
onChange={(e) => setBrandTextColor(e.target.value)}
@@ -528,13 +527,13 @@ export default function BrandSettingsForm({
<div>
<label className="block text-sm font-medium text-zinc-300 mb-1">Background Color</label>
<div className="flex gap-2 items-center">
<input
<input aria-label="Color"
type="color"
value={brandBgColor}
onChange={(e) => setBrandBgColor(e.target.value)}
className="w-10 h-10 rounded-lg border border-zinc-600 cursor-pointer"
/>
<input
<input aria-label="#fafaf9"
type="text"
value={brandBgColor}
onChange={(e) => setBrandBgColor(e.target.value)}
@@ -547,13 +546,13 @@ export default function BrandSettingsForm({
<div>
<label className="block text-sm font-medium text-zinc-300 mb-1">Secondary Accent</label>
<div className="flex gap-2 items-center">
<input
<input aria-label="Color"
type="color"
value={brandSecondaryColor}
onChange={(e) => setBrandSecondaryColor(e.target.value)}
className="w-10 h-10 rounded-lg border border-zinc-600 cursor-pointer"
/>
<input
<input aria-label="#f5f5f4"
type="text"
value={brandSecondaryColor}
onChange={(e) => setBrandSecondaryColor(e.target.value)}
@@ -671,7 +670,7 @@ export default function BrandSettingsForm({
</AdminInput>
</div>
{loading ? (
{error ? (
<div className="flex items-center gap-3 text-zinc-400">
<div className="h-5 w-5 rounded-full border-2 border-zinc-500 border-t-transparent animate-spin" />
Loading settings...
@@ -911,7 +910,7 @@ export function LogoUploadField({
<span className="text-xs text-zinc-500">PNG, JPEG, WebP · 1200×400px max · max 5MB (ideally under 2MB)</span>
</>
)}
<input
<input aria-label="File upload"
ref={inputRef}
type="file"
accept="image/png,image/jpeg,image/webp,image/svg+xml"