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:
@@ -61,16 +61,81 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [saved, setSaved] = useState(false);
|
||||
|
||||
const [customer_name, setCustomer_name] = useState(order.customer_name);
|
||||
const [customer_email, setCustomer_email] = useState(order.customer_email ?? "");
|
||||
const [customer_phone, setCustomer_phone] = useState(order.customer_phone ?? "");
|
||||
const [discount_amount, setDiscount_amount] = useState(order.discount_amount ?? 0);
|
||||
const [discount_reason, setDiscount_reason] = useState(order.discount_reason ?? "");
|
||||
const [internal_notes, setInternal_notes] = useState(order.internal_notes ?? "");
|
||||
const [status, setStatus] = useState(order.status);
|
||||
const [pickup_complete, setPickup_complete] = useState(order.pickup_complete);
|
||||
// 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<{
|
||||
customer_name?: string;
|
||||
customer_email?: string;
|
||||
customer_phone?: string;
|
||||
discount_amount?: number;
|
||||
discount_reason?: string;
|
||||
internal_notes?: string;
|
||||
status?: string;
|
||||
pickup_complete?: boolean;
|
||||
items?: EditableItem[];
|
||||
}>({});
|
||||
|
||||
const [items, setItems] = useState<EditableItem[]>(
|
||||
const customer_name = draft.customer_name ?? order.customer_name;
|
||||
const customer_email = draft.customer_email ?? order.customer_email ?? "";
|
||||
const customer_phone = draft.customer_phone ?? order.customer_phone ?? "";
|
||||
const discount_amount = draft.discount_amount ?? order.discount_amount ?? 0;
|
||||
const discount_reason = draft.discount_reason ?? order.discount_reason ?? "";
|
||||
const internal_notes = draft.internal_notes ?? order.internal_notes ?? "";
|
||||
const status = draft.status ?? order.status;
|
||||
const pickup_complete = draft.pickup_complete ?? order.pickup_complete;
|
||||
|
||||
const setCustomer_name = (v: string | ((prev: string) => string)) =>
|
||||
setDraft((d) => ({
|
||||
...d,
|
||||
customer_name: typeof v === "function" ? v(d.customer_name ?? order.customer_name) : v,
|
||||
}));
|
||||
const setCustomer_email = (v: string | ((prev: string) => string)) =>
|
||||
setDraft((d) => ({
|
||||
...d,
|
||||
customer_email:
|
||||
typeof v === "function" ? v(d.customer_email ?? order.customer_email ?? "") : v,
|
||||
}));
|
||||
const setCustomer_phone = (v: string | ((prev: string) => string)) =>
|
||||
setDraft((d) => ({
|
||||
...d,
|
||||
customer_phone:
|
||||
typeof v === "function" ? v(d.customer_phone ?? order.customer_phone ?? "") : v,
|
||||
}));
|
||||
const setDiscount_amount = (v: number | ((prev: number) => number)) =>
|
||||
setDraft((d) => ({
|
||||
...d,
|
||||
discount_amount:
|
||||
typeof v === "function"
|
||||
? v(d.discount_amount ?? order.discount_amount ?? 0)
|
||||
: v,
|
||||
}));
|
||||
const setDiscount_reason = (v: string | ((prev: string) => string)) =>
|
||||
setDraft((d) => ({
|
||||
...d,
|
||||
discount_reason:
|
||||
typeof v === "function" ? v(d.discount_reason ?? order.discount_reason ?? "") : v,
|
||||
}));
|
||||
const setInternal_notes = (v: string | ((prev: string) => string)) =>
|
||||
setDraft((d) => ({
|
||||
...d,
|
||||
internal_notes:
|
||||
typeof v === "function" ? v(d.internal_notes ?? order.internal_notes ?? "") : v,
|
||||
}));
|
||||
const setStatus = (v: string | ((prev: string) => string)) =>
|
||||
setDraft((d) => ({
|
||||
...d,
|
||||
status: typeof v === "function" ? v(d.status ?? order.status) : v,
|
||||
}));
|
||||
const setPickup_complete = (v: boolean | ((prev: boolean) => boolean)) =>
|
||||
setDraft((d) => ({
|
||||
...d,
|
||||
pickup_complete:
|
||||
typeof v === "function" ? v(d.pickup_complete ?? order.pickup_complete) : v,
|
||||
}));
|
||||
|
||||
const items =
|
||||
draft.items ??
|
||||
order.order_items.map((item) => ({
|
||||
id: item.id,
|
||||
product_id: item.product_id,
|
||||
@@ -78,8 +143,25 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
price: Number(item.price),
|
||||
productName: item.products?.name ?? "Unknown",
|
||||
removed: false,
|
||||
}))
|
||||
);
|
||||
}));
|
||||
const setItems = (updater: React.SetStateAction<EditableItem[]>) =>
|
||||
setDraft((d) => {
|
||||
const currentItems =
|
||||
d.items ??
|
||||
order.order_items.map((item) => ({
|
||||
id: item.id,
|
||||
product_id: item.product_id,
|
||||
quantity: item.quantity,
|
||||
price: Number(item.price),
|
||||
productName: item.products?.name ?? "Unknown",
|
||||
removed: false,
|
||||
}));
|
||||
const next =
|
||||
typeof updater === "function"
|
||||
? (updater as (prev: EditableItem[]) => EditableItem[])(currentItems)
|
||||
: updater;
|
||||
return { ...d, items: next };
|
||||
});
|
||||
|
||||
const visibleItems = items.filter((i) => !i.removed);
|
||||
const subtotal = visibleItems.reduce(
|
||||
@@ -138,32 +220,57 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
const toRemove = items.filter((i) => i.removed);
|
||||
|
||||
try {
|
||||
for (const item of toRemove) {
|
||||
const result = await deleteOrderItem(item.id);
|
||||
if (!result.success) {
|
||||
showError("Failed to remove item", result.error ?? "Please try again");
|
||||
setSaving(false);
|
||||
return;
|
||||
}
|
||||
const removeResults = await Promise.all(
|
||||
toRemove.map(async (item) => {
|
||||
try {
|
||||
const result = await deleteOrderItem(item.id);
|
||||
if (result.success) {
|
||||
return { id: item.id, success: true, error: null as string | null };
|
||||
}
|
||||
return { id: item.id, success: false, error: result.error };
|
||||
} catch {
|
||||
return { id: item.id, success: false, error: "Network error" };
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const failedRemoval = removeResults.find((r) => !r.success);
|
||||
if (failedRemoval) {
|
||||
showError("Failed to remove item", failedRemoval.error ?? "Please try again");
|
||||
setSaving(false);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const item of toSave) {
|
||||
const orig = order.order_items.find((o) => o.id === item.id);
|
||||
if (!orig) continue;
|
||||
if (
|
||||
Number(orig.quantity) !== item.quantity ||
|
||||
Number(orig.price) !== item.price
|
||||
) {
|
||||
const result = await updateOrderItem(item.id, {
|
||||
quantity: item.quantity,
|
||||
price: Number(item.price),
|
||||
});
|
||||
if (!result.success) {
|
||||
showError("Failed to update item", result.error ?? "Please try again");
|
||||
setSaving(false);
|
||||
return;
|
||||
const updateResults = await Promise.all(
|
||||
toSave.map(async (item) => {
|
||||
const orig = order.order_items.find((o) => o.id === item.id);
|
||||
if (!orig) return { id: item.id, success: true, error: null as string | null };
|
||||
if (
|
||||
Number(orig.quantity) === item.quantity &&
|
||||
Number(orig.price) === item.price
|
||||
) {
|
||||
return { id: item.id, success: true, error: null as string | null };
|
||||
}
|
||||
}
|
||||
try {
|
||||
const result = await updateOrderItem(item.id, {
|
||||
quantity: item.quantity,
|
||||
price: Number(item.price),
|
||||
});
|
||||
if (result.success) {
|
||||
return { id: item.id, success: true, error: null as string | null };
|
||||
}
|
||||
return { id: item.id, success: false, error: result.error };
|
||||
} catch {
|
||||
return { id: item.id, success: false, error: "Network error" };
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const failedUpdate = updateResults.find((r) => !r.success);
|
||||
if (failedUpdate) {
|
||||
showError("Failed to update item", failedUpdate.error ?? "Please try again");
|
||||
setSaving(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await updateOrder(order.id, brandId, {
|
||||
@@ -253,7 +360,7 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
>
|
||||
{item.productName}
|
||||
</p>
|
||||
<button
|
||||
<button type="button"
|
||||
onClick={() => removeItem(item.id)}
|
||||
className="shrink-0 rounded-lg px-2 py-1 text-xs font-medium"
|
||||
style={{ color: "var(--admin-danger)" }}
|
||||
@@ -265,7 +372,7 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
<div className="mt-3 grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="ha-field-label mb-1">Qty</label>
|
||||
<input
|
||||
<input aria-label="Number"
|
||||
type="number"
|
||||
min="1"
|
||||
value={item.quantity}
|
||||
@@ -284,7 +391,7 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
>
|
||||
$
|
||||
</span>
|
||||
<input
|
||||
<input aria-label="Number"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
@@ -313,7 +420,7 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
{/* Pricing */}
|
||||
<div className="space-y-4">
|
||||
<AdminInput label="Subtotal (auto-calculated)">
|
||||
<input
|
||||
<input aria-label="Number"
|
||||
type="number"
|
||||
step="0.01"
|
||||
value={subtotal}
|
||||
@@ -333,7 +440,7 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
>
|
||||
$
|
||||
</span>
|
||||
<input
|
||||
<input aria-label="Number"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
@@ -355,7 +462,7 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
</div>
|
||||
<div>
|
||||
<label className="ha-field-label mb-1.5">Discount Reason</label>
|
||||
<input
|
||||
<input aria-label="Optional"
|
||||
type="text"
|
||||
value={discount_reason}
|
||||
onChange={(e) => setDiscount_reason(e.target.value)}
|
||||
@@ -396,7 +503,7 @@ export default function OrderEditForm({ order, brandId }: OrderEditFormProps) {
|
||||
<span>Name</span>
|
||||
<span className="ha-field-label-required">*</span>
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="Text"
|
||||
type="text"
|
||||
value={customer_name}
|
||||
onChange={(e) => {
|
||||
|
||||
Reference in New Issue
Block a user