From dc76a1a7b6099d32350006743002e57223071678 Mon Sep 17 00:00:00 2001 From: Jacob Maynard Date: Sat, 18 Apr 2026 12:08:04 -0500 Subject: [PATCH 1/5] close out 481 --- .../checklist/ChecklistYjsWrapper.tsx | 42 ++---------- .../checklist/LocalChecklistView.tsx | 44 ++----------- packages/web/src/primitives/db.ts | 4 ++ .../checklists/useChecklistViewModel.ts | 64 +++++++++++++++++++ packages/web/src/stores/projectStore.ts | 4 +- 5 files changed, 82 insertions(+), 76 deletions(-) create mode 100644 packages/web/src/primitives/useProject/checklists/useChecklistViewModel.ts diff --git a/packages/web/src/components/checklist/ChecklistYjsWrapper.tsx b/packages/web/src/components/checklist/ChecklistYjsWrapper.tsx index a76de2770..906105cad 100644 --- a/packages/web/src/components/checklist/ChecklistYjsWrapper.tsx +++ b/packages/web/src/components/checklist/ChecklistYjsWrapper.tsx @@ -9,7 +9,7 @@ import { ChevronLeftIcon } from 'lucide-react'; import { ChecklistWithPdf } from '@/components/checklist/ChecklistWithPdf'; import { useProjectContext } from '@/components/project/ProjectContext'; import { connectionPool } from '@/project/ConnectionPool'; -import { useChecklistAnswers } from '@/primitives/useProject/checklists/useChecklistAnswers'; +import { useChecklistViewModel } from '@/primitives/useProject/checklists/useChecklistViewModel'; import { useProjectStore, selectConnectionPhase } from '@/stores/projectStore'; import { useAuthStore, selectUser } from '@/stores/authStore'; import { ACCESS_DENIED_ERRORS } from '@/constants/errors.js'; @@ -27,7 +27,6 @@ import { AlertDialogFooter, AlertDialogAction, } from '@/components/ui/alert-dialog'; -import { getChecklistTypeFromState, scoreChecklistOfType } from '@/checklist-registry/index'; import { ScoreTag } from '@/components/checklist/ScoreTag'; import { isAMSTAR2Complete } from '@/components/checklist/AMSTAR2Checklist/checklist.js'; import { isROBINSIComplete } from '@/components/checklist/ROBINSIChecklist/checklist'; @@ -97,15 +96,8 @@ export function ChecklistYjsWrapper({ projectId, studyId, checklistId }: Checkli } }, [connectionState.error, navigate]); - const currentStudy = useProjectStore(s => { - const studies = s.projects[projectId]?.studies || []; - return studies.find((st: any) => st.id === studyId) || null; - }); - - const currentChecklist = useMemo(() => { - if (!currentStudy) return null; - return currentStudy.checklists?.find((c: any) => c.id === checklistId) || null; - }, [currentStudy, checklistId]); + const { currentStudy, currentChecklist, checklistForUI, checklistType, currentScore } = + useChecklistViewModel(projectId, studyId, checklistId); const isReadOnly = currentChecklist?.status ? !isEditable(currentChecklist.status) : false; @@ -214,30 +206,6 @@ export function ChecklistYjsWrapper({ projectId, studyId, checklistId }: Checkli [orgId, projectId, studyId, studyPdfs, user?.id, addPdfToStudy], ); - const answers = useChecklistAnswers(projectId, studyId, checklistId); - - const checklistForUI = useMemo(() => { - if (!currentChecklist || !answers) return null; - return { - id: currentChecklist.id, - name: currentStudy?.name || 'Checklist', - reviewerName: '', - createdAt: currentChecklist.createdAt, - ...answers, - }; - }, [currentChecklist, currentStudy, answers]); - - const checklistType = useMemo(() => { - if (currentChecklist?.type) return currentChecklist.type; - if (checklistForUI) return getChecklistTypeFromState(checklistForUI); - return 'AMSTAR2'; - }, [currentChecklist, checklistForUI]); - - const currentScore = useMemo(() => { - if (!checklistForUI || !checklistType) return null; - return scoreChecklistOfType(checklistType, checklistForUI); - }, [checklistForUI, checklistType]); - const isChecklistValid = useMemo(() => { if (!checklistForUI) return false; if (checklistType === 'AMSTAR2') return isAMSTAR2Complete(checklistForUI as any); @@ -374,7 +342,7 @@ export function ChecklistYjsWrapper({ projectId, studyId, checklistId }: Checkli
- + {!isReadOnly ?