feat: add favorites table, CRUD commands, and Pinia store
This commit is contained in:
@@ -677,3 +677,61 @@ pub fn get_project_budget_status(state: State<AppState>, project_id: i64) -> Res
|
|||||||
"percent_amount": project_row.1.map(|b| if b > 0.0 { (amount_used / b) * 100.0 } else { 0.0 })
|
"percent_amount": project_row.1.map(|b| if b > 0.0 { (amount_used / b) * 100.0 } else { 0.0 })
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Favorite structs and commands
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct Favorite {
|
||||||
|
pub id: Option<i64>,
|
||||||
|
pub project_id: i64,
|
||||||
|
pub task_id: Option<i64>,
|
||||||
|
pub description: Option<String>,
|
||||||
|
pub sort_order: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn get_favorites(state: State<AppState>) -> Result<Vec<Favorite>, String> {
|
||||||
|
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||||
|
let mut stmt = conn.prepare(
|
||||||
|
"SELECT id, project_id, task_id, description, sort_order FROM favorites ORDER BY sort_order"
|
||||||
|
).map_err(|e| e.to_string())?;
|
||||||
|
let favs = stmt.query_map([], |row| {
|
||||||
|
Ok(Favorite {
|
||||||
|
id: Some(row.get(0)?),
|
||||||
|
project_id: row.get(1)?,
|
||||||
|
task_id: row.get(2)?,
|
||||||
|
description: row.get(3)?,
|
||||||
|
sort_order: row.get(4)?,
|
||||||
|
})
|
||||||
|
}).map_err(|e| e.to_string())?;
|
||||||
|
favs.collect::<Result<Vec<_>, _>>().map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn create_favorite(state: State<AppState>, fav: Favorite) -> Result<i64, String> {
|
||||||
|
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||||
|
conn.execute(
|
||||||
|
"INSERT INTO favorites (project_id, task_id, description, sort_order) VALUES (?1, ?2, ?3, ?4)",
|
||||||
|
params![fav.project_id, fav.task_id, fav.description, fav.sort_order],
|
||||||
|
).map_err(|e| e.to_string())?;
|
||||||
|
Ok(conn.last_insert_rowid())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn delete_favorite(state: State<AppState>, id: i64) -> Result<(), String> {
|
||||||
|
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||||
|
conn.execute("DELETE FROM favorites WHERE id = ?1", params![id])
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn reorder_favorites(state: State<AppState>, ids: Vec<i64>) -> Result<(), String> {
|
||||||
|
let conn = state.db.lock().map_err(|e| e.to_string())?;
|
||||||
|
for (i, id) in ids.iter().enumerate() {
|
||||||
|
conn.execute(
|
||||||
|
"UPDATE favorites SET sort_order = ?1 WHERE id = ?2",
|
||||||
|
params![i as i32, id],
|
||||||
|
).map_err(|e| e.to_string())?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|||||||
@@ -158,6 +158,19 @@ pub fn init_db(conn: &Connection) -> Result<(), rusqlite::Error> {
|
|||||||
[],
|
[],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
conn.execute(
|
||||||
|
"CREATE TABLE IF NOT EXISTS favorites (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
project_id INTEGER NOT NULL,
|
||||||
|
task_id INTEGER,
|
||||||
|
description TEXT,
|
||||||
|
sort_order INTEGER DEFAULT 0,
|
||||||
|
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE SET NULL
|
||||||
|
)",
|
||||||
|
[],
|
||||||
|
)?;
|
||||||
|
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"CREATE TABLE IF NOT EXISTS settings (
|
"CREATE TABLE IF NOT EXISTS settings (
|
||||||
key TEXT PRIMARY KEY,
|
key TEXT PRIMARY KEY,
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ pub fn run() {
|
|||||||
commands::get_entry_tags,
|
commands::get_entry_tags,
|
||||||
commands::set_entry_tags,
|
commands::set_entry_tags,
|
||||||
commands::get_project_budget_status,
|
commands::get_project_budget_status,
|
||||||
|
commands::get_favorites,
|
||||||
|
commands::create_favorite,
|
||||||
|
commands::delete_favorite,
|
||||||
|
commands::reorder_favorites,
|
||||||
])
|
])
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
#[cfg(desktop)]
|
#[cfg(desktop)]
|
||||||
|
|||||||
57
src/stores/favorites.ts
Normal file
57
src/stores/favorites.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
|
export interface Favorite {
|
||||||
|
id?: number
|
||||||
|
project_id: number
|
||||||
|
task_id?: number | null
|
||||||
|
description?: string | null
|
||||||
|
sort_order: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useFavoritesStore = defineStore('favorites', () => {
|
||||||
|
const favorites = ref<Favorite[]>([])
|
||||||
|
|
||||||
|
async function fetchFavorites() {
|
||||||
|
try {
|
||||||
|
favorites.value = await invoke<Favorite[]>('get_favorites')
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch favorites:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createFavorite(fav: Favorite): Promise<number | null> {
|
||||||
|
try {
|
||||||
|
const id = await invoke<number>('create_favorite', { fav })
|
||||||
|
favorites.value.push({ ...fav, id: Number(id) })
|
||||||
|
return Number(id)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to create favorite:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteFavorite(id: number): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await invoke('delete_favorite', { id })
|
||||||
|
favorites.value = favorites.value.filter(f => f.id !== id)
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to delete favorite:', error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function reorderFavorites(ids: number[]): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await invoke('reorder_favorites', { ids })
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to reorder favorites:', error)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { favorites, fetchFavorites, createFavorite, deleteFavorite, reorderFavorites }
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user