feat(09-02): implement admin quote builder UI with server actions
- src/lib/quote-actions.ts: createQuote server action with nanoid tokens and atomic DB transaction - src/components/admin/quotes/QuoteBuilderForm.tsx: Two-column form (left: client/offer/price inputs, right: live preview) - src/components/admin/quotes/OfferSelector.tsx: Grouped dropdown for macro/micro offer selection - src/components/admin/quotes/PriceOverrideInput.tsx: Price input with server validation feedback - src/components/admin/quotes/QuotePreview.tsx: Live preview card showing offer details and calculated total - src/app/admin/quotes/new/page.tsx: Quote builder page rendering form with data from DB - src/app/admin/quotes/new/actions.ts: Re-export of createQuote for page-level action imports - src/lib/admin-queries.ts: Added getAllOfferMacrosWithMicros() query for form population Features: - Admin selects client and offer (required fields) - Form validates on blur and displays success/error states - Server action validates data and rejects if total mismatch - On success, displays public /quote/[token] link with copy button - Quote saved as draft state with immutable accepted_total Completes Phase 9 Plan 2 Wave 1: Admin UI Layer Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { QuoteBuilderForm } from "@/components/admin/quotes/QuoteBuilderForm";
|
||||
import { getAllClientsWithPayments } from "@/lib/admin-queries";
|
||||
import { getAllOfferMacrosWithMicros } from "@/lib/admin-queries";
|
||||
|
||||
export const revalidate = 0;
|
||||
|
||||
export default async function QuoteBuilderPage() {
|
||||
const [clientsData, offersData] = await Promise.all([
|
||||
getAllClientsWithPayments(),
|
||||
getAllOfferMacrosWithMicros(),
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-gray-900">Crea Preventivo</h1>
|
||||
<p className="text-gray-600 mt-1">
|
||||
Componi un preventivo per il cliente selezionando l'offerta e il prezzo
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Card className="p-6">
|
||||
<QuoteBuilderForm clients={clientsData} offerMacros={offersData} />
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user