Fazekit

Code

"use client";
import * as React from "react";
import { MotionConfig, useReducedMotion } from "motion/react";
import { cn } from "@/lib/utils";
import { defaultWeddingData, type WeddingData } from "./data";
import { Enquire, Faq, Footer, Testimonials, type Enquiry, type EnquiryPrefill } from "./sections/closing";
import { Gallery, Timeline, Vendors } from "./sections/gallery";
import { formatLongDate, Hero, Story } from "./sections/hero";
import { Navbar } from "./sections/navbar";
import { brandProps, scrollToId, useMoney, useOpenStatus } from "./sections/ui";
import { CapacityPlanner, Packages, Spaces } from "./sections/venue";

export type { WeddingData, Enquiry };
export { defaultWeddingData };

export interface WeddingEventTemplateProps {
  /** Override any top-level content group (brand, spaces, packages, gallery…). Missing groups fall back to data.ts. */
  data?: Partial<WeddingData>;
  /** Called when the enquiry form is sent. Return a promise to keep the loading state until your API answers. */
  onEnquire?: (enquiry: Enquiry) => void | Promise<void>;
  className?: string;
}

/**
 * Willow Hall — a romantic, editorial website for a wedding & event venue.
 * Hero with a date-availability calendar, story, spaces, packages with peak/off-peak toggle, a guest capacity
 * planner with live floor plan, gallery lightbox, scroll-drawn timeline of the day, vendor partners,
 * testimonials, FAQ, enquiry form with validation, viewing hours ("open now"), estate map + directions and footer.
 */
export function WeddingEventTemplate({ data, onEnquire, className }: WeddingEventTemplateProps) {
  const d: WeddingData = React.useMemo(() => ({ ...defaultWeddingData, ...data }), [data]);
  const reduce = useReducedMotion();
  const money = useMoney(d.brand.currency, d.brand.locale);
  const status = useOpenStatus(d.hours);
  const brand = brandProps(d.brandColors);
  const [guests, setGuests] = React.useState(120);
  const [prefill, setPrefill] = React.useState<EnquiryPrefill>({ nonce: 0 });

  const go = React.useCallback((id: string) => scrollToId(id, reduce), [reduce]);
  const enquire = (p: Omit<EnquiryPrefill, "nonce"> = {}) => {
    setPrefill((c) => ({ ...p, nonce: c.nonce + 1 }));
    go("enquire");
  };

  return (
    <MotionConfig reducedMotion="user">
      <div className={cn("relative w-full bg-background text-foreground antialiased selection:bg-primary/20", brand.className, className)} style={brand.style}>
        <Navbar data={d} status={status} onEnquire={() => go("enquire")} />
        <main>
          <Hero data={d} money={money} onHold={(iso) => enquire({ date: iso, message: `We'd love to hold ${formatLongDate(iso, d.brand.locale)}.` })} onViewing={() => enquire({ message: "We'd like to book a viewing." })} />
          <Story data={d} />
          <Spaces spaces={d.spaces} />
          <Packages data={d} money={money} guests={guests} onChoose={(name) => enquire({ guests, message: `We're interested in the ${name} package.` })} />
          <CapacityPlanner data={d} guests={guests} onGuests={setGuests} onUse={(s) => enquire({ guests: s.guests, message: `${s.guests} guests, ${s.style.toLowerCase()} layout${s.space ? ` — ${s.space} looks perfect` : ""}.` })} />
          <Gallery items={d.gallery} />
          <Timeline steps={d.timeline} />
          <Vendors vendors={d.vendors} />
          <Testimonials data={d} />
          <Faq data={d} />
          <Enquire data={d} status={status} prefill={prefill} onSubmit={onEnquire} />
        </main>
        <Footer data={d} onNav={go} />
      </div>
    </MotionConfig>
  );
}

More in Landing Pages

View all →