Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
This commit is contained in:
parent
1716a1bbda
commit
fa2532503c
@ -17,6 +17,7 @@ const AuthInitializer: React.FC<AuthInitializerProps> = ({ children }) => {
|
|||||||
const isAuthenticated = useAppSelector(selectIsAuthenticated);
|
const isAuthenticated = useAppSelector(selectIsAuthenticated);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log('AuthInitializer effect - isAuthenticated:', isAuthenticated, 'showLogin:', showLogin);
|
||||||
// Only process admin parameter once
|
// Only process admin parameter once
|
||||||
if (hasProcessedAdminParam) return;
|
if (hasProcessedAdminParam) return;
|
||||||
|
|
||||||
@ -52,7 +53,10 @@ const AuthInitializer: React.FC<AuthInitializerProps> = ({ children }) => {
|
|||||||
return (
|
return (
|
||||||
<LoginPrompt
|
<LoginPrompt
|
||||||
isAdmin={isAdminMode}
|
isAdmin={isAdminMode}
|
||||||
onComplete={() => setShowLogin(false)}
|
onComplete={() => {
|
||||||
|
console.log('onComplete called, setting showLogin to false');
|
||||||
|
setShowLogin(false);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { IonIcon } from '@ionic/react';
|
||||||
|
import { micOutline } from 'ionicons/icons';
|
||||||
import { useAppDispatch } from '../../redux/hooks';
|
import { useAppDispatch } from '../../redux/hooks';
|
||||||
import { setAuth } from '../../redux/authSlice';
|
import { setAuth } from '../../redux/authSlice';
|
||||||
|
import { database } from '../../firebase/config';
|
||||||
|
import { ref, get } from 'firebase/database';
|
||||||
import type { Authentication } from '../../types';
|
import type { Authentication } from '../../types';
|
||||||
|
|
||||||
interface LoginPromptProps {
|
interface LoginPromptProps {
|
||||||
@ -9,77 +13,242 @@ interface LoginPromptProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const LoginPrompt: React.FC<LoginPromptProps> = ({ isAdmin, onComplete }) => {
|
const LoginPrompt: React.FC<LoginPromptProps> = ({ isAdmin, onComplete }) => {
|
||||||
const [singerName, setSingerName] = useState(isAdmin ? 'Admin' : '');
|
const [singerName, setSingerName] = useState(isAdmin ? 'Admin' : 'Matt');
|
||||||
const [partyId, setPartyId] = useState('');
|
const [partyId, setPartyId] = useState('mbrucedogs-test');
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const handleSubmit = (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
console.log('Login form submitted');
|
||||||
if (!partyId.trim() || !singerName.trim()) {
|
if (!partyId.trim() || !singerName.trim()) {
|
||||||
setError('Please enter both Party Id and your name.');
|
setError('Please enter both Party Id and your name.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setError('');
|
setError('');
|
||||||
const auth: Authentication = {
|
|
||||||
authenticated: true,
|
// Check if controller exists in Firebase
|
||||||
singer: singerName.trim(),
|
try {
|
||||||
isAdmin: isAdmin,
|
const controllerRef = ref(database, `controllers/${partyId.trim()}`);
|
||||||
controller: partyId.trim(),
|
const snapshot = await get(controllerRef);
|
||||||
};
|
|
||||||
dispatch(setAuth(auth));
|
if (!snapshot.exists()) {
|
||||||
onComplete();
|
setError('Invalid Party Id. Please check your Party Id and try again.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auth: Authentication = {
|
||||||
|
authenticated: true,
|
||||||
|
singer: singerName.trim(),
|
||||||
|
isAdmin: isAdmin,
|
||||||
|
controller: partyId.trim(),
|
||||||
|
};
|
||||||
|
console.log('Dispatching auth:', auth);
|
||||||
|
dispatch(setAuth(auth));
|
||||||
|
console.log('Calling onComplete');
|
||||||
|
onComplete();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking controller:', error);
|
||||||
|
setError('Error connecting to server. Please try again.');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen flex items-center justify-center bg-gray-50">
|
<>
|
||||||
<div className="max-w-md w-full bg-white shadow-lg rounded-lg p-6">
|
<div className="login-container">
|
||||||
<div className="text-center mb-6">
|
<div className="login-card">
|
||||||
<h1 className="text-2xl font-bold text-gray-900 mb-2">
|
<div className="login-header">
|
||||||
Welcome to Karaoke! 🎤
|
<h1 className="login-title">Login</h1>
|
||||||
</h1>
|
<div className="app-brand">
|
||||||
<p className="text-gray-600">
|
<div className="microphone-icon">
|
||||||
{isAdmin ? 'You have admin privileges' : 'Enter your Party Id and name to get started'}
|
<IonIcon icon={micOutline} size='large'/>
|
||||||
</p>
|
</div>
|
||||||
|
<h2 className="app-name">Sings-A-Lot</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form onSubmit={handleSubmit} className="login-form">
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="partyId" className="form-label">
|
||||||
|
Party Id
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="partyId"
|
||||||
|
value={partyId}
|
||||||
|
onChange={(e) => setPartyId(e.target.value)}
|
||||||
|
className="form-input"
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="singerName" className="form-label">
|
||||||
|
FirstName
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="singerName"
|
||||||
|
value={singerName}
|
||||||
|
onChange={(e) => setSingerName(e.target.value)}
|
||||||
|
className="form-input"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{error && <div className="error-message">{error}</div>}
|
||||||
|
|
||||||
|
<button type="submit" className="login-button">
|
||||||
|
Login
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={handleSubmit} className="space-y-4">
|
|
||||||
<div>
|
|
||||||
<label htmlFor="partyId" className="block text-sm font-medium text-gray-700 mb-1">
|
|
||||||
Party Id
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="partyId"
|
|
||||||
value={partyId}
|
|
||||||
onChange={(e) => setPartyId(e.target.value)}
|
|
||||||
placeholder="Enter your Party Id"
|
|
||||||
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
||||||
autoFocus
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label htmlFor="singerName" className="block text-sm font-medium text-gray-700 mb-1">
|
|
||||||
Your Name
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="singerName"
|
|
||||||
value={singerName}
|
|
||||||
onChange={(e) => setSingerName(e.target.value)}
|
|
||||||
placeholder={isAdmin ? 'Admin' : 'Enter your name'}
|
|
||||||
className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{error && <div className="text-red-500 text-sm text-center">{error}</div>}
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="w-full bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-md transition-colors"
|
|
||||||
>
|
|
||||||
{isAdmin ? 'Start as Admin' : 'Join Session'}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<style>{`
|
||||||
|
.login-container {
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #000000;
|
||||||
|
color: #ffffff;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-card {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 400px;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-header {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-brand {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.microphone-icon {
|
||||||
|
font-size: 3rem;
|
||||||
|
color: #3b82f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.microphone-icon ion-icon {
|
||||||
|
width: 3rem;
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-name {
|
||||||
|
font-size: 2rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
display: block;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.75rem;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #ffffff;
|
||||||
|
background: transparent;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 1rem;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input:focus {
|
||||||
|
border-bottom-color: #3b82f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
color: #ef4444;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
background-color: #3b82f6;
|
||||||
|
color: #ffffff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button:hover {
|
||||||
|
background-color: #2563eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-button:active {
|
||||||
|
transform: translateY(1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light mode overrides */
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
.login-container {
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-title,
|
||||||
|
.app-name,
|
||||||
|
.form-label {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input {
|
||||||
|
border-bottom-color: #000000;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input::placeholder {
|
||||||
|
color: rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user