diff --git a/apps/judicial-system/api/src/app/modules/case-list/models/caseList.model.ts b/apps/judicial-system/api/src/app/modules/case-list/models/caseList.model.ts index 6372ac2e17d2..b5bf4659ebcc 100644 --- a/apps/judicial-system/api/src/app/modules/case-list/models/caseList.model.ts +++ b/apps/judicial-system/api/src/app/modules/case-list/models/caseList.model.ts @@ -11,6 +11,7 @@ import { CourtSessionType, IndictmentCaseReviewDecision, IndictmentDecision, + PunishmentType, } from '@island.is/judicial-system/types' import { Defendant } from '../../defendant' @@ -142,4 +143,10 @@ export class CaseListEntry { @Field(() => String, { nullable: true }) readonly indictmentCompletedDate?: string + + // TEMP: Use with caution! This key will never be populated. + // It was added to bypass table component type checks for a required custom sort key + // until we have a resolution on how to handle multiple defendants in the case list + @Field(() => PunishmentType, { nullable: true }) + readonly defendantsPunishmentType?: PunishmentType } diff --git a/apps/judicial-system/web/messages/Core/tables.ts b/apps/judicial-system/web/messages/Core/tables.ts index b2b2500d65bb..c17703f0fbf6 100644 --- a/apps/judicial-system/web/messages/Core/tables.ts +++ b/apps/judicial-system/web/messages/Core/tables.ts @@ -113,6 +113,11 @@ export const tables = defineMessages({ defaultMessage: 'Dómstóll', description: 'Notaður sem titill fyrir dómstóll dálk í lista yfir mál.', }, + punishmentType: { + id: 'judicial.system.core:tables.punishment_type', + defaultMessage: 'Refsitegund', + description: 'Notaður sem titill fyrir refsitegund dálk í lista yfir mál.', + }, sentencingDate: { id: 'judicial.system.core:tables.sentencing_date', defaultMessage: 'Dómsuppkvaðning', diff --git a/apps/judicial-system/web/src/components/Table/Table.tsx b/apps/judicial-system/web/src/components/Table/Table.tsx index 8e572422391c..13e6a3cad088 100644 --- a/apps/judicial-system/web/src/components/Table/Table.tsx +++ b/apps/judicial-system/web/src/components/Table/Table.tsx @@ -180,6 +180,8 @@ const Table: FC = (props) => { switch (column) { case 'defendants': return entry.defendants?.[0]?.name ?? '' + case 'defendantsPunishmentType': + return entry.defendants?.[0]?.punishmentType ?? '' case 'courtCaseNumber': return courtAbbreviation ? `${courtAbbreviation}: ${entry.courtCaseNumber}` diff --git a/apps/judicial-system/web/src/components/Tags/CaseTag.strings.ts b/apps/judicial-system/web/src/components/Tags/CaseTag.strings.ts index 28f7807d82f3..0119c6c284ab 100644 --- a/apps/judicial-system/web/src/components/Tags/CaseTag.strings.ts +++ b/apps/judicial-system/web/src/components/Tags/CaseTag.strings.ts @@ -97,4 +97,29 @@ export const strings = defineMessages({ defaultMessage: 'Afturkallað', description: 'Notað fyrir "Afturkallað" tagg', }, + punishmentTypeImprisonment: { + id: 'judicial.system.core:case_tag.punishment_type_imprisonment', + defaultMessage: 'Óskb.', + description: 'Notað fyrir "Óskilorðsbundið" tagg', + }, + punishmentTypeProbation: { + id: 'judicial.system.core:case_tag.punishment_type_probation', + defaultMessage: 'Skb.', + description: 'Notað fyrir "Skilorðsbundið" tagg', + }, + punishmentTypeFine: { + id: 'judicial.system.core:case_tag.punishment_type_fine', + defaultMessage: 'Sekt', + description: 'Notað fyrir "Sekt" tagg', + }, + punishmentTypeIndictmentRulingDecisionFine: { + id: 'judicial.system.core:case_tag.punishment_type_indictment_ruling_decision_fine', + defaultMessage: 'VL', + description: 'Notað fyrir "Viðurlagaákvörðun" tagg', + }, + punishmentTypeSignedFineInvitation: { + id: 'judicial.system.core:case_tag.punishment_type_signed_fine_invitation', + defaultMessage: 'ÁS', + description: 'Notað fyrir "Áritað sektarboð" tagg', + }, }) diff --git a/apps/judicial-system/web/src/components/Tags/utils.ts b/apps/judicial-system/web/src/components/Tags/utils.ts index 1b047e13806a..51cc830a199e 100644 --- a/apps/judicial-system/web/src/components/Tags/utils.ts +++ b/apps/judicial-system/web/src/components/Tags/utils.ts @@ -2,6 +2,7 @@ import { TagVariant } from '@island.is/island-ui/core' import { isDistrictCourtUser, isPublicProsecutorUser, + PunishmentType, } from '@island.is/judicial-system/types' import { @@ -120,6 +121,37 @@ export const getIndictmentRulingDecisionTag = ( } } +export const getPunishmentTypeTag = ( + punishmentType?: PunishmentType | null, +): { + color: TagVariant + text: { id: string; defaultMessage: string; description: string } +} | null => { + if (!punishmentType) return null + + const getPunishmentTypeLabel = (punishmentType?: PunishmentType | null) => { + switch (punishmentType) { + case PunishmentType.IMPRISONMENT: + return strings.punishmentTypeImprisonment + case PunishmentType.PROBATION: + return strings.punishmentTypeProbation + case PunishmentType.FINE: + return strings.punishmentTypeFine + case PunishmentType.INDICTMENT_RULING_DECISION_FINE: + return strings.punishmentTypeIndictmentRulingDecisionFine + case PunishmentType.SIGNED_FINE_INVITATION: + return strings.punishmentTypeSignedFineInvitation + default: + return strings.unknown + } + } + + return { + color: 'red' as TagVariant, + text: getPunishmentTypeLabel(punishmentType), + } +} + export const getPrisonCaseStateTag = ( prisonCaseState: CaseState, ): { diff --git a/apps/judicial-system/web/src/routes/Shared/Cases/PrisonCases.tsx b/apps/judicial-system/web/src/routes/Shared/Cases/PrisonCases.tsx index 1e4046e8e11e..1c00c16dde09 100644 --- a/apps/judicial-system/web/src/routes/Shared/Cases/PrisonCases.tsx +++ b/apps/judicial-system/web/src/routes/Shared/Cases/PrisonCases.tsx @@ -32,13 +32,17 @@ import { getDurationDate, } from '@island.is/judicial-system-web/src/components/Table' import Table from '@island.is/judicial-system-web/src/components/Table/Table' -import { getPrisonCaseStateTag } from '@island.is/judicial-system-web/src/components/Tags/utils' +import { + getPrisonCaseStateTag, + getPunishmentTypeTag, +} from '@island.is/judicial-system-web/src/components/Tags/utils' import { CaseListEntry, CaseState, CaseType, InstitutionType, } from '@island.is/judicial-system-web/src/graphql/schema' +import { isNonEmptyArray } from '@island.is/judicial-system-web/src/utils/arrayHelpers' import { usePrisonCasesQuery } from './prisonCases.generated' import { cases as m } from './Cases.strings' @@ -183,6 +187,10 @@ export const PrisonCases: FC = () => { { title: formatMessage(tables.court), }, + { + title: formatMessage(tables.punishmentType), + sortable: { isSortable: true, key: 'defendantsPunishmentType' }, + }, { title: capitalize(formatMessage(tables.sentencingDate)), }, @@ -213,6 +221,20 @@ export const PrisonCases: FC = () => { { cell: (row) => , }, + { + cell: (row) => { + const punishmentType = isNonEmptyArray(row.defendants) + ? row.defendants[0].punishmentType + : undefined + const punishmentTypeTag = getPunishmentTypeTag(punishmentType) + return punishmentTypeTag ? ( + + ) : null + }, + }, { cell: (row) => ( diff --git a/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql b/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql index 0bcfe4933c95..b188cbfac1aa 100644 --- a/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql +++ b/apps/judicial-system/web/src/routes/Shared/Cases/cases.graphql @@ -28,8 +28,10 @@ query Cases { defenderChoice verdictViewDate isSentToPrisonAdmin + punishmentType openedByPrisonAdminDate } + defendantsPunishmentType courtDate isValidToDateInThePast initialRulingDate diff --git a/apps/judicial-system/web/src/routes/Shared/Cases/prisonCases.graphql b/apps/judicial-system/web/src/routes/Shared/Cases/prisonCases.graphql index 321f459f4a7c..98b6483bff99 100644 --- a/apps/judicial-system/web/src/routes/Shared/Cases/prisonCases.graphql +++ b/apps/judicial-system/web/src/routes/Shared/Cases/prisonCases.graphql @@ -26,6 +26,7 @@ query PrisonCases { name noNationalId defenderChoice + punishmentType openedByPrisonAdminDate } courtDate diff --git a/apps/judicial-system/web/src/utils/arrayHelpers.spec.ts b/apps/judicial-system/web/src/utils/arrayHelpers.spec.ts new file mode 100644 index 000000000000..fa49af5eefe5 --- /dev/null +++ b/apps/judicial-system/web/src/utils/arrayHelpers.spec.ts @@ -0,0 +1,45 @@ +import { isEmptyArray, isNonEmptyArray, isPresentArray } from './arrayHelpers' + +describe('arrayHelpers', () => { + describe('isPresentArray', () => { + const testCases = [ + { input: undefined, expected: false }, + { input: null, expected: false }, + { input: [], expected: true }, + { input: [1], expected: true }, + ] + testCases.forEach(({ input, expected }) => { + it(`should return ${expected} for input ${input}`, () => { + expect(isPresentArray(input)).toBe(expected) + }) + }) + }) + + describe('isEmptyArray', () => { + const testCases = [ + { input: undefined, expected: false }, + { input: null, expected: false }, + { input: [], expected: true }, + { input: [1], expected: false }, + ] + testCases.forEach(({ input, expected }) => { + it(`should return ${expected} for input ${input}`, () => { + expect(isEmptyArray(input)).toBe(expected) + }) + }) + }) + + describe('isNonEmptyArray', () => { + const testCases = [ + { input: undefined, expected: false }, + { input: null, expected: false }, + { input: [], expected: false }, + { input: [1], expected: true }, + ] + testCases.forEach(({ input, expected }) => { + it(`should return ${expected} for input ${input}`, () => { + expect(isNonEmptyArray(input)).toBe(expected) + }) + }) + }) +}) diff --git a/apps/judicial-system/web/src/utils/arrayHelpers.ts b/apps/judicial-system/web/src/utils/arrayHelpers.ts new file mode 100644 index 000000000000..8b2d62131b7b --- /dev/null +++ b/apps/judicial-system/web/src/utils/arrayHelpers.ts @@ -0,0 +1,8 @@ +export const isPresentArray = (arr: T[] | undefined | null): arr is T[] => + arr !== undefined && arr !== null && Array.isArray(arr) + +export const isEmptyArray = (arr: T[] | undefined | null): arr is T[] => + isPresentArray(arr) && arr?.length === 0 + +export const isNonEmptyArray = (arr: T[] | undefined | null): arr is T[] => + isPresentArray(arr) && arr.length > 0