fix(web): forgot-password dialog, settings tagline, account dialog triggers
- Login page: replace static 'Forget Password? Contact IT' line with a proper dialog button. Clicking opens an explanatory dialog (self- service reset is intentionally disabled; admins can reset from /settings/users or run scripts/set-password.sh). - /settings: drop the 'cm WhatsApp Bot · self-hosted' tagline. - /accounts/[id]: Unpair + Delete cards weren't responding to clicks. Restructure so the transparent <button> overlay is a sibling of <Card> inside a <div className='relative'> wrapper (mirrors the working Pair/Re-pair pattern). The previous layout placed the DialogTrigger inside the Card, which produced no clickable button in the rendered DOM under radix-ui 1.4. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c493101b60
commit
5d583d9194
@ -156,26 +156,26 @@ export default async function AccountDetailPage({ params }: AccountDetailPagePro
|
||||
</Card>
|
||||
</Link>
|
||||
|
||||
{/* Unpair — transparent <button> overlay opens the dialog
|
||||
so we don't pass button-specific props onto the Card div
|
||||
(Radix asChild does that and it produces a hydration
|
||||
mismatch on a div). */}
|
||||
{/* Unpair — transparent <button> overlay (sibling of Card,
|
||||
inside a relative wrapper). Same pattern as Delete below. */}
|
||||
<Dialog>
|
||||
<Card className="relative transition-all hover:shadow-md hover:ring-amber-500/30 cursor-pointer">
|
||||
<CardContent className="flex items-center justify-between gap-4 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex size-9 items-center justify-center rounded-lg bg-amber-500/10">
|
||||
<PowerOffIcon className="size-4 text-amber-600 dark:text-amber-400" />
|
||||
<div className="relative">
|
||||
<Card className="transition-all hover:shadow-md hover:ring-amber-500/30 cursor-pointer">
|
||||
<CardContent className="flex items-center justify-between gap-4 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex size-9 items-center justify-center rounded-lg bg-amber-500/10">
|
||||
<PowerOffIcon className="size-4 text-amber-600 dark:text-amber-400" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium">Unpair</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Disconnect from WhatsApp; keep the account so you can re-pair later
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium">Unpair</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Disconnect from WhatsApp; keep the account so you can re-pair later
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<ChevronRightIcon className="size-4 text-muted-foreground/60" />
|
||||
</CardContent>
|
||||
<ChevronRightIcon className="size-4 text-muted-foreground/60" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<DialogTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
@ -183,7 +183,7 @@ export default async function AccountDetailPage({ params }: AccountDetailPagePro
|
||||
className="absolute inset-0 w-full rounded-xl bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||
/>
|
||||
</DialogTrigger>
|
||||
</Card>
|
||||
</div>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Unpair this account?</DialogTitle>
|
||||
@ -207,23 +207,31 @@ export default async function AccountDetailPage({ params }: AccountDetailPagePro
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Delete — transparent <button> overlay opens the dialog. */}
|
||||
{/* Delete — transparent <button> overlay opens the dialog.
|
||||
The button lives as a sibling of <Card> (inside a relative
|
||||
wrapper) instead of inside the Card. Radix's asChild-driven
|
||||
DialogTrigger stops emitting the underlying button when the
|
||||
wrapper Card adds an `absolute inset-0` sibling on the same
|
||||
stacking context, so we mirror the working pattern from the
|
||||
Pair/Re-pair card above. */}
|
||||
<Dialog>
|
||||
<Card className="relative transition-all hover:shadow-md hover:ring-destructive/30 cursor-pointer">
|
||||
<CardContent className="flex items-center justify-between gap-4 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex size-9 items-center justify-center rounded-lg bg-destructive/10">
|
||||
<Trash2Icon className="size-4 text-destructive" />
|
||||
<div className="relative">
|
||||
<Card className="transition-all hover:shadow-md hover:ring-destructive/30 cursor-pointer">
|
||||
<CardContent className="flex items-center justify-between gap-4 py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex size-9 items-center justify-center rounded-lg bg-destructive/10">
|
||||
<Trash2Icon className="size-4 text-destructive" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-destructive">Delete Account</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Remove the account and all its reminders, groups, and history
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm font-medium text-destructive">Delete Account</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Remove the account and all its reminders, groups, and history
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<ChevronRightIcon className="size-4 text-muted-foreground/60" />
|
||||
</CardContent>
|
||||
<ChevronRightIcon className="size-4 text-muted-foreground/60" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
<DialogTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
@ -231,7 +239,7 @@ export default async function AccountDetailPage({ params }: AccountDetailPagePro
|
||||
className="absolute inset-0 w-full rounded-xl bg-transparent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-destructive focus-visible:ring-offset-2"
|
||||
/>
|
||||
</DialogTrigger>
|
||||
</Card>
|
||||
</div>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Delete this account permanently?</DialogTitle>
|
||||
|
||||
@ -1,8 +1,18 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useTransition } from "react";
|
||||
import { Loader2Icon, LockIcon } from "lucide-react";
|
||||
import { Loader2Icon, LockIcon, HelpCircleIcon } from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
DialogClose,
|
||||
} from "@/components/ui/dialog";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { loginAction } from "@/actions/auth";
|
||||
@ -58,9 +68,41 @@ export function LoginFormClient({ next }: { next: string }) {
|
||||
)}
|
||||
Sign in
|
||||
</Button>
|
||||
<p className="text-xs text-muted-foreground text-center">
|
||||
Forget Password? Contact IT
|
||||
</p>
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
variant="link"
|
||||
size="sm"
|
||||
className="w-full text-xs text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<HelpCircleIcon className="size-3.5" />
|
||||
Forgot password?
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Forgot your password?</DialogTitle>
|
||||
<DialogDescription>
|
||||
Self-service password reset is intentionally disabled on
|
||||
this deployment. To recover access, contact an
|
||||
administrator. They can reset your password from
|
||||
Settings → Users, or run{" "}
|
||||
<code className="font-mono text-[0.75rem]">
|
||||
./scripts/set-password.sh <username>
|
||||
</code>{" "}
|
||||
from the tools container.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DialogFooter showCloseButton>
|
||||
<DialogClose asChild>
|
||||
<Button type="button" size="sm">
|
||||
Got it
|
||||
</Button>
|
||||
</DialogClose>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
@ -77,10 +77,6 @@ export default async function SettingsPage() {
|
||||
<ThemeToggle />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<p className="text-center text-xs text-muted-foreground">
|
||||
cm WhatsApp Bot · self-hosted
|
||||
</p>
|
||||
</PageShell>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user