@@ -150,7 +150,7 @@ export function SessionQuestionsCard({
{viewAllTo ? (
View All
@@ -163,7 +163,7 @@ export function SessionQuestionsCard({
type="button"
onClick={() => live && setAskModalOpen(true)}
disabled={!live}
- className="shrink-0 rounded-lg bg-[#ef8d1d] px-3 py-2 text-xs font-semibold text-white shadow-[0_2px_4px_rgba(0,0,0,0.1)] transition hover:bg-[#e0800c] disabled:opacity-50"
+ className="shrink-0 rounded-lg bg-[#ef8d1 bg-[var(--theme-button-color)] px-3 py-2 text-xs font-semibold text-white shadow-[0_2px_4px_rgba(0,0,0,0.1)] transition-all duration-300 ease-in-out hover:bg-[#e0800c] transition hover:bg-[var(--theme-button-color)]/90 disabled:opacity-50"
>
Ask your Question
diff --git a/src/components/SessionQuizPollsSection.tsx b/src/components/SessionQuizPollsSection.tsx
index a6df256..6d9b2a8 100644
--- a/src/components/SessionQuizPollsSection.tsx
+++ b/src/components/SessionQuizPollsSection.tsx
@@ -44,7 +44,7 @@ export function SessionQuizPollsSection({ eventId, sessionId }: SessionQuizPolls
}).toString()}`;
return (
-
+
{open ? (
-
+
) : (
-
+
)}
@@ -91,7 +91,7 @@ export function SessionQuizPollsSection({ eventId, sessionId }: SessionQuizPolls
{actionLabel(item.type)}
diff --git a/src/hooks/useEventTheme.ts b/src/hooks/useEventTheme.ts
new file mode 100644
index 0000000..f809296
--- /dev/null
+++ b/src/hooks/useEventTheme.ts
@@ -0,0 +1,22 @@
+import { useEffect } from "react";
+import { applyEventTheme, clearEventTheme } from "../theme/eventTheme";
+import type { EventThemeConfig } from "../types/visitorContext";
+import { readStoredVisitorContext } from "../types/visitorContext";
+
+/**
+ * Applies event theme CSS variables to ``.
+ * When `theme` is omitted, uses theme from stored visitor context (if any).
+ */
+export function useEventTheme(theme?: EventThemeConfig | null) {
+ useEffect(() => {
+ const resolved = theme ?? readStoredVisitorContext()?.event?.theme ?? null;
+ if (resolved) {
+ applyEventTheme(resolved);
+ }
+ return () => {
+ // Keep vars while navigating between themed event pages;
+ // only clear when an explicit null theme is passed.
+ if (theme === null) clearEventTheme();
+ };
+ }, [theme]);
+}
diff --git a/src/index.css b/src/index.css
index 47b3bee..d60dddc 100644
--- a/src/index.css
+++ b/src/index.css
@@ -15,15 +15,20 @@
html {
min-height: 100dvh;
- background-color: #f2f2f7;
+ background-color: var(--theme-bg-color, #f2f2f7);
+ background-image: var(--theme-bg-image, none);
+ background-size: var(--theme-bg-size, auto);
+ background-repeat: var(--theme-bg-repeat, no-repeat);
+ background-position: var(--theme-bg-position, center center);
+ background-attachment: fixed;
}
body {
margin: 0;
min-height: 100dvh;
- font-family: var(--font-sans);
+ font-family: var(--theme-body-font, var(--font-sans));
color: var(--color-eb-text);
- background-color: #f2f2f7;
+ background: transparent;
-webkit-font-smoothing: antialiased;
}
@@ -31,35 +36,42 @@ body {
display: flex;
flex-direction: column;
min-height: 100dvh;
- background-color: #f2f2f7;
+ background: transparent;
}
.eb-gradient-banner {
background: linear-gradient(
34.8deg,
- rgb(29, 102, 239) 0%,
- rgb(30, 121, 240) 45%,
- rgb(189, 53, 230) 100%
+ var(--theme-primary-color, rgb(29, 102, 239)) 0%,
+ var(--theme-primary-color, rgb(30, 121, 240)) 45%,
+ var(--theme-secondary-color, rgb(189, 53, 230)) 100%
);
}
.eb-gradient-fab {
background: linear-gradient(
65deg,
- rgb(29, 102, 239) 0%,
- rgb(30, 121, 240) 40%,
- rgb(189, 53, 230) 100%
+ var(--theme-primary-color, rgb(29, 102, 239)) 0%,
+ var(--theme-primary-color, rgb(30, 121, 240)) 40%,
+ var(--theme-secondary-color, rgb(189, 53, 230)) 100%
);
}
/* Auth / modal shells (Figma EventBuzz_Event_Mobile_V1_Register) */
.eb-gradient-auth {
- background: linear-gradient(
- 77.92deg,
- rgb(29, 102, 239) 0%,
- rgb(30, 121, 240) 45%,
- rgb(189, 53, 230) 100%
+ background-color: var(--theme-bg-color, transparent);
+ background-image: var(
+ --theme-bg-image,
+ linear-gradient(
+ 77.92deg,
+ rgb(29, 102, 239) 0%,
+ rgb(30, 121, 240) 45%,
+ rgb(189, 53, 230) 100%
+ )
);
+ background-size: var(--theme-bg-size, cover);
+ background-repeat: var(--theme-bg-repeat, no-repeat);
+ background-position: var(--theme-bg-position, center center);
}
/* Rewards / Leaderboard “Total Points” card */
@@ -116,6 +128,36 @@ body {
animation: eb-live-blink 1.2s ease-in-out infinite;
}
+.card-bg {
+ background-color: var(--theme-card-color, #ffffff);
+ color: var(--theme-card-text-color, #333333);
+ backdrop-filter: blur(10px);
+}
+.theme-btn-bg {
+ background-color: var(--theme-button-color, #ef8d1d);
+ color: var(--theme-button-text-color, #ffffff);
+}
+.theme-btn-link {
+ color: var(--theme-button-color, #ef8d1d);
+ text-decoration: underline;
+ text-underline-offset: 2px;
+ text-decoration-thickness: 1px;
+ text-decoration-color: var(--theme-button-color, #ef8d1d);
+ text-decoration-style: solid;
+ text-decoration-skip-ink: none;
+ text-decoration-skip-ink: none;
+}
+/* @layer utilities {
+ .btn-bg {
+ background-color: var(--theme-button-color, #ef8d1d);
+ color: var(--theme-button-text-color, #ffffff);
+ }
+ .btn-bg:hover {
+ background-color: var(--theme-primary-color, #ef8d1d);
+ color: var(--theme-button-text-color, #ffffff);
+ }
+} */
+
@keyframes eb-live-blink {
0%,
100% {
diff --git a/src/lib/api.ts b/src/lib/api.ts
index 440083b..0d3c0b5 100644
--- a/src/lib/api.ts
+++ b/src/lib/api.ts
@@ -1,7 +1,102 @@
import type { AttendeeParticipant } from "./attendeeAuth";
import { getAttendeeToken } from "./attendeeAuth";
+import { applyEventTheme } from "../theme/eventTheme";
import type { LoginPreviewResponse, ResolveCodeResponse, VisitorJoinType } from "../types/visitorContext";
+/** Temporary test payload for getVisitorLoginPreview — remove when wiring live API again. */
+const LOGIN_PREVIEW_SAMPLE: LoginPreviewResponse = {
+ _id: "69ce3c91be56b4a3b09b2333",
+ organization: "69b58b13aff81b3887b0026c",
+ name: "COPD Conference",
+ description: "COPD Conference in various locations joined using Zoom",
+ type: "conference",
+ status: "upcoming",
+ startDate: "2026-06-25T12:00:00.000Z",
+ endDate: "2026-09-04T12:00:00.000Z",
+ location:
+ "Stratawiz Technologies Pvt Ltd, First Floor, D-Building, Anant Shilp Society, DSK Raanwaara Rd, Patil Nagar, Bavdhan, Pune, Maharashtra 411021",
+ locationType: "virtual",
+ tags: [],
+ image:
+ "https://did94hhhcgq1d.cloudfront.net/eventbuzz/69b58b13aff81b3887b0026c/69ce3c91be56b4a3b09b2333/event/logo/event-logo-1775123603963.png",
+ bannerImage:
+ "https://did94hhhcgq1d.cloudfront.net/eventbuzz/69b58b13aff81b3887b0026c/69ce3c91be56b4a3b09b2333/event/banner/event-banner-1782452674436.png",
+ metadata: {
+ totalRevenue: 0,
+ rating: 3.9,
+ ratingCount: 8,
+ registrationCustomFields: [],
+ },
+ category: undefined,
+ virtualLink: "https://zoom.us",
+ subtitle: undefined,
+ settings: {
+ registrationOpen: true,
+ requiresApproval: false,
+ registrationMode: "Open",
+ verifyEmail: false,
+ registrationDeadline: "2026-09-12T12:00:00.000Z",
+ enableFeedback: true,
+ enableRatings: true,
+ authenticationType: "none",
+ registrationBaseFields: "name_email",
+ },
+ logoUrl:
+ "https://did94hhhcgq1d.cloudfront.net/eventbuzz/69b58b13aff81b3887b0026c/69ce3c91be56b4a3b09b2333/event/logo/event-logo-1775123603963.png",
+ ratings: {
+ average: 3.9,
+ count: 8,
+ },
+ // theme: {
+ // "theme": "simple",
+ // "color": "#151937",
+ // "font": "Roboto",
+ // "primaryColor": "#303F9F",
+ // "secondaryColor": "#4CAF50",
+ // "headerColor": "",
+ // "buttonColor": "#2c357a",
+ // "textColor": "#ffffff",
+ // "textHighlightColor": "",
+ // "cardColor": "rgba(255,255,255,0.65)",
+ // "cardTextColor": "#ffffff"
+ // },
+ // theme: {
+ // theme: "gradient",
+ // color: "#bd35e6",
+ // // "gradient": {
+ // // "color1": "#1e72ef",
+ // // "color2": "#ef8d1d"
+ // // },
+ // font: "Open Sans",
+ // primaryColor: "#1e72ef",
+ // secondaryColor: "#bd35e6",
+ // headerColor: "",
+ // buttonColor: "#1e72ef",
+ // textColor: "#ffffff",
+ // textHighlightColor: "",
+ // cardColor: "rgba(255, 255, 255, 0.9)",
+ // cardTextColor: "#333333",
+ // },
+ theme: {
+ theme: "background",
+ color: "#1e72ef",
+ background: {
+ url: "https://did94hhhcgq1d.cloudfront.net/rapport/backgrounds/eventbuzz-bg2.jpg",
+ size: "cover",
+ repeat: "no",
+ },
+ font: "Poppins",
+ primaryColor: "#1e72ef",
+ secondaryColor: "#bd35e6",
+ headerColor: "",
+ buttonColor: "#1e72ef",
+ textColor: "#ffffff",
+ textHighlightColor: "",
+ cardColor: "rgba(255, 255, 255, 0.9)",
+ cardTextColor: "#333333",
+ },
+};
+
function getBaseUrl(): string {
const raw = import.meta.env.VITE_API_BASE_URL;
if (typeof raw !== "string" || !raw.trim()) return "";
@@ -55,17 +150,25 @@ export async function postVisitorResolveCode(code: string): Promise
{
- const base = getBaseUrl();
- const url = `${base}/api/visitor/events/${encodeURIComponent(eventId)}/login-preview`;
- const res = await fetch(url);
- const body = await parseJson(res);
- if (!res.ok) {
- throw new Error(messageFromBody(body));
- }
- if (!body || typeof body !== "object" || !("data" in body)) {
- throw new Error("Invalid response");
- }
- return (body as { data: LoginPreviewResponse }).data;
+ // TODO: restore live API call below once theme testing is done
+ void eventId;
+ const data = LOGIN_PREVIEW_SAMPLE;
+ if (data.theme) applyEventTheme(data.theme);
+ return data;
+
+ // const base = getBaseUrl();
+ // const url = `${base}/api/visitor/events/${encodeURIComponent(eventId)}/login-preview`;
+ // const res = await fetch(url);
+ // const body = await parseJson(res);
+ // if (!res.ok) {
+ // throw new Error(messageFromBody(body));
+ // }
+ // if (!body || typeof body !== "object" || !("data" in body)) {
+ // throw new Error("Invalid response");
+ // }
+ // const data = (body as { data: LoginPreviewResponse }).data;
+ // if (data?.theme) applyEventTheme(data.theme);
+ // return data;
}
export type VisitorEventTrackListItem = {
diff --git a/src/pages/EventLandingPage.tsx b/src/pages/EventLandingPage.tsx
index 6b14870..684b837 100644
--- a/src/pages/EventLandingPage.tsx
+++ b/src/pages/EventLandingPage.tsx
@@ -149,15 +149,15 @@ export function EventLandingPage() {
-
+
-
+
{event.name}
{reg.enableRatings ? (
-
+
rate now
) : (
@@ -167,7 +167,7 @@ export function EventLandingPage() {
{event.description?.trim() || event.subtitle?.trim() || "Welcome to this event."}
-