f5f90cd643
Blocco A+B (milestone v2.3). Migration 0011 is additive (ADD COLUMN only): clients.email, clients.phone, leads.archived. - createClientCore() extracted from createClient and reused by conversion - clients.email/phone added to create + edit forms and shown on client header (never exposed on the public /client/[token] page) - convertLeadToClient(): reuses core, carries over lead transcripts (client_transcripts.client_id), links project.created_from_lead_id, archives the lead while keeping its "won" status; idempotent - "Converti in cliente" button on won leads; "Convertito → Apri cliente" once converted (clientId resolved via created_from_lead_id) - archived leads hidden from list/kanban; detail page fetches by id incl. archived Migration must be applied to the prod DB BEFORE this is deployed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
129 lines
3.9 KiB
TypeScript
129 lines
3.9 KiB
TypeScript
import { notFound } from "next/navigation";
|
|
import { db } from "@/db";
|
|
import { clients } from "@/db/schema";
|
|
import { eq } from "drizzle-orm";
|
|
import { updateClient } from "@/app/admin/clients/[id]/actions";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
import Link from "next/link";
|
|
|
|
export default async function EditClientPage({
|
|
params,
|
|
searchParams,
|
|
}: {
|
|
params: Promise<{ id: string }>;
|
|
searchParams: Promise<{ error?: string }>;
|
|
}) {
|
|
const { id } = await params;
|
|
const { error } = await searchParams;
|
|
const [client] = await db.select().from(clients).where(eq(clients.id, id)).limit(1);
|
|
if (!client) notFound();
|
|
|
|
return (
|
|
<div className="max-w-lg">
|
|
<div className="mb-6">
|
|
<Link
|
|
href={`/admin/clients/${id}`}
|
|
className="text-sm text-[#71717a] hover:text-[#1a1a1a]"
|
|
>
|
|
← {client.name}
|
|
</Link>
|
|
</div>
|
|
|
|
<h1 className="text-xl font-bold text-[#1a1a1a] mb-6">Modifica cliente</h1>
|
|
|
|
{error === "slug_taken" && (
|
|
<div className="mb-4 rounded-lg bg-red-50 border border-red-200 px-4 py-3 text-sm text-red-700">
|
|
Slug già in uso da un altro cliente. Scegline uno diverso.
|
|
</div>
|
|
)}
|
|
|
|
<form
|
|
action={async (fd: FormData) => {
|
|
"use server";
|
|
await updateClient(id, fd);
|
|
}}
|
|
className="space-y-5"
|
|
>
|
|
<div className="space-y-1.5">
|
|
<Label htmlFor="name">Nome cliente</Label>
|
|
<Input id="name" name="name" defaultValue={client.name} required />
|
|
</div>
|
|
|
|
<div className="space-y-1.5">
|
|
<Label htmlFor="brand_name">Brand name</Label>
|
|
<Input
|
|
id="brand_name"
|
|
name="brand_name"
|
|
defaultValue={client.brand_name}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<div className="space-y-1.5">
|
|
<Label htmlFor="email">Email</Label>
|
|
<Input
|
|
id="email"
|
|
name="email"
|
|
type="email"
|
|
defaultValue={client.email ?? ""}
|
|
placeholder="marco@rossistudio.it"
|
|
/>
|
|
</div>
|
|
<div className="space-y-1.5">
|
|
<Label htmlFor="phone">Telefono</Label>
|
|
<Input
|
|
id="phone"
|
|
name="phone"
|
|
type="tel"
|
|
defaultValue={client.phone ?? ""}
|
|
placeholder="+39 333 1234567"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-1.5">
|
|
<Label htmlFor="brief">Brief progetto</Label>
|
|
<Textarea
|
|
id="brief"
|
|
name="brief"
|
|
defaultValue={client.brief}
|
|
rows={4}
|
|
placeholder="Descrizione breve del progetto..."
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-1.5">
|
|
<Label htmlFor="slug">Slug personalizzato (opzionale)</Label>
|
|
<p className="text-xs text-[#71717a]">
|
|
Solo lettere minuscole, numeri e trattini (es. mario-rossi). Min 3, max 50 caratteri.
|
|
</p>
|
|
<Input
|
|
id="slug"
|
|
name="slug"
|
|
type="text"
|
|
defaultValue={client.slug ?? ""}
|
|
pattern="[a-z0-9-]{3,50}"
|
|
placeholder="mario-rossi"
|
|
/>
|
|
<p className="text-xs text-[#71717a]">
|
|
Link cliente:{" "}
|
|
<span className="font-mono text-[#1a1a1a]">
|
|
/client/{client.slug || client.token}
|
|
</span>
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex gap-3 pt-2">
|
|
<Button type="submit">Salva modifiche</Button>
|
|
<Button asChild variant="ghost">
|
|
<Link href={`/admin/clients/${id}`}>Annulla</Link>
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
);
|
|
} |