diff --git a/prisma/schema.prisma b/prisma/schema.prisma index cf2308c..0415d23 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -45,12 +45,10 @@ model Item { urlId Int @map("url_id") wikidataId String? @map("wikidata_id") itemOrder Int @default(0) @map("item_order") - globalItemId String @unique @map("global_item_id") + globalItemId String @map("global_item_id") // Relations url Url @relation(fields: [urlId], references: [id], onDelete: Cascade) - itemProperties ItemProperty[] @relation("ItemToItemProperty") - deletedProperties DeletedProperty[] @@map("items") } @@ -62,7 +60,6 @@ model ItemProperty { value String // Relations - item Item @relation("ItemToItemProperty", fields: [globalItemId], references: [globalItemId], onDelete: Cascade) property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade) @@id([globalItemId, propertyId]) @@ -90,7 +87,6 @@ model DeletedProperty { // Relations url Url @relation(fields: [urlId], references: [id], onDelete: Cascade) - item Item @relation(fields: [globalItemId], references: [globalItemId], onDelete: Cascade) property Property @relation(fields: [propertyId], references: [id], onDelete: Cascade) @@id([urlId, globalItemId, propertyId]) diff --git a/src/app/api/urls/[encodedUrl]/items/[itemId]/route.ts b/src/app/api/urls/[encodedUrl]/items/[itemId]/route.ts index 2e6d46a..63d281c 100644 --- a/src/app/api/urls/[encodedUrl]/items/[itemId]/route.ts +++ b/src/app/api/urls/[encodedUrl]/items/[itemId]/route.ts @@ -6,10 +6,12 @@ import { Item } from '@/types/database'; // PUT /api/urls/[encodedUrl]/items/[itemId] - Update a specific item export async function PUT( request: NextRequest, - { params }: { params: { encodedUrl: string; itemId: string } } + { params }: { params: Promise<{ encodedUrl: string; itemId: string }> } ) { try { - const { encodedUrl, itemId } = params; + // Await params before accessing properties + const resolvedParams = await params; + const { encodedUrl, itemId } = resolvedParams; const url = decodeURIComponent(encodedUrl); const item: Item = await request.json(); @@ -46,12 +48,16 @@ export async function PUT( return NextResponse.json({ success: true, itemId }); } catch (error) { console.error('[API] Update error:', error); + + // Await params for error handling too + const resolvedParams = await params; + return NextResponse.json( { error: 'Database error', details: error instanceof Error ? error.message : 'Unknown error', - itemId: params.itemId, - url: decodeURIComponent(params.encodedUrl) + itemId: resolvedParams.itemId, + url: decodeURIComponent(resolvedParams.encodedUrl) }, { status: 500 } ); @@ -61,10 +67,12 @@ export async function PUT( // DELETE /api/urls/[encodedUrl]/items/[itemId] - Delete a specific item export async function DELETE( request: NextRequest, - { params }: { params: { encodedUrl: string; itemId: string } } + { params }: { params: Promise<{ encodedUrl: string; itemId: string }> } ) { - const url = decodeURIComponent(params.encodedUrl); - const itemId = params.itemId; + // Await params before accessing properties + const resolvedParams = await params; + const url = decodeURIComponent(resolvedParams.encodedUrl); + const itemId = resolvedParams.itemId; console.log('[API] Deleting item', itemId, 'from URL', url); diff --git a/src/lib/database.ts b/src/lib/database.ts index 87fbad8..f682909 100644 --- a/src/lib/database.ts +++ b/src/lib/database.ts @@ -120,23 +120,13 @@ export async function insertItemByUrl(url: string, item: Item): Promise { console.log(`[DB] URL ID: ${urlRecord.id}`); - // 2. Check if this specific item already exists for this URL - const existingItem = await tx.item.findUnique({ - where: { id: item.id } - }); - - // 3. Find or create globalItemId based on item name + // 2. ALWAYS find existing globalItemId by name first (this is the key fix) let globalItemId: string; - if (existingItem) { - // Use existing globalItemId if item already exists - globalItemId = existingItem.globalItemId; - console.log(`[DB] Using existing global item ID: ${globalItemId}`); - } else { - // For new items, find existing globalItemId by name or create new one + if (item.name.trim()) { + // Look for existing global item with the same name const namePropertyId = await getOrCreateProperty(tx, 'name'); - // Look for existing global item with the same name const existingGlobalItem = await tx.itemProperty.findFirst({ where: { propertyId: namePropertyId, @@ -145,25 +135,29 @@ export async function insertItemByUrl(url: string, item: Item): Promise { select: { globalItemId: true } }); - if (existingGlobalItem && item.name.trim()) { + if (existingGlobalItem) { // Use existing globalItemId for items with the same name globalItemId = existingGlobalItem.globalItemId; console.log(`[DB] Found existing global item ID for name "${item.name}": ${globalItemId}`); } else { - // Create new globalItemId for new names or empty names + // Create new globalItemId for new names globalItemId = uuidv4(); - console.log(`[DB] Created new global item ID: ${globalItemId}`); + console.log(`[DB] Created new global item ID for new name "${item.name}": ${globalItemId}`); } + } else { + // For empty names, always create new globalItemId + globalItemId = uuidv4(); + console.log(`[DB] Created new global item ID for empty name: ${globalItemId}`); } - // 4. Get max order for new items + // 3. Get max order for new items const maxOrder = await tx.item.findFirst({ where: { urlId: urlRecord.id }, orderBy: { itemOrder: 'desc' }, select: { itemOrder: true } }); - // 5. Upsert the item record (unique by item.id) + // 4. Upsert the item record (unique by item.id) await tx.item.upsert({ where: { id: item.id }, update: { @@ -180,7 +174,7 @@ export async function insertItemByUrl(url: string, item: Item): Promise { } }); - // 6. Handle all properties (core + custom) + // 5. Handle all properties (core + custom) const allProperties = [ ['name', item.name], ['description', item.description], @@ -239,11 +233,19 @@ export async function deleteItemByUrl(url: string, itemId: string): Promise