fix: currency suggestion uses region detection, seed adds market prices
- Currency auto-suggestion now uses locale region subtag (en-US → US → USD, en-DE → DE → EUR) instead of language prefix. Fixes wrong suggestion for users with English browser locale in European countries. - Added dismiss button (X) to suggestion banner - Dev seed script now clears existing dev data before re-seeding (safe to run repeatedly without manual DB cleanup) - Added DEV_MARKET_PRICES with multi-market UVP data for 10 global items (EU/US/UK prices) and community prices for 5 owned items Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
// ── Dev Seed Runner ────────────────────────────────────────────────
|
||||
// Idempotent script to populate a dev database with realistic data.
|
||||
// Clears dev data and re-seeds with fresh realistic data.
|
||||
// Usage: bun run db:seed:dev
|
||||
// Preserves real (non-dev) users. Safe to run repeatedly.
|
||||
|
||||
import { and, eq } from "drizzle-orm";
|
||||
import { and, eq, like, sql } from "drizzle-orm";
|
||||
import {
|
||||
DEV_CATEGORIES,
|
||||
DEV_GLOBAL_ITEMS,
|
||||
DEV_MARKET_PRICES,
|
||||
DEV_SETTINGS,
|
||||
DEV_SETUPS,
|
||||
DEV_TAG_ASSIGNMENTS,
|
||||
@@ -18,19 +20,64 @@ import { seedGlobalItems } from "./seed-global-items.ts";
|
||||
|
||||
type Db = typeof db;
|
||||
|
||||
async function seedDevData(database: Db = db) {
|
||||
// ── Idempotency check ──────────────────────────────────────────
|
||||
const existing = await database
|
||||
.select()
|
||||
.from(schema.users)
|
||||
.where(eq(schema.users.logtoSub, "dev-user-seed"))
|
||||
.limit(1);
|
||||
async function clearDevData(database: Db) {
|
||||
console.log("Clearing existing dev seed data...");
|
||||
|
||||
if (existing.length > 0) {
|
||||
console.log("Dev seed data already exists, skipping.");
|
||||
return;
|
||||
// Find dev user(s)
|
||||
const devUsers = await database
|
||||
.select({ id: schema.users.id })
|
||||
.from(schema.users)
|
||||
.where(like(schema.users.logtoSub, "dev-user%"));
|
||||
|
||||
for (const user of devUsers) {
|
||||
// Delete in FK order: setup_items → setups, thread_candidates → threads, items, categories, settings, shares
|
||||
await database
|
||||
.delete(schema.setupItems)
|
||||
.where(
|
||||
sql`${schema.setupItems.setupId} IN (SELECT id FROM setups WHERE user_id = ${user.id})`,
|
||||
);
|
||||
await database
|
||||
.delete(schema.shares)
|
||||
.where(
|
||||
sql`${schema.shares.setupId} IN (SELECT id FROM setups WHERE user_id = ${user.id})`,
|
||||
);
|
||||
await database
|
||||
.delete(schema.setups)
|
||||
.where(eq(schema.setups.userId, user.id));
|
||||
await database
|
||||
.delete(schema.threadCandidates)
|
||||
.where(
|
||||
sql`${schema.threadCandidates.threadId} IN (SELECT id FROM threads WHERE user_id = ${user.id})`,
|
||||
);
|
||||
await database
|
||||
.delete(schema.threads)
|
||||
.where(eq(schema.threads.userId, user.id));
|
||||
await database
|
||||
.delete(schema.communityPrices)
|
||||
.where(eq(schema.communityPrices.userId, user.id));
|
||||
await database.delete(schema.items).where(eq(schema.items.userId, user.id));
|
||||
await database
|
||||
.delete(schema.categories)
|
||||
.where(eq(schema.categories.userId, user.id));
|
||||
await database
|
||||
.delete(schema.settings)
|
||||
.where(eq(schema.settings.userId, user.id));
|
||||
await database.delete(schema.users).where(eq(schema.users.id, user.id));
|
||||
console.log(` Cleared dev user id=${user.id}`);
|
||||
}
|
||||
|
||||
// Clear market prices (these are global, not user-scoped, but seeded by dev)
|
||||
await database.delete(schema.marketPrices);
|
||||
console.log(" Cleared market prices.");
|
||||
|
||||
// Global items and tags are shared — leave them (seedGlobalItems handles idempotency)
|
||||
console.log("Dev data cleared.\n");
|
||||
}
|
||||
|
||||
async function seedDevData(database: Db = db) {
|
||||
// ── Clear previous dev data ────────────────────────────────────
|
||||
await clearDevData(database);
|
||||
|
||||
try {
|
||||
// ── 1. Seed global items and tags ──────────────────────────
|
||||
await seedGlobalItems(database);
|
||||
@@ -286,9 +333,50 @@ async function seedDevData(database: Db = db) {
|
||||
}
|
||||
console.log(` ${DEV_SETTINGS.length} settings created.`);
|
||||
|
||||
// ── 12. Insert market prices ───────────────────────────────
|
||||
let marketPriceCount = 0;
|
||||
for (const mp of DEV_MARKET_PRICES) {
|
||||
const giId = globalItemIds[mp.globalItemIndex];
|
||||
if (!giId) continue;
|
||||
await database.insert(schema.marketPrices).values({
|
||||
globalItemId: giId,
|
||||
market: mp.market,
|
||||
currency: mp.currency,
|
||||
priceCents: mp.priceCents,
|
||||
source: mp.source,
|
||||
});
|
||||
marketPriceCount++;
|
||||
}
|
||||
console.log(` ${marketPriceCount} market prices created.`);
|
||||
|
||||
// ── 13. Insert community prices ────────────────────────────
|
||||
// Seed a few community prices from the dev user for items they own
|
||||
const ownedGlobalItemIds = insertedItems
|
||||
.filter((i) => i.globalItemId !== null)
|
||||
.map((i) => i.globalItemId as number);
|
||||
|
||||
let communityPriceCount = 0;
|
||||
for (const giId of ownedGlobalItemIds.slice(0, 5)) {
|
||||
const item = insertedItems.find((i) => i.globalItemId === giId);
|
||||
if (!item) continue;
|
||||
await database.insert(schema.communityPrices).values({
|
||||
globalItemId: giId,
|
||||
userId,
|
||||
market: "EU",
|
||||
currency: "EUR",
|
||||
priceCents: item.priceCents
|
||||
? Math.round(item.priceCents * 0.85)
|
||||
: 10000,
|
||||
priceDate: new Date("2026-03-15"),
|
||||
sourceType: "purchased",
|
||||
});
|
||||
communityPriceCount++;
|
||||
}
|
||||
console.log(` ${communityPriceCount} community prices created.`);
|
||||
|
||||
// ── Summary ────────────────────────────────────────────────
|
||||
console.log(
|
||||
`\nDev seed complete: ${globalItemIds.length} global items, ${allTags.length} tags, ${insertedItems.length} user items, ${threadResults.length} threads, ${setupResults.length} setups`,
|
||||
`\nDev seed complete: ${globalItemIds.length} global items, ${allTags.length} tags, ${insertedItems.length} user items, ${threadResults.length} threads, ${setupResults.length} setups, ${marketPriceCount} market prices`,
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("Seed failed:", err);
|
||||
|
||||
Reference in New Issue
Block a user