Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(j-s): Allow prosecutor office to change the prosecutor decision #17355

Merged
merged 12 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ const prosecutorFields: (keyof UpdateCaseDto)[] = [
'hasCivilClaims',
]

const publicProsecutorFields: (keyof UpdateCaseDto)[] = ['indictmentReviewerId']
const publicProsecutorFields: (keyof UpdateCaseDto)[] = [
'indictmentReviewerId',
'indictmentReviewDecision',
]

const districtCourtFields: (keyof UpdateCaseDto)[] = [
'defenderName',
Expand Down
oddsson marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { Dispatch, SetStateAction, useContext, useMemo } from 'react'
import { useIntl } from 'react-intl'

import { Box, Option, Select, Text } from '@island.is/island-ui/core'
import { formatDate } from '@island.is/judicial-system/formatters'
import { CaseIndictmentRulingDecision } from '@island.is/judicial-system/types'
import {
BlueBox,
SectionHeading,
UserContext,
} from '@island.is/judicial-system-web/src/components'
import { useProsecutorSelectionUsersQuery } from '@island.is/judicial-system-web/src/components/ProsecutorSelection/prosecutorSelectionUsers.generated'
import { TempCase } from '@island.is/judicial-system-web/src/types'

import { strings } from './Overview.strings'

export const IndictmentReviewerSelector = ({
workingCase,
selectedIndictmentReviewer,
setSelectedIndictmentReviewer,
}: {
workingCase: TempCase
selectedIndictmentReviewer: Option<string> | null | undefined
setSelectedIndictmentReviewer: Dispatch<
SetStateAction<Option<string> | null | undefined>
>
}) => {
const { formatMessage: fm } = useIntl()

const { user } = useContext(UserContext)

const { data, loading } = useProsecutorSelectionUsersQuery({
fetchPolicy: 'no-cache',
errorPolicy: 'all',
})

const publicProsecutors = useMemo(() => {
if (!data?.users || !user) {
return []
}
return data.users.reduce(
(acc: { label: string; value: string }[], prosecutor) => {
if (prosecutor.institution?.id === user?.institution?.id) {
acc.push({
label: prosecutor.name ?? '',
value: prosecutor.id,
})
}
return acc
},
[],
)
}, [data?.users, user])

return (
<Box marginBottom={5}>
<SectionHeading
title={fm(strings.reviewerTitle)}
description={
<Text variant="eyebrow">
{fm(strings.reviewerSubtitle, {
isFine:
workingCase.indictmentRulingDecision ===
CaseIndictmentRulingDecision.FINE,
indictmentAppealDeadline: formatDate(
workingCase.indictmentAppealDeadline,
),
appealDeadlineIsInThePast:
workingCase.indictmentVerdictAppealDeadlineExpired,
})}
</Text>
}
/>
<BlueBox>
<Select
name="reviewer"
label={fm(strings.reviewerLabel)}
placeholder={fm(strings.reviewerPlaceholder)}
value={
selectedIndictmentReviewer
? selectedIndictmentReviewer
: workingCase.indictmentReviewer
? {
label: workingCase.indictmentReviewer.name || '',
value: workingCase.indictmentReviewer.id,
}
: undefined
}
options={publicProsecutors}
onChange={(value) => {
setSelectedIndictmentReviewer(value as Option<string>)
}}
isDisabled={loading}
required
/>
</BlueBox>
</Box>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,10 @@ export const strings = defineMessages({
'Máli {caseNumber} hefur verið úthlutað til yfirlestrar á {reviewer}.',
description: 'Notaður sem texti í tilkynningaglugga um yfirlesara.',
},
changeReviewedDecisionButtonText: {
id: 'judicial.system.core:public_prosecutor.indictments.overview.change_reviewed_decision_button_text',
defaultMessage: 'Breyta ákvörðun?',
thorhildurt marked this conversation as resolved.
Show resolved Hide resolved
description:
'Notaður sem texti fyrir staðfestingartakka þegar ákvörðun ríkissaksóknara er breytt.',
},
})
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useCallback, useContext, useMemo, useState } from 'react'
import { useCallback, useContext, useState } from 'react'
import { useIntl } from 'react-intl'
import { useRouter } from 'next/router'

import { Box, Option, Select, Text } from '@island.is/island-ui/core'
import { Box, Option } from '@island.is/island-ui/core'
import * as constants from '@island.is/judicial-system/consts'
import { formatDate } from '@island.is/judicial-system/formatters'
import {
CaseIndictmentRulingDecision,
IndictmentCaseReviewDecision,
} from '@island.is/judicial-system/types'
import { core, titles } from '@island.is/judicial-system-web/messages'
import {
BlueBox,
BlueBoxWithDate,
CourtCaseInfo,
FormContentContainer,
Expand All @@ -20,27 +22,34 @@ import {
PageHeader,
PageLayout,
PageTitle,
SectionHeading,
// useIndictmentsLawsBroken, NOTE: Temporarily hidden while list of laws broken is not complete
UserContext,
} from '@island.is/judicial-system-web/src/components'
import { useProsecutorSelectionUsersQuery } from '@island.is/judicial-system-web/src/components/ProsecutorSelection/prosecutorSelectionUsers.generated'
import { CaseIndictmentRulingDecision } from '@island.is/judicial-system-web/src/graphql/schema'
import { useCase } from '@island.is/judicial-system-web/src/utils/hooks'

import { ReviewDecision } from '../../components/ReviewDecision/ReviewDecision'
import {
CONFIRM_PROSECUTOR_DECISION,
ConfirmationModal,
isReviewerAssignedModal,
REVIEWER_ASSIGNED,
} from '../../components/utils'
import { IndictmentReviewerSelector } from './IndictmentReviewerSelector'
import { strings } from './Overview.strings'
type VisibleModal = 'REVIEWER_ASSIGNED'

export const Overview = () => {
const router = useRouter()
const { formatMessage: fm } = useIntl()
const { user } = useContext(UserContext)
const { updateCase } = useCase()
const { workingCase, isLoadingWorkingCase, caseNotFound } =
useContext(FormContext)
const [selectedIndictmentReviewer, setSelectedIndictmentReviewer] =
useState<Option<string> | null>()
const [modalVisible, setModalVisible] = useState<VisibleModal>()
const [isReviewedDecisionChanged, setIsReviewedDecisionChanged] =
useState<boolean>(false)

const [confirmationModal, setConfirmationModal] = useState<
ConfirmationModal | undefined
>()

// const lawsBroken = useIndictmentsLawsBroken(workingCase) NOTE: Temporarily hidden while list of laws broken is not complete

const assignReviewer = async () => {
Expand All @@ -54,37 +63,14 @@ export const Overview = () => {
return
}

setModalVisible('REVIEWER_ASSIGNED')
setConfirmationModal(REVIEWER_ASSIGNED)
}

const handleNavigationTo = useCallback(
(destination: string) => router.push(`${destination}/${workingCase.id}`),
[router, workingCase.id],
)

const { data, loading } = useProsecutorSelectionUsersQuery({
fetchPolicy: 'no-cache',
errorPolicy: 'all',
})

const publicProsecutors = useMemo(() => {
if (!data?.users || !user) {
return []
}
return data.users.reduce(
(acc: { label: string; value: string }[], prosecutor) => {
if (prosecutor.institution?.id === user?.institution?.id) {
acc.push({
label: prosecutor.name ?? '',
value: prosecutor.id,
})
}
return acc
},
[],
)
}, [data?.users, user])

return (
<PageLayout
workingCase={workingCase}
Expand Down Expand Up @@ -121,67 +107,64 @@ export const Overview = () => {
<Box component="section" marginBottom={5}>
<IndictmentCaseFilesList workingCase={workingCase} />
</Box>
{!workingCase.indictmentReviewDecision && (
<Box marginBottom={5}>
<SectionHeading
title={fm(strings.reviewerTitle)}
description={
<Text variant="eyebrow">
{fm(strings.reviewerSubtitle, {
isFine:
workingCase.indictmentRulingDecision ===
CaseIndictmentRulingDecision.FINE,
indictmentAppealDeadline: formatDate(
workingCase.indictmentAppealDeadline,
),
appealDeadlineIsInThePast:
workingCase.indictmentVerdictAppealDeadlineExpired,
})}
</Text>
}
/>
<BlueBox>
<Select
name="reviewer"
label={fm(strings.reviewerLabel)}
placeholder={fm(strings.reviewerPlaceholder)}
value={
selectedIndictmentReviewer
? selectedIndictmentReviewer
: workingCase.indictmentReviewer
? {
label: workingCase.indictmentReviewer.name || '',
value: workingCase.indictmentReviewer.id,
}
: undefined
}
options={publicProsecutors}
onChange={(value) => {
setSelectedIndictmentReviewer(value as Option<string>)
}}
isDisabled={loading}
required
/>
</BlueBox>
</Box>
{!workingCase.indictmentReviewDecision ? (
<IndictmentReviewerSelector
workingCase={workingCase}
selectedIndictmentReviewer={selectedIndictmentReviewer}
setSelectedIndictmentReviewer={setSelectedIndictmentReviewer}
/>
) : (
<ReviewDecision
caseId={workingCase.id}
currentDecision={workingCase.indictmentReviewDecision}
indictmentAppealDeadline={
workingCase.indictmentAppealDeadline ?? ''
}
indictmentAppealDeadlineIsInThePast={
workingCase.indictmentVerdictAppealDeadlineExpired ?? false
}
modalVisible={confirmationModal}
setModalVisible={setConfirmationModal}
isFine={
workingCase.indictmentRulingDecision ===
CaseIndictmentRulingDecision.FINE
}
onChange={(decision: IndictmentCaseReviewDecision) => {
const isDecisionChanged =
decision !== workingCase.indictmentReviewDecision
setIsReviewedDecisionChanged(isDecisionChanged)
}}
/>
)}
</FormContentContainer>
<FormContentContainer isFooter>
<FormFooter
nextButtonIcon="arrowForward"
previousUrl={constants.CASES_ROUTE}
nextIsLoading={isLoadingWorkingCase}
nextIsDisabled={
!selectedIndictmentReviewer ||
selectedIndictmentReviewer.value ===
workingCase.indictmentReviewer?.id ||
isLoadingWorkingCase
}
onNextButtonClick={assignReviewer}
nextButtonText={fm(core.continue)}
/>
{!workingCase.indictmentReviewDecision ? (
<FormFooter
nextButtonIcon="arrowForward"
previousUrl={constants.CASES_ROUTE}
nextIsLoading={isLoadingWorkingCase}
nextIsDisabled={
!selectedIndictmentReviewer ||
selectedIndictmentReviewer.value ===
workingCase.indictmentReviewer?.id ||
isLoadingWorkingCase
}
onNextButtonClick={assignReviewer}
nextButtonText={fm(core.continue)}
/>
) : (
<FormFooter
previousUrl={constants.CASES_ROUTE}
nextIsLoading={isLoadingWorkingCase}
nextIsDisabled={!isReviewedDecisionChanged}
onNextButtonClick={() =>
setConfirmationModal(CONFIRM_PROSECUTOR_DECISION)
}
nextButtonText={fm(strings.changeReviewedDecisionButtonText)}
/>
)}
</FormContentContainer>
{modalVisible === 'REVIEWER_ASSIGNED' && (
{isReviewerAssignedModal(confirmationModal) && (
<Modal
title={fm(strings.reviewerAssignedModalTitle)}
text={fm(strings.reviewerAssignedModalText, {
Expand Down
Loading
Loading