Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 352x 70x 5x 2x 1x | import { AdminBand } from "./AdminPageHead";
import { Field, Label } from "../ui/field";
import { Input } from "../ui/input";
import type { AdminUser } from "../../lib/api";
import { StatusBadge } from "../ui/status-badge";
import { formatDateTime } from "../../lib/utils";
interface UserInfoCardProps {
user: AdminUser;
onUpdateField: (field: keyof AdminUser, value: unknown) => void;
}
/** A read-only `.spec` row: a muted term, its value right-aligned. */
function Spec({ term, children }: { term: string; children: React.ReactNode }) {
return (
<div className="grid grid-cols-[8.5rem_minmax(0,1fr)] items-baseline gap-3 border-t border-border-default py-1.5 first:border-t-0">
<dt className="text-sm text-foreground-muted">{term}</dt>
<dd className="min-w-0 text-right text-sm text-foreground-default">
{children}
</dd>
</div>
);
}
export function UserInfoCard({ user, onUpdateField }: UserInfoCardProps) {
return (
<>
<section className="space-y-3">
<AdminBand title="User Information" />
<div className="space-y-4">
<Field controlId="user-name">
<Label>Name</Label>
<Input
id="user-name"
value={user.name}
onChange={(e) => onUpdateField("name", e.target.value)}
/>
</Field>
<Field controlId="user-email">
<Label>Email</Label>
<Input
id="user-email"
type="email"
value={user.email}
onChange={(e) => onUpdateField("email", e.target.value)}
/>
</Field>
<Field controlId="user-phone">
<Label>Phone Number</Label>
<Input
id="user-phone"
value={user.phoneNumber || ""}
onChange={(e) => onUpdateField("phoneNumber", e.target.value)}
placeholder="91XXXXXXXXXX"
/>
</Field>
</div>
</section>
<section className="space-y-3">
<AdminBand title="Info" />
{/* `.spec` rows, hairline-ruled: no box, no card title. */}
<dl>
<Spec term="User ID">
<span className="font-mono tabular-nums">{user.id}</span>
</Spec>
<Spec term="Status">
{user.banned ? (
<StatusBadge status="Banned" variant="error" />
) : (
<StatusBadge status="Active" variant="success" />
)}
</Spec>
{user.banned && user.banReason && (
<Spec term="Ban Reason">
<span className="text-error">{user.banReason}</span>
</Spec>
)}
<Spec term="Email Verified">
{/*
* A verification state is a printed code, not a coloured
* "Yes"/"No" — colour never travels alone.
*/}
{user.emailVerified ? (
<StatusBadge status="Verified" variant="success" />
) : (
<StatusBadge status="Unverified" variant="warning" />
)}
</Spec>
{/* `en-IN` from one place. */}
<Spec term="Created">
<span className="tabular-nums">
{formatDateTime(user.createdAt)}
</span>
</Spec>
<Spec term="Updated">
<span className="tabular-nums">
{formatDateTime(user.updatedAt)}
</span>
</Spec>
</dl>
</section>
</>
);
}
|