feat: add featured event with automatic fallback

- Add featured_event_id to site_settings (schema + migration)
- Backend: featured event logic in /events/next/upcoming with auto-unset when event ends
- Site settings: PUT supports featuredEventId, add PUT /featured-event for admin
- Admin events: Set as featured checkbox in editor, star toggle in list, featured badge
- Admin settings: Featured Event section with current event and remove/change links
- API: siteSettingsApi.setFeaturedEvent(), Event.isFeatured, SiteSettings.featuredEventId
- Homepage/linktree unchanged: still use getNextUpcoming (now returns featured or fallback)
This commit is contained in:
Michilis
2026-02-03 19:24:00 +00:00
parent 0fd8172e04
commit 0c142884c7
9 changed files with 421 additions and 78 deletions

View File

@@ -388,6 +388,7 @@ async function migrate() {
instagram_url TEXT,
twitter_url TEXT,
linkedin_url TEXT,
featured_event_id TEXT REFERENCES events(id),
maintenance_mode INTEGER NOT NULL DEFAULT 0,
maintenance_message TEXT,
maintenance_message_es TEXT,
@@ -396,6 +397,11 @@ async function migrate() {
)
`);
// Add featured_event_id column to site_settings if it doesn't exist
try {
await (db as any).run(sql`ALTER TABLE site_settings ADD COLUMN featured_event_id TEXT REFERENCES events(id)`);
} catch (e) { /* column may already exist */ }
// Legal pages table for admin-editable legal content
await (db as any).run(sql`
CREATE TABLE IF NOT EXISTS legal_pages (
@@ -748,6 +754,7 @@ async function migrate() {
instagram_url VARCHAR(500),
twitter_url VARCHAR(500),
linkedin_url VARCHAR(500),
featured_event_id UUID REFERENCES events(id),
maintenance_mode INTEGER NOT NULL DEFAULT 0,
maintenance_message TEXT,
maintenance_message_es TEXT,
@@ -756,6 +763,11 @@ async function migrate() {
)
`);
// Add featured_event_id column to site_settings if it doesn't exist
try {
await (db as any).execute(sql`ALTER TABLE site_settings ADD COLUMN featured_event_id UUID REFERENCES events(id)`);
} catch (e) { /* column may already exist */ }
// Legal pages table for admin-editable legal content
await (db as any).execute(sql`
CREATE TABLE IF NOT EXISTS legal_pages (

View File

@@ -283,6 +283,8 @@ export const sqliteSiteSettings = sqliteTable('site_settings', {
instagramUrl: text('instagram_url'),
twitterUrl: text('twitter_url'),
linkedinUrl: text('linkedin_url'),
// Featured event - manually promoted event shown on homepage/linktree
featuredEventId: text('featured_event_id').references(() => sqliteEvents.id),
// Other settings
maintenanceMode: integer('maintenance_mode', { mode: 'boolean' }).notNull().default(false),
maintenanceMessage: text('maintenance_message'),
@@ -563,6 +565,8 @@ export const pgSiteSettings = pgTable('site_settings', {
instagramUrl: varchar('instagram_url', { length: 500 }),
twitterUrl: varchar('twitter_url', { length: 500 }),
linkedinUrl: varchar('linkedin_url', { length: 500 }),
// Featured event - manually promoted event shown on homepage/linktree
featuredEventId: uuid('featured_event_id').references(() => pgEvents.id),
// Other settings
maintenanceMode: pgInteger('maintenance_mode').notNull().default(0),
maintenanceMessage: pgText('maintenance_message'),