Files
blackheart-website/src/data/seed.ts
diana.dolgolyova 84b0bc4d60 feat: add master classes section with registration system
- New master classes section on landing page with upcoming events grid
- Admin CRUD for master classes (image, slots, trainer, style, cost, location)
- User signup modal (name + Instagram required, Telegram optional)
- Admin registration management: view, add, edit, delete with quick-contact links
- Customizable success message for signup confirmation
- Auto-filter past events, Russian date formatting, duration auto-calculation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 18:29:06 +03:00

98 lines
2.5 KiB
TypeScript

/**
* Seed script — populates the SQLite database from content.ts
* Run: npx tsx src/data/seed.ts
*/
import Database from "better-sqlite3";
import path from "path";
import { siteContent } from "./content";
const DB_PATH =
process.env.DATABASE_PATH ||
path.join(process.cwd(), "db", "blackheart.db");
const db = new Database(DB_PATH);
db.pragma("journal_mode = WAL");
// Create tables
db.exec(`
CREATE TABLE IF NOT EXISTS sections (
key TEXT PRIMARY KEY,
data TEXT NOT NULL,
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS team_members (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
role TEXT NOT NULL,
image TEXT NOT NULL,
instagram TEXT,
description TEXT,
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);
`);
// Seed sections (team members go in their own table)
const sectionData: Record<string, unknown> = {
meta: siteContent.meta,
hero: siteContent.hero,
about: siteContent.about,
classes: siteContent.classes,
masterClasses: siteContent.masterClasses,
faq: siteContent.faq,
pricing: siteContent.pricing,
schedule: siteContent.schedule,
contact: siteContent.contact,
};
// Team section stores only the title
sectionData.team = { title: siteContent.team.title };
const upsertSection = db.prepare(
`INSERT INTO sections (key, data, updated_at) VALUES (?, ?, datetime('now'))
ON CONFLICT(key) DO UPDATE SET data = excluded.data, updated_at = excluded.updated_at`
);
const insertMember = db.prepare(
`INSERT INTO team_members (name, role, image, instagram, description, sort_order)
VALUES (?, ?, ?, ?, ?, ?)`
);
const tx = db.transaction(() => {
// Upsert all sections
for (const [key, data] of Object.entries(sectionData)) {
upsertSection.run(key, JSON.stringify(data));
}
// Clear existing team members and re-insert
db.prepare("DELETE FROM team_members").run();
siteContent.team.members.forEach((m, i) => {
insertMember.run(
m.name,
m.role,
m.image,
m.instagram ?? null,
m.description ?? null,
i
);
});
});
tx();
const sectionCount = (
db.prepare("SELECT COUNT(*) as c FROM sections").get() as { c: number }
).c;
const memberCount = (
db.prepare("SELECT COUNT(*) as c FROM team_members").get() as { c: number }
).c;
console.log(`Seeded ${sectionCount} sections and ${memberCount} team members.`);
console.log(`Database: ${DB_PATH}`);
db.close();