Boring changes

This commit is contained in:
Andras Schmelczer 2026-07-12 15:10:26 +01:00
parent cfaf58dfba
commit 920119ff48
32 changed files with 912 additions and 88 deletions

View file

@ -2,6 +2,7 @@ import { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import pb from '../lib/pocketbase';
import { trackEvent } from '../lib/analytics';
import { resolveAuthError, type AuthErrorAction } from '../lib/auth-errors';
export interface AuthUser {
id: string;
@ -41,6 +42,7 @@ export function useAuth() {
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [errorAction, setErrorAction] = useState<AuthErrorAction>(null);
// Sync with authStore changes (cross-tab, external updates)
useEffect(() => {
@ -58,13 +60,15 @@ export function useAuth() {
async (email: string, password: string) => {
setLoading(true);
setError(null);
setErrorAction(null);
try {
const result = await pb.collection('users').authWithPassword(email, password);
setUser(recordToUser(result.record));
trackEvent('Login', { method: 'email' });
} catch (err) {
const msg = err instanceof Error ? err.message : t('auth.loginFailed');
setError(msg);
const { message, action } = resolveAuthError(err, 'login', t);
setError(message);
setErrorAction(action);
throw err;
} finally {
setLoading(false);
@ -77,21 +81,41 @@ export function useAuth() {
async (email: string, password: string) => {
setLoading(true);
setError(null);
setErrorAction(null);
try {
await pb.collection('users').create({
email,
password,
passwordConfirm: password,
newsletter: true,
});
// Auto-login after registration
const result = await pb.collection('users').authWithPassword(email, password);
setUser(recordToUser(result.record));
trackEvent('Register');
} catch (err) {
const msg = err instanceof Error ? err.message : t('auth.registrationFailed');
setError(msg);
throw err;
// Step 1: create the account. A failure here means nothing was created,
// so surface a friendly, field-aware message (e.g. "email already exists").
try {
await pb.collection('users').create({
email,
password,
passwordConfirm: password,
newsletter: true,
});
} catch (err) {
const { message, action } = resolveAuthError(err, 'register', t);
setError(message);
setErrorAction(action);
throw err;
}
// Step 2: the account now EXISTS. If auto-login fails (commonly a 429
// rate limit from the two back-to-back writes) the account is NOT
// orphaned: tell the user it was created and let them log in with the
// same credentials, instead of a misleading "registration failed".
try {
const result = await pb.collection('users').authWithPassword(email, password);
setUser(recordToUser(result.record));
trackEvent('Register');
} catch (err) {
const status = (err as { status?: number } | null)?.status;
setError(
status === 429
? t('auth.accountCreatedRateLimited')
: t('auth.accountCreatedPleaseLogIn')
);
setErrorAction('switchToLogin');
throw err;
}
} finally {
setLoading(false);
}
@ -103,6 +127,7 @@ export function useAuth() {
async (provider: string) => {
setLoading(true);
setError(null);
setErrorAction(null);
try {
const result = await pb.collection('users').authWithOAuth2({
provider,
@ -111,8 +136,9 @@ export function useAuth() {
setUser(recordToUser(result.record));
trackEvent('Login', { method: provider });
} catch (err) {
const msg = err instanceof Error ? err.message : t('auth.oauthFailed');
setError(msg);
const { message, action } = resolveAuthError(err, 'oauth', t);
setError(message);
setErrorAction(action);
throw err;
} finally {
setLoading(false);
@ -131,11 +157,13 @@ export function useAuth() {
async (email: string) => {
setLoading(true);
setError(null);
setErrorAction(null);
try {
await pb.collection('users').requestPasswordReset(email);
} catch (err) {
const msg = err instanceof Error ? err.message : t('auth.passwordResetFailed');
setError(msg);
const { message, action } = resolveAuthError(err, 'reset', t);
setError(message);
setErrorAction(action);
throw err;
} finally {
setLoading(false);
@ -167,12 +195,14 @@ export function useAuth() {
const clearError = useCallback(() => {
setError(null);
setErrorAction(null);
}, []);
return {
user,
loading,
error,
errorAction,
login,
register,
loginWithOAuth,