-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
301 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,5 +29,3 @@ export const App = () => { | |
</> | ||
); | ||
}; | ||
|
||
// TODO: Add link to the github repo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,33 @@ | ||
import { useState } from "react"; | ||
import { createContext, Dispatch, SetStateAction, useState } from "react"; | ||
import { LoadingSkeleton } from "../components/LoadingSkeleton"; | ||
import { useFetch } from "../hooks/useFetch"; | ||
import { Card } from "../types/cards"; | ||
import { Card, convertCardJSON } from "../types/cards"; | ||
import { CardsEmpty } from "./CardsEmpty"; | ||
import { CardsTable } from "./CardsTable"; | ||
|
||
interface CardContextProps { | ||
cards: readonly Card[]; | ||
setCards: Dispatch<SetStateAction<readonly Card[]>>; | ||
} | ||
|
||
export const CardContext = createContext<CardContextProps>({ | ||
cards: [], | ||
setCards: () => {}, | ||
}); | ||
|
||
export const Cards = () => { | ||
const [cards, setCards] = useState<readonly Card[]>([]); | ||
const { loading, error: _ } = useFetch<readonly Card[]>("cards", setCards); | ||
const { loading, error: _ } = useFetch<readonly Card[]>( | ||
"cards", | ||
setCards, | ||
convertCardJSON | ||
); | ||
|
||
return ( | ||
<LoadingSkeleton loading={loading}> | ||
{!!cards.length ? ( | ||
<CardsTable cards={cards} setCards={setCards} /> | ||
) : ( | ||
<CardsEmpty /> | ||
)} | ||
<CardContext.Provider value={{ cards, setCards }}> | ||
{!!cards.length ? <CardsTable /> : <CardsEmpty />} | ||
</CardContext.Provider> | ||
</LoadingSkeleton> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,110 @@ | ||
import { Add, CancelOutlined } from "@mui/icons-material"; | ||
import { Add } from "@mui/icons-material"; | ||
import { Button, Typography } from "@mui/material"; | ||
import { useState } from "react"; | ||
import { ConfirmationModal } from "../components/ConfirmationModal"; | ||
import { useConfirm } from "material-ui-confirm"; | ||
import { useSnackbar } from "notistack"; | ||
import { useContext, useState } from "react"; | ||
import { Card, CardPostResponse, convertCardJSON } from "../types/cards"; | ||
import { getApi, isResponseNot200Error, postApi } from "../util/fetch"; | ||
import { equal, randomInt } from "../util/util"; | ||
import { CardContext } from "./Cards"; | ||
|
||
const CHECK_INTERVAL = 1000; | ||
const REGISTER_TIME = 60000; | ||
|
||
const confirmTitle = "Register a new card"; | ||
const confirmContent = ` | ||
Once you click 'register' you will have 60 seconds to hold your card to the scanner. | ||
A popup will appear when the card is registered successfully and it will be added to your cards table. | ||
`; | ||
|
||
const requestSuccess = "Register your card by holding it to vinscant"; | ||
const requestYou = "You are already registering a card!"; | ||
const requestOther = | ||
"Failed to start the card registering process because another user is already registering a card. Please try again later."; | ||
const requestFail = | ||
"Failed to start the card registration process. Please try again later or contact a sysadmin"; | ||
|
||
const registerSucces = "Card registered successfully"; | ||
const registerFail = "Failed to register card"; | ||
|
||
const getCards = () => | ||
getApi<readonly Card[]>("cards", convertCardJSON).catch((_) => null); | ||
|
||
const checkCardsChange = async (): Promise< | ||
[boolean, readonly Card[] | null] | ||
> => { | ||
const startTime = Date.now(); | ||
const cardsStart = await getCards(); | ||
|
||
if (!cardsStart) return [false, null]; | ||
|
||
let cardsNow: readonly Card[] | null = null; | ||
while (Date.now() - startTime < REGISTER_TIME) { | ||
cardsNow = await getCards(); | ||
|
||
if (!equal(cardsStart, cardsNow)) break; | ||
|
||
await new Promise((r) => setTimeout(r, CHECK_INTERVAL)); | ||
} | ||
|
||
return [cardsNow !== null && cardsNow !== cardsStart, cardsNow]; | ||
}; | ||
|
||
export const CardsAdd = () => { | ||
const [open, setOpen] = useState<boolean>(false); | ||
const { setCards } = useContext(CardContext); | ||
const [disabled, setDisabled] = useState<boolean>(false); | ||
const confirm = useConfirm(); | ||
const { enqueueSnackbar, closeSnackbar } = useSnackbar(); | ||
|
||
const handleOpen = () => setOpen(true); | ||
const handleClose = () => setOpen(false); | ||
const startRegistering = () => | ||
postApi<Card[]>("cards/register") | ||
.then(() => { | ||
const id = randomInt().toString(); | ||
enqueueSnackbar(requestSuccess, { | ||
variant: "info", | ||
persist: true, | ||
key: id, | ||
}); | ||
setDisabled(true); | ||
|
||
const title = "Register a new card"; | ||
checkCardsChange().then((result) => { | ||
closeSnackbar(id); | ||
setDisabled(false); | ||
|
||
const content = ` | ||
This feature is not yet implemented as I'm waiting for an endpoint. | ||
Hannes................................................ | ||
`; | ||
if (result[0] && result[1] !== null) { | ||
enqueueSnackbar(registerSucces, { variant: "success" }); | ||
setCards(result[1]); | ||
} else enqueueSnackbar(registerFail, { variant: "error" }); | ||
}); | ||
}) | ||
.catch((error) => { | ||
if (isResponseNot200Error(error)) { | ||
error.response.json().then((response: CardPostResponse) => { | ||
if (response.is_current_user) | ||
enqueueSnackbar(requestYou, { variant: "warning" }); | ||
else | ||
enqueueSnackbar(requestOther, { variant: "error" }); | ||
}); | ||
} else enqueueSnackbar(requestFail, { variant: "error" }); | ||
}); | ||
|
||
const actions = ( | ||
<> | ||
<Button onClick={handleClose} color="error" variant="contained"> | ||
<CancelOutlined sx={{ mr: 1 }} /> | ||
<Typography>Cancel</Typography> | ||
</Button> | ||
<Button color="success" variant="contained"> | ||
<Add sx={{ mr: 1 }} /> | ||
<Typography>Register</Typography> | ||
</Button> | ||
</> | ||
); | ||
const handleClick = () => { | ||
confirm({ | ||
title: confirmTitle, | ||
description: confirmContent, | ||
confirmationText: "Register", | ||
}).then(() => startRegistering()); | ||
}; | ||
|
||
return ( | ||
<> | ||
<Button onClick={handleOpen} variant="contained" sx={{ my: "1%" }}> | ||
<Add /> | ||
<Typography>Register new card</Typography> | ||
</Button> | ||
<ConfirmationModal | ||
open={open} | ||
onClose={handleClose} | ||
title={title} | ||
content={content} | ||
actions={actions} | ||
></ConfirmationModal> | ||
</> | ||
<Button | ||
onClick={handleClick} | ||
variant="contained" | ||
sx={{ my: "1%" }} | ||
disabled={disabled} | ||
> | ||
<Add /> | ||
<Typography>Register new card</Typography> | ||
</Button> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.