Add ContactForm component and utility functions; update Navbar styles

This commit is contained in:
ASOwnerYT
2025-04-04 02:11:26 +00:00
parent 900a43fb0e
commit c5968f2876
12 changed files with 874 additions and 88 deletions
+69
View File
@@ -0,0 +1,69 @@
import styles from "./ContactForm.module.css";
export default function ContactForm() {
return (
<div>
<h2 className="text-3xl font-bold mb-4">Contact Us</h2>
<div className={styles.contactDetails}>
<h3 className="text-lg font-bold hover:underline">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
width="1em"
>
<path
fillRule="evenodd"
d="M2 3.5A1.5 1.5 0 0 1 3.5 2h1.148a1.5 1.5 0 0 1 1.465 1.175l.716 3.223a1.5 1.5 0 0 1-1.052 1.767l-.933.267c-.41.117-.643.555-.48.95a11.542 11.542 0 0 0 6.254 6.254c.395.163.833-.07.95-.48l.267-.933a1.5 1.5 0 0 1 1.767-1.052l3.223.716A1.5 1.5 0 0 1 18 15.352V16.5a1.5 1.5 0 0 1-1.5 1.5H15c-1.149 0-2.263-.15-3.326-.43A13.022 13.022 0 0 1 2.43 8.326 13.019 13.019 0 0 1 2 5V3.5Z"
clipRule="evenodd"
/>
</svg>
<a href="tel:+640211077483">021 107 7483</a>
</h3>
<h3 className="text-lg font-bold hover:underline">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
width="1em"
>
<path
fillRule="evenodd"
d="M5.404 14.596A6.5 6.5 0 1 1 16.5 10a1.25 1.25 0 0 1-2.5 0 4 4 0 1 0-.571 2.06A2.75 2.75 0 0 0 18 10a8 8 0 1 0-2.343 5.657.75.75 0 0 0-1.06-1.06 6.5 6.5 0 0 1-9.193 0ZM10 7.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5Z"
clipRule="evenodd"
/>
</svg>
<a href="mailto:[email protected]">
info@teatatucomputers.com
</a>
</h3>
</div>
<form
action="https://form.taxi/s/es9ddva1"
method="POST"
className={styles.form}
>
<label htmlFor="Name">Name*</label>
<input type="text" name="Name" required />
<label htmlFor="Phone">Phone Number </label>
<input type="tel" name="Phone" />
<label htmlFor="Email">Email*</label>
<input type="email" name="Email" required />
<label htmlFor="firstname">Message*</label>
<textarea name="Message"></textarea>
<p className={styles.sm}>* required</p>
<input
type="submit"
value="Submit"
required
className="text-white bg-sky-800 hover:bg-sky-700 transition"
/>
</form>
</div>
);
}
@@ -1,7 +1,3 @@
.form {
margin-bottom: 35em;
}
.form input[type="text"],
.form input[type="email"],
.form input[type="tel"],
@@ -26,8 +22,8 @@
}
.sm {
font-size: 0.75em;
font-style: italic;
font-size: 0.75em;
font-style: italic;
}
.contactDetails {
@@ -42,4 +38,4 @@
.contactDetails h3 a {
color: black;
}
}
+67 -12
View File
@@ -8,6 +8,7 @@ import logo from "../assets/logo.svg";
import menu from "../assets/menu.svg";
import close from "../assets/close.svg";
import { usePathname } from "next/navigation";
import { ChevronDownIcon } from "lucide-react";
// import { motion } from "motion/react"
export default function Navbar() {
@@ -82,33 +83,87 @@ export default function Navbar() {
${styles.dropdown}
${isDropdownActive && !isActive ? styles.dropdownActive : ""}
`}
onMouseEnter={() => setDropdownActive(true)}
onMouseLeave={() => setDropdownActive(false)}
>
<a
className={`${styles.dropdownTitle}
${pathname === "/services" ? styles.active : ""}`}
onClick={handleDropdownToggle}
<div
data-state={isDropdownActive ? "open" : "close"}
className="flex items-center justify-center gap-1 [&[data-state=open]>svg]:rotate-180"
>
Services
</a>
<a
className={`${styles.dropdownTitle}
${pathname === "/services" ? styles.active : ""}`}
onClick={handleDropdownToggle}
>
Services
</a>
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
</div>
<ul className={styles.dropdownMenu}>
<li>
<Link href="/services/computer-repair" className={`link ${pathname === "/services/computer-repair" ? styles.active : ""}`}>Computer & Laptop Repairs</Link>
<Link
href="/services/computer-repair"
className={`link ${
pathname === "/services/computer-repair"
? styles.active
: ""
}`}
>
Computer & Laptop Repairs
</Link>
</li>
<li>
<Link href="/services/computer-upgrades" className={`link ${pathname === "/services/computer-upgrades" ? styles.active : ""}`}>Computer Upgrades & Speedup</Link>
<Link
href="/services/computer-upgrades"
className={`link ${
pathname === "/services/computer-upgrades"
? styles.active
: ""
}`}
>
Computer Upgrades & Speedup
</Link>
</li>
<li>
<Link href="/services/it-support" className={`link ${pathname === "/services/it-support" ? styles.active : ""}`}>IT Support</Link>
<Link
href="/services/it-support"
className={`link ${
pathname === "/services/it-support" ? styles.active : ""
}`}
>
IT Support
</Link>
</li>
<li>
<Link href="/services/web-design" className={`link ${pathname === "/services/web-design" ? styles.active : ""}`}>Web Design</Link>
<Link
href="/services/web-design"
className={`link ${
pathname === "/services/web-design" ? styles.active : ""
}`}
>
Web Design
</Link>
</li>
<li>
<Link href="/services/virus-removal" className={`link ${pathname === "/services/virus-removal" ? styles.active : ""}`}>Virus Removal</Link>
<Link
href="/services/virus-removal"
className={`link ${
pathname === "/services/virus-removal" ? styles.active : ""
}`}
>
Virus Removal
</Link>
</li>
</ul>
</li>
<li className="bg-sky-900 text-white">
<li>
<Link
href="/#faq"
>
FAQ
</Link>
</li>
<li className="bg-sky-900 text-white lg:ml-4">
<Link
href="/contact"
className={`link ${pathname === "/contact" ? styles.active : ""}`}
+1 -1
View File
@@ -76,7 +76,7 @@
border-radius: 0;
position: absolute;
top: -10em;
top: -14em;
left: 0;
right: 0;
z-index: -2;
+3 -62
View File
@@ -1,71 +1,12 @@
import styles from "./page.module.css";
import HeaderSm from "../components/HeaderSm";
import ContactForm from "../components/ContactForm";
export default function Home() {
return (
<div>
<HeaderSm text="Contact" />
<section className="container mx-auto">
<p className="mb-4">
Contact us about anything related to our company or services.
<br />
We&apos;ll do our best to get back to you as soon as possible.
</p>
<div className={styles.contactDetails}>
<h3 className="text-lg font-bold hover:underline">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
width="1em"
>
<path
fillRule="evenodd"
d="M2 3.5A1.5 1.5 0 0 1 3.5 2h1.148a1.5 1.5 0 0 1 1.465 1.175l.716 3.223a1.5 1.5 0 0 1-1.052 1.767l-.933.267c-.41.117-.643.555-.48.95a11.542 11.542 0 0 0 6.254 6.254c.395.163.833-.07.95-.48l.267-.933a1.5 1.5 0 0 1 1.767-1.052l3.223.716A1.5 1.5 0 0 1 18 15.352V16.5a1.5 1.5 0 0 1-1.5 1.5H15c-1.149 0-2.263-.15-3.326-.43A13.022 13.022 0 0 1 2.43 8.326 13.019 13.019 0 0 1 2 5V3.5Z"
clipRule="evenodd"
/>
</svg>
<a href="tel:+640211077483">021 107 7483</a>
</h3>
<h3 className="text-lg font-bold hover:underline">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
width="1em"
>
<path
fillRule="evenodd"
d="M5.404 14.596A6.5 6.5 0 1 1 16.5 10a1.25 1.25 0 0 1-2.5 0 4 4 0 1 0-.571 2.06A2.75 2.75 0 0 0 18 10a8 8 0 1 0-2.343 5.657.75.75 0 0 0-1.06-1.06 6.5 6.5 0 0 1-9.193 0ZM10 7.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5Z"
clipRule="evenodd"
/>
</svg>
<a href="mailto:[email protected]">
info@teatatucomputers.com
</a>
</h3>
</div>
<form
action="https://form.taxi/s/es9ddva1"
method="POST"
className={styles.form}
>
<label htmlFor="Name">Name*</label>
<input type="text" name="Name" required />
<label htmlFor="Phone">Phone Number </label>
<input type="tel" name="Phone" />
<label htmlFor="Email">Email*</label>
<input type="email" name="Email" required />
<label htmlFor="firstname">Message*</label>
<textarea name="Message"></textarea>
<p className={styles.sm}>* required</p>
<input type="submit" value="Submit" required className="text-white bg-sky-800 hover:bg-sky-700 transition" />
</form>
<section className="container mx-auto mb-64">
<ContactForm />
</section>
</div>
);
+129
View File
@@ -1,4 +1,9 @@
@import 'tailwindcss';
@import "tw-animate-css";
/*
---break---
*/
@custom-variant dark (&:is(.dark *));
@utility container {
padding-inline: 1rem;
@@ -20,4 +25,128 @@
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
/*
---break---
*/
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.129 0.042 264.695);
--card: oklch(1 0 0);
--card-foreground: oklch(0.129 0.042 264.695);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.129 0.042 264.695);
--primary: oklch(0.208 0.042 265.755);
--primary-foreground: oklch(0.984 0.003 247.858);
--secondary: oklch(0.968 0.007 247.896);
--secondary-foreground: oklch(0.208 0.042 265.755);
--muted: oklch(0.968 0.007 247.896);
--muted-foreground: oklch(0.554 0.046 257.417);
--accent: oklch(0.968 0.007 247.896);
--accent-foreground: oklch(0.208 0.042 265.755);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.929 0.013 255.508);
--input: oklch(0.929 0.013 255.508);
--ring: oklch(0.704 0.04 256.788);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.984 0.003 247.858);
--sidebar-foreground: oklch(0.129 0.042 264.695);
--sidebar-primary: oklch(0.208 0.042 265.755);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.968 0.007 247.896);
--sidebar-accent-foreground: oklch(0.208 0.042 265.755);
--sidebar-border: oklch(0.929 0.013 255.508);
--sidebar-ring: oklch(0.704 0.04 256.788);
}
/*
---break---
*/
.dark {
--background: oklch(0.129 0.042 264.695);
--foreground: oklch(0.984 0.003 247.858);
--card: oklch(0.208 0.042 265.755);
--card-foreground: oklch(0.984 0.003 247.858);
--popover: oklch(0.208 0.042 265.755);
--popover-foreground: oklch(0.984 0.003 247.858);
--primary: oklch(0.929 0.013 255.508);
--primary-foreground: oklch(0.208 0.042 265.755);
--secondary: oklch(0.279 0.041 260.031);
--secondary-foreground: oklch(0.984 0.003 247.858);
--muted: oklch(0.279 0.041 260.031);
--muted-foreground: oklch(0.704 0.04 256.788);
--accent: oklch(0.279 0.041 260.031);
--accent-foreground: oklch(0.984 0.003 247.858);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.551 0.027 264.364);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.208 0.042 265.755);
--sidebar-foreground: oklch(0.984 0.003 247.858);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.279 0.041 260.031);
--sidebar-accent-foreground: oklch(0.984 0.003 247.858);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.551 0.027 264.364);
}
/*
---break---
*/
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
}
/*
---break---
*/
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
+179 -4
View File
@@ -4,6 +4,13 @@ import bgimage from "./assets/header-bg.jpg";
import Button from "./components/Button";
import Link from "next/link";
import { GoogleMapsEmbed } from "@next/third-parties/google";
import ContactForm from "./components/ContactForm";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
export default function Home() {
return (
@@ -61,7 +68,7 @@ export default function Home() {
</div>
</section>
<section className="container mx-auto mb-16">
<section className="container mx-auto mb-32">
<h1 className="text-center text-3xl font-bold mb-4">
Services we Offer
</h1>
@@ -163,17 +170,185 @@ export default function Home() {
</div>
</div>
</section>
<section className="container mx-auto">
<div className={styles.map}>
<section className="container mx-auto flex flex-col gap-8 lg:flex-row mb-32">
<ContactForm />
<div className="w-full">
<GoogleMapsEmbed
apiKey="AIzaSyDbgQY55TQY5CefsCUwKbc8RfoOUe8U5gY"
height="500px"
width="100%"
height="600px"
mode="place"
q="place_id:ChIJz0ZoDYhADW0R0TDgWoWMq0M"
/>
</div>
</section>
<section className="container mx-auto mb-16 max-w-3xl mb-32" id="faq">
<h1 className="text-center text-3xl font-bold mb-8">
Frequently Asked Questions
</h1>
<h3 className="text-lg font-bold text-slate-900">
Computer Repair and IT Support
</h3>
<Accordion className="mb-8">
<AccordionItem value="item-1">
<AccordionTrigger>
What types of devices do you repair?
</AccordionTrigger>
<AccordionContent>
We repair desktops, laptops, chromebooks and PCs. We also handle
custom-built systems and some tablets, depending on the issue.
Currently we do not repair Apple devices.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2">
<AccordionTrigger>
What kinds of issues can you fix?
</AccordionTrigger>
<AccordionContent>
We handle a wide range of problems, including (but not limited
to):
<ul className="list-disc pl-6 my-2">
<li>
Software issues (e.g. Windows errors, slow performance)
</li>
<li>Virus removal and protection</li>
<li>Data recovery and backup solutions</li>
<li>Network setup and troubleshooting</li>
<li>Hardware upgrades (e.g. RAM, SSD, graphics card)</li>
<li>Custom PC builds</li>
<li>Web development and design</li>
<li>Remote support for software issues</li>
<li>General IT support and consulting</li>
<li>Printer setup and troubleshooting</li>
<li>Software installation and configuration</li>
<li>Operating system installation and upgrades</li>
<li>Data migration from old devices to new ones</li>
</ul>
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-3">
<AccordionTrigger>
Do I need an appointment, or can I just walk in?
</AccordionTrigger>
<AccordionContent>
Currently we are operating by appointment only. Please contact
us to schedule a time that works for you. We can also arrange
remote support for certain issues.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-4">
<AccordionTrigger>
How long will the repair take?
</AccordionTrigger>
<AccordionContent>
Most basic repairs are completed within 24-48 hours. Some issues
may take longer, depending on parts availability and complexity.
Well give you an estimated turnaround time when we diagnose the
problem. Most parts take about a week to arrive.
</AccordionContent>
</AccordionItem>
</Accordion>
<h3 className="text-lg font-bold text-slate-900">
Web Design and Development
</h3>
<Accordion>
<AccordionItem value="item-1">
<AccordionTrigger>
What platforms do you build websites with?
</AccordionTrigger>
<AccordionContent>
We specialize in modern web development using WordPress for
content-driven sites and React/Next.js for high-performance,
custom web applications. We also offer support for almost any
website builder, whether it&apos;s Wix, Oddo, Squarespace, or
anything else. Whether you need a blog, business site,
portfolio, or a fully custom web appwe&apos;ve got you covered.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2">
<AccordionTrigger>
How do I choose between WordPress and React/Next.js?
</AccordionTrigger>
<AccordionContent>
It depends on your needs:
<ul className="list-disc pl-6 my-2">
<li>
<strong>WordPress</strong> is best for content-heavy
websites like blogs, portfolios, and marketing sites.
</li>
<li>
<strong>React/Next.js</strong> is ideal for fast, scalable,
custom web applications or interactive user interfaces.
</li>
</ul>
Well help you decide what works best based on your goals and
budget.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-3">
<AccordionTrigger>
Do you design the website too, or just build it?
</AccordionTrigger>
<AccordionContent>
We do both! We offer full-service web design and development.
This includes UX/UI design, branding, responsive layouts, and
mobile-first designall tailored to your needs.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-4">
<AccordionTrigger>
Can you redesign or improve my existing site?
</AccordionTrigger>
<AccordionContent>
Absolutely. We can modernize your design, improve performance,
migrate platforms, or fully rebuild your site with a better
structure and codebase.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-5">
<AccordionTrigger>
Do you offer SEO and performance optimization?
</AccordionTrigger>
<AccordionContent>
Yes! All our builds include basic SEO best practices and speed
optimization. We also offer advanced technical SEO, Core Web
Vitals tuning, and image/code optimization.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-6">
<AccordionTrigger>
Do you provide ongoing maintenance and support?
</AccordionTrigger>
<AccordionContent>
Yes, we offer monthly maintenance plans for updates, backups,
security checks, and minor edits. We can also provide on-demand
support when needed.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-7">
<AccordionTrigger>
Will my site work on mobile devices?
</AccordionTrigger>
<AccordionContent>
Definitely. Every site we build is fully responsive and tested
on a variety of devices to ensure it looks great and works well
on phones, tablets, and desktops.
</AccordionContent>
</AccordionItem>
<AccordionItem value="item-8">
<AccordionTrigger>
What do you need from me to get started?
</AccordionTrigger>
<AccordionContent>
Well need some info about your goals, brand, content (text,
images, logo), and examples of sites you like. Dont worrywell
guide you through the process!
</AccordionContent>
</AccordionItem>
</Accordion>
</section>
</main>
</div>
);