Harden login and refresh production deploy guide

This commit is contained in:
2026-05-17 05:52:09 +07:00
parent 9141f99f6a
commit 1274f2b822
5 changed files with 255 additions and 197 deletions

View File

@ -31,6 +31,9 @@ export async function AppShell({
<MobileNav pathname={pathname} userRole={user.role} />
<Topbar title={copy.title} description={copy.description} user={user} />
<div className="flex-1 p-6">{children}</div>
<footer className="border-t border-line/70 px-6 py-4 text-center text-sm text-slate-500">
© 2026 AbelBirdnest
</footer>
</div>
</main>
</div>

View File

@ -6,28 +6,20 @@ import { FormEvent, useState } from "react";
import { AppLogo } from "@/components/branding/app-logo";
import { useLocale } from "@/components/providers/locale-provider";
import { defaultAuthAccounts } from "@/features/auth/lib/default-accounts";
export function LoginClient() {
const { dict } = useLocale();
const router = useRouter();
const searchParams = useSearchParams();
const [identity, setIdentity] = useState("admin@abelbirdnest.local");
const [password, setPassword] = useState("admin123");
const [identity, setIdentity] = useState("");
const [password, setPassword] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [submitting, setSubmitting] = useState(false);
const [error, setError] = useState<string | null>(null);
const [helperEmail, setHelperEmail] = useState("admin@abelbirdnest.local");
const [helperEmail, setHelperEmail] = useState("");
const [helperSubmitting, setHelperSubmitting] = useState<"reset" | "verify" | null>(null);
const [helperMessage, setHelperMessage] = useState<string | null>(null);
function applyAccount(identityValue: string, passwordValue: string) {
setIdentity(identityValue);
setPassword(passwordValue);
setHelperEmail(identityValue);
setError(null);
}
async function submitHelper(type: "reset" | "verify") {
setHelperSubmitting(type);
setHelperMessage(null);
@ -246,31 +238,6 @@ export function LoginClient() {
<span>{dict.login.privacy}</span>
<span>{dict.login.terms}</span>
</div>
<div className="mt-8 rounded-lg border border-blue-200 bg-blue-50 px-4 py-4 text-left text-[13px] leading-6 text-slate-600">
<p className="font-semibold text-slate-700">{dict.login.devAccounts}</p>
<div className="mt-3 space-y-3">
{defaultAuthAccounts.map((account) => (
<button
key={account.roleCode}
type="button"
onClick={() => applyAccount(account.email, account.password)}
className="block w-full rounded-lg border border-blue-200 bg-white px-3 py-3 text-left transition hover:border-moss/40 hover:bg-moss/5"
>
<div className="flex items-center justify-between gap-3">
<span className="font-semibold text-ink">{account.roleLabel}</span>
<span className="text-[11px] font-bold uppercase tracking-[0.08em] text-slate-500">
{account.username}
</span>
</div>
<div className="mt-2 text-[12px] text-slate-600">{account.email}</div>
<div className="text-[12px] text-slate-600">Password: <span className="font-semibold text-ink">{account.password}</span></div>
</button>
))}
</div>
<p className="mt-3 text-[12px] text-slate-500">
{dict.login.autoFillHint}
</p>
</div>
</footer>
</div>
</section>
@ -278,7 +245,7 @@ export function LoginClient() {
<div className="pointer-events-none fixed bottom-0 left-0 flex w-full justify-between px-4 py-3 text-[11px] font-bold uppercase tracking-[0.08em] text-slate-400">
<span>v2.4.0-pro</span>
<span>© 2024 AbelBirdnest Stock</span>
<span>© 2026 AbelBirdnest</span>
</div>
</main>
);