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
+80 -13
View File
@@ -36,15 +36,82 @@ export default function ProductEditForm({ product, brands }: ProductEditFormProp
const [error, setError] = useState<string | null>(null);
const [saved, setSaved] = useState(false);
const [name, setName] = useState(product.name);
const [description, setDescription] = useState(product.description);
const [price, setPrice] = useState(product.price);
const [type, setType] = useState(product.type);
const [active, setActive] = useState(product.active);
const [brand_id, setBrand_id] = useState(product.brand_id);
const [image_url, setImage_url] = useState(product.image_url ?? "");
const [is_taxable, setIs_taxable] = useState(product.is_taxable ?? true);
const [pickup_type, setPickup_type] = useState(product.pickup_type ?? "scheduled_stop");
// Holds user edits only; missing keys fall back to the current prop so we
// never copy the prop into useState. When the prop changes, the fallback
// value tracks the new prop automatically.
const [draft, setDraft] = useState<{
name?: string;
description?: string;
price?: number;
type?: string;
active?: boolean;
brand_id?: string;
image_url?: string;
is_taxable?: boolean;
pickup_type?: string;
}>({});
const name = draft.name ?? product.name;
const description = draft.description ?? product.description;
const price = draft.price ?? product.price;
const type = draft.type ?? product.type;
const active = draft.active ?? product.active;
const brand_id = draft.brand_id ?? product.brand_id;
const image_url = draft.image_url ?? product.image_url ?? "";
const is_taxable = draft.is_taxable ?? product.is_taxable ?? true;
const pickup_type = draft.pickup_type ?? product.pickup_type ?? "scheduled_stop";
const setName = (v: string | ((prev: string) => string)) =>
setDraft((d) => ({
...d,
name: typeof v === "function" ? v(d.name ?? product.name) : v,
}));
const setDescription = (v: string | ((prev: string) => string)) =>
setDraft((d) => ({
...d,
description: typeof v === "function" ? v(d.description ?? product.description) : v,
}));
const setPrice = (v: number | ((prev: number) => number)) =>
setDraft((d) => ({
...d,
price: typeof v === "function" ? v(d.price ?? product.price) : v,
}));
const setType = (v: string | ((prev: string) => string)) =>
setDraft((d) => ({
...d,
type: typeof v === "function" ? v(d.type ?? product.type) : v,
}));
const setActive = (v: boolean | ((prev: boolean) => boolean)) =>
setDraft((d) => ({
...d,
active: typeof v === "function" ? v(d.active ?? product.active) : v,
}));
const setBrand_id = (v: string | ((prev: string) => string)) =>
setDraft((d) => ({
...d,
brand_id: typeof v === "function" ? v(d.brand_id ?? product.brand_id) : v,
}));
const setImage_url = (v: string | ((prev: string) => string)) =>
setDraft((d) => ({
...d,
image_url:
typeof v === "function" ? v(d.image_url ?? product.image_url ?? "") : v,
}));
const setIs_taxable = (v: boolean | ((prev: boolean) => boolean)) =>
setDraft((d) => ({
...d,
is_taxable:
typeof v === "function" ? v(d.is_taxable ?? product.is_taxable ?? true) : v,
}));
const setPickup_type = (v: string | ((prev: string) => string)) =>
setDraft((d) => ({
...d,
pickup_type:
typeof v === "function"
? v(d.pickup_type ?? product.pickup_type ?? "scheduled_stop")
: v,
}));
const [dragOver, setDragOver] = useState(false);
const [uploading, setUploading] = useState(false);
const [uploadError, setUploadError] = useState<string | null>(null);
@@ -207,7 +274,7 @@ export default function ProductEditForm({ product, brands }: ProductEditFormProp
<div>
<label className="mb-2 block text-sm font-medium text-[var(--admin-text-primary)]">Status</label>
<button
<button type="button"
onClick={() => setActive((v) => !v)}
className={`w-full rounded-xl px-4 py-3 text-sm font-medium transition-colors ${
active
@@ -221,7 +288,7 @@ export default function ProductEditForm({ product, brands }: ProductEditFormProp
<div>
<label className="mb-2 block text-sm font-medium text-[var(--admin-text-primary)]">Taxable</label>
<button
<button type="button"
onClick={() => setIs_taxable((v) => !v)}
className={`w-full rounded-xl px-4 py-3 text-sm font-medium transition-colors flex items-center gap-3 ${
is_taxable
@@ -287,7 +354,7 @@ export default function ProductEditForm({ product, brands }: ProductEditFormProp
<span className="text-sm text-[var(--admin-text-muted)]">Drag & drop or click to upload</span>
</>
)}
<input
<input aria-label="File upload"
ref={fileInputRef}
type="file"
accept="image/png,image/jpeg,image/webp"
@@ -314,7 +381,7 @@ export default function ProductEditForm({ product, brands }: ProductEditFormProp
{/* Save button bar — new design tokens */}
<div className="flex items-center gap-3 pt-4 border-t border-[var(--admin-border-light)]">
<button
<button type="button"
onClick={handleSave}
disabled={saving}
className="ha-btn-primary"