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:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useCallback, useEffect, useRef } from "react";
|
||||
import { useState, useCallback, useRef, useEffect } from "react";
|
||||
import { createStop } from "@/actions/stops/create-stop";
|
||||
import { updateStop } from "@/actions/stops/update-stop";
|
||||
import GlassModal from "@/components/admin/GlassModal";
|
||||
@@ -52,16 +52,15 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
const cityRef = useRef<HTMLInputElement>(null);
|
||||
const isEditing = Boolean(stop);
|
||||
|
||||
useEffect(() => {
|
||||
// Reset form when modal opens or stop changes — derived during render
|
||||
// per React docs: "Adjusting some state when a prop changes".
|
||||
const [prevSyncKey, setPrevSyncKey] = useState<string | null>(null);
|
||||
const syncKey = `${isOpen ? "open" : "closed"}:${stop?.id ?? "new"}`;
|
||||
if (syncKey !== prevSyncKey) {
|
||||
setPrevSyncKey(syncKey);
|
||||
if (isOpen) {
|
||||
if (stop) {
|
||||
// Edit mode - populate from existing stop.
|
||||
// setState in effect is intentional: we sync form fields with the
|
||||
// incoming `stop` prop whenever the modal opens or the target
|
||||
// stop changes (the parent re-renders the modal with a new
|
||||
// `stop` ref). The parent could also use a `key` to force a
|
||||
// remount, but keeping the data in one place is clearer.
|
||||
/* eslint-disable react-hooks/set-state-in-effect */
|
||||
setCity(stop.city);
|
||||
setStateField(stop.state);
|
||||
setLocation(stop.location);
|
||||
@@ -84,10 +83,21 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
setStatus("draft");
|
||||
}
|
||||
setError(null);
|
||||
requestAnimationFrame(() => cityRef.current?.focus());
|
||||
/* eslint-enable react-hooks/set-state-in-effect */
|
||||
}
|
||||
}, [isOpen, stop]);
|
||||
}
|
||||
|
||||
// Focus the first field once the modal has actually opened. This is
|
||||
// a DOM side-effect, so it must run after the commit (i.e. in an
|
||||
// effect) — accessing `cityRef.current` during render is illegal.
|
||||
// The `prevSyncKey.startsWith("open:")` guard keeps the focus call
|
||||
// to the transition into the open state, not every re-render.
|
||||
useEffect(() => {
|
||||
if (prevSyncKey?.startsWith("open:")) {
|
||||
const id = requestAnimationFrame(() => cityRef.current?.focus());
|
||||
return () => cancelAnimationFrame(id);
|
||||
}
|
||||
return undefined;
|
||||
}, [prevSyncKey]);
|
||||
|
||||
const handleSubmit = useCallback(
|
||||
async (e: React.FormEvent) => {
|
||||
@@ -204,7 +214,7 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
<span>City</span>
|
||||
<span className="ha-field-label-required">*</span>
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="Denver"
|
||||
ref={cityRef}
|
||||
id="stop-city"
|
||||
type="text"
|
||||
@@ -221,7 +231,7 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
<span>State</span>
|
||||
<span className="ha-field-label-required">*</span>
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="CO"
|
||||
id="stop-state"
|
||||
type="text"
|
||||
value={stateField}
|
||||
@@ -242,7 +252,7 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
<span>Location / Venue</span>
|
||||
<span className="ha-field-label-required">*</span>
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="Whole Foods Market — Highlands"
|
||||
id="stop-location"
|
||||
type="text"
|
||||
value={location}
|
||||
@@ -264,7 +274,7 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
<span>Pickup Date</span>
|
||||
<span className="ha-field-label-required">*</span>
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="Stop Date"
|
||||
id="stop-date"
|
||||
type="date"
|
||||
value={date}
|
||||
@@ -281,7 +291,7 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
</svg>
|
||||
<span>Pickup Time</span>
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="Stop Time"
|
||||
id="stop-time"
|
||||
type="time"
|
||||
value={time}
|
||||
@@ -301,7 +311,7 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
</svg>
|
||||
<span>Street Address</span>
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="123 Main St"
|
||||
id="stop-address"
|
||||
type="text"
|
||||
value={address}
|
||||
@@ -315,7 +325,7 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
<label htmlFor="stop-zip" className="ha-field-label">
|
||||
<span>ZIP</span>
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="80202"
|
||||
id="stop-zip"
|
||||
type="text"
|
||||
value={zip}
|
||||
@@ -334,7 +344,7 @@ export default function EditStopModal({ isOpen, onClose, brandId, stop, onSucces
|
||||
</svg>
|
||||
<span>Cutoff</span>
|
||||
</label>
|
||||
<input
|
||||
<input aria-label="Stop Cutoff"
|
||||
id="stop-cutoff"
|
||||
type="time"
|
||||
value={cutoffTime}
|
||||
|
||||
Reference in New Issue
Block a user