Skip to content

Commit

Permalink
VKT(Frontend & Backend): Grade UI fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
jrkkp committed Nov 18, 2024
1 parent 36260a1 commit 81e5b1d
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package fi.oph.vkt.api.dto.clerk;

import fi.oph.vkt.api.dto.EnrollmentGradeDTO;
import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record ExaminerEnrollmentGradesDTO(
@NonNull @NotNull Integer version,
EnrollmentGradeDTO speakingPartialExam,
EnrollmentGradeDTO speechComprehensionPartialExam,
EnrollmentGradeDTO writingPartialExam,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@Setter
@Entity
@Table(name = "enrollment_grade")
public class EnrollmentGrade {
public class EnrollmentGrade extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package fi.oph.vkt.model.type;

public enum EnrollmentGradeType {
ACCEPTED,
FAILED,
GOOD,
SATISFACTORY,
FAILED
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,15 @@ public ExaminerEnrollmentGradesDTO upsertAppointmentGrades(
final EnrollmentAppointment enrollmentAppointment = enrollmentAppointmentRepository.getReferenceById(
enrollmentAppointmentId
);

checkExaminerOid(enrollmentAppointment, oid);

final Optional<EnrollmentGrade> enrollmentGradeOptional = enrollmentGradesRepository.findByEnrollmentAppointment(
enrollmentAppointment
);
final EnrollmentGrade enrollmentGrade = enrollmentGradeOptional.orElseGet(EnrollmentGrade::new);

enrollmentGrade.assertVersion(dto.version());
if (dto.speakingPartialExam() != null) {
enrollmentGrade.setSpeakingPartialExamGrade(dto.speakingPartialExam().grade());
enrollmentGrade.setSpeakingPartialExamComment(dto.speakingPartialExam().comment());
Expand Down Expand Up @@ -187,6 +189,7 @@ public ExaminerEnrollmentGradesDTO upsertAppointmentGrades(
private ExaminerEnrollmentGradesDTO createGradesDTO(final EnrollmentGrade enrollmentGrade) {
return ExaminerEnrollmentGradesDTO
.builder()
.version(enrollmentGrade.getVersion())
.writingPartialExam(
createGradeDTO(enrollmentGrade.getWritingPartialExamGrade(), enrollmentGrade.getWritingPartialExamComment())
)
Expand Down
5 changes: 5 additions & 0 deletions frontend/packages/vkt/public/i18n/fi-FI/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
"understandingSkill": "Ymmärtämisen taito",
"writingPartialExam": "Kirjoittaminen"
},
"grades": {
"GOOD": "Hyvä",
"SATISFACTORY": "Tyydyttävä",
"FAILED": "Hylätty"
},
"textFields": {
"country": "Maa",
"email": "Sähköpostiosoite",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
H3,
InfoText,
Text,
valueAsOption,
} from 'shared/components';
import {
APIResponseStatus,
Expand All @@ -34,12 +33,17 @@ import {
useKoodistoMunicipalitiesTranslation,
} from 'configs/i18n';
import { useAppDispatch, useAppSelector } from 'configs/redux';
import { EnrollmentAppointmentStatus, PaymentStatus } from 'enums/app';
import {
EnrollmentAppointmentStatus,
ExamGrades,
PaymentStatus,
} from 'enums/app';
import { ClerkEnrollmentTextFieldEnum } from 'enums/clerkEnrollment';
import {
ClerkEnrollmentAppointment,
ClerkEnrollmentAppointmentGrades,
ClerkPayment,
GradedExams,
} from 'interfaces/clerkEnrollment';
import { ClerkEnrollmentTextFieldProps } from 'interfaces/clerkEnrollmentTextField';
import { PartialExamsAndSkills } from 'interfaces/common/enrollment';
Expand Down Expand Up @@ -105,14 +109,14 @@ const GradeModal = ({
}) => {
const translateCommon = useCommonTranslation();
const dispatch = useAppDispatch();
const exams: Array<keyof ClerkEnrollmentAppointmentGrades> = [
const exams: Array<keyof GradedExams> = [
'writingPartialExam',
'readingComprehensionPartialExam',
'speakingPartialExam',
'speechComprehensionPartialExam',
];
const selectedSkills = exams.filter(
(skill: keyof ClerkEnrollmentAppointmentGrades) => skills[skill],
(skill: keyof GradedExams) => skills[skill],
);
const { grades, gradesSaveStatus } = useAppSelector(
clerkEnrollmentAppointmentSelector,
Expand All @@ -138,25 +142,38 @@ const GradeModal = ({
}, [gradesSaveStatus, dispatch, closeModal]);

const onSetComment =
(exam: keyof ClerkEnrollmentAppointmentGrades) =>
(event: ChangeEvent<HTMLTextAreaElement>) =>
(exam: keyof GradedExams) => (event: ChangeEvent<HTMLTextAreaElement>) =>
setGrades((prev) => ({
...prev,
[exam]: {
...prev[exam],
grade: prev[exam]?.grade ?? '',
comment: event.target.value,
},
}));

const onSetGrade =
(exam: keyof ClerkEnrollmentAppointmentGrades) => (grade?: string) =>
setGrades((prev) => ({
...prev,
[exam]: {
...prev[exam],
grade,
},
}));
const onSetGrade = (exam: keyof GradedExams) => (grade?: string) =>
setGrades((prev) => ({
...prev,
[exam]: {
comment: prev[exam]?.comment ?? '',
grade,
},
}));

const gradeValues = [
{
label: translateCommon(`enrollment.grades.${ExamGrades.GOOD}`),
value: ExamGrades.GOOD,
},
{
label: translateCommon(`enrollment.grades.${ExamGrades.SATISFACTORY}`),
value: ExamGrades.SATISFACTORY,
},
{
label: translateCommon(`enrollment.grades.${ExamGrades.FAILED}`),
value: ExamGrades.FAILED,
},
];

return (
<CustomModal
Expand All @@ -170,34 +187,30 @@ const GradeModal = ({
<Text className="bold">Osakoe</Text>
<Text className="bold">Arvosana</Text>
<Text className="bold">Huomautuksia</Text>
{selectedSkills.map(
(skill: keyof ClerkEnrollmentAppointmentGrades, index) => (
<Fragment key={index}>
<Text>
{translateCommon(
`enrollment.partialExamsAndSkills.${skill}`,
)}
</Text>
<ComboBox
autoHighlight
values={['ACCEPTED', 'FAILED'].map(valueAsOption)}
variant={TextFieldVariant.Outlined}
onChange={onSetGrade(skill)}
value={
newGrades[skill]?.grade
? gradeToComboBoxOption(newGrades[skill]?.grade)
: null
}
disabled={isLoading}
/>
<CustomTextField
value={newGrades[skill]?.comment ?? ''}
onChange={onSetComment(skill)}
disabled={isLoading}
/>
</Fragment>
),
)}
{selectedSkills.map((skill: keyof GradedExams, index) => (
<Fragment key={index}>
<Text>
{translateCommon(`enrollment.partialExamsAndSkills.${skill}`)}
</Text>
<ComboBox
autoHighlight
values={gradeValues}
variant={TextFieldVariant.Outlined}
onChange={onSetGrade(skill)}
value={
newGrades[skill]?.grade
? gradeToComboBoxOption(newGrades[skill]?.grade)
: null
}
disabled={isLoading}
/>
<CustomTextField
value={newGrades[skill]?.comment ?? ''}
onChange={onSetComment(skill)}
disabled={isLoading}
/>
</Fragment>
))}
</div>
<div className="columns gapped flex-end">
<CustomButton
Expand Down Expand Up @@ -404,7 +417,10 @@ const ClerkEnrollmentSkillsListTable = ({

const { grades } = useAppSelector(clerkEnrollmentAppointmentSelector);

const renderGrade = (grade: string) => (grade && grade !== '' ? grade : '-');
const renderGrade = (grade: string) =>
grade && grade !== '' ? translateCommon(`enrollment.grades.${grade}`) : '-';
const renderComment = (comment: string) =>
comment && comment !== '' ? comment : '-';

const partialExamsRow = (exams: Array<keyof PartialExamsAndSkills>) => {
return exams.map((exam) => (
Expand All @@ -415,7 +431,7 @@ const ClerkEnrollmentSkillsListTable = ({
</Text>
</div>
<Text>{renderGrade(grades[exam]?.grade)}</Text>
<Text>{renderGrade(grades[exam]?.comment)}</Text>
<Text>{renderComment(grades[exam]?.comment)}</Text>
</Fragment>
));
};
Expand Down
6 changes: 6 additions & 0 deletions frontend/packages/vkt/src/enums/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ export enum ExamEventToggleFilter {
Passed = 'passed',
}

export enum ExamGrades {
GOOD = 'GOOD',
SATISFACTORY = 'SATISFACTORY',
FAILED = 'FAILED',
}

export enum UIMode {
Edit = 'edit',
View = 'view',
Expand Down
5 changes: 4 additions & 1 deletion frontend/packages/vkt/src/interfaces/clerkEnrollment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { ClerkFreeEnrollmentBasis } from 'interfaces/clerkEducation';
import {
CertificateShippingData,
PartialExams,
PartialExamsAndSkills,
} from 'interfaces/common/enrollment';
import {
Expand Down Expand Up @@ -126,7 +127,9 @@ interface Grade {
comment: string;
}

export interface ClerkEnrollmentAppointmentGrades {
export interface GradedExams extends Omit<PartialExams, 'understandingSkill'> {}

export interface ClerkEnrollmentAppointmentGrades extends WithVersion {
speakingPartialExam: Grade;
speechComprehensionPartialExam: Grade;
writingPartialExam: Grade;
Expand Down
9 changes: 6 additions & 3 deletions frontend/packages/vkt/src/interfaces/common/enrollment.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
export interface PartialExamsAndSkills {
oralSkill: boolean;
textualSkill: boolean;
export interface PartialExams {
understandingSkill: boolean;
speakingPartialExam: boolean;
speechComprehensionPartialExam: boolean;
writingPartialExam: boolean;
readingComprehensionPartialExam: boolean;
}

export interface PartialExamsAndSkills extends PartialExams {
oralSkill: boolean;
textualSkill: boolean;
}

export interface CertificateShippingTextFields {
street?: string;
postalCode?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const initialState: ClerkEnrollmentAppointmentState = {
examEventsStatus: APIResponseStatus.NotStarted,
examEvents: [],
grades: {
version: 0,
speakingPartialExam: {
grade: '',
comment: '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ function* upsertClerkEnrollmentAppointmentGradesSaga(
) {
const { enrollment, grades, oid } = action.payload;
const nonEmptyGrades = {
version: grades.version ?? 0,
speakingPartialExam:
grades.speakingPartialExam?.grade !== ''
? grades.speakingPartialExam
Expand Down

0 comments on commit 81e5b1d

Please sign in to comment.