# Clients View & NavRail Reorganization Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Add a Clients management view with billing details and reorder the NavRail into a logical workflow. **Architecture:** Backend-first approach — migrate the database schema, update Rust structs/queries, expand the TypeScript store, then build the frontend view and update navigation. The Clients.vue view follows the same card-grid + dialog pattern established by Projects.vue. **Tech Stack:** Tauri v2 (Rust + SQLite), Vue 3 Composition API, Tailwind CSS v4 with @theme tokens, Lucide icons, Pinia stores, vue-router --- ### Task 1: Database migration — add new columns to clients table **Files:** - Modify: `src-tauri/src/database.rs:1-118` **Step 1: Add ALTER TABLE statements after the existing table creation** After the `CREATE TABLE IF NOT EXISTS clients` block (line 13), add 5 `ALTER TABLE ADD COLUMN` statements. These use `ALTER TABLE ... ADD COLUMN` which is safe to re-run because SQLite will error on duplicate columns — wrap each in a closure that ignores "duplicate column" errors. Add this code after line 13 (after the `?;` that closes the clients CREATE TABLE): ```rust // Migrate clients table — add new columns (safe to re-run) let migration_columns = [ "ALTER TABLE clients ADD COLUMN company TEXT", "ALTER TABLE clients ADD COLUMN phone TEXT", "ALTER TABLE clients ADD COLUMN tax_id TEXT", "ALTER TABLE clients ADD COLUMN payment_terms TEXT", "ALTER TABLE clients ADD COLUMN notes TEXT", ]; for sql in &migration_columns { match conn.execute(sql, []) { Ok(_) => {} Err(e) => { let msg = e.to_string(); if !msg.contains("duplicate column") { return Err(e); } } } } ``` **Step 2: Build to verify migration compiles** Run: `cd src-tauri && cargo check` Expected: compiles with no errors **Step 3: Commit** ```bash git add src-tauri/src/database.rs git commit -m "feat: add migration for new client billing columns" ``` --- ### Task 2: Expand Rust Client struct and update all CRUD queries **Files:** - Modify: `src-tauri/src/commands.rs:6-99` (Client struct + 4 commands) - Modify: `src-tauri/src/commands.rs:382-457` (export_data) **Step 1: Expand the Client struct** Replace the existing `Client` struct (lines 7-12) with: ```rust #[derive(Debug, Serialize, Deserialize)] pub struct Client { pub id: Option, pub name: String, pub email: Option, pub address: Option, pub company: Option, pub phone: Option, pub tax_id: Option, pub payment_terms: Option, pub notes: Option, } ``` **Step 2: Update `get_clients` query (line 62)** Replace the SELECT and row mapping: ```rust let mut stmt = conn.prepare( "SELECT id, name, email, address, company, phone, tax_id, payment_terms, notes FROM clients ORDER BY name" ).map_err(|e| e.to_string())?; let clients = stmt.query_map([], |row| { Ok(Client { id: Some(row.get(0)?), name: row.get(1)?, email: row.get(2)?, address: row.get(3)?, company: row.get(4)?, phone: row.get(5)?, tax_id: row.get(6)?, payment_terms: row.get(7)?, notes: row.get(8)?, }) }).map_err(|e| e.to_string())?; ``` **Step 3: Update `create_client` INSERT (line 77-80)** ```rust conn.execute( "INSERT INTO clients (name, email, address, company, phone, tax_id, payment_terms, notes) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)", params![client.name, client.email, client.address, client.company, client.phone, client.tax_id, client.payment_terms, client.notes], ).map_err(|e| e.to_string())?; ``` **Step 4: Update `update_client` UPDATE (line 87-89)** ```rust conn.execute( "UPDATE clients SET name = ?1, email = ?2, address = ?3, company = ?4, phone = ?5, tax_id = ?6, payment_terms = ?7, notes = ?8 WHERE id = ?9", params![client.name, client.email, client.address, client.company, client.phone, client.tax_id, client.payment_terms, client.notes, client.id], ).map_err(|e| e.to_string())?; ``` **Step 5: Update `export_data` clients query (lines 386-397)** Replace the clients block inside `export_data`: ```rust let clients = { let mut stmt = conn.prepare("SELECT id, name, email, address, company, phone, tax_id, payment_terms, notes FROM clients").map_err(|e| e.to_string())?; let rows: Vec = stmt.query_map([], |row| { Ok(serde_json::json!({ "id": row.get::<_, i64>(0)?, "name": row.get::<_, String>(1)?, "email": row.get::<_, Option>(2)?, "address": row.get::<_, Option>(3)?, "company": row.get::<_, Option>(4)?, "phone": row.get::<_, Option>(5)?, "tax_id": row.get::<_, Option>(6)?, "payment_terms": row.get::<_, Option>(7)?, "notes": row.get::<_, Option>(8)? })) }).map_err(|e| e.to_string())?.collect::, _>>().map_err(|e| e.to_string())?; rows }; ``` **Step 6: Build to verify everything compiles** Run: `cd src-tauri && cargo check` Expected: compiles with no errors **Step 7: Commit** ```bash git add src-tauri/src/commands.rs git commit -m "feat: expand Client struct with billing fields and update all queries" ``` --- ### Task 3: Expand TypeScript Client interface in the Pinia store **Files:** - Modify: `src/stores/clients.ts:5-10` **Step 1: Add new optional fields to the Client interface** Replace the existing `Client` interface (lines 5-10) with: ```typescript export interface Client { id?: number name: string email?: string address?: string company?: string phone?: string tax_id?: string payment_terms?: string notes?: string } ``` No other changes needed — the store's `createClient`, `updateClient`, `fetchClients` all pass/receive `Client` objects, so the new fields flow through automatically. **Step 2: Verify the frontend builds** Run: `npm run build` Expected: builds with no errors **Step 3: Commit** ```bash git add src/stores/clients.ts git commit -m "feat: expand Client interface with billing fields" ``` --- ### Task 4: Add /clients route to the router **Files:** - Modify: `src/router/index.ts` **Step 1: Add the clients route** Insert the clients route between the `/timer` and `/projects` routes (between lines 16 and 17): ```typescript { path: '/clients', name: 'Clients', component: () => import('../views/Clients.vue') }, ``` The full routes array will now be: `/` (Dashboard), `/timer` (Timer), `/clients` (Clients), `/projects` (Projects), `/entries` (Entries), `/reports` (Reports), `/invoices` (Invoices), `/settings` (Settings). **Step 2: Commit** ```bash git add src/router/index.ts git commit -m "feat: add /clients route" ``` --- ### Task 5: Reorder NavRail and add Clients entry **Files:** - Modify: `src/components/NavRail.vue` **Step 1: Add `Users` to the Lucide import** Replace the import block (lines 6-13) with: ```typescript import { LayoutDashboard, Clock, Users, FolderKanban, List, BarChart3, FileText, Settings } from 'lucide-vue-next' ``` **Step 2: Reorder the navItems array** Replace the `navItems` array (lines 19-27) with the new workflow order: ```typescript const navItems = [ { name: 'Dashboard', path: '/', icon: LayoutDashboard }, { name: 'Timer', path: '/timer', icon: Clock }, { name: 'Clients', path: '/clients', icon: Users }, { name: 'Projects', path: '/projects', icon: FolderKanban }, { name: 'Entries', path: '/entries', icon: List }, { name: 'Invoices', path: '/invoices', icon: FileText }, { name: 'Reports', path: '/reports', icon: BarChart3 }, { name: 'Settings', path: '/settings', icon: Settings } ] ``` Note: Invoices moved before Reports (bill clients, then analyze). **Step 3: Verify the frontend builds** Run: `npm run build` Expected: builds with no errors (will warn about missing Clients.vue — that's fine, it's lazy-loaded) **Step 4: Commit** ```bash git add src/components/NavRail.vue git commit -m "feat: reorder NavRail and add Clients entry" ``` --- ### Task 6: Create Clients.vue — card grid, empty state, and base layout **Files:** - Create: `src/views/Clients.vue` **Step 1: Create the Clients view** Create `src/views/Clients.vue` following the Projects.vue pattern exactly. The view has: - Header with "Clients" title and "+ Add" button - Card grid (1-3 columns responsive) showing: name (bold), company subtitle (if set), email (tertiary) - Hover reveals edit/delete icons (same SVG icons as Projects.vue) - Empty state with `Users` icon, "No clients yet" message, and "Create Client" CTA - Create/Edit dialog with two sections: - **Contact Info**: Name (required), Email, Phone, Address (textarea) - **Billing Details** (collapsible): Company, Tax ID, Payment Terms, Notes (textarea) - Delete confirmation dialog (same pattern as Projects) ```vue