diff --git a/public/pulsatingMap.jpg b/public/pulsatingMap.jpg new file mode 100644 index 0000000..c1e64d7 Binary files /dev/null and b/public/pulsatingMap.jpg differ diff --git a/src/app/contact-us/page.tsx b/src/app/contact-us/page.tsx index d527b37..b8688b2 100644 --- a/src/app/contact-us/page.tsx +++ b/src/app/contact-us/page.tsx @@ -1,28 +1,150 @@ "use client"; import Image from "next/image"; -import React, { useState } from "react"; +import React, { useCallback, useEffect, useRef, useState } from "react"; + import BottomFooter from "@components/BottomFooter"; const ContactUs = () => { - const [formData, setFormData] = useState({ - name: "", - email: "", - message: "", - }); + // Form/modal + const [formData, setFormData] = useState({ name: "", email: "", message: "" }); + const [isModalOpen, setIsModalOpen] = useState(false); - const handleChange = (e: { target: { name: any; value: any } }) => { + // 1. Lava (Instagram): state & timer + const [lavaActive, setLavaActive] = useState(false); + const lavaTimeout = useRef(null); + + // 2. Pulsating Map (Facebook): state & timer + const [pulsatingActive, setPulsatingActive] = useState(false); + const pulsatingTimeout = useRef(null); + + // 3. Shake (LinkedIn): state & timer + const [shaking, setShaking] = useState(false); + const shakeTimeout = useRef(null); + + // 4. Crack & Collapse (X): state & timer + const [showCracks, setShowCracks] = useState(false); + const [collapse, setCollapse] = useState(false); + const crackTimeout = useRef(null); + + // Lava flood handler (top-down flood) + const handleInstagramClick = useCallback((e: React.MouseEvent) => { + e.preventDefault(); + setLavaActive(true); + if (lavaTimeout.current) clearTimeout(lavaTimeout.current); + lavaTimeout.current = setTimeout(() => setLavaActive(false), 2000); + }, []); + + // Pulsating Map handler + const handleFacebookClick = useCallback((e: React.MouseEvent) => { + e.preventDefault(); + setPulsatingActive(true); + if (pulsatingTimeout.current) clearTimeout(pulsatingTimeout.current); + pulsatingTimeout.current = setTimeout(() => setPulsatingActive(false), 2000); + }, []); + + // LinkedIn shake handler + const handleLinkedInClick = useCallback( + (e: React.MouseEvent) => { + e.preventDefault(); + if (shaking) return; + setShaking(true); + const body = document.body; + body.classList.remove("shake-screen"); + void body.offsetWidth; + body.classList.add("shake-screen"); + if (shakeTimeout.current) clearTimeout(shakeTimeout.current); + shakeTimeout.current = setTimeout(() => { + setShaking(false); + body.classList.remove("shake-screen"); + }, 1000); + }, + [shaking] + ); + + // X (crack and collapse) handler + const handleXClick = useCallback((e: React.MouseEvent) => { + e.preventDefault(); + setShowCracks(true); + if (crackTimeout.current) clearTimeout(crackTimeout.current); + crackTimeout.current = setTimeout(() => { + setCollapse(true); + setTimeout(() => { + setShowCracks(false); + setCollapse(false); + }, 1500); + }, 1000); + }, []); + + // Clean up timeouts and shake class + useEffect(() => { + return () => { + if (lavaTimeout.current) clearTimeout(lavaTimeout.current); + if (pulsatingTimeout.current) clearTimeout(pulsatingTimeout.current); + if (shakeTimeout.current) clearTimeout(shakeTimeout.current); + if (crackTimeout.current) clearTimeout(crackTimeout.current); + document.body.classList.remove("shake-screen"); + }; + }, []); + + // Form handlers + const handleChange = (e: React.ChangeEvent) => { setFormData({ ...formData, [e.target.name]: e.target.value }); }; - - const handleSubmit = (e: { preventDefault: () => void }) => { + const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); console.log("Form submitted with data:", formData); - alert("Thank you for reaching out! We will get back to you soon."); + setIsModalOpen(true); setFormData({ name: "", email: "", message: "" }); }; return (
+ {/* Lava Flood Overlay */} + {lavaActive && ( +
+ Lava flood +
+ )} + {/* Pulsating Overlay */} + {pulsatingActive && ( +
+ Pulsating Map +
+ )} + {/* Crack & Collapse Overlay */} + {(showCracks || collapse) && ( +
+ + +
+ )} + {/* Modal: Submit Success */} + {isModalOpen && ( +
+
+

Thank You!

+

Thank you for submitting a message. We will be responding via our email.

+ +
+
+ )} { className="border border-neutral-300 absolute z-10 -top-20" src="/tsunamiWaves.jpg" /> - {/* Overlay for readability */}
{/* Container */} @@ -41,8 +162,6 @@ const ContactUs = () => { Have questions or concerns about earthquakes, observatories or artefacts? Contact us via phone, email, social media or using the form below with the relevant contact details.

- - {/* Content Section */}
{/* Contact Form Section */}
@@ -62,7 +181,6 @@ const ContactUs = () => { required />
-
-
-
- {/* Contact Details Section */}

Get in Touch

@@ -120,23 +235,51 @@ const ContactUs = () => {

Address

-

1 Swentown Row, Greenwich, London, SE3 0FQ

+

1 Sweentown Row, Greenwich, London, SE3 0FQ

Follow Us

- + ); }; diff --git a/src/app/shop/page.tsx b/src/app/shop/page.tsx index 4365800..f39be36 100644 --- a/src/app/shop/page.tsx +++ b/src/app/shop/page.tsx @@ -191,7 +191,6 @@ export default function Shop() { // todo create receiving api route // todo handle sending to api route - // todo only ask for email if the user is not signed in // todo (optional) add create account button to auto-fill email in sign-up modal const genOrder = () => "#" + Math.random().toString(36).substring(2, 10).toUpperCase(); setOrderNumber(genOrder());