Fazekit

Code

"use client";
import * as React from "react";
import { MotionConfig, useReducedMotion } from "motion/react";
import { cn } from "@/lib/utils";
import { defaultRestaurantData, type EventItem, type RestaurantData } from "./data";
import { Events } from "./sections/events";
import { Footer } from "./sections/footer";
import { Gallery } from "./sections/gallery";
import { Hero } from "./sections/hero";
import { Location } from "./sections/location";
import { MenuSection } from "./sections/menu";
import { Navbar } from "./sections/navbar";
import { Reservation, type ReservationRequest } from "./sections/reservation";
import { Reviews } from "./sections/reviews";
import { Story } from "./sections/story";
import { Tasting } from "./sections/tasting";
import { EO_SERIF_STACK, scrollToId } from "./sections/ui";
import { WineList } from "./sections/wine";

export type { RestaurantData, ReservationRequest, EventItem };
export { defaultRestaurantData };

export interface RestaurantTemplateProps {
  /** Override any top-level content group (brand, hero, menu, wine…). Missing groups fall back to the demo content. */
  data?: Partial<RestaurantData>;
  /** Called when a guest confirms a table. Return a promise to keep the loading state until your API answers. */
  onReserve?: (reservation: ReservationRequest) => void | Promise<void>;
  /** Called when someone joins the newsletter in the footer. */
  onSubscribe?: (email: string) => void;
  /** Called when a guest reserves seats for an event. */
  onEventRsvp?: (event: EventItem) => void;
  className?: string;
}

export function RestaurantTemplate({ data, onReserve, onSubscribe, onEventRsvp, className }: RestaurantTemplateProps) {
  const d = React.useMemo(() => ({ ...defaultRestaurantData, ...data }), [data]);
  const reduce = useReducedMotion();
  const toReserve = React.useCallback(() => scrollToId("reserve", reduce), [reduce]);
  const toMenu = React.useCallback(() => scrollToId("menu", reduce), [reduce]);

  return (
    <MotionConfig reducedMotion="user">
      <div
        className={cn("relative w-full bg-background text-foreground antialiased selection:bg-orange-600/25", className)}
        style={{ "--eo-serif": EO_SERIF_STACK } as React.CSSProperties}
      >
        <Navbar name={d.brand.name} links={d.nav} phone={d.brand.phone} onReserve={toReserve} />
        <main>
          <Hero hero={d.hero} onReserve={toReserve} onMenu={toMenu} />
          <Story story={d.story} />
          <MenuSection menu={d.menu} currency={d.brand.currency} />
          <Tasting tasting={d.tasting} currency={d.brand.currency} onBook={toReserve} />
          <WineList wine={d.wine} currency={d.brand.currency} />
          <Gallery gallery={d.gallery} />
          <Reservation reservation={d.reservation} brandName={d.brand.name} address={`${d.brand.address}, ${d.brand.city}`} onReserve={onReserve} />
          <Events events={d.events} currency={d.brand.currency} onRsvp={onEventRsvp} />
          <Reviews reviews={d.reviews} />
          <Location location={d.location} brand={d.brand} />
        </main>
        <Footer footer={d.footer} brand={d.brand} onSubscribe={onSubscribe} />
      </div>
    </MotionConfig>
  );
}

More in Landing Pages

View all →