Fazekit

Code

"use client";
import * as React from "react";
import { MotionConfig, useReducedMotion } from "motion/react";
import { cn } from "@/lib/utils";
import { defaultConsultingData, type ConsultingData } from "./data";
import { Consultation, Footer, Offices, type ConsultationPrefill, type ConsultationRequest } from "./sections/contact";
import { Clients, Hero } from "./sections/hero";
import { Navbar } from "./sections/navbar";
import { Insights, People } from "./sections/people";
import { Practices, Results } from "./sections/practice";
import { scrollToId } from "./sections/ui";

export type { ConsultingData, ConsultationRequest };
export { defaultConsultingData };

export interface ConsultingTemplateProps {
  /** Override any top-level content group (brand, practices, partners…). Missing groups fall back to the demo content. */
  data?: Partial<ConsultingData>;
  /** Called when a consultation request passes validation. Return a promise to keep the checking state until your API answers. */
  onConsultation?: (request: ConsultationRequest) => void | Promise<void>;
  className?: string;
}

/**
 * Whitmore & Co. — a premium law & advisory firm site.
 * Line-drawn portico hero with count-up stats, client marks, filterable practice grid,
 * case results, partner bios in a modal, insights list, a conflict-checked consultation form,
 * office tabs with live local time and a formal footer.
 */
export function ConsultingTemplate({ data, onConsultation, className }: ConsultingTemplateProps) {
  const d: ConsultingData = React.useMemo(() => ({ ...defaultConsultingData, ...data }), [data]);
  const reduce = useReducedMotion();
  const [prefill, setPrefill] = React.useState<ConsultationPrefill>({ nonce: 0 });
  const go = React.useCallback((id: string) => scrollToId(id, reduce), [reduce]);
  const consult = React.useCallback(
    (p: Omit<ConsultationPrefill, "nonce"> = {}) => {
      setPrefill((cur) => ({ ...p, nonce: cur.nonce + 1 }));
      scrollToId("consult", reduce);
    },
    [reduce],
  );

  return (
    <MotionConfig reducedMotion="user">
      <div className={cn("relative w-full bg-background text-foreground antialiased selection:bg-[#d4b27a]/30", className)}>
        <Navbar data={d} onConsult={() => consult()} />
        <main>
          <Hero data={d} onConsult={() => consult()} onPractices={() => go("practices")} />
          <Clients clients={d.clients} />
          <Practices data={d} onConsult={(practiceId) => consult({ practiceId })} />
          <Results data={d} />
          <People partners={d.partners} onConsult={(p) => consult({ practiceId: d.practices.find((x) => x.lead === p.id)?.id, office: p.office })} />
          <Insights data={d} />
          <Consultation data={d} prefill={prefill} onSubmit={onConsultation} />
          <Offices offices={d.offices} onConsult={(office) => consult({ office })} />
        </main>
        <Footer data={d} onNav={go} />
      </div>
    </MotionConfig>
  );
}

More in Landing Pages

View all →