added a fix for variant selection (without it cards with multiple versions would add all at form submit)

This commit is contained in:
Zach Harding
2026-04-05 16:32:44 -04:00
parent d06c6fb9bf
commit 5d716a4d8e
3 changed files with 23 additions and 9 deletions

View File

@@ -131,6 +131,7 @@ export const inventory = pokeSchema.table('inventory',{
catalogName: varchar({ length: 100 }), catalogName: varchar({ length: 100 }),
cardId: integer().notNull(), cardId: integer().notNull(),
condition: varchar({ length: 255 }).notNull(), condition: varchar({ length: 255 }).notNull(),
variant: varchar({ length: 100 }).default('Normal'),
quantity: integer(), quantity: integer(),
purchasePrice: decimal({ precision: 10, scale: 2 }), purchasePrice: decimal({ precision: 10, scale: 2 }),
note: varchar({ length:255 }), note: varchar({ length:255 }),

View File

@@ -2,7 +2,7 @@ import type { APIRoute } from 'astro';
import { db } from '../../db/index'; import { db } from '../../db/index';
import { inventory, skus, cards } from '../../db/schema'; import { inventory, skus, cards } from '../../db/schema';
import { client } from '../../db/typesense'; import { client } from '../../db/typesense';
import { eq, and } from 'drizzle-orm'; import { eq, and, sql } from 'drizzle-orm';
const GainLoss = (purchasePrice: any, marketPrice: any) => { const GainLoss = (purchasePrice: any, marketPrice: any) => {
if (!purchasePrice || !marketPrice) return '<div class="fs-5 fw-semibold">N/A</div>'; if (!purchasePrice || !marketPrice) return '<div class="fs-5 fw-semibold">N/A</div>';
@@ -20,6 +20,7 @@ const inventories = await db
inventoryId: inventory.inventoryId, inventoryId: inventory.inventoryId,
cardId: inventory.cardId, cardId: inventory.cardId,
condition: inventory.condition, condition: inventory.condition,
variant: inventory.variant,
quantity: inventory.quantity, quantity: inventory.quantity,
purchasePrice: inventory.purchasePrice, purchasePrice: inventory.purchasePrice,
note: inventory.note, note: inventory.note,
@@ -35,7 +36,11 @@ const inventories = await db
skus, skus,
and( and(
eq(cards.productId, skus.productId), eq(cards.productId, skus.productId),
eq(inventory.condition, skus.condition) eq(inventory.condition, skus.condition),
eq(
sql`COALESCE(${inventory.variant}, 'Normal')`,
skus.variant
)
) )
) )
.where(and( .where(and(
@@ -49,7 +54,7 @@ const inventories = await db
const purchasePriceDisplay = inv.purchasePrice ? `$${Number(inv.purchasePrice).toFixed(2)}` : '—'; const purchasePriceDisplay = inv.purchasePrice ? `$${Number(inv.purchasePrice).toFixed(2)}` : '—';
return ` return `
<article class="alert alert-dark rounded-4 inventory-entry-card" <article class="border rounded-4 p-2 inventory-entry-card"
data-inventory-id="${inv.inventoryId}" data-inventory-id="${inv.inventoryId}"
data-card-id="${inv.cardId}" data-card-id="${inv.cardId}"
data-purchase-price="${inv.purchasePrice}" data-purchase-price="${inv.purchasePrice}"
@@ -106,12 +111,13 @@ const inventories = await db
} }
const addToInventory = async (userId: string, cardId: number, condition: string, purchasePrice: number, quantity: number, note: string, catalogName: string) => { const addToInventory = async (userId: string, cardId: number, condition: string, variant: string, purchasePrice: number, quantity: number, note: string, catalogName: string) => {
const inv = await db.insert(inventory).values({ const inv = await db.insert(inventory).values({
userId: userId, userId: userId,
cardId: cardId, cardId: cardId,
catalogName: catalogName, catalogName: catalogName,
condition: condition, condition: condition,
variant: variant,
purchasePrice: purchasePrice, purchasePrice: purchasePrice,
quantity: quantity, quantity: quantity,
note: note, note: note,
@@ -147,11 +153,12 @@ export const POST: APIRoute = async ({ request, locals }) => {
case 'add': case 'add':
const condition = formData.get('condition')?.toString() || 'Unknown'; const condition = formData.get('condition')?.toString() || 'Unknown';
const variant = formData.get('variant')?.toString() || 'Normal';
const purchasePrice = Number(formData.get('purchasePrice')) || 0; const purchasePrice = Number(formData.get('purchasePrice')) || 0;
const quantity = Number(formData.get('quantity')) || 1; const quantity = Number(formData.get('quantity')) || 1;
const note = formData.get('note')?.toString() || ''; const note = formData.get('note')?.toString() || '';
const catalogName = formData.get('catalogName')?.toString() || 'Default'; const catalogName = formData.get('catalogName')?.toString() || 'Default';
await addToInventory(userId!, cardId, condition, purchasePrice, quantity, note, catalogName); await addToInventory(userId!, cardId, condition, variant, purchasePrice, quantity, note, catalogName);
break; break;
case 'remove': case 'remove':

View File

@@ -181,6 +181,9 @@ for (const price of card?.prices ?? []) {
} }
} }
// ── Derive distinct variants available for this card ─────────────────────
const availableVariants = [...new Set(cardSkus.map(s => s.variant))].sort();
const ebaySearchUrl = (card: any) => { const ebaySearchUrl = (card: any) => {
return `https://www.ebay.com/sch/i.html?_nkw=${encodeURIComponent(card?.productUrlName)}+${encodeURIComponent(card?.set?.setUrlName)}+${encodeURIComponent(card?.number)}&LH_Sold=1&Graded=No&_dcat=183454`; return `https://www.ebay.com/sch/i.html?_nkw=${encodeURIComponent(card?.productUrlName)}+${encodeURIComponent(card?.set?.setUrlName)}+${encodeURIComponent(card?.number)}&LH_Sold=1&Graded=No&_dcat=183454`;
}; };
@@ -360,13 +363,13 @@ const altSearchUrl = (card: any) => {
})} })}
{hasAccess && ( {hasAccess && (
<div class="tab-pane fade" id="nav-vendor" role="tabpanel" aria-labelledby="nav-vendor" tabindex="0"> <div class="tab-pane fade" id="nav-vendor" role="tabpanel" aria-labelledby="nav-vendor" tabindex="0">
<div class="row g-3"> <div class="row g-4">
<div class="col-12 col-md-6"> <div class="col-12 col-md-6">
<h6 class="mt-1 mb-2">Add {card?.productName} to inventory</h6> <h6 class="mt-1 mb-2">Add {card?.productName} to inventory</h6>
<form id="inventoryForm" data-inventory-form novalidate> <form id="inventoryForm" data-inventory-form novalidate>
<div class="row gx-3 gy-1"> <div class="row gx-3 gy-1">
<div class="col-4"> <div class="col-3">
<label for="quantity" class="form-label">Quantity</label> <label for="quantity" class="form-label">Quantity</label>
<input <input
type="number" type="number"
@@ -381,7 +384,7 @@ const altSearchUrl = (card: any) => {
<div class="invalid-feedback">Required.</div> <div class="invalid-feedback">Required.</div>
</div> </div>
<div class="col-8"> <div class="col-9">
<div class="d-flex justify-content-between align-items-start gap-2 flex-wrap"> <div class="d-flex justify-content-between align-items-start gap-2 flex-wrap">
<label for="purchasePrice" class="form-label"> <label for="purchasePrice" class="form-label">
Purchase price Purchase price
@@ -486,6 +489,9 @@ const altSearchUrl = (card: any) => {
<label class="btn btn-cond-dmg" for="cond-dmg">DMG</label> <label class="btn btn-cond-dmg" for="cond-dmg">DMG</label>
</div> </div>
</div> </div>
<input type="hidden" name="variant" value={card?.variant} />
<div class="col-12"> <div class="col-12">
<label for="catalogName" class="form-label"> <label for="catalogName" class="form-label">
Catalog Catalog
@@ -534,7 +540,7 @@ const altSearchUrl = (card: any) => {
<h6 class="mt-1 mb-2">Inventory entries for {card?.productName}</h6> <h6 class="mt-1 mb-2">Inventory entries for {card?.productName}</h6>
<!-- Empty state --> <!-- Empty state -->
<div class="alert alert-dark rounded-4 d-none" id="inventoryEmptyState"> <div class="alert alert-dark border-0 rounded-4 d-none" id="inventoryEmptyState">
<div class="fw-medium mb-1">No inventory entries yet</div> <div class="fw-medium mb-1">No inventory entries yet</div>
<div class="text-secondary small"> <div class="text-secondary small">
Once you add copies of this card, they'll show up here. Once you add copies of this card, they'll show up here.