import React, { useContext, useEffect, useState } from "react"; import { useParams, useNavigate, useLocation } from "react-router-dom"; import { Box, Paper, Grid } from "@mui/material"; import SessionView from "./components/SessionView"; import { getEventLevel } from "../../../components/utils"; import EventEntryList from "./components/entries/EventEntryList"; import Summary from "./components/summary/Summary"; import HeatList from "./components/heats/HeatList"; import { GET_SESSION_EVENTS } from "../../../utils/graphql/queries"; import { ROUND_HEAT_STATUS_SUBSCRIPTION } from "../../../utils/graphql/subscriptions"; import { GET_HEAT_LIST } from "../../../utils/graphql/queries"; import useFetch from "../../../hooks/graphql/useFetch"; import EventHeader from "./components/EventHeader"; import { getView } from "../../../components/utils/getView"; import CombinedResults from "./components/combined/CombinedResults"; import useCombinedResults from "../../../hooks/useCombinedResults"; import useConditionalSub from "../../../hooks/graphql/useConditionalSub"; import { CompetitionDetailsContext } from "../../../context/CompetitionDetailsContext"; interface EventViewProps { competition: Competition | undefined; session: CompetitionSession | undefined; setSelectedSession: React.Dispatch< React.SetStateAction<CompetitionSession | undefined> >; setSessionTabIndex: React.Dispatch<React.SetStateAction<number>>; timeProgramEntryId: number | undefined; setTimeProgramEntryId: React.Dispatch< React.SetStateAction<number | undefined> >; eventView: View; setEventView: React.Dispatch<React.SetStateAction<View>>; isCompetitionActive: boolean; } const findEventView = (eventView: string | undefined): View => { switch (eventView as View) { case "entries": return "entries"; case "heats": return "heats"; case "summary": return "summary"; case "combined": return "combined"; default: return "entries"; } }; export default function EventView({ competition, isCompetitionActive, session, setSelectedSession, setSessionTabIndex, timeProgramEntryId, setTimeProgramEntryId, eventView, setEventView, }: EventViewProps) { const competitionId = competition?.id; const combinedGroup = competition?.combined_group; const showAge = competition?.show_age; const poolType = competition?.pool_type; const sessions = competition?.competition_sessions; const combinedType = competition?.combined_type; const params = useParams(); const navigate = useNavigate(); const location = useLocation(); const { loading, error, data, refresh: refetch, } = useFetch<TimeProgramEntry[]>( GET_SESSION_EVENTS, { _id: session?.id }, "_id", "cache-and-network" ); const { data: heatData } = useFetch<TimeProgramEntry>( GET_HEAT_LIST, { id: timeProgramEntryId }, ); const [eventId, setEventId] = useState<number | undefined>(undefined); const [selectedEventViewTab, setSelectedEventViewTab] = useState<number>(0); const [tpes, setTpes] = useState<TimeProgramEntry[]>([]); const [selectedTpe, setSelectedTpe] = useState<TimeProgramEntry | undefined>( undefined ); const [tpeFinal, setTpeFinal] = useState<boolean>(false); const [eventLevel, setEventLevel] = useState<number>(0); const [showOfficialTimeStamp, setShowOfficialTimeStamp] = useState<boolean>(false); const [roundStatus, setRoundStatus] = useState<number | undefined>(undefined); const [summaryTypes, setSummaryTypes] = useState<SummaryType[] | undefined>( selectedTpe?.round?.summary_types ); useEffect(() => { setSelectedTpe(data ? data[0] : undefined); }, [data]) const { shouldSubscribe } = useContext(CompetitionDetailsContext); const handleStatusClick = () => { if (showOfficialTimeStamp) { setShowOfficialTimeStamp(false); } else setShowOfficialTimeStamp(true); }; useEffect(() => { if (data) { //INFO: avoid error if query only returns one tpe as an object if (!Array.isArray(data)) { try { let arr = [] as TimeProgramEntry[]; arr.push(data); setTpes(arr); setSelectedTpe(data); } catch (err) { console.log(err); } } else { try { setTpes(data); const foundTpe = data.find((tpe) => tpe?.id === timeProgramEntryId); foundTpe && setSelectedTpe(foundTpe); } catch (err) { console.log(err); } } } }, [data]); useEffect(() => { if (selectedTpe) { setTimeProgramEntryId(selectedTpe?.id); } }, [selectedTpe]); useEffect(() => { refetch(); }, [timeProgramEntryId]); const { data: roundHeatSubData, isActive, endSub, } = useConditionalSub<Round>( ROUND_HEAT_STATUS_SUBSCRIPTION, { id: selectedTpe?.round?.id }, !(isCompetitionActive && !!selectedTpe?.round?.id) /* || !shouldSubscribe */ ); useEffect(() => { if (roundHeatSubData?.status) { setRoundStatus(roundHeatSubData?.status); } }, [roundHeatSubData]); /* CHECK AND SET COMPETITION-/EVENT LEVEL (SHOW/DON'T SHOW RANK) */ useEffect(() => { if (selectedTpe) { setEventLevel( getEventLevel(selectedTpe?.round?.event?.event_competition_level) ); setSummaryTypes(selectedTpe?.round?.summary_types); } }, [selectedTpe, timeProgramEntryId]); useEffect(() => { if (selectedTpe?.round?.sort_order && selectedTpe?.round?.sort_order >= 2) { setTpeFinal(true); } else { setTpeFinal(false); } }, [selectedTpe]); // useEffect(() => { // const foundEventView: View = findEventView(params?.eventView); // const parsedSession = Number(params.session); // const foundSession = sessions?.find( // (session) => session.oid === parsedSession // ); // const parsedTpe = Number(params.tpe); // const foundTpe = foundSession?.time_program_entries?.find( // (tpe) => tpe?.oid === parsedTpe // ); // if (location?.state?.tpeCard && selectedTpe?.round) { // switch (selectedTpe?.round?.status) { // case 0: // setEventView("entries"); // setSelectedEventViewTab(0); // navigate( // `../competitions/${params.competitionName}/events/entries/${session?.oid}/${selectedTpe?.oid}` // ); // break; // case 1: // case 3: // setEventView("heats"); // setSelectedEventViewTab(1); // navigate( // `../competitions/${params.competitionName}/events/heats/${session?.oid}/${selectedTpe?.oid}` // ); // break; // case 5: // setEventView("summary"); // setSelectedEventViewTab(2); // navigate( // `../competitions/${params.competitionName}/events/summary/${session?.oid}/${selectedTpe?.oid}` // ); // break; // } // } else if (params.eventView && params.session && params.tpe) { // if (foundEventView && foundSession && foundTpe) { // //console.log('found event view, session and tpe'); // const foundSessionIndex = sessions?.findIndex( // (session) => session?.id === foundSession?.id // ); // foundSessionIndex && setSessionTabIndex(foundSessionIndex); // setEventView(foundEventView); // setSelectedEventViewTab(getView.AsIndex(foundEventView)); // setSelectedSession(foundSession); // setTimeProgramEntryId(foundTpe?.id); // setEventId(foundTpe?.round?.event?.id); // navigate( // `../competitions/${params.competitionName}/events/${foundEventView}/${foundSession?.oid}/${foundTpe?.oid}` // ); // } else { // //TODO: if no view in params, check tpe status to decide between entries, heats and summary // //console.log('eventView, session & tpe: did not find event view'); // setEventView("entries"); // setSelectedEventViewTab(0); // sessions && // sessions[0].time_program_entries && // setTimeProgramEntryId(sessions[0]?.time_program_entries[0]?.id); // sessions && // sessions[0].time_program_entries && // navigate( // `../competitions/${params.competitionName}/events/entries/${sessions[0]?.oid}/${sessions[0]?.time_program_entries[0]?.oid}` // ); // } // } else if (params.eventView && params.session) { // const foundEventView: View = findEventView(params?.eventView); // const parsedSession = Number(params.session); // const foundSession = sessions?.find( // (session) => session?.oid === parsedSession // ); // if (foundEventView && foundSession) { // //console.log('found event view and session'); // setEventView(foundEventView); // setSelectedEventViewTab(getView.AsIndex(foundEventView)); // foundSession?.time_program_entries && // setTimeProgramEntryId(foundSession?.time_program_entries[0]?.id); // foundSession?.time_program_entries && // setEventId(foundSession?.time_program_entries[0]?.round?.event?.id); // foundSession?.time_program_entries && // navigate( // `../competitions/${params.competitionName}/events/${foundEventView}/${foundSession.oid}/${foundSession?.time_program_entries[0]?.oid}` // ); // } else { // //console.log('eventView & session: did not find event view'); // setEventView("entries"); // setSelectedEventViewTab(0); // navigate( // `../competitions/${params.competitionName}/events/entries/${session?.oid}/${selectedTpe?.oid}` // ); // } // } else { // setEventView("entries"); // setSelectedEventViewTab(0); // sessions && // sessions[0].time_program_entries && // setTimeProgramEntryId(sessions[0]?.time_program_entries[0]?.id); // sessions && // sessions[0].time_program_entries && // setEventId(sessions[0]?.time_program_entries[0]?.round?.event?.id); // sessions && // sessions[0].time_program_entries && // navigate( // `../competitions/${params.competitionName}/events/entries/${sessions[0]?.oid}/${sessions[0]?.time_program_entries[0]?.oid}` // ); // } // }, [eventView, timeProgramEntryId, params.eventView]); useEffect(() => { return () => { endSub(); }; }, []); const handleEventViewChange = (e: React.ChangeEvent, newValue: number) => { setSelectedEventViewTab(newValue); localStorage.setItem('lastVisitedTab', String(newValue)); navigate( `../competitions/${params.competitionName}/events/${getView.AsView( newValue as 0 | 1 | 2 | 3 )}/${session?.oid}/${selectedTpe?.oid}` ); }; // Handle default view settings useEffect(() => { // if a view is selected by the user then keep that view as default, else execute the logic below ... if(eventView === "entries" && selectedEventViewTab === 0) { setEventView("entries") setSelectedEventViewTab(0); } if(eventView && selectedEventViewTab) { return } if (selectedTpe && selectedTpe.round) { const status = selectedTpe?.round?.status; const hasHeats = heatData?.heats !== undefined || heatData?.heats !== null ? true : false; if (status === 5) { // If status is 5, set default view to "summary" and selected tab to 2 setEventView("summary"); setSelectedEventViewTab(2); } else if(hasHeats) { // If round is "heat", set default view to "heats" and selected tab to 1 setEventView("heats"); setSelectedEventViewTab(1); } else { // If status is not 5 and round is not "heat", set default view to "entries" and selected tab to 0 setEventView("entries"); setSelectedEventViewTab(0); } } }, [selectedTpe]); useEffect(() => { const lastVisitedTab = localStorage.getItem('lastVisitedTab'); const defaultView = eventView || 'entries'; const defaultTab = lastVisitedTab ? parseInt(lastVisitedTab) : 0; // Check if a view is already selected by the user if (!eventView && selectedEventViewTab === 0) { setEventView(defaultView); setSelectedEventViewTab(defaultTab); } }, [eventView, selectedEventViewTab]); const sponsorImg = selectedTpe?.round?.event?.sponsor?.img; const sponsorLink = selectedTpe?.round?.event?.sponsor?.link; const sponsorText = selectedTpe?.round?.event?.sponsor?.name; const eventNumber = selectedTpe?.round?.event?.number; const roundType = selectedTpe?.round?.round_type; const { combinedData: competitions, unsub, restartSub, lanes, loading: combinedLoading, error: combinedError, setSelectedAgeGroup, selectedAgeGroup, setAgeGroupTabIndex, ageGroupTabIndex, } = useCombinedResults( combinedGroup, eventNumber, roundType, combinedType, isCompetitionActive && eventView === "combined", eventView ); return ( <> <Grid container> <Grid item xs={4}> <Paper elevation={3} sx={{ position: "sticky", maxHeight: "100vh", overflowY: "scroll", "&::-webkit-scrollbar": { display: "none" }, top: "1px", }} > {session && ( <SessionView competitionId={competitionId} session={session} time_program_entries={tpes} setEventId={setEventId} setSelectedTpe={setSelectedTpe} time_programId={timeProgramEntryId} setSummaryTypes={setSummaryTypes} /> )} </Paper> </Grid> <Grid item xs={8} sx={{ bgcolor: "" }}> <Box ml={1} sx={{ bgcolor: "" }}> <EventHeader combinedCompetitions={competitions} combinedGroup={combinedGroup} eventView={eventView} eventId={selectedTpe?.round?.event?.id} selectedEventViewTab={selectedEventViewTab} setEventView={setEventView} handleEventViewChange={handleEventViewChange} handleStatusClick={handleStatusClick} selectedTpe={selectedTpe} sponsorImg={sponsorImg} showOfficialTimeStamp={showOfficialTimeStamp} setShowOfficialTimeStamp={setShowOfficialTimeStamp} sponsorLink={sponsorLink} sponsorText={sponsorText} roundStatus={roundStatus} tpeFinal={tpeFinal} isActive={isActive} /> {selectedTpe?.type === 1 && ( <Grid item xs={12} mx={0} mt={1} mb={2} sx={{ bgcolor: "" }}> {eventView === "entries" && ( <EventEntryList competitionId={competitionId} event={selectedTpe?.round?.event} round={selectedTpe?.round} time_programId={selectedTpe?.id} tpeFinal={tpeFinal} eventLevel={eventLevel} showAge={showAge} competitionPoolType={poolType} sortByName={ selectedTpe.round?.event?.entry_list_types?.[0] && selectedTpe.round?.event?.entry_list_types?.[0] .sort_by_name } /> )} {eventView === "heats" && ( <HeatList eventView={eventView} eventType={selectedTpe.round?.event?.event_type} roundHeatSubData={roundHeatSubData} isCompetitionActive={isCompetitionActive} timeProgramEntry={selectedTpe} round={selectedTpe?.round} time_programId={selectedTpe?.id} eventLevel={eventLevel} showAge={showAge} superliveSeo={session?.superlive_seo_link} /> )} {eventView === "summary" && summaryTypes && summaryTypes?.length > 0 && ( <Summary eventView={eventView} roundHeatSubData={roundHeatSubData} roundStatus={selectedTpe?.round?.status} isCompetitionActive={isCompetitionActive} summary_types={summaryTypes} time_programId={selectedTpe?.id} eventLevel={eventLevel} showAge={showAge} /> )} {eventView === "combined" && ( <CombinedResults restartSub={restartSub} unsub={unsub} ageGroupTabIndex={ageGroupTabIndex} selectedAgeGroup={selectedAgeGroup} setAgeGroupTabIndex={setAgeGroupTabIndex} setSelectedAgeGroup={setSelectedAgeGroup} loading={combinedLoading} error={combinedError} eventLevel={eventLevel} showAge={showAge} compId={competitionId} competitions={competitions} lanes={lanes} /> )} </Grid> )} </Box> </Grid> </Grid> </> ); }
Preview:
downloadDownload PNG
downloadDownload JPEG
downloadDownload SVG
Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!
Click to optimize width for Twitter