build: d805a69a-e437-4a58-a083-30e34be74fcd

This commit is contained in:
AppCakes
2026-05-29 11:55:08 +00:00
commit eabe2fef76
131 changed files with 10025 additions and 0 deletions
+203
View File
@@ -0,0 +1,203 @@
import React, { useState } from 'react';
import {
IonButton,
IonContent,
IonHeader,
IonInput,
IonItem,
IonLabel,
IonPage,
IonText,
IonTitle,
IonToolbar,
useIonViewWillEnter,
} from '@ionic/react';
import { useHistory } from 'react-router-dom';
import { supabase } from '../supabase';
import { setStatusBarStyle, Style } from '../utils/statusBar';
const Auth: React.FC = () => {
const history = useHistory();
const [mode, setMode] = useState<'login' | 'signup'>('login');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [message, setMessage] = useState('');
const [errorMessage, setErrorMessage] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
useIonViewWillEnter(() => {
setStatusBarStyle(Style.Light);
});
const showError = (msg: string) => {
setErrorMessage(msg);
window.setTimeout(() => setErrorMessage(''), 4000);
};
const showMessage = (msg: string) => {
setMessage(msg);
window.setTimeout(() => setMessage(''), 4000);
};
const normaliseAuthError = (msg: string) => {
const lowered = msg.toLowerCase();
if (lowered.includes('email not confirmed')) {
return 'Please confirm your email before signing in. Check your inbox for the verification email.';
}
if (lowered.includes('invalid login credentials')) {
return 'Incorrect email or password. Please try again.';
}
if (lowered.includes('user already registered')) {
return 'An account with this email already exists. Please sign in instead.';
}
return msg;
};
const handleResendConfirmation = async () => {
if (!email.trim()) {
showError(
'Enter your email address first so we can resend the confirmation email.'
);
return;
}
setIsSubmitting(true);
const { error } = await supabase.auth.resend({
type: 'signup',
email: email.trim(),
});
setIsSubmitting(false);
if (error) {
showError(normaliseAuthError(error.message));
return;
}
showMessage('Confirmation email sent. Please check your inbox.');
};
const handleSubmit = async () => {
if (!email.trim() || password.trim().length < 6) {
showError('Enter a valid email and password with at least 6 characters.');
return;
}
setIsSubmitting(true);
if (mode === 'login') {
const { error } = await supabase.auth.signInWithPassword({
email: email.trim(),
password,
});
setIsSubmitting(false);
if (error) {
showError(normaliseAuthError(error.message));
return;
}
history.replace('/home');
return;
}
const { data, error } = await supabase.auth.signUp({
email: email.trim(),
password,
});
setIsSubmitting(false);
if (error) {
showError(normaliseAuthError(error.message));
return;
}
if (data.session) {
history.replace('/home');
return;
}
showMessage('Account created! Check your email for a verification link.');
};
return (
<IonPage>
<IonHeader className="ion-no-border">
<IonToolbar>
<IonTitle>
{mode === 'login' ? 'Welcome back' : 'Create account'}
</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent className="ion-padding auth-page">
<div className="auth-card">
<h1>
{mode === 'login'
? 'Sign in to continue'
: 'Create your shopping account'}
</h1>
<p className="muted-text">
Save your orders, addresses, and track deliveries securely.
</p>
{errorMessage && (
<IonText color="danger">
<p>{errorMessage}</p>
</IonText>
)}
{message && (
<IonText color="success">
<p>{message}</p>
</IonText>
)}
<div className="auth-form">
<IonItem lines="none" className="auth-input-item">
<IonLabel position="stacked">Email</IonLabel>
<IonInput
value={email}
type="email"
onIonInput={(e) => setEmail(e.detail.value ?? '')}
/>
</IonItem>
<IonItem lines="none" className="auth-input-item">
<IonLabel position="stacked">Password</IonLabel>
<IonInput
value={password}
type="password"
onIonInput={(e) => setPassword(e.detail.value ?? '')}
/>
</IonItem>
<IonButton
expand="block"
onClick={handleSubmit}
disabled={isSubmitting}
>
{mode === 'login' ? 'Sign in' : 'Create account'}
</IonButton>
{mode === 'login' && (
<IonButton
fill="clear"
expand="block"
onClick={handleResendConfirmation}
disabled={isSubmitting}
>
Resend confirmation email
</IonButton>
)}
<IonButton
fill="clear"
expand="block"
onClick={() => setMode(mode === 'login' ? 'signup' : 'login')}
>
{mode === 'login'
? 'Need an account? Sign up'
: 'Already have an account? Sign in'}
</IonButton>
</div>
</div>
</IonContent>
</IonPage>
);
};
export default Auth;