Skip to content

Esempi Pratici ​

πŸ“Š Esempio 1: Dashboard Protetta ​

Configurazione ​

typescript
// app/routes.ts
export default [
    route("dashboard", "routes/dashboard.tsx"),
] satisfies RouteConfig;

Implementazione ​

typescript
// app/routes/dashboard.tsx
import { AuthenticatedLayout } from "@/components/layout/authenticated-layout";
import { createProtectedLoader } from "@/lib/auth/loaders";

// βœ… Protezione automatica
export const clientLoader = createProtectedLoader();

export default function Dashboard() {
    return (
        <AuthenticatedLayout>
            <div className="p-8">
                <h1 className="text-3xl font-bold mb-6">Dashboard</h1>

                <div className="grid grid-cols-1 md:grid-cols-3 gap-6">
                    <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
                        <h2 className="text-xl font-semibold mb-2">Statistiche</h2>
                        <p className="text-gray-600 dark:text-gray-400">
                            I tuoi dati principali
                        </p>
                    </div>

                    <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
                        <h2 className="text-xl font-semibold mb-2">AttivitΓ </h2>
                        <p className="text-gray-600 dark:text-gray-400">
                            Ultime azioni
                        </p>
                    </div>

                    <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
                        <h2 className="text-xl font-semibold mb-2">Notifiche</h2>
                        <p className="text-gray-600 dark:text-gray-400">
                            Messaggi recenti
                        </p>
                    </div>
                </div>
            </div>
        </AuthenticatedLayout>
    );
}

πŸ‘€ Esempio 2: Pagina Profilo con Dati Utente ​

Configurazione ​

typescript
// app/routes.ts
export default [
    route("profile", "routes/profile.tsx"),
] satisfies RouteConfig;

Implementazione ​

typescript
// app/routes/profile.tsx
import { AuthenticatedLayout } from "@/components/layout/authenticated-layout";
import { createProtectedLoader } from "@/lib/auth/loaders";
import { useAuthStore } from "@/store/auth/auth.store";
import { useState } from "react";

// βœ… Protezione con requireSettings: true
// Verifica SIA l'autenticazione CHE la presenza dei settings utente
// Se i settings non sono presenti, reindirizza a /welcome per caricarli
export const clientLoader = createProtectedLoader({ requireSettings: true });

export default function Profile() {
    const userSettings = useAuthStore((state) => state.userSettings);

    // Grazie a requireSettings: true, sei sicuro che userSettings non Γ¨ null
    const [name, setName] = useState(userSettings!.data.d_user);
    const [company, setCompany] = useState(userSettings!.data.d_company);

    const handleSave = () => {
        // Logica di salvataggio
        console.log("Profilo salvato", { name, company });
    };

    return (
        <AuthenticatedLayout>
            <div className="max-w-2xl mx-auto p-8">
                <h1 className="text-3xl font-bold mb-6">Il Mio Profilo</h1>

                <div className="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
                    <div className="space-y-4">
                        <div>
                            <label className="block text-sm font-medium mb-2">
                                Nome Utente
                            </label>
                            <input
                                type="text"
                                value={name}
                                onChange={(e) => setName(e.target.value)}
                                className="w-full px-3 py-2 border rounded-md"
                            />
                        </div>

                        <div>
                            <label className="block text-sm font-medium mb-2">
                                Azienda
                            </label>
                            <input
                                type="text"
                                value={company}
                                onChange={(e) => setCompany(e.target.value)}
                                className="w-full px-3 py-2 border rounded-md"
                            />
                        </div>

                        <div>
                            <label className="block text-sm font-medium mb-2">
                                Moduli Disponibili
                            </label>
                            <ul className="list-disc list-inside">
                                {userSettings!.data.modules.map((module) => (
                                    <li key={module.id}>{module.name}</li>
                                ))}
                            </ul>
                        </div>

                        <button
                            onClick={handleSave}
                            className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700"
                        >
                            Salva Modifiche
                        </button>
                    </div>
                </div>
            </div>
        </AuthenticatedLayout>
    );
}

πŸ“ Esempio 3: Form di Registrazione ​

Configurazione ​

typescript
// app/routes.ts
export default [
    route("register", "routes/register.tsx"),
] satisfies RouteConfig;

Implementazione ​

typescript
```typescript
// app/routes/register.tsx
import { useState } from "react";
import { useNavigate, Link } from "react-router";
import { createGuestLoader } from "@/lib/auth/loaders";

// βœ… Reindirizza utenti giΓ  autenticati
export const clientLoader = createGuestLoader();

export default function Register() {
    const navigate = useNavigate();
    const [formData, setFormData] = useState({
        username: "",
        email: "",
        password: "",
    });

    const handleSubmit = (e: React.FormEvent) => {
        e.preventDefault();

        // Logica di registrazione
        console.log("Registrazione:", formData);

        // Dopo la registrazione, reindirizza al login
        navigate("/");
    };

    return (
        <div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900">
            <div className="max-w-md w-full bg-white dark:bg-gray-800 rounded-lg shadow-lg p-8">
                <h1 className="text-3xl font-bold text-center mb-6">
                    Registrazione
                </h1>

                <form onSubmit={handleSubmit} className="space-y-4">
                    <div>
                        <label className="block text-sm font-medium mb-2">
                            Username
                        </label>
                        <input
                            type="text"
                            value={formData.username}
                            onChange={(e) => setFormData({...formData, username: e.target.value})}
                            className="w-full px-3 py-2 border rounded-md"
                            required
                        />
                    </div>

                    <div>
                        <label className="block text-sm font-medium mb-2">
                            Email
                        </label>
                        <input
                            type="email"
                            value={formData.email}
                            onChange={(e) => setFormData({...formData, email: e.target.value})}
```" "}
                    <Link to="/" className="text-blue-600 hover:underline">
                        Accedi
                    </Link>
                </p>
            </div>
        </div>
    );
}

ℹ️ Esempio 4: Pagina Pubblica Generica ​

Configurazione ​

typescript
// app/routes.ts
export default [
    route("about", "routes/about.tsx"),  // Non in PROTECTED nΓ© in PUBLIC
] satisfies RouteConfig;

Implementazione ​

typescript
// app/routes/about.tsx
import { Link } from "react-router";

export default function About() {
    return (
        <div className="min-h-screen bg-gray-50 dark:bg-gray-900">
            <div className="max-w-4xl mx-auto p-8">
                <h1 className="text-4xl font-bold mb-6">Chi Siamo</h1>

                <div className="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-8">
                    <p className="text-lg mb-4">
                        Questa Γ¨ una pagina pubblica accessibile a tutti,
                        sia utenti autenticati che non.
                    </p>

                    <p className="text-gray-600 dark:text-gray-400 mb-4">
                        Puoi inserire qui informazioni sulla tua azienda,
                        il team, la missione, ecc.
                    </p>

                    <div className="mt-6">
                        <Link
                            to="/"
                            className="text-blue-600 hover:underline"
                        >
                            ← Torna al Login
                        </Link>
                    </div>
                </div>
            </div>
        </div>
    );
}

🎯 Note Importanti ​

  • Tutti gli esempi usano clientLoader per bloccare prima del render
  • createProtectedLoader() per pagine che richiedono solo autenticazione
  • createProtectedLoader({ requireSettings: true }) per pagine che richiedono autenticazione + settings utente (verifica entrambe le condizioni)
  • createGuestLoader() per pagine come login/register
  • Nessun clientLoader per pagine accessibili a tutti
  • AuthenticatedLayout fornisce menu e logout automatici
  • Puoi usare tutti gli hook di React Router normalmente

Documentazione Elerama Frontend