Fazekit

Code

"use client";
import * as React from "react";
import { MotionConfig, useReducedMotion } from "motion/react";
import { cn } from "@/lib/utils";
import { defaultClinicData, type ClinicData } from "./data";
import { Booking, type BookingPrefill, type BookingRequest } from "./sections/booking";
import { Contact, Faq, Footer, Reviews } from "./sections/closing";
import { Hero } from "./sections/hero";
import { Navbar } from "./sections/navbar";
import { Doctors, Results } from "./sections/people";
import { Insurers, Services } from "./sections/services";
import { scrollToId, useMoney } from "./sections/ui";

export type { ClinicData, BookingRequest };
export { defaultClinicData };

export interface ClinicTemplateProps {
  /** Override any top-level content group (brand, services, doctors…). Missing groups fall back to the demo content. */
  data?: Partial<ClinicData>;
  /** Called when a patient confirms an appointment. Return a promise to keep the loading state until your API answers. */
  onBook?: (request: BookingRequest) => void | Promise<void>;
  className?: string;
}

/**
 * Clearview Dental — a calm, trustworthy clinic landing page.
 * Hero with appointment CTA, insurer marquee, priced services, dentists, before/after slider,
 * a 5-step booking widget, review marquee, FAQ, hours & map and a CTA footer.
 */
export function ClinicTemplate({ data, onBook, className }: ClinicTemplateProps) {
  const d: ClinicData = React.useMemo(() => ({ ...defaultClinicData, ...data }), [data]);
  const reduce = useReducedMotion();
  const money = useMoney(d.brand.currency);
  const [prefill, setPrefill] = React.useState<BookingPrefill>({ nonce: 0 });

  const book = React.useCallback(
    (p: Omit<BookingPrefill, "nonce"> = {}) => {
      setPrefill((cur) => ({ ...p, nonce: cur.nonce + 1 }));
      scrollToId("book", reduce);
    },
    [reduce],
  );

  return (
    <MotionConfig reducedMotion="user">
      <div className={cn("relative w-full bg-background text-foreground antialiased selection:bg-teal-500/20", className)}>
        <Navbar data={d} onBook={() => book()} />
        <main>
          <Hero data={d} onBook={() => book()} onServices={() => scrollToId("services", reduce)} />
          <Insurers insurers={d.insurers} />
          <Services services={d.services} money={money} onBook={(serviceId) => book({ serviceId })} />
          <Doctors doctors={d.doctors} onBook={(doctorId) => book({ doctorId })} />
          <Results cases={d.cases} doctors={d.doctors} />
          <Booking data={d} money={money} prefill={prefill} onBook={onBook} />
          <Reviews reviews={d.reviews} />
          <Faq faq={d.faq} phone={d.brand.phone} />
          <Contact data={d} />
        </main>
        <Footer data={d} onBook={() => book()} />
      </div>
    </MotionConfig>
  );
}

More in Landing Pages

View all →