102 lines
3.2 KiB
TypeScript
102 lines
3.2 KiB
TypeScript
import {Ticket, TicketType, TicketTypeLabel} from "@/interfaces/ticket";
|
|
import {User} from "@/interfaces/user";
|
|
import axios from "axios";
|
|
import {useState} from "react";
|
|
import {toast} from "react-toastify";
|
|
import ShortUniqueId from "short-unique-id";
|
|
import Button from "../Low/Button";
|
|
import Input from "../Low/Input";
|
|
import Select from "../Low/Select";
|
|
|
|
interface Props {
|
|
user: User;
|
|
page: string;
|
|
onClose: () => void;
|
|
}
|
|
|
|
export default function TicketSubmission({user, page, onClose}: Props) {
|
|
const [subject, setSubject] = useState("");
|
|
const [type, setType] = useState<TicketType>();
|
|
const [description, setDescription] = useState("");
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
const submit = () => {
|
|
if (!type) return toast.error("Please choose a type!", {toastId: "missing-type"});
|
|
if (subject.trim() === "")
|
|
return toast.error("Please input a subject!", {
|
|
toastId: "missing-subject",
|
|
});
|
|
if (description.trim() === "")
|
|
return toast.error("Please describe your ticket!", {
|
|
toastId: "missing-desc",
|
|
});
|
|
|
|
setIsLoading(true);
|
|
|
|
const shortUID = new ShortUniqueId();
|
|
const ticket: Ticket = {
|
|
id: shortUID.randomUUID(8),
|
|
date: new Date().toISOString(),
|
|
reporter: {
|
|
id: user.id,
|
|
email: user.email,
|
|
name: user.name,
|
|
type: user.type,
|
|
},
|
|
status: "submitted",
|
|
subject,
|
|
type,
|
|
reportedFrom: page,
|
|
description,
|
|
};
|
|
|
|
axios
|
|
.post(`/api/tickets`, ticket)
|
|
.then(() => {
|
|
toast.success(`Your ticket has been submitted! You will be contacted by e-mail for further discussion.`, {toastId: "submitted"});
|
|
onClose();
|
|
})
|
|
.catch((e) => {
|
|
console.error(e);
|
|
toast.error("Something went wrong, please try again later!", {
|
|
toastId: "error",
|
|
});
|
|
})
|
|
.finally(() => setIsLoading(false));
|
|
};
|
|
|
|
return (
|
|
<form className="flex flex-col gap-4 pt-8">
|
|
<Input label="Subject" type="text" name="subject" placeholder="Subject..." onChange={(e) => setSubject(e)} />
|
|
<div className="-md:flex-col flex w-full items-center gap-4">
|
|
<div className="flex w-full flex-col gap-3">
|
|
<label className="text-mti-gray-dim text-base font-normal">Type</label>
|
|
<Select
|
|
options={Object.keys(TicketTypeLabel).map((x) => ({
|
|
value: x,
|
|
label: TicketTypeLabel[x as keyof typeof TicketTypeLabel],
|
|
}))}
|
|
onChange={(value) => setType((value?.value as TicketType) ?? undefined)}
|
|
placeholder="Type..."
|
|
/>
|
|
</div>
|
|
<Input label="Reporter" type="text" name="reporter" onChange={() => null} value={`${user.name} - ${user.email}`} disabled />
|
|
</div>
|
|
<textarea
|
|
className="input border-mti-gray-platinum h-full min-h-[300px] w-full cursor-text rounded-3xl border bg-white px-7 py-8"
|
|
onChange={(e) => setDescription(e.target.value)}
|
|
placeholder="Write your ticket's description here..."
|
|
spellCheck
|
|
/>
|
|
<div className="mt-2 flex w-full items-center justify-end gap-4">
|
|
<Button type="button" color="red" className="w-full max-w-[200px]" variant="outline" onClick={onClose} isLoading={isLoading}>
|
|
Cancel
|
|
</Button>
|
|
<Button type="button" className="w-full max-w-[200px]" isLoading={isLoading} onClick={submit}>
|
|
Submit
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
);
|
|
}
|