Skip to content

Commit e9da251

Browse files
committed
Add patient card
1 parent 53256e6 commit e9da251

File tree

11 files changed

+324
-109
lines changed

11 files changed

+324
-109
lines changed

aidbox-forms-smart-launch-2/src/app/patients/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ export default async function PatientsPage({ searchParams }: PageProps) {
150150
<TableCell>
151151
<div className="flex gap-2">
152152
<Button asChild variant="link" size="sm">
153-
<a href={`/patients/${patient?.id}/edit`}>
153+
<Link href={`/patients/${patient?.id}/edit`}>
154154
<Edit />
155-
</a>
155+
</Link>
156156
</Button>
157157
</div>
158158
</TableCell>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"use client";
2+
3+
import * as React from "react";
4+
import { LayoutDashboard, UserCog, Users } from "lucide-react";
5+
import { usePathname } from "next/navigation";
6+
import { cn } from "@/lib/utils";
7+
8+
import {
9+
SidebarMenu,
10+
SidebarMenuButton,
11+
SidebarMenuItem,
12+
} from "@/components/ui/sidebar";
13+
import Link from "next/link";
14+
15+
const data = {
16+
navMain: [
17+
{
18+
title: "Dashboard",
19+
href: "/",
20+
icon: LayoutDashboard,
21+
},
22+
{
23+
title: "Patients",
24+
href: "/patients",
25+
icon: Users,
26+
},
27+
{
28+
title: "Practitioners",
29+
href: "/practitioners",
30+
icon: UserCog,
31+
},
32+
],
33+
};
34+
35+
export function AppMenu() {
36+
const pathname = usePathname();
37+
38+
return (
39+
<SidebarMenu>
40+
{data.navMain.map((item) => (
41+
<SidebarMenuItem key={item.title}>
42+
<SidebarMenuButton
43+
asChild
44+
className={cn(
45+
"flex items-center gap-3",
46+
pathname === item.href && "bg-accent text-accent-foreground",
47+
)}
48+
>
49+
<Link href={item.href} className="font-medium">
50+
<item.icon className="mr-2 h-4 w-4" />
51+
{item.title}
52+
</Link>
53+
</SidebarMenuButton>
54+
</SidebarMenuItem>
55+
))}
56+
</SidebarMenu>
57+
);
58+
}

aidbox-forms-smart-launch-2/src/components/app-sidebar.tsx

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
1-
"use client";
2-
31
import * as React from "react";
4-
import { LayoutDashboard, UserCog, Users } from "lucide-react";
5-
import { usePathname } from "next/navigation";
6-
import { cn } from "@/lib/utils";
72
import Image from "next/image";
83

94
import {
105
Sidebar,
116
SidebarContent,
7+
SidebarFooter,
128
SidebarGroup,
139
SidebarHeader,
1410
SidebarMenu,
@@ -17,30 +13,10 @@ import {
1713
SidebarRail,
1814
} from "@/components/ui/sidebar";
1915
import Link from "next/link";
20-
21-
const data = {
22-
navMain: [
23-
{
24-
title: "Dashboard",
25-
href: "/",
26-
icon: LayoutDashboard,
27-
},
28-
{
29-
title: "Patients",
30-
href: "/patients",
31-
icon: Users,
32-
},
33-
{
34-
title: "Practitioners",
35-
href: "/practitioners",
36-
icon: UserCog,
37-
},
38-
],
39-
};
16+
import { PatientCard } from "@/components/patient-card";
17+
import { AppMenu } from "@/components/app-menu";
4018

4119
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
42-
const pathname = usePathname();
43-
4420
return (
4521
<Sidebar {...props}>
4622
<SidebarHeader>
@@ -68,27 +44,12 @@ export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
6844
</SidebarHeader>
6945
<SidebarContent>
7046
<SidebarGroup>
71-
<SidebarMenu>
72-
{data.navMain.map((item) => (
73-
<SidebarMenuItem key={item.title}>
74-
<SidebarMenuButton
75-
asChild
76-
className={cn(
77-
"flex items-center gap-3",
78-
pathname === item.href &&
79-
"bg-accent text-accent-foreground",
80-
)}
81-
>
82-
<a href={item.href} className="font-medium">
83-
<item.icon className="mr-2 h-4 w-4" />
84-
{item.title}
85-
</a>
86-
</SidebarMenuButton>
87-
</SidebarMenuItem>
88-
))}
89-
</SidebarMenu>
47+
<AppMenu />
9048
</SidebarGroup>
9149
</SidebarContent>
50+
<SidebarFooter>
51+
<PatientCard />
52+
</SidebarFooter>
9253
<SidebarRail />
9354
</Sidebar>
9455
);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"use client";
2+
3+
import { Copy } from "lucide-react";
4+
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
5+
import * as React from "react";
6+
7+
export function CopyIdMenuItem({ id }: { id: string }) {
8+
return (
9+
<DropdownMenuItem onClick={() => navigator.clipboard.writeText(id)}>
10+
<Copy />
11+
Copy ID
12+
</DropdownMenuItem>
13+
);
14+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
2+
import * as React from "react";
3+
import { constructAddress, constructGender, constructName } from "@/lib/utils";
4+
import { UserAvatar } from "@/components/user-avatar";
5+
import { Button } from "@/components/ui/button";
6+
import { MoreHorizontal } from "lucide-react";
7+
import { getCurrentPatient, getCurrentUser } from "@/lib/smart";
8+
import {
9+
DropdownMenu,
10+
DropdownMenuContent,
11+
DropdownMenuTrigger,
12+
} from "@/components/ui/dropdown-menu";
13+
import { CopyIdMenuItem } from "@/components/copy-id-menu-item";
14+
15+
export async function PatientCard({}) {
16+
const patient = await getCurrentPatient();
17+
const user = await getCurrentUser();
18+
19+
if (!patient || user.resourceType === "Patient") {
20+
return undefined;
21+
}
22+
23+
const name = constructName(patient.name);
24+
const age = patient.birthDate
25+
? new Date().getFullYear() - new Date(patient.birthDate).getFullYear()
26+
: "unknown";
27+
const address = patient.address
28+
? constructAddress(patient.address)
29+
: "unknown";
30+
const gender = constructGender(patient.gender);
31+
32+
return (
33+
<Card className="mx-4 mb-4 shadow-none">
34+
<CardHeader className="px-4 space-y-0 py-2 border-b flex-row items-center">
35+
<CardTitle>Current Patient</CardTitle>
36+
37+
<DropdownMenu>
38+
<DropdownMenuTrigger asChild>
39+
<Button variant="ghost" className="h-8 w-8 ml-auto">
40+
<span className="sr-only">Open menu</span>
41+
<MoreHorizontal className="h-4 w-4" />
42+
</Button>
43+
</DropdownMenuTrigger>
44+
<DropdownMenuContent align="start">
45+
<CopyIdMenuItem id={patient.id as string} />
46+
</DropdownMenuContent>
47+
</DropdownMenu>
48+
</CardHeader>
49+
<CardContent className="px-4 py-3">
50+
<div className="flex items-start gap-3 mb-2">
51+
<UserAvatar user={patient} />
52+
<div className="flex flex-col text-sm">
53+
<div className=" font-medium">{name}</div>
54+
<div className="text-xs text-muted-foreground">
55+
{gender}, {age} years old
56+
</div>
57+
</div>
58+
</div>
59+
60+
<div className="text-xs text-muted-foreground">{address}</div>
61+
</CardContent>
62+
</Card>
63+
);
64+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import * as React from "react"
2+
3+
import { cn } from "@/lib/utils"
4+
5+
const Card = React.forwardRef<
6+
HTMLDivElement,
7+
React.HTMLAttributes<HTMLDivElement>
8+
>(({ className, ...props }, ref) => (
9+
<div
10+
ref={ref}
11+
className={cn(
12+
"rounded-xl border bg-card text-card-foreground shadow",
13+
className
14+
)}
15+
{...props}
16+
/>
17+
))
18+
Card.displayName = "Card"
19+
20+
const CardHeader = React.forwardRef<
21+
HTMLDivElement,
22+
React.HTMLAttributes<HTMLDivElement>
23+
>(({ className, ...props }, ref) => (
24+
<div
25+
ref={ref}
26+
className={cn("flex flex-col space-y-1.5 p-6", className)}
27+
{...props}
28+
/>
29+
))
30+
CardHeader.displayName = "CardHeader"
31+
32+
const CardTitle = React.forwardRef<
33+
HTMLDivElement,
34+
React.HTMLAttributes<HTMLDivElement>
35+
>(({ className, ...props }, ref) => (
36+
<div
37+
ref={ref}
38+
className={cn("font-semibold leading-none tracking-tight", className)}
39+
{...props}
40+
/>
41+
))
42+
CardTitle.displayName = "CardTitle"
43+
44+
const CardDescription = React.forwardRef<
45+
HTMLDivElement,
46+
React.HTMLAttributes<HTMLDivElement>
47+
>(({ className, ...props }, ref) => (
48+
<div
49+
ref={ref}
50+
className={cn("text-sm text-muted-foreground", className)}
51+
{...props}
52+
/>
53+
))
54+
CardDescription.displayName = "CardDescription"
55+
56+
const CardContent = React.forwardRef<
57+
HTMLDivElement,
58+
React.HTMLAttributes<HTMLDivElement>
59+
>(({ className, ...props }, ref) => (
60+
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
61+
))
62+
CardContent.displayName = "CardContent"
63+
64+
const CardFooter = React.forwardRef<
65+
HTMLDivElement,
66+
React.HTMLAttributes<HTMLDivElement>
67+
>(({ className, ...props }, ref) => (
68+
<div
69+
ref={ref}
70+
className={cn("flex items-center p-6 pt-0", className)}
71+
{...props}
72+
/>
73+
))
74+
CardFooter.displayName = "CardFooter"
75+
76+
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }

0 commit comments

Comments
 (0)