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): Speeding #17589

Merged
merged 23 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a51d893
Add option SPEEDING
oddsson Jan 20, 2025
0e78722
Add legal arguments
oddsson Jan 20, 2025
a3abfaa
Add input fields
oddsson Jan 20, 2025
6f81279
Add recordedSpeed and speedLimit to db
oddsson Jan 20, 2025
dbcefc3
Enable seedLimit update
oddsson Jan 21, 2025
98f3e9e
Merge branch 'main' of github.com:island-is/island.is into j-s/speeding
oddsson Jan 21, 2025
ca7dd96
Add validation
oddsson Jan 21, 2025
d54f27d
Update indictment description
oddsson Jan 21, 2025
2b11e68
Clear recorded speed and speed limit when removing speedig
oddsson Jan 21, 2025
061ebb7
Add error handling
oddsson Jan 21, 2025
529766d
Fix comment
oddsson Jan 21, 2025
46df9a0
Fix lint
oddsson Jan 21, 2025
cd909aa
Merge branch 'main' of github.com:island-is/island.is into j-s/speeding
oddsson Jan 21, 2025
1a52b36
Remove css
oddsson Jan 21, 2025
f038a57
Make Icon position abs
oddsson Jan 21, 2025
1b79e40
Merge branch 'main' of github.com:island-is/island.is into j-s/speeding
oddsson Jan 22, 2025
f3f78fe
Rec speed and speed limit is now number
oddsson Jan 22, 2025
371458c
Remove island-ui change
oddsson Jan 22, 2025
1dcbfad
Merge branch 'main' of github.com:island-is/island.is into j-s/speeding
oddsson Jan 24, 2025
2533785
Merge branch 'main' of github.com:island-is/island.is into j-s/speeding
oddsson Jan 28, 2025
7f420b7
Improve validation
oddsson Jan 28, 2025
393e7a7
Merge branch 'main' of github.com:island-is/island.is into j-s/speeding
oddsson Jan 28, 2025
1a01f73
Use Number.isNaN instead of isNaN
oddsson Jan 28, 2025
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
@@ -1,7 +1,14 @@
import { Allow, IsArray, IsEnum, IsOptional } from 'class-validator'
import {
Allow,
IsArray,
IsEnum,
IsNumber,
IsOptional,
Min,
} from 'class-validator'
import { GraphQLJSONObject } from 'graphql-type-json'

import { Field, ID, InputType } from '@nestjs/graphql'
import { Field, ID, InputType, Int } from '@nestjs/graphql'

import type { SubstanceMap } from '@island.is/judicial-system/types'
import {
Expand Down Expand Up @@ -63,4 +70,18 @@ export class UpdateIndictmentCountInput {
@IsEnum(IndictmentSubtype, { each: true })
@Field(() => [IndictmentSubtype], { nullable: true })
readonly indictmentCountSubtypes?: IndictmentSubtype[]

@Allow()
@IsOptional()
@IsNumber()
@Min(0)
@Field(() => Int, { nullable: true })
readonly recordedSpeed?: number

oddsson marked this conversation as resolved.
Show resolved Hide resolved
@Allow()
@IsOptional()
@IsNumber()
@Min(0)
@Field(() => Int, { nullable: true })
readonly speedLimit?: number
}
oddsson marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GraphQLJSONObject } from 'graphql-type-json'

import { Field, ID, ObjectType, registerEnumType } from '@nestjs/graphql'
import { Field, ID, Int, ObjectType, registerEnumType } from '@nestjs/graphql'

import type { SubstanceMap } from '@island.is/judicial-system/types'
import {
Expand Down Expand Up @@ -48,4 +48,10 @@ export class IndictmentCount {

@Field(() => [IndictmentSubtype], { nullable: true })
readonly indictmentCountSubtypes?: IndictmentSubtype[]

@Field(() => Int, { nullable: true })
readonly recordedSpeed?: number

@Field(() => Int, { nullable: true })
readonly speedLimit?: number
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module.exports = {
oddsson marked this conversation as resolved.
Show resolved Hide resolved
async up(queryInterface, Sequelize) {
return queryInterface.sequelize.transaction((t) =>
Promise.all([
queryInterface.addColumn(
'indictment_count',
'recorded_speed',
{
type: Sequelize.INTEGER,
allowNull: true,
},
{ transaction: t },
),
queryInterface.addColumn(
'indictment_count',
'speed_limit',
{
type: Sequelize.INTEGER,
allowNull: true,
},
{ transaction: t },
),
]),
)
},
async down(queryInterface) {
return queryInterface.sequelize.transaction((t) =>
Promise.all([
queryInterface.removeColumn('indictment_count', 'recorded_speed', {
transaction: t,
}),
queryInterface.removeColumn('indictment_count', 'speed_limit', {
transaction: t,
}),
]),
)
},
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {
IsArray,
IsEnum,
IsNumber,
IsObject,
IsOptional,
IsString,
MaxLength,
Min,
} from 'class-validator'

import { ApiPropertyOptional } from '@nestjs/swagger'
Expand Down Expand Up @@ -59,4 +61,16 @@ export class UpdateIndictmentCountDto {
@IsEnum(IndictmentSubtype, { each: true })
@ApiPropertyOptional({ enum: IndictmentSubtype, isArray: true })
readonly indictmentCountSubtypes?: IndictmentSubtype[]

@IsOptional()
@IsNumber()
@Min(0)
@ApiPropertyOptional({ type: Number })
readonly recordedSpeed?: number
oddsson marked this conversation as resolved.
Show resolved Hide resolved

@IsOptional()
@IsNumber()
@Min(0)
@ApiPropertyOptional({ type: Number })
readonly speedLimit?: number
oddsson marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,12 @@ export class IndictmentCount extends Model {
})
@ApiPropertyOptional({ enum: IndictmentSubtype, isArray: true })
indictmentCountSubtypes?: IndictmentSubtype[]

@Column({ type: DataType.INTEGER, allowNull: true })
@ApiPropertyOptional({ type: Number })
recordedSpeed?: number

@Column({ type: DataType.INTEGER, allowNull: true })
@ApiPropertyOptional({ type: Number })
speedLimit?: number
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ query Case($input: CaseQueryInput!) {
incidentDescription
legalArguments
indictmentCountSubtypes
recordedSpeed
speedLimit
}
requestDriversLicenseSuspension
appealState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,24 @@ export const indictmentCount = defineMessages({
description:
'Notaður sem skýritexti á "vínandamagn" svæði á ákæruliða skrefi í ákærum.',
},
speedingTitle: {
id: 'judicial.system.core:indictments_indictment.indictment_count.speeding',
defaultMessage: 'Hraði',
description:
'Notaður sem titill á "Hraði" svæði á ákæruliða skrefi í ákærum.',
},
recordedSpeedLabel: {
id: 'judicial.system.core:indictments_indictment.indictment_count.recorded_speed_label',
defaultMessage: 'Mældur hraði (km/klst)',
description:
'Notaður sem titill á "Mældur hraði" innsláttarsvæði á ákæruliða skrefi í ákærum.',
},
speedLimitLabel: {
id: 'judicial.system.core:indictments_indictment.indictment_count.speed_limit_label',
defaultMessage: 'Leyfilegur hámarkshraði (km/klst)',
description:
'Notaður sem titill á "Leyfilegur hámarkshraði" innsláttarsvæði á ákæruliða skrefi í ákærum.',
},
lawsBrokenTitle: {
id: 'judicial.system.core:indictments_indictment.indictment_count.laws_broken_title',
defaultMessage: 'Lagaákvæði',
Expand All @@ -118,10 +136,15 @@ export const indictmentCount = defineMessages({
defaultMessage: '{paragraph}. mgr. {article}. gr. umfl.',
description: 'Notaður sem texti í lagaákvæði taggi.',
},
lawsBrokenTagArticleOnly: {
id: 'judicial.system.core:indictments_indictment.indictment_count.laws_broken_tag_article_only',
defaultMessage: '{article}. gr. umfl.',
description: 'Notaður sem texti í lagaákvæði taggi.',
},
incidentDescriptionAutofill: {
id: 'judicial.system.core:indictments_indictment.indictment_count.incident_description_auto_fill',
id: 'judicial.system.core:indictments_indictment.indictment_count.incident_description_auto_fill_v1',
defaultMessage:
'fyrir umferðarlagabrot með því að hafa, {incidentDate}, ekið bifreiðinni {vehicleRegistrationNumber} {reason} um {incidentLocation}, þar sem lögregla stöðvaði aksturinn.',
'fyrir umferðarlagabrot með því að hafa, {incidentDate}, ekið bifreiðinni {vehicleRegistrationNumber} {reason} um {incidentLocation}, {isSpeeding, select, true {á {recordedSpeed} km hraða á klukkustund, að teknu tilliti til vikmarka, þar sem leyfður hámarkshraði var {speedLimit} km/klst} other {þar sem lögregla stöðvaði aksturinn}}.',
description:
'Notaður sem skýritexti á "atvikalýsing" svæði á ákæruliða skrefi í umferðalagabrots ákærum.',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ const offensesCompare = (
return 0
}

/**
* Indicates what laws are broken for each offence. The first number is
* the paragraph and the second is the article, i.e. [49, 2] means paragraph
* 49, article 2. If article is set to 0, that means that an article is
* not specified.
*/
const offenseLawsMap: Record<
IndictmentCountOffense | 'DRUNK_DRIVING_MINOR' | 'DRUNK_DRIVING_MAJOR',
[number, number][]
Expand All @@ -98,6 +104,7 @@ const offenseLawsMap: Record<
[48, 1],
[48, 2],
],
[IndictmentCountOffense.SPEEDING]: [[37, 0]],
}

const generalLaws: [number, number][] = [[95, 1]]
Expand Down Expand Up @@ -269,9 +276,13 @@ export const getLegalArguments = (
let articles = `${lawsBroken[0][1]}.`

for (let i = 1; i < lawsBroken.length; i++) {
const noArticle = articles === '0.'
oddsson marked this conversation as resolved.
Show resolved Hide resolved
let useSbr = true

if (lawsBroken[i][0] !== lawsBroken[i - 1][0]) {
articles = `${articles} mgr. ${lawsBroken[i - 1][0]}. gr.`
articles = `${noArticle ? '' : `${articles} mgr. `}${
lawsBroken[i - 1][0]
}. gr.`
useSbr = i > andIndex
}

Expand Down Expand Up @@ -334,11 +345,21 @@ export const getIncidentDescription = (
formatMessage,
)

const isSpeeding = indictmentCount.offenses?.includes(
IndictmentCountOffense.SPEEDING,
)

const recordedSpeed = indictmentCount.recordedSpeed ?? '[Mældur hraði]'
const speedLimit = indictmentCount.speedLimit ?? '[Leyfilegur hraði]'

return formatMessage(strings.incidentDescriptionAutofill, {
incidentDate,
vehicleRegistrationNumber: vehicleRegistration,
reason,
incidentLocation,
isSpeeding,
recordedSpeed,
speedLimit,
})
}

Expand Down Expand Up @@ -380,6 +401,10 @@ export const IndictmentCount: FC<Props> = ({
useState<string>('')
const [legalArgumentsErrorMessage, setLegalArgumentsErrorMessage] =
useState<string>('')
const [recordedSpeedErrorMessage, setRecordedSpeedErrorMessage] =
useState<string>('')
const [speedLimitErrorMessage, setSpeedLimitErrorMessage] =
useState<string>('')

const subtypes: IndictmentSubtype[] = indictmentCount.policeCaseNumber
? workingCase.indictmentSubtypes[indictmentCount.policeCaseNumber]
Expand Down Expand Up @@ -685,6 +710,10 @@ export const IndictmentCount: FC<Props> = ({
handleIndictmentCountChanges({
offenses,
substances: indictmentCount.substances,
...(offense === IndictmentCountOffense.SPEEDING && {
recordedSpeed: null,
speedLimit: null,
}),
})
}}
>
Expand Down Expand Up @@ -767,6 +796,107 @@ export const IndictmentCount: FC<Props> = ({
</InputMask>
</Box>
)}
{indictmentCount.offenses?.includes(
IndictmentCountOffense.SPEEDING,
) && (
<Box marginBottom={2}>
<SectionHeading
title={formatMessage(strings.speedingTitle)}
heading="h4"
marginBottom={2}
/>
<Box marginBottom={1}>
<InputMask
mask={'999'}
maskPlaceholder={null}
value={indictmentCount.recordedSpeed?.toString() ?? ''}
onChange={(event) => {
const recordedSpeed = parseInt(event.target.value)

removeErrorMessageIfValid(
['empty'],
event.target.value,
recordedSpeedErrorMessage,
setRecordedSpeedErrorMessage,
)

updateIndictmentCountState(
indictmentCount.id,
{ recordedSpeed },
setWorkingCase,
)
}}
onBlur={(event) => {
const recordedSpeed = parseInt(event.target.value)

validateAndSetErrorMessage(
['empty'],
recordedSpeed.toString(),
setRecordedSpeedErrorMessage,
)

handleIndictmentCountChanges({
recordedSpeed,
})
}}
>
<Input
name="recordedSpeed"
autoComplete="off"
label={formatMessage(strings.recordedSpeedLabel)}
placeholder="0"
required
errorMessage={recordedSpeedErrorMessage}
hasError={recordedSpeedErrorMessage !== ''}
/>
</InputMask>
</Box>
<InputMask
mask={'999'}
maskPlaceholder={null}
value={indictmentCount.speedLimit?.toString() ?? ''}
onChange={(event) => {
const speedLimit = parseInt(event.target.value)

removeErrorMessageIfValid(
['empty'],
event.target.value,
speedLimitErrorMessage,
setSpeedLimitErrorMessage,
)

updateIndictmentCountState(
indictmentCount.id,
{ speedLimit },
setWorkingCase,
)
}}
onBlur={(event) => {
const speedLimit = parseInt(event.target.value)

validateAndSetErrorMessage(
['empty'],
speedLimit.toString(),
setSpeedLimitErrorMessage,
)

handleIndictmentCountChanges({
speedLimit,
})
}}
>
<Input
name="speedLimit"
autoComplete="off"
label={formatMessage(strings.speedLimitLabel)}
placeholder="0"
required
errorMessage={speedLimitErrorMessage}
hasError={speedLimitErrorMessage !== ''}
/>
</InputMask>
</Box>
oddsson marked this conversation as resolved.
Show resolved Hide resolved
)}
{indictmentCount.offenses
?.filter(
(offenseType) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ export const indictmentCountEnum = defineMessages({
defaultMessage: 'Lyfjaakstur',
description: 'Notaður sem titill á subtype fyrir "lyfjaakstur" brot.',
},
SPEEDING: {
id: 'judicial.system.core:indictments_indictment.indictment_count_enum.speeding',
defaultMessage: 'Hraðakstur',
description: 'Notaður sem titill á subtype fyrir "hraðakstur" brot.',
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ export const Substance: FC<Props> = ({
}}
errorMessage={substanceAmountMissingErrorMessage}
hasError={substanceAmountMissingErrorMessage !== ''}
></Input>
/>
)
}
Loading
Loading