Skip to content

Commit 29469cd

Browse files
authored
Merge pull request #11 from Health-Informatics-UoN/feat/getarticledetails
Restructure api calls to match new index
2 parents 50bae32 + 17d7645 commit 29469cd

16 files changed

Lines changed: 515 additions & 270 deletions

app/api/concepts/route.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

app/api/notes/route.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

app/api/pmc/route.ts

Lines changed: 0 additions & 19 deletions
This file was deleted.

app/page.tsx

Lines changed: 36 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,35 @@
1-
"use client";
2-
3-
import { useEffect, useState } from "react";
4-
import ConceptList from "@/components/ConceptList";
5-
import NotesList from "@/components/NotesList";
6-
import { Note, Concept } from "@/types/OmopTables";
1+
import { Suspense } from "react";
2+
import { use } from "react";
3+
import ConceptsSection from "@/components/ConceptsSection";
4+
import NotesSection from "@/components/NotesSection";
75
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
8-
import {
9-
Select,
10-
SelectContent,
11-
SelectItem,
12-
SelectTrigger,
13-
SelectValue,
14-
} from "@/components/ui/select";
15-
16-
export default function Home() {
17-
const [concepts, setConcepts] = useState<Concept[]>([]);
18-
const [notes, setNotes] = useState<Note[]>([]);
19-
const [selectedConcept, setSelectedConcept] = useState<string | null>(null);
20-
const [domain, setDomain] = useState("All");
21-
const [conceptName, setConceptName] = useState<string | null>(null);
6+
import DomainSelect from "@/components/DomainSelect";
227

23-
// Filter concepts by domain
24-
useEffect(() => {
25-
fetch(`/api/concepts?domain=${domain}`)
26-
.then((res) => res.json())
27-
.then((data) => {
28-
if (Array.isArray(data)) {
29-
setConcepts(data);
30-
} else {
31-
console.error("Concepts is not an array:", data);
32-
setConcepts([]);
33-
}
34-
})
35-
.catch((err) => {
36-
console.error("Fetch error:", err);
37-
setConcepts([]);
38-
});
39-
}, [domain]);
40-
41-
const loadNotes = async (conceptId: string) => {
42-
setSelectedConcept(conceptId);
8+
export default function Page(props: {
9+
searchParams: Promise<{
10+
conceptId?: string;
11+
domain?: string;
12+
}>;
13+
}) {
14+
return (
15+
<Suspense fallback={<div>Loading page...</div>}>
16+
<PageContent {...props} />
17+
</Suspense>
18+
);
19+
}
4320

44-
const res = await fetch(`/api/notes?conceptId=${conceptId}`);
45-
const data = await res.json();
21+
function PageContent({
22+
searchParams,
23+
}: {
24+
searchParams: Promise<{
25+
conceptId?: string;
26+
domain?: string;
27+
}>;
28+
}) {
29+
const params = use(searchParams);
4630

47-
setNotes(data.notes);
48-
setConceptName(data.conceptName);
49-
};
31+
const conceptId = params.conceptId ?? null;
32+
const domain = params.domain ?? "All";
5033

5134
return (
5235
<div className="min-h-screen bg-muted/40 p-6">
@@ -64,34 +47,24 @@ export default function Home() {
6447

6548
<CardContent>
6649
<div className="flex items-center gap-4">
67-
<span className="text-lg font-medium">Domain</span>
68-
69-
<Select value={domain} onValueChange={setDomain}>
70-
<SelectTrigger className="w-[200px]">
71-
<SelectValue placeholder="Select domain" />
72-
</SelectTrigger>
50+
<span className="text-lg font-medium ">Domain</span>
7351

74-
<SelectContent>
75-
<SelectItem value="All">All</SelectItem>
76-
<SelectItem value="Condition">Condition</SelectItem>
77-
<SelectItem value="Drug">Drug</SelectItem>
78-
</SelectContent>
79-
</Select>
52+
<DomainSelect domain={domain} />
8053
</div>
8154
</CardContent>
8255
</Card>
8356

8457
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
8558
<Card className="p-0 md:col-span-1">
86-
<ConceptList concepts={concepts} onSelect={loadNotes} />
59+
<Suspense fallback={<div>Loading concepts...</div>}>
60+
<ConceptsSection domain={domain} />
61+
</Suspense>
8762
</Card>
8863

8964
<Card className="p-0 md:col-span-2">
90-
<NotesList
91-
notes={notes}
92-
conceptId={selectedConcept}
93-
conceptName={conceptName}
94-
/>
65+
<Suspense fallback={<div>Loading notes...</div>}>
66+
<NotesSection conceptId={conceptId} />
67+
</Suspense>
9568
</Card>
9669
</div>
9770
</div>

components/ConceptList.tsx

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,42 @@
1-
import { Concept } from '@/types/OmopTables';
1+
"use client";
2+
import { useRouter, useSearchParams } from "next/navigation";
3+
import type { Concept } from "@/types/OmopTables";
24
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
35
import { Button } from "@/components/ui/button";
6+
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
7+
8+
export default function ConceptList({ concepts }: { concepts: Concept[] }) {
9+
const router = useRouter();
10+
const searchParams = useSearchParams();
11+
12+
const onSelect = (conceptId: string) => {
13+
const params = new URLSearchParams(searchParams.toString());
14+
params.set("conceptId", conceptId);
15+
router.push(`/?${params.toString()}`);
16+
};
417

5-
export default function ConceptList({
6-
concepts,
7-
onSelect
8-
}: {
9-
concepts: Concept[];
10-
onSelect: (id: string) => void;
11-
}) {
1218
return (
1319
<Card className="w-full">
1420
<CardHeader>
15-
<CardTitle className='text-2xl'>Common Search Terms</CardTitle>
21+
<CardTitle className="text-2xl">Common Search Terms</CardTitle>
1622
</CardHeader>
17-
18-
<CardContent>
19-
<div className="space-y-2">
20-
{concepts.map((c) => (
21-
<Button
22-
key={c.concept_id}
23-
variant="ghost"
24-
className="w-full justify-between h-auto py-3 px-4"
25-
onClick={() => onSelect(c.concept_id)}
26-
>
27-
<span className="text-lg">{c.name}</span>
28-
</Button>
29-
))}
30-
</div>
31-
</CardContent>
23+
<ScrollArea className="h-400">
24+
<CardContent>
25+
<div className="space-y-2">
26+
{concepts.map((c) => (
27+
<Button
28+
key={c.concept_id}
29+
variant="ghost"
30+
className="w-full justify-between h-auto py-3 px-4"
31+
onClick={() => onSelect(c.concept_id)}
32+
>
33+
<span className="text-lg">{c.name}</span>
34+
</Button>
35+
))}
36+
</div>
37+
</CardContent>
38+
<ScrollBar className=" w-3" />
39+
</ScrollArea>
3240
</Card>
3341
);
34-
}
42+
}

components/ConceptsSection.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import ConceptList from "./ConceptList";
2+
import { getConcepts } from "@/lib/services/conceptsService";
3+
import type { Concept } from "@/types/OmopTables";
4+
5+
export default async function ConceptsSection({ domain }: { domain: string }) {
6+
const concepts: Concept[] = await getConcepts(domain);
7+
8+
return <ConceptList concepts={concepts} />;
9+
}

components/DomainSelect.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"use client";
2+
import { useRouter, useSearchParams } from "next/navigation";
3+
import {
4+
Select,
5+
SelectContent,
6+
SelectItem,
7+
SelectTrigger,
8+
SelectValue,
9+
} from "@/components/ui/select";
10+
11+
export default function DomainSelect({ domain }: { domain: string }) {
12+
const router = useRouter();
13+
const searchParams = useSearchParams();
14+
function handleChange(value: string) {
15+
const params = new URLSearchParams(searchParams.toString());
16+
17+
if (value === "All") {
18+
params.delete("domain");
19+
} else {
20+
// Clear the conceptId if domain is changed
21+
params.delete("conceptId");
22+
params.set("domain", value);
23+
}
24+
router.push(`?${params.toString()}`);
25+
}
26+
return (
27+
<Select value={domain} onValueChange={handleChange}>
28+
<SelectTrigger className="w-50">
29+
<SelectValue placeholder="Select domain" />
30+
</SelectTrigger>
31+
32+
<SelectContent>
33+
<SelectItem value="All">All</SelectItem>
34+
<SelectItem value="Condition">Condition</SelectItem>
35+
<SelectItem value="Drug">Drug</SelectItem>
36+
<SelectItem value="Procedure">Procedure</SelectItem>
37+
<SelectItem value="Measurement">Measurement</SelectItem>
38+
</SelectContent>
39+
</Select>
40+
);
41+
}

0 commit comments

Comments
 (0)