fix(web): dashboard reminders card uses X/Y; hide /accounts duplicate H1

Dashboard:
* "Active reminders" card retitled to "Reminders" and now shows
  active / total in the same X / Y format as the Accounts card
  (mirroring 2 / 3 connected / total).

Accounts list:
* The page-level <h1>Accounts</h1> is now hidden on mobile (the top
  bar already shows it), matching the Dashboard pattern. The
  "Add Account" button still shows on every breakpoint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
yiekheng 2026-05-10 14:53:47 +08:00
parent f50a1fc0a7
commit f96eea8e93
3 changed files with 12 additions and 10 deletions

View File

@ -168,11 +168,11 @@ export default async function DashboardPage() {
href="/accounts"
/>
<StatCard
title="Active reminders"
value={stats.activeReminders}
title="Reminders"
value={`${stats.activeReminders} / ${stats.totalReminders}`}
icon={BellIcon}
description="Scheduled & running"
href="/reminders?filter=active"
description="Active / total"
href="/reminders"
/>
<StatCard
title="Recent runs"

View File

@ -30,8 +30,9 @@ interface AccountsListViewProps {
export function AccountsListView({ accounts }: AccountsListViewProps) {
return (
<div className="px-4 py-6 sm:px-6 sm:py-8 max-w-5xl mx-auto space-y-6">
<div className="flex items-center justify-between gap-4">
<h1 className="text-2xl font-semibold tracking-tight">Accounts</h1>
<div className="flex items-center justify-end sm:justify-between gap-4">
{/* Hidden on mobile — the top header already shows "Accounts". */}
<h1 className="hidden sm:block text-2xl font-semibold tracking-tight">Accounts</h1>
<Button asChild size="sm">
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
<Link href={"/accounts/new" as any}>

View File

@ -6,9 +6,9 @@ export async function getDashboardStats(operatorId: string) {
const accounts = await db.query.whatsappAccounts.findMany({
where: (a, { eq }) => eq(a.operatorId, operatorId),
});
const reminders = await db.query.reminders.findMany({
where: (_, { sql: s }) => s`status = 'active'`,
});
// All reminder rows so the dashboard can show active/total in one query.
// Status enum today is active / ended (paused will join in a later phase).
const allReminders = await db.query.reminders.findMany();
// LEFT JOIN so runs whose reminder has been deleted still appear. The
// ownership filter widens to: either the reminder still exists and the
// operator owns its account, OR the reminder is gone but the run row
@ -31,7 +31,8 @@ export async function getDashboardStats(operatorId: string) {
return {
connectedAccounts: accounts.filter((a) => a.status === "connected").length,
totalAccounts: accounts.length,
activeReminders: reminders.length,
activeReminders: allReminders.filter((r) => r.status === "active").length,
totalReminders: allReminders.length,
recentRuns: recentRuns.rows as Array<{
id: string;
status: string;