219 lines
7.5 KiB
TypeScript
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 };
|
|
}
|
|
};
|