Persistent notifications
Disable auto-dismiss for toast messages
No project was selected. Choose a project to save your tracked time. The timer has been running for a long time. Would you like to stop and save?
{{ formattedDuration }}
{{ tpl.name }}
{{ getProjectName(tpl.project_id) }} - {{ formatDuration(tpl.duration) }}
No saved templates
``` Add script setup code for fetching and deleting templates via `useEntryTemplatesStore`. **Step 3:** Verify: `npx vue-tsc --noEmit` **Step 4:** Commit: `git add src/views/Settings.vue && git commit -m "feat: entry template management in settings"` --- ### Task 19: Timesheet smart row persistence - backend **Files:** - Modify: `src-tauri/src/database.rs` (add `timesheet_rows` table) - Modify: `src-tauri/src/commands.rs` (add 3 commands) - Modify: `src-tauri/src/lib.rs` (register) **Step 1:** Add table: ```rust conn.execute( "CREATE TABLE IF NOT EXISTS timesheet_rows ( id INTEGER PRIMARY KEY AUTOINCREMENT, week_start TEXT NOT NULL, project_id INTEGER NOT NULL REFERENCES projects(id), task_id INTEGER REFERENCES tasks(id), sort_order INTEGER NOT NULL DEFAULT 0 )", [], )?; ``` **Step 2:** Add commands: ```rust #[tauri::command] pub fn get_timesheet_rows(state: State| ` and ` | ` - Summary stats: "Most productive: Monday 9-10 AM", "Quietest: Sunday" Data computation: ```ts function computePatterns() { const grid: number[][] = Array.from({ length: 7 }, () => Array(24).fill(0)) for (const entry of entriesStore.entries) { const d = new Date(entry.start_time) const day = d.getDay() === 0 ? 6 : d.getDay() - 1 // Mon=0, Sun=6 const hour = d.getHours() grid[day][hour] += entry.duration / 3600 } heatmapData.value = grid patternsLoaded = true } ``` **Step 4:** Verify: `npx vue-tsc --noEmit && npx vite build` **Step 5:** Commit: `git add src/views/Reports.vue && git commit -m "feat: time-of-day heatmap in reports patterns tab"` --- ### Task 29: Rounding visibility - Entries.vue **Files:** - Modify: `src/views/Entries.vue` **Step 1:** Read the duration column in the entries table (around line 161-169). **Step 2:** Import `roundDuration` from `../utils/rounding` and settings store. For each entry, compute if rounding changes the value: ```ts import { roundDuration } from '../utils/rounding' function getRoundedDuration(seconds: number): number | null { if (settingsStore.settings.rounding_enabled !== 'true') return null const increment = parseInt(settingsStore.settings.rounding_increment) || 0 const method = (settingsStore.settings.rounding_method || 'nearest') as 'nearest' | 'up' | 'down' if (increment <= 0) return null const rounded = roundDuration(seconds, increment, method) return rounded !== seconds ? rounded : null } ``` In the duration ` | `, after the duration display, add:
```html
Rounded
```
Add a tooltip mechanism using `title` attribute or a custom tooltip with `role="tooltip"` and `aria-describedby` for the actual vs rounded values.
**Step 3:** Verify: `npx vue-tsc --noEmit`
**Step 4:** Commit: `git add src/views/Entries.vue && git commit -m "feat: rounding visibility indicators on entry rows"`
---
### Task 30: Rounding visibility - Invoices and Reports
**Files:**
- Modify: `src/views/Invoices.vue` (show actual vs rounded on line items)
- Modify: `src/views/Reports.vue` (add rounding impact summary in Hours tab)
**Step 1:** In Invoices.vue, where invoice line items are displayed, show both actual and rounded hours when rounding is active. Add a small "+Xm" or "-Xm" text label.
**Step 2:** In Reports.vue Hours tab, after the billable split line (around line 124), add a rounding impact summary:
```html
Rounding {{ roundingImpact > 0 ? 'added' : 'subtracted' }}:
{{ formatHours(Math.abs(roundingImpact)) }}
across {{ roundedEntryCount }} entries
```
**Step 3:** Verify: `npx vue-tsc --noEmit && npx vite build`
**Step 4:** Commit: `git add src/views/Invoices.vue src/views/Reports.vue && git commit -m "feat: rounding visibility in invoices and reports"`
---
### Task 31: Export completeness - backend
**Files:**
- Modify: `src-tauri/src/commands.rs` (expand `export_data`, update `import_json_data`, add `auto_backup`)
- Modify: `src-tauri/src/lib.rs` (register)
**Step 1:** Read `export_data` (lines 586-669) and `import_json_data` (lines 1501-1609).
**Step 2:** Expand `export_data` to include ALL tables:
- Add: tasks, tags, entry_tags, tracked_apps, favorites, recurring_entries, expenses, timeline_events, calendar_sources, calendar_events, timesheet_locks, invoice_items, settings, entry_templates, timesheet_rows
**Step 3:** Update `import_json_data` to handle expanded format. Import new tables if present in the JSON, skip if not (backward compatible).
**Step 4:** Add `auto_backup` command:
```rust
#[tauri::command]
pub fn auto_backup(state: StateLast exported {{ lastExportedFormatted }} Auto-backup on close Save a backup when the app closes Backup directory {{ backupPath || 'Not set' }} |
|---|