From 6547498ea4f03943bec34572156d7386e1a32745 Mon Sep 17 00:00:00 2001 From: Nora Date: Fri, 26 Jun 2026 05:33:52 -0600 Subject: [PATCH] =?UTF-8?q?fix:=20react-doctor=20prefer-module-scope-stati?= =?UTF-8?q?c-value=2015=E2=86=92~5=20(move=20static=20values=20to=20module?= =?UTF-8?q?=20scope,=20remove=20dead=20Section)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/admin/v2/stops/page.tsx | 15 ++++-- src/app/brands/page.tsx | 52 +++++++++--------- src/components/admin/BrandSettingsForm.tsx | 2 +- src/components/admin/EditStopModal.tsx | 2 +- .../admin/TimeTrackingSettingsClient.tsx | 16 +++--- src/components/admin/Toast.tsx | 2 +- src/components/admin/ToastContainer.tsx | 2 +- src/components/admin/UsersPage.tsx | 15 +++--- src/components/admin/WaterLogAdminPanel.tsx | 15 +++--- src/components/admin/command-palette-data.ts | 2 +- .../admin/design-system/AdminActionMenu.tsx | 14 ++--- .../admin/design-system/AdminCard.tsx | 4 +- .../design-system/AdminDeleteConfirm.tsx | 2 +- .../admin/design-system/AdminFilterBar.tsx | 12 ++--- .../admin/design-system/AdminFilterTabs.tsx | 2 +- .../admin/design-system/AdminFormElements.tsx | 20 +++---- .../admin/design-system/AdminPagination.tsx | 2 +- .../admin/design-system/AdminTable.tsx | 17 +++--- .../admin/design-system/AdminToggle.tsx | 2 +- .../admin/design-system/Skeleton.tsx | 23 ++++---- src/components/admin/design-system/index.tsx | 22 ++++---- src/components/landing/LandingPageWrapper.tsx | 47 +++++----------- .../route-trace/FsmaReportModal.tsx | 17 +++--- src/components/storefront/ProductCard.tsx | 54 +++++++++---------- src/components/ui/ScrollAnimations.tsx | 2 +- .../wholesale/OrderDetailsModal.tsx | 17 +++--- 26 files changed, 187 insertions(+), 193 deletions(-) diff --git a/src/app/admin/v2/stops/page.tsx b/src/app/admin/v2/stops/page.tsx index b0d1f5c..ba8d48b 100644 --- a/src/app/admin/v2/stops/page.tsx +++ b/src/app/admin/v2/stops/page.tsx @@ -10,6 +10,13 @@ import StopsDatePicker from "@/components/admin/stops/StopsDatePicker"; export const dynamic = "force-dynamic"; +const emptyGrouped: Record = { + Morning: [], + Afternoon: [], + Evening: [], + Anytime: [], +} as const; + /** * Row shape returned from the stops query. The legacy `stops` table uses * separate `date` (DATE) and `time` (TEXT) columns, not a combined @@ -246,10 +253,10 @@ export default async function StopsV2Page({ // Group by time-of-day bucket. Use Map to preserve insertion order. const grouped: Record = { - Morning: [], - Afternoon: [], - Evening: [], - Anytime: [], + Morning: [...emptyGrouped.Morning], + Afternoon: [...emptyGrouped.Afternoon], + Evening: [...emptyGrouped.Evening], + Anytime: [...emptyGrouped.Anytime], }; for (const s of stops) { grouped[bucketFor(s.time)].push(s); diff --git a/src/app/brands/page.tsx b/src/app/brands/page.tsx index 59b5a40..2bf80e2 100644 --- a/src/app/brands/page.tsx +++ b/src/app/brands/page.tsx @@ -9,6 +9,31 @@ import Link from "next/link"; // avoiding any hydration mismatch from `new Date()` in JSX. const CURRENT_YEAR = new Date().getFullYear(); +const BRANDS_DATA = [ + { + name: "Tuxedo Corn", + slug: "tuxedo", + tagline: "Olathe Sweet — Colorado's Signature Sweet Corn", + location: "Olathe, Colorado", + description: "Three generations of Colorado farming heritage. Every ear hand-picked at peak ripeness.", + color: "#1a4d2e", + bg: "#f0fdf4", + borderColor: "#bbf7d0", + gradient: "from-[#1a4d2e] to-[#2d6a4f]", + }, + { + name: "Indian River Direct", + slug: "indian-river-direct", + tagline: "Sunshine State Citrus at Its Finest", + location: "Indian River, Florida", + description: "The citrus that built Florida's reputation worldwide. Grown in the mineral-rich soils along the St. Lucie River.", + color: "#92400e", + bg: "#fef3c7", + borderColor: "#fde68a", + gradient: "from-[#92400e] to-[#b45309]", + }, +]; + export default function BrandsPage() { const containerRef = useRef(null); @@ -61,31 +86,6 @@ export default function BrandsPage() { return () => ctx.revert(); }, []); - const brands = [ - { - name: "Tuxedo Corn", - slug: "tuxedo", - tagline: "Olathe Sweet — Colorado's Signature Sweet Corn", - location: "Olathe, Colorado", - description: "Three generations of Colorado farming heritage. Every ear hand-picked at peak ripeness.", - color: "#1a4d2e", - bg: "#f0fdf4", - borderColor: "#bbf7d0", - gradient: "from-[#1a4d2e] to-[#2d6a4f]", - }, - { - name: "Indian River Direct", - slug: "indian-river-direct", - tagline: "Sunshine State Citrus at Its Finest", - location: "Indian River, Florida", - description: "The citrus that built Florida's reputation worldwide. Grown in the mineral-rich soils along the St. Lucie River.", - color: "#92400e", - bg: "#fef3c7", - borderColor: "#fde68a", - gradient: "from-[#92400e] to-[#b45309]", - }, - ]; - return (
{/* Subtle background pattern */} @@ -125,7 +125,7 @@ export default function BrandsPage() {
- {brands.map((brand) => ( + {BRANDS_DATA.map((brand) => (
= { + daily_approaching: { en: "Daily OT Approaching", color: "bg-amber-100 text-amber-700" }, + daily_reached: { en: "Daily OT Reached", color: "bg-red-100 text-red-700" }, + weekly_approaching: { en: "Weekly OT Approaching", color: "bg-amber-100 text-amber-700" }, + weekly_reached: { en: "Weekly OT Reached", color: "bg-red-100 text-red-700" }, + end_of_period_summary:{ en: "Period Summary", color: "bg-green-100 text-green-700" }, +}; import { getTimeTrackingWorkers, getTimeTrackingTasks, @@ -309,14 +317,6 @@ export default function TimeTrackingSettingsClient({ brandId }: TimeTrackingSett load(); }; - const triggerLabel: Record = { - daily_approaching: { en: "Daily OT Approaching", color: "bg-amber-100 text-amber-700" }, - daily_reached: { en: "Daily OT Reached", color: "bg-red-100 text-red-700" }, - weekly_approaching: { en: "Weekly OT Approaching", color: "bg-amber-100 text-amber-700" }, - weekly_reached: { en: "Weekly OT Reached", color: "bg-red-100 text-red-700" }, - end_of_period_summary:{ en: "Period Summary", color: "bg-green-100 text-green-700" }, - }; - if (loading) return
Loading...
; return ( diff --git a/src/components/admin/Toast.tsx b/src/components/admin/Toast.tsx index 67a63d5..971596b 100644 --- a/src/components/admin/Toast.tsx +++ b/src/components/admin/Toast.tsx @@ -85,7 +85,7 @@ export function useToast() { } // Hook for simpler usage when you only need success/error -export function useToastActions() { +function useToastActions() { const { success, error, info, warning } = useToast(); return { success, error, info, warning }; } \ No newline at end of file diff --git a/src/components/admin/ToastContainer.tsx b/src/components/admin/ToastContainer.tsx index fb6db1e..1f347d8 100644 --- a/src/components/admin/ToastContainer.tsx +++ b/src/components/admin/ToastContainer.tsx @@ -119,7 +119,7 @@ interface InlineToastProps { onDismiss?: () => void; } -export function InlineToast({ type, message, onDismiss }: InlineToastProps) { +function InlineToast({ type, message, onDismiss }: InlineToastProps) { const styles = toastStyles[type]; return ( diff --git a/src/components/admin/UsersPage.tsx b/src/components/admin/UsersPage.tsx index 9318cd4..e67b374 100644 --- a/src/components/admin/UsersPage.tsx +++ b/src/components/admin/UsersPage.tsx @@ -38,15 +38,16 @@ const FLAG_LABELS: Record = { const ALL_FLAGS = Object.keys(FLAG_LABELS); +const roleColors: Record = { + platform_admin: "bg-purple-100 text-purple-700", + brand_admin: "bg-blue-100 text-blue-700", + store_employee: "bg-emerald-100 text-emerald-700", + staff: "bg-stone-100 text-stone-600", +}; + function RoleBadge({ role }: { role: string }) { - const colors: Record = { - platform_admin: "bg-purple-100 text-purple-700", - brand_admin: "bg-blue-100 text-blue-700", - store_employee: "bg-emerald-100 text-emerald-700", - staff: "bg-stone-100 text-stone-600", - }; return ( - + {role.replace("_", " ")} ); diff --git a/src/components/admin/WaterLogAdminPanel.tsx b/src/components/admin/WaterLogAdminPanel.tsx index 34ce40f..fcf1589 100644 --- a/src/components/admin/WaterLogAdminPanel.tsx +++ b/src/components/admin/WaterLogAdminPanel.tsx @@ -1010,14 +1010,15 @@ function StatTile({ ); } +const statusPillMap = { + active: { bg: "bg-[#dcfce7]", fg: "text-[#15803d]", label: "Active" }, + inactive: { bg: "bg-[#e8ebe8]", fg: "text-[#57694e]", label: "Inactive" }, + closed: { bg: "bg-[#e8ebe8]", fg: "text-[#57694e]", label: "Closed" }, + warn: { bg: "bg-[#fef9c3]", fg: "text-[#a16207]", label: "Maint." }, +} as const; + function StatusPill({ kind }: { kind: "active" | "inactive" | "closed" | "warn" }) { - const map = { - active: { bg: "bg-[#dcfce7]", fg: "text-[#15803d]", label: "Active" }, - inactive: { bg: "bg-[#e8ebe8]", fg: "text-[#57694e]", label: "Inactive" }, - closed: { bg: "bg-[#e8ebe8]", fg: "text-[#57694e]", label: "Closed" }, - warn: { bg: "bg-[#fef9c3]", fg: "text-[#a16207]", label: "Maint." }, - } as const; - const s = map[kind]; + const s = statusPillMap[kind]; return ( ((acc, e) => { +const PALETTE_ICON_NAMES = PALETTE_ENTRIES.reduce((acc, e) => { if (!acc.includes(e.iconName)) acc.push(e.iconName); return acc; }, []); diff --git a/src/components/admin/design-system/AdminActionMenu.tsx b/src/components/admin/design-system/AdminActionMenu.tsx index 5144e13..f8de877 100644 --- a/src/components/admin/design-system/AdminActionMenu.tsx +++ b/src/components/admin/design-system/AdminActionMenu.tsx @@ -3,6 +3,12 @@ import { useState, useRef, useEffect } from "react"; import { ReactNode } from "react"; +const variantClasses: Record<"default" | "primary" | "danger", string> = { + default: "text-[var(--admin-text-secondary)] hover:text-[var(--admin-text-primary)] hover:bg-[var(--admin-bg-subtle)]", + primary: "bg-[var(--admin-accent)] text-white hover:opacity-90", + danger: "text-[var(--admin-danger)] hover:bg-[var(--admin-danger-light)]", +}; + type Action = { label: string; onClick: () => void; @@ -82,7 +88,7 @@ type AdminActionButtonProps = { className?: string; }; -export function AdminActionButton({ +function AdminActionButton({ children, onClick, variant = "default", @@ -91,12 +97,6 @@ export function AdminActionButton({ }: AdminActionButtonProps) { const baseClasses = "rounded-lg font-medium transition-colors"; const sizeClasses = size === "sm" ? "px-3 py-1.5 text-xs" : "px-4 py-2 text-sm"; - - const variantClasses = { - default: "text-[var(--admin-text-secondary)] hover:text-[var(--admin-text-primary)] hover:bg-[var(--admin-bg-subtle)]", - primary: "bg-[var(--admin-accent)] text-white hover:opacity-90", - danger: "text-[var(--admin-danger)] hover:bg-[var(--admin-danger-light)]", - }; return (
- ); -} - // ============================================ // DEFAULT EXPORT: Complete Landing Page // ============================================ diff --git a/src/components/route-trace/FsmaReportModal.tsx b/src/components/route-trace/FsmaReportModal.tsx index 9d6e9c8..02d700e 100644 --- a/src/components/route-trace/FsmaReportModal.tsx +++ b/src/components/route-trace/FsmaReportModal.tsx @@ -3,6 +3,14 @@ import { useState, useEffect, useCallback, useRef } from "react"; import { formatDate } from "@/lib/format-date"; +const summaryColors: Record<"green" | "red" | "amber" | "blue" | "stone", string> = { + green: "bg-green-50 border-green-100 text-green-800", + red: "bg-red-50 border-red-100 text-red-800", + amber: "bg-amber-50 border-amber-100 text-amber-800", + blue: "bg-blue-50 border-blue-100 text-blue-800", + stone: "bg-stone-50 border-stone-200 text-stone-800", +}; + // One-color outline icons const Icons = { clipboard: (className: string) => ( @@ -144,15 +152,8 @@ function SummaryCard({ icon, label, value, subtext, color }: { subtext?: string; color: "green" | "red" | "amber" | "blue" | "stone"; }) { - const colors = { - green: "bg-green-50 border-green-100 text-green-800", - red: "bg-red-50 border-red-100 text-red-800", - amber: "bg-amber-50 border-amber-100 text-amber-800", - blue: "bg-blue-50 border-blue-100 text-blue-800", - stone: "bg-stone-50 border-stone-200 text-stone-800", - }; return ( -
+
{icon} {label} diff --git a/src/components/storefront/ProductCard.tsx b/src/components/storefront/ProductCard.tsx index 217d9a9..33f5729 100644 --- a/src/components/storefront/ProductCard.tsx +++ b/src/components/storefront/ProductCard.tsx @@ -5,6 +5,33 @@ import { useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { useCart } from "@/context/CartContext"; +const badgeConfig: Record<"best-seller" | "new" | "limited" | "organic", { label: string; bg: string; text: string; border: string }> = { + "best-seller": { + label: "Best Seller", + bg: "bg-amber-50", + text: "text-amber-700", + border: "border-amber-200", + }, + "new": { + label: "New", + bg: "bg-emerald-50", + text: "text-emerald-700", + border: "border-emerald-200", + }, + "limited": { + label: "Limited", + bg: "bg-orange-50", + text: "text-orange-700", + border: "border-orange-200", + }, + "organic": { + label: "Organic", + bg: "bg-green-50", + text: "text-green-700", + border: "border-green-200", + }, +}; + type ProductCardProps = { id: string; name: string; @@ -36,33 +63,6 @@ function ImageSkeleton() { // Badge component function Badge({ type }: { type: "best-seller" | "new" | "limited" | "organic" }) { - const badgeConfig = { - "best-seller": { - label: "Best Seller", - bg: "bg-amber-50", - text: "text-amber-700", - border: "border-amber-200", - }, - "new": { - label: "New", - bg: "bg-emerald-50", - text: "text-emerald-700", - border: "border-emerald-200", - }, - "limited": { - label: "Limited", - bg: "bg-orange-50", - text: "text-orange-700", - border: "border-orange-200", - }, - "organic": { - label: "Organic", - bg: "bg-green-50", - text: "text-green-700", - border: "border-green-200", - }, - }; - const config = badgeConfig[type]; return ( diff --git a/src/components/ui/ScrollAnimations.tsx b/src/components/ui/ScrollAnimations.tsx index d554054..5e31fe4 100644 --- a/src/components/ui/ScrollAnimations.tsx +++ b/src/components/ui/ScrollAnimations.tsx @@ -248,7 +248,7 @@ interface ProgressIndicatorProps { color?: string; } -export function ProgressIndicator({ +function ProgressIndicator({ className = "", color = "#10b981", }: ProgressIndicatorProps) { diff --git a/src/components/wholesale/OrderDetailsModal.tsx b/src/components/wholesale/OrderDetailsModal.tsx index aaa3950..830786b 100644 --- a/src/components/wholesale/OrderDetailsModal.tsx +++ b/src/components/wholesale/OrderDetailsModal.tsx @@ -11,16 +11,17 @@ type Props = { fulfilling: string | null; }; +const statusBadgeMap: Record = { + pending: "bg-yellow-100 text-yellow-700", + awaiting_deposit: "bg-purple-100 text-purple-700", + confirmed: "bg-blue-100 text-blue-700", + fulfilled: "bg-green-100 text-green-700", + cancelled: "bg-red-100 text-red-700", +}; + function StatusBadge({ status }: { status: string }) { - const map: Record = { - pending: "bg-yellow-100 text-yellow-700", - awaiting_deposit: "bg-purple-100 text-purple-700", - confirmed: "bg-blue-100 text-blue-700", - fulfilled: "bg-green-100 text-green-700", - cancelled: "bg-red-100 text-red-700", - }; return ( - + {status.replace(/_/g, " ")} );