feat: non-functional submit page
This commit is contained in:
parent
84a732c34d
commit
b35c0a53ea
6 changed files with 187 additions and 3 deletions
|
|
@ -17,6 +17,8 @@
|
|||
"next-auth": "5.0.0-beta.25",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-dropzone": "^14.3.8",
|
||||
"react-select": "^5.10.1",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export default async function Header() {
|
|||
const session = await auth();
|
||||
|
||||
return (
|
||||
<div className="sticky top-0 z-50 w-full p-4 grid grid-cols-3 gap-2 gap-x-4 items-center bg-amber-50 border-b-4 border-amber-200 shadow-md max-lg:grid-cols-2 max-sm:grid-cols-1">
|
||||
<div className="sticky top-0 z-50 w-full p-4 grid grid-cols-3 gap-2 gap-x-4 items-center bg-amber-50 border-b-4 border-amber-500 shadow-md max-lg:grid-cols-2 max-sm:grid-cols-1">
|
||||
<Link href={"/"} className="font-black text-3xl tracking-wide text-orange-400 max-sm:text-center max-sm:col-span-3">
|
||||
TomodachiShare
|
||||
</Link>
|
||||
|
|
|
|||
167
src/app/components/submit-form.tsx
Normal file
167
src/app/components/submit-form.tsx
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
"use client";
|
||||
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import CreatableSelect from "react-select/creatable";
|
||||
import { Icon } from "@iconify/react";
|
||||
|
||||
const options = [
|
||||
{ value: "anime", label: "anime" },
|
||||
{ value: "art", label: "art" },
|
||||
{ value: "cartoon", label: "cartoon" },
|
||||
{ value: "celebrity", label: "celebrity" },
|
||||
{ value: "games", label: "games" },
|
||||
{ value: "history", label: "history" },
|
||||
{ value: "meme", label: "meme" },
|
||||
{ value: "movie", label: "movie" },
|
||||
{ value: "oc", label: "oc" },
|
||||
{ value: "tv", label: "tv" },
|
||||
];
|
||||
|
||||
export default function SubmitForm() {
|
||||
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({
|
||||
accept: {
|
||||
"image/*": [".png", ".jpg", ".jpeg", ".bmp", ".webp"],
|
||||
},
|
||||
});
|
||||
|
||||
// todo: tag validating
|
||||
|
||||
return (
|
||||
<form onSubmit={(e) => e.preventDefault()} className="grid grid-cols-2">
|
||||
<div className="p-4">
|
||||
<div className="p-2 border-2 bg-orange-100 border-amber-500 rounded-2xl shadow-lg h-48">
|
||||
<div
|
||||
{...getRootProps({
|
||||
className:
|
||||
"bg-orange-100 flex flex-col justify-center items-center gap-2 p-4 rounded-xl border border-2 border-dashed border-amber-500 select-none h-full",
|
||||
})}
|
||||
>
|
||||
<input {...getInputProps({ multiple: false })} />
|
||||
<Icon icon="material-symbols:upload" fontSize={64} />
|
||||
<p className="text-center">
|
||||
Drag and drop your images here
|
||||
<br />
|
||||
or click to open
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* todo: show file list here */}
|
||||
</div>
|
||||
|
||||
<div className="p-4 flex flex-col gap-2">
|
||||
<div className="w-full grid grid-cols-3 items-center">
|
||||
<label htmlFor="name" className="font-semibold">
|
||||
Name
|
||||
</label>
|
||||
<input
|
||||
name="name"
|
||||
type="text"
|
||||
className="pill input w-full col-span-2"
|
||||
minLength={2}
|
||||
maxLength={64}
|
||||
placeholder="Type your mii's name here..."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="w-full grid grid-cols-3 items-center">
|
||||
<label htmlFor="tags" className="font-semibold">
|
||||
Tags
|
||||
</label>
|
||||
<CreatableSelect
|
||||
isMulti
|
||||
placeholder="Select or create tags..."
|
||||
options={options}
|
||||
className="pill input col-span-2 w-full !py-0.5"
|
||||
styles={{
|
||||
control: (provided) => ({
|
||||
...provided,
|
||||
border: "none",
|
||||
background: "transparent",
|
||||
width: "100%",
|
||||
boxShadow: "none",
|
||||
}),
|
||||
valueContainer: (provided) => ({
|
||||
...provided,
|
||||
padding: "0",
|
||||
}),
|
||||
multiValue: (provided) => ({
|
||||
...provided,
|
||||
borderRadius: "16px",
|
||||
padding: "2px 8px",
|
||||
backgroundColor: "var(--color-orange-300)",
|
||||
}),
|
||||
multiValueRemove: (provided) => ({
|
||||
...provided,
|
||||
cursor: "pointer",
|
||||
"&:hover": {
|
||||
backgroundColor: "transparent",
|
||||
color: "var(--color-black)",
|
||||
},
|
||||
}),
|
||||
indicatorsContainer: (provided) => ({
|
||||
...provided,
|
||||
"*": {
|
||||
padding: "1px",
|
||||
color: "black",
|
||||
cursor: "pointer",
|
||||
},
|
||||
}),
|
||||
indicatorSeparator: () => ({
|
||||
display: "none",
|
||||
}),
|
||||
placeholder: (provided) => ({
|
||||
...provided,
|
||||
color: "rgba(0, 0, 0, 0.4)",
|
||||
}),
|
||||
menu: (provided) => ({
|
||||
...provided,
|
||||
backgroundColor: "var(--color-orange-200)",
|
||||
border: "2px solid var(--color-orange-400)",
|
||||
borderRadius: "8px",
|
||||
}),
|
||||
option: (provided, { isFocused }) => ({
|
||||
...provided,
|
||||
backgroundColor: isFocused ? "rgba(0, 0, 0, 0.15)" : "var(--color-orange-200)",
|
||||
cursor: "pointer",
|
||||
padding: "2px 8px",
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<fieldset className="border-t-2 border-b-2 border-black p-3 flex flex-col items-center gap-2">
|
||||
<legend className="px-2">QR Code</legend>
|
||||
|
||||
<div className="p-2 border-2 bg-orange-100 border-amber-500 rounded-2xl shadow-lg w-full">
|
||||
<div
|
||||
{...getRootProps({
|
||||
className:
|
||||
"bg-orange-100 flex flex-col justify-center items-center gap-2 p-4 rounded-xl border border-2 border-dashed border-amber-500 select-none h-full",
|
||||
})}
|
||||
>
|
||||
<input {...getInputProps({ multiple: false })} />
|
||||
<Icon icon="material-symbols:upload" fontSize={48} />
|
||||
<p className="text-center text-sm">
|
||||
Drag and drop your QR code image here
|
||||
<br />
|
||||
or click to open
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span>or</span>
|
||||
|
||||
<button className="pill button gap-2">
|
||||
<Icon icon="mdi:camera" fontSize={20} />
|
||||
Use your camera
|
||||
</button>
|
||||
</fieldset>
|
||||
|
||||
<button type="submit" className="pill button w-min ml-auto">
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ export default function UsernameForm() {
|
|||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
required
|
||||
className="pill !bg-orange-200 outline-0 focus:ring-[3px] ring-orange-400/50 transition w-96 mt-8 mb-2"
|
||||
className="pill input w-96 mt-8 mb-2"
|
||||
/>
|
||||
|
||||
<button type="submit" className="pill button w-min">
|
||||
|
|
|
|||
|
|
@ -13,9 +13,13 @@ body {
|
|||
}
|
||||
|
||||
.pill {
|
||||
@apply flex justify-center items-center px-5 py-2 bg-orange-300 border-2 border-orange-400 rounded-full shadow-md;
|
||||
@apply flex justify-center items-center px-5 py-2 bg-orange-300 border-2 border-orange-400 rounded-4xl shadow-md;
|
||||
}
|
||||
|
||||
.button {
|
||||
@apply hover:bg-orange-400 transition cursor-pointer;
|
||||
}
|
||||
|
||||
.input {
|
||||
@apply !bg-orange-200 outline-0 focus:ring-[3px] ring-orange-400/50 transition placeholder:text-black/40;
|
||||
}
|
||||
|
|
|
|||
11
src/app/submit/page.tsx
Normal file
11
src/app/submit/page.tsx
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import { redirect } from "next/navigation";
|
||||
import { auth } from "@/lib/auth";
|
||||
import SubmitForm from "../components/submit-form";
|
||||
|
||||
export default async function SubmitPage() {
|
||||
const session = await auth();
|
||||
|
||||
if (!session) redirect("/login");
|
||||
|
||||
return <SubmitForm />;
|
||||
}
|
||||
Loading…
Reference in a new issue