Harden login and refresh production deploy guide
This commit is contained in:
@ -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>
|
||||
|
||||
@ -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>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user