--- phase: 10 plan: 03 type: execute wave: 2 depends_on: [10-01, 10-02] files_modified: - src/components/admin/leads/LogActivityModal.tsx - src/components/admin/leads/SendQuoteModal.tsx - src/app/admin/leads/actions.ts - src/components/admin/dashboard/FollowUpWidget.tsx - src/app/admin/page.tsx autonomous: true requirements: - CRM-04 - CRM-05 - CRM-06 - CRM-07 --- Phase 10 CRM UI (Part 2): Implement activity logging modal (<10 sec UX), send quote button with lead status update, and follow-up reminders widget on admin dashboard. Complete the CRM workflow with activity tracking and lead progression. Purpose: Enable admins to quickly log interactions (calls, emails, meetings, notes) and transition leads through the pipeline. "Send Quote" button creates/selects quotes and updates lead status to "proposal_sent". Follow-up widget on dashboard highlights leads needing contact (last contact > 7 days ago). Output: - LogActivityModal: fast form (type dropdown, date picker, optional duration, notes) with server action - SendQuoteModal: select existing quote or create new, auto-update lead.status → "proposal_sent" - FollowUpWidget: dashboard card showing leads needing follow-up (count + link to /admin/leads) - Server actions: createActivity (auto-updates lead.last_contact_date), updateLeadStageViaQuote - Activity list updates immediately after form submit @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/REQUIREMENTS.md @.planning/phases/10-crm-pipeline-activity-logging/10-01-SUMMARY.md @.planning/phases/10-crm-pipeline-activity-logging/10-02-SUMMARY.md From src/lib/lead-service.ts (created in Plan 1): ```typescript export async function createActivity(data: { lead_id: string; type: string; activity_date: Date; duration_minutes?: number; notes: string; }): Promise; export async function getLeadsNeedingFollowUp(daysAgo?: number): Promise; ``` From src/lib/lead-validators.ts (created in Plan 1): ```typescript export const ACTIVITY_TYPES = ["call", "email", "meeting", "note"] as const; export const createActivitySchema: ZodType<{ lead_id, type, activity_date, duration_minutes?, notes }>; ``` From existing quote-service.ts (Phase 9): ```typescript export async function getQuoteByTokenAdmin(token: string); export async function createQuote(data: any): Promise; ``` Task 1: Create LogActivityModal component and server action src/components/admin/leads/LogActivityModal.tsx, src/app/admin/leads/actions.ts File: `src/components/admin/leads/LogActivityModal.tsx` ```typescript "use client"; import { useState } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; import { createActivitySchema, ACTIVITY_TYPES } from "@/lib/lead-validators"; import { logActivity } from "@/app/admin/leads/actions"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Button } from "@/components/ui/button"; type LogActivityInput = z.infer; export function LogActivityModal({ leadId }: { leadId: string }) { const [open, setOpen] = useState(false); const form = useForm({ resolver: zodResolver(createActivitySchema), defaultValues: { lead_id: leadId, type: "note", activity_date: new Date().toISOString().split("T")[0], }, }); async function onSubmit(data: LogActivityInput) { const result = await logActivity(data); if (result.success) { setOpen(false); form.reset({ lead_id: leadId, type: "note", activity_date: new Date().toISOString().split("T")[0], }); // TODO: Toast success + revalidate parent activity log } } return ( Registra Attività
( Tipo )} /> ( Data )} /> ( Durata (minuti) - opzionale )} /> ( Note