EventBuzz_Console/src/app/components/dashboard/EventHomeHeaderActions.tsx

170 lines
5.3 KiB
TypeScript

import React, { useEffect, useState } from "react";
import { QrCode, Radio } from "lucide-react";
import { AgendaQrModal } from "../agenda/AgendaQrModal";
import { useBreakpoint } from "../../hooks/useBreakpoint";
import { useAppNav } from "../../contexts/AppNavContext";
import { eventsApi } from "../../../services/api/events";
import type { Event } from "../../../services/api/types";
const headerBtnBase: React.CSSProperties = {
display: "flex",
alignItems: "center",
gap: "6px",
padding: "7px 14px",
borderRadius: "var(--radius-button)",
borderWidth: "1px",
borderStyle: "solid",
fontSize: "var(--text-sm)",
fontFamily: "var(--font-noto-sans)",
fontWeight: "var(--font-weight-medium)",
cursor: "pointer",
transition: "all 0.15s",
};
export function EventHomeHeaderActions() {
const { selectedEventId } = useAppNav();
const bp = useBreakpoint();
const isSmall = bp === "mobile" || bp === "tablet";
const [qrOpen, setQrOpen] = useState(false);
const [liveActive, setLiveActive] = useState(false);
const [qrEvent, setQrEvent] = useState<Event | null | undefined>(undefined);
useEffect(() => {
if (!qrOpen || !selectedEventId) {
setQrEvent(undefined);
return;
}
setQrEvent(undefined);
let cancelled = false;
void eventsApi.get(selectedEventId).then((res) => {
if (!cancelled) setQrEvent(res.data ?? null);
});
return () => {
cancelled = true;
};
}, [qrOpen, selectedEventId]);
function openQr() {
if (!selectedEventId) {
window.alert("Select an event from the sidebar first.");
return;
}
setQrOpen(true);
}
function toggleLive() {
if (!liveActive && !window.confirm("Start broadcasting this event as Live? All participants will be notified.")) {
return;
}
setLiveActive((v) => !v);
}
return (
<>
<div style={{ display: "flex", alignItems: "center", gap: "8px", flexWrap: "wrap" }}>
<button
type="button"
onClick={openQr}
disabled={!selectedEventId}
style={{
...headerBtnBase,
borderColor: "var(--border)",
background: "var(--card)",
color: "var(--card-foreground)",
opacity: selectedEventId ? 1 : 0.55,
cursor: selectedEventId ? "pointer" : "not-allowed",
}}
onMouseEnter={(e) => {
if (!selectedEventId) return;
(e.currentTarget as HTMLElement).style.borderColor = "var(--primary)";
(e.currentTarget as HTMLElement).style.color = "var(--primary)";
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLElement).style.borderColor = "var(--border)";
(e.currentTarget as HTMLElement).style.color = "var(--card-foreground)";
}}
>
<QrCode size={14} />
{isSmall ? "QR" : "Generate QR Code"}
</button>
<button
type="button"
onClick={toggleLive}
style={{
...headerBtnBase,
borderColor: liveActive ? "var(--destructive)" : "var(--border)",
background: liveActive ? "var(--destructive)" : "var(--card)",
color: liveActive ? "var(--destructive-foreground)" : "var(--card-foreground)",
}}
onMouseEnter={(e) => {
if (liveActive) return;
(e.currentTarget as HTMLElement).style.borderColor = "var(--primary)";
(e.currentTarget as HTMLElement).style.color = "var(--primary)";
}}
onMouseLeave={(e) => {
if (liveActive) return;
(e.currentTarget as HTMLElement).style.borderColor = "var(--border)";
(e.currentTarget as HTMLElement).style.color = "var(--card-foreground)";
}}
>
{liveActive ? (
<span
style={{
width: "7px",
height: "7px",
borderRadius: "50%",
background: "var(--destructive-foreground)",
display: "block",
}}
/>
) : (
<Radio size={14} />
)}
{liveActive ? "Stop Live" : isSmall ? "Go Live" : "Go Live"}
</button>
</div>
{qrOpen && selectedEventId && qrEvent !== undefined ? (
<AgendaQrModal
open
onClose={() => setQrOpen(false)}
kind="event"
joinCode={(qrEvent?.joinCode ?? "").trim()}
label={qrEvent?.name ?? "Event"}
/>
) : null}
{qrOpen && selectedEventId && qrEvent === undefined ? (
<div
role="status"
aria-live="polite"
style={{
position: "fixed",
inset: 0,
background: "rgba(0,0,0,0.45)",
zIndex: 120,
display: "flex",
alignItems: "center",
justifyContent: "center",
padding: "16px",
}}
>
<div
style={{
background: "var(--card)",
borderRadius: "var(--radius-card)",
padding: "24px 32px",
border: "1px solid var(--border)",
fontFamily: "var(--font-noto-sans)",
fontSize: "var(--text-sm)",
color: "var(--muted)",
}}
>
Loading event…
</div>
</div>
) : null}
</>
);
}