|
| 1 | +# Sherlock's Diary Feature Specification |
| 2 | + |
| 3 | +## Overview |
| 4 | +A mobile-first note-taking extension for on-the-go investigators, accessible via a pencil icon in the sidebar. |
| 5 | + |
| 6 | +## Feature Components |
| 7 | + |
| 8 | +### 1. Sidebar Integration |
| 9 | +- Add pencil icon (`PenLine` from lucide-react) to the navigation |
| 10 | +- Route: `/cases/[id]/notebook` or a global `/notebook` |
| 11 | + |
| 12 | +### 2. Sherlock's Diary UI |
| 13 | +A mobile-optimized interface with three main sections: |
| 14 | + |
| 15 | +#### A. Note Entry |
| 16 | +- **Text Notes**: Simple textarea with save functionality |
| 17 | +- **Audio Notes**: |
| 18 | + - Record button using Web Audio API / MediaRecorder |
| 19 | + - Upload existing audio files |
| 20 | + - Auto-save recordings as MP3/WebM |
| 21 | + |
| 22 | +#### B. Notes Directory |
| 23 | +- List view showing all notes for the current case |
| 24 | +- Each note displays: |
| 25 | + - AI-generated title (via Gemini) |
| 26 | + - AI-generated subtitle/summary |
| 27 | + - Date created |
| 28 | + - Type indicator (text/audio) |
| 29 | +- Sorted by date (newest first) |
| 30 | + |
| 31 | +#### C. Chat Integration |
| 32 | +- Floating chatbot button (reuse existing Chatbot component) |
| 33 | +- Future: Notes will be integrated into chatbot memory |
| 34 | + |
| 35 | +### 3. Export to Evidence |
| 36 | +Each note in the directory has an "Export as Evidence" button: |
| 37 | +- **Audio notes**: Upload MP3 directly to GCS evidence bucket |
| 38 | +- **Text notes**: Convert to PDF, then upload to GCS evidence bucket |
| 39 | +- Uses existing file upload infrastructure |
| 40 | + |
| 41 | +### 4. Mobile-First UX |
| 42 | +- Optimized for small screens |
| 43 | +- Bottom navigation for main actions |
| 44 | +- Swipe gestures for note navigation |
| 45 | +- Responsive but mobile-first design |
| 46 | + |
| 47 | +### 5. Device Detection |
| 48 | +- In middleware, detect mobile devices via User-Agent |
| 49 | +- On mobile login, redirect to `/cases/[id]/notebook` by default |
| 50 | +- Add toggle to switch to full desktop view |
| 51 | + |
| 52 | +## Technical Implementation |
| 53 | + |
| 54 | +### Backend API Endpoints |
| 55 | +``` |
| 56 | +POST /api/cases/{case_id}/notes - Create note |
| 57 | +GET /api/cases/{case_id}/notes - List notes |
| 58 | +GET /api/cases/{case_id}/notes/{id} - Get single note |
| 59 | +PUT /api/cases/{case_id}/notes/{id} - Update note |
| 60 | +DELETE /api/cases/{case_id}/notes/{id} - Delete note |
| 61 | +POST /api/cases/{case_id}/notes/{id}/export - Export to evidence |
| 62 | +POST /api/cases/{case_id}/notes/generate-metadata - AI generate title/subtitle |
| 63 | +``` |
| 64 | + |
| 65 | +### Database Schema |
| 66 | +```sql |
| 67 | +CREATE TABLE case_notes ( |
| 68 | + id UUID PRIMARY KEY, |
| 69 | + case_id UUID REFERENCES cases(id), |
| 70 | + user_id TEXT NOT NULL, |
| 71 | + type VARCHAR(10) NOT NULL, -- 'text' or 'audio' |
| 72 | + content TEXT, -- For text notes |
| 73 | + audio_storage_path VARCHAR(500), -- For audio notes |
| 74 | + audio_duration_seconds INTEGER, |
| 75 | + title VARCHAR(255), -- AI-generated |
| 76 | + subtitle TEXT, -- AI-generated |
| 77 | + is_exported BOOLEAN DEFAULT FALSE, |
| 78 | + exported_file_id UUID REFERENCES case_files(id), |
| 79 | + created_at TIMESTAMPTZ DEFAULT NOW(), |
| 80 | + updated_at TIMESTAMPTZ DEFAULT NOW() |
| 81 | +); |
| 82 | + |
| 83 | +CREATE INDEX idx_case_notes_case_id ON case_notes(case_id); |
| 84 | +CREATE INDEX idx_case_notes_user_id ON case_notes(user_id); |
| 85 | +``` |
| 86 | + |
| 87 | +### Frontend Pages/Components |
| 88 | +- `/app/(app)/cases/[id]/notebook/page.tsx` - Main notebook page |
| 89 | +- `/components/notebook/` - All notebook components |
| 90 | + - `NoteEditor.tsx` - Text/audio note editor |
| 91 | + - `AudioRecorder.tsx` - Audio recording component |
| 92 | + - `NotesList.tsx` - Directory list view |
| 93 | + - `NoteCard.tsx` - Individual note display |
| 94 | + - `ExportButton.tsx` - Export to evidence button |
| 95 | + |
| 96 | +### Gemini Integration |
| 97 | +Use existing Gemini configuration for title/subtitle generation: |
| 98 | +- Small context window call |
| 99 | +- Input: Note content (text or audio transcript) |
| 100 | +- Output: { title: string, subtitle: string } |
| 101 | + |
| 102 | +## Implementation Phases |
| 103 | + |
| 104 | +### Phase 1: Core Infrastructure ✅ |
| 105 | +1. Database migration for case_notes table |
| 106 | +2. Backend API endpoints |
| 107 | +3. Basic frontend page structure |
| 108 | + |
| 109 | +### Phase 2: Text Notes ✅ |
| 110 | +1. Note editor component |
| 111 | +2. Create/edit/delete text notes |
| 112 | +3. Notes list view |
| 113 | + |
| 114 | +### Phase 3: Audio Notes ✅ |
| 115 | +1. Audio recorder component |
| 116 | +2. Audio upload to GCS |
| 117 | +3. Audio playback |
| 118 | + |
| 119 | +### Phase 4: AI Metadata ✅ |
| 120 | +1. Gemini integration for title/subtitle |
| 121 | +2. Auto-generate on save |
| 122 | +3. Manual regenerate option |
| 123 | + |
| 124 | +### Phase 5: Export to Evidence ✅ |
| 125 | +1. Text to PDF conversion (via reportlab) |
| 126 | +2. Audio export |
| 127 | +3. Evidence library integration |
| 128 | + |
| 129 | +### Phase 6: Mobile Detection ✅ |
| 130 | +1. Middleware device detection |
| 131 | +2. Mobile routing |
| 132 | +3. Full/mobile view toggle |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +## Implementation Status |
| 137 | + |
| 138 | +### Backend Files Created/Modified: |
| 139 | +- `backend/alembic/versions/add_case_notes_table.py` - Database migration |
| 140 | +- `backend/app/models/note.py` - CaseNote SQLAlchemy model |
| 141 | +- `backend/app/models/__init__.py` - Added note model export |
| 142 | +- `backend/app/models/case.py` - Added notes relationship |
| 143 | +- `backend/app/schemas/notes.py` - Pydantic schemas for notes API |
| 144 | +- `backend/app/schemas/__init__.py` - Added notes schema exports |
| 145 | +- `backend/app/api/notes.py` - Full CRUD + export API endpoints |
| 146 | +- `backend/app/main.py` - Registered notes router |
| 147 | + |
| 148 | +### Frontend Files Created/Modified: |
| 149 | +- `frontend/src/lib/api/notes.ts` - Notes API client |
| 150 | +- `frontend/src/hooks/useNotes.ts` - React hook for notes management |
| 151 | +- `frontend/src/hooks/index.ts` - Added useNotes export |
| 152 | +- `frontend/src/components/notebook/AudioRecorder.tsx` - Audio recording component |
| 153 | +- `frontend/src/components/notebook/NoteCard.tsx` - Note display card |
| 154 | +- `frontend/src/components/notebook/Notebook.tsx` - Main notebook interface |
| 155 | +- `frontend/src/components/notebook/ViewToggle.tsx` - Mobile/desktop view toggle |
| 156 | +- `frontend/src/components/notebook/index.ts` - Barrel exports |
| 157 | +- `frontend/src/components/app/case-nav-section.tsx` - Added Sherlock's Diary tab |
| 158 | +- `frontend/src/middleware.ts` - Mobile detection and routing |
| 159 | +- `frontend/src/app/(app)/cases/[id]/notebook/page.tsx` - Notebook page route |
| 160 | + |
| 161 | +### Required Backend Dependencies: |
| 162 | +- `reportlab` - For PDF generation (text notes export) |
| 163 | + |
| 164 | +### To Complete Setup: |
| 165 | +1. Run database migrations: `make migrate` |
| 166 | +2. Install reportlab: `cd backend && uv add reportlab` |
| 167 | +3. Restart backend: `make dev-backend` |
| 168 | +4. Test the notebook at: `/cases/{caseId}/notebook` |
| 169 | + |
0 commit comments