diff --git a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.strings.ts b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.strings.ts index ab0f020ba135..5a4b7ecb6bb6 100644 --- a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.strings.ts +++ b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.strings.ts @@ -51,4 +51,10 @@ export const strings = defineMessages({ description: 'Notaður sem texti á PDF takka til að sækja birtingarvottorð í ákærum.', }, + sentToPrisonAdmin: { + id: 'judicial.system.core:indictment_case_files_list.sent_to_prison_admin', + defaultMessage: 'Fullnusta', + description: + 'Notaður sem titill á fullnusta hluta á dómskjalaskjá í ákærum.', + }, }) diff --git a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx index b9646bc28671..752011aac971 100644 --- a/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx +++ b/apps/judicial-system/web/src/components/IndictmentCaseFilesList/IndictmentCaseFilesList.tsx @@ -1,4 +1,4 @@ -import { FC, useContext } from 'react' +import { FC, useContext, useMemo } from 'react' import { useIntl } from 'react-intl' import { AnimatePresence } from 'framer-motion' @@ -9,6 +9,7 @@ import { isCompletedCase, isDefenceUser, isDistrictCourtUser, + isPrisonAdminUser, isProsecutionUser, isPublicProsecutor, isPublicProsecutorUser, @@ -25,6 +26,7 @@ import { import { CaseFile, CaseFileCategory, + User, } from '@island.is/judicial-system-web/src/graphql/schema' import { TempCase as Case } from '@island.is/judicial-system-web/src/types' import { useFileList } from '@island.is/judicial-system-web/src/utils/hooks' @@ -45,6 +47,13 @@ interface RenderFilesProps { onOpenFile: (fileId: string) => void } +interface FileSection { + title: string + onOpenFile: (fileId: string) => void + files?: CaseFile[] + shouldRender?: boolean +} + export const RenderFiles: FC = ({ caseFiles, onOpenFile, @@ -65,6 +74,82 @@ export const RenderFiles: FC = ({ ) } +const FileSection: FC = (props: FileSection) => { + const { title, files, onOpenFile, shouldRender = true } = props + + if (!files?.length || !shouldRender) { + return null + } + + return ( + + + {title} + + + + ) +} + +const useFilteredCaseFiles = (caseFiles?: CaseFile[] | null) => { + return useMemo(() => { + const filterByCategories = ( + categories: CaseFileCategory | CaseFileCategory[], + ) => { + const categoryArray = Array.isArray(categories) + ? categories + : [categories] + + return ( + caseFiles?.filter( + (file) => file.category && categoryArray.includes(file.category), + ) ?? [] + ) + } + + return { + indictments: filterByCategories(CaseFileCategory.INDICTMENT), + criminalRecords: filterByCategories(CaseFileCategory.CRIMINAL_RECORD), + costBreakdowns: filterByCategories(CaseFileCategory.COST_BREAKDOWN), + others: filterByCategories(CaseFileCategory.CASE_FILE), + rulings: filterByCategories(CaseFileCategory.RULING), + courtRecords: filterByCategories(CaseFileCategory.COURT_RECORD), + criminalRecordUpdate: filterByCategories( + CaseFileCategory.CRIMINAL_RECORD_UPDATE, + ), + uploadedCaseFiles: filterByCategories([ + CaseFileCategory.PROSECUTOR_CASE_FILE, + CaseFileCategory.DEFENDANT_CASE_FILE, + ]), + civilClaims: filterByCategories(CaseFileCategory.CIVIL_CLAIM), + sentToPrisonAdminFiles: filterByCategories( + CaseFileCategory.SENT_TO_PRISON_ADMIN_FILE, + ), + } + }, [caseFiles]) +} + +const useFilePermissions = (workingCase: Case, user?: User) => { + return useMemo( + () => ({ + canViewCriminalRecordUpdate: + isDistrictCourtUser(user) || + isPublicProsecutor(user) || + isPublicProsecutorUser(user), + canViewCivilClaims: + Boolean(workingCase.hasCivilClaims) && + (isDistrictCourtUser(user) || + isProsecutionUser(user) || + isDefenceUser(user)), + canViewSentToPrisonAdminFiles: + isPrisonAdminUser(user) || isPublicProsecutorUser(user), + canViewRulings: + isDistrictCourtUser(user) || isCompletedCase(workingCase.state), + }), + [user, workingCase.hasCivilClaims, workingCase.state], + ) +} + const IndictmentCaseFilesList: FC = ({ workingCase, displayGeneratedPDFs = true, @@ -89,51 +174,19 @@ const IndictmentCaseFilesList: FC = ({ (defendant) => defendant.subpoenas && defendant.subpoenas.length > 0, ) - const cf = workingCase.caseFiles - - const indictments = cf?.filter( - (file) => file.category === CaseFileCategory.INDICTMENT, - ) - const criminalRecords = cf?.filter( - (file) => file.category === CaseFileCategory.CRIMINAL_RECORD, - ) - const costBreakdowns = cf?.filter( - (file) => file.category === CaseFileCategory.COST_BREAKDOWN, - ) - const others = cf?.filter( - (file) => file.category === CaseFileCategory.CASE_FILE, - ) - const rulings = cf?.filter( - (file) => file.category === CaseFileCategory.RULING, - ) - const courtRecords = cf?.filter( - (file) => file.category === CaseFileCategory.COURT_RECORD, - ) - const criminalRecordUpdate = cf?.filter( - (file) => file.category === CaseFileCategory.CRIMINAL_RECORD_UPDATE, - ) - const uploadedCaseFiles = cf?.filter( - (file) => - file.category === CaseFileCategory.PROSECUTOR_CASE_FILE || - file.category === CaseFileCategory.DEFENDANT_CASE_FILE, - ) - const civilClaims = cf?.filter( - (file) => file.category === CaseFileCategory.CIVIL_CLAIM, - ) + const filteredFiles = useFilteredCaseFiles(workingCase.caseFiles) + const permissions = useFilePermissions(workingCase, user) return ( <> {displayHeading && ( )} - {indictments && indictments.length > 0 && ( - - - {formatMessage(caseFiles.indictmentSection)} - - - - )} + {showTrafficViolationCaseFiles && displayGeneratedPDFs && ( @@ -150,42 +203,27 @@ const IndictmentCaseFilesList: FC = ({ )} - {criminalRecords && criminalRecords.length > 0 && ( - - - {formatMessage(caseFiles.criminalRecordSection)} - - - - )} - {criminalRecordUpdate && - criminalRecordUpdate.length > 0 && - (isDistrictCourtUser(user) || - isPublicProsecutor(user) || - isPublicProsecutorUser(user)) && ( - - - {formatMessage(caseFiles.criminalRecordUpdateSection)} - - - - )} - {costBreakdowns && costBreakdowns.length > 0 && ( - - - {formatMessage(caseFiles.costBreakdownSection)} - - - - )} - {others && others.length > 0 && ( - - - {formatMessage(caseFiles.otherDocumentsSection)} - - - - )} + + + + {displayGeneratedPDFs && ( @@ -207,34 +245,34 @@ const IndictmentCaseFilesList: FC = ({ ))} )} - {courtRecords?.length || rulings?.length ? ( + {filteredFiles.courtRecords?.length || filteredFiles.rulings?.length ? ( {formatMessage(strings.rulingAndCourtRecordsTitle)} - {courtRecords && courtRecords.length > 0 && ( - - )} - {(isDistrictCourtUser(user) || isCompletedCase(workingCase.state)) && - rulings && - rulings.length > 0 && ( - + {filteredFiles.courtRecords && + filteredFiles.courtRecords.length > 0 && ( + + )} + {permissions.canViewRulings && + filteredFiles.rulings && + filteredFiles.rulings.length > 0 && ( + )} ) : null} - {workingCase.hasCivilClaims && - civilClaims && - civilClaims.length > 0 && - (isDistrictCourtUser(user) || - isProsecutionUser(user) || - isDefenceUser(user)) && ( - - - {formatMessage(strings.civilClaimsTitle)} - - - - )} + {showSubpoenaPdf && ( @@ -273,14 +311,24 @@ const IndictmentCaseFilesList: FC = ({ )} )} - {uploadedCaseFiles && uploadedCaseFiles.length > 0 && ( - - - {formatMessage(strings.uploadedCaseFiles)} - - - - )} + {filteredFiles.uploadedCaseFiles && + filteredFiles.uploadedCaseFiles.length > 0 && ( + + + {formatMessage(strings.uploadedCaseFiles)} + + + + )} + {fileNotFound && } diff --git a/libs/judicial-system/types/src/lib/user.ts b/libs/judicial-system/types/src/lib/user.ts index 8c0dcb478e20..408c3136cebd 100644 --- a/libs/judicial-system/types/src/lib/user.ts +++ b/libs/judicial-system/types/src/lib/user.ts @@ -70,8 +70,8 @@ export const isPublicProsecutorUser = (user?: InstitutionUser): boolean => { return Boolean( user?.role && publicProsecutorRoles.includes(user.role) && - user?.institution?.type === InstitutionType.PROSECUTORS_OFFICE && - user?.institution?.id === '8f9e2f6d-6a00-4a5e-b39b-95fd110d762e', // TODO: Create a new institution type to avoid hardcoding + user.institution?.type === InstitutionType.PROSECUTORS_OFFICE && + user.institution?.id === '8f9e2f6d-6a00-4a5e-b39b-95fd110d762e', // TODO: Create a new institution type to avoid hardcoding ) } @@ -85,7 +85,7 @@ export const isDistrictCourtUser = (user?: InstitutionUser): boolean => { return Boolean( user?.role && districtCourtRoles.includes(user.role) && - user?.institution?.type === InstitutionType.DISTRICT_COURT, + user.institution?.type === InstitutionType.DISTRICT_COURT, ) } @@ -99,7 +99,7 @@ export const isCourtOfAppealsUser = (user?: InstitutionUser): boolean => { return Boolean( user?.role && courtOfAppealsRoles.includes(user.role) && - user?.institution?.type === InstitutionType.COURT_OF_APPEALS, + user.institution?.type === InstitutionType.COURT_OF_APPEALS, ) } @@ -109,14 +109,14 @@ export const isPrisonSystemUser = (user?: InstitutionUser): boolean => { return Boolean( user?.role && prisonSystemRoles.includes(user.role) && - (user?.institution?.type === InstitutionType.PRISON || - user?.institution?.type === InstitutionType.PRISON_ADMIN), + (user.institution?.type === InstitutionType.PRISON || + user.institution?.type === InstitutionType.PRISON_ADMIN), ) } -export const isPrisonAdminUser = (user: InstitutionUser): boolean => +export const isPrisonAdminUser = (user?: InstitutionUser): boolean => Boolean( - user.role && + user?.role && prisonSystemRoles.includes(user.role) && user.institution?.type === InstitutionType.PRISON_ADMIN, )