diff --git a/src/app/appointment/page.tsx b/src/app/appointment/page.tsx new file mode 100644 index 0000000..153860e --- /dev/null +++ b/src/app/appointment/page.tsx @@ -0,0 +1,67 @@ +import { EmbeddedScheduler } from "@/components/embedded-scheduler"; +import { ContactForm } from "@/components/contact-form"; +import { offices } from "@/lib/site-config"; + +export default function AppointmentPage() { + return ( +
+
+
+

+ Appointments +

+

+ Book your tax, insurance, or bookkeeping appointment +

+

+ Choose a convenient time for an in‑person or virtual appointment. + Use the form below to tell us what you need and which office you + prefer, and we'll follow up to confirm the details. +

+
+
+
+ + +
+ +
+
+
+ ); +} + diff --git a/src/app/contact/page.tsx b/src/app/contact/page.tsx new file mode 100644 index 0000000..f7e5520 --- /dev/null +++ b/src/app/contact/page.tsx @@ -0,0 +1,43 @@ +import { ContactForm } from "@/components/contact-form"; +import { LocationsSection } from "@/components/locations-section"; + +export default function ContactPage() { + return ( +
+
+
+
+

+ Contact +

+

+ We're here to help +

+

+ Have a question about your taxes, insurance, or bookkeeping? Send + us a message and our team will respond as soon as possible. +

+
+
+ +
+

+ Phone & email +

+

+ You can also reach us by phone or email using the office + details below. +

+

+ For time‑sensitive questions during tax season, calling one of + our offices is usually the fastest way to get help. +

+
+
+
+
+ +
+ ); +} + diff --git a/src/app/globals.css b/src/app/globals.css index a8da733..53d78b4 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -121,9 +121,14 @@ @apply border-border outline-ring/50; } body { + font-family: var(--font-sans), system-ui, -apple-system, sans-serif; @apply bg-background text-foreground; } html { - @apply font-sans; + font-family: var(--font-sans), system-ui, -apple-system, sans-serif; } +} + +.font-serif { + font-family: var(--font-display), "Playfair Display", serif; } \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index f7fa87e..e86f5a7 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,20 +1,24 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; +import { Inter, Playfair_Display } from "next/font/google"; import "./globals.css"; +import { SiteHeader } from "@/components/site-header"; +import { SiteFooter } from "@/components/site-footer"; +import { FloatingCallButton } from "@/components/floating-call-button"; -const geistSans = Geist({ - variable: "--font-geist-sans", +const sans = Inter({ subsets: ["latin"], + variable: "--font-sans", }); -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", +export const playfair = Playfair_Display({ subsets: ["latin"], + variable: "--font-display", }); export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Ghion Financial — Tax, Insurance & Bookkeeping", + description: + "Ghion Financial provides trusted income tax preparation, insurance services, and bookkeeping for individuals, families, and businesses across Virginia and Maryland.", }; export default function RootLayout({ @@ -25,9 +29,14 @@ export default function RootLayout({ return ( - {children} +
+ +
{children}
+ +
+ ); diff --git a/src/app/page.tsx b/src/app/page.tsx index 295f8fd..e222f56 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,65 +1,17 @@ -import Image from "next/image"; +import { Hero } from "@/components/hero"; +import { ServicesSection } from "@/components/services-section"; +import { AppointmentCards } from "@/components/appointment-cards"; +import { LocationsSection } from "@/components/locations-section"; +import { ReviewsSection } from "@/components/reviews-section"; export default function Home() { return ( -
-
- Next.js logo -
-

- To get started, edit the page.tsx file. -

-

- Looking for a starting point or more instructions? Head over to{" "} - - Templates - {" "} - or the{" "} - - Learning - {" "} - center. -

-
-
- - Vercel logomark - Deploy Now - - - Documentation - -
-
-
+ <> + + + + + + ); } diff --git a/src/components/appointment-cards.tsx b/src/components/appointment-cards.tsx new file mode 100644 index 0000000..e8ff6f9 --- /dev/null +++ b/src/components/appointment-cards.tsx @@ -0,0 +1,76 @@ +import Link from "next/link"; +import { offices } from "@/lib/site-config"; +import { Button } from "@/components/ui/button"; + +export function AppointmentCards() { + return ( +
+
+
+
+

+ Book an appointment in minutes +

+

+ Choose the office that is most convenient for you. We offer + in‑person and virtual appointments for tax preparation, + insurance, and bookkeeping. +

+
+

+ Serving Virginia & Maryland clients year‑round. +

+
+
+ {offices.map((office) => ( +
+
+

+ {office.label} +

+
+ {office.addressLines.map((line) => ( +
{line}
+ ))} +
+ +
+ In‑person & virtual appointments available +
+
+
+ + +
+
+ ))} +
+
+
+ ); +} + diff --git a/src/components/contact-form.tsx b/src/components/contact-form.tsx new file mode 100644 index 0000000..04680bc --- /dev/null +++ b/src/components/contact-form.tsx @@ -0,0 +1,172 @@ +"use client"; + +import { useState } from "react"; +import { offices } from "@/lib/site-config"; +import { Button } from "@/components/ui/button"; + +type Mode = "contact" | "appointment"; + +export function ContactForm({ mode }: { mode: Mode }) { + const [status, setStatus] = useState<"idle" | "submitted">("idle"); + + function handleSubmit(event: React.FormEvent) { + event.preventDefault(); + const form = event.currentTarget; + if (!form.checkValidity()) { + form.reportValidity(); + return; + } + setStatus("submitted"); + } + + const heading = + mode === "appointment" + ? "Request an appointment" + : "Send us a message"; + + return ( +
+

{heading}

+

+ Fill out the form and a member of our team will follow up within one + business day. +

+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ {mode === "appointment" && ( +
+
+ + +
+
+ + +
+
+ )} +
+ +