Add contact form
This commit is contained in:
parent
107ee8794d
commit
3866e8ade0
7
src/app/api/test/route.ts
Normal file
7
src/app/api/test/route.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
export function GET (req: Request) {
|
||||
console.log(req.headers.get("x-forwarded-for") ?? 'damn');
|
||||
|
||||
return NextResponse.json({ status: "ok" });
|
||||
}
|
||||
@ -22,7 +22,7 @@
|
||||
animation-timing-function: linear(0.2, 0.8, 1);
|
||||
}
|
||||
50% {
|
||||
transform: translate(0px, -180px) scale(1.18, 0.9);
|
||||
transform: translate(0px, -120px) scale(1.18, 0.9);
|
||||
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
96
src/components/form/contact-form.tsx
Normal file
96
src/components/form/contact-form.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
'use client'
|
||||
|
||||
import { ChangeEvent, useRef, useState } from "react";
|
||||
import { CheckboxInput, Input, Submit } from "./form";
|
||||
import { FloatingLabel } from "../floating-label";
|
||||
|
||||
export default function ContactForm() {
|
||||
const [anon, setAnon] = useState(false);
|
||||
const formRef = useRef<HTMLFormElement | null>(null);
|
||||
const [status, setStatus] = useState<'success' | 'loading' | 'failed' | 'idle'>('idle');
|
||||
const [errorMsg, setErrorMsg] = useState("");
|
||||
|
||||
const statusMsg = {
|
||||
success: 'Sended!',
|
||||
loading: 'Sending...',
|
||||
failed: 'Failed :(',
|
||||
idle: 'Send!'
|
||||
}
|
||||
|
||||
const send = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
setStatus('idle');
|
||||
setErrorMsg('');
|
||||
|
||||
if (status == 'loading' || !formRef.current) return;
|
||||
|
||||
const formData = new FormData(formRef.current);
|
||||
|
||||
const data = {
|
||||
anon,
|
||||
name: formData.get('name')?.toString(),
|
||||
email: formData.get('email')?.toString(),
|
||||
message: formData.get('message')!.toString()
|
||||
}
|
||||
|
||||
if ((data.name && data.email) && (data.name.length < 1 || data.email.length < 1) && !data.anon) {
|
||||
setErrorMsg("Name and email are required. If you prefer not to provide them, check the box to send anonymously.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.message.length < 1) {
|
||||
setErrorMsg("What do you want to tell me???");
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus('loading');
|
||||
//process
|
||||
|
||||
await new Promise(res => setTimeout(res, 2000));
|
||||
setStatus('success');
|
||||
}
|
||||
|
||||
return (
|
||||
<form action="POST" className="space-y-4" ref={formRef} onSubmit={send}>
|
||||
<FloatingLabel placeholder="Leave an anonymous message, but I won't answer it">
|
||||
<CheckboxInput
|
||||
name="anon"
|
||||
placeholder="Send anonymously🤫"
|
||||
onChange={setAnon}
|
||||
/>
|
||||
</FloatingLabel>
|
||||
{!anon && <>
|
||||
<label className="block" htmlFor="contact-name">
|
||||
<div className="mb-2">Name</div>
|
||||
<Input
|
||||
id="contact-name"
|
||||
className="w-full"
|
||||
name="name"
|
||||
type="text"
|
||||
placeholder="Any name you want me to know"
|
||||
/>
|
||||
</label>
|
||||
<label className="block" htmlFor="contact-email">
|
||||
<div className="mb-2">Email</div>
|
||||
<Input
|
||||
id="contact-email"
|
||||
className="w-full"
|
||||
name="email"
|
||||
type="email"
|
||||
/>
|
||||
</label>
|
||||
</>}
|
||||
<label className="block" htmlFor="contact-msg">
|
||||
<div className="mb-2">Message</div>
|
||||
<textarea
|
||||
name="message"
|
||||
id="contact-msg"
|
||||
className="max-h-96 h-32 w-full p-3 bg-background border border-primary"
|
||||
placeholder="Tell me something cool, or ask question"
|
||||
/>
|
||||
</label>
|
||||
<div className="text-primary">{errorMsg}</div>
|
||||
<Submit className="w-full">{statusMsg[status]}</Submit>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
49
src/components/form/form.tsx
Normal file
49
src/components/form/form.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
'use client'
|
||||
|
||||
import clsx from "clsx";
|
||||
import { Icon } from "@iconify/react";
|
||||
import { useState } from "react";
|
||||
|
||||
export function Input ({ className, type, ...props }: React.ComponentProps<'input'>) {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
className={clsx("block py-3 px-4 bg-background text-white border border-primary", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function Submit ({ className, type, ...props }: React.ComponentProps<'button'>) {
|
||||
return (
|
||||
<button
|
||||
type={'submit'}
|
||||
className={clsx("block py-3 px-4 bg-primary text-background", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
interface CheckboxInputProps {
|
||||
name: string,
|
||||
placeholder: string,
|
||||
onChange: (value: boolean) => void
|
||||
}
|
||||
|
||||
export function CheckboxInput ({ placeholder, name, onChange }: CheckboxInputProps) {
|
||||
const [checked, setCheck] = useState(false);
|
||||
|
||||
const onClick = () => {
|
||||
setCheck(c => !c);
|
||||
onChange(!checked);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<button type="button" id={`checkbox-${name}`} className="inline-block bg-none border border-primary w-4 h-4" onClick={onClick}>
|
||||
{checked && <Icon icon="lucide:check" className="text-primary" />}
|
||||
</button>
|
||||
<label htmlFor={`checkbox-${name}`} className="ps-2 inline-block">{placeholder}</label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -2,11 +2,11 @@ import Image from "next/image"
|
||||
import { FloatingLabel } from "./floating-label"
|
||||
|
||||
export const LandingImage = () => (
|
||||
<FloatingLabel placeholder="Coral Glasses ❤️. Alert: NOT MY WORK! See the end of the page">
|
||||
<FloatingLabel placeholder="ENA ❤️. Alert: NOT MY WORK!">
|
||||
<Image
|
||||
className="mb-8 mx-auto"
|
||||
className="mb-8 mx-auto h-auto"
|
||||
alt="Coral <3"
|
||||
src="https://media1.tenor.com/m/RIP2rxKM_FgAAAAC/ena-ena-dream-bbq.gif"
|
||||
src="https://media.tenor.com/1BCeG1aTiBAAAAAd/temptation-stairway-ena.gif"
|
||||
width={280}
|
||||
height={280}
|
||||
unoptimized
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import Image from "next/image"
|
||||
import Link from "@/components/link";
|
||||
import { FloatingLabel } from "@/components/floating-label";
|
||||
import ContactForm from "@/components/form/contact-form";
|
||||
|
||||
Welcome!
|
||||
|
||||
@ -8,6 +9,8 @@ This is our cozy little corner of the internet where we run services and website
|
||||
|
||||
We've got tools, resources, game server and other stuff that just works and doesn't burn our wallet, maybe.
|
||||
|
||||
I love putting silly favorite characters on this site
|
||||
|
||||
## About Me
|
||||
|
||||
Nomi Nonszy (also known as Nonszy, Nomi Nonsense, whatever).
|
||||
@ -15,9 +18,9 @@ I write code, do some art, and make sure our server doesn't catch on fire lol.
|
||||
|
||||
I build sick web apps with modern stacks. Big fan of open-source stuff.
|
||||
Hate something that make things overengineered and boilerplate, but still use them anyway.
|
||||
I only play indie games, and cooking up cursed mods just for fun.
|
||||
Love with indie games, and cooking up cursed mods just for fun.
|
||||
|
||||
Multifandom with Psychopomp, Deltarune, and ENA! I'm currently dedicated to the ENA SERIES!! Especially <Link href="https://enajoelg.fandom.com/wiki/Coral_Glasses" target="_blank">Coral Glasses</Link> my beloved wife ❤️
|
||||
Multifandom with Psychopomp, Deltarune, and ENA! I'm currently dedicated to the ENA SERIES!!
|
||||
|
||||
<Image
|
||||
className="mb-12 mx-auto"
|
||||
@ -87,6 +90,7 @@ and published under the ENA Team. She speaks Korean in the game and is voiced by
|
||||
|
||||
The game is part of the surreal and artistically distinct ENA universe, which expands upon his earlier animated web series of the same name.
|
||||
|
||||
She's supposed to handle business stuff, but she's sweating, faxing out of her hairline, and spiraling into mild panic every five minutes
|
||||
|
||||
She's cute, anxious, awkward, weird, beautiful and i swear, she's literally me at work sweating through every conversation ashdjakwoiqhkaslchmaujqk
|
||||
## Tell me something
|
||||
|
||||
<ContactForm />
|
||||
@ -7,7 +7,7 @@ const events: EventsDate[] = [
|
||||
{
|
||||
name: 'christmas',
|
||||
start: [12, 20],
|
||||
end: [12, 30]
|
||||
end: [12, 32]
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user