56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
import { eq, inArray } from 'drizzle-orm';
|
|
import { db, wishlistItems, itemClaims, guests } from '@/lib/db';
|
|
|
|
type RawItem = typeof wishlistItems.$inferSelect;
|
|
|
|
export async function attachClaimsToItems(items: RawItem[]) {
|
|
if (items.length === 0) return [];
|
|
const itemIds = items.map((i) => i.id);
|
|
const rows = await db
|
|
.select({
|
|
id: itemClaims.id,
|
|
itemId: itemClaims.itemId,
|
|
quantity: itemClaims.quantity,
|
|
note: itemClaims.note,
|
|
isPurchased: itemClaims.isPurchased,
|
|
claimedAt: itemClaims.claimedAt,
|
|
guestId: guests.id,
|
|
guestName: guests.name,
|
|
})
|
|
.from(itemClaims)
|
|
.innerJoin(guests, eq(itemClaims.guestId, guests.id))
|
|
.where(inArray(itemClaims.itemId, itemIds));
|
|
|
|
const byItem = new Map<string, ReturnType<typeof shapeClaim>[]>();
|
|
for (const r of rows) {
|
|
const arr = byItem.get(r.itemId) ?? [];
|
|
arr.push(shapeClaim(r));
|
|
byItem.set(r.itemId, arr);
|
|
}
|
|
|
|
return items.map((it) => {
|
|
const claims = byItem.get(it.id) ?? [];
|
|
const claimedQuantity = claims.reduce((s, c) => s + c.quantity, 0);
|
|
return {
|
|
...it,
|
|
claims,
|
|
claimedQuantity,
|
|
remainingQuantity: Math.max(0, it.quantity - claimedQuantity),
|
|
};
|
|
});
|
|
}
|
|
|
|
function shapeClaim(r: {
|
|
id: string; quantity: number; note: string | null; isPurchased: boolean;
|
|
claimedAt: Date; guestId: string; guestName: string;
|
|
}) {
|
|
return {
|
|
id: r.id,
|
|
quantity: r.quantity,
|
|
note: r.note,
|
|
isPurchased: r.isPurchased,
|
|
claimedAt: r.claimedAt,
|
|
guest: { id: r.guestId, name: r.guestName },
|
|
};
|
|
}
|