Update microsite rendering and add environment example.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
709607aeca
commit
d9270632dc
|
|
@ -0,0 +1,8 @@
|
|||
# Local development — Vite proxies /api to VITE_API_PROXY_TARGET
|
||||
VITE_API_BASE_URL=/api
|
||||
VITE_API_PROXY_TARGET=http://localhost:3001
|
||||
VITE_PUBLIC_WEB_BASE=http://localhost:5175
|
||||
|
||||
# Production (see .env.production — used automatically by `npm run build`)
|
||||
# VITE_API_BASE_URL=https://api.eventbuzz.live/api
|
||||
# VITE_PUBLIC_WEB_BASE=https://web.eventbuzz.live
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
"name": "eventbuzz-web",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"bootstrap-icons": "^1.13.1",
|
||||
"flatpickr": "^4.6.13",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
|
|
@ -1275,6 +1276,22 @@
|
|||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bootstrap-icons": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.13.1.tgz",
|
||||
"integrity": "sha512-ijombt4v6bv5CLeXvRWKy7CuM3TRTuPEuGaGKvTV5cz65rQSY8RQ2JcHt6b90cBBAC7s8fsf2EkQDldzCoXUjw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/twbs"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/bootstrap"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.28.4",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
"preview": "vite preview --port 5175"
|
||||
},
|
||||
"dependencies": {
|
||||
"bootstrap-icons": "^1.13.1",
|
||||
"flatpickr": "^4.6.13",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,21 @@ function str(v: unknown, fallback = ''): string {
|
|||
return v != null ? String(v).trim() : fallback;
|
||||
}
|
||||
|
||||
function isRegisterLabel(label: string): boolean {
|
||||
return /\bregister\b/i.test(label);
|
||||
}
|
||||
|
||||
function looksLikeRegistrationUrl(url: string): boolean {
|
||||
return /\/register\/?$/i.test(url) || /\/form\/[a-f0-9]{24}\/?$/i.test(url);
|
||||
}
|
||||
|
||||
function resolveRegistrationCtaUrl(label: string, configuredUrl: unknown, registrationUrl: string): string {
|
||||
const configured = str(configuredUrl);
|
||||
const wantsRegistration = isRegisterLabel(label) || looksLikeRegistrationUrl(configured);
|
||||
if (wantsRegistration) return registrationUrl;
|
||||
return configured || '#';
|
||||
}
|
||||
|
||||
function HeaderSection({ section, ctx }: { section: MicrositeSection; ctx: Ctx }) {
|
||||
const c = section.config;
|
||||
const logoText = str(c.logoText, ctx.data.event.name);
|
||||
|
|
@ -40,6 +55,7 @@ function HeaderSection({ section, ctx }: { section: MicrositeSection; ctx: Ctx }
|
|||
const label = str(item.label);
|
||||
const url = str(item.url, '#');
|
||||
const isReg = label.toLowerCase() === 'register';
|
||||
if (isReg && !ctx.registrationUrl) return null;
|
||||
return (
|
||||
<li key={i}>
|
||||
<a
|
||||
|
|
@ -59,13 +75,13 @@ function HeaderSection({ section, ctx }: { section: MicrositeSection; ctx: Ctx }
|
|||
);
|
||||
}
|
||||
|
||||
function BannerSection({ section }: { section: MicrositeSection }) {
|
||||
function BannerSection({ section, ctx }: { section: MicrositeSection; ctx: Ctx }) {
|
||||
const c = section.config;
|
||||
const headline = str(c.headline, 'Welcome');
|
||||
const subtext = str(c.subtext);
|
||||
const heroMetaLine = str(c.heroMetaLine);
|
||||
const ctaText = str(c.ctaText);
|
||||
const ctaUrl = str(c.ctaUrl, '#');
|
||||
const ctaUrl = resolveRegistrationCtaUrl(ctaText, c.ctaUrl, ctx.registrationUrl);
|
||||
const bgImage = str(c.backgroundImage);
|
||||
const secText = str(c.secondaryCtaText);
|
||||
const secUrl = str(c.secondaryCtaUrl, '#schedule');
|
||||
|
|
@ -80,7 +96,7 @@ function BannerSection({ section }: { section: MicrositeSection }) {
|
|||
{subtext ? <p className="eb-hero-intro mb-4">{subtext}</p> : null}
|
||||
{(ctaText || secText) && (
|
||||
<div className="eb-hero-cta">
|
||||
{ctaText ? (
|
||||
{ctaText && ctaUrl ? (
|
||||
<a className="btn btn-primary btn-lg" href={ctaUrl}>
|
||||
{ctaText}
|
||||
</a>
|
||||
|
|
@ -141,13 +157,13 @@ function CountdownSection({ section, ctx }: { section: MicrositeSection; ctx: Ct
|
|||
);
|
||||
}
|
||||
|
||||
function AboutSection({ section }: { section: MicrositeSection }) {
|
||||
function AboutSection({ section, ctx }: { section: MicrositeSection; ctx: Ctx }) {
|
||||
const c = section.config;
|
||||
const title = str(c.title, 'About');
|
||||
const body = str(c.body);
|
||||
const body = str(c.body) || str(c.lead);
|
||||
const bullets = Array.isArray(c.bullets) ? (c.bullets as string[]) : [];
|
||||
const ctaText = str(c.ctaText);
|
||||
const ctaUrl = str(c.ctaUrl, '#');
|
||||
const ctaText = str(c.ctaText) || str(c.ctaLabel);
|
||||
const ctaUrl = resolveRegistrationCtaUrl(ctaText, c.ctaUrl, ctx.registrationUrl);
|
||||
|
||||
return (
|
||||
<section id="about" className="py-5 eb-section-light">
|
||||
|
|
@ -161,7 +177,7 @@ function AboutSection({ section }: { section: MicrositeSection }) {
|
|||
))}
|
||||
</ul>
|
||||
) : null}
|
||||
{ctaText ? (
|
||||
{ctaText && ctaUrl ? (
|
||||
<div className="text-center mt-4">
|
||||
<a className="btn btn-primary btn-lg" href={ctaUrl}>
|
||||
{ctaText}
|
||||
|
|
@ -427,40 +443,27 @@ function AboutSection({ section }: { section: MicrositeSection }) {
|
|||
// );
|
||||
// }
|
||||
function AgendaSection({
|
||||
|
||||
section,
|
||||
items,
|
||||
ctx,
|
||||
}: {
|
||||
|
||||
section: MicrositeSection;
|
||||
items: AgendaItem[];
|
||||
ctx: Ctx;
|
||||
}) {
|
||||
console.log("Items:",items);
|
||||
|
||||
|
||||
const title = str(section.config.title, "Schedule");
|
||||
const title = str(section.config.title, 'Schedule');
|
||||
|
||||
const list = items.length
|
||||
? items
|
||||
: [{ title: "Session 1", time: "9:00 AM", track: "Main", date: "" }];
|
||||
: [{ title: 'Session 1', time: '9:00 AM', track: 'Main', date: '' }];
|
||||
|
||||
// Get unique dates
|
||||
const dates = [...new Set(list.map((item) => item.date).filter(Boolean))];
|
||||
|
||||
// Selected day
|
||||
const [selectedDate, setSelectedDate] = useState(
|
||||
dates.length ? dates[0] : ""
|
||||
);
|
||||
const [selectedDate, setSelectedDate] = useState(dates.length ? dates[0]! : '');
|
||||
|
||||
// Expanded accordion
|
||||
const [expandedIndex, setExpandedIndex] = useState<number | null>(null);
|
||||
|
||||
// Filter sessions according to selected date
|
||||
const filteredList = list.filter((item) => item.date === selectedDate);
|
||||
console.log("dates:", dates);
|
||||
console.log("selectedDate:", selectedDate);
|
||||
console.log("filteredList:", filteredList);
|
||||
console.log("list:", list);
|
||||
const filteredList = dates.length ? list.filter((item) => item.date === selectedDate) : list;
|
||||
return (
|
||||
<section id="schedule" className="eb-schedule-section section py-5">
|
||||
<div className="container">
|
||||
|
|
@ -728,9 +731,11 @@ console.log("list:", list);
|
|||
|
||||
{/* Action Buttons */}
|
||||
<div className="text-center mt-4">
|
||||
<a className="btn btn-primary btn-lg me-2" href="#register">
|
||||
Register
|
||||
</a>
|
||||
{ctx.registrationUrl ? (
|
||||
<a className="btn btn-primary btn-lg me-2" href={ctx.registrationUrl}>
|
||||
Register
|
||||
</a>
|
||||
) : null}
|
||||
<a className="btn btn-outline-secondary btn-lg" href="#hero">
|
||||
Back to top
|
||||
</a>
|
||||
|
|
@ -790,10 +795,12 @@ function SpeakersSection({ section, speakers }: { section: MicrositeSection; spe
|
|||
}
|
||||
|
||||
function RegisterLinksSection({ section, ctx }: { section: MicrositeSection; ctx: Ctx }) {
|
||||
if (!ctx.registrationUrl) return null;
|
||||
|
||||
const c = section.config;
|
||||
const title = str(c.title, 'Register');
|
||||
const primaryLabel = str(c.primaryLabel, 'Register Now');
|
||||
const primaryUrl = str(c.primaryUrl, ctx.registrationUrl);
|
||||
const primaryUrl = ctx.registrationUrl;
|
||||
const secondaryLabel = str(c.secondaryLabel);
|
||||
const secondaryUrl = str(c.secondaryUrl, '#');
|
||||
|
||||
|
|
@ -959,16 +966,18 @@ function CtaSection({ section, ctx }: { section: MicrositeSection; ctx: Ctx }) {
|
|||
const headline = str(c.headline, 'Join us');
|
||||
const subtext = str(c.subtext);
|
||||
const buttonLabel = str(c.buttonLabel, 'Register');
|
||||
const buttonUrl = str(c.buttonUrl, ctx.registrationUrl);
|
||||
const buttonUrl = resolveRegistrationCtaUrl(buttonLabel, c.buttonUrl, ctx.registrationUrl);
|
||||
|
||||
return (
|
||||
<section id="cta" className="py-5 text-white text-center" style={{ background: 'var(--eb-conf-primary)' }}>
|
||||
<div className="container">
|
||||
<h2 className="eb-section-heading text-white mb-3">{headline}</h2>
|
||||
{subtext ? <p className="lead mb-4">{subtext}</p> : null}
|
||||
<a className="btn btn-light btn-lg" href={buttonUrl}>
|
||||
{buttonLabel}
|
||||
</a>
|
||||
{buttonUrl && buttonUrl !== '#' ? (
|
||||
<a className="btn btn-light btn-lg" href={buttonUrl}>
|
||||
{buttonLabel}
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
|
@ -1068,9 +1077,11 @@ function TicketsSection({ section, ctx }: { section: MicrositeSection; ctx: Ctx
|
|||
<h3 style={{ marginTop: 0 }}>{str(tier.name)}</h3>
|
||||
<p style={{ fontSize: '1.5rem', fontWeight: 700, color: 'var(--eb-conf-primary)' }}>{str(tier.price)}</p>
|
||||
{tier.description ? <p className="text-muted">{tier.description}</p> : null}
|
||||
<a className="btn btn-primary" href={ctx.registrationUrl}>
|
||||
Register
|
||||
</a>
|
||||
{ctx.registrationUrl ? (
|
||||
<a className="btn btn-primary" href={ctx.registrationUrl}>
|
||||
Register
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
|
@ -1085,13 +1096,13 @@ export function SectionRenderer({ section, ctx }: { section: MicrositeSection; c
|
|||
case 'header':
|
||||
return <HeaderSection section={section} ctx={ctx} />;
|
||||
case 'banner':
|
||||
return <BannerSection section={section} />;
|
||||
return <BannerSection section={section} ctx={ctx} />;
|
||||
case 'countdown':
|
||||
return <CountdownSection section={section} ctx={ctx} />;
|
||||
case 'about':
|
||||
return <AboutSection section={section} />;
|
||||
return <AboutSection section={section} ctx={ctx} />;
|
||||
case 'agenda':
|
||||
return <AgendaSection section={section} items={ctx.data.agenda} />;
|
||||
return <AgendaSection section={section} items={ctx.data.agenda} ctx={ctx} />;
|
||||
case 'speakers':
|
||||
return <SpeakersSection section={section} speakers={ctx.data.speakers} />;
|
||||
case 'register_links':
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ export function EventMicrositePage() {
|
|||
);
|
||||
}
|
||||
|
||||
const registrationUrl = data.registrationUrl || `${PUBLIC_WEB_BASE}/event/${eventId}/register`;
|
||||
const registrationUrl = data.registrationFormId
|
||||
? `${PUBLIC_WEB_BASE}/event/${eventId}/form/${data.registrationFormId}`
|
||||
: '';
|
||||
const ctx = { data, eventId, registrationUrl };
|
||||
|
||||
if (data.micrositeHtml) {
|
||||
|
|
@ -53,7 +55,9 @@ export function EventMicrositePage() {
|
|||
);
|
||||
}
|
||||
|
||||
const sections = [...(data.sections || [])].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
||||
const sections = [...(data.sections || [])]
|
||||
.filter((section) => section.type !== 'sponsors')
|
||||
.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
||||
|
||||
return (
|
||||
<MicrositeLayout data={data}>
|
||||
|
|
|
|||
Loading…
Reference in New Issue