feat: organizers, meetups UI, Plausible analytics, and migration tooling
- Add organizer model/API, admin and public organizer pages, meetup cards - Refresh events/home/contact; add calendar dialog and carousel components - Optional Plausible via NEXT_PUBLIC_PLAUSIBLE_* env vars in root layout - Prisma migration, seed updates, baseline-and-migrate script Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "Organizer" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"name" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "Organizer_slug_key" ON "Organizer"("slug");
|
||||
|
||||
INSERT INTO "Organizer" ("id", "name", "slug", "createdAt", "updatedAt")
|
||||
VALUES (
|
||||
'00000000-0000-4000-8000-000000000001',
|
||||
'Belgian Bitcoin Embassy',
|
||||
'belgian-bitcoin-embassy',
|
||||
datetime('now'),
|
||||
datetime('now')
|
||||
);
|
||||
|
||||
-- RedefineTables
|
||||
PRAGMA defer_foreign_keys=ON;
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_Meetup" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT NOT NULL,
|
||||
"date" TEXT NOT NULL,
|
||||
"time" TEXT NOT NULL,
|
||||
"location" TEXT NOT NULL,
|
||||
"link" TEXT,
|
||||
"imageId" TEXT,
|
||||
"status" TEXT NOT NULL DEFAULT 'DRAFT',
|
||||
"featured" BOOLEAN NOT NULL DEFAULT false,
|
||||
"visibility" TEXT NOT NULL DEFAULT 'PUBLIC',
|
||||
"organizerId" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
CONSTRAINT "Meetup_organizerId_fkey" FOREIGN KEY ("organizerId") REFERENCES "Organizer" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||
);
|
||||
INSERT INTO "new_Meetup" ("createdAt", "date", "description", "featured", "id", "imageId", "link", "location", "organizerId", "status", "time", "title", "updatedAt", "visibility")
|
||||
SELECT "createdAt", "date", "description", "featured", "id", "imageId", "link", "location", '00000000-0000-4000-8000-000000000001', "status", "time", "title", "updatedAt", "visibility" FROM "Meetup";
|
||||
DROP TABLE "Meetup";
|
||||
ALTER TABLE "new_Meetup" RENAME TO "Meetup";
|
||||
CREATE INDEX "Meetup_organizerId_idx" ON "Meetup"("organizerId");
|
||||
PRAGMA foreign_keys=ON;
|
||||
PRAGMA defer_foreign_keys=OFF;
|
||||
@@ -17,8 +17,17 @@ model User {
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Organizer {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
slug String @unique
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
meetups Meetup[]
|
||||
}
|
||||
|
||||
model Meetup {
|
||||
id String @id @default(uuid())
|
||||
id String @id @default(uuid())
|
||||
title String
|
||||
description String
|
||||
date String
|
||||
@@ -26,11 +35,13 @@ model Meetup {
|
||||
location String
|
||||
link String?
|
||||
imageId String?
|
||||
status String @default("DRAFT") // DRAFT, PUBLISHED, CANCELLED (Upcoming/Past derived from date)
|
||||
featured Boolean @default(false)
|
||||
visibility String @default("PUBLIC") // PUBLIC, HIDDEN
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
status String @default("DRAFT") // DRAFT, PUBLISHED, CANCELLED (Upcoming/Past derived from date)
|
||||
featured Boolean @default(false)
|
||||
visibility String @default("PUBLIC") // PUBLIC, HIDDEN
|
||||
organizerId String
|
||||
organizer Organizer @relation(fields: [organizerId], references: [id], onDelete: Restrict)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Media {
|
||||
|
||||
@@ -56,6 +56,16 @@ async function main() {
|
||||
});
|
||||
}
|
||||
|
||||
const defaultOrganizer = await prisma.organizer.upsert({
|
||||
where: { slug: 'belgian-bitcoin-embassy' },
|
||||
update: {},
|
||||
create: {
|
||||
id: '00000000-0000-4000-8000-000000000001',
|
||||
name: 'Belgian Bitcoin Embassy',
|
||||
slug: 'belgian-bitcoin-embassy',
|
||||
},
|
||||
});
|
||||
|
||||
const existingMeetup = await prisma.meetup.findFirst({
|
||||
where: { title: 'Monthly Bitcoin Meetup' },
|
||||
});
|
||||
@@ -70,8 +80,9 @@ async function main() {
|
||||
time: '19:00',
|
||||
location: 'Brussels, Belgium',
|
||||
link: 'https://meetup.com/example',
|
||||
status: 'UPCOMING',
|
||||
status: 'PUBLISHED',
|
||||
featured: true,
|
||||
organizerId: defaultOrganizer.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user