authentication and calendar-sync passwords keyed (214 -> 163)

Authentication reaches zero -- sign-in, bootstrap, forgot and reset password. These
are the first words a new account reads, which is why the brief ranked them above
the larger screens.

DavAppPasswords had the third toLocaleDateString(undefined, ...) in the shell; it now
uses useFormat().date like the other two.

DebugPanel's three labels are keyed too. Worth knowing rather than acting on: that
panel is rendered behind showDebug, which Background.tsx hardcodes to false, so it
never appears. Keyed rather than deleted because removing it is not my call.
This commit is contained in:
2026-08-23 05:15:22 +00:00
parent 7f8455f1af
commit b978e09327
9 changed files with 189 additions and 63 deletions
@@ -8,12 +8,14 @@ import { toast } from 'sonner';
import { useForm } from 'hooks/useForm';
import { useAuth } from 'hooks/useAuth';
import { useGlobal } from 'hooks/useGlobal';
import { useTranslation } from '@/lib/i18n';
const initialState: LoginFormState = {
// email: 'pastilhas@pastilhas.dev',
// password: '',
};
export function Login() {
const { t } = useTranslation();
const [isSubmitting, setIsSubmitting] = useState(false);
const { state, formRef, update, isValid } = useForm<LoginFormState>(initialState, validateForm);
const { signin } = useAuth();
@@ -40,20 +42,20 @@ export function Login() {
return (
<Card className="md:py-6 md:px-24 md:min-w-[480px] flex flex-col gap-6">
<div className="text-center">
<div className="text-duck-dark text-2xl font-bold">Welcome Back</div>
<div className="text-duck-dark/60">Sign in to your account</div>
<div className="text-duck-dark text-2xl font-bold">{t('auth.signInTitle')}</div>
<div className="text-duck-dark/60">{t('auth.signInSubtitle')}</div>
</div>
<form ref={formRef} onSubmit={handleSubmit} className="grid gap-4">
<Label className="grid gap-2">
<span className="text-duck-dark/70">Email or username</span>
<span className="text-duck-dark/70">{t('auth.emailOrUsername')}</span>
<Input
className="h-11 bg-background/60 border-duck-dark/20 text-duck-dark placeholder:text-duck-dark/40"
// `text`, not `email`: the browser refuses to submit a username under type="email", so the
// field would have validated the user out of an account they have.
type="text"
name="email"
placeholder="you@example.com"
placeholder={t('auth.emailPlaceholder')}
// `username` rather than `email`, which is what password managers expect for a field that
// takes either — and it is the value they already store beside the password.
autoComplete="username"
@@ -61,12 +63,12 @@ export function Login() {
</Label>
<Label className="grid gap-2">
<span className="text-duck-dark/70">Password</span>
<span className="text-duck-dark/70">{t('auth.password')}</span>
<Input
className="h-11 bg-background/60 border-duck-dark/20 text-duck-dark placeholder:text-duck-dark/40"
type="password"
name="password"
placeholder="Your password"
placeholder={t('auth.passwordPlaceholder')}
autoComplete="current-password"
/>
</Label>
@@ -90,7 +92,7 @@ export function Login() {
{/* </p> */}
<p>
<Link to="/auth/forgot-password" className="text-duck-forest underline hover:text-duck-forest/80">
Forgot password?
{t('auth.forgotPassword')}
</Link>
</p>
</div>