"use client"; import theme from "@/theme"; import { Button, ChakraProvider, Container, Flex, Heading, Image, Input, Text, Box, Separator, } from "@chakra-ui/react"; import { useEffect, useState, useRef, Suspense } from "react"; import { useSearchParams } from "next/navigation"; import { toaster } from "@/components/ui/toaster"; import { getRandomResultFromGCI, lmgcitfy } from "@/actions"; export default function Home() { // state shit const [query, setQuery] = useState(""); const [loading, setLoading] = useState(false); const [link, setLink] = useState(""); // animation refs const inputRef = useRef(null); const normalButtonRef = useRef(null); const luckyButtonRef = useRef(null); const cursorRef = useRef(null); // query shit const passedInParams = useSearchParams(); const passedInQuery = passedInParams.get("query"); const isFeelingLucky = passedInParams.get("lucky"); // handle shit const handleGenerateLink = async (feelingLucky: boolean) => { if (!query) { toaster.error({ description: "You must provide a search query." }); return; } const queryParams = new URLSearchParams(); queryParams.append("query", query); try { setLoading(true); let result: APIResult; if (feelingLucky) { queryParams.append("lucky", "true"); result = await getRandomResultFromGCI(query); } else { result = await lmgcitfy(query); } if (result.error) { toaster.create({ type: "error", title: "Error", description: result.errorMessage, }); return; } setLink( `${window.location.protocol}//${window.location.host}/?${queryParams.toString()}`, ); } catch (error) { if (error instanceof Error) { toaster.error({ description: error.message }); return; } toaster.error({ description: "Something went wrong." }); return; } finally { setLoading(false); } }; const handleCursorMove = () => { requestAnimationFrame(() => { // we have to stack this because browser paints the first render, then we request twice to paint the third render which applies the necessary changes for the transition (gay) requestAnimationFrame(() => { const input = inputRef.current!.getBoundingClientRect(); const inputTargetWidth = input.x + input.width / 3; const inputTargetHeight = input.y + input.height / 2; cursorRef.current!.style.left = `${inputTargetWidth}px`; cursorRef.current!.style.top = `${inputTargetHeight}px`; }); }); }; useEffect(() => { if (!passedInQuery) { return; } const handleMoveToButton = () => { let buttonRef; if (isFeelingLucky === "true") { buttonRef = luckyButtonRef; } else { buttonRef = normalButtonRef; } const boundingRect = buttonRef.current!.getBoundingClientRect(); const buttonX = boundingRect.x + boundingRect.width / 2; const buttonY = boundingRect.y + boundingRect.height / 2; cursorRef.current!.style.left = `${buttonX}px`; cursorRef.current!.style.top = `${buttonY}px`; setTimeout(() => { buttonRef.current!.style.scale = `0.95`; }, 1250); setTimeout(() => { buttonRef.current!.style.scale = `1`; }, 1750); setTimeout(() => { toaster.create({ type: "success", title: "LMGCITFY", description: "Was that so hard?", }); }, 3000); }; const handleTypingAnimation = () => { setTimeout(() => { const chars = passedInQuery!.split(""); let counter = 0; const intervalId = setInterval(() => { if (inputRef.current!.value.length < chars.length) { const splitValue = inputRef.current!.value.split(""); splitValue.push(chars[counter]); inputRef.current!.value = splitValue.join(""); counter++; } if (chars.length === inputRef.current!.value.length) { clearInterval(intervalId); handleMoveToButton(); } }, 75); }, 2000); }; const getGCILink = async () => { let result: APIResult; if (isFeelingLucky === "true") { result = await getRandomResultFromGCI(passedInQuery); } else { result = await lmgcitfy(passedInQuery); } if (result.error) { toaster.create({ type: "error", title: "Error", description: result.errorMessage, }); return; } const link = result.payload; setTimeout(() => (window.location.href = link), 9000); }; handleCursorMove(); handleTypingAnimation(); getGCILink(); }, [passedInQuery, isFeelingLucky]); return ( Fake cursor 0 ? "visible" : "hidden"} position={"fixed"} top={0} left={0} zIndex={1000} transition={"top 2s, left 2s"} /> GunCAD Index logo GunCAD Index A search engine for guns. setQuery(e.target.value)} /> ); }