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>
</>
);
}