frontend/app/components/repas/credentials.tsx
Nathan Lamy 81d73fd99d
All checks were successful
Deploy to Netlify / Deploy to Netlify (push) Successful in 1m31s
feat: add BJRepas credentials
2025-08-26 00:26:30 +02:00

148 lines
4.9 KiB
TypeScript

import { Github, Loader2, Save } from "lucide-react";
import { Button } from "../ui/button";
import { Card } from "../ui/card";
import { Input } from "../ui/input";
import { Label } from "../ui/label";
import { Link } from "react-router";
import { getCredentialsStatus, testCredentials } from "~/lib/api";
import { useState } from "react";
import { toast } from "sonner";
export default function BJRepas() {
const credentials = getSavedCredentials();
const [username, setUsername] = useState(credentials?.username || "");
const [password, setPassword] = useState(credentials?.password || "");
let intervalId: NodeJS.Timeout | null = null;
const [isLoading, setLoading] = useState(false);
const handleSaveCredentials = async () => {
try {
if (!username || !password) {
toast.error(
"Veuillez renseigner vos identifiants BJColle avant de continuer."
);
return;
}
await testCredentials(username, password);
setLoading(true);
// Try every second to check if the credentials are valid
intervalId = setInterval(async () => {
try {
const res = await getCredentialsStatus();
// Credentials are valid
if (res.authenticated === "SUCCESS") {
saveCredentials(username, password);
toast.success("Vos identifiants ont été enregistrés avec succès.");
setLoading(false);
if (intervalId) clearInterval(intervalId);
}
// Credentials are invalid
if (res.authenticated === "ERROR") {
toast.error(
"Identifiants invalides. Veuillez vérifier votre nom d'utilisateur et mot de passe."
);
setUsername("");
setPassword("");
setLoading(false);
if (intervalId) clearInterval(intervalId);
}
} catch (error) {
console.error("Error testing credentials:", error);
}
}, 1000);
} catch (error) {
console.error("Error testing credentials:", error);
toast.error(
"Une erreur est survenue lors de la validation des identifiants. Veuillez réessayer plus tard."
);
}
};
return (
<div className="space-y-4 px-2">
<h2 className="text-2xl font-bold">Inscription aux repas</h2>
<p className="text-muted-foreground text-sm">
Pour vous inscrire aux repas (via BJ Repas), veuillez renseigner vos
identifiants BJColle ci-dessous.
</p>
<p className="text-muted-foreground text-xs">
Vos identifiants sont enregistrés localement sur votre appareil et ne
sont jamais stockés sur nos serveurs.
</p>
<Card className="space-y-4 p-4 my-6">
<div className="space-y-4">
<h4 className="text-lg font-semibold">Vos identifiants BJColle</h4>
<div>
<Label htmlFor="username">Nom d'utilisateur</Label>
<Input
type="text"
id="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
placeholder="Entrez votre nom d'utilisateur"
className="mt-1"
/>
</div>
<div>
<Label htmlFor="password">Mot de passe</Label>
<Input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Entrez votre mot de passe"
className="mt-1"
/>
</div>
<Button
className="w-full"
onClick={handleSaveCredentials}
disabled={isLoading}
>
{isLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Vérification en cours...
</>
) : (
<>
<Save className="mr-2 h-4 w-4" />
Enregistrer mes identifiants
</>
)}
</Button>
</div>
</Card>
<div className="flex justify-center items-center flex-col space-y-1">
<p className="text-sm text-muted-foreground text-center">
Pour en savoir plus sur la sécurité et la confidentialité, consultez
le code source du projet.{" "}
</p>
<Link to={import.meta.env.VITE_GITHUB_URL} target="_blank">
<Button variant="link" size="sm" className="p-0">
<Github className="h-4 w-4" />
Khollisé sur GitHub
</Button>
</Link>
</div>
</div>
);
}
const saveCredentials = (username: string, password: string) => {
localStorage.setItem("bj_username", username);
localStorage.setItem("bj_password", password);
};
export const getSavedCredentials = () => {
const username = localStorage.getItem("bj_username");
const password = localStorage.getItem("bj_password");
if (username && password) {
return { username, password };
}
return null;
};