aboutsummaryrefslogtreecommitdiff
path: root/src/app/get-started/page.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/get-started/page.tsx')
-rw-r--r--src/app/get-started/page.tsx206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/app/get-started/page.tsx b/src/app/get-started/page.tsx
new file mode 100644
index 0000000..75f04b0
--- /dev/null
+++ b/src/app/get-started/page.tsx
@@ -0,0 +1,206 @@
+"use client";
+
+import Spinner from "@/components/Spinner";
+import { motion } from "motion/react";
+import Form from "next/form";
+import { useActionState } from "react";
+import logFormData from "./actions";
+
+// Debug states for testing UI without sending email
+const debugSuccess = {
+ message:
+ "Sucessfully submitted your consultation request - expect to hear back soon via email!",
+ error: false,
+};
+
+const debugError = {
+ message:
+ "Failed to send email. This has been reported. Please try again later, and sorry for any inconvenience.",
+ error: true,
+};
+
+const initialState = {
+ message: "",
+ error: false,
+};
+
+export default function Home() {
+ // TODO: look up webdevsimplified video on forms in nextjs
+ const [state, formAction, pending] = useActionState(
+ logFormData,
+ initialState
+ );
+
+ return (
+ <div className="container mx-auto isolate px-4 py-6 sm:py-12 xl:py-16">
+ <div
+ aria-hidden="true"
+ className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
+ >
+ <div
+ style={{
+ clipPath:
+ "polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)",
+ }}
+ className="relative left-1/2 -z-10 aspect-1155/678 w-144.5 max-w-none -translate-x-1/2 rotate-30 bg-linear-to-br from-indigo-600 to-red-300 opacity-50 sm:left-[calc(50%-40rem)] sm:w-288.75"
+ />
+ </div>
+ <div className="mx-auto max-w-3xl outline outline-gray-700/20 rounded-xl p-6 shadow-lg shadow-gray-700/10 backdrop-blur-lg sm:p-10 bg-white/30">
+ <motion.div
+ className="mx-auto max-w-2xl text-center"
+ initial={{ opacity: 0, y: -20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5 }}
+ >
+ <h2 className="text-4xl font-semibold tracking-tight text-balance text-gray-900 sm:text-5xl">
+ Schedule a <span className="text-gradient">Free Consultation</span>
+ </h2>
+ <p className="mt-6 text-lg text-gray-600">
+ We want to have a 20 minute conversation with you to discuss your
+ needs and talk pricing - completely free and with no obligation.
+ </p>
+ </motion.div>
+
+ <Form action={formAction} className="mx-auto mt-8">
+ <motion.div
+ className="grid grid-cols-1 gap-x-8 gap-y-6 sm:grid-cols-2"
+ initial={{ opacity: 0, y: 20 }}
+ animate={{ opacity: 1, y: 0 }}
+ transition={{ duration: 0.5, delay: 0.1 }}
+ >
+ <div>
+ <label
+ htmlFor="firstname"
+ className="block text-sm/6 font-semibold text-gray-900"
+ >
+ First name
+ </label>
+ <div className="mt-2.5">
+ <input
+ id="firstname"
+ name="firstname"
+ type="text"
+ auto-complete="given-name"
+ className="block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600"
+ placeholder="First Name"
+ required
+ />
+ </div>
+ </div>
+ <div>
+ <label
+ htmlFor="lastname"
+ className="block text-sm/6 font-semibold text-gray-900"
+ >
+ Last Name
+ </label>
+ <div className="mt-2.5">
+ <input
+ id="lastname"
+ name="lastname"
+ type="text"
+ auto-complete="familyname"
+ className="block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600"
+ placeholder="Last Name"
+ required
+ />
+ </div>
+ </div>
+ <div>
+ <label
+ htmlFor="email"
+ className="block text-sm/6 font-semibold text-gray-900"
+ >
+ Email
+ </label>
+ <div className="mt-2.5">
+ <input
+ id="email"
+ name="email"
+ type="email"
+ auto-complete="email"
+ className="block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600"
+ placeholder="email@domain.com"
+ required
+ />
+ </div>
+ </div>
+ <div>
+ <label
+ htmlFor="phonenumber"
+ className="block text-sm/6 font-semibold text-gray-900"
+ >
+ Phone Number (optional)
+ </label>
+ <div className="mt-2.5">
+ <input
+ id="phonenumber"
+ name="phonenumber"
+ type="tel"
+ auto-complete="tel"
+ className="block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600"
+ placeholder="(216) 555-1234"
+ />
+ </div>
+ </div>
+ <div className="sm:col-span-2">
+ <label
+ htmlFor="message"
+ className="block text-sm/6 font-semibold text-gray-900"
+ >
+ Message
+ </label>
+ <div className="mt-2.5">
+ <textarea
+ id="message"
+ name="message"
+ rows={4}
+ className="block w-full rounded-md bg-white px-3.5 py-2 text-base text-gray-900 outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600"
+ placeholder="Please include a brief message about your (or your child's) needs - including subjects, grade levels, and any specific requests."
+ defaultValue={""}
+ ></textarea>
+ </div>
+ </div>
+ <div className="sm:col-span-2">
+ <motion.button
+ whileHover={{ scale: 1.02 }}
+ whileTap={{ scale: 0.9 }}
+ transition={{ type: "spring", stiffness: 400, damping: 17 }}
+ disabled={pending}
+ type="submit"
+ className="block w-full
+ rounded-md button-gradient
+ px-3.5 py-2.5 text-center text-md font-semibold text-white shadow-xs
+ hover:shadow-sm
+ disabled:bg-gray-600
+ hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
+ >
+ {pending ? (
+ <div className="flex items-center justify-center">
+ <Spinner /> <span>Submitting...</span>
+ </div>
+ ) : (
+ "Submit"
+ )}
+ </motion.button>
+ </div>
+ <div className="sm:col-span-2" hidden={!state.message}>
+ <div className="text-center block w-full">
+ {state.error ? (
+ <p className="font-semibold bg-red-50 rounded-md text-md outline-1 -outline-offset-1 outline-red-700 px-3 py-2 text-red-800">
+ <span className="font-bold">Error(!): </span>
+ {state.message}
+ </p>
+ ) : (
+ <p className="font-semibold bg-green-50 rounded-md text-md outline-1 -outline-offset-1 outline-green-700 px-3 py-2 text-green-800">
+ {state.message}
+ </p>
+ )}
+ </div>
+ </div>
+ </motion.div>
+ </Form>
+ </div>
+ </div>
+ );
+}