Add TodoItem component, enhance task list, and improve API data handling

- Introduced `TodoItem.vue`, a reusable component for task items.
- Refactored `ListScreen` to use `TodoItem` for better modularity.
- Added new animations and styles for smooth transitions.
- Updated `useTasks` with `updateTask` method to sync task updates via API.
- Improved type definitions for `Task` and added nullable fields for flexibility.
- Added dependencies: `luxon`, `@types/luxon`, `uuid`, and `@vueuse/core`.
This commit is contained in:
2026-02-21 21:23:28 +01:00
parent e44e88adfd
commit f1e098d3c7
10 changed files with 192 additions and 39 deletions

View File

@@ -51,10 +51,10 @@ export function useApi() {
const get = (endpoint: string, options: RequestInit = {}) =>
apiFetch(endpoint, { ...options, method: 'GET' });
const post = (endpoint: string, body: BodyInit | null, options: RequestInit = {}) =>
const post = (endpoint: string, body: unknown, options: RequestInit = {}) =>
apiFetch(endpoint, { ...options, method: 'POST', body: JSON.stringify(body) });
const put = (endpoint: string, body: BodyInit | null, options: RequestInit = {}) =>
const put = (endpoint: string, body: unknown, options: RequestInit = {}) =>
apiFetch(endpoint, { ...options, method: 'PUT', body: JSON.stringify(body) });
return {

View File

@@ -27,7 +27,7 @@ export function useSettings() {
let password = readSettings.password ?? '';
if (password) {
try {
password = decrypt(password);
password = decrypt(password) as string;
} catch (error) {
console.warn('Failed to decrypt stored password:', error);
}
@@ -41,7 +41,7 @@ export function useSettings() {
const saveSettings = async () => {
const encryptedPassword = settings.value.password
? encrypt(settings.value.password)
? encrypt(settings.value.password) as string
: '';
await setValue<Settings>('settings', {

View File

@@ -15,8 +15,7 @@ export function useTasks() {
isLoading.value = true;
error.value = null;
try {
const response = await api.get('e5880167-9322-4d7b-8a38-e06bae8a7734/list');
const data = await response.json();
const data = await api.get('e5880167-9322-4d7b-8a38-e06bae8a7734/list').then((res) => res.json());
tasks.value = data.tasks ?? [];
} catch (e: any) {
error.value = e.message || 'Failed to fetch tasks';
@@ -45,15 +44,10 @@ export function useTasks() {
archived: false,
};
await api.put('e5880167-9322-4d7b-8a38-e06bae8a7734/list', { tasks: [newTask] });
// Update local store (optimistic update or refetch)
// Since it's a PUT to '.../list' with {tasks: [task]}, it seems to add/update?
// Based on CreateScreen.vue, it just navigates back.
// To keep store in sync without full refetch, we could add it locally if we knew the full structure
// But maybe it's safer to refetch or at least push to local state if we have the full object.
// Let's refetch to be sure it's in sync with server.
await fetchTasks(true);
const data = await api.put('e5880167-9322-4d7b-8a38-e06bae8a7734/list', { tasks: [newTask] }).then((res) => res.json());
if (data.tasks) {
tasks.value = data.tasks;
}
} catch (e: any) {
error.value = e.message || 'Failed to create task';
console.error('Error creating task:', e);
@@ -63,11 +57,30 @@ export function useTasks() {
}
};
const updateTask = async (task: Task) => {
console.log('updateTask',task);
isLoading.value = true;
error.value = null;
try {
const data = await api.put('e5880167-9322-4d7b-8a38-e06bae8a7734/list', { tasks: [task] }).then((res) => res.json());
if (data.tasks) {
tasks.value = data.tasks;
}
} catch (e: any) {
error.value = e.message || 'Failed to update task';
console.error('Error updating task:', e);
throw e;
} finally {
isLoading.value = false;
}
}
return {
tasks,
isLoading,
error,
fetchTasks,
createTask,
updateTask,
};
}