diff --git a/frontend/src/pages/Bin.tsx b/frontend/src/pages/Bin.tsx new file mode 100644 index 0000000..57b93fb --- /dev/null +++ b/frontend/src/pages/Bin.tsx @@ -0,0 +1,96 @@ +import React, { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; +import { Header, Spinner, Request, Button } from "../components"; +import { Error } from "../pages"; +import { DreadBin, DreadBinResponse } from "../types"; +import { QuestionMarkCircleIcon } from "@heroicons/react/solid"; + +const Bin = () => { + const { id } = useParams(); + + const [loading, setLoading] = useState(false); + const [refresh, setRefresh] = useState(0); + const [error, setError] = useState(null); + const [bin, setBin] = useState(null); + + useEffect(() => { + const interval = setInterval(() => { + setRefresh(Math.random()); + }, 1500); + + return () => clearInterval(interval); + }, []); + + useEffect(() => { + (async () => { + try { + setLoading(true); + + const response = await fetch(`${process.env.REACT_APP_BASE_API_URL}/${id}`); + const body = await response.json() as DreadBinResponse; + + if (response.ok) + setBin(body.bin); + else + setError(response.status); + + setLoading(false); + } catch (_) { + setError(500); + setLoading(false); + } + })(); + }, [id, refresh]); + + if (error) { + if (error === 404) { + return ( + + ); + } + + return ( + + ); + } + + return ( +
+
: ( +
+

+ Your DreadBin endpoint:{" "} + + {process.env.REACT_APP_BASE_API_URL}/-/{id} + +

+
+ )} /> + {!loading && bin && ( + Object.keys(bin.requests).length === 0 ? ( +
+ +

No Requests Found

+
+ ) : ( +
+ {Object + .keys(bin.requests) + .sort((a, b) => bin.requests[a].timestamp > bin.requests[b].timestamp ? -1 : 1) + .map(requestId => )} +
+ ) + )} +
+ ); +}; + +export default Bin; diff --git a/frontend/src/pages/Error.tsx b/frontend/src/pages/Error.tsx new file mode 100644 index 0000000..05ef555 --- /dev/null +++ b/frontend/src/pages/Error.tsx @@ -0,0 +1,58 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { Header } from "../components"; + +interface ErrorProps { + code: number, + message?: string +} + +const Error = (props: ErrorProps) => { + const { code, message } = props; + + let defaultMessage: string; + + switch (code) { + case 404: + defaultMessage = "The requested resource could not be found"; + break; + case 401 || 403: + defaultMessage = "You don't have permission to access this resource"; + break; + default: + defaultMessage = "An unknown error occurred"; + break; + } + + return ( +
+
+ +
+
+					Code:    {code}
+				
+
+					Message: {message ? message : defaultMessage}
+				
+
+ +
+ + Go to Homepage. + + + Report an Issue. + +
+
+ ); +}; + +export default Error; diff --git a/frontend/src/pages/Landing.tsx b/frontend/src/pages/Landing.tsx new file mode 100644 index 0000000..8f1d28c --- /dev/null +++ b/frontend/src/pages/Landing.tsx @@ -0,0 +1,107 @@ +import React, { useState } from "react"; +import { Header, Button } from "../components"; +import { ExclamationCircleIcon } from "@heroicons/react/solid"; +import { useNavigate } from "react-router-dom"; +import { DreadBinResponse, ErrorResponse } from "../types"; + +const Landing = () => { + const navigate = useNavigate(); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + + const handleCreateBin = async () => { + setError(null); + setLoading(true); + + try { + const response = await fetch(`${process.env.REACT_APP_BASE_API_URL}/create`, { + method: "POST" + }); + + if (response.ok) { + const body = await response.json() as DreadBinResponse; + navigate(`/${body.bin.id}`); + + return; + } + + const body = await response.json() as ErrorResponse; + + setError(body.message); + } catch (_) { + setError("An unknown error occurred"); + } + + setLoading(false); + }; + + return ( +
+
+
+ ); +}; + +export default Landing; diff --git a/frontend/src/pages/index.tsx b/frontend/src/pages/index.tsx new file mode 100644 index 0000000..3c1292a --- /dev/null +++ b/frontend/src/pages/index.tsx @@ -0,0 +1,9 @@ +import Landing from "./Landing"; +import Error from "./Error"; +import Bin from "./Bin"; + +export { + Landing, + Error, + Bin +};