chore(polish): integrate toasts, reports paging, loading motion; login centring floor for short windows; load-more uses notifyError; round records
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3e0c615fd8
commit
da3ed2f3ab
+1
-1
@@ -580,7 +580,7 @@ Action results and errors never take page layout. They are toasts from `src/lib/
|
||||
|
||||
### Login consent and the legal pages (2026-09-30)
|
||||
|
||||
- **Login:** under the form, an unticked checkbox 「我已阅读并同意《用户协议》和《隐私政策》」 (`.auth-consent`, caption size, links underlined, open in a new tab). Sending a code or a password sign-in with the box unticked does nothing but mark the box (a `--color-danger` outline, `.auth-consent.is-attention`) and raise the error toast 「请先阅读并勾选同意,再继续。」; ticking clears the mark. The operators' admin login (password-only, `/admin`) has no box. The login page is a three-row grid (`1fr auto 1fr`): the card sits in the middle row, exactly centred, and the caption footer 用户协议 · 隐私政策 (plus the ICP number to beian.miit.gov.cn once configured) takes the bottom row, so it never pushes the card up (BUG-1122). Below 768px the rows are `1fr auto` and the footer sits under the full-height card.
|
||||
- **Login:** under the form, an unticked checkbox 「我已阅读并同意《用户协议》和《隐私政策》」 (`.auth-consent`, caption size, links underlined, open in a new tab). Sending a code or a password sign-in with the box unticked does nothing but mark the box (a `--color-danger` outline, `.auth-consent.is-attention`) and raise the error toast 「请先阅读并勾选同意,再继续。」; ticking clears the mark. The operators' admin login (password-only, `/admin`) has no box. The login page is a three-row grid (`minmax(56px, 1fr) auto minmax(56px, 1fr)`, no vertical padding; the card's min-height is `min(680px, 100dvh - 128px)`): the card sits in the middle row, exactly centred, and the 56px floors keep the footer off the card on short windows, and the caption footer 用户协议 · 隐私政策 (plus the ICP number to beian.miit.gov.cn once configured) takes the bottom row, so it never pushes the card up (BUG-1122). Below 768px the rows are `1fr auto` and the footer sits under the full-height card.
|
||||
- **Account menu:** a caption row at the very bottom, 「用户协议 · 隐私政策」, below 退出登录.
|
||||
- **/terms and /privacy:** public, static, one 720px column on `--color-canvas-soft`; a top row with 「返回 Jyotisha」 and a link to the other document; while the text is a draft, a warning-tinted note 「草稿 · 版本 …,待律师审定」 above the title; h1 in the display face, h2 per section, bullet lists for enumerations.
|
||||
- **Re-consent:** when a final version replaces the one a signed-in user accepted, one modal 「协议已更新」 with the same checkbox and 「同意并继续」; it cannot be dismissed without agreeing. Off while the documents are a draft.
|
||||
|
||||
@@ -2083,10 +2083,10 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
|
||||
|
||||
/* Three rows so the legal footer sits at the bottom without pushing the card up
|
||||
(BUG-1122): the card is centred in the viewport, the footer takes the last row. */
|
||||
.auth-page { display: grid; grid-template-rows: minmax(0, 1fr) auto minmax(0, 1fr); justify-items: center; padding: var(--space-8) var(--space-8) 0; background: var(--color-canvas-soft); }
|
||||
.auth-page { display: grid; grid-template-rows: minmax(56px, 1fr) auto minmax(56px, 1fr); justify-items: center; padding: 0 var(--space-8); background: var(--color-canvas-soft); }
|
||||
.auth-page > .auth-shell { grid-row: 2; }
|
||||
.auth-page > .auth-legal-footer { grid-row: 3; align-self: end; }
|
||||
.auth-shell { width: min(1040px, 100%); min-height: min(680px, calc(100dvh - 64px)); display: grid; grid-template-columns: 1.08fr .92fr; overflow: hidden; border-radius: var(--radius-xl); background: var(--color-canvas); box-shadow: var(--shadow-elevated); }
|
||||
.auth-shell { width: min(1040px, 100%); min-height: min(680px, calc(100dvh - 128px)); display: grid; grid-template-columns: 1.08fr .92fr; overflow: hidden; border-radius: var(--radius-xl); background: var(--color-canvas); box-shadow: var(--shadow-elevated); }
|
||||
.auth-story { display: flex; flex-direction: column; justify-content: space-between; padding: var(--space-12); border-right: 1px solid var(--color-border); background: var(--color-canvas-muted); color: var(--color-ink); }
|
||||
.auth-story-brand, .auth-brand { display: flex; align-items: center; gap: var(--space-3); font-family: var(--font-display); font-size: var(--type-title-lg); }
|
||||
.auth-story-brand strong, .auth-brand strong { font-weight: 400; }
|
||||
|
||||
@@ -4,7 +4,7 @@ import { AppLink } from "@/components/app-link";
|
||||
import { FileText, RefreshCw } from "lucide-react";
|
||||
import { InlineSpinner } from "@/components/inline-spinner";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import { notifyError } from "@/lib/notify";
|
||||
|
||||
import { SecondaryPageShell } from "@/components/secondary-page-shell";
|
||||
import { readCurrentSubjectScope, useCurrentSubjectScope, useCurrentSubjectReady } from "@/lib/current-subject";
|
||||
@@ -172,10 +172,10 @@ export function PersonalReportCenter() {
|
||||
const fresh = page.reports.filter(report => !deletedIds.current.has(report.id));
|
||||
setState(current => ({ ...current, reports: appendReportPage(current.reports, fresh), nextCursor: page.nextCursor, extended: true }));
|
||||
} else {
|
||||
toast.error("更早的报告没读出来,再试一次。");
|
||||
notifyError("更早的报告没读出来,再试一次。", { id: "reports-load-more" });
|
||||
}
|
||||
} catch {
|
||||
if (!cancelled.current) toast.error("更早的报告没读出来,再试一次。");
|
||||
if (!cancelled.current) notifyError("更早的报告没读出来,再试一次。", { id: "reports-load-more" });
|
||||
} finally {
|
||||
if (!cancelled.current) setLoadingMore(false);
|
||||
}
|
||||
|
||||
@@ -141,7 +141,11 @@ test("production refuses placeholder operator details", () => {
|
||||
test("the login card stays centred; the legal footer takes its own bottom row (BUG-1122)", () => {
|
||||
const styles = read("../src/app/globals.css");
|
||||
const page = cssDeclarations(".auth-page", styles);
|
||||
assert.match(page, /grid-template-rows:\s*minmax\(0, 1fr\) auto minmax\(0, 1fr\)/);
|
||||
// Equal rows with room for the footer: a 0 minimum let the footer ride up over
|
||||
// the card on windows 760px tall or less (seen in Chromium during acceptance).
|
||||
assert.match(page, /grid-template-rows:\s*minmax\(56px, 1fr\) auto minmax\(56px, 1fr\)/);
|
||||
assert.match(page, /padding:\s*0 var\(--space-8\)/, "no top-only padding: the card sits in the exact middle");
|
||||
assert.match(cssDeclarations(".auth-shell", styles), /min-height:\s*min\(680px, calc\(100dvh - 128px\)\)/);
|
||||
assert.match(page, /grid-template-rows:\s*minmax\(0, 1fr\) auto;/, "phones: card row then footer row");
|
||||
assert.doesNotMatch(page, /place-items:\s*center/, "a single centred group is what pushed the card up");
|
||||
assert.match(cssDeclarations(".auth-page > .auth-shell", styles), /grid-row:\s*2/);
|
||||
|
||||
Reference in New Issue
Block a user