revamp gruida, come funziona e accordion faqs nel sito
This commit is contained in:
parent
9cc6ee343e
commit
0ba65eb2aa
9 changed files with 194 additions and 295 deletions
|
|
@ -40,7 +40,7 @@ export const AccordionComp = forwardRef<HTMLDivElement, AccordionCompProps>(
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
<Accordion
|
<Accordion
|
||||||
className="w-full"
|
className="w-full space-y-2 text-secondary-foreground"
|
||||||
collapsible
|
collapsible
|
||||||
defaultValue={
|
defaultValue={
|
||||||
defaultOpen !== undefined ? `item-${defaultOpen}` : undefined
|
defaultOpen !== undefined ? `item-${defaultOpen}` : undefined
|
||||||
|
|
@ -49,12 +49,12 @@ export const AccordionComp = forwardRef<HTMLDivElement, AccordionCompProps>(
|
||||||
>
|
>
|
||||||
{texts.map((text, index) => (
|
{texts.map((text, index) => (
|
||||||
<AccordionItem
|
<AccordionItem
|
||||||
className="border-b dark:border-muted-foreground/50"
|
className="rounded-2xl border-none bg-secondary px-2 py-0 shadow-secondary shadow-sm sm:px-4"
|
||||||
// biome-ignore lint/suspicious/noArrayIndexKey: <index is safe here>
|
// biome-ignore lint/suspicious/noArrayIndexKey: <index is safe here>
|
||||||
key={`ac-item-${index}`}
|
key={`ac-item-${index}`}
|
||||||
value={`item-${index}`}
|
value={`item-${index}`}
|
||||||
>
|
>
|
||||||
<AccordionTrigger className="cursor-pointer gap-4 border-natural-200 text-left text-md">
|
<AccordionTrigger className="cursor-pointer py-2 text-left text-md sm:py-4 [&>svg]:text-secondary-foreground">
|
||||||
{text.title}
|
{text.title}
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent className="text-base">
|
<AccordionContent className="text-base">
|
||||||
|
|
|
||||||
|
|
@ -1,176 +1,119 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { domAnimation, LazyMotion, m } from "framer-motion";
|
import { domAnimation, LazyMotion, m } from "framer-motion";
|
||||||
|
import { ArrowRight } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
import type React from "react";
|
import type React from "react";
|
||||||
|
import { Button } from "~/components/ui/button";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
|
||||||
interface CardProps {
|
const divClassNames = {
|
||||||
number: string;
|
orange:
|
||||||
title: string;
|
"bg-orange-50 dark:bg-orange-500/10 border-orange-100 dark:border-orange-500/20",
|
||||||
description: string;
|
blue: "bg-blue-50 dark:bg-blue-500/10 border-blue-100 dark:border-blue-500/20",
|
||||||
colorTheme?: "orange" | "blue" | "purple";
|
purple:
|
||||||
className?: string;
|
"bg-purple-50 dark:bg-purple-500/10 border-purple-100 dark:border-purple-500/20",
|
||||||
rotate?: string;
|
green:
|
||||||
colors?: {
|
"bg-green-50 dark:bg-green-500/10 border-green-100 dark:border-green-500/20",
|
||||||
bg: string;
|
|
||||||
text: string;
|
|
||||||
border: string;
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
const Card = ({
|
const txtClassNames = {
|
||||||
number,
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
colorTheme = "blue",
|
|
||||||
className,
|
|
||||||
colors: customColors,
|
|
||||||
}: CardProps) => {
|
|
||||||
const defaultBgColors = {
|
|
||||||
orange: "bg-orange-50 dark:bg-orange-500/10",
|
|
||||||
blue: "bg-blue-50 dark:bg-blue-500/10",
|
|
||||||
purple: "bg-purple-50 dark:bg-purple-500/10",
|
|
||||||
};
|
|
||||||
const defaultTextColors = {
|
|
||||||
orange: "text-orange-500 dark:text-orange-400",
|
orange: "text-orange-500 dark:text-orange-400",
|
||||||
blue: "text-blue-600 dark:text-blue-400",
|
blue: "text-blue-600 dark:text-blue-400",
|
||||||
purple: "text-purple-600 dark:text-purple-400",
|
purple: "text-purple-600 dark:text-purple-400",
|
||||||
};
|
green: "text-green-600 dark:text-green-400",
|
||||||
const defaultBorderColors = {
|
|
||||||
orange: "border-orange-100 dark:border-orange-500/20",
|
|
||||||
blue: "border-blue-100 dark:border-blue-500/20",
|
|
||||||
purple: "border-purple-100 dark:border-purple-500/20",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const bgColor = customColors?.bg || defaultBgColors[colorTheme];
|
interface Step {
|
||||||
const textColor = customColors?.text || defaultTextColors[colorTheme];
|
|
||||||
const borderColor = customColors?.border || defaultBorderColors[colorTheme];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
`relative w-full transition-transform duration-300 hover:z-30 hover:scale-105 md:w-[400px]`,
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className="rounded-[25px] border border-neutral-100 bg-card p-2 shadow-[0px_10px_20px_0px_#D3D3D3] dark:border-neutral-800 dark:shadow-none">
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
`relative flex h-full flex-col overflow-hidden rounded-[15px] border p-[15px]`,
|
|
||||||
bgColor,
|
|
||||||
borderColor,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<span className={cn(`mb-5 text-4xl`, textColor)}>{number}</span>
|
|
||||||
<h3 className="mb-[10px] font-semibold text-2xl text-neutral-800 leading-none dark:text-neutral-100">
|
|
||||||
{title}
|
|
||||||
</h3>
|
|
||||||
<p className="text-neutral-500 tracking-tight dark:text-neutral-400">
|
|
||||||
{description}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface Step {
|
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
colorTheme?: "orange" | "blue" | "purple";
|
colorTheme: "orange" | "blue" | "purple" | "green";
|
||||||
colors?: {
|
link?: {
|
||||||
bg: string;
|
href: string;
|
||||||
text: string;
|
text: string;
|
||||||
border: string;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface StepPosition {
|
const F_ita: Step[] = [
|
||||||
className?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HowItWorksProps {
|
|
||||||
features?: Step[];
|
|
||||||
className?: string;
|
|
||||||
stepPositions?: StepPosition[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const DEFAULT_CARD_POSITIONS: StepPosition[] = [
|
|
||||||
{
|
{
|
||||||
className: "md:absolute md:top-0 md:left-[15%] lg:left-[10%]",
|
title: "Esplora gli annunci",
|
||||||
},
|
|
||||||
{
|
|
||||||
className: "md:absolute md:top-[210px] md:right-[15%] lg:right-[10%]",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
className: "md:absolute md:top-[450px] md:left-[15%] lg:left-[10%]",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
className: "md:absolute md:top-[680px] md:right-[10%] lg:right-[10%]",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
className: "md:absolute md:top-[910px] md:left-[15%] lg:left-[10%]",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function HowItWorks({
|
|
||||||
features,
|
|
||||||
className,
|
|
||||||
stepPositions,
|
|
||||||
}: HowItWorksProps) {
|
|
||||||
const defaultFeatures: Step[] = [
|
|
||||||
{
|
|
||||||
title: "Create Account",
|
|
||||||
description:
|
description:
|
||||||
"Sign up in minutes. Enter your details and verify your email to get started.",
|
"In base a località, tipologia, prezzo, data di disponibilità e molte altre caratteristiche.",
|
||||||
colorTheme: "orange",
|
colorTheme: "orange",
|
||||||
|
link: {
|
||||||
|
href: "/annunci",
|
||||||
|
text: "Vai agli annunci",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Verify Identity",
|
title: "Attiva il servizio",
|
||||||
description:
|
description:
|
||||||
"Complete your profile verification to ensure secure transactions and compliance.",
|
"Richiedi il servizio, ti invieremo un collegamento per completare la ricerca che abbiamo creato per te e acquistare il servizio.",
|
||||||
colorTheme: "blue",
|
colorTheme: "blue",
|
||||||
|
link: {
|
||||||
|
href: "/contatti",
|
||||||
|
text: "Contattaci",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Select Plan",
|
title: "Visita le case",
|
||||||
description:
|
description:
|
||||||
"Choose from a variety of investment plans tailored to your financial goals.",
|
"Fissa appuntamenti direttamente con i proprietari per una visita. La trattativa è tra voi privati. Non c'è mediazione.",
|
||||||
colorTheme: "purple",
|
colorTheme: "purple",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Analyze & Invest",
|
title: "Contratto di affitto",
|
||||||
description:
|
description:
|
||||||
"Review returns and make your first investment with confidence.",
|
"Procederemo alla stesura del contratto di locazione in base agli accordi che hai trovato con il propritario.",
|
||||||
colorTheme: "orange",
|
colorTheme: "green",
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Track Growth",
|
|
||||||
description:
|
|
||||||
"Monitor your portfolio in real-time and watch your wealth grow over time.",
|
|
||||||
colorTheme: "blue",
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const F_eng: Step[] = [
|
||||||
|
{
|
||||||
|
title: "Explore Listings",
|
||||||
|
description:
|
||||||
|
"Search by location, type, price, availability date, and many other criteria.",
|
||||||
|
colorTheme: "orange",
|
||||||
|
link: {
|
||||||
|
href: "/annunci",
|
||||||
|
text: "Go to listings",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Activate the Service",
|
||||||
|
description:
|
||||||
|
"Request the service; we’ll send you a link to complete the search we created for you and purchase the service.",
|
||||||
|
colorTheme: "blue",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Visit the Homes",
|
||||||
|
description:
|
||||||
|
"Schedule appointments directly with owners for viewings. The negotiation is private between you and the owner—no mediation.",
|
||||||
|
colorTheme: "purple",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Rental Agreement",
|
||||||
|
description:
|
||||||
|
"We’ll draft the lease contract based on the terms you’ve agreed upon with the owner.",
|
||||||
|
colorTheme: "green",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export default function HowItWorks({ className }: { className?: string }) {
|
||||||
|
const { locale } = useTranslation();
|
||||||
|
|
||||||
const data = features && features.length > 0 ? features : defaultFeatures;
|
const features: Step[] = locale === "it" ? F_ita : F_eng;
|
||||||
const positions = stepPositions || DEFAULT_CARD_POSITIONS;
|
|
||||||
|
|
||||||
let height = 1130;
|
|
||||||
if (data.length === 1) height = 400;
|
|
||||||
else if (data.length === 2) height = 450;
|
|
||||||
else if (data.length === 3) height = 800;
|
|
||||||
else if (data.length === 4) height = 900;
|
|
||||||
else height = 1130;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LazyMotion features={domAnimation}>
|
<LazyMotion features={domAnimation}>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
`relative mt-5 bg-background max-md:pt-5 max-md:pb-5 md:pt-10`,
|
`relative mt-0 overflow-clip rounded-2xl bg-background max-md:pt-5 max-md:pb-5 md:pt-0`,
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="pointer-events-none absolute inset-0 opacity-[0.08] dark:opacity-[0.15]"
|
className="pointer-events-none absolute inset-0 hidden opacity-[0.08] md:block dark:opacity-[0.15]"
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: "linear-gradient(#000 1px, transparent 1px)",
|
backgroundImage: "linear-gradient(#000 1px, transparent 1px)",
|
||||||
backgroundSize: "100% 32px",
|
backgroundSize: "100% 32px",
|
||||||
|
|
@ -178,31 +121,28 @@ export default function HowItWorks({
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
<div
|
<div
|
||||||
className="pointer-events-none absolute inset-0 opacity-0 dark:opacity-[0.1]"
|
className="pointer-events-none absolute inset-0 hidden opacity-0 md:block dark:opacity-[0.1]"
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: "linear-gradient(#fff 1px, transparent 1px)",
|
backgroundImage: "linear-gradient(#fff 1px, transparent 1px)",
|
||||||
backgroundSize: "100% 32px",
|
backgroundSize: "100% 32px",
|
||||||
marginTop: "4px",
|
marginTop: "4px",
|
||||||
}}
|
}}
|
||||||
></div>
|
></div>
|
||||||
<div className="pointer-events-none absolute inset-y-0 left-0 w-1/2 bg-linear-to-r from-background"></div>
|
<div className="pointer-events-none absolute inset-y-0 left-0 hidden w-1/2 bg-linear-to-r from-background md:block"></div>
|
||||||
<div className="pointer-events-none absolute inset-y-0 right-0 w-1/2 bg-linear-to-l from-background"></div>
|
<div className="pointer-events-none absolute inset-y-0 right-0 hidden w-1/2 bg-linear-to-l from-background md:block"></div>
|
||||||
|
|
||||||
<div className="relative z-10 mx-auto max-w-6xl">
|
<div className="relative z-10 mx-auto max-w-6xl">
|
||||||
<div
|
<div className="relative mx-auto flex h-auto w-full max-w-[1400px] flex-col space-y-4 sm:space-y-8 md:block md:h-[920px] md:space-y-0">
|
||||||
className="relative mx-auto flex h-auto w-full max-w-[1400px] flex-col space-y-6 sm:space-y-8 md:block md:h-(--md-height) md:space-y-0"
|
{features.length > 1 && (
|
||||||
style={{ "--md-height": `${height}px` } as React.CSSProperties}
|
|
||||||
>
|
|
||||||
{data.length > 1 && (
|
|
||||||
<svg
|
<svg
|
||||||
className="pointer-events-none absolute top-0 left-0 z-0 hidden h-full w-full md:block"
|
className="pointer-events-none absolute top-0 left-0 z-0 hidden h-full w-full md:block"
|
||||||
preserveAspectRatio="none"
|
preserveAspectRatio="none"
|
||||||
viewBox={`0 0 1000 ${height}`}
|
viewBox={`0 0 1000 920`}
|
||||||
>
|
>
|
||||||
<title>stroke</title>
|
<title>stroke</title>
|
||||||
{(() => {
|
{(() => {
|
||||||
const pathD = data.reduce((acc, _, index) => {
|
const pathD = features.reduce((acc, _, index) => {
|
||||||
if (index >= data.length - 1) return acc;
|
if (index >= features.length - 1) return acc;
|
||||||
if (index === 0)
|
if (index === 0)
|
||||||
return "M 290 150 C 500 150, 550 270, 710 270"; // 1 -> 2
|
return "M 290 150 C 500 150, 550 270, 710 270"; // 1 -> 2
|
||||||
if (index === 1)
|
if (index === 1)
|
||||||
|
|
@ -238,19 +178,58 @@ export default function HowItWorks({
|
||||||
</svg>
|
</svg>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{data.map((step, index) => {
|
{features.map((step, index) => {
|
||||||
const position = positions[index % positions.length];
|
|
||||||
if (!position) return null;
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<div
|
||||||
className={position.className}
|
className={cn(
|
||||||
colors={step.colors}
|
`relative w-full transition-transform duration-300 hover:z-30 hover:scale-105 md:absolute md:top-(--offset) md:w-[400px]`,
|
||||||
colorTheme={step.colorTheme || "blue"}
|
index % 2 === 0
|
||||||
description={step.description}
|
? "md:left-[15%] lg:left-[10%]"
|
||||||
|
: "md:right-[15%] lg:right-[10%]",
|
||||||
|
)}
|
||||||
key={step.title}
|
key={step.title}
|
||||||
number={`0${index + 1}`}
|
style={
|
||||||
title={step.title}
|
{
|
||||||
/>
|
"--offset": `${index === 0 ? 25 : index * 220}px`,
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="rounded-2xl border border-border bg-card p-2 shadow-sm dark:shadow-none">
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
`relative flex h-full flex-col overflow-hidden rounded-xl border p-[15px]`,
|
||||||
|
divClassNames[step.colorTheme],
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
`mb-5 text-4xl`,
|
||||||
|
txtClassNames[step.colorTheme],
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{`0${index + 1}`}
|
||||||
|
</span>
|
||||||
|
<h3 className="mb-[10px] font-semibold text-2xl text-neutral-800 leading-none dark:text-neutral-100">
|
||||||
|
{step.title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-neutral-500 tracking-tight dark:text-neutral-400">
|
||||||
|
{step.description}
|
||||||
|
</p>
|
||||||
|
{step.link && (
|
||||||
|
<Link className="mt-2" href={step.link.href}>
|
||||||
|
<Button
|
||||||
|
className="w-full text-foreground"
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
<span>{step.link.text}</span>
|
||||||
|
<ArrowRight />
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -275,12 +275,7 @@ export const en: LangDict = {
|
||||||
},
|
},
|
||||||
annulla: "Cancel",
|
annulla: "Cancel",
|
||||||
annunci: {
|
annunci: {
|
||||||
accordion_minifaq: [
|
accordion_minifaq: [Faqs.cosa_significa_transitorio, Faqs.posso_visitarli],
|
||||||
Faqs.cosa_significa_transitorio,
|
|
||||||
Faqs.posso_visitarli,
|
|
||||||
Faqs.posso_contattarvi,
|
|
||||||
Faqs.come_confermare,
|
|
||||||
],
|
|
||||||
comune: "City",
|
comune: "City",
|
||||||
consegna: "From",
|
consegna: "From",
|
||||||
budget: "Budget",
|
budget: "Budget",
|
||||||
|
|
|
||||||
|
|
@ -280,12 +280,7 @@ export const it: LangDict = {
|
||||||
},
|
},
|
||||||
annulla: "Annulla",
|
annulla: "Annulla",
|
||||||
annunci: {
|
annunci: {
|
||||||
accordion_minifaq: [
|
accordion_minifaq: [Faqs.cosa_significa_transitorio, Faqs.posso_visitarli],
|
||||||
Faqs.cosa_significa_transitorio,
|
|
||||||
Faqs.posso_visitarli,
|
|
||||||
Faqs.posso_contattarvi,
|
|
||||||
Faqs.come_confermare,
|
|
||||||
],
|
|
||||||
comune: "Comune",
|
comune: "Comune",
|
||||||
consegna: "Disponibile da",
|
consegna: "Disponibile da",
|
||||||
budget: "Budget",
|
budget: "Budget",
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,12 @@ const Annunci = ({ options }: AnnunciPageProps) => {
|
||||||
{t.annunci.titolo}
|
{t.annunci.titolo}
|
||||||
</Badge>
|
</Badge>
|
||||||
<ScrollToTop />
|
<ScrollToTop />
|
||||||
<Ricerca />
|
|
||||||
<AccordionComp
|
<AccordionComp
|
||||||
className="max-w-6xl px-4 py-4 md:py-8"
|
className="max-w-6xl"
|
||||||
defaultOpen={0}
|
defaultOpen={undefined}
|
||||||
texts={t.annunci.accordion_minifaq}
|
texts={t.annunci.accordion_minifaq}
|
||||||
/>
|
/>
|
||||||
|
<Ricerca />
|
||||||
</main>
|
</main>
|
||||||
</RicercaProvider>
|
</RicercaProvider>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import {
|
||||||
AccordionTrigger,
|
AccordionTrigger,
|
||||||
} from "~/components/ui/accordion";
|
} from "~/components/ui/accordion";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
import { Button } from "~/components/ui/button";
|
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -16,49 +15,6 @@ import { useTranslation } from "~/providers/I18nProvider";
|
||||||
*/
|
*/
|
||||||
const Guida: NextPage = () => {
|
const Guida: NextPage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
//todo translation
|
|
||||||
const features = [
|
|
||||||
{
|
|
||||||
title: "Esplora gli annunci",
|
|
||||||
description:
|
|
||||||
"In base a località, tipologia, prezzo, data di disponibilità e molte altre caratteristiche.",
|
|
||||||
colors: {
|
|
||||||
bg: "bg-orange-50 dark:bg-orange-500/10",
|
|
||||||
text: "text-orange-500 dark:text-orange-400",
|
|
||||||
border: "border-orange-100 dark:border-orange-500/20",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Attiva il servizio",
|
|
||||||
description:
|
|
||||||
"Richiedi il servizio, ti invieremo un collegamento per completare la ricerca che abbiamo creato per te e acquistare il servizio.",
|
|
||||||
colors: {
|
|
||||||
bg: "bg-blue-50 dark:bg-blue-500/10",
|
|
||||||
text: "text-blue-600 dark:text-blue-400",
|
|
||||||
border: "border-blue-100 dark:border-blue-500/20",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Visita le case",
|
|
||||||
description:
|
|
||||||
"Fissa appuntamenti direttamente con i proprietari per una visita. La trattativa è tra voi privati. Non c'è mediazione.",
|
|
||||||
colors: {
|
|
||||||
bg: "bg-purple-50 dark:bg-purple-500/10",
|
|
||||||
text: "text-purple-600 dark:text-purple-400",
|
|
||||||
border: "border-purple-100 dark:border-purple-500/20",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Contratto di affitto",
|
|
||||||
description:
|
|
||||||
"Procederemo alla stesura del contratto di locazione in base agli accordi che hai trovato con il propritario.",
|
|
||||||
colors: {
|
|
||||||
bg: "bg-green-50 dark:bg-green-500/10",
|
|
||||||
text: "text-green-500 dark:text-green-400",
|
|
||||||
border: "border-green-100 dark:border-green-500/20",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -72,7 +28,7 @@ const Guida: NextPage = () => {
|
||||||
</Badge>
|
</Badge>
|
||||||
|
|
||||||
{/* <ComeFunziona /> */}
|
{/* <ComeFunziona /> */}
|
||||||
<HowItWorks features={features} />
|
<HowItWorks className="sm:mt-1" />
|
||||||
<FAQSection />
|
<FAQSection />
|
||||||
</main>
|
</main>
|
||||||
</>
|
</>
|
||||||
|
|
@ -83,13 +39,6 @@ export default Guida;
|
||||||
const FAQSection = () => {
|
const FAQSection = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const handleScroll = (id: string) => {
|
|
||||||
document.getElementById(id)?.scrollIntoView({
|
|
||||||
behavior: "smooth",
|
|
||||||
});
|
|
||||||
window.history.replaceState({}, "", `${window.location.pathname}#${id}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!t.faq?.domande) {
|
if (!t.faq?.domande) {
|
||||||
return null; // Ensure translations are loaded before rendering
|
return null; // Ensure translations are loaded before rendering
|
||||||
}
|
}
|
||||||
|
|
@ -102,29 +51,16 @@ const FAQSection = () => {
|
||||||
<h2 className="font-bold text-3xl tracking-tighter md:text-4xl">
|
<h2 className="font-bold text-3xl tracking-tighter md:text-4xl">
|
||||||
{t.faq.titolo}
|
{t.faq.titolo}
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-muted-foreground md:text-xl/relaxed lg:text-base/relaxed xl:text-xl/relaxed">
|
<p className="md:text-xl/relaxed lg:text-base/relaxed xl:text-xl/relaxed">
|
||||||
{t.faq.descrizione}
|
{t.faq.descrizione}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex w-full max-w-6xl justify-between gap-5">
|
|
||||||
<div className="hidden flex-col gap-5 md:flex">
|
|
||||||
{t.faq.domande.map((item) => (
|
|
||||||
<Button
|
|
||||||
className="justify-start font-semibold text-lg"
|
|
||||||
key={item.id}
|
|
||||||
onClick={() => handleScroll(`faq-${item.id}`)}
|
|
||||||
variant="ghost"
|
|
||||||
>
|
|
||||||
{item.label}
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="flex w-full flex-col gap-5">
|
<div className="flex w-full flex-col gap-5">
|
||||||
{t.faq.domande.map((item) => (
|
{t.faq.domande.map((item) => (
|
||||||
<Accordion
|
<Accordion
|
||||||
className="relative w-full rounded-lg bg-muted p-4"
|
className="relative w-full rounded-lg bg-secondary p-4 text-secondary-foreground"
|
||||||
collapsible
|
collapsible
|
||||||
key={`accordion-${item.id}`}
|
key={`accordion-${item.id}`}
|
||||||
//defaultValue="0"
|
//defaultValue="0"
|
||||||
|
|
@ -135,14 +71,14 @@ const FAQSection = () => {
|
||||||
<div className="flex flex-col gap-1">
|
<div className="flex flex-col gap-1">
|
||||||
{item.qas.map((f, i) => (
|
{item.qas.map((f, i) => (
|
||||||
<AccordionItem
|
<AccordionItem
|
||||||
className="border-b dark:border-muted-foreground/50"
|
className="border-primary border-b"
|
||||||
key={`accordion-item-${item.id}-${
|
key={`accordion-item-${item.id}-${
|
||||||
// biome-ignore lint/suspicious/noArrayIndexKey: <ok>
|
// biome-ignore lint/suspicious/noArrayIndexKey: <ok>
|
||||||
i
|
i
|
||||||
}`}
|
}`}
|
||||||
value={i.toString()}
|
value={i.toString()}
|
||||||
>
|
>
|
||||||
<AccordionTrigger className="cursor-pointer text-left">
|
<AccordionTrigger className="cursor-pointer text-left [&>svg]:text-secondary-foreground">
|
||||||
{f.title}
|
{f.title}
|
||||||
</AccordionTrigger>
|
</AccordionTrigger>
|
||||||
<AccordionContent>
|
<AccordionContent>
|
||||||
|
|
@ -155,7 +91,6 @@ const FAQSection = () => {
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import Link from "next/link";
|
||||||
import { AccordionComp } from "~/components/accordionComp";
|
import { AccordionComp } from "~/components/accordionComp";
|
||||||
import { AnniversaryBanner } from "~/components/banners";
|
import { AnniversaryBanner } from "~/components/banners";
|
||||||
import { CodiceBox } from "~/components/codiceRicerca";
|
import { CodiceBox } from "~/components/codiceRicerca";
|
||||||
import { ComeFunziona } from "~/components/expand_guida";
|
|
||||||
import { HeroSvg } from "~/components/hero-svg";
|
import { HeroSvg } from "~/components/hero-svg";
|
||||||
|
import HowItWorks from "~/components/how-it-works";
|
||||||
import { LogoSvg } from "~/components/logo-svg";
|
import { LogoSvg } from "~/components/logo-svg";
|
||||||
import { PricingChoice } from "~/components/prezzi";
|
import { PricingChoice } from "~/components/prezzi";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -56,10 +56,11 @@ const Home: NextPage = () => {
|
||||||
|
|
||||||
<div className="flex w-full flex-col gap-y-4 md:gap-y-6">
|
<div className="flex w-full flex-col gap-y-4 md:gap-y-6">
|
||||||
{/* <FrequentSearches /> */}
|
{/* <FrequentSearches /> */}
|
||||||
<div className="mx-auto w-full max-w-5xl">
|
{/* <div className="mx-auto w-full max-w-5xl">
|
||||||
<ComeFunziona />
|
<ComeFunziona />
|
||||||
</div>
|
</div> */}
|
||||||
<AnniversaryBanner />
|
<AnniversaryBanner />
|
||||||
|
<HowItWorks />
|
||||||
<AccordionComp
|
<AccordionComp
|
||||||
className="w-full max-w-5xl"
|
className="w-full max-w-5xl"
|
||||||
texts={t.index.accordion_minifaq}
|
texts={t.index.accordion_minifaq}
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ const Prezzi: NextPage = () => {
|
||||||
|
|
||||||
{/* <ConsulenzaServizio data={prezziario.transitorio} /> */}
|
{/* <ConsulenzaServizio data={prezziario.transitorio} /> */}
|
||||||
<AccordionComp
|
<AccordionComp
|
||||||
className="w-full max-w-full rounded-lg bg-muted px-4 py-2"
|
className="w-full max-w-full px-4 py-2"
|
||||||
texts={t.prezzi.faq_transitori}
|
texts={t.prezzi.faq_transitori}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -122,7 +122,7 @@ const Prezzi: NextPage = () => {
|
||||||
</div>
|
</div>
|
||||||
{/* <ConsulenzaServizio data={prezziario.stabile} /> */}
|
{/* <ConsulenzaServizio data={prezziario.stabile} /> */}
|
||||||
<AccordionComp
|
<AccordionComp
|
||||||
className="w-full max-w-full rounded-lg bg-muted px-4 py-2"
|
className="w-full max-w-full rounded-lg px-4 py-2"
|
||||||
texts={t.prezzi.faq_stabile}
|
texts={t.prezzi.faq_stabile}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -170,7 +170,7 @@ const Prezzi: NextPage = () => {
|
||||||
</div>
|
</div>
|
||||||
{/* <ConsulenzaTable data={prezziario.consulenza} /> */}
|
{/* <ConsulenzaTable data={prezziario.consulenza} /> */}
|
||||||
<AccordionComp
|
<AccordionComp
|
||||||
className="w-full max-w-full rounded-lg bg-muted px-4 py-2"
|
className="w-full max-w-full rounded-lg px-4 py-2"
|
||||||
texts={t.prezzi.faq_contratti}
|
texts={t.prezzi.faq_contratti}
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import Link from "next/link";
|
||||||
import { AccordionComp } from "~/components/accordionComp";
|
import { AccordionComp } from "~/components/accordionComp";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Card, CardContent } from "~/components/ui/card";
|
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -55,15 +54,10 @@ const Proprietari: NextPage = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<Card className="mx-auto w-full max-w-4xl py-3">
|
|
||||||
<CardContent>
|
|
||||||
<AccordionComp
|
<AccordionComp
|
||||||
className="w-full max-w-full"
|
className="w-full max-w-full"
|
||||||
texts={t.proprietari.faq}
|
texts={t.proprietari.faq}
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<section className="relative mx-auto flex max-w-6xl flex-col items-center justify-between gap-8 px-4 py-4 sm:flex-row sm:gap-20 md:px-8">
|
<section className="relative mx-auto flex max-w-6xl flex-col items-center justify-between gap-8 px-4 py-4 sm:flex-row sm:gap-20 md:px-8">
|
||||||
<div className="mx-auto mt-5 flex-1 sm:w-9/12 md:mt-0 md:w-auto">
|
<div className="mx-auto mt-5 flex-1 sm:w-9/12 md:mt-0 md:w-auto">
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue