Files
chadebebe/lib/items-with-claims.ts

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 },
};
}