Upload files to "frontend/src/pages"

master
Joseph 2024-10-31 17:01:27 +00:00
parent b1ded0e922
commit 98485dc078
4 changed files with 270 additions and 0 deletions

View File

@ -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<number | null>(null);
const [bin, setBin] = useState<DreadBin | null>(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 (
<Error code={404} message="A request bin could not be found with the ID provided"/>
);
}
return (
<Error code={error} />
);
}
return (
<div className="m-8">
<Header row={loading ? <Spinner /> : (
<div className="flex items-center justify-between">
<p className="font-mono text-pink-500 font-bold select-none">
Your DreadBin endpoint:{" "}
<span className="font-mono select-all rounded-lg p-1 px-2 bg-black/25 text-neutral-300">
{process.env.REACT_APP_BASE_API_URL}/-/{id}
</span>
</p>
<Button
className={
"flex items-center justify-center disabled:cursor-not-allowed shadow-lg tracking-tight " +
"rounded-md bg-cyan-600 hover:bg-cyan-700 text-white font-semibold text-lg px-4 py-1"}
text="Refresh"
textClassName="font-mono"
onClick={() => setRefresh(Math.random())}
/>
</div>
)} />
{!loading && bin && (
Object.keys(bin.requests).length === 0 ? (
<div className="flex mt-8 gap-2">
<QuestionMarkCircleIcon className="h-6 w-6 text-white" />
<p className="font-bold text-white">No Requests Found</p>
</div>
) : (
<div className="flex gap-4 mt-8 flex-col">
{Object
.keys(bin.requests)
.sort((a, b) => bin.requests[a].timestamp > bin.requests[b].timestamp ? -1 : 1)
.map(requestId => <Request key={requestId} request={bin.requests[requestId]} />)}
</div>
)
)}
</div>
);
};
export default Bin;

View File

@ -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 (
<div className="m-8 select-none">
<Header />
<div className="mt-8">
<pre className="font-mono text-red-500 font-bold">
Code: {code}
</pre>
<pre className="font-mono text-red-500 font-bold">
Message: {message ? message : defaultMessage}
</pre>
</div>
<div className="mt-8 flex gap-4">
<Link
className="font-mono font-bold text-cyan-600 underline cursor-pointer"
to="/"
>
Go to Homepage.
</Link>
<a
className="font-mono font-bold text-cyan-600 underline cursor-pointer"
href="mailto:klez@cocaine.ninja"
>
Report an Issue.
</a>
</div>
</div>
);
};
export default Error;

View File

@ -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<string | null>(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 (
<div className="m-8 select-none">
<Header row={<>
<Button
loading={loading}
className={
"flex items-center justify-center disabled:cursor-not-allowed shadow-lg tracking-tight " +
"rounded-md bg-cyan-600 hover:bg-cyan-700 text-white font-semibold text-lg px-4 py-1"}
onClick={handleCreateBin}
text="Create a Bin"
textClassName="font-mono"
/>
{error && (
<p className="mt-3 font-bold font-mono text-red-600 text-sm flex gap-2 items-center">
<ExclamationCircleIcon className="w-5 h-5 inline-block" />
{error}
</p>
)}
</>} />
<div className="mt-16">
<h5 className="font-mono font-bold text-pink-600 mb-1">
# What can I do with this?
</h5>
<p className="ml-2 font-mono text-neutral-400 font-bold text-sm">
Anything you want really. Each request you make to the endpoint provided can be inspected, including:
</p>
<p className="ml-4 font-mono text-neutral-400 font-bold text-sm">- Request Method</p>
<p className="ml-4 font-mono text-neutral-400 font-bold text-sm">- Timestamp</p>
<p className="ml-4 font-mono text-neutral-400 font-bold text-sm">- Headers</p>
<p className="ml-4 font-mono text-neutral-400 font-bold text-sm">- Body (including formatting for common types)</p>
</div>
<div className="mt-8">
<h5 className="font-mono font-bold text-pink-600 mb-1">
# Is it open-source?
</h5>
<p className="ml-2 font-mono text-neutral-400 font-bold text-sm">
Yes.{" "}
<a
className="font-mono text-cyan-600 underline cursor-pointer"
target="_blank" rel="noreferrer noopener"
href="https://fsdfsd.net/Klez/DreadBin.git"
>
https://fsdfsd.net/Klez/DreadBin.git
</a>
</p>
</div>
<div className="mt-8">
<h5 className="font-mono font-bold text-pink-600 mb-1">
# Who made this <span className="font-mono font-extrabold">*amazing*</span> tool?
</h5>
<p className="ml-2 font-mono text-neutral-400 font-bold text-sm">
Me.{" "}
<a
className="font-mono text-cyan-600 underline cursor-pointer"
target="_blank" rel="noreferrer noopener"
href="https://dreadfulservices.xyz"
>
https://dreadfulservices.xyz
</a>
</p>
</div>
</div>
);
};
export default Landing;

View File

@ -0,0 +1,9 @@
import Landing from "./Landing";
import Error from "./Error";
import Bin from "./Bin";
export {
Landing,
Error,
Bin
};