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:
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user