<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inscription - HTTP-MCP Bridge</title>
<link rel="stylesheet" href="/static/css/main.css">
</head>
<body>
<div class="min-h-screen flex items-center justify-center bg-secondary">
<div class="card w-full max-w-md">
<div class="card-header text-center">
<div class="logo-icon mx-auto mb-3">
đ
</div>
<h2 class="card-title text-xl">HTTP-MCP Bridge</h2>
<p class="card-subtitle">Créez votre compte</p>
</div>
<div class="card-content">
<form id="register-form" class="space-y-4">
<div class="form-group">
<label for="username" class="form-label">Nom d'utilisateur</label>
<input
type="text"
id="username"
name="username"
class="form-input"
required
autocomplete="username"
placeholder="Choisissez un nom d'utilisateur"
minlength="3"
>
<p class="text-xs text-secondary mt-1">Au moins 3 caractĂšres</p>
</div>
<div class="form-group">
<label for="email" class="form-label">Email</label>
<input
type="email"
id="email"
name="email"
class="form-input"
required
autocomplete="email"
placeholder="votre@email.com"
>
</div>
<div class="form-group">
<label for="password" class="form-label">Mot de passe</label>
<input
type="password"
id="password"
name="password"
class="form-input"
required
autocomplete="new-password"
placeholder="Créez un mot de passe"
minlength="6"
>
<p class="text-xs text-secondary mt-1">Au moins 6 caractĂšres, 1 majuscule, 1 minuscule, 1 chiffre</p>
</div>
<div class="form-group">
<label for="confirm_password" class="form-label">Confirmer le mot de passe</label>
<input
type="password"
id="confirm_password"
name="confirm_password"
class="form-input"
required
autocomplete="new-password"
placeholder="Répétez votre mot de passe"
>
</div>
<div class="form-group">
<label class="flex items-center gap-2">
<input type="checkbox" name="terms" class="form-checkbox" required>
<span class="text-sm">J'accepte les conditions d'utilisation</span>
</label>
</div>
<button type="submit" class="btn btn-primary w-full">
<span id="register-text">Créer mon compte</span>
<span id="register-loading" class="hidden">Création...</span>
</button>
</form>
<div id="register-error" class="alert alert-error mt-3 hidden"></div>
<div id="register-success" class="alert alert-success mt-3 hidden"></div>
<!-- Lien pour retourner Ă la connexion -->
<div class="text-center mt-4">
<p class="text-sm text-secondary mb-2">Déjà un compte ?</p>
<a href="/login" class="btn btn-outline w-full">
Se connecter
</a>
</div>
</div>
<div class="card-footer text-center">
<p class="text-sm text-secondary">
AccÚs sécurisé au bridge MCP Home Assistant
</p>
<div class="mt-2">
<span class="badge badge-info">v1.0.0</span>
</div>
</div>
</div>
</div>
<!-- Loader global -->
<div id="loader" class="fixed inset-0 bg-overlay flex items-center justify-center hidden z-50" style="display: none !important;">
<div class="bg-white p-6 rounded-lg shadow-lg">
<div class="flex items-center gap-3">
<div class="animate-spin w-5 h-5 border-2 border-primary border-t-transparent rounded-full"></div>
<span>Chargement...</span>
</div>
</div>
</div>
<script>
// EmpĂȘcher l'initialisation automatique de MCPDashboard sur la page d'inscription
window.skipDashboardInit = true;
</script>
<script src="/static/js/secure-cache.js"></script>
<!-- Le dashboard.js n'est pas nécessaire sur la page d'inscription -->
<script>
// đ Gestion du formulaire d'inscription uniquement
document.addEventListener('DOMContentLoaded', function() {
console.log('đ Page d\'inscription chargĂ©e');
const registerForm = document.getElementById('register-form');
if (registerForm) {
registerForm.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(registerForm);
const registerData = {
username: formData.get('username'),
email: formData.get('email'),
password: formData.get('password')
};
// Vérifier que les mots de passe correspondent
const confirmPassword = formData.get('confirm_password');
if (registerData.password !== confirmPassword) {
alert('Les mots de passe ne correspondent pas');
return;
}
try {
const response = await fetch('/auth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(registerData)
});
const result = await response.json();
if (response.ok) {
console.log('â
Inscription réussie');
alert('Inscription réussie ! Vous pouvez maintenant vous connecter.');
window.location.href = '/login';
} else {
console.error('â Erreur d\'inscription:', result.detail);
alert('Erreur d\'inscription: ' + result.detail);
}
} catch (error) {
console.error('đ„ Erreur rĂ©seau:', error);
alert('Erreur de connexion au serveur');
}
});
}
});
</script>
<script>
// Gestion spécifique de la page d'inscription
document.addEventListener('DOMContentLoaded', () => {
// Masquer le loader global s'il est affiché
const globalLoader = document.getElementById('loader');
if (globalLoader) {
globalLoader.classList.add('hidden');
}
// Rediriger si déjà connecté
const token = localStorage.getItem('mcp_token');
if (token && window.location.pathname === '/register') {
window.location.href = '/dashboard';
return;
}
const form = document.getElementById('register-form');
const errorDiv = document.getElementById('register-error');
const successDiv = document.getElementById('register-success');
const registerText = document.getElementById('register-text');
const registerLoading = document.getElementById('register-loading');
// Validation en temps réel des mots de passe
const password = document.getElementById('password');
const confirmPassword = document.getElementById('confirm_password');
function validatePasswords() {
if (password.value !== confirmPassword.value) {
confirmPassword.setCustomValidity('Les mots de passe ne correspondent pas');
} else {
confirmPassword.setCustomValidity('');
}
}
password.addEventListener('input', validatePasswords);
confirmPassword.addEventListener('input', validatePasswords);
form.addEventListener('submit', async (e) => {
e.preventDefault();
// Validation finale
if (password.value !== confirmPassword.value) {
errorDiv.textContent = 'Les mots de passe ne correspondent pas';
errorDiv.classList.remove('hidden');
return;
}
// UI Loading state
registerText.classList.add('hidden');
registerLoading.classList.remove('hidden');
errorDiv.classList.add('hidden');
successDiv.classList.add('hidden');
const formData = new FormData(form);
const userData = {
username: formData.get('username'),
email: formData.get('email'),
password: formData.get('password')
};
try {
const response = await fetch('/auth/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(userData)
});
if (response.ok) {
const data = await response.json();
// Afficher le succĂšs
successDiv.textContent = 'Compte créé avec succĂšs ! Vous allez ĂȘtre redirigĂ© vers la connexion.';
successDiv.classList.remove('hidden');
// Rediriger vers login aprĂšs 2 secondes
setTimeout(() => {
window.location.href = '/login';
}, 2000);
} else {
const error = await response.json();
throw new Error(error.detail || 'Erreur lors de la création du compte');
}
} catch (error) {
console.error('Erreur inscription:', error);
errorDiv.textContent = error.message || 'Erreur lors de la création du compte. Veuillez réessayer.';
errorDiv.classList.remove('hidden');
} finally {
// Reset UI
registerText.classList.remove('hidden');
registerLoading.classList.add('hidden');
}
});
// Focus automatique sur le champ username
document.getElementById('username').focus();
});
</script>
<style>
.min-h-screen {
min-height: 100vh;
}
.max-w-md {
max-width: 28rem;
}
.space-y-4 > * + * {
margin-top: 1rem;
}
.form-checkbox {
width: 1rem;
height: 1rem;
border: 1px solid var(--border-color);
border-radius: 3px;
}
.animate-spin {
animation: spin 1s linear infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.fixed {
position: fixed;
}
.inset-0 {
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.z-50 {
z-index: 50;
}
</style>
</body>
</html>