11"use client" ;
2+
23import { Concept , Note } from "@/types/OmopTables" ;
34import { Button } from "@/components/ui/button" ;
45import {
@@ -15,26 +16,64 @@ import {
1516} from "@/components/ui/collapsible" ;
1617import { Badge } from "@/components/ui/badge" ;
1718import { ChevronDownIcon } from "@radix-ui/react-icons" ;
18- import Link from 'next/link'
19+ import Link from "next/link" ;
20+ import { usePathname , useRouter , useSearchParams } from "next/navigation" ;
21+ import { buildSearchParams } from "@/lib/helpers" ;
22+
1923export default function NoteCard ( {
2024 note,
2125 article,
2226} : {
2327 note : Note ;
2428 article : any ;
2529} ) {
26- const pmcid = note . note_source_value ?. match ( / P M C ( \d + ) / ) ?. [ 1 ] ;
30+ const router = useRouter ( ) ;
31+ const pathname = usePathname ( ) ;
32+ const searchParams = useSearchParams ( ) ;
2733
34+ const selectedConceptIds = searchParams . getAll ( "conceptId" ) ;
35+ const pmcid = note . note_source_value ?. match ( / P M C ( \d + ) / ) ?. [ 1 ] ;
2836 const uniqueConcepts = Array . from (
29- new Map ( ( note . concepts || [ ] ) . map ( ( c : any ) => [ c . concept_id , c ] ) ) . values ( ) ,
37+ new Map (
38+ ( note . concepts || [ ] ) . map ( ( c : any ) => [
39+ String ( c . concept_id ) ,
40+ {
41+ ...c ,
42+ concept_id : String ( c . concept_id ) ,
43+ } ,
44+ ] ) ,
45+ ) . values ( ) ,
3046 ) ;
3147
48+ const selectConcept = ( conceptId : string ) => {
49+ const existing = searchParams . getAll ( "conceptId" ) ;
50+
51+ const nextConceptIds = existing . includes ( conceptId )
52+ ? existing . filter ( ( id ) => id !== conceptId )
53+ : [ ...existing , conceptId ] ;
54+
55+ const query = buildSearchParams ( {
56+ conceptIds : nextConceptIds ,
57+ domain : searchParams . get ( "domain" ) ,
58+ page : 1 ,
59+ } ) ;
60+
61+ router . push ( `${ pathname } ?${ query } ` ) ;
62+ router . refresh ( ) ;
63+ } ;
64+
3265 return (
3366 < Card className = "bg-zinc-50 ring-foreground/15 dark:bg-neutral-800 mb-5" >
3467 < CardHeader >
3568 < CardTitle className = "text-lg" >
36- { article . articleUrl && pmcid ? (
37- < p > < Link href = { article . articleUrl } > { article . title } </ Link > </ p >
69+ { article ?. articleUrl && pmcid ? (
70+ < Link
71+ href = { article . articleUrl }
72+ target = "_blank"
73+ className = "hover:underline"
74+ >
75+ { article . title }
76+ </ Link >
3877 ) : (
3978 < p className = "text-sm text-gray-400" > Loading article...</ p >
4079 ) }
@@ -43,13 +82,14 @@ export default function NoteCard({
4382
4483 < CardContent className = "flex flex-wrap items-center gap-2 md:flex-row" >
4584 { article ? (
46- < Collapsible className = "rounded-md data-[state=open]:bg-muted" >
85+ < Collapsible className = "w-full rounded-md data-[state=open]:bg-muted" >
4786 < CollapsibleTrigger asChild >
48- < Button variant = "outline " className = "group w-full bg-transparent" >
87+ < Button variant = "ghost " className = "group w-full bg-transparent" >
4988 Description
50- < ChevronDownIcon className = "ml-auto group-data-[state=open]:rotate-180" />
89+ < ChevronDownIcon className = "ml-auto transition-transform group-data-[state=open]:rotate-180" />
5190 </ Button >
5291 </ CollapsibleTrigger >
92+
5393 < CollapsibleContent className = "flex flex-col items-start gap-2 p-2.5 pt-0 text-sm" >
5494 { article . description }
5595 </ CollapsibleContent >
@@ -61,20 +101,44 @@ export default function NoteCard({
61101
62102 < CardFooter className = "bg-neutral-50 border-t-gray-200 dark:bg-neutral-900 dark:border-t-neutral-600" >
63103 < div className = "flex flex-wrap gap-2" >
64- { uniqueConcepts . map ( ( c : Concept ) => (
65- < Badge
66- variant = { "secondary" }
67- key = { c . concept_id }
68- className = { `flex flex-wrap gap-2 text-sm py-0
69- ${ c . domain === "Condition" ? "bg-sky-100 dark:bg-[#1B3C53]" : "" }
70- ${ c . domain === "Drug" ? "bg-emerald-100 dark:bg-[#3F4F44]" : "" }
71- ${ c . domain === "Procedure" ? "bg-violet-100 dark:bg-[#49243E]" : "" }
72- ${ c . domain === "Measurement" ? "bg-orange-100 dark:bg-amber-800" : "" }
73- ` }
74- >
75- { c . name }
76- </ Badge >
77- ) ) }
104+ { uniqueConcepts . map ( ( c : Concept ) => {
105+ const selected = selectedConceptIds . includes ( String ( c . concept_id ) ) ;
106+
107+ return (
108+ < Badge
109+ key = { c . concept_id }
110+ variant = { "secondary" }
111+ onClick = { ( ) => selectConcept ( String ( c . concept_id ) ) }
112+ className = { `
113+ cursor-pointer transition hover:opacity-80
114+ flex flex-wrap gap-2 py-0 text-sm
115+ ${ selected ? "ring-2 ring-primary" : "" }
116+ ${
117+ c . domain === "Condition"
118+ ? "bg-sky-100 dark:bg-[#1B3C53]"
119+ : ""
120+ }
121+ ${
122+ c . domain === "Drug"
123+ ? "bg-emerald-100 dark:bg-[#3F4F44]"
124+ : ""
125+ }
126+ ${
127+ c . domain === "Procedure"
128+ ? "bg-violet-100 dark:bg-[#49243E]"
129+ : ""
130+ }
131+ ${
132+ c . domain === "Measurement"
133+ ? "bg-orange-100 dark:bg-amber-800"
134+ : ""
135+ }
136+ ` }
137+ >
138+ { c . name }
139+ </ Badge >
140+ ) ;
141+ } ) }
78142 </ div >
79143 </ CardFooter >
80144 </ Card >
0 commit comments