html / index.html
ubaliiringim's picture
Add 3 files
349d4dd verified
Raw History Blame Contribute Delete
21.8 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Auth System | Login & Signup</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Firebase SDK -->
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-auth.js"></script>
<style>
.auth-container {
perspective: 1000px;
}
.auth-form {
transition: transform 0.6s;
transform-style: preserve-3d;
}
.flipped {
transform: rotateY(180deg);
}
.form-front, .form-back {
backface-visibility: hidden;
position: absolute;
width: 100%;
}
.form-back {
transform: rotateY(180deg);
}
.input-field:focus-within {
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5);
}
.error-message {
animation: shake 0.5s;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
20%, 40%, 60%, 80% { transform: translateX(5px); }
}
</style>
</head>
<body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen flex items-center justify-center p-4">
<div class="auth-container w-full max-w-md">
<div class="auth-form relative w-full h-full">
<!-- Login Form (Front) -->
<div class="form-front bg-white rounded-xl shadow-2xl p-8">
<div class="text-center mb-8">
<h1 class="text-3xl font-bold text-indigo-600">Welcome Back</h1>
<p class="text-gray-500 mt-2">Login to access your account</p>
</div>
<div id="login-error" class="hidden bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4"></div>
<form id="login-form" class="space-y-6">
<div class="input-field bg-gray-50 rounded-lg p-3 border border-gray-200 transition-all">
<label for="login-email" class="block text-sm font-medium text-gray-700 mb-1">Email</label>
<div class="flex items-center">
<i class="fas fa-envelope text-gray-400 mr-2"></i>
<input type="email" id="login-email" required class="w-full bg-transparent outline-none text-gray-700">
</div>
</div>
<div class="input-field bg-gray-50 rounded-lg p-3 border border-gray-200 transition-all">
<label for="login-password" class="block text-sm font-medium text-gray-700 mb-1">Password</label>
<div class="flex items-center">
<i class="fas fa-lock text-gray-400 mr-2"></i>
<input type="password" id="login-password" required class="w-full bg-transparent outline-none text-gray-700">
<button type="button" class="text-gray-400 hover:text-gray-600" onclick="togglePassword('login-password', this)">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<input id="remember-me" type="checkbox" class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded">
<label for="remember-me" class="ml-2 block text-sm text-gray-700">Remember me</label>
</div>
<a href="#" class="text-sm text-indigo-600 hover:text-indigo-500">Forgot password?</a>
</div>
<button type="submit" class="w-full bg-indigo-600 text-white py-3 px-4 rounded-lg font-medium hover:bg-indigo-700 transition duration-300 flex items-center justify-center">
<span id="login-btn-text">Login</span>
<i id="login-spinner" class="fas fa-spinner fa-spin ml-2 hidden"></i>
</button>
</form>
<div class="mt-6">
<div class="relative">
<div class="absolute inset-0 flex items-center">
<div class="w-full border-t border-gray-300"></div>
</div>
<div class="relative flex justify-center text-sm">
<span class="px-2 bg-white text-gray-500">Or continue with</span>
</div>
</div>
<div class="mt-6 grid grid-cols-2 gap-3">
<button onclick="signInWithGoogle()" class="w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
<i class="fab fa-google text-red-500 mr-2"></i> Google
</button>
<button onclick="signInWithGithub()" class="w-full inline-flex justify-center py-2 px-4 border border-gray-300 rounded-md shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50">
<i class="fab fa-github text-gray-800 mr-2"></i> GitHub
</button>
</div>
<p class="mt-6 text-center text-sm text-gray-600">
Don't have an account?
<button onclick="flipForm()" class="text-indigo-600 font-medium hover:text-indigo-500">Sign up</button>
</p>
</div>
</div>
<!-- Signup Form (Back) -->
<div class="form-back bg-white rounded-xl shadow-2xl p-8">
<div class="text-center mb-8">
<h1 class="text-3xl font-bold text-indigo-600">Create Account</h1>
<p class="text-gray-500 mt-2">Join us today!</p>
</div>
<div id="signup-error" class="hidden bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4"></div>
<form id="signup-form" class="space-y-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="input-field bg-gray-50 rounded-lg p-3 border border-gray-200 transition-all">
<label for="signup-firstname" class="block text-sm font-medium text-gray-700 mb-1">First Name</label>
<div class="flex items-center">
<i class="fas fa-user text-gray-400 mr-2"></i>
<input type="text" id="signup-firstname" required class="w-full bg-transparent outline-none text-gray-700">
</div>
</div>
<div class="input-field bg-gray-50 rounded-lg p-3 border border-gray-200 transition-all">
<label for="signup-lastname" class="block text-sm font-medium text-gray-700 mb-1">Last Name</label>
<div class="flex items-center">
<i class="fas fa-user text-gray-400 mr-2"></i>
<input type="text" id="signup-lastname" required class="w-full bg-transparent outline-none text-gray-700">
</div>
</div>
</div>
<div class="input-field bg-gray-50 rounded-lg p-3 border border-gray-200 transition-all">
<label for="signup-email" class="block text-sm font-medium text-gray-700 mb-1">Email</label>
<div class="flex items-center">
<i class="fas fa-envelope text-gray-400 mr-2"></i>
<input type="email" id="signup-email" required class="w-full bg-transparent outline-none text-gray-700">
</div>
</div>
<div class="input-field bg-gray-50 rounded-lg p-3 border border-gray-200 transition-all">
<label for="signup-password" class="block text-sm font-medium text-gray-700 mb-1">Password</label>
<div class="flex items-center">
<i class="fas fa-lock text-gray-400 mr-2"></i>
<input type="password" id="signup-password" required class="w-full bg-transparent outline-none text-gray-700">
<button type="button" class="text-gray-400 hover:text-gray-600" onclick="togglePassword('signup-password', this)">
<i class="fas fa-eye"></i>
</button>
</div>
<p class="text-xs text-gray-500 mt-1">Must be at least 8 characters</p>
</div>
<div class="input-field bg-gray-50 rounded-lg p-3 border border-gray-200 transition-all">
<label for="signup-confirm-password" class="block text-sm font-medium text-gray-700 mb-1">Confirm Password</label>
<div class="flex items-center">
<i class="fas fa-lock text-gray-400 mr-2"></i>
<input type="password" id="signup-confirm-password" required class="w-full bg-transparent outline-none text-gray-700">
<button type="button" class="text-gray-400 hover:text-gray-600" onclick="togglePassword('signup-confirm-password', this)">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="flex items-center">
<input id="terms" type="checkbox" required class="h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded">
<label for="terms" class="ml-2 block text-sm text-gray-700">
I agree to the <a href="#" class="text-indigo-600 hover:text-indigo-500">Terms</a> and <a href="#" class="text-indigo-600 hover:text-indigo-500">Privacy Policy</a>
</label>
</div>
<button type="submit" class="w-full bg-indigo-600 text-white py-3 px-4 rounded-lg font-medium hover:bg-indigo-700 transition duration-300 flex items-center justify-center">
<span id="signup-btn-text">Sign Up</span>
<i id="signup-spinner" class="fas fa-spinner fa-spin ml-2 hidden"></i>
</button>
<p class="mt-6 text-center text-sm text-gray-600">
Already have an account?
<button onclick="flipForm()" class="text-indigo-600 font-medium hover:text-indigo-500">Login</button>
</p>
</form>
</div>
</div>
</div>
<!-- Success Modal -->
<div id="success-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white rounded-xl p-8 max-w-md w-full mx-4 text-center">
<div class="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<i class="fas fa-check text-green-500 text-2xl"></i>
</div>
<h3 class="text-2xl font-bold text-gray-800 mb-2" id="success-title">Success!</h3>
<p class="text-gray-600 mb-6" id="success-message">Your account has been created successfully.</p>
<button onclick="closeSuccessModal()" class="bg-indigo-600 text-white px-6 py-2 rounded-lg hover:bg-indigo-700 transition">
Continue
</button>
</div>
</div>
<script>
// Firebase configuration - Replace with your actual config
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const auth = firebase.auth();
// Toggle password visibility
function togglePassword(id, button) {
const input = document.getElementById(id);
const icon = button.querySelector('i');
if (input.type === 'password') {
input.type = 'text';
icon.classList.replace('fa-eye', 'fa-eye-slash');
} else {
input.type = 'password';
icon.classList.replace('fa-eye-slash', 'fa-eye');
}
}
// Flip between login and signup forms
function flipForm() {
document.querySelector('.auth-form').classList.toggle('flipped');
}
// Close success modal
function closeSuccessModal() {
document.getElementById('success-modal').classList.add('hidden');
}
// Handle login form submission
document.getElementById('login-form').addEventListener('submit', async (e) => {
e.preventDefault();
const email = document.getElementById('login-email').value;
const password = document.getElementById('login-password').value;
const errorElement = document.getElementById('login-error');
const loginBtnText = document.getElementById('login-btn-text');
const loginSpinner = document.getElementById('login-spinner');
// Show loading state
loginBtnText.textContent = 'Logging in...';
loginSpinner.classList.remove('hidden');
try {
const userCredential = await auth.signInWithEmailAndPassword(email, password);
// Login successful
showSuccess('Login Successful', 'You have been logged in successfully!');
} catch (error) {
// Handle errors
errorElement.textContent = getErrorMessage(error.code);
errorElement.classList.remove('hidden');
setTimeout(() => errorElement.classList.add('hidden'), 5000);
} finally {
// Reset button state
loginBtnText.textContent = 'Login';
loginSpinner.classList.add('hidden');
}
});
// Handle signup form submission
document.getElementById('signup-form').addEventListener('submit', async (e) => {
e.preventDefault();
const firstName = document.getElementById('signup-firstname').value;
const lastName = document.getElementById('signup-lastname').value;
const email = document.getElementById('signup-email').value;
const password = document.getElementById('signup-password').value;
const confirmPassword = document.getElementById('signup-confirm-password').value;
const errorElement = document.getElementById('signup-error');
const signupBtnText = document.getElementById('signup-btn-text');
const signupSpinner = document.getElementById('signup-spinner');
// Validate passwords match
if (password !== confirmPassword) {
errorElement.textContent = 'Passwords do not match';
errorElement.classList.remove('hidden');
setTimeout(() => errorElement.classList.add('hidden'), 5000);
return;
}
// Validate password length
if (password.length < 8) {
errorElement.textContent = 'Password must be at least 8 characters';
errorElement.classList.remove('hidden');
setTimeout(() => errorElement.classList.add('hidden'), 5000);
return;
}
// Show loading state
signupBtnText.textContent = 'Creating account...';
signupSpinner.classList.remove('hidden');
try {
const userCredential = await auth.createUserWithEmailAndPassword(email, password);
// Update user profile with name
await userCredential.user.updateProfile({
displayName: `${firstName} ${lastName}`
});
// Signup successful
showSuccess('Account Created', 'Your account has been created successfully!');
flipForm(); // Flip back to login form
} catch (error) {
// Handle errors
errorElement.textContent = getErrorMessage(error.code);
errorElement.classList.remove('hidden');
setTimeout(() => errorElement.classList.add('hidden'), 5000);
} finally {
// Reset button state
signupBtnText.textContent = 'Sign Up';
signupSpinner.classList.add('hidden');
}
});
// Google Sign In
function signInWithGoogle() {
const provider = new firebase.auth.GoogleAuthProvider();
auth.signInWithPopup(provider)
.then((result) => {
showSuccess('Login Successful', 'You have been logged in with Google!');
})
.catch((error) => {
document.getElementById('login-error').textContent = getErrorMessage(error.code);
document.getElementById('login-error').classList.remove('hidden');
setTimeout(() => document.getElementById('login-error').classList.add('hidden'), 5000);
});
}
// GitHub Sign In
function signInWithGithub() {
const provider = new firebase.auth.GithubAuthProvider();
auth.signInWithPopup(provider)
.then((result) => {
showSuccess('Login Successful', 'You have been logged in with GitHub!');
})
.catch((error) => {
document.getElementById('login-error').textContent = getErrorMessage(error.code);
document.getElementById('login-error').classList.remove('hidden');
setTimeout(() => document.getElementById('login-error').classList.add('hidden'), 5000);
});
}
// Show success modal
function showSuccess(title, message) {
document.getElementById('success-title').textContent = title;
document.getElementById('success-message').textContent = message;
document.getElementById('success-modal').classList.remove('hidden');
}
// Map Firebase error codes to user-friendly messages
function getErrorMessage(errorCode) {
const errorMessages = {
'auth/invalid-email': 'Invalid email address',
'auth/user-disabled': 'Account disabled',
'auth/user-not-found': 'Account not found',
'auth/wrong-password': 'Incorrect password',
'auth/email-already-in-use': 'Email already in use',
'auth/operation-not-allowed': 'Operation not allowed',
'auth/weak-password': 'Password is too weak',
'auth/network-request-failed': 'Network error. Please check your connection',
'auth/too-many-requests': 'Too many attempts. Try again later',
'auth/popup-closed-by-user': 'Sign in popup was closed',
'auth/cancelled-popup-request': 'Only one popup request allowed at a time'
};
return errorMessages[errorCode] || 'An error occurred. Please try again.';
}
// Check if user is already logged in
auth.onAuthStateChanged((user) => {
if (user) {
// User is signed in
showSuccess('Welcome Back', `You're already logged in as ${user.displayName || user.email}`);
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=ubaliiringim/html" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>