EventBuzz_Website/src/pages/FeedbackPage.tsx

165 lines
5.8 KiB
TypeScript

import { useEffect, useState } from "react";
import { Link, useSearchParams } from "react-router-dom";
import { HeaderMobile } from "../components/HeaderMobile";
import { MobileShell } from "../components/MobileShell";
import { DynamicFeedbackForm } from "../components/DynamicFeedbackForm";
import { useAutoNavigateToLiveQuizPoll } from "../hooks/useAutoNavigateToLiveQuizPoll";
import { useEventRegistrationSettings } from "../hooks/useEventRegistrationSettings";
import {
getVisitorFeedbackFormSchema,
getVisitorLoginPreview,
resolveVisitorFeedbackFormSchema,
type VisitorPublicFeedbackForm,
} from "../lib/api";
import { readStoredVisitorContext } from "../types/visitorContext";
export function FeedbackPage() {
const [searchParams] = useSearchParams();
const formId = searchParams.get("form_id")?.trim() || "";
const urlEventId = searchParams.get("event_id")?.trim() || "";
const urlSessionId = searchParams.get("session_id")?.trim() || "";
const ctx = readStoredVisitorContext();
const eventId = urlEventId || ctx?.eventId || "";
const sessionId = urlSessionId || ctx?.sessionId || "";
useAutoNavigateToLiveQuizPoll({
eventId,
sessionId,
enabled: Boolean(eventId && sessionId),
});
const [eventSnapshot, setEventSnapshot] = useState(
ctx?.eventId === eventId && ctx.event ? ctx.event : null,
);
const [schema, setSchema] = useState<VisitorPublicFeedbackForm | null>(null);
const [schemaLoading, setSchemaLoading] = useState(false);
const [schemaErr, setSchemaErr] = useState<string | null>(null);
useEffect(() => {
if (!eventId) {
setEventSnapshot(null);
return;
}
if (ctx?.eventId === eventId && ctx.event) {
setEventSnapshot(ctx.event);
return;
}
let cancelled = false;
getVisitorLoginPreview(eventId)
.then((ev) => {
if (!cancelled) setEventSnapshot(ev);
})
.catch(() => {
if (!cancelled) setEventSnapshot(null);
});
return () => {
cancelled = true;
};
}, [eventId, ctx?.eventId, ctx?.event]);
useEffect(() => {
if (!eventId) {
setSchema(null);
setSchemaErr(null);
setSchemaLoading(false);
return;
}
let cancelled = false;
setSchemaLoading(true);
setSchemaErr(null);
const load = formId
? getVisitorFeedbackFormSchema(eventId, formId)
: resolveVisitorFeedbackFormSchema(eventId, { sessionId, purpose: "feedback" });
load
.then((s) => {
if (!cancelled) setSchema(s);
})
.catch((e) => {
if (!cancelled) {
setSchema(null);
setSchemaErr(e instanceof Error ? e.message : "Could not load form.");
}
})
.finally(() => {
if (!cancelled) setSchemaLoading(false);
});
return () => {
cancelled = true;
};
}, [formId, eventId, sessionId]);
const reg = useEventRegistrationSettings(eventSnapshot);
if (!eventId) {
return (
<MobileShell className="relative">
<HeaderMobile logoUrl={ctx?.event?.logoUrl} eventId={null} />
<main className="flex flex-1 flex-col px-4 pb-10 pt-6">
<div className="mx-auto w-full max-w-[370px]">
<div className="card-bg rounded-lg shadow-md p-4">
<h1 className="font-inter text-xl font-semibold text-[var(--theme-card-text-color)]">Feedback</h1>
<p className="mt-3 text-sm text-[var(--theme-card-text-color)]/80">Open feedback from your event or session link.</p>
<Link to="/" className="mt-4 inline-block text-sm font-semibold theme-btn-link">
Home
</Link>
</div>
</div>
</main>
</MobileShell>
);
}
if (!reg.enableFeedback) {
return (
<MobileShell className="relative">
<HeaderMobile logoUrl={eventSnapshot?.logoUrl} eventId={eventId || null} />
<main className="flex flex-1 flex-col px-4 pb-10 pt-6">
<div className="mx-auto w-full max-w-[370px]">
<div className="card-bg rounded-lg shadow-md p-4">
<h1 className="text-xl font-semibold text-[var(--theme-card-text-color)]">Feedback</h1>
<p className="mt-3 text-sm text-[var(--theme-card-text-color)]/80">Feedback is disabled for this event.</p>
<Link to="/event" className="mt-4 inline-block text-sm font-semibold theme-btn-link">
Back to event
</Link>
</div>
</div>
</main>
</MobileShell>
);
}
return (
<MobileShell className="relative">
<HeaderMobile logoUrl={eventSnapshot?.logoUrl} eventId={eventId || null} />
<main className="flex flex-1 flex-col px-4 pb-10 pt-6">
<div className="mx-auto w-full max-w-[370px]">
<div className="card-bg rounded-lg shadow-md p-4">
<h1 className="text-xl font-semibold text-[var(--theme-card-text-color)]">{schema?.name || "Feedback"}</h1>
{schemaLoading ? (
<p className="mt-4 text-sm text-[var(--theme-card-text-color)]/80">Loading form…</p>
) : schemaErr ? (
<div className="mt-4">
<p className="text-sm text-red-600">{schemaErr}</p>
<p className="mt-2 text-sm text-[var(--theme-card-text-color)]/80">
Ask the organizer to publish an active feedback form for this event.
</p>
<Link to="/event" className="mt-4 inline-block text-sm font-semibold theme-btn-link">
Back to event
</Link>
</div>
) : schema ? (
<div className="mt-2">
<DynamicFeedbackForm eventId={eventId} schema={schema} variant="light" className="px-0" />
</div>
) : null}
</div>
</div>
</main>
</MobileShell>
);
}