chore: mark completion of sessions and SWOT components in devbook.md; add @hello-pangea/dnd dependency for drag & drop functionality
This commit is contained in:
215
src/services/sessions.ts
Normal file
215
src/services/sessions.ts
Normal file
@@ -0,0 +1,215 @@
|
||||
import { prisma } from '@/services/database';
|
||||
import type { SwotCategory } from '@prisma/client';
|
||||
|
||||
// ============================================
|
||||
// Session CRUD
|
||||
// ============================================
|
||||
|
||||
export async function getSessionsByUserId(userId: string) {
|
||||
return prisma.session.findMany({
|
||||
where: { userId },
|
||||
include: {
|
||||
_count: {
|
||||
select: {
|
||||
items: true,
|
||||
actions: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { updatedAt: 'desc' },
|
||||
});
|
||||
}
|
||||
|
||||
export async function getSessionById(sessionId: string, userId: string) {
|
||||
return prisma.session.findFirst({
|
||||
where: {
|
||||
id: sessionId,
|
||||
userId,
|
||||
},
|
||||
include: {
|
||||
items: {
|
||||
orderBy: { order: 'asc' },
|
||||
},
|
||||
actions: {
|
||||
include: {
|
||||
links: {
|
||||
include: {
|
||||
swotItem: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { createdAt: 'asc' },
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function createSession(userId: string, data: { title: string; collaborator: string }) {
|
||||
return prisma.session.create({
|
||||
data: {
|
||||
...data,
|
||||
userId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateSession(
|
||||
sessionId: string,
|
||||
userId: string,
|
||||
data: { title?: string; collaborator?: string }
|
||||
) {
|
||||
return prisma.session.updateMany({
|
||||
where: { id: sessionId, userId },
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteSession(sessionId: string, userId: string) {
|
||||
return prisma.session.deleteMany({
|
||||
where: { id: sessionId, userId },
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// SWOT Items CRUD
|
||||
// ============================================
|
||||
|
||||
export async function createSwotItem(
|
||||
sessionId: string,
|
||||
data: { content: string; category: SwotCategory }
|
||||
) {
|
||||
// Get max order for this category
|
||||
const maxOrder = await prisma.swotItem.aggregate({
|
||||
where: { sessionId, category: data.category },
|
||||
_max: { order: true },
|
||||
});
|
||||
|
||||
return prisma.swotItem.create({
|
||||
data: {
|
||||
...data,
|
||||
sessionId,
|
||||
order: (maxOrder._max.order ?? -1) + 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateSwotItem(
|
||||
itemId: string,
|
||||
data: { content?: string; category?: SwotCategory; order?: number }
|
||||
) {
|
||||
return prisma.swotItem.update({
|
||||
where: { id: itemId },
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteSwotItem(itemId: string) {
|
||||
return prisma.swotItem.delete({
|
||||
where: { id: itemId },
|
||||
});
|
||||
}
|
||||
|
||||
export async function reorderSwotItems(
|
||||
sessionId: string,
|
||||
category: SwotCategory,
|
||||
itemIds: string[]
|
||||
) {
|
||||
const updates = itemIds.map((id, index) =>
|
||||
prisma.swotItem.update({
|
||||
where: { id },
|
||||
data: { order: index },
|
||||
})
|
||||
);
|
||||
|
||||
return prisma.$transaction(updates);
|
||||
}
|
||||
|
||||
export async function moveSwotItem(
|
||||
itemId: string,
|
||||
newCategory: SwotCategory,
|
||||
newOrder: number
|
||||
) {
|
||||
return prisma.swotItem.update({
|
||||
where: { id: itemId },
|
||||
data: {
|
||||
category: newCategory,
|
||||
order: newOrder,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Actions CRUD
|
||||
// ============================================
|
||||
|
||||
export async function createAction(
|
||||
sessionId: string,
|
||||
data: {
|
||||
title: string;
|
||||
description?: string;
|
||||
priority?: number;
|
||||
linkedItemIds: string[];
|
||||
}
|
||||
) {
|
||||
return prisma.action.create({
|
||||
data: {
|
||||
title: data.title,
|
||||
description: data.description,
|
||||
priority: data.priority ?? 0,
|
||||
sessionId,
|
||||
links: {
|
||||
create: data.linkedItemIds.map((swotItemId) => ({
|
||||
swotItemId,
|
||||
})),
|
||||
},
|
||||
},
|
||||
include: {
|
||||
links: {
|
||||
include: {
|
||||
swotItem: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateAction(
|
||||
actionId: string,
|
||||
data: {
|
||||
title?: string;
|
||||
description?: string;
|
||||
priority?: number;
|
||||
status?: string;
|
||||
dueDate?: Date | null;
|
||||
}
|
||||
) {
|
||||
return prisma.action.update({
|
||||
where: { id: actionId },
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteAction(actionId: string) {
|
||||
return prisma.action.delete({
|
||||
where: { id: actionId },
|
||||
});
|
||||
}
|
||||
|
||||
export async function linkItemToAction(actionId: string, swotItemId: string) {
|
||||
return prisma.actionLink.create({
|
||||
data: {
|
||||
actionId,
|
||||
swotItemId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function unlinkItemFromAction(actionId: string, swotItemId: string) {
|
||||
return prisma.actionLink.deleteMany({
|
||||
where: {
|
||||
actionId,
|
||||
swotItemId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user