feat(admin): design system audit fixes

- Add CSS design tokens for consistency (--admin-danger-hover, --admin-accent-dot, shadow-md warm tone)
- Replace unicode icons with inline SVG (⋮, ✕, ▼, ▶)
- Consolidate duplicate PageHeader/AdminPageHeader components
- Standardize border-radius (rounded-xl → rounded-lg for ViewModeTabs)
- Remove hardcoded brand UUID in products page
- Replace hardcoded bg-red-600 with CSS variables in delete buttons
- Add AdminButton, AdminFilterTabs, AdminSearchInput, PageHeader design system components
- Fix GlassModal and AdminModal close button styling
- Remove duplicate 'New Lot' button on Route Trace dashboard
This commit is contained in:
2026-06-02 03:31:54 +00:00
parent 15e939ad7e
commit 7203cf1ead
65 changed files with 3478 additions and 3176 deletions
+30 -65
View File
@@ -7,6 +7,7 @@ import {
testFedExConnection,
type ShippingSettings,
} from "@/actions/shipping/settings";
import { AdminInput, AdminTextInput, AdminTextarea, AdminSelect } from "./design-system";
const SERVICE_OPTIONS = [
{ value: "FEDEX_OVERNIGHT", label: "FedEx Overnight" },
@@ -121,18 +122,13 @@ export default function ShippingSettingsForm({
<form onSubmit={handleSave} className="space-y-8">
{/* Platform admin brand picker */}
{isPlatformAdmin && brands.length > 0 && (
<div>
<label className="mb-1 block text-sm font-medium text-zinc-300">Brand</label>
<select
<AdminInput label="Brand">
<AdminSelect
value={activeBrandId}
onChange={(e) => setActiveBrandId(e.target.value)}
className="w-full rounded-xl border border-zinc-600 bg-zinc-800 px-4 py-3 text-base text-zinc-100 outline-none focus:border-zinc-400"
>
{brands.map((b) => (
<option key={b.id} value={b.id}>{b.name}</option>
))}
</select>
</div>
options={brands.map((b) => ({ value: b.id, label: b.name }))}
/>
</AdminInput>
)}
{/* Connection status banner */}
@@ -180,45 +176,29 @@ export default function ShippingSettingsForm({
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-zinc-300">
FedEx Account Number <span className="text-red-500">*</span>
</label>
<input
type="text"
<AdminInput label="FedEx Account Number *">
<AdminTextInput
value={fedexAccountNumber}
onChange={(e) => setFedexAccountNumber(e.target.value)}
placeholder="000000000000 (12 digits)"
maxLength={12}
className="mt-1 w-full rounded-xl border border-zinc-600 bg-zinc-800 px-4 py-3 text-sm font-mono text-zinc-100 outline-none focus:border-zinc-400"
/>
</div>
<div>
<label className="block text-sm font-medium text-zinc-300">
API Key <span className="text-red-500">*</span>
</label>
<input
type="text"
</AdminInput>
<AdminInput label="API Key *">
<AdminTextInput
value={fedexApiKey}
onChange={(e) => setFedexApiKey(e.target.value)}
placeholder="Your FedEx API key"
className="mt-1 w-full rounded-xl border border-zinc-600 bg-zinc-800 px-4 py-3 text-sm text-zinc-100 outline-none focus:border-zinc-400"
/>
</div>
</AdminInput>
</div>
<div>
<label className="block text-sm font-medium text-zinc-300">
API Secret <span className="text-red-500">*</span>
<span className="ml-2 text-slate-400 font-normal">(password field)</span>
</label>
<div className="relative mt-1">
<input
<AdminInput label="API Secret *" helpText="Password field — click Show/Hide to reveal">
<div className="relative">
<AdminTextInput
type={showSecret ? "text" : "password"}
value={fedexApiSecret}
onChange={(e) => setFedexApiSecret(e.target.value)}
placeholder="Your FedEx API secret"
className="w-full rounded-xl border border-zinc-600 bg-zinc-800 px-4 py-3 pr-12 text-sm text-zinc-100 outline-none focus:border-zinc-400"
/>
<button
type="button"
@@ -228,7 +208,7 @@ export default function ShippingSettingsForm({
{showSecret ? "Hide" : "Show"}
</button>
</div>
</div>
</AdminInput>
{/* Production toggle */}
<div className="flex items-center gap-3 rounded-lg border border-zinc-700 bg-zinc-800 px-4 py-3">
@@ -287,20 +267,13 @@ export default function ShippingSettingsForm({
</p>
</div>
<div>
<label className="mb-2 block text-sm font-medium text-zinc-300">
Default for non-perishable orders
</label>
<select
<AdminInput label="Default for non-perishable orders">
<AdminSelect
value={defaultServiceType}
onChange={(e) => setDefaultServiceType(e.target.value)}
className="w-full rounded-xl border border-zinc-600 bg-zinc-800 px-4 py-3 text-sm text-zinc-100 outline-none focus:border-zinc-400"
>
{SERVICE_OPTIONS.map((opt) => (
<option key={opt.value} value={opt.value}>{opt.label}</option>
))}
</select>
</div>
options={SERVICE_OPTIONS}
/>
</AdminInput>
</div>
{/* Handling notes */}
@@ -312,34 +285,26 @@ export default function ShippingSettingsForm({
</p>
</div>
<div>
<label className="mb-1 block text-sm font-medium text-zinc-300">
🌽 Refrigerated / Perishable Notes
</label>
<textarea
<AdminInput
label="Refrigerated / Perishable Notes"
helpText="Applied to all shipments with perishable items (is_perishable = true)."
>
<AdminTextarea
value={refrigeratedHandlingNotes}
onChange={(e) => setRefrigeratedHandlingNotes(e.target.value)}
rows={3}
className="w-full rounded-xl border border-zinc-600 bg-zinc-800 px-4 py-3 text-sm text-zinc-100 outline-none focus:border-zinc-400"
placeholder="e.g. Keep refrigerated. Do not freeze. Contains fresh sweet corn and/or onions."
/>
<p className="mt-1 text-xs text-zinc-500">
Applied to all shipments with perishable items (is_perishable = true).
</p>
</div>
</AdminInput>
<div>
<label className="mb-1 block text-sm font-medium text-zinc-300">
📦 Fragile Items Notes
</label>
<textarea
<AdminInput label="Fragile Items Notes">
<AdminTextarea
value={fragileHandlingNotes}
onChange={(e) => setFragileHandlingNotes(e.target.value)}
rows={2}
className="w-full rounded-xl border border-zinc-600 bg-zinc-800 px-4 py-3 text-sm text-zinc-100 outline-none focus:border-zinc-400"
placeholder="e.g. Fragile — handle with care. Do not stack heavy items on top."
/>
</div>
</AdminInput>
</div>
{loading ? (