feat: Move action buttons to contextual headers for CRUD pages
Implemented proper contextual header pattern for all Order CRUD pages. Problem: - New/Edit pages had action buttons at bottom of form - Detail page showed duplicate headers (contextual + inline) - Not following mobile-first best practices Solution: [Back] Page Title [Action] 1. Edit Order Page Header: [Back] Edit Order #337 [Save] Implementation: - Added formRef to trigger form submit from header - Save button in contextual header - Removed submit button from form bottom - Button shows loading state during save Changes: - Edit.tsx: Added formRef, updated header with Save button - OrderForm.tsx: Added formRef and hideSubmitButton props - Form submit triggered via formRef.current.requestSubmit() 2. New Order Page Header: [Back] New Order [Create] Implementation: - Added formRef to trigger form submit from header - Create button in contextual header - Removed submit button from form bottom - Button shows loading state during creation Changes: - New.tsx: Added formRef, updated header with Create button - Same OrderForm props as Edit page 3. Order Detail Page Header: (hidden) Implementation: - Cleared contextual header completely - Detail page has its own inline header with actions - Inline header: [Back] Order #337 [Print] [Invoice] [Label] [Edit] Changes: - Detail.tsx: clearPageHeader() in useEffect - No duplicate headers OrderForm Component Updates: - Added formRef prop (React.RefObject<HTMLFormElement>) - Added hideSubmitButton prop (boolean) - Form element accepts ref: <form ref={formRef}> - Submit button conditionally rendered: {!hideSubmitButton && <Button...>} - Backward compatible (both props optional) Benefits: ✅ Consistent header pattern across all CRUD pages ✅ Action buttons always visible (sticky header) ✅ Better mobile UX (no scrolling to find buttons) ✅ Loading states in header buttons ✅ Clean, modern interface ✅ Follows industry standards (Gmail, Notion, Linear) Files Modified: - routes/Orders/New.tsx - routes/Orders/Edit.tsx - routes/Orders/Detail.tsx - routes/Orders/partials/OrderForm.tsx Result: ✅ New/Edit: Action buttons in contextual header ✅ Detail: No contextual header (has inline header) ✅ Professional, mobile-first UX! 🎯
This commit is contained in:
@@ -142,35 +142,11 @@ export default function OrderShow() {
|
||||
retryPaymentMutation.mutate();
|
||||
}
|
||||
|
||||
// Set page header with actions
|
||||
// Hide contextual header on detail page (has its own inline header)
|
||||
useEffect(() => {
|
||||
if (!order || isPrintMode) {
|
||||
clearPageHeader();
|
||||
return;
|
||||
}
|
||||
|
||||
const actions = (
|
||||
<div className="flex gap-2">
|
||||
<Button size="sm" variant="outline" onClick={printInvoice}>
|
||||
<FileText className="w-4 h-4 mr-1" />
|
||||
{__('Invoice')}
|
||||
</Button>
|
||||
<Link to={`/orders/${id}/edit`}>
|
||||
<Button size="sm">
|
||||
<Pencil className="w-4 h-4 mr-1" />
|
||||
{__('Edit')}
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
|
||||
setPageHeader(
|
||||
order.number ? `${__('Order')} #${order.number}` : __('Order'),
|
||||
actions
|
||||
);
|
||||
|
||||
clearPageHeader();
|
||||
return () => clearPageHeader();
|
||||
}, [order, isPrintMode, id, setPageHeader, clearPageHeader]);
|
||||
}, [clearPageHeader]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isPrintMode || !qrRef.current || !order) return;
|
||||
|
||||
Reference in New Issue
Block a user