seperation of nearle admin

This commit is contained in:
2026-09-28 15:43:07 +05:30
parent 153f87b577
commit c9616edad9
7 changed files with 397 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ import {
Loader2,
Lock,
Mail,
Building2,
ShieldCheck,
Sparkles,
} from 'lucide-react';
@@ -17,6 +18,7 @@ import {
checkAccount,
MIN_PASSWORD_LENGTH,
PasswordSetupRequiredError,
WrongConsoleError,
setInitialPassword,
} from '@/auth/session';
@@ -41,6 +43,8 @@ export function LoginPage() {
const [password, setPassword] = useState('');
const [isPasswordVisible, setIsPasswordVisible] = useState(false);
const [error, setError] = useState<string | null>(null);
/* Separate from `error`: the wrong console is guidance, not a failure. */
const [notice, setNotice] = useState<string | null>(null);
const [isBusy, setIsBusy] = useState(false);
/**
@@ -143,6 +147,15 @@ export function LoginPage() {
setNewPassword('');
setConfirmPassword('');
setStep('setup');
} else if (cause instanceof WrongConsoleError) {
// Not a failure. The password was right and the account is fine — it
// belongs to the other console. Shown as guidance rather than as an
// error, because somebody told "sign-in failed" in red goes and resets a
// password that works. The field is cleared and the step returns to the
// email, since retyping the same password here will do the same thing.
setNotice(cause.message);
setPassword('');
setStep('email');
} else {
setError(cause instanceof Error ? cause.message : 'Sign-in failed');
}
@@ -234,6 +247,7 @@ export function LoginPage() {
password={password}
isPasswordVisible={isPasswordVisible}
error={error}
notice={notice}
isBusy={isBusy}
canSubmit={canSubmit}
onEmail={setEmail}
@@ -401,6 +415,8 @@ interface FormPanelProps {
password: string;
isPasswordVisible: boolean;
error: string | null;
/** The wrong-console sentence. Rendered beside `error`, never as one. */
notice: string | null;
isBusy: boolean;
canSubmit: boolean;
onEmail: (value: string) => void;
@@ -416,6 +432,7 @@ function FormPanel({
password,
isPasswordVisible,
error,
notice,
isBusy,
canSubmit,
onEmail,
@@ -508,6 +525,7 @@ function FormPanel({
something the system does not do. */}
<ErrorNote message={error} />
<ConsoleNote message={notice} />
<SubmitButton
canSubmit={canSubmit}
@@ -683,6 +701,9 @@ function SetupPanel({
: 'Passwords on this backend are stored as typed. Do not reuse one from elsewhere.'}
</Hint>
{/* No ConsoleNote here. The setup step is reached only by an account
that has never had a password — a branch login this console just
spawned — so it is the right console by construction. */}
<ErrorNote message={error} />
<SubmitButton
@@ -738,6 +759,41 @@ function ErrorNote({ message }: { message: string | null }) {
);
}
/**
* The right account at the wrong console.
*
* Deliberately not `ErrorNote`. Nothing failed: the password was correct and
* the account is in good standing — it simply belongs to the other site. Shown
* in red beside "Sign-in failed", it sends people to reset a password that
* works, or to ask an administrator to fix an account that is not broken.
*
* `role="status"` rather than `role="alert"` for the same reason: a screen
* reader should read this as information, not as something that went wrong.
*/
function ConsoleNote({ message }: { message: string | null }) {
if (!message) return null;
return (
<div
role="status"
style={{
display: 'flex',
alignItems: 'flex-start',
gap: 9,
padding: '11px 13px',
borderRadius: 12,
background: 'var(--color-surface-sunken, #F4F5F7)',
border: '1px solid var(--color-line, #E6E8EB)',
color: 'var(--color-ink-2, #52606D)',
fontSize: 13,
lineHeight: 1.55,
}}
>
<Building2 size={16} style={{ flex: 'none', marginTop: 1 }} />
{message}
</div>
);
}
function SubmitButton({
canSubmit,
isBusy,