diff --git a/package-lock.json b/package-lock.json index fda014e..5a478c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,7 @@ "dependencies": { "grommet-icons": "^4.12.1", "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router-dom": "^6.23.1" + "react-dom": "^18.2.0" }, "devDependencies": { "@types/react": "^18.2.66", @@ -1074,14 +1073,6 @@ "node": ">=14" } }, - "node_modules/@remix-run/router": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz", - "integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==", - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.17.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", @@ -1741,12 +1732,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -2451,9 +2442,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -3492,36 +3483,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-router": { - "version": "6.23.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz", - "integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==", - "dependencies": { - "@remix-run/router": "1.16.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.23.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz", - "integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==", - "dependencies": { - "@remix-run/router": "1.16.1", - "react-router": "6.23.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/package.json b/package.json index d51a00d..7fb7e99 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,7 @@ "dependencies": { "grommet-icons": "^4.12.1", "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-router-dom": "^6.23.1" + "react-dom": "^18.2.0" }, "devDependencies": { "@types/react": "^18.2.66", diff --git a/src/components/ContactForm.tsx b/src/components/ContactForm.tsx new file mode 100644 index 0000000..e023781 --- /dev/null +++ b/src/components/ContactForm.tsx @@ -0,0 +1,128 @@ +import { useState, useEffect } from 'react'; +import InputBox from './InputBox'; + +export default function ContactForm() { + const [ error, setError ] = useState(""); + const [ success, setSuccess ] = useState(false); + const [ inputState, setInputState ] = useState<{name: string, email: string, subject: string, message: string}>({ + name: "", + email: "", + subject: "", + message: "" + }); + + const onSubmit = () => { + if ( + inputState.name === "" + || inputState.email === "" + || inputState.subject === "" + || inputState.message === "" + ) { + setError("A required field was missing") + } else { + console.log("Form submitted") + + fetch("https://api.alexav.gg/v4/contact", { + method: "post", + headers: { + 'content-type': 'application/json' + }, + body: JSON.stringify(inputState) + }).then((res) => { + if (res.ok) { + setSuccess(true) + } else { + setError("An error occurred while submitting your info.") + } + }).catch((e) => { + console.error(e) + setError("An error occurred while submitting your info.") + }) + } + } + + useEffect(() => { + setTimeout(() => { + setError("") + }, 6000) + }, [error]); + useEffect(() => { + setTimeout(() => { + setSuccess(false) + }, 6000) + }) + + return ( +
+

Contact Me

+
+ +
+ { + setInputState((prevState) => { + return { + ...prevState, + name: value + } + }) + }} + /> + { + setInputState((prevState) => { + return { + ...prevState, + email: value + } + }) + }} + /> + { + setInputState((prevState) => { + return { + ...prevState, + subject: value + } + }) + }} + /> + { + setInputState((prevState) => { + return { + ...prevState, + message: value + } + }) + }} + /> +
+ +
+ +

{error}

+

{ success && "Success! Your message has been received"}

+
+
+ ) +} \ No newline at end of file diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 7ff342b..ac9fee9 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -15,8 +15,9 @@ export default function Footer() { }, [mailState]) return ( -
+

© {new Date().getFullYear()}, Alex Frantz. All Rights Reserved

+

All logos & images on this page belong to their respective owners.

{ mailState ? ( diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 606706e..5364a5e 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,12 +1,8 @@ export default function Header() { return ( -
+

Alex Frantz

Professional button clicker & word typer

-
diff --git a/src/components/InputBox.tsx b/src/components/InputBox.tsx new file mode 100644 index 0000000..b395134 --- /dev/null +++ b/src/components/InputBox.tsx @@ -0,0 +1,36 @@ +export default function InputBox({ + name, + placeholder, + isText = true, + onChange +}: { + name: string, + isText?: boolean, + placeholder: string, + onChange: (value: string) => void +}) { + if (isText) { + return ( +
+ onChange(target.value)} + /> +
+ ) + } else { + return ( +
+