feat(admin): comprehensive functionality pass across admin apps (Codex review)
- Restore admin order creation (top blocker): - New createAdminOrder server action wrapping create_order_with_items RPC with proper getAdminUser + can_manage_orders + brand scoping. - AdminOrdersPanel now supports ?new=true with working modal form (customer, stop/ship, dynamic items with fulfillment/price/qty, live total). - Fixed dashboard "New Order" and "Create your first order" links; added /admin/orders/new redirect. - Success flow: toast + redirect to list. - Product edit reliability and admin flows hardened. - Form a11y + validation foundation (cross-cutting): - AdminInput now generates stable ids, sets htmlFor, forwards required/aria-required/aria-describedby to children. - All admin forms benefit (labels programmatic, required semantics real). - Integrations: non-secret fields (email, name, phone for Resend/Twilio) no longer masked as password by default. Only isSecret fields use type=password + toggle. - Advanced/AI settings pages now expose real content (cards + links to actual config) instead of pure redirects. - Permission hardening example: water-log admin creates now enforce getAdminUser + can_manage_water_log + service key. - Systematic coverage of admin "apps": orders, products, stops, communications, wholesale, water-log, time-tracking, route-trace, settings (billing/integrations/ai/apps/etc), import, users, reports, etc. via exploration + targeted fixes. Empty states, toasts, scoping, quick actions improved. - Updated MEMORY.md with full pass summary, test instructions, and remaining items from Codex review. Non-destructive focus during pass; used dev auth for verification. Core blockers from review now addressed for testing. See session plan.md for detailed execution guide.
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
type AdminInputProps = {
|
||||
label?: string;
|
||||
error?: string;
|
||||
@@ -15,19 +17,44 @@ export function AdminInput({
|
||||
helpText,
|
||||
required,
|
||||
className = "",
|
||||
children
|
||||
}: AdminInputProps) {
|
||||
children,
|
||||
id,
|
||||
}: AdminInputProps & { id?: string }) {
|
||||
// Generate a stable id for label association when label is provided
|
||||
const generatedId = id || (label ? `admin-input-${label.toLowerCase().replace(/[^a-z0-9]/g, "-")}` : undefined);
|
||||
|
||||
// Clone child to inject id + aria props if it's a valid element (input/textarea/select)
|
||||
const enhancedChildren = React.isValidElement(children)
|
||||
? React.cloneElement(children as React.ReactElement<any>, {
|
||||
id: (children as any).props?.id || generatedId,
|
||||
"aria-required": required ? "true" : undefined,
|
||||
required: required ? true : undefined,
|
||||
"aria-describedby": error ? `${generatedId}-error` : helpText ? `${generatedId}-help` : undefined,
|
||||
})
|
||||
: children;
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{label && (
|
||||
<label className="block text-xs font-semibold text-[var(--admin-text-secondary)] mb-1.5">
|
||||
<label
|
||||
htmlFor={generatedId}
|
||||
className="block text-xs font-semibold text-[var(--admin-text-secondary)] mb-1.5 cursor-pointer"
|
||||
>
|
||||
{label}
|
||||
{required && <span className="text-[var(--admin-danger)] ml-1">*</span>}
|
||||
{required && <span className="text-[var(--admin-danger)] ml-1" aria-hidden="true">*</span>}
|
||||
</label>
|
||||
)}
|
||||
{children}
|
||||
{helpText && !error && <p className="mt-1 text-[10px] text-[var(--admin-text-muted)]">{helpText}</p>}
|
||||
{error && <p className="mt-1 text-xs text-[var(--admin-danger)]">{error}</p>}
|
||||
{enhancedChildren}
|
||||
{helpText && !error && (
|
||||
<p id={generatedId ? `${generatedId}-help` : undefined} className="mt-1 text-[10px] text-[var(--admin-text-muted)]">
|
||||
{helpText}
|
||||
</p>
|
||||
)}
|
||||
{error && (
|
||||
<p id={generatedId ? `${generatedId}-error` : undefined} className="mt-1 text-xs text-[var(--admin-danger)]" role="alert">
|
||||
{error}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user