feat(04-03): install Svelecte and add tag support to load/actions
- Install svelecte package for tag input with autocomplete - Import tagRepository in +page.server.ts - Attach tags to entries in load function alongside images - Return allTags for autocomplete suggestions - Add updateTags action to update entry tags via JSON payload
This commit is contained in:
10
package-lock.json
generated
10
package-lock.json
generated
@@ -13,6 +13,7 @@
|
|||||||
"drizzle-orm": "^0.45.1",
|
"drizzle-orm": "^0.45.1",
|
||||||
"nanoid": "^5.1.6",
|
"nanoid": "^5.1.6",
|
||||||
"sharp": "^0.34.5",
|
"sharp": "^0.34.5",
|
||||||
|
"svelecte": "^5.3.0",
|
||||||
"svelte-gestures": "^5.2.2",
|
"svelte-gestures": "^5.2.2",
|
||||||
"svelte-lightbox": "^1.1.7",
|
"svelte-lightbox": "^1.1.7",
|
||||||
"svelte-persisted-store": "^0.12.0",
|
"svelte-persisted-store": "^0.12.0",
|
||||||
@@ -5164,6 +5165,15 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svelecte": {
|
||||||
|
"version": "5.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelecte/-/svelecte-5.3.0.tgz",
|
||||||
|
"integrity": "sha512-9WKD6KxPf31CweyZtObTetGtkq1TncBA2E+aSHcT+bfjALgP+LUGMMQUU+2qhlfSoGpw9JYmLfxphGjb0q350g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"svelte": "^5.2.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/svelte": {
|
"node_modules/svelte": {
|
||||||
"version": "5.49.0",
|
"version": "5.49.0",
|
||||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.49.0.tgz",
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.49.0.tgz",
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
"drizzle-orm": "^0.45.1",
|
"drizzle-orm": "^0.45.1",
|
||||||
"nanoid": "^5.1.6",
|
"nanoid": "^5.1.6",
|
||||||
"sharp": "^0.34.5",
|
"sharp": "^0.34.5",
|
||||||
|
"svelecte": "^5.3.0",
|
||||||
"svelte-gestures": "^5.2.2",
|
"svelte-gestures": "^5.2.2",
|
||||||
"svelte-lightbox": "^1.1.7",
|
"svelte-lightbox": "^1.1.7",
|
||||||
"svelte-persisted-store": "^0.12.0",
|
"svelte-persisted-store": "^0.12.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { PageServerLoad, Actions } from './$types';
|
import type { PageServerLoad, Actions } from './$types';
|
||||||
import { fail } from '@sveltejs/kit';
|
import { fail } from '@sveltejs/kit';
|
||||||
import { entryRepository, imageRepository } from '$lib/server/db/repository';
|
import { entryRepository, imageRepository, tagRepository } from '$lib/server/db/repository';
|
||||||
import {
|
import {
|
||||||
saveOriginal,
|
saveOriginal,
|
||||||
saveThumbnail,
|
saveThumbnail,
|
||||||
@@ -13,14 +13,19 @@ export const load: PageServerLoad = async ({ url }) => {
|
|||||||
const showCompleted = url.searchParams.get('showCompleted') === 'true';
|
const showCompleted = url.searchParams.get('showCompleted') === 'true';
|
||||||
const entries = entryRepository.getOrdered({ showCompleted });
|
const entries = entryRepository.getOrdered({ showCompleted });
|
||||||
|
|
||||||
// Attach images to each entry
|
// Attach images AND tags to each entry
|
||||||
const entriesWithImages = entries.map((entry) => ({
|
const entriesWithData = entries.map((entry) => ({
|
||||||
...entry,
|
...entry,
|
||||||
images: imageRepository.getByEntryId(entry.id)
|
images: imageRepository.getByEntryId(entry.id),
|
||||||
|
tags: tagRepository.getByEntryId(entry.id)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Get all tags for autocomplete
|
||||||
|
const allTags = tagRepository.getAll();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entries: entriesWithImages,
|
entries: entriesWithData,
|
||||||
|
allTags,
|
||||||
showCompleted
|
showCompleted
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -260,5 +265,28 @@ export const actions: Actions = {
|
|||||||
entryRepository.update(id, { dueDate: dueDate || null });
|
entryRepository.update(id, { dueDate: dueDate || null });
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
|
},
|
||||||
|
|
||||||
|
updateTags: async ({ request }) => {
|
||||||
|
const formData = await request.formData();
|
||||||
|
const id = formData.get('id')?.toString();
|
||||||
|
const tagsJson = formData.get('tags')?.toString() || '[]';
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return fail(400, { error: 'Entry ID is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = entryRepository.getById(id);
|
||||||
|
if (!existing) {
|
||||||
|
return fail(404, { error: 'Entry not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tagNames = JSON.parse(tagsJson) as string[];
|
||||||
|
tagRepository.updateEntryTags(id, tagNames);
|
||||||
|
return { success: true };
|
||||||
|
} catch {
|
||||||
|
return fail(400, { error: 'Invalid tags format' });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user