This repository has been archived on 2024-08-06. You can view files and clone it, but cannot push or open issues or pull requests.
readyornot/pages/[map].tsx

157 lines
5.2 KiB
TypeScript
Raw Permalink Normal View History

2022-12-03 20:02:18 +00:00
import Head from 'next/head'
import { ReactElement, useEffect, useState } from 'react'
import LayoutReadyOrNot from '../components/layout'
import styles from '/styles/ReadyOrNot.module.css'
import { NextPageWithLayout } from './_app';
import React from 'react';
import useSWR, { KeyedMutator, mutate } from 'swr';
import { useRouter } from 'next/router';
import Image from 'next/image';
2022-12-03 20:02:18 +00:00
import ReadyOrNotMap from '../interfaces/ReadyOrNot';
import useWindowSize from '../components/windowsize';
2022-12-03 20:02:18 +00:00
const fetcher = (url: string) => fetch(url).then((res) => res.json())
const ReadyOrNotMaps: NextPageWithLayout = () => {
const [floor, setFloor] = useState(0);
const { mapInfo, isLoadingInfo, isErrorInfo } = useMap(useRouter().query.map?.toString() || "a_lethal_obsession")
const { mapImages, isLoadingImages, isErrorImages, mutateImage } = useImages(useRouter().query.map?.toString() || "a_lethal_obsession")
const isMobile = useWindowSize();
let infoHtml: ReactElement = <></>;
let mapHtml: ReactElement = <></>;
if (isErrorInfo) {
infoHtml = (
<h1 className={styles.title}>
<a>Error loading page Data</a>
</h1>
)
}
else if (isLoadingInfo) {
infoHtml = (
<h1 className={styles.title}>
<a>Loading...</a>
</h1>
)
}
else {
const info = mapInfo
infoHtml = (
<h1 className={styles.title}>
<a>{info.name} ({info.alias})</a>
</h1>
)
if (isErrorImages) {
mapHtml = <div className={styles.mapContainer}><p>Error loading Map or Map not present</p></div>
}
else if (isLoadingImages) {
mapHtml = <div className={styles.mapContainer}><p>Loading...</p></div>
}
else if(info.floors){
// TODO: ask Yahia if he would rather the buttons turn off at the corresponding limits
// move to highest floor after going down from lowest
if (floor < info.floors[0]) {
setFloor(info.floors[info.floors.length-1])
}
// move to lowest floor after going up from highest
if (floor > info.floors[info.floors.length-1]) {
setFloor(info.floors[0])
}
// map the images to the corresponding floor number in an array
let images: string[] = [];
mapImages.forEach((image, index) => {
// assign the floor number of the image position, since floors and images are synced from the info object this works
images[info.floors[index]] = image
});
let inverseFloors = info.floors.slice(0);
inverseFloors.reverse()
mapHtml = (
<div className={[styles.mapContainer, (isMobile ? styles.mc_mobile : styles.mc_desktop)].join(" ")}>
<div className={[
styles.floorIndicator,
(isMobile ? styles.findicator_mobile : styles.findicator_desktop)
].join(" ")}>
<p className={[
styles.floorNumber,
(isMobile ? styles.fn_mobile : styles.fn_desktop)
].join(" ")}>{floor}</p>
{inverseFloors.map((level: number, index: number) => (
<div key={level} className={[
styles.floorIcon,
(floor == level ? styles.fi_active : styles.fi_inactive),
(isMobile ? styles.fi_mobile : styles.fi_desktop)
].join(" ")} onClick={() => {setFloor(level)}}></div>
))}
</div>
<div className={[styles.map, (isMobile ? styles.map_mobile : styles.map_desktop)].join(" ")}>
<Image alt="Floorplan" src={images[floor]} layout="fill" objectFit='contain'></Image>
</div>
<div className={[
styles.floorSelection,
(isMobile ? styles.fs_mobile : styles.fs_desktop)
].join(" ")}>
<button className={[
styles.floor_button,
(isMobile ? styles.fb_mobile : "")
].join(" ")} onClick={() => setFloor(floor + 1)} >+</button>
<button className={[
styles.floor_button,
(isMobile ? styles.fb_mobile : "")
].join(" ")} onClick={() => setFloor(floor - 1)} >-</button>
</div>
</div>
)
}
else {
mapHtml = <div className={styles.mapContainer}><p>Invalid or missing floor info: {info.floors}</p></div>
}
}
// TODO: set background here depending on image loaded
return (
<>
<Head>
<title>Ready or Not</title>
<meta charSet='utf-8' />
<link rel="icon" href="/favicon.ico" />
</Head>
{infoHtml}
{mapHtml}
</>
)
}
ReadyOrNotMaps.getLayout = function getLayout(page: ReactElement) {
return (
<LayoutReadyOrNot>
{page}
</LayoutReadyOrNot>
)
}
function useMap(path: string):{mapInfo: ReadyOrNotMap, isLoadingInfo: boolean, isErrorInfo: boolean} {
const { data, error } = useSWR(`/api/${path}`, fetcher)
return {
mapInfo: data,
isLoadingInfo: !error && !data,
isErrorInfo: error
}
}
function useImages(path: string):{mapImages: string[], isLoadingImages: boolean, isErrorImages: boolean, mutateImage: KeyedMutator<any>} {
const { data, error, mutate } = useSWR(`/api/${path}/maps`, fetcher)
return {
mapImages: data,
isLoadingImages: !error && !data,
isErrorImages: error,
mutateImage: mutate,
}
}
export default ReadyOrNotMaps;