Skip to content

Commit

Permalink
feat: clinical trial annotate pre (#6)
Browse files Browse the repository at this point in the history
* add annotate list of clinical trial tables

* add clinical trial table individual view in annotation

* fixing bug

* add more descriptions on annotation title

* make fdalabel annotation tables page looking nicer

* update fdalabel short format
  • Loading branch information
zcemycl authored Oct 4, 2024
1 parent 990d775 commit 46aff09
Show file tree
Hide file tree
Showing 12 changed files with 383 additions and 52 deletions.
2 changes: 2 additions & 0 deletions src/app/(auth)/profile/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default function Profile() {
async function setAnnotationRecord(id: number) {
const annotatedData = await fetchUnannotatedAETableByUserId(
id,
AnnotationCategoryEnum.ADVERSE_EFFECT_TABLE,
nPerPage * pageNAnnotate,
nPerPage,
true,
Expand Down Expand Up @@ -74,6 +75,7 @@ export default function Profile() {
setCountHistory(historyCount);
const numberAnnotated = await fetchUnannotatedAETableByUserIdCount(
id,
AnnotationCategoryEnum.ADVERSE_EFFECT_TABLE,
true,
);
setCountAnnotated(numberAnnotated);
Expand Down
18 changes: 11 additions & 7 deletions src/app/(service)/annotate/adverse_effect_table/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ import {
useAETableAnnotation,
useLoader,
} from "@/contexts";
import { IBaseTable, IUnAnnotatedAETable } from "@/types";
import {
AnnotationCategoryEnum,
IBaseTable,
IUnAnnotatedAETable,
} from "@/types";
import { useState, useEffect, useRef } from "react";
import { useRouter } from "next/navigation";
import { GoIcon } from "@/icons";
Expand All @@ -42,33 +46,33 @@ export default function Page() {
const [tableData, setTableData] = useState<IUnAnnotatedAETable[]>([]);
const [hoverIdx, setHoverIdx] = useState<number | null>(null);
const [nPerPage, _] = useState(10);
const [topN, setTopN] = useState(100);
const [topN, setTopN] = useState(0);
const refUnannotatedGroup = useRef(null);

useEffect(() => {
async function getData(
credentials: string,
userId: number,
tabName: AnnotationTypeEnum,
pageN: number,
) {
const res = await fetchUnannotatedAETableByUserId(
userId,
AnnotationCategoryEnum.ADVERSE_EFFECT_TABLE,
pageN * nPerPage,
nPerPage,
tabName === AnnotationTypeEnum.COMPLETE,
tabName === AnnotationTypeEnum.AI,
);
const count = await fetchUnannotatedAETableByUserIdCount(
userId,
AnnotationCategoryEnum.ADVERSE_EFFECT_TABLE,
tabName === AnnotationTypeEnum.COMPLETE,
tabName === AnnotationTypeEnum.AI,
);
if ("detail" in res) {
router.push("/logout");
return;
}
console.log(count);
setTopN(count);
setTableData(res);
}
Expand All @@ -78,7 +82,7 @@ export default function Page() {

console.log(credentials, isLoadingAuth, userId);
setIsLoading(true);
getData(credentials, userId as number, tabName, pageN);
getData(userId as number, tabName, pageN);
(refUnannotatedGroup.current as any).scrollTo({
top: 0,
behavior: "smooth",
Expand Down Expand Up @@ -110,7 +114,7 @@ export default function Page() {
<div className="sm:w-1/2 flex flex-col mt-8 w-screen px-1 pt-5 pb-5 space-y-2">
<div className="flex justify-between items-center">
<div className="flex justify-between items-center space-x-1">
<TypographyH2>Annotations</TypographyH2>
<TypographyH2>AE Table Annotations</TypographyH2>
<AnnotationTypeDropdown
queryType={tabName}
setQueryType={(q) => {
Expand Down Expand Up @@ -171,7 +175,7 @@ export default function Page() {
<Table
{...{
content: {
table: data.adverse_effect_table.content.table.slice(
table: data.adverse_effect_table!.content.table.slice(
0,
6,
),
Expand Down
180 changes: 180 additions & 0 deletions src/app/(service)/annotate/clinical_trial_table/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
"use client";

import {
Spinner,
TypographyH2,
Table,
ExpandableBtn,
PaginationBar,
} from "@/components";
import { AnnotationTypeEnum } from "@/constants";
import { ProtectedRoute, useAuth, useLoader } from "@/contexts";
import {
fetchUnannotatedAETableByUserId,
fetchUnannotatedAETableByUserIdCount,
} from "@/http/backend";
import { GoIcon } from "@/icons";
import {
AnnotationCategoryEnum,
IBaseTable,
IUnAnnotatedAETable,
} from "@/types";
import { useRouter } from "next/navigation";
import { useState, useEffect, useRef } from "react";

export default function Page() {
const router = useRouter();
const { userId, credentials, isLoadingAuth } = useAuth();
const { isLoading, setIsLoading } = useLoader();
const refUnannotatedGroup = useRef(null);
const [tableData, setTableData] = useState<IUnAnnotatedAETable[]>([]);

const [hoverIdx, setHoverIdx] = useState<number | null>(null);
const [nPerPage, _] = useState(10);
const [topN, setTopN] = useState(100);
const [pageN, setPageN] = useState(0);
const [tabName, setTabName] = useState(AnnotationTypeEnum.ONGOING);

useEffect(() => {
async function getData(
userId: number,
tabName: AnnotationTypeEnum,
pageN: number,
) {
const res = await fetchUnannotatedAETableByUserId(
userId,
AnnotationCategoryEnum.CLINICAL_TRIAL_TABLE,
pageN * nPerPage,
nPerPage,
tabName === AnnotationTypeEnum.COMPLETE,
tabName === AnnotationTypeEnum.AI,
);
const count = await fetchUnannotatedAETableByUserIdCount(
userId,
AnnotationCategoryEnum.CLINICAL_TRIAL_TABLE,
tabName === AnnotationTypeEnum.COMPLETE,
tabName === AnnotationTypeEnum.AI,
);
if ("detail" in res) {
router.push("/logout");
return;
}
setTopN(count);
setTableData(res);
}

if (isLoadingAuth) return;
if (credentials.length === 0) return;
if (!userId) return;
setIsLoading(true);
getData(userId as number, tabName, pageN);
(refUnannotatedGroup.current as any).scrollTo({
top: 0,
behavior: "smooth",
});
setHoverIdx(null);
setIsLoading(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [tabName, pageN, isLoadingAuth, userId]);

return (
<ProtectedRoute>
<section
className={`text-gray-400 bg-gray-900 body-font
h-[83vh] sm:h-[90vh] overflow-y-scroll
${isLoading || isLoadingAuth ? "animate-pulse" : ""}`}
ref={refUnannotatedGroup}
>
<div className="container px-2 py-24 mx-auto grid justify-items-center">
<div
role="status"
className={`absolute left-1/2 top-1/2 transition-opacity duration-700
-translate-x-1/2 -translate-y-1/2 ${isLoading || isLoadingAuth ? "opacity-1" : "opacity-0"}`}
>
<Spinner />
<span className="sr-only">Loading...</span>
</div>

<div className="sm:w-1/2 flex flex-col mt-8 w-screen px-1 pt-5 pb-5 space-y-2">
<div className="flex justify-between items-center">
<div className="flex justify-between items-center space-x-1">
<TypographyH2>CT Table Annotations</TypographyH2>
</div>
<button
onClick={() => {
router.back();
}}
className="bg-purple-700 rounded p-2
text-white hover:bg-purple-800"
>
Back
</button>
</div>
</div>
{tableData.map((data, idx) => {
return (
<ExpandableBtn
key={`${data.fdalabel.setid}-${data.idx}`}
refkey={`${data.fdalabel.setid}-${data.idx}`}
childrenLong={
<>
{data.fdalabel.indication
?.split(" ")
.splice(0, 20)
.join(" ")}{" "}
...
<Table
{...{
content: {
table: data.clinical_trial_table!.content.table.slice(
0,
6,
),
} as IBaseTable,
}}
/>
</>
}
hoverCondition={hoverIdx == idx}
onMouseOver={(e) => {
setHoverIdx(idx);
}}
onClick={(e) => {
e.preventDefault();
setIsLoading(true);
let redirectUrl = `/annotate/fdalabel/${data.fdalabel.setid}/clinical_trial_table/${data.idx}`;
if (tabName === AnnotationTypeEnum.AI) {
redirectUrl = `${redirectUrl}/ai`;
}
router.push(redirectUrl);
}}
>
<>
<p className="leading-relaxed w-full">
{data.fdalabel.tradename} [Table {data.idx}]
</p>
<div
className={`transition duration-300
${hoverIdx == idx ? "opacity-1 translate-x-0" : "opacity-0 -translate-x-1/2"}`}
>
<GoIcon />
</div>
</>
</ExpandableBtn>
);
})}
<div className="flex justify-center space-x-1 flex-wrap">
<PaginationBar
topN={topN}
pageN={pageN}
nPerPage={nPerPage}
setPageN={(i: number) => {
setPageN(i);
}}
/>
</div>
</div>
</section>
</ProtectedRoute>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ export default function Page({ params }: Readonly<PageProps>) {
// set table
useEffect(() => {
async function getData() {
const res = await fetchAETableByIds(params.table_id, params.id);
const res = await fetchAETableByIds(
params.table_id,
AnnotationCategoryEnum.ADVERSE_EFFECT_TABLE,
params.id,
);
setTableData(res);
const res_history = await fetchAnnotatedTableMapByNameIds(
res.id,
Expand Down Expand Up @@ -144,7 +148,7 @@ export default function Page({ params }: Readonly<PageProps>) {
<div className="sm:w-2/3 flex flex-col mt-8 w-screen p-10 space-y-2">
<div className="flex justify-between">
<h2 className="text-white text-lg mb-1 font-medium title-font">
Annotation (AI)
AE Table Annotation (AI)
</h2>
<button
onClick={() => router.back()}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,11 @@ export default function Page({ params }: Readonly<PageProps>) {
// set table
useEffect(() => {
async function getData() {
const res = await fetchAETableByIds(params.table_id, params.id);
const res = await fetchAETableByIds(
params.table_id,
AnnotationCategoryEnum.ADVERSE_EFFECT_TABLE,
params.id,
);
setTableData(res);
const res_history = await fetchAnnotatedTableMapByNameIds(
res.id,
Expand Down Expand Up @@ -150,7 +154,7 @@ export default function Page({ params }: Readonly<PageProps>) {
<div className="sm:w-2/3 flex flex-col mt-8 w-screen p-10 space-y-2">
<div className="flex justify-between">
<h2 className="text-white text-lg mb-1 font-medium title-font">
Annotation
AE Table Annotation
</h2>
<button
onClick={() => router.back()}
Expand Down
Loading

0 comments on commit 46aff09

Please sign in to comment.