mirror of
https://github.com/System-End/campfire.git
synced 2026-04-19 20:55:10 +00:00
feat: add map + under construction pages (#11)
* feat: add map * feat: move map to top * feat: move map + 404 * feat: add record id to table * chore: prisma generated files * feat: record record ids * feat: fillout events param
This commit is contained in:
parent
f4d6684426
commit
ae4b1e8519
24 changed files with 626 additions and 39 deletions
50
astro/package-lock.json
generated
50
astro/package-lock.json
generated
|
|
@ -15,13 +15,16 @@
|
||||||
"@prisma/client": "^7.1.0",
|
"@prisma/client": "^7.1.0",
|
||||||
"@prisma/config": "^7.1.0",
|
"@prisma/config": "^7.1.0",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
|
"@types/leaflet": "^1.9.21",
|
||||||
"@types/react": "^19.2.7",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"astro": "^5.16.5",
|
"astro": "^5.16.5",
|
||||||
"better-auth": "^1.4.6",
|
"better-auth": "^1.4.6",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"react": "^19.2.1",
|
"react": "^19.2.1",
|
||||||
"react-dom": "^19.2.1",
|
"react-dom": "^19.2.1",
|
||||||
|
"react-leaflet": "^5.0.0",
|
||||||
"svelte": "^5.45.10",
|
"svelte": "^5.45.10",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
|
|
@ -1415,6 +1418,17 @@
|
||||||
"@prisma/debug": "7.1.0"
|
"@prisma/debug": "7.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-leaflet/core": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ==",
|
||||||
|
"license": "Hippocratic-2.1",
|
||||||
|
"peerDependencies": {
|
||||||
|
"leaflet": "^1.9.0",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@rolldown/pluginutils": {
|
"node_modules/@rolldown/pluginutils": {
|
||||||
"version": "1.0.0-beta.27",
|
"version": "1.0.0-beta.27",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
|
@ -2148,6 +2162,12 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/geojson": {
|
||||||
|
"version": "7946.0.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
|
||||||
|
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/hast": {
|
"node_modules/@types/hast": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
@ -2155,6 +2175,15 @@
|
||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/leaflet": {
|
||||||
|
"version": "1.9.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.21.tgz",
|
||||||
|
"integrity": "sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/geojson": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/mdast": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
@ -3879,6 +3908,13 @@
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/leaflet": {
|
||||||
|
"version": "1.9.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz",
|
||||||
|
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/lightningcss": {
|
"node_modules/lightningcss": {
|
||||||
"version": "1.30.2",
|
"version": "1.30.2",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
|
|
@ -5381,6 +5417,20 @@
|
||||||
"react": "^19.2.1"
|
"react": "^19.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-leaflet": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-CWbTpr5vcHw5bt9i4zSlPEVQdTVcML390TjeDG0cK59z1ylexpqC6M1PJFjV8jD7CF+ACBFsLIDs6DRMoLEofw==",
|
||||||
|
"license": "Hippocratic-2.1",
|
||||||
|
"dependencies": {
|
||||||
|
"@react-leaflet/core": "^3.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"leaflet": "^1.9.0",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-refresh": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.17.0",
|
"version": "0.17.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,16 @@
|
||||||
"@prisma/client": "^7.1.0",
|
"@prisma/client": "^7.1.0",
|
||||||
"@prisma/config": "^7.1.0",
|
"@prisma/config": "^7.1.0",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
|
"@types/leaflet": "^1.9.21",
|
||||||
"@types/react": "^19.2.7",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"astro": "^5.16.5",
|
"astro": "^5.16.5",
|
||||||
"better-auth": "^1.4.6",
|
"better-auth": "^1.4.6",
|
||||||
"dotenv": "^17.2.3",
|
"dotenv": "^17.2.3",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
"react": "^19.2.1",
|
"react": "^19.2.1",
|
||||||
"react-dom": "^19.2.1",
|
"react-dom": "^19.2.1",
|
||||||
|
"react-leaflet": "^5.0.0",
|
||||||
"svelte": "^5.45.10",
|
"svelte": "^5.45.10",
|
||||||
"tailwindcss": "^4.1.18",
|
"tailwindcss": "^4.1.18",
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- A unique constraint covering the columns `[recordId]` on the table `Satellite` will be added. If there are existing duplicate values, this will fail.
|
||||||
|
- Added the required column `recordId` to the `Satellite` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Satellite" ADD COLUMN "recordId" TEXT NOT NULL;
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Satellite_recordId_key" ON "Satellite"("recordId");
|
||||||
|
|
@ -15,6 +15,7 @@ datasource db {
|
||||||
|
|
||||||
model Satellite {
|
model Satellite {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
|
recordId String @unique
|
||||||
slug String @unique
|
slug String @unique
|
||||||
data Json
|
data Json
|
||||||
active Boolean @default(true)
|
active Boolean @default(true)
|
||||||
|
|
|
||||||
BIN
astro/public/map/map-flag.png
Normal file
BIN
astro/public/map/map-flag.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 831 B |
BIN
astro/public/map/map-screenshot.png
Normal file
BIN
astro/public/map/map-screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 147 KiB |
|
|
@ -5,9 +5,11 @@ import Step from '../primitives/Step.js';
|
||||||
import StoryCard from '../primitives/StoryCard.js';
|
import StoryCard from '../primitives/StoryCard.js';
|
||||||
import GameCard from '../primitives/GameCard.js';
|
import GameCard from '../primitives/GameCard.js';
|
||||||
import NavbarLink from '../primitives/NavbarLink.tsx';
|
import NavbarLink from '../primitives/NavbarLink.tsx';
|
||||||
import VideoEmbed from '../primitives/VideoEmbed.tsx';
|
import MapEmbed from '../primitives/MapEmbed.tsx';
|
||||||
|
import { Map } from '../primitives/Map.tsx';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
import type { EventLocation } from '../../lib/events.ts';
|
||||||
|
|
||||||
const FORM_URL_ORGANIZER_APPLICATION = "https://forms.hackclub.com/t/8L51MzWyrHus";
|
const FORM_URL_ORGANIZER_APPLICATION = "https://forms.hackclub.com/t/8L51MzWyrHus";
|
||||||
const FORM_URL_RSVP = "https://forms.hackclub.com/t/a3QSt8MuvHus";
|
const FORM_URL_RSVP = "https://forms.hackclub.com/t/a3QSt8MuvHus";
|
||||||
|
|
@ -49,12 +51,13 @@ function FlagshipCTA({ className, compact, maxWidth }: { className?: string; com
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function App() {
|
function App({ events }: { events: EventLocation[] }) {
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [scrollY, setScrollY] = useState(document.body.scrollTop);
|
const [scrollY, setScrollY] = useState(document.body.scrollTop);
|
||||||
const [isLargeScreen, setIsLargeScreen] = useState(window.innerWidth >= 1280);
|
const [isLargeScreen, setIsLargeScreen] = useState(window.innerWidth >= 1280);
|
||||||
const [windowHeight, setWindowHeight] = useState(window.innerHeight);
|
const [windowHeight, setWindowHeight] = useState(window.innerHeight);
|
||||||
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
|
||||||
|
const [isMapOpen, setIsMapOpen] = useState(false);
|
||||||
const emailRef = useRef<HTMLInputElement>(null);
|
const emailRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -111,7 +114,7 @@ function App() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full h-screen">
|
<div className={clsx("w-full relative", windowHeight > windowWidth && windowWidth < 860 ? "h-full" : "h-screen")}>
|
||||||
<header className="relative h-[60px] md:h-[115px] bg-[#45b4f5] justify-end items-center content-center md:pr-16 hidden sm:flex">
|
<header className="relative h-[60px] md:h-[115px] bg-[#45b4f5] justify-end items-center content-center md:pr-16 hidden sm:flex">
|
||||||
<nav className="flex gap-4 w-full justify-between px-8 md:px-0 text-2xl md:gap-12 items-center md:justify-end text-white md:text-3xl xl:text-5xl font-bold font-ember-and-fire">
|
<nav className="flex gap-4 w-full justify-between px-8 md:px-0 text-2xl md:gap-12 items-center md:justify-end text-white md:text-3xl xl:text-5xl font-bold font-ember-and-fire">
|
||||||
<NavbarLink onClick={() => scrollToSection('steps')}>How to organize</NavbarLink>
|
<NavbarLink onClick={() => scrollToSection('steps')}>How to organize</NavbarLink>
|
||||||
|
|
@ -124,8 +127,8 @@ function App() {
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section className={clsx(
|
<section className={clsx(
|
||||||
"relative h-full px-6 md:px-16 md:px-24 2xl:px-32 bg-[url(/backgrounds/blue-sky.webp)] bg-center bg-cover",
|
"relative px-6 md:px-16 md:px-24 2xl:px-32 bg-[url(/backgrounds/blue-sky.webp)] bg-center bg-cover",
|
||||||
windowHeight > windowWidth && windowWidth < 860 ? "flex items-stretch pb-16" : "flex items-end pb-32 2xl:pb-48"
|
windowHeight > windowWidth && windowWidth < 860 ? "flex items-stretch pb-0" : "h-full flex items-end pb-32 2xl:pb-48"
|
||||||
)}>
|
)}>
|
||||||
<div className="absolute top-0 left-0 w-full h-full pointer-events-none">
|
<div className="absolute top-0 left-0 w-full h-full pointer-events-none">
|
||||||
<img src="/backgrounds/sky-shine.webp" alt="" className="w-full h-full object-cover select-none" />
|
<img src="/backgrounds/sky-shine.webp" alt="" className="w-full h-full object-cover select-none" />
|
||||||
|
|
@ -159,21 +162,24 @@ function App() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="absolute -bottom-[50px] left-0 w-full h-[120px] pointer-events-none">
|
{/* <div className="absolute -bottom-[50px] left-0 w-full h-[120px] pointer-events-none">
|
||||||
<img
|
<img
|
||||||
src="/decorative/vines.webp"
|
src="/decorative/vines.webp"
|
||||||
alt=""
|
alt=""
|
||||||
className="w-full h-full object-cover object-top select-none"
|
className="w-full h-full object-cover object-top select-none"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="flex flex-col md:flex-row justify-between items-center md:items-start xl:items-center w-full gap-8 pb-16 z-30 h-full pt-16 md:pt-0 md:h-auto">
|
<div className={clsx(
|
||||||
|
"flex flex-col md:flex-row justify-between items-center md:items-start xl:items-center w-full gap-8 z-30 pt-16 md:pt-0",
|
||||||
|
windowHeight > windowWidth && windowWidth < 860 ? "pb-32" : "pb-16 h-full md:h-auto"
|
||||||
|
)}>
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
"flex flex-col gap-4 w-full md:w-[648px]",
|
"flex flex-col gap-4 w-full md:w-[648px]",
|
||||||
windowHeight > windowWidth && windowWidth < 860 && "justify-between h-full"
|
windowHeight > windowWidth && windowWidth < 860 && "justify-between h-full"
|
||||||
)}>
|
)}>
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
{windowWidth >= 400 && <FlagshipCTA className="min-[860px]:hidden -mt-12 mb-8" compact={windowWidth < 500} />}
|
{/* {windowWidth >= 400 && <FlagshipCTA className="min-[860px]:hidden -mt-12 mb-8" compact={windowWidth < 500} />} */}
|
||||||
|
|
||||||
<div className="flex items-center gap-3 mb-4 relative z-30">
|
<div className="flex items-center gap-3 mb-4 relative z-30">
|
||||||
<a href='https://hackclub.com' className='transition-transform hover:scale-105 active:scale-95'>
|
<a href='https://hackclub.com' className='transition-transform hover:scale-105 active:scale-95'>
|
||||||
|
|
@ -280,7 +286,7 @@ function App() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<VideoEmbed className="hidden xl:block self-end mb-8" />
|
<MapEmbed className="hidden xl:block self-end mb-8 relative z-50" onOpenMap={() => setIsMapOpen(true)} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
@ -297,8 +303,8 @@ function App() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section className="relative pb-96 bg-[url(/backgrounds/underwater-gradient.webp)] bg-cover bg-top">
|
<section className="relative pb-96 bg-[url(/backgrounds/underwater-gradient.webp)] bg-cover bg-top">
|
||||||
<div className="xl:hidden pt-16 pb-8 relative z-10">
|
<div className="xl:hidden pt-16 pb-8 relative z-50">
|
||||||
<VideoEmbed className="px-6" />
|
<MapEmbed className="px-6 relative z-50 max-w-sm mx-auto" onOpenMap={() => setIsMapOpen(true)} />
|
||||||
</div>
|
</div>
|
||||||
<div className="pt-[8vw] xl:pt-[13vw]"></div>
|
<div className="pt-[8vw] xl:pt-[13vw]"></div>
|
||||||
<div className="absolute top-0 left-0 w-screen h-[200px] bg-gradient-to-b from-[#004b2a] to-transparent pointer-events-none"></div>
|
<div className="absolute top-0 left-0 w-screen h-[200px] bg-gradient-to-b from-[#004b2a] to-transparent pointer-events-none"></div>
|
||||||
|
|
@ -709,6 +715,29 @@ function App() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
{isMapOpen && (
|
||||||
|
<div
|
||||||
|
className="fixed inset-0 bg-black/80 z-[9999] flex items-center justify-center p-4"
|
||||||
|
onClick={() => setIsMapOpen(false)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="relative w-[90vw] h-[80vh]"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsMapOpen(false)}
|
||||||
|
className="absolute -top-10 right-0 text-white text-3xl font-bold hover:opacity-70 cursor-pointer"
|
||||||
|
>
|
||||||
|
✕
|
||||||
|
</button>
|
||||||
|
<Map
|
||||||
|
events={events}
|
||||||
|
className="w-full h-full rounded-2xl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import FaqButton from '../primitives/FaqButton.js';
|
||||||
import Step from '../primitives/Step.js';
|
import Step from '../primitives/Step.js';
|
||||||
import GameCard from '../primitives/GameCard.js';
|
import GameCard from '../primitives/GameCard.js';
|
||||||
import NavbarLink from '../primitives/NavbarLink.tsx';
|
import NavbarLink from '../primitives/NavbarLink.tsx';
|
||||||
import VideoEmbed from '../primitives/VideoEmbed.tsx';
|
import VideoEmbed from '../primitives/MapEmbed.tsx';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import type { SatelliteContent } from '../../lib/satellite.ts';
|
import type { SatelliteContent } from '../../lib/satellite.ts';
|
||||||
|
|
|
||||||
153
astro/src/components/pages/UnderConstruction.tsx
Normal file
153
astro/src/components/pages/UnderConstruction.tsx
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
import '../../styles/global.css';
|
||||||
|
import { useState, useRef } from 'react';
|
||||||
|
import clsx from 'clsx';
|
||||||
|
|
||||||
|
const FORM_URL_SIGN_UP = "https://forms.hackclub.com/campfire-signup";
|
||||||
|
|
||||||
|
interface UnderConstructionProps {
|
||||||
|
event_name: string;
|
||||||
|
record_id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function UnderConstruction({ event_name, record_id }: UnderConstructionProps) {
|
||||||
|
const [email, setEmail] = useState("");
|
||||||
|
const emailRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
function openWithEmail(url: string) {
|
||||||
|
if (!emailRef?.current?.reportValidity() || !email)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window.open(`${url}?email=${encodeURIComponent(email)}&event=${encodeURIComponent(record_id || "")}`, "_blank");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full min-h-screen flex flex-col overflow-hidden relative bg-[#fca84a]">
|
||||||
|
{/* Background layers */}
|
||||||
|
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||||
|
<img
|
||||||
|
src="/backgrounds/blue-sky.webp"
|
||||||
|
alt=""
|
||||||
|
className="absolute inset-0 w-full h-full object-cover select-none"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src="/backgrounds/sky-shine.webp"
|
||||||
|
alt=""
|
||||||
|
className="absolute inset-0 w-full h-full object-cover select-none"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src="/backgrounds/landing-grass.png"
|
||||||
|
alt=""
|
||||||
|
className="absolute bottom-0 left-0 w-full h-auto object-cover select-none"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="relative z-10 flex flex-col items-center justify-center flex-1 px-6 py-16">
|
||||||
|
<div className="flex flex-col gap-8 items-center max-w-[648px] w-full">
|
||||||
|
{/* Logo section */}
|
||||||
|
<div className="flex md:block flex-col items-center justify-center">
|
||||||
|
<div className="flex items-center gap-3 mb-4 relative z-30">
|
||||||
|
<a href='https://hackclub.com' className='transition-transform hover:scale-105 active:scale-95'>
|
||||||
|
<img
|
||||||
|
src="/decorative/flag-standalone-wtransparent.png"
|
||||||
|
alt="Hack Club"
|
||||||
|
className="w-[151px] h-[53px] object-cover transform rotate-[-4.8deg] select-none"
|
||||||
|
style={{
|
||||||
|
filter: "drop-shadow(3px 3px 0px rgba(0,0,0,0.25))"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
<div className="w-[2px] h-8 bg-white opacity-60"></div>
|
||||||
|
<a href='https://opensauce.com' className='transition-transform scale-125 hover:scale-130 active:scale-130'>
|
||||||
|
<img
|
||||||
|
src="/branding/logo-opensauce.webp"
|
||||||
|
alt="Open Sauce"
|
||||||
|
className="h-[70px] object-contain select-none pl-4"
|
||||||
|
style={{
|
||||||
|
filter: "drop-shadow(3px 3px 0px rgba(0,0,0,0.25))"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="transform md:rotate-[-2.97deg] w-min">
|
||||||
|
<h1
|
||||||
|
className="text-[#fcf5ed] text-[80px] md:text-[100px] xl:text-[150px] font-normal leading-none -mb-4 font-dream-planner"
|
||||||
|
style={{
|
||||||
|
textShadow: "5px 8px 0px rgba(0,0,0,0.25)"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
CAMPFIRE
|
||||||
|
</h1>
|
||||||
|
<h3
|
||||||
|
className="text-[#fcf5ed] text-[40px] md:text-[50px] xl:text-[60px] font-normal leading-none mb-4 font-dream-planner text-right"
|
||||||
|
style={{
|
||||||
|
textShadow: "5px 8px 0px rgba(0,0,0,0.25)"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{event_name.toUpperCase()}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="pl-2 md:pl-4">
|
||||||
|
<p
|
||||||
|
className="text-white text-4xl md:text-3xl xl:text-4xl font-bold mb-2 font-ember-and-fire text-center"
|
||||||
|
style={{
|
||||||
|
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
This site is still under construction!
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
className="text-white text-4xl md:text-3xl xl:text-4xl font-bold font-ember-and-fire text-center"
|
||||||
|
style={{
|
||||||
|
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
You can still sign up below:
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* RSVP form */}
|
||||||
|
<div className='flex flex-col gap-4'>
|
||||||
|
<div className="flex flex-col md:flex-row items-center gap-2">
|
||||||
|
<div
|
||||||
|
className={clsx(
|
||||||
|
"bg-[#f9e2ca] border-4 border-[#d5a16c] rounded-[20px] px-4 md:px-8 py-4 flex items-center gap-3 md:gap-6 w-full transform md:rotate-[-1.2deg] shadow-[0_8px_20px_rgba(0,0,0,0.25)]",
|
||||||
|
"transition-transform hover:scale-105"
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<img src="/icons/email.svg" alt="" className="w-6 h-5 flex-shrink-0 select-none" />
|
||||||
|
<input
|
||||||
|
required
|
||||||
|
ref={emailRef}
|
||||||
|
value={email}
|
||||||
|
onChange={e => setEmail(e.target.value)}
|
||||||
|
type="email"
|
||||||
|
className="text-[#854d16] text-2xl md:text-4xl font-bold truncate bg-transparent border-none outline-none flex-1 cursor-text font-ember-and-fire"
|
||||||
|
placeholder="you@hackclub.com"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="bg-[#fca147] border-[5px] border-[rgba(0,0,0,0.2)] rounded-[20px] px-8 md:px-14 py-4 hover:scale-105 transition-transform w-full md:w-auto transform md:rotate-[1.5deg] shadow-[0_8px_20px_rgba(0,0,0,0.25)] cursor-pointer active:scale-95"
|
||||||
|
type="button"
|
||||||
|
onClick={() => openWithEmail(FORM_URL_SIGN_UP)}
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
className="text-[#8d3f34] text-3xl md:text-5xl font-normal font-dream-planner whitespace-nowrap"
|
||||||
|
>
|
||||||
|
SIGN UP!
|
||||||
|
</p>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UnderConstruction;
|
||||||
89
astro/src/components/primitives/Map.tsx
Normal file
89
astro/src/components/primitives/Map.tsx
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import type { EventLocation } from '../../lib/events';
|
||||||
|
import '../../styles/map.css';
|
||||||
|
|
||||||
|
interface MapProps {
|
||||||
|
events: EventLocation[];
|
||||||
|
center?: [number, number];
|
||||||
|
zoom?: number;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Map({ events, center = [20, 0], zoom = 2, className }: MapProps) {
|
||||||
|
const [MapComponents, setMapComponents] = useState<{
|
||||||
|
MapContainer: any;
|
||||||
|
TileLayer: any;
|
||||||
|
Marker: any;
|
||||||
|
Popup: any;
|
||||||
|
useMap: any;
|
||||||
|
flagIcon: any;
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
import('leaflet/dist/leaflet.css');
|
||||||
|
Promise.all([import('leaflet'), import('react-leaflet')]).then(([L, module]) => {
|
||||||
|
const flagIcon = L.icon({
|
||||||
|
iconUrl: '/map/map-flag.png',
|
||||||
|
iconSize: [32, 32],
|
||||||
|
iconAnchor: [16, 32],
|
||||||
|
popupAnchor: [0, -32]
|
||||||
|
});
|
||||||
|
setMapComponents({
|
||||||
|
MapContainer: module.MapContainer,
|
||||||
|
TileLayer: module.TileLayer,
|
||||||
|
Marker: module.Marker,
|
||||||
|
Popup: module.Popup,
|
||||||
|
useMap: module.useMap,
|
||||||
|
flagIcon,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const validEvents = events.filter(
|
||||||
|
(event) => typeof event.lat === 'number' && typeof event.long === 'number'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!MapComponents) {
|
||||||
|
return <div style={{ minHeight: '400px', height: '100%', width: '100%', background: 'linear-gradient(135deg, #CCF4FD 0%, #B8D9F8 100%)', borderRadius: '16px' }} className={className} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { MapContainer, TileLayer, Marker, Popup, useMap, flagIcon } = MapComponents;
|
||||||
|
|
||||||
|
function InvalidateSize() {
|
||||||
|
const map = useMap();
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setTimeout(() => map.invalidateSize(), 0);
|
||||||
|
const resizeTimer = setTimeout(() => map.invalidateSize(), 300);
|
||||||
|
return () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
clearTimeout(resizeTimer);
|
||||||
|
};
|
||||||
|
}, [map]);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MapContainer
|
||||||
|
center={center}
|
||||||
|
zoom={zoom}
|
||||||
|
className={className}
|
||||||
|
style={{ minHeight: '400px', height: '100%', width: '100%' }}
|
||||||
|
>
|
||||||
|
<InvalidateSize />
|
||||||
|
<TileLayer
|
||||||
|
attribution='© OpenStreetMap contributors © CARTO'
|
||||||
|
url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png"
|
||||||
|
detectRetina={true}
|
||||||
|
/>
|
||||||
|
{validEvents.map((event) => (
|
||||||
|
<Marker key={event.slug} position={[event.lat, event.long]} icon={flagIcon}>
|
||||||
|
<Popup className="custom-popup">
|
||||||
|
<div>
|
||||||
|
<a href={`https://campfire.hackclub.com/${event.slug}`} className="text-black text-lg font-bold font-ember-and-fire">Campfire {event.event_name}</a>
|
||||||
|
</div>
|
||||||
|
</Popup>
|
||||||
|
</Marker>
|
||||||
|
))}
|
||||||
|
</MapContainer>
|
||||||
|
);
|
||||||
|
}
|
||||||
40
astro/src/components/primitives/MapEmbed.tsx
Normal file
40
astro/src/components/primitives/MapEmbed.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
interface MapEmbedProps {
|
||||||
|
className?: string;
|
||||||
|
onOpenMap: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MapEmbed({ className, onOpenMap }: MapEmbedProps) {
|
||||||
|
return (
|
||||||
|
<div className={className}>
|
||||||
|
<div className="flex items-center justify-center gap-3 mb-4 2xl:mb-8">
|
||||||
|
<p
|
||||||
|
className="text-white text-3xl 2xl:text-5xl font-bold font-ember-and-fire"
|
||||||
|
style={{
|
||||||
|
textShadow: "0px 4px 4px rgba(0,0,0,0.25)"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
find an event near you
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<img
|
||||||
|
src="/compressed/ui/arrow.webp"
|
||||||
|
alt=""
|
||||||
|
className="w-[45px] md:w-[55px] h-[33px] md:h-[41px] translate-y-6 rotate-[6.2deg] z-50 select-none"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={onOpenMap}
|
||||||
|
className="relative transform rotate-[1.7deg] transition-transform hover:scale-105 w-[70vw] md:w-[50vw] xl:w-[442px] mx-auto cursor-pointer"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="/map/map-screenshot.png"
|
||||||
|
alt="Map screenshot"
|
||||||
|
className="w-full rounded-2xl shadow-[12px_12px_0px_0px_rgba(0,0,0,0.25)]"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MapEmbed;
|
||||||
80
astro/src/lib/events.ts
Normal file
80
astro/src/lib/events.ts
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
import 'dotenv/config';
|
||||||
|
const { AIRTABLE_API_KEY, AIRTABLE_BASE_ID } = process.env;
|
||||||
|
|
||||||
|
import Airtable from 'airtable';
|
||||||
|
let airtableBase: any = null;
|
||||||
|
|
||||||
|
if (AIRTABLE_API_KEY && AIRTABLE_BASE_ID) {
|
||||||
|
airtableBase = new Airtable({ apiKey: AIRTABLE_API_KEY }).base(AIRTABLE_BASE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EventLocation {
|
||||||
|
slug: string;
|
||||||
|
lat: number;
|
||||||
|
long: number;
|
||||||
|
event_name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AirtableRecord {
|
||||||
|
id: string;
|
||||||
|
fields: EventLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EventLocationWithDistance extends EventLocation {
|
||||||
|
distance: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchEventsLoc() {
|
||||||
|
return (await airtableBase('events').select({
|
||||||
|
view: 'Everything',
|
||||||
|
// filterByFormula: '{website_active} = 1',
|
||||||
|
fields: [
|
||||||
|
'slug', //string
|
||||||
|
'event_name', //string
|
||||||
|
'lat', //number
|
||||||
|
'long', //number
|
||||||
|
'website_active' //boolean
|
||||||
|
]
|
||||||
|
}).all()) as AirtableRecord[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Cache to avoid multiple geocoding during build
|
||||||
|
let cachedEvents: EventLocation[] | null = null;
|
||||||
|
|
||||||
|
export async function loadEventsLoc(): Promise<EventLocation[]> {
|
||||||
|
// do nothing if the API keys aren't set
|
||||||
|
if (!AIRTABLE_API_KEY || !AIRTABLE_BASE_ID) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedEvents) {
|
||||||
|
return cachedEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Geocoding all events")
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Fetch all approved events from Airtable with pagination
|
||||||
|
const locations = await fetchEventsLoc();
|
||||||
|
|
||||||
|
return locations.map(location => location.fields);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch event data:', error);
|
||||||
|
cachedEvents = [];
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Haversine formula to calculate distance between two points in miles
|
||||||
|
export function calculateDistance(lat1: number, lng1: number, lat2: number, lng2: number): number {
|
||||||
|
const R = 3959; // Earth's radius in miles
|
||||||
|
const dLat = (lat2 - lat1) * Math.PI / 180;
|
||||||
|
const dLng = (lng2 - lng1) * Math.PI / 180;
|
||||||
|
const a =
|
||||||
|
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||||
|
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
|
||||||
|
Math.sin(dLng / 2) * Math.sin(dLng / 2);
|
||||||
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||||
|
return R * c; // Distance in miles
|
||||||
|
}
|
||||||
|
|
@ -18,21 +18,6 @@ export async function getSatelliteData(slug: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setSatelliteData(slug: string, data: any) {
|
|
||||||
return prisma.satellite.upsert({
|
|
||||||
where: {
|
|
||||||
slug,
|
|
||||||
},
|
|
||||||
create: {
|
|
||||||
slug,
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
update: {
|
|
||||||
data,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SatelliteContent = {
|
export type SatelliteContent = {
|
||||||
hero: {
|
hero: {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import "../styles/global.css";
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
import Satellite from "../components/pages/Satellite";
|
import Satellite from "../components/pages/Satellite";
|
||||||
import { getSatelliteData, getSatelliteSlugs } from "../lib/satellite";
|
import { getSatelliteData, getSatelliteSlugs } from "../lib/satellite";
|
||||||
|
import UnderConstruction from "../components/pages/UnderConstruction";
|
||||||
|
import type { SatelliteContent } from "../lib/satellite";
|
||||||
|
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
const { slug } = Astro.params;
|
const { slug } = Astro.params;
|
||||||
|
|
@ -48,6 +50,7 @@ const satelliteData = await getSatelliteData(slug);
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Satellite client:only="react" slug={slug} content={satelliteData.data} />
|
{!satelliteData?.active && <UnderConstruction client:only="react" event_name={slug} record_id={satelliteData?.recordId} />}
|
||||||
|
{satelliteData?.active && <Satellite client:only="react" slug={slug} content={satelliteData.data as SatelliteContent} />}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
---
|
---
|
||||||
import "../styles/global.css";
|
import "../styles/global.css";
|
||||||
import App from "../components/pages/App"
|
import App from "../components/pages/App"
|
||||||
|
|
||||||
|
import { loadEventsLoc } from "../lib/events";
|
||||||
|
|
||||||
|
const events = await loadEventsLoc();
|
||||||
---
|
---
|
||||||
|
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
|
|
@ -35,6 +39,6 @@ import App from "../components/pages/App"
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<App client:only="react" />
|
<App client:only="react" events={events} />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
27
astro/src/pages/map.astro
Normal file
27
astro/src/pages/map.astro
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
import "../styles/global.css";
|
||||||
|
import { Map } from "../components/primitives/Map";
|
||||||
|
import { loadEventsLoc } from "../lib/events";
|
||||||
|
|
||||||
|
const events = await loadEventsLoc();
|
||||||
|
---
|
||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Map - Hack Club Campfire</title>
|
||||||
|
|
||||||
|
<!-- OpenGraph meta tags -->
|
||||||
|
<meta property="og:title" content="Campfire Map" />
|
||||||
|
<meta property="og:description" content="Find Campfire events happening around the world!" />
|
||||||
|
<meta property="og:image" content="/og-banner.png" />
|
||||||
|
<meta property="og:url" content="https://campfire.hackclub.com/map" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
</head>
|
||||||
|
<body class="w-screen h-screen">
|
||||||
|
<Map client:only="react" events={events} className="w-full h-full" />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
66
astro/src/styles/map.css
Normal file
66
astro/src/styles/map.css
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
.leaflet-container {
|
||||||
|
background: linear-gradient(135deg, #CCF4FD 0%, #B8D9F8 100%) !important;
|
||||||
|
border-radius: 16px !important;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-zoom a {
|
||||||
|
background: #44DBC8 !important;
|
||||||
|
border: 2px solid #3CC2AF !important;
|
||||||
|
color: white !important;
|
||||||
|
border-radius: 8px !important;
|
||||||
|
box-shadow: 0 4px 12px rgba(68, 219, 200, 0.3) !important;
|
||||||
|
transition: all 0.2s ease-in-out !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-zoom a:hover {
|
||||||
|
background: #3CC2AF !important;
|
||||||
|
transform: translateY(-1px) !important;
|
||||||
|
box-shadow: 0 6px 16px rgba(68, 219, 200, 0.4) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-attribution {
|
||||||
|
background: rgba(252, 247, 196, 0.9) !important;
|
||||||
|
border: 1px solid #D3B180 !important;
|
||||||
|
border-radius: 8px !important;
|
||||||
|
color: #78531D !important;
|
||||||
|
font-family: 'Atkinson Hyperlegible', system-ui, sans-serif !important;
|
||||||
|
backdrop-filter: blur(8px) !important;
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-attribution a {
|
||||||
|
color: #4477A3 !important;
|
||||||
|
text-decoration: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-attribution a:hover {
|
||||||
|
color: #44DBC8 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-popup .leaflet-popup-content-wrapper {
|
||||||
|
background: #FFFBDF !important;
|
||||||
|
border: 1px solid #D3B180 !important;
|
||||||
|
border-radius: 8px !important;
|
||||||
|
box-shadow: 0 4px 8px rgba(211, 177, 128, 0.15) !important;
|
||||||
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-popup .leaflet-popup-content {
|
||||||
|
margin: 8px 12px !important;
|
||||||
|
color: #78531D !important;
|
||||||
|
font-size: 14px !important;
|
||||||
|
font-weight: 500 !important;
|
||||||
|
line-height: 1.2 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-popup .leaflet-popup-tip {
|
||||||
|
background: #FFFBDF !important;
|
||||||
|
border: 1px solid #D3B180 !important;
|
||||||
|
border-top: none !important;
|
||||||
|
border-right: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-tile-pane {
|
||||||
|
filter: hue-rotate(5deg) saturate(0.8) brightness(1.1) !important;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- A unique constraint covering the columns `[recordId]` on the table `Satellite` will be added. If there are existing duplicate values, this will fail.
|
||||||
|
- Added the required column `recordId` to the `Satellite` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Satellite" ADD COLUMN "recordId" TEXT NOT NULL;
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Satellite_recordId_key" ON "Satellite"("recordId");
|
||||||
|
|
@ -15,6 +15,7 @@ datasource db {
|
||||||
|
|
||||||
model Satellite {
|
model Satellite {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
|
recordId String @unique
|
||||||
slug String @unique
|
slug String @unique
|
||||||
data Json
|
data Json
|
||||||
active Boolean @default(true)
|
active Boolean @default(true)
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = {
|
||||||
"clientVersion": "7.2.0",
|
"clientVersion": "7.2.0",
|
||||||
"engineVersion": "0c8ef2ce45c83248ab3df073180d5eda9e8be7a3",
|
"engineVersion": "0c8ef2ce45c83248ab3df073180d5eda9e8be7a3",
|
||||||
"activeProvider": "postgresql",
|
"activeProvider": "postgresql",
|
||||||
"inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?\n// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../src/generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\nmodel Satellite {\n id Int @id @default(autoincrement())\n slug String @unique\n data Json\n active Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n",
|
"inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\n// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?\n// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../src/generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\nmodel Satellite {\n id Int @id @default(autoincrement())\n recordId String @unique\n slug String @unique\n data Json\n active Boolean @default(true)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n",
|
||||||
"runtimeDataModel": {
|
"runtimeDataModel": {
|
||||||
"models": {},
|
"models": {},
|
||||||
"enums": {},
|
"enums": {},
|
||||||
|
|
@ -28,7 +28,7 @@ const config: runtime.GetPrismaClientConfig = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config.runtimeDataModel = JSON.parse("{\"models\":{\"Satellite\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"slug\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"active\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
|
config.runtimeDataModel = JSON.parse("{\"models\":{\"Satellite\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"recordId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"slug\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"active\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}")
|
||||||
|
|
||||||
async function decodeBase64AsWasm(wasmBase64: string): Promise<WebAssembly.Module> {
|
async function decodeBase64AsWasm(wasmBase64: string): Promise<WebAssembly.Module> {
|
||||||
const { Buffer } = await import('node:buffer')
|
const { Buffer } = await import('node:buffer')
|
||||||
|
|
|
||||||
|
|
@ -519,6 +519,7 @@ export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof
|
||||||
|
|
||||||
export const SatelliteScalarFieldEnum = {
|
export const SatelliteScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
|
recordId: 'recordId',
|
||||||
slug: 'slug',
|
slug: 'slug',
|
||||||
data: 'data',
|
data: 'data',
|
||||||
active: 'active',
|
active: 'active',
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ export type TransactionIsolationLevel = (typeof TransactionIsolationLevel)[keyof
|
||||||
|
|
||||||
export const SatelliteScalarFieldEnum = {
|
export const SatelliteScalarFieldEnum = {
|
||||||
id: 'id',
|
id: 'id',
|
||||||
|
recordId: 'recordId',
|
||||||
slug: 'slug',
|
slug: 'slug',
|
||||||
data: 'data',
|
data: 'data',
|
||||||
active: 'active',
|
active: 'active',
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ export type SatelliteSumAggregateOutputType = {
|
||||||
|
|
||||||
export type SatelliteMinAggregateOutputType = {
|
export type SatelliteMinAggregateOutputType = {
|
||||||
id: number | null
|
id: number | null
|
||||||
|
recordId: string | null
|
||||||
slug: string | null
|
slug: string | null
|
||||||
active: boolean | null
|
active: boolean | null
|
||||||
createdAt: Date | null
|
createdAt: Date | null
|
||||||
|
|
@ -44,6 +45,7 @@ export type SatelliteMinAggregateOutputType = {
|
||||||
|
|
||||||
export type SatelliteMaxAggregateOutputType = {
|
export type SatelliteMaxAggregateOutputType = {
|
||||||
id: number | null
|
id: number | null
|
||||||
|
recordId: string | null
|
||||||
slug: string | null
|
slug: string | null
|
||||||
active: boolean | null
|
active: boolean | null
|
||||||
createdAt: Date | null
|
createdAt: Date | null
|
||||||
|
|
@ -52,6 +54,7 @@ export type SatelliteMaxAggregateOutputType = {
|
||||||
|
|
||||||
export type SatelliteCountAggregateOutputType = {
|
export type SatelliteCountAggregateOutputType = {
|
||||||
id: number
|
id: number
|
||||||
|
recordId: number
|
||||||
slug: number
|
slug: number
|
||||||
data: number
|
data: number
|
||||||
active: number
|
active: number
|
||||||
|
|
@ -71,6 +74,7 @@ export type SatelliteSumAggregateInputType = {
|
||||||
|
|
||||||
export type SatelliteMinAggregateInputType = {
|
export type SatelliteMinAggregateInputType = {
|
||||||
id?: true
|
id?: true
|
||||||
|
recordId?: true
|
||||||
slug?: true
|
slug?: true
|
||||||
active?: true
|
active?: true
|
||||||
createdAt?: true
|
createdAt?: true
|
||||||
|
|
@ -79,6 +83,7 @@ export type SatelliteMinAggregateInputType = {
|
||||||
|
|
||||||
export type SatelliteMaxAggregateInputType = {
|
export type SatelliteMaxAggregateInputType = {
|
||||||
id?: true
|
id?: true
|
||||||
|
recordId?: true
|
||||||
slug?: true
|
slug?: true
|
||||||
active?: true
|
active?: true
|
||||||
createdAt?: true
|
createdAt?: true
|
||||||
|
|
@ -87,6 +92,7 @@ export type SatelliteMaxAggregateInputType = {
|
||||||
|
|
||||||
export type SatelliteCountAggregateInputType = {
|
export type SatelliteCountAggregateInputType = {
|
||||||
id?: true
|
id?: true
|
||||||
|
recordId?: true
|
||||||
slug?: true
|
slug?: true
|
||||||
data?: true
|
data?: true
|
||||||
active?: true
|
active?: true
|
||||||
|
|
@ -183,6 +189,7 @@ export type SatelliteGroupByArgs<ExtArgs extends runtime.Types.Extensions.Intern
|
||||||
|
|
||||||
export type SatelliteGroupByOutputType = {
|
export type SatelliteGroupByOutputType = {
|
||||||
id: number
|
id: number
|
||||||
|
recordId: string
|
||||||
slug: string
|
slug: string
|
||||||
data: runtime.JsonValue
|
data: runtime.JsonValue
|
||||||
active: boolean
|
active: boolean
|
||||||
|
|
@ -215,6 +222,7 @@ export type SatelliteWhereInput = {
|
||||||
OR?: Prisma.SatelliteWhereInput[]
|
OR?: Prisma.SatelliteWhereInput[]
|
||||||
NOT?: Prisma.SatelliteWhereInput | Prisma.SatelliteWhereInput[]
|
NOT?: Prisma.SatelliteWhereInput | Prisma.SatelliteWhereInput[]
|
||||||
id?: Prisma.IntFilter<"Satellite"> | number
|
id?: Prisma.IntFilter<"Satellite"> | number
|
||||||
|
recordId?: Prisma.StringFilter<"Satellite"> | string
|
||||||
slug?: Prisma.StringFilter<"Satellite"> | string
|
slug?: Prisma.StringFilter<"Satellite"> | string
|
||||||
data?: Prisma.JsonFilter<"Satellite">
|
data?: Prisma.JsonFilter<"Satellite">
|
||||||
active?: Prisma.BoolFilter<"Satellite"> | boolean
|
active?: Prisma.BoolFilter<"Satellite"> | boolean
|
||||||
|
|
@ -224,6 +232,7 @@ export type SatelliteWhereInput = {
|
||||||
|
|
||||||
export type SatelliteOrderByWithRelationInput = {
|
export type SatelliteOrderByWithRelationInput = {
|
||||||
id?: Prisma.SortOrder
|
id?: Prisma.SortOrder
|
||||||
|
recordId?: Prisma.SortOrder
|
||||||
slug?: Prisma.SortOrder
|
slug?: Prisma.SortOrder
|
||||||
data?: Prisma.SortOrder
|
data?: Prisma.SortOrder
|
||||||
active?: Prisma.SortOrder
|
active?: Prisma.SortOrder
|
||||||
|
|
@ -233,6 +242,7 @@ export type SatelliteOrderByWithRelationInput = {
|
||||||
|
|
||||||
export type SatelliteWhereUniqueInput = Prisma.AtLeast<{
|
export type SatelliteWhereUniqueInput = Prisma.AtLeast<{
|
||||||
id?: number
|
id?: number
|
||||||
|
recordId?: string
|
||||||
slug?: string
|
slug?: string
|
||||||
AND?: Prisma.SatelliteWhereInput | Prisma.SatelliteWhereInput[]
|
AND?: Prisma.SatelliteWhereInput | Prisma.SatelliteWhereInput[]
|
||||||
OR?: Prisma.SatelliteWhereInput[]
|
OR?: Prisma.SatelliteWhereInput[]
|
||||||
|
|
@ -241,10 +251,11 @@ export type SatelliteWhereUniqueInput = Prisma.AtLeast<{
|
||||||
active?: Prisma.BoolFilter<"Satellite"> | boolean
|
active?: Prisma.BoolFilter<"Satellite"> | boolean
|
||||||
createdAt?: Prisma.DateTimeFilter<"Satellite"> | Date | string
|
createdAt?: Prisma.DateTimeFilter<"Satellite"> | Date | string
|
||||||
updatedAt?: Prisma.DateTimeFilter<"Satellite"> | Date | string
|
updatedAt?: Prisma.DateTimeFilter<"Satellite"> | Date | string
|
||||||
}, "id" | "slug">
|
}, "id" | "recordId" | "slug">
|
||||||
|
|
||||||
export type SatelliteOrderByWithAggregationInput = {
|
export type SatelliteOrderByWithAggregationInput = {
|
||||||
id?: Prisma.SortOrder
|
id?: Prisma.SortOrder
|
||||||
|
recordId?: Prisma.SortOrder
|
||||||
slug?: Prisma.SortOrder
|
slug?: Prisma.SortOrder
|
||||||
data?: Prisma.SortOrder
|
data?: Prisma.SortOrder
|
||||||
active?: Prisma.SortOrder
|
active?: Prisma.SortOrder
|
||||||
|
|
@ -262,6 +273,7 @@ export type SatelliteScalarWhereWithAggregatesInput = {
|
||||||
OR?: Prisma.SatelliteScalarWhereWithAggregatesInput[]
|
OR?: Prisma.SatelliteScalarWhereWithAggregatesInput[]
|
||||||
NOT?: Prisma.SatelliteScalarWhereWithAggregatesInput | Prisma.SatelliteScalarWhereWithAggregatesInput[]
|
NOT?: Prisma.SatelliteScalarWhereWithAggregatesInput | Prisma.SatelliteScalarWhereWithAggregatesInput[]
|
||||||
id?: Prisma.IntWithAggregatesFilter<"Satellite"> | number
|
id?: Prisma.IntWithAggregatesFilter<"Satellite"> | number
|
||||||
|
recordId?: Prisma.StringWithAggregatesFilter<"Satellite"> | string
|
||||||
slug?: Prisma.StringWithAggregatesFilter<"Satellite"> | string
|
slug?: Prisma.StringWithAggregatesFilter<"Satellite"> | string
|
||||||
data?: Prisma.JsonWithAggregatesFilter<"Satellite">
|
data?: Prisma.JsonWithAggregatesFilter<"Satellite">
|
||||||
active?: Prisma.BoolWithAggregatesFilter<"Satellite"> | boolean
|
active?: Prisma.BoolWithAggregatesFilter<"Satellite"> | boolean
|
||||||
|
|
@ -270,6 +282,7 @@ export type SatelliteScalarWhereWithAggregatesInput = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SatelliteCreateInput = {
|
export type SatelliteCreateInput = {
|
||||||
|
recordId: string
|
||||||
slug: string
|
slug: string
|
||||||
data: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
data: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
||||||
active?: boolean
|
active?: boolean
|
||||||
|
|
@ -279,6 +292,7 @@ export type SatelliteCreateInput = {
|
||||||
|
|
||||||
export type SatelliteUncheckedCreateInput = {
|
export type SatelliteUncheckedCreateInput = {
|
||||||
id?: number
|
id?: number
|
||||||
|
recordId: string
|
||||||
slug: string
|
slug: string
|
||||||
data: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
data: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
||||||
active?: boolean
|
active?: boolean
|
||||||
|
|
@ -287,6 +301,7 @@ export type SatelliteUncheckedCreateInput = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SatelliteUpdateInput = {
|
export type SatelliteUpdateInput = {
|
||||||
|
recordId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
slug?: Prisma.StringFieldUpdateOperationsInput | string
|
slug?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
data?: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
data?: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
||||||
active?: Prisma.BoolFieldUpdateOperationsInput | boolean
|
active?: Prisma.BoolFieldUpdateOperationsInput | boolean
|
||||||
|
|
@ -296,6 +311,7 @@ export type SatelliteUpdateInput = {
|
||||||
|
|
||||||
export type SatelliteUncheckedUpdateInput = {
|
export type SatelliteUncheckedUpdateInput = {
|
||||||
id?: Prisma.IntFieldUpdateOperationsInput | number
|
id?: Prisma.IntFieldUpdateOperationsInput | number
|
||||||
|
recordId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
slug?: Prisma.StringFieldUpdateOperationsInput | string
|
slug?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
data?: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
data?: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
||||||
active?: Prisma.BoolFieldUpdateOperationsInput | boolean
|
active?: Prisma.BoolFieldUpdateOperationsInput | boolean
|
||||||
|
|
@ -305,6 +321,7 @@ export type SatelliteUncheckedUpdateInput = {
|
||||||
|
|
||||||
export type SatelliteCreateManyInput = {
|
export type SatelliteCreateManyInput = {
|
||||||
id?: number
|
id?: number
|
||||||
|
recordId: string
|
||||||
slug: string
|
slug: string
|
||||||
data: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
data: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
||||||
active?: boolean
|
active?: boolean
|
||||||
|
|
@ -313,6 +330,7 @@ export type SatelliteCreateManyInput = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SatelliteUpdateManyMutationInput = {
|
export type SatelliteUpdateManyMutationInput = {
|
||||||
|
recordId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
slug?: Prisma.StringFieldUpdateOperationsInput | string
|
slug?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
data?: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
data?: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
||||||
active?: Prisma.BoolFieldUpdateOperationsInput | boolean
|
active?: Prisma.BoolFieldUpdateOperationsInput | boolean
|
||||||
|
|
@ -322,6 +340,7 @@ export type SatelliteUpdateManyMutationInput = {
|
||||||
|
|
||||||
export type SatelliteUncheckedUpdateManyInput = {
|
export type SatelliteUncheckedUpdateManyInput = {
|
||||||
id?: Prisma.IntFieldUpdateOperationsInput | number
|
id?: Prisma.IntFieldUpdateOperationsInput | number
|
||||||
|
recordId?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
slug?: Prisma.StringFieldUpdateOperationsInput | string
|
slug?: Prisma.StringFieldUpdateOperationsInput | string
|
||||||
data?: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
data?: Prisma.JsonNullValueInput | runtime.InputJsonValue
|
||||||
active?: Prisma.BoolFieldUpdateOperationsInput | boolean
|
active?: Prisma.BoolFieldUpdateOperationsInput | boolean
|
||||||
|
|
@ -331,6 +350,7 @@ export type SatelliteUncheckedUpdateManyInput = {
|
||||||
|
|
||||||
export type SatelliteCountOrderByAggregateInput = {
|
export type SatelliteCountOrderByAggregateInput = {
|
||||||
id?: Prisma.SortOrder
|
id?: Prisma.SortOrder
|
||||||
|
recordId?: Prisma.SortOrder
|
||||||
slug?: Prisma.SortOrder
|
slug?: Prisma.SortOrder
|
||||||
data?: Prisma.SortOrder
|
data?: Prisma.SortOrder
|
||||||
active?: Prisma.SortOrder
|
active?: Prisma.SortOrder
|
||||||
|
|
@ -344,6 +364,7 @@ export type SatelliteAvgOrderByAggregateInput = {
|
||||||
|
|
||||||
export type SatelliteMaxOrderByAggregateInput = {
|
export type SatelliteMaxOrderByAggregateInput = {
|
||||||
id?: Prisma.SortOrder
|
id?: Prisma.SortOrder
|
||||||
|
recordId?: Prisma.SortOrder
|
||||||
slug?: Prisma.SortOrder
|
slug?: Prisma.SortOrder
|
||||||
active?: Prisma.SortOrder
|
active?: Prisma.SortOrder
|
||||||
createdAt?: Prisma.SortOrder
|
createdAt?: Prisma.SortOrder
|
||||||
|
|
@ -352,6 +373,7 @@ export type SatelliteMaxOrderByAggregateInput = {
|
||||||
|
|
||||||
export type SatelliteMinOrderByAggregateInput = {
|
export type SatelliteMinOrderByAggregateInput = {
|
||||||
id?: Prisma.SortOrder
|
id?: Prisma.SortOrder
|
||||||
|
recordId?: Prisma.SortOrder
|
||||||
slug?: Prisma.SortOrder
|
slug?: Prisma.SortOrder
|
||||||
active?: Prisma.SortOrder
|
active?: Prisma.SortOrder
|
||||||
createdAt?: Prisma.SortOrder
|
createdAt?: Prisma.SortOrder
|
||||||
|
|
@ -386,6 +408,7 @@ export type IntFieldUpdateOperationsInput = {
|
||||||
|
|
||||||
export type SatelliteSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
export type SatelliteSelect<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
||||||
id?: boolean
|
id?: boolean
|
||||||
|
recordId?: boolean
|
||||||
slug?: boolean
|
slug?: boolean
|
||||||
data?: boolean
|
data?: boolean
|
||||||
active?: boolean
|
active?: boolean
|
||||||
|
|
@ -395,6 +418,7 @@ export type SatelliteSelect<ExtArgs extends runtime.Types.Extensions.InternalArg
|
||||||
|
|
||||||
export type SatelliteSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
export type SatelliteSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
||||||
id?: boolean
|
id?: boolean
|
||||||
|
recordId?: boolean
|
||||||
slug?: boolean
|
slug?: boolean
|
||||||
data?: boolean
|
data?: boolean
|
||||||
active?: boolean
|
active?: boolean
|
||||||
|
|
@ -404,6 +428,7 @@ export type SatelliteSelectCreateManyAndReturn<ExtArgs extends runtime.Types.Ext
|
||||||
|
|
||||||
export type SatelliteSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
export type SatelliteSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetSelect<{
|
||||||
id?: boolean
|
id?: boolean
|
||||||
|
recordId?: boolean
|
||||||
slug?: boolean
|
slug?: boolean
|
||||||
data?: boolean
|
data?: boolean
|
||||||
active?: boolean
|
active?: boolean
|
||||||
|
|
@ -413,6 +438,7 @@ export type SatelliteSelectUpdateManyAndReturn<ExtArgs extends runtime.Types.Ext
|
||||||
|
|
||||||
export type SatelliteSelectScalar = {
|
export type SatelliteSelectScalar = {
|
||||||
id?: boolean
|
id?: boolean
|
||||||
|
recordId?: boolean
|
||||||
slug?: boolean
|
slug?: boolean
|
||||||
data?: boolean
|
data?: boolean
|
||||||
active?: boolean
|
active?: boolean
|
||||||
|
|
@ -420,13 +446,14 @@ export type SatelliteSelectScalar = {
|
||||||
updatedAt?: boolean
|
updatedAt?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SatelliteOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "slug" | "data" | "active" | "createdAt" | "updatedAt", ExtArgs["result"]["satellite"]>
|
export type SatelliteOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "recordId" | "slug" | "data" | "active" | "createdAt" | "updatedAt", ExtArgs["result"]["satellite"]>
|
||||||
|
|
||||||
export type $SatellitePayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
export type $SatellitePayload<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
|
||||||
name: "Satellite"
|
name: "Satellite"
|
||||||
objects: {}
|
objects: {}
|
||||||
scalars: runtime.Types.Extensions.GetPayloadResult<{
|
scalars: runtime.Types.Extensions.GetPayloadResult<{
|
||||||
id: number
|
id: number
|
||||||
|
recordId: string
|
||||||
slug: string
|
slug: string
|
||||||
data: runtime.JsonValue
|
data: runtime.JsonValue
|
||||||
active: boolean
|
active: boolean
|
||||||
|
|
@ -856,6 +883,7 @@ export interface Prisma__SatelliteClient<T, Null = never, ExtArgs extends runtim
|
||||||
*/
|
*/
|
||||||
export interface SatelliteFieldRefs {
|
export interface SatelliteFieldRefs {
|
||||||
readonly id: Prisma.FieldRef<"Satellite", 'Int'>
|
readonly id: Prisma.FieldRef<"Satellite", 'Int'>
|
||||||
|
readonly recordId: Prisma.FieldRef<"Satellite", 'String'>
|
||||||
readonly slug: Prisma.FieldRef<"Satellite", 'String'>
|
readonly slug: Prisma.FieldRef<"Satellite", 'String'>
|
||||||
readonly data: Prisma.FieldRef<"Satellite", 'Json'>
|
readonly data: Prisma.FieldRef<"Satellite", 'Json'>
|
||||||
readonly active: Prisma.FieldRef<"Satellite", 'Boolean'>
|
readonly active: Prisma.FieldRef<"Satellite", 'Boolean'>
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@ Airtable.configure({
|
||||||
endpointUrl: 'https://api.airtable.com',
|
endpointUrl: 'https://api.airtable.com',
|
||||||
});
|
});
|
||||||
const base = Airtable.base(process.env.AIRTABLE_BASE_ID!);
|
const base = Airtable.base(process.env.AIRTABLE_BASE_ID!);
|
||||||
const eventsTable = base('Event');
|
const eventsTable = base('events');
|
||||||
|
|
||||||
export async function listOfEventWebsiteData() {
|
export async function listOfEventWebsiteData() {
|
||||||
return (await eventsTable.select({
|
return (await eventsTable.select({
|
||||||
view: 'Everything',
|
view: 'Everything',
|
||||||
filterByFormula: '{website_active} = 1',
|
// filterByFormula: '{website_active} = 1',
|
||||||
fields: [
|
fields: [
|
||||||
'slug', //string
|
'slug', //string
|
||||||
'website_json', //string
|
'website_json', //string
|
||||||
|
|
@ -38,8 +38,8 @@ class AirtableSyncWorker {
|
||||||
for (const record of records) {
|
for (const record of records) {
|
||||||
const slug = record.get('slug') as string;
|
const slug = record.get('slug') as string;
|
||||||
const websiteJson = record.get('website_json') as string;
|
const websiteJson = record.get('website_json') as string;
|
||||||
const websiteActive = record.get('website_active') as boolean;
|
const websiteActive = record.get('website_active') === true;
|
||||||
|
|
||||||
if (!slug) {
|
if (!slug) {
|
||||||
console.warn(`Skipping record ${record.id}: missing slug`);
|
console.warn(`Skipping record ${record.id}: missing slug`);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -56,18 +56,20 @@ class AirtableSyncWorker {
|
||||||
await prisma.satellite.upsert({
|
await prisma.satellite.upsert({
|
||||||
where: { slug },
|
where: { slug },
|
||||||
update: {
|
update: {
|
||||||
|
recordId: record.id,
|
||||||
data,
|
data,
|
||||||
active: websiteActive,
|
active: websiteActive,
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
|
recordId: record.id,
|
||||||
slug,
|
slug,
|
||||||
data,
|
data,
|
||||||
active: websiteActive,
|
active: websiteActive,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`✓ Synced: ${slug}`);
|
console.log(`✓ Synced: ${slug} - Active: ${websiteActive}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const inactiveCount = await prisma.satellite.updateMany({
|
const inactiveCount = await prisma.satellite.updateMany({
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue