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
clientLoaderper bloccare prima del render createProtectedLoader()per pagine che richiedono solo autenticazionecreateProtectedLoader({ requireSettings: true })per pagine che richiedono autenticazione + settings utente (verifica entrambe le condizioni)createGuestLoader()per pagine come login/register- Nessun
clientLoaderper pagine accessibili a tutti AuthenticatedLayoutfornisce menu e logout automatici- Puoi usare tutti gli hook di React Router normalmente