"use client"; import { useState, useCallback, useEffect } from "react"; import { createStop } from "@/actions/stops/create-stop"; import GlassModal from "@/components/admin/GlassModal"; type Props = { isOpen: boolean; onClose: () => void; brandId: string; duplicateFrom?: { city: string; state: string; location: string; date: string; time: string; address?: string | null; zip?: string | null; cutoff_time?: string | null; } | null; onSuccess?: (stopId: string) => void; }; export default function AddStopModal({ isOpen, onClose, brandId, duplicateFrom, onSuccess }: Props) { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [city, setCity] = useState(""); const [state, setState] = useState(""); const [location, setLocation] = useState(""); const [date, setDate] = useState(""); const [time, setTime] = useState(""); /* eslint-disable react-hooks/set-state-in-effect */ const [address, setAddress] = useState(""); const [zip, setZip] = useState(""); const [cutoffTime, setCutoffTime] = useState(""); const [status, setStatus] = useState<"draft" | "active">("draft"); useEffect(() => { if (isOpen) { // Reset form when modal opens with optional duplicate source setCity(duplicateFrom?.city ?? ""); setState(duplicateFrom?.state ?? ""); setLocation(duplicateFrom?.location ?? ""); setDate(duplicateFrom?.date ?? ""); setTime(duplicateFrom?.time ?? ""); setAddress(duplicateFrom?.address ?? ""); setZip(duplicateFrom?.zip ?? ""); setCutoffTime(duplicateFrom?.cutoff_time ?? ""); setStatus("draft"); setError(null); } /* eslint-enable react-hooks/set-state-in-effect */ }, [isOpen, duplicateFrom]); const handleSubmit = useCallback(async (e: React.FormEvent) => { e.preventDefault(); setError(null); if (!city.trim() || !state.trim() || !location.trim() || !date) { setError("City, state, location, and date are required."); return; } setLoading(true); try { const result = await createStop(brandId, { city: city.trim(), state: state.trim(), location: location.trim(), date, time: time || "08:00", address: address || undefined, zip: zip || undefined, cutoff_time: cutoffTime || undefined, active: status === "active", }); if (result.success) { onSuccess?.(result.id); onClose(); } else { setError(result.error ?? "Failed to create stop"); } } catch { setError("Network error. Please try again."); } finally { setLoading(false); } }, [brandId, city, state, location, date, time, address, zip, cutoffTime, status, onSuccess, onClose]); const isDuplicate = Boolean(duplicateFrom); const title = isDuplicate ? "Duplicate Stop" : "Add New Stop"; const subtitle = isDuplicate && duplicateFrom ? `From ${duplicateFrom.city}, ${duplicateFrom.state}` : "Create a new tour stop for your route."; const inputStyle = { background: 'rgba(0, 0, 0, 0.02)', border: '1px solid rgba(0, 0, 0, 0.06)', outline: 'none', }; const handleFocus = (e: React.FocusEvent) => { e.target.style.background = 'rgba(16, 185, 129, 0.04)'; e.target.style.border = '1px solid rgba(16, 185, 129, 0.5)'; e.target.style.boxShadow = '0 0 0 4px rgba(16, 185, 129, 0.08), 0 2px 8px rgba(0, 0, 0, 0.04)'; }; const handleBlur = (e: React.FocusEvent) => { e.target.style.background = 'rgba(0, 0, 0, 0.02)'; e.target.style.border = '1px solid rgba(0, 0, 0, 0.06)'; e.target.style.boxShadow = 'none'; }; if (!isOpen) return null; return (
{error && (
{error}
)}
setCity(e.target.value)} placeholder="Denver" className="w-full rounded-xl px-4 py-3 text-sm text-stone-900 placeholder:text-stone-400 transition-all" style={inputStyle} onFocus={handleFocus} onBlur={handleBlur} required />
setState(e.target.value.toUpperCase())} placeholder="CO" maxLength={2} className="w-full rounded-xl px-4 py-3 text-sm text-stone-900 placeholder:text-stone-400 transition-all" style={inputStyle} onFocus={handleFocus} onBlur={handleBlur} required />
setLocation(e.target.value)} placeholder="Whole Foods Market" className="w-full rounded-xl px-4 py-3 text-sm text-stone-900 placeholder:text-stone-400 transition-all" style={inputStyle} onFocus={handleFocus} onBlur={handleBlur} required />
setDate(e.target.value)} className="w-full rounded-xl px-4 py-3 text-sm text-stone-900 transition-all" style={inputStyle} onFocus={handleFocus} onBlur={handleBlur} required />
setTime(e.target.value)} className="w-full rounded-xl px-4 py-3 text-sm text-stone-900 transition-all" style={inputStyle} onFocus={handleFocus} onBlur={handleBlur} />
setAddress(e.target.value)} placeholder="123 Main St" className="w-full rounded-xl px-4 py-3 text-sm text-stone-900 placeholder:text-stone-400 transition-all" style={inputStyle} onFocus={handleFocus} onBlur={handleBlur} />
setZip(e.target.value)} placeholder="80202" className="w-full rounded-xl px-4 py-3 text-sm text-stone-900 placeholder:text-stone-400 transition-all" style={inputStyle} onFocus={handleFocus} onBlur={handleBlur} />
setCutoffTime(e.target.value)} className="w-full rounded-xl px-4 py-3 text-sm text-stone-900 transition-all" style={inputStyle} onFocus={handleFocus} onBlur={handleBlur} />

Orders close this time the day before pickup

{/* Status toggle */}
{/* Footer */}
); } // Hook for easy integration export function useAddStopModal(brandId: string, duplicateFrom?: Props["duplicateFrom"]) { const [isOpen, setIsOpen] = useState(false); const open = useCallback(() => setIsOpen(true), []); const close = useCallback(() => setIsOpen(false), []); const Modal = useCallback(() => ( ), [isOpen, close, brandId, duplicateFrom]); return { open, close, Modal }; }