107 lines
3.9 KiB
TypeScript
107 lines
3.9 KiB
TypeScript
import { useState } from "react";
|
|
import { ChevronDown, ChevronUp } from "lucide-react";
|
|
import { Link } from "react-router-dom";
|
|
import { useSessionQuizPollsRtdb } from "../hooks/useSessionQuizPollsRtdb";
|
|
|
|
function typeBadgeClass(type: string): string {
|
|
const t = type.toLowerCase();
|
|
if (t === "poll") return "bg-[#eaddff]";
|
|
if (t === "survey") return "bg-[#e5e5ea]";
|
|
return "bg-[#ebffee]";
|
|
}
|
|
|
|
function typeLabel(type: string): string {
|
|
const t = type.toLowerCase();
|
|
if (t === "poll") return "Poll";
|
|
if (t === "survey") return "Survey";
|
|
return "Quiz";
|
|
}
|
|
|
|
function actionLabel(type: string): string {
|
|
const t = type.toLowerCase();
|
|
if (t === "poll") return "Take Poll";
|
|
if (t === "survey") return "Take Survey";
|
|
return "Take Quiz";
|
|
}
|
|
|
|
type SessionQuizPollsSectionProps = {
|
|
eventId: string;
|
|
sessionId: string;
|
|
};
|
|
|
|
export function SessionQuizPollsSection({ eventId, sessionId }: SessionQuizPollsSectionProps) {
|
|
const [open, setOpen] = useState(true);
|
|
const { items, loading, error } = useSessionQuizPollsRtdb(sessionId);
|
|
const eid = eventId.trim();
|
|
const sid = sessionId.trim();
|
|
const live = Boolean(eid && sid);
|
|
|
|
const takeHref = (quizPollId: string) =>
|
|
`/quiz-poll?${new URLSearchParams({
|
|
event_id: eid,
|
|
session_id: sid,
|
|
quiz_poll_id: quizPollId,
|
|
}).toString()}`;
|
|
|
|
return (
|
|
<div className="w-full max-w-none rounded-lg border border-[rgba(116,112,112,0.2)] bg-white shadow-sm">
|
|
<button
|
|
type="button"
|
|
className="flex w-full items-center justify-between gap-2 px-4 py-3 text-left"
|
|
onClick={() => setOpen(!open)}
|
|
aria-expanded={open}
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<span className="text-sm font-semibold text-[#24282f]">Quiz & Polls</span>
|
|
<span className="rounded bg-[#ebffee] px-2 py-0.5 text-[10px] uppercase text-[#24282f]">
|
|
{loading ? "…" : `${items.length} Active`}
|
|
</span>
|
|
</div>
|
|
{open ? (
|
|
<ChevronUp className="size-4 shrink-0 text-[#1d66ef]" strokeWidth={2} />
|
|
) : (
|
|
<ChevronDown className="size-4 shrink-0 text-[#1d66ef]" strokeWidth={2} />
|
|
)}
|
|
</button>
|
|
|
|
{open ? (
|
|
<div className="border-t border-[#f2f2f7] px-4 pb-4 pt-1">
|
|
{!live ? (
|
|
<p className="py-3 text-center text-sm text-[rgba(36,40,47,0.55)]">Join a session to see quizzes.</p>
|
|
) : error ? (
|
|
<p className="py-3 text-center text-sm text-red-600">{error}</p>
|
|
) : loading ? (
|
|
<p className="py-3 text-center text-sm text-[rgba(36,40,47,0.55)]">Loading quizzes…</p>
|
|
) : items.length === 0 ? (
|
|
<p className="py-3 text-center text-sm text-[rgba(36,40,47,0.55)]">No live quizzes or polls right now.</p>
|
|
) : (
|
|
<ul className="flex flex-col gap-0">
|
|
{items.map((item) => (
|
|
<li
|
|
key={item._id}
|
|
className="flex items-center justify-between gap-2 border-b border-[#f2f2f7] py-3 last:border-0"
|
|
>
|
|
<div className="min-w-0 flex-1">
|
|
<span
|
|
className={`inline-block rounded px-2 py-0.5 text-[10px] font-medium text-[#24282f] ${typeBadgeClass(item.type)}`}
|
|
>
|
|
{typeLabel(item.type).toUpperCase()}
|
|
</span>
|
|
<p className="mt-1 truncate text-sm font-medium text-[#24282f]">{item.title || "Untitled"}</p>
|
|
</div>
|
|
<Link
|
|
to={takeHref(item._id)}
|
|
className="shrink-0 rounded bg-[#0b4dd1] px-3 py-1.5 text-center text-xs font-semibold text-white transition hover:bg-[#0a43b8]"
|
|
>
|
|
{actionLabel(item.type)}
|
|
</Link>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
);
|
|
}
|