import React, {useEffect, useState, useContext} from "react";
import {useLocation} from "react-router-dom";
import {encode} from "base64-arraybuffer";
import {getSubreactFromLocation} from "helpers/Location.jsx";
import {UserContext} from "contexts/UserContext.jsx";
import {StateContext} from "contexts/StateContext.jsx";
import Card from "components/card/Card.jsx";
import Button from "components/button/Button.jsx";
import Input from "components/input/Input.jsx";
import Loading from "components/loading/Loading.jsx";
import styles from "./Submission.css";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faMinus, faPlus} from "@fortawesome/free-solid-svg-icons";
import {getFieldError, correctFieldAnimate, isSupportedExtension} from "helpers/Input.jsx";
const maxFileSize = 4 * 1000 * 1000; // 4MB max size
const validateTitle = (title) => getFieldError(title?.target?.value, [3, 128]);
const validateContents = (contents) => getFieldError(contents?.target?.value, [5, 3000]);
function validateFile(file) {
const files = file?.target?.files;
if (files == null || files.length == 0) {
return "Required";
}
const f = files.item(0);
if (f.size > maxFileSize) { // 4MB
return "File too large, exceeded 4MB";
}
const ext = f.name.split(".")?.pop()?.toLowerCase();
if (!isSupportedExtension(ext)) {
return "Unsupported image extension";
}
return null;
}
function ErrorMessage({message}) {
return (
);
}
function RequestButton({promise, setPromise, title, setTitle, contents, setContents,
file, setFile, setError, className, children, setSubmissionActive, subreact}) {
const onClick = (event) => {
event.preventDefault();
if (promise != null) {
return;
}
setError(null);
const titleErrors = validateTitle(title);
const contentsErrors = validateContents(contents);
const fileErrors = validateFile(file);
if (titleErrors != null || contentsErrors != null || fileErrors != null) {
correctFieldAnimate(title, setTitle, titleErrors);
correctFieldAnimate(contents, setContents, contentsErrors);
correctFieldAnimate(file, setFile, fileErrors);
return;
}
setPromise(file.target.files.item(0).arrayBuffer()
.then((buffer) => {
const init = {
method: "POST",
headers: {
'Content-Type': "application/json"
},
body: JSON.stringify({
"title": title.target.value,
"contents": contents.target.value,
"subreact": subreact,
"file": encode(buffer),
}),
referrer: "same-origin",
};
return fetch("/api/post", init);
})
.then((response) => {
if (response.ok) {
setSubmissionActive(false);
setContents(null);
setTitle(null);
setFile(null);
return;
}
return response.json()
.then((json) => {
if ("error" in json) {
throw new Error(json.error);
}
throw new Error("unexpected data received");
});
})
.catch((error) => {
console.log(error);
setError(error.message);
})
.finally(() => {
setPromise(null);
}));
}
return (
);
}
function TabIcon({icon, submissionActive, isDefault}) {
return (
);
}
function Tab({submissionActive, setSubmissionActive, user, setLoginActive}) {
const [animate, setAnimate] = useState(false);
const onClick = () => {
if (user === null) {
setLoginActive(true);
return;
}
setAnimate(true);
setSubmissionActive(!submissionActive);
};
return (
);
}
function SubmissionForm({setSubmissionActive, setError, subreact}) {
const [promise, setPromise] = useState(null);
const [title, setTitle] = useState(null);
const [contents, setContents] = useState(null);
const [file, setFile] = useState(null);
return (
);
}
export default function Submission({active, setActive}) {
const [error, setError] = useState(null);
const location = useLocation();
const subreact = getSubreactFromLocation(location);
const [user] = useContext(UserContext);
const [state, setState] = useContext(StateContext);
const setLoginActive = (active) => {setState({...state, loginActive: active})};
// If our subreact is the front page, disable our ability to post. Posting
// should be done to the main subreact.
useEffect(() => {
if (subreact === "") {
setActive(false);
}
}, [location]);
return (
Make a new submission
);
}