Files
kottgard-production/docs/annotated/src/app/login/page.annotated.tsx
T

385 lines
20 KiB
TypeScript

/**
* ANNOTATED COPY — every line explained
* Source: src/app/login/page.tsx
* NOT used by the app — read this to learn how the real file works
*/
// Next.js: this file runs in the BROWSER (needs useState, onClick, localStorage, etc.)
'use client';
// (blank line — separates logical blocks for readability)
// Import React — core UI library (components, hooks, JSX)
import { useState } from 'react';
// Next.js Link — fast client-side navigation without full page reload
import Link from 'next/link';
// Next.js App Router hooks — useRouter, useParams, useSearchParams
import { useRouter } from 'next/navigation';
// Import project module (@/ alias = src/ folder in tsconfig)
import Button from '@/components/ui/Button';
// Import project module (@/ alias = src/ folder in tsconfig)
import { useAuthStore } from '@/store/auth';
// Import project module (@/ alias = src/ folder in tsconfig)
import { useTranslation } from '@/hooks/useTranslation';
// Import project module (@/ alias = src/ folder in tsconfig)
import { DEMO_EMAIL } from '@/lib/constants';
// (blank line — separates logical blocks for readability)
// Default export — main component/page Next.js or other files import
export default function LoginPage() {
// Next.js router — programmatic navigation (router.push)
const router = useRouter();
// Zustand selector — subscribe to slice of global store
const { login, register } = useAuthStore();
// Custom hook — returns t() translator and current locale
const { t } = useTranslation();
// React useState — local component state that triggers re-render on change
const [isRegister, setIsRegister] = useState(false);
// React useState — local component state that triggers re-render on change
const [error, setError] = useState('');
// React useState — local component state that triggers re-render on change
const [form, setForm] = useState({
// Property or array item — trailing comma allowed in TypeScript
name: '',
// Property or array item — trailing comma allowed in TypeScript
email: '',
// Property or array item — trailing comma allowed in TypeScript
password: '',
// Property or array item — trailing comma allowed in TypeScript
phone: '',
// Property or array item — trailing comma allowed in TypeScript
street: '',
// Property or array item — trailing comma allowed in TypeScript
city: '',
// Property or array item — trailing comma allowed in TypeScript
state: '',
// Property or array item — trailing comma allowed in TypeScript
zip: '',
// Closing brace — end of block (function, if, object, JSX)
});
// (blank line — separates logical blocks for readability)
// Line 28: const handleSubmit = (e: React.FormEvent) => {
const handleSubmit = (e: React.FormEvent) => {
// Line 29: e.preventDefault();
e.preventDefault();
// Line 30: setError('');
setError('');
// (blank line — separates logical blocks for readability)
// Conditional branch — different behavior based on runtime value
if (isRegister) {
// Line 33: const success = register({
const success = register({
// Property or array item — trailing comma allowed in TypeScript
name: form.name,
// Property or array item — trailing comma allowed in TypeScript
email: form.email,
// Property or array item — trailing comma allowed in TypeScript
password: form.password,
// Property or array item — trailing comma allowed in TypeScript
phone: form.phone,
// Line 38: address: {
address: {
// Property or array item — trailing comma allowed in TypeScript
street: form.street,
// Property or array item — trailing comma allowed in TypeScript
city: form.city,
// Property or array item — trailing comma allowed in TypeScript
state: form.state,
// Property or array item — trailing comma allowed in TypeScript
zip: form.zip,
// Closing brace — end of block (function, if, object, JSX)
},
// Closing brace — end of block (function, if, object, JSX)
});
// Conditional branch — different behavior based on runtime value
if (success) router.push('/account');
// Closing brace — end of block (function, if, object, JSX)
} else {
// Line 47: const success = login(form.email, form.password);
const success = login(form.email, form.password);
// Conditional branch — different behavior based on runtime value
if (success) {
// Line 49: router.push('/account');
router.push('/account');
// Closing brace — end of block (function, if, object, JSX)
} else {
// Line 51: setError(t('auth.invalidCredentials', { email: DEMO_EMAIL...
setError(t('auth.invalidCredentials', { email: DEMO_EMAIL }));
// Closing brace — end of block (function, if, object, JSX)
}
// Closing brace — end of block (function, if, object, JSX)
}
// Closing brace — end of block (function, if, object, JSX)
};
// (blank line — separates logical blocks for readability)
// Return JSX — describes UI tree React renders to the DOM
return (
// JSX element — HTML-like tag becomes React component in browser
<div className="flex min-h-[70vh] items-center justify-center bg-gray-50 px-4 py-12">
// JSX element — HTML-like tag becomes React component in browser
<div className="w-full max-w-md">
// JSX element — HTML-like tag becomes React component in browser
<div className="mb-8 text-center">
// JSX element — HTML-like tag becomes React component in browser
<div className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-full bg-brand-700">
// JSX element — HTML-like tag becomes React component in browser
<span className="font-display text-xl font-bold text-gold-400">
// Line 62: {t('site.initials')}
{t('site.initials')}
// JSX element — HTML-like tag becomes React component in browser
</span>
// JSX element — HTML-like tag becomes React component in browser
</div>
// JSX element — HTML-like tag becomes React component in browser
<h1 className="font-display text-2xl font-bold text-brand-900">
// Line 66: {isRegister ? t('auth.createAccount') : t('auth.welcomeBa...
{isRegister ? t('auth.createAccount') : t('auth.welcomeBack')}
// JSX element — HTML-like tag becomes React component in browser
</h1>
// JSX element — HTML-like tag becomes React component in browser
<p className="mt-1 text-sm text-gray-500">
// Line 69: {isRegister
{isRegister
// Line 70: ? t('auth.joinTagline', { name: t('site.name') })
? t('auth.joinTagline', { name: t('site.name') })
// Line 71: : t('auth.signInTagline', { name: t('site.name') })}
: t('auth.signInTagline', { name: t('site.name') })}
// JSX element — HTML-like tag becomes React component in browser
</p>
// JSX element — HTML-like tag becomes React component in browser
</div>
// (blank line — separates logical blocks for readability)
// JSX element — HTML-like tag becomes React component in browser
<div className="card-premium p-8">
// JSX element — HTML-like tag becomes React component in browser
<form onSubmit={handleSubmit} className="space-y-4">
// Line 77: {isRegister && (
{isRegister && (
// JSX element — HTML-like tag becomes React component in browser
<div>
// JSX element — HTML-like tag becomes React component in browser
<label className="label-text">{t('auth.fullName')}</label>
// JSX element — HTML-like tag becomes React component in browser
<input
// Line 81: required
required
// Tailwind CSS utility classes — styling (colors, spacing, layout)
className="input-field"
// Line 83: value={form.name}
value={form.name}
// Change handler — runs when input/select value changes
onChange={(e) => setForm({ ...form, name: e.target.value })}
// Line 85: />
/>
// JSX element — HTML-like tag becomes React component in browser
</div>
// Line 87: )}
)}
// (blank line — separates logical blocks for readability)
// JSX element — HTML-like tag becomes React component in browser
<div>
// JSX element — HTML-like tag becomes React component in browser
<label className="label-text">{t('auth.email')}</label>
// JSX element — HTML-like tag becomes React component in browser
<input
// Line 92: required
required
// Line 93: type="email"
type="email"
// Tailwind CSS utility classes — styling (colors, spacing, layout)
className="input-field"
// Line 95: value={form.email}
value={form.email}
// Change handler — runs when input/select value changes
onChange={(e) => setForm({ ...form, email: e.target.value })}
// Line 97: />
/>
// JSX element — HTML-like tag becomes React component in browser
</div>
// (blank line — separates logical blocks for readability)
// JSX element — HTML-like tag becomes React component in browser
<div>
// JSX element — HTML-like tag becomes React component in browser
<label className="label-text">{t('auth.password')}</label>
// JSX element — HTML-like tag becomes React component in browser
<input
// Line 103: required
required
// Line 104: type="password"
type="password"
// Tailwind CSS utility classes — styling (colors, spacing, layout)
className="input-field"
// Line 106: value={form.password}
value={form.password}
// Change handler — runs when input/select value changes
onChange={(e) => setForm({ ...form, password: e.target.value })}
// Line 108: />
/>
// JSX element — HTML-like tag becomes React component in browser
</div>
// (blank line — separates logical blocks for readability)
// Line 111: {isRegister && (
{isRegister && (
// React Fragment — group elements without extra wrapper DOM node
<>
// JSX element — HTML-like tag becomes React component in browser
<div>
// JSX element — HTML-like tag becomes React component in browser
<label className="label-text">{t('auth.phone')}</label>
// JSX element — HTML-like tag becomes React component in browser
<input
// Line 116: required
required
// Line 117: type="tel"
type="tel"
// Tailwind CSS utility classes — styling (colors, spacing, layout)
className="input-field"
// Line 119: value={form.phone}
value={form.phone}
// Change handler — runs when input/select value changes
onChange={(e) => setForm({ ...form, phone: e.target.value })}
// Line 121: />
/>
// JSX element — HTML-like tag becomes React component in browser
</div>
// JSX element — HTML-like tag becomes React component in browser
<div>
// JSX element — HTML-like tag becomes React component in browser
<label className="label-text">{t('auth.street')}</label>
// JSX element — HTML-like tag becomes React component in browser
<input
// Line 126: required
required
// Tailwind CSS utility classes — styling (colors, spacing, layout)
className="input-field"
// Line 128: value={form.street}
value={form.street}
// Change handler — runs when input/select value changes
onChange={(e) => setForm({ ...form, street: e.target.value })}
// Line 130: />
/>
// JSX element — HTML-like tag becomes React component in browser
</div>
// JSX element — HTML-like tag becomes React component in browser
<div className="grid grid-cols-2 gap-3">
// JSX element — HTML-like tag becomes React component in browser
<div>
// JSX element — HTML-like tag becomes React component in browser
<label className="label-text">{t('auth.city')}</label>
// JSX element — HTML-like tag becomes React component in browser
<input
// Line 136: required
required
// Tailwind CSS utility classes — styling (colors, spacing, layout)
className="input-field"
// Line 138: value={form.city}
value={form.city}
// Change handler — runs when input/select value changes
onChange={(e) => setForm({ ...form, city: e.target.value })}
// Line 140: />
/>
// JSX element — HTML-like tag becomes React component in browser
</div>
// JSX element — HTML-like tag becomes React component in browser
<div>
// JSX element — HTML-like tag becomes React component in browser
<label className="label-text">{t('auth.state')}</label>
// JSX element — HTML-like tag becomes React component in browser
<input
// Line 145: required
required
// Tailwind CSS utility classes — styling (colors, spacing, layout)
className="input-field"
// Line 147: value={form.state}
value={form.state}
// Change handler — runs when input/select value changes
onChange={(e) => setForm({ ...form, state: e.target.value })}
// Line 149: />
/>
// JSX element — HTML-like tag becomes React component in browser
</div>
// JSX element — HTML-like tag becomes React component in browser
</div>
// JSX element — HTML-like tag becomes React component in browser
<div>
// JSX element — HTML-like tag becomes React component in browser
<label className="label-text">{t('auth.zip')}</label>
// JSX element — HTML-like tag becomes React component in browser
<input
// Line 155: required
required
// Tailwind CSS utility classes — styling (colors, spacing, layout)
className="input-field"
// Line 157: value={form.zip}
value={form.zip}
// Change handler — runs when input/select value changes
onChange={(e) => setForm({ ...form, zip: e.target.value })}
// Line 159: />
/>
// JSX element — HTML-like tag becomes React component in browser
</div>
// JSX element — HTML-like tag becomes React component in browser
</>
// Line 162: )}
)}
// (blank line — separates logical blocks for readability)
// Line 164: {error && (
{error && (
// JSX element — HTML-like tag becomes React component in browser
<p className="rounded-lg bg-red-50 px-4 py-2 text-sm text-red-600">{error}</p>
// Line 166: )}
)}
// (blank line — separates logical blocks for readability)
// JSX element — HTML-like tag becomes React component in browser
<Button type="submit" variant="primary" size="lg" className="w-full">
// Line 169: {isRegister ? t('auth.register') : t('auth.signIn')}
{isRegister ? t('auth.register') : t('auth.signIn')}
// JSX element — HTML-like tag becomes React component in browser
</Button>
// JSX element — HTML-like tag becomes React component in browser
</form>
// (blank line — separates logical blocks for readability)
// JSX element — HTML-like tag becomes React component in browser
<div className="mt-6 text-center">
// JSX element — HTML-like tag becomes React component in browser
<button
// Click handler — runs when user clicks (must be client component)
onClick={() => {
// Line 176: setIsRegister(!isRegister);
setIsRegister(!isRegister);
// Line 177: setError('');
setError('');
// Closing brace — end of block (function, if, object, JSX)
}}
// Tailwind CSS utility classes — styling (colors, spacing, layout)
className="text-sm font-medium text-brand-600 hover:text-brand-800"
// Line 180: >
>
// Line 181: {isRegister ? t('auth.hasAccount') : t('auth.noAccount')}
{isRegister ? t('auth.hasAccount') : t('auth.noAccount')}
// JSX element — HTML-like tag becomes React component in browser
</button>
// JSX element — HTML-like tag becomes React component in browser
</div>
// (blank line — separates logical blocks for readability)
// Line 185: {!isRegister && (
{!isRegister && (
// JSX element — HTML-like tag becomes React component in browser
<div className="mt-4 rounded-lg bg-brand-50 px-4 py-3 text-center">
// JSX element — HTML-like tag becomes React component in browser
<p className="text-xs text-brand-700">
// Line 188: {t('auth.demo', { email: DEMO_EMAIL })}
{t('auth.demo', { email: DEMO_EMAIL })}
// JSX element — HTML-like tag becomes React component in browser
</p>
// JSX element — HTML-like tag becomes React component in browser
</div>
// Line 191: )}
)}
// JSX element — HTML-like tag becomes React component in browser
</div>
// JSX element — HTML-like tag becomes React component in browser
</div>
// JSX element — HTML-like tag becomes React component in browser
</div>
// Line 195: );
);
// Closing brace — end of block (function, if, object, JSX)
}