chore: merge executor worktree (worktree-agent-aaf61d7161f7818a0)

# Conflicts:
#	.planning/phases/14-crm-attio-style-fix/deferred-items.md
This commit is contained in:
2026-06-14 12:51:37 +02:00
6 changed files with 167 additions and 30 deletions
@@ -12,34 +12,33 @@ export async function FollowUpWidget() {
<CardHeader>
<CardTitle className="flex items-center gap-2">
<AlertCircle className="h-5 w-5 text-orange-600" />
Require Follow-up
Richiedi Follow-up
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{leadsNeedingFollowUp.length > 0 ? (
<>
<p className="text-lg font-bold text-orange-900">
{leadsNeedingFollowUp.length} lead{leadsNeedingFollowUp.length !== 1 ? "s" : ""}{" "}
to contact
{leadsNeedingFollowUp.length} lead da contattare
</p>
<ul className="space-y-2 text-sm">
{leadsNeedingFollowUp.slice(0, 3).map((lead) => (
<li key={lead.id} className="flex justify-between items-center">
<span>{lead.name}</span>
<Button variant="ghost" size="sm" asChild>
<Link href={`/admin/leads/${lead.id}`}>Contact</Link>
<Link href={`/admin/leads/${lead.id}`}>Contatta</Link>
</Button>
</li>
))}
</ul>
{leadsNeedingFollowUp.length > 3 && (
<Button variant="outline" className="w-full" asChild>
<Link href="/admin/leads">View All ({leadsNeedingFollowUp.length})</Link>
<Link href="/admin/leads">Vedi Tutto ({leadsNeedingFollowUp.length})</Link>
</Button>
)}
</>
) : (
<p className="text-gray-600 text-sm">All leads are up to date!</p>
<p className="text-gray-600 text-sm">Tutti i lead sono aggiornati!</p>
)}
</CardContent>
</Card>
+4 -7
View File
@@ -3,8 +3,7 @@
import { useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { createLeadSchema, LEAD_STAGES } from "@/lib/lead-validators";
import { createLeadSchema, LEAD_STAGES, type CreateLeadInput } from "@/lib/lead-validators";
import { Lead } from "@/db/schema";
import { createLead, updateLead } from "@/app/admin/leads/actions";
import {
@@ -33,12 +32,10 @@ import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Button } from "@/components/ui/button";
type CreateLeadInput = z.infer<typeof createLeadSchema>;
export function CreateLeadModal() {
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const form = useForm<any>({
const form = useForm<CreateLeadInput>({
resolver: zodResolver(createLeadSchema),
defaultValues: {
name: "",
@@ -202,14 +199,14 @@ export function CreateLeadModal() {
export function EditLeadModal({ lead }: { lead: Lead }) {
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const form = useForm<any>({
const form = useForm<CreateLeadInput>({
resolver: zodResolver(createLeadSchema),
defaultValues: {
name: lead.name,
email: lead.email || "",
phone: lead.phone || "",
company: lead.company || "",
status: lead.status as any,
status: lead.status as CreateLeadInput["status"],
notes: lead.notes || "",
},
});
@@ -48,12 +48,6 @@ export function SendQuoteModal({ leadId }: { leadId: string }) {
async function onSubmit(data: any) {
setLoading(true);
try {
if (tab === "new") {
// Redirect to quote builder pre-filled with this lead
window.location.href = `/admin/quotes/new?lead_id=${leadId}`;
return;
}
const result = await assignQuoteToLead({
lead_id: leadId,
quote_token: data.quote_token,
@@ -109,7 +103,7 @@ export function SendQuoteModal({ leadId }: { leadId: string }) {
/>
<p className="text-xs text-gray-600">
Copia il token dal preventivo e incollalo qui. Il lead sarà aggiornato a
"Proposal Sent".
&quot;Proposal Sent&quot;.
</p>
<Button type="submit" disabled={loading} className="w-full">
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
+7 -6
View File
@@ -27,15 +27,16 @@ const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue
)
const FormField = React.forwardRef<
any,
ControllerProps<any, any>
>(({ ...props }, ref) => (
const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
...props
}: ControllerProps<TFieldValues, TName>) => (
<FormFieldContext.Provider value={{ name: props.name }}>
<Controller {...props} />
</FormFieldContext.Provider>
))
FormField.displayName = "FormField"
)
const useFormField = () => {
const fieldContext = React.useContext(FormFieldContext)