Files
el-inv/src/routes/folders/[...path]/+page.server.ts

219 lines
7.5 KiB
TypeScript

import { db } from '$lib/server/db';
import { items, folders, categories, reservations } from '$lib/server/db/schema';
import { eq, and, isNull, inArray, sql } from 'drizzle-orm';
import { error } from '@sveltejs/kit';
import { processProperties } from '$lib/utils/propertyUtils';
import { getOrSeedHomeFolder } from '$lib/server/db/utils';
export const load = async ({ params, url }: { params: { path: string }, url: URL }) => {
const pathSegments = params.path.split('/').filter(Boolean);
let currentFolder = null;
const breadcrumbs: any[] = [];
// Start with Home folder as the root parent
const homeFolder = await getOrSeedHomeFolder();
let parentId: string | null = homeFolder.id;
for (const segment of pathSegments) {
const folder = await db.select().from(folders)
.where(and(
eq(folders.name, decodeURIComponent(segment)),
eq(folders.parentId, parentId)
))
.limit(1);
if (folder.length === 0) {
throw error(404, 'Folder not found');
}
currentFolder = folder[0];
parentId = currentFolder.id;
const parentPath = breadcrumbs.map(b => b.name).join('/');
breadcrumbs.push({
name: currentFolder.name,
url: `/folders${parentPath ? '/' + parentPath : ''}/${currentFolder.name}`
});
}
if (!currentFolder) {
throw error(404, 'Folder not found');
}
// Fetch subfolders
const subfolders = await db.select().from(folders)
.where(eq(folders.parentId, currentFolder.id));
// Fetch items
const folderItems = await db.select({
id: items.id,
name: items.name,
count: items.count,
categoryName: categories.name,
categoryId: items.categoryId,
folderId: items.folderId,
tags: items.tags,
properties: items.properties,
reservedCount: sql<number>`(SELECT COALESCE(SUM(count), 0) FROM reservations WHERE item_id = ${items.id})`.mapWith(Number)
})
.from(items)
.leftJoin(categories, eq(items.categoryId, categories.id))
.where(eq(items.folderId, currentFolder.id));
const allCategories = await db.select().from(categories);
const allFolders = await db.select().from(folders);
return {
currentFolder,
breadcrumbs,
items: folderItems,
subfolders,
categories: allCategories,
allFolders
};
};
export const actions = {
createFolder: async ({ request }: { request: Request }) => {
const data = await request.formData();
const name = data.get('name') as string;
const parentId = data.get('parentId') as string || null;
await db.insert(folders).values({
name,
parentId
});
return { success: true };
},
createItem: async ({ request }: { request: Request }) => {
const data = await request.formData();
const name = (data.get('name') as string) || null;
const folderId = data.get('folderId') as string;
const categoryId = data.get('categoryId') as string;
const count = parseInt(data.get('count') as string) || 0;
const properties = processProperties(data);
await db.insert(items).values({
name,
folderId: folderId,
categoryId,
count,
properties
});
return { success: true };
},
updateItem: async ({ request }: { request: Request }) => {
const data = await request.formData();
const id = data.get('id') as string;
const name = (data.get('name') as string) || null;
const categoryId = data.get('categoryId') as string;
const count = parseInt(data.get('count') as string) || 0;
const folderId = data.get('folderId') as string;
const properties = processProperties(data);
const updateData: any = {
name,
categoryId,
count,
properties,
updatedAt: new Date()
};
if (folderId !== undefined) {
updateData.folderId = folderId;
}
await db.update(items)
.set(updateData)
.where(eq(items.id, id));
return { success: true };
},
deleteItem: async ({ request }: { request: Request }) => {
const data = await request.formData();
const id = data.get('id') as string;
await db.delete(items).where(eq(items.id, id));
return { success: true };
},
moveItem: async ({ request }: { request: Request }) => {
const data = await request.formData();
const id = data.get('id') as string;
const folderId = data.get('folderId') as string;
await db.update(items).set({ folderId: folderId }).where(eq(items.id, id));
return { success: true };
},
bulkDelete: async ({ request }: { request: Request }) => {
const data = await request.formData();
const ids = JSON.parse(data.get('ids') as string);
if (ids.length > 0) {
await db.delete(items).where(inArray(items.id, ids));
}
return { success: true };
},
bulkMove: async ({ request }: { request: Request }) => {
const data = await request.formData();
const ids = JSON.parse(data.get('ids') as string);
const folderId = data.get('folderId') as string;
if (ids.length > 0) {
await db.update(items).set({ folderId: folderId }).where(inArray(items.id, ids));
}
return { success: true };
},
updateCount: async ({ request }: { request: Request }) => {
const data = await request.formData();
const id = data.get('id') as string;
const delta = parseInt(data.get('delta') as string) || 0;
const item = await db.select({ count: items.count }).from(items).where(eq(items.id, id)).limit(1);
if (item.length > 0) {
const newCount = Math.max(0, (item[0].count || 0) + delta);
await db.update(items).set({ count: newCount }).where(eq(items.id, id));
}
return { success: true };
},
renameFolder: async ({ request }: { request: Request }) => {
const data = await request.formData();
const id = data.get('id') as string;
const name = data.get('name') as string;
await db.update(folders)
.set({ name })
.where(eq(folders.id, id));
return { success: true };
},
moveFolder: async ({ request }: { request: Request }) => {
const data = await request.formData();
const id = data.get('id') as string;
const parentId = data.get('folderId') as string; // Reusing folderId param name from item move
// Prevent moving folder into itself or its children (basic check: not into itself)
if (id === parentId) {
// In a real app we'd check for cycles, but for now just prevent direct self-parenting
return { success: false, error: "Cannot move folder into itself" };
}
await db.update(folders)
.set({ parentId: parentId || null })
.where(eq(folders.id, id));
return { success: true };
},
deleteFolder: async ({ request }: { request: Request }) => {
const data = await request.formData();
const id = data.get('id') as string;
// Note: This assumes cascading delete or that the user has emptied the folder.
// If not cascading, this might fail. For now, we assume simple delete.
await db.delete(folders).where(eq(folders.id, id));
return { success: true };
}
};