refactor(ux): consolidate BMAD skills, update design system, and clean up Prisma generated client

This commit is contained in:
Sepehr Ramezani
2026-04-19 19:21:27 +02:00
parent 5296c4da2c
commit 25529a24b8
2476 changed files with 127934 additions and 101962 deletions

View File

@@ -30,10 +30,20 @@ export async function GET(
}
if (note.userId !== session.user.id) {
return NextResponse.json(
{ success: false, error: 'Forbidden' },
{ status: 403 }
)
const share = await prisma.noteShare.findUnique({
where: {
noteId_userId: {
noteId: note.id,
userId: session.user.id
}
}
})
if (!share || share.status !== 'accepted') {
return NextResponse.json(
{ success: false, error: 'Forbidden' },
{ status: 403 }
)
}
}
return NextResponse.json({
@@ -92,11 +102,29 @@ export async function PUT(
if ('labels' in body) {
updateData.labels = body.labels ?? null
}
updateData.updatedAt = new Date()
// Only update if data actually changed
const hasChanges = Object.keys(updateData).some((key) => {
const newValue = updateData[key]
const oldValue = (existingNote as any)[key]
// Handle arrays/objects by comparing JSON
if (typeof newValue === 'object' && newValue !== null) {
return JSON.stringify(newValue) !== JSON.stringify(oldValue)
}
return newValue !== oldValue
})
// If no changes, return existing note without updating timestamp
if (!hasChanges) {
return NextResponse.json({
success: true,
data: parseNote(existingNote),
})
}
const note = await prisma.note.update({
where: { id },
data: updateData
data: updateData,
})
return NextResponse.json({
@@ -146,13 +174,14 @@ export async function DELETE(
)
}
await prisma.note.delete({
where: { id }
await prisma.note.update({
where: { id },
data: { trashedAt: new Date() }
})
return NextResponse.json({
success: true,
message: 'Note deleted successfully'
message: 'Note moved to trash'
})
} catch (error) {
console.error('Error deleting note:', error)

View File

@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
import { revalidatePath } from 'next/cache'
import { deleteImageFileSafely, parseImageUrls } from '@/lib/image-cleanup'
export async function POST(req: NextRequest) {
try {
@@ -14,6 +15,12 @@ export async function POST(req: NextRequest) {
)
}
// Fetch notes with images before deleting for cleanup
const notesWithImages = await prisma.note.findMany({
where: { userId: session.user.id },
select: { id: true, images: true },
})
// Delete all notes for the user (cascade will handle labels-note relationships)
const result = await prisma.note.deleteMany({
where: {
@@ -21,6 +28,13 @@ export async function POST(req: NextRequest) {
}
})
// Clean up image files from disk (best-effort, don't block response)
const imageCleanup = Promise.allSettled(
notesWithImages.flatMap(note =>
parseImageUrls(note.images).map(url => deleteImageFileSafely(url, note.id))
)
)
// Delete all labels for the user
await prisma.label.deleteMany({
where: {
@@ -39,6 +53,9 @@ export async function POST(req: NextRequest) {
revalidatePath('/')
revalidatePath('/settings/data')
// Await cleanup in background (don't block response)
imageCleanup.catch(() => {})
return NextResponse.json({
success: true,
deletedNotes: result.count

View File

@@ -16,7 +16,8 @@ export async function GET(req: NextRequest) {
// Fetch all notes with related data
const notes = await prisma.note.findMany({
where: {
userId: session.user.id
userId: session.user.id,
trashedAt: null
},
include: {
labelRelations: {
@@ -107,7 +108,7 @@ export async function GET(req: NextRequest) {
return new NextResponse(jsonString, {
headers: {
'Content-Type': 'application/json',
'Content-Disposition': `attachment; filename="keep-notes-export-${new Date().toISOString().split('T')[0]}.json"`
'Content-Disposition': `attachment; filename="memento-export-${new Date().toISOString().split('T')[0]}.json"`
}
})
} catch (error) {

View File

@@ -19,7 +19,8 @@ export async function GET(request: NextRequest) {
const search = searchParams.get('search')
let where: any = {
userId: session.user.id
userId: session.user.id,
trashedAt: null
}
if (!includeArchived) {
@@ -210,13 +211,14 @@ export async function DELETE(request: NextRequest) {
)
}
await prisma.note.delete({
where: { id }
await prisma.note.update({
where: { id },
data: { trashedAt: new Date() }
})
return NextResponse.json({
success: true,
message: 'Note deleted successfully'
message: 'Note moved to trash'
})
} catch (error) {
console.error('Error deleting note:', error)