"""Contacts: people directory for CRM.""" from fastapi import APIRouter, Request, Form, Depends from fastapi.templating import Jinja2Templates from fastapi.responses import RedirectResponse from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import text from typing import Optional from core.database import get_db from core.base_repository import BaseRepository from core.sidebar import get_sidebar_data router = APIRouter(prefix="/contacts", tags=["contacts"]) templates = Jinja2Templates(directory="templates") @router.get("/") async def list_contacts(request: Request, db: AsyncSession = Depends(get_db)): sidebar = await get_sidebar_data(db) result = await db.execute(text(""" SELECT * FROM contacts WHERE is_deleted = false ORDER BY sort_order, first_name, last_name """)) items = [dict(r._mapping) for r in result] return templates.TemplateResponse("contacts.html", { "request": request, "sidebar": sidebar, "items": items, "page_title": "Contacts", "active_nav": "contacts", }) @router.get("/create") async def create_form(request: Request, db: AsyncSession = Depends(get_db)): sidebar = await get_sidebar_data(db) return templates.TemplateResponse("contact_form.html", { "request": request, "sidebar": sidebar, "page_title": "New Contact", "active_nav": "contacts", "item": None, }) @router.post("/create") async def create_contact( request: Request, first_name: str = Form(...), last_name: Optional[str] = Form(None), company: Optional[str] = Form(None), role: Optional[str] = Form(None), email: Optional[str] = Form(None), phone: Optional[str] = Form(None), notes: Optional[str] = Form(None), tags: Optional[str] = Form(None), db: AsyncSession = Depends(get_db), ): repo = BaseRepository("contacts", db) data = { "first_name": first_name, "last_name": last_name, "company": company, "role": role, "email": email, "phone": phone, "notes": notes, } if tags and tags.strip(): data["tags"] = [t.strip() for t in tags.split(",") if t.strip()] await repo.create(data) return RedirectResponse(url="/contacts", status_code=303) @router.get("/{contact_id}") async def contact_detail(contact_id: str, request: Request, db: AsyncSession = Depends(get_db)): repo = BaseRepository("contacts", db) sidebar = await get_sidebar_data(db) item = await repo.get(contact_id) if not item: return RedirectResponse(url="/contacts", status_code=303) return templates.TemplateResponse("contact_detail.html", { "request": request, "sidebar": sidebar, "item": item, "page_title": f"{item['first_name']} {item.get('last_name', '')}".strip(), "active_nav": "contacts", }) @router.get("/{contact_id}/edit") async def edit_form(contact_id: str, request: Request, db: AsyncSession = Depends(get_db)): repo = BaseRepository("contacts", db) sidebar = await get_sidebar_data(db) item = await repo.get(contact_id) if not item: return RedirectResponse(url="/contacts", status_code=303) return templates.TemplateResponse("contact_form.html", { "request": request, "sidebar": sidebar, "page_title": "Edit Contact", "active_nav": "contacts", "item": item, }) @router.post("/{contact_id}/edit") async def update_contact( contact_id: str, first_name: str = Form(...), last_name: Optional[str] = Form(None), company: Optional[str] = Form(None), role: Optional[str] = Form(None), email: Optional[str] = Form(None), phone: Optional[str] = Form(None), notes: Optional[str] = Form(None), tags: Optional[str] = Form(None), db: AsyncSession = Depends(get_db), ): repo = BaseRepository("contacts", db) data = { "first_name": first_name, "last_name": last_name, "company": company, "role": role, "email": email, "phone": phone, "notes": notes, } if tags and tags.strip(): data["tags"] = [t.strip() for t in tags.split(",") if t.strip()] else: data["tags"] = None await repo.update(contact_id, data) return RedirectResponse(url=f"/contacts/{contact_id}", status_code=303) @router.post("/{contact_id}/delete") async def delete_contact(contact_id: str, db: AsyncSession = Depends(get_db)): repo = BaseRepository("contacts", db) await repo.soft_delete(contact_id) return RedirectResponse(url="/contacts", status_code=303) @router.post("/reorder") async def reorder_contact( request: Request, item_id: str = Form(...), direction: str = Form(...), db: AsyncSession = Depends(get_db), ): repo = BaseRepository("contacts", db) await repo.move_in_order(item_id, direction) return RedirectResponse(url=request.headers.get("referer", "/contacts"), status_code=303)