feat(OnboardTutorial): Add onboarding tutorial component with localization support
This commit is contained in:
parent
11b74ed6dc
commit
93169b191a
5 changed files with 169 additions and 1 deletions
123
apps/infoalloggi/src/components/onboard_tutorial.tsx
Normal file
123
apps/infoalloggi/src/components/onboard_tutorial.tsx
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
"use client";
|
||||
import { getCookie, setCookie } from "cookies-next/client";
|
||||
import { add } from "date-fns";
|
||||
import { ArrowRight, CheckCircle } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import { useTranslation } from "~/providers/I18nProvider";
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "./ui/alert-dialog";
|
||||
|
||||
const COOKIE_KEY = "onboard_tutorial_shown";
|
||||
|
||||
export const OnboardTutorial = () => {
|
||||
const { t } = useTranslation();
|
||||
const hasCookie = getCookie(COOKIE_KEY) === "true";
|
||||
|
||||
const handleClose = () => {
|
||||
setCookie(COOKIE_KEY, "true", {
|
||||
expires: add(new Date(), { days: 30 }),
|
||||
});
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasCookie) {
|
||||
const timer = setTimeout(() => {
|
||||
setOpen(true);
|
||||
}, 1000); // 1 second delay
|
||||
return () => clearTimeout(timer);
|
||||
}
|
||||
}, [hasCookie]);
|
||||
|
||||
return (
|
||||
<AlertDialog open={open}>
|
||||
<AlertDialogContent className="max-w-2xl">
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle className="flex items-center gap-2 font-semibold text-2xl">
|
||||
<CheckCircle className="size-7 text-green-500" />
|
||||
{t.onboarding_tutorial.title}
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription className="sr-only">
|
||||
descrizione
|
||||
</AlertDialogDescription>
|
||||
<div className="space-y-4 pt-4 text-base text-foreground">
|
||||
<p className="font-medium text-foreground text-lg">
|
||||
{t.onboarding_tutorial.sub_title}
|
||||
</p>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex gap-3">
|
||||
<div className="flex size-8 shrink-0 items-center justify-center rounded-full bg-blue-100 text-blue-600">
|
||||
<span className="font-semibold">1</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="font-semibold text-foreground">
|
||||
{t.onboarding_tutorial.step1_title}
|
||||
</p>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t.onboarding_tutorial.step1_desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-3">
|
||||
<div className="flex size-8 shrink-0 items-center justify-center rounded-full bg-blue-100 text-blue-600">
|
||||
<span className="font-semibold">2</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="font-semibold text-foreground">
|
||||
{t.onboarding_tutorial.step2_title}
|
||||
</p>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t.onboarding_tutorial.step2_desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-3">
|
||||
<div className="flex size-8 shrink-0 items-center justify-center rounded-full bg-blue-100 text-blue-600">
|
||||
<span className="font-semibold">3</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="font-semibold text-foreground">
|
||||
{t.onboarding_tutorial.step3_title}
|
||||
</p>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t.onboarding_tutorial.step3_desc}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 rounded-lg border border-blue-200 bg-blue-50 p-3">
|
||||
<p className="text-blue-900 text-sm">
|
||||
💡 <strong>{t.onboarding_tutorial.tip_title}</strong>{" "}
|
||||
{t.onboarding_tutorial.tip}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<Button
|
||||
className="flex items-center gap-2"
|
||||
onClick={handleClose}
|
||||
size="lg"
|
||||
variant="success"
|
||||
>
|
||||
<span>{t.onboarding_tutorial.button_text}</span>
|
||||
<ArrowRight className="size-5" />
|
||||
</Button>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
);
|
||||
};
|
||||
|
|
@ -1333,4 +1333,19 @@ The Stable Rent service, ideal for those with demonstrable work references and f
|
|||
verificata: "Email verified",
|
||||
verificata_desc: "You can now access your account.",
|
||||
},
|
||||
onboarding_tutorial: {
|
||||
title: "Welcome to Infoalloggi!",
|
||||
sub_title: "Follow these simple steps to activate the service:",
|
||||
step1_title: "Verify the pre-filled data",
|
||||
step1_desc:
|
||||
"We have pre-filled some fields, please check that everything is correct.",
|
||||
step2_title: "Complete the missing fields",
|
||||
step2_desc: "Add the required information to complete your request.",
|
||||
step3_title: "Proceed to payment",
|
||||
step3_desc:
|
||||
"Once the data is completed, you can proceed with the activation of the service.",
|
||||
tip_title: "Tip:",
|
||||
tip: "Make sure the entered data matches your search to get the best results.",
|
||||
button_text: "Got it, let's get started!",
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1331,4 +1331,20 @@ export const it: LangDict = {
|
|||
verificata: "Email verificata",
|
||||
verificata_desc: "Ora puoi accedere al tuo account.",
|
||||
},
|
||||
onboarding_tutorial: {
|
||||
title: "Benvenuto in Infoalloggi!",
|
||||
sub_title: "Segui questi semplici passi per attivare il servizio:",
|
||||
step1_title: "Verifica i dati precompilati",
|
||||
step1_desc:
|
||||
"Abbiamo precompilato alcuni campi, controlla che tutto sia corretto.",
|
||||
step2_title: "Completa i campi mancanti",
|
||||
step2_desc:
|
||||
"Aggiungi le informazioni richieste per completare la tua richiesta.",
|
||||
step3_title: "Procedi al pagamento",
|
||||
step3_desc:
|
||||
"Una volta completati i dati, potrai procedere con l'attivazione del servizio.",
|
||||
tip_title: "Suggerimento:",
|
||||
tip: "Assicurati che i dati inseriti corrispondano alla tua ricerca per ottenere i migliori risultati.",
|
||||
button_text: "Ho capito, iniziamo!",
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -769,6 +769,19 @@ export type LangDict = {
|
|||
error: string;
|
||||
download: string;
|
||||
};
|
||||
onboarding_tutorial: {
|
||||
title: string;
|
||||
sub_title: string;
|
||||
step1_title: string;
|
||||
step1_desc: string;
|
||||
step2_title: string;
|
||||
step2_desc: string;
|
||||
step3_title: string;
|
||||
step3_desc: string;
|
||||
tip_title: string;
|
||||
tip: string;
|
||||
button_text: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type Locales = "it" | "en";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import type { GetServerSideProps } from "next";
|
||||
import { AreaRiservataLayout } from "~/components/Layout";
|
||||
import { LoadingPage } from "~/components/loading";
|
||||
import { OnboardTutorial } from "~/components/onboard_tutorial";
|
||||
import { Status500 } from "~/components/status-page";
|
||||
import { FormNewServizioAcquisto } from "~/forms/FormNewServizioAcquisto";
|
||||
import type { NextPageWithLayout } from "~/pages/_app";
|
||||
|
|
@ -34,7 +35,7 @@ const OnboardServizio: NextPageWithLayout<OnboardServizioProps> = ({
|
|||
{locale === "it" ? "Dettagli del servizio" : "Service Details"}
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<OnboardTutorial />
|
||||
<FormNewServizioAcquisto initialData={data} userId={data.userData.id} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue