mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-24 07:41:47 +00:00
0b36427c09
- New todo_items DB table with priority, due date, description, user assignment - Full CRUD API with WebSocket real-time sync - 3-column UI: sidebar filters (All, My Tasks, Overdue, Done, by Priority), task list with inline badges, and detail/create pane - Apple-inspired design with custom dropdowns, date picker, priority system (P1-P3) - Mobile responsive: icon-only sidebar, bottom-sheet modals for detail/create - Lists tab with sub-tabs (Packing List + To-Do), persisted selection - Addon renamed from "Packing List" to "Lists" - i18n keys for all 13 languages - UI polish: notification colors use system theme, mobile navbar cleanup, settings page responsive buttons
68 lines
2.2 KiB
TypeScript
68 lines
2.2 KiB
TypeScript
import { todoApi } from '../../api/client'
|
|
import type { StoreApi } from 'zustand'
|
|
import type { TripStoreState } from '../tripStore'
|
|
import type { TodoItem } from '../../types'
|
|
import { getApiErrorMessage } from '../../types'
|
|
|
|
type SetState = StoreApi<TripStoreState>['setState']
|
|
type GetState = StoreApi<TripStoreState>['getState']
|
|
|
|
export interface TodoSlice {
|
|
addTodoItem: (tripId: number | string, data: Partial<TodoItem>) => Promise<TodoItem>
|
|
updateTodoItem: (tripId: number | string, id: number, data: Partial<TodoItem>) => Promise<TodoItem>
|
|
deleteTodoItem: (tripId: number | string, id: number) => Promise<void>
|
|
toggleTodoItem: (tripId: number | string, id: number, checked: boolean) => Promise<void>
|
|
}
|
|
|
|
export const createTodoSlice = (set: SetState, get: GetState): TodoSlice => ({
|
|
addTodoItem: async (tripId, data) => {
|
|
try {
|
|
const result = await todoApi.create(tripId, data)
|
|
set(state => ({ todoItems: [...state.todoItems, result.item] }))
|
|
return result.item
|
|
} catch (err: unknown) {
|
|
throw new Error(getApiErrorMessage(err, 'Error adding todo'))
|
|
}
|
|
},
|
|
|
|
updateTodoItem: async (tripId, id, data) => {
|
|
try {
|
|
const result = await todoApi.update(tripId, id, data)
|
|
set(state => ({
|
|
todoItems: state.todoItems.map(item => item.id === id ? result.item : item)
|
|
}))
|
|
return result.item
|
|
} catch (err: unknown) {
|
|
throw new Error(getApiErrorMessage(err, 'Error updating todo'))
|
|
}
|
|
},
|
|
|
|
deleteTodoItem: async (tripId, id) => {
|
|
const prev = get().todoItems
|
|
set(state => ({ todoItems: state.todoItems.filter(item => item.id !== id) }))
|
|
try {
|
|
await todoApi.delete(tripId, id)
|
|
} catch (err: unknown) {
|
|
set({ todoItems: prev })
|
|
throw new Error(getApiErrorMessage(err, 'Error deleting todo'))
|
|
}
|
|
},
|
|
|
|
toggleTodoItem: async (tripId, id, checked) => {
|
|
set(state => ({
|
|
todoItems: state.todoItems.map(item =>
|
|
item.id === id ? { ...item, checked: checked ? 1 : 0 } : item
|
|
)
|
|
}))
|
|
try {
|
|
await todoApi.update(tripId, id, { checked })
|
|
} catch {
|
|
set(state => ({
|
|
todoItems: state.todoItems.map(item =>
|
|
item.id === id ? { ...item, checked: checked ? 0 : 1 } : item
|
|
)
|
|
}))
|
|
}
|
|
},
|
|
})
|