Skip to content

Commit

Permalink
wip: Opintopiste/kurssi-homma käliin;
Browse files Browse the repository at this point in the history
Saattaa ehkä jo toimia, mutta ei ole testattu
  • Loading branch information
ilkkahanninen committed Jan 15, 2025
1 parent 27c8405 commit f25db2e
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 38 deletions.
30 changes: 22 additions & 8 deletions web/app/components-v2/opiskeluoikeus/LaajuusField.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import { isNonEmpty } from 'fp-ts/lib/Array'
import * as $ from 'optics-ts'
import React, { useCallback } from 'react'
import React, { useCallback, useEffect } from 'react'
import { useSafeState } from '../../api-fetch'
import { useKoodistoFiller } from '../../appstate/koodisto'
import { TestIdLayer, TestIdText } from '../../appstate/useTestId'
import { t } from '../../i18n/i18n'
import { Laajuus } from '../../types/fi/oph/koski/schema/Laajuus'
import { LaajuusKursseissa } from '../../types/fi/oph/koski/schema/LaajuusKursseissa'
import { LaajuusOpintopisteissä } from '../../types/fi/oph/koski/schema/LaajuusOpintopisteissa'
import { nonNull } from '../../util/fp/arrays'
import { formatNumber, removeFloatingPointDrift } from '../../util/numbers'
import { EmptyObject } from '../../util/objects'
import { CollectableOptic } from '../../util/types'
import { common, CommonProps } from '../CommonProps'
import { NumberField } from '../controls/NumberField'
import { FieldErrors } from '../forms/FieldErrors'
import { FieldEditorProps, FieldViewerProps } from '../forms/FormField'
import { nonNull } from '../../util/fp/arrays'
import { TestIdLayer, TestIdText, useTestId } from '../../appstate/useTestId'
import { EmptyObject } from '../../util/objects'
import { LaajuusKursseissa } from '../../types/fi/oph/koski/schema/LaajuusKursseissa'

/* ---------------------------------------------------------------------
*
Expand Down Expand Up @@ -55,12 +57,26 @@ export type LaajuusEditProps<T extends Laajuus> = CommonProps<
*/

export const LaajuusEdit = <T extends Laajuus>(props: LaajuusEditProps<T>) => {
const fillNimi = useKoodistoFiller()
const { onChange, createLaajuus } = props
const onChangeCB = useCallback(
(arvo: number) => onChange(createLaajuus(arvo)),
[createLaajuus, onChange]
)

const [yksikönNimi, setYksikönNimi] = useSafeState<string>('')

useEffect(() => {
const laajuus = props.value || createLaajuus(0)
if (laajuus.yksikkö.nimi || laajuus.yksikkö.lyhytNimi) {
setYksikönNimi(t(laajuus.yksikkö.lyhytNimi || laajuus.yksikkö.nimi) || '')
} else {
fillNimi(laajuus).then((l) =>
setYksikönNimi(t(l.yksikkö.lyhytNimi || l.yksikkö.nimi) || '')
)
}
}, [])

Check warning on line 78 in web/app/components-v2/opiskeluoikeus/LaajuusField.tsx

View workflow job for this annotation

GitHub Actions / 👀 / Lint Koski

React Hook useEffect has missing dependencies: 'createLaajuus', 'fillNimi', 'props.value', and 'setYksikönNimi'. Either include them or remove the dependency array

return (
<label {...common(props, ['LaajuusField'])}>
<div className="LaajuusField__container">
Expand All @@ -71,9 +87,7 @@ export const LaajuusEdit = <T extends Laajuus>(props: LaajuusEditProps<T>) => {
hasErrors={Boolean(props.errors)}
testId="laajuus.edit"
/>
<span className="LaajuusField__yksikko">
{t(props.value?.yksikkö.lyhytNimi || props.value?.yksikkö.nimi)}
</span>
<span className="LaajuusField__yksikko">{yksikönNimi}</span>
</div>
<TestIdLayer id="laajuus.edit">
<FieldErrors errors={props.errors} />
Expand Down
6 changes: 6 additions & 0 deletions web/app/components-v2/opiskeluoikeus/OppiaineTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const OppiaineTable = <T extends OppiaineTablePäätasonSuoritus>({
const suoritus = getValue(selectedSuoritus.path)(form.state)
const path = selectedSuoritus.pathTokens
const organisaatioOid = form.state.oppilaitos?.oid
const alkamispäivä = form.state.alkamispäivä

const showPredictedGrade =
selectedSuoritus.suoritus.$class === IBTutkinnonSuoritus.className
Expand Down Expand Up @@ -181,6 +182,7 @@ export const OppiaineTable = <T extends OppiaineTablePäätasonSuoritus>({
<TestIdLayer id={oppiaineIndex} key={oppiaineIndex}>
<OppiaineRow
organisaatioOid={organisaatioOid!}
alkamispäivä={alkamispäivä}
oppiaine={oppiaine}
form={form}
showPredictedGrade={showPredictedGrade}
Expand Down Expand Up @@ -214,6 +216,7 @@ export type OppiaineRowProps<T> = {
form: FormModel<OppiaineTableOpiskeluoikeus>
oppiainePath: PathToken[]
organisaatioOid: string
alkamispäivä?: string
oppiaine: Oppiaine
showPredictedGrade: boolean
addOsasuoritusDialog: AddOppiaineenOsasuoritusDialog<T>
Expand All @@ -227,6 +230,7 @@ export type OppiaineRowProps<T> = {
}

export type AddOppiaineenOsasuoritusDialog<T> = React.FC<{
alkamispäivä?: string
organisaatioOid: string
oppiaine: Oppiaine
onAdd: (t: T) => void
Expand All @@ -235,6 +239,7 @@ export type AddOppiaineenOsasuoritusDialog<T> = React.FC<{

const OppiaineRow = <T,>({
organisaatioOid,
alkamispäivä,
oppiaine,
oppiainePath,
form,
Expand Down Expand Up @@ -320,6 +325,7 @@ const OppiaineRow = <T,>({
/>
{addOsasuoritusDialogVisible && (
<AddOsasuoritusDialog
alkamispäivä={alkamispäivä}
organisaatioOid={organisaatioOid}
oppiaine={oppiaine}
onAdd={addOsasuoritus}
Expand Down
27 changes: 22 additions & 5 deletions web/app/components-v2/opiskeluoikeus/OppiaineTableKurssiEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import React from 'react'
import React, { useCallback } from 'react'
import { emptyLocalizedString, t } from '../../i18n/i18n'
import {
createIBLaajuus,
useIBLaajuusyksikkö
} from '../../ib/components/IBLaajuusEdit'
import { LaajuusKursseissa } from '../../types/fi/oph/koski/schema/LaajuusKursseissa'
import { isLukionKurssinSuoritus2015 } from '../../types/fi/oph/koski/schema/LukionKurssinSuoritus2015'
import { OsaamisenTunnustaminen } from '../../types/fi/oph/koski/schema/OsaamisenTunnustaminen'
import { isPaikallinenLukionKurssi2015 } from '../../types/fi/oph/koski/schema/PaikallinenLukionKurssi2015'
import { isPreIBKurssinSuoritus2015 } from '../../types/fi/oph/koski/schema/PreIBKurssinSuoritus2015'
import { isValinnaisuus } from '../../types/fi/oph/koski/schema/Valinnaisuus'
import { isValtakunnallinenLukionKurssi2015 } from '../../types/fi/oph/koski/schema/ValtakunnallinenLukionKurssi2015'
import { PathToken, get } from '../../util/laxModify'
Expand All @@ -13,11 +18,11 @@ import { Checkbox } from '../controls/Checkbox'
import { DateEdit } from '../controls/DateField'
import { FlatButton } from '../controls/FlatButton'
import { LocalizedTextEdit } from '../controls/LocalizedTestField'
import { NumberField } from '../controls/NumberField'
import { RaisedButton } from '../controls/RaisedButton'
import { FormModel } from '../forms/FormModel'
import { ArvosanaEdit } from './ArvosanaField'
import { KoodistoSelect } from './KoodistoSelect'
import { LaajuusEdit } from './LaajuusField'
import {
OppiaineTableOpiskeluoikeus,
OppiaineenOsasuoritus
Expand Down Expand Up @@ -58,6 +63,17 @@ export const OppiaineTableKurssiEditor: React.FC<
})
)

const ibYksikkö = useIBLaajuusyksikkö(
kurssi.koulutusmoduuli.laajuus,
form.state.alkamispäivä
)
const createLaajuus = useCallback((arvo: number) => {
if (isPreIBKurssinSuoritus2015(kurssi)) {
return createIBLaajuus(arvo, ibYksikkö)
}
throw new Error(`Unimplemented: createLaajuus for ${kurssi.$class}`)
}, [])

Check warning on line 75 in web/app/components-v2/opiskeluoikeus/OppiaineTableKurssiEditor.tsx

View workflow job for this annotation

GitHub Actions / 👀 / Lint Koski

React Hook useCallback has missing dependencies: 'ibYksikkö' and 'kurssi'. Either include them or remove the dependency array

return (
<Modal onClose={onClose}>
<ModalTitle>
Expand All @@ -67,9 +83,10 @@ export const OppiaineTableKurssiEditor: React.FC<
<ModalBody>
<KeyValueTable>
<KeyValueRow localizableLabel="Laajuus">
<NumberField
value={kurssi.koulutusmoduuli.laajuus?.arvo}
onChange={form.set(...path, ...laajuusPath, 'arvo')}
<LaajuusEdit
value={kurssi.koulutusmoduuli.laajuus}
onChange={form.set(...path, ...laajuusPath)}
createLaajuus={createLaajuus}
/>
</KeyValueRow>

Expand Down
9 changes: 9 additions & 0 deletions web/app/date/date.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import fecha from 'fecha'
import { pipe } from 'fp-ts/lib/function'

const toUndefined =
<T extends any[]>(f: (...as: T) => Date | boolean) =>
(...as: T): Date | undefined => {
const date = f(...as)
return typeof date === 'boolean' ? undefined : date
}

const finnishDateRE = /([0-3]?\d)\.([0-2]?\d)\.(\d\d\d\d)/
export const formatISODate = (date: Date) => format(date, 'YYYY-MM-DD')
export const parseFinnishDate = (dateStr: string) => {
Expand Down Expand Up @@ -28,6 +35,8 @@ export const ISO2FinnishDateTime = (dateStr: string) =>
export const parseISODate = (dateStr: string) =>
fecha.parse(dateStr, 'YYYY-MM-DD')

export const parseISODateNullable = toUndefined(parseISODate)

export const formatFinnishDate = (date: Date) => format(date, 'D.M.YYYY')

export const yearFromIsoDateString = (dateStr: string) =>
Expand Down
74 changes: 74 additions & 0 deletions web/app/ib/components/IBLaajuusEdit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useCallback, useMemo } from 'react'
import {
LaajuusEdit,
LaajuusEditProps
} from '../../components-v2/opiskeluoikeus/LaajuusField'
import { parseISODateNullable, today } from '../../date/date'
import { Koodistokoodiviite } from '../../types/fi/oph/koski/schema/Koodistokoodiviite'
import { LaajuusKursseissa } from '../../types/fi/oph/koski/schema/LaajuusKursseissa'
import { LaajuusOpintopisteissä } from '../../types/fi/oph/koski/schema/LaajuusOpintopisteissa'
import { LaajuusOpintopisteissäTaiKursseissa } from '../../types/fi/oph/koski/schema/LaajuusOpintopisteissaTaiKursseissa'

const laajuusyksikönVaihtumispäivä = new Date(2025, 8 - 1, 1)

export type IBLaajuusEditProps = Omit<
LaajuusEditProps<LaajuusOpintopisteissäTaiKursseissa> & {
alkamispäivä?: string
},
'createLaajuus'
>

export const IBLaajuusEdit: React.FC<IBLaajuusEditProps> = (props) => {
const yksikkö = useIBLaajuusyksikkö(props.value, props.alkamispäivä)
const createLaajuus = useCallback(
(arvo: number) => {
return createIBLaajuus(arvo, yksikkö!)
},
[yksikkö]
)

return yksikkö ? (
<>
<LaajuusEdit
{...props}
createLaajuus={createLaajuus}
testId={props.testId || 'laajuus'}
/>
</>
) : null
}

export const createIBLaajuus = (
arvo: number,
yksikkö: Koodistokoodiviite
): LaajuusOpintopisteissäTaiKursseissa =>
yksikkö.koodiarvo === Kursseja
? LaajuusKursseissa({ arvo })
: LaajuusOpintopisteissä({ arvo })

export const Kursseja = '4'
export const Opintopisteitä = '2'
type IBLaajuusYksikkö = Koodistokoodiviite<
'opintojenlaajuusyksikko',
typeof Kursseja | typeof Opintopisteitä
>

export const useIBLaajuusyksikkö = (
value?: LaajuusOpintopisteissäTaiKursseissa,
alkamispäivä?: string
): IBLaajuusYksikkö =>
useMemo(
() =>
value
? value.yksikkö
: laajuusyksikköPäivänPerusteella(
(alkamispäivä && parseISODateNullable(alkamispäivä)) || today()
),
[value, alkamispäivä]
)

const laajuusyksikköPäivänPerusteella = (pvm: Date): IBLaajuusYksikkö =>
Koodistokoodiviite({
koodiarvo: pvm < laajuusyksikönVaihtumispäivä ? Kursseja : Opintopisteitä,
koodistoUri: 'opintojenlaajuusyksikko'
})
16 changes: 8 additions & 8 deletions web/app/ib/dialogs/UusiPreIB2015OsasuoritusDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ import {
UusiIBKurssiKey,
UusiPaikallinenLukionKurssiKey
} from '../state/preIB2015Kurssi'
import { IBLaajuusEdit } from '../components/IBLaajuusEdit'

export const UusiPreIB2015OsasuoritusDialog: AddOppiaineenOsasuoritusDialog<
PreIBKurssinSuoritus2015
> = ({ onAdd, ...props }) => {
> = ({ onAdd, alkamispäivä, ...props }) => {
const {
preferences: paikallisetLukionKurssit,
store: storePaikallinenLukionKurssi,
Expand All @@ -63,7 +64,8 @@ export const UusiPreIB2015OsasuoritusDialog: AddOppiaineenOsasuoritusDialog<
} = usePreferences<IBKurssi>(props.organisaatioOid, 'ibkurssi')

const state = usePreIB2015OsasuoritusState(
props.oppiaine.koulutusmoduuli.tunniste
props.oppiaine.koulutusmoduuli.tunniste,
alkamispäivä
)

const valtakunnallisetTunnisteetOptions =
Expand Down Expand Up @@ -225,12 +227,10 @@ export const UusiPreIB2015OsasuoritusDialog: AddOppiaineenOsasuoritusDialog<
{state.laajuus.visible && (
<label>
{t('Laajuus')}
<NumberField
value={state.laajuus.value?.arvo}
onChange={(arvo) =>
state.laajuus.set(LaajuusKursseissa({ arvo }))
}
testId="laajuus"
<IBLaajuusEdit
alkamispäivä={alkamispäivä}
value={state.laajuus.value}
onChange={state.laajuus.set}
/>
</label>
)}
Expand Down
4 changes: 2 additions & 2 deletions web/app/ib/oppiaineet/ibTutkintoKurssi.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { IBKurssi } from '../../types/fi/oph/koski/schema/IBKurssi'
import { IBKurssinSuoritus } from '../../types/fi/oph/koski/schema/IBKurssinSuoritus'
import { Koodistokoodiviite } from '../../types/fi/oph/koski/schema/Koodistokoodiviite'
import { LaajuusKursseissa } from '../../types/fi/oph/koski/schema/LaajuusKursseissa'
import { LaajuusOpintopisteissäTaiKursseissa } from '../../types/fi/oph/koski/schema/LaajuusOpintopisteissaTaiKursseissa'
import { LocalizedString } from '../../types/fi/oph/koski/schema/LocalizedString'
import { PaikallinenKoodi } from '../../types/fi/oph/koski/schema/PaikallinenKoodi'
import { isValidPaikallinenKoodi } from './tunnisteet'

export type IBKurssinSuoritusProps = {
tunniste?: PaikallinenKoodi
kuvaus?: LocalizedString
laajuus?: LaajuusKursseissa
laajuus?: LaajuusOpintopisteissäTaiKursseissa
pakollinen?: boolean
suorituskieli?: Koodistokoodiviite<'kieli'>
}
Expand Down
15 changes: 10 additions & 5 deletions web/app/ib/oppiaineet/preIBKurssi2015.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { t } from '../../i18n/i18n'
import { IBKurssi } from '../../types/fi/oph/koski/schema/IBKurssi'
import { Koodistokoodiviite } from '../../types/fi/oph/koski/schema/Koodistokoodiviite'
import { LaajuusKursseissa } from '../../types/fi/oph/koski/schema/LaajuusKursseissa'
import { isLaajuusKursseissa } from '../../types/fi/oph/koski/schema/LaajuusKursseissa'
import { LaajuusOpintopisteissäTaiKursseissa } from '../../types/fi/oph/koski/schema/LaajuusOpintopisteissaTaiKursseissa'
import { LocalizedString } from '../../types/fi/oph/koski/schema/LocalizedString'
import {
isPaikallinenKoodi,
Expand All @@ -22,7 +22,7 @@ export type PreIBKurssi2015Props = {
lukiokurssinTyyppi?: Koodistokoodiviite<'lukionkurssintyyppi'>
kuvaus?: LocalizedString
pakollinen?: boolean
laajuus?: LaajuusKursseissa
laajuus?: LaajuusOpintopisteissäTaiKursseissa
}

export type PreIB2015KurssiOppiaineenTunniste = PermissiveKoodiviite<
Expand Down Expand Up @@ -64,7 +64,12 @@ const createPreIBKurssi2015 = ({
pakollinen,
laajuus
}: PreIBKurssi2015Props): PreIBKurssi2015 | null => {
if (lukiokurssinTyyppi && tunniste && !isPaikallinenKoodi(tunniste)) {
if (
lukiokurssinTyyppi &&
tunniste &&
!isPaikallinenKoodi(tunniste) &&
isLaajuusKursseissa(laajuus)
) {
return ValtakunnallinenLukionKurssi2015({
tunniste,
kurssinTyyppi: lukiokurssinTyyppi,
Expand All @@ -81,7 +86,7 @@ const createPreIBKurssi2015 = ({
laajuus
})
} else {
return lukiokurssinTyyppi
return lukiokurssinTyyppi && isLaajuusKursseissa(laajuus)
? PaikallinenLukionKurssi2015({
tunniste,
kurssinTyyppi: lukiokurssinTyyppi,
Expand Down
Loading

0 comments on commit f25db2e

Please sign in to comment.