Skip to content

Commit

Permalink
VKT(Frontend): Rework enrollment preview structure on mobile to bette…
Browse files Browse the repository at this point in the history
…r match designs [deploy]
  • Loading branch information
pkoivisto committed Sep 11, 2024
1 parent 8fd24b8 commit 2554b41
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 62 deletions.
7 changes: 6 additions & 1 deletion frontend/packages/vkt/public/i18n/fi-FI/public.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,12 @@
},
"examEventDetails": {
"previousEnrollmentLabel": "Aikaisempiin erinomaisen taidon tutkintoihin osallistuminen",
"selectedSkillsLabel": "Valitut tutkinnot",
"desktop": {
"selectedSkillsLabel": "Valitut tutkinnot"
},
"phone": {
"selectedSkillLabel": "Valittu tutkinto"
},
"selectedPartialExamsLabel": "Valitut osakokeet",
"title": "Tutkinnon tiedot"
},
Expand Down
7 changes: 6 additions & 1 deletion frontend/packages/vkt/public/i18n/sv-SE/public.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,12 @@
},
"examEventDetails": {
"previousEnrollmentLabel": "Deltagande i tidigare språkexamina för statsförvaltingen som gäller utmärkta språkkunskaper",
"selectedSkillsLabel": "Valda examina",
"desktop": {
"selectedSkillsLabel": "Valda examina"
},
"phone": {
"selectedSkillLabel": "Valt examen"
},
"selectedPartialExamsLabel": "Valda delprov",
"title": "Uppgifter om examen"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,85 +1,87 @@
import { Divider } from '@mui/material';
import { H2, Text } from 'shared/components';
import { useWindowProperties } from 'shared/hooks';

import { useCommonTranslation, usePublicTranslation } from 'configs/i18n';
import { useAppSelector } from 'configs/redux';
import { ClerkEnrollment } from 'interfaces/clerkEnrollment';
import { PartialExamsAndSkills } from 'interfaces/common/enrollment';
import { PublicFreeEnrollmentDetails } from 'interfaces/publicEducation';
import { PublicEnrollment } from 'interfaces/publicEnrollment';
import { publicEnrollmentSelector } from 'redux/selectors/publicEnrollment';
import { EnrollmentUtils } from 'utils/enrollment';
import { ENROLLMENT_SKILL_PRICE } from 'utils/publicEnrollment';
export const ExamEventDetails = ({

const getFreeEnrollmentsLeft = (
skill: string,
freeEnrollmentDetails?: PublicFreeEnrollmentDetails,
) => {
if (!freeEnrollmentDetails) {
return '';
}

switch (skill) {
case 'textualSkill':
return freeEnrollmentDetails.freeTextualSkillLeft;
case 'oralSkill':
return freeEnrollmentDetails.freeOralSkillLeft;
default:
return '';
}
};

const getEnrollmentSkillPrice = (
skill: string,
enrollment: PublicEnrollment | ClerkEnrollment,
freeEnrollmentDetails?: PublicFreeEnrollmentDetails,
) => {
if (!freeEnrollmentDetails || !EnrollmentUtils.hasFreeBasis(enrollment)) {
return ENROLLMENT_SKILL_PRICE;
}

switch (skill) {
case 'textualSkill':
return freeEnrollmentDetails.freeTextualSkillLeft > 0
? 0
: ENROLLMENT_SKILL_PRICE;
case 'oralSkill':
return freeEnrollmentDetails.freeOralSkillLeft > 0
? 0
: ENROLLMENT_SKILL_PRICE;
default:
return ENROLLMENT_SKILL_PRICE;
}
};

const DesktopSkillsList = ({
enrollment,
clerkView = false,
clerkView,
}: {
enrollment: PublicEnrollment | ClerkEnrollment;
clerkView?: boolean;
clerkView: boolean;
}) => {
const translateCommon = useCommonTranslation();
const { t } = usePublicTranslation({
keyPrefix: 'vkt.component.publicEnrollment.steps.preview',
});
const translateCommon = useCommonTranslation();
const publicEnrollment = useAppSelector(publicEnrollmentSelector);
const freeEnrollmentDetails =
(enrollment as ClerkEnrollment).freeEnrollmentDetails ||
publicEnrollment.freeEnrollmentDetails;

const skills = ['textualSkill', 'oralSkill'].filter(
(skill) => !!enrollment[skill as keyof PartialExamsAndSkills],
);

const partialExams = [
'writingPartialExam',
'readingComprehensionPartialExam',
'speakingPartialExam',
'speechComprehensionPartialExam',
].filter((exam) => !!enrollment[exam as keyof PartialExamsAndSkills]);

const getFreeEnrollmentsLeft = (skill: string) => {
if (!freeEnrollmentDetails) {
return '';
}

switch (skill) {
case 'textualSkill':
return freeEnrollmentDetails.freeTextualSkillLeft;
case 'oralSkill':
return freeEnrollmentDetails.freeOralSkillLeft;
default:
return '';
}
};

const getEnrollmentSkillPrice = (skill: string) => {
if (!freeEnrollmentDetails || !EnrollmentUtils.hasFreeBasis(enrollment)) {
return ENROLLMENT_SKILL_PRICE;
}

switch (skill) {
case 'textualSkill':
return freeEnrollmentDetails.freeTextualSkillLeft > 0
? 0
: ENROLLMENT_SKILL_PRICE;
case 'oralSkill':
return freeEnrollmentDetails.freeOralSkillLeft > 0
? 0
: ENROLLMENT_SKILL_PRICE;
default:
return ENROLLMENT_SKILL_PRICE;
}
};

const hasFreeEnrollments =
freeEnrollmentDetails &&
EnrollmentUtils.hasFreeBasis(enrollment) &&
(freeEnrollmentDetails.freeTextualSkillLeft > 0 ||
freeEnrollmentDetails.freeOralSkillLeft > 0);
const skills = ['textualSkill', 'oralSkill'].filter(
(skill) => !!enrollment[skill as keyof PartialExamsAndSkills],
);

const displaySkillsList = () => (
return (
<div className="rows gapped-xxs">
<div className="grid-3-columns gapped">
<Text className="bold">
{t('examEventDetails.selectedPartialExamsLabel')}
{t('examEventDetails.desktop.selectedSkillsLabel')}
</Text>
{hasFreeEnrollments && !clerkView && (
<Text className="bold">
Expand All @@ -96,36 +98,160 @@ export const ExamEventDetails = ({
{translateCommon(`enrollment.partialExamsAndSkills.${skill}`)}
</Text>
{(enrollment.isFree || EnrollmentUtils.hasFreeBasis(enrollment)) &&
!clerkView && <Text>{getFreeEnrollmentsLeft(skill)} / 3</Text>}
{!clerkView && <Text>{getEnrollmentSkillPrice(skill)}&euro;</Text>}
!clerkView && (
<Text>
{getFreeEnrollmentsLeft(skill, freeEnrollmentDetails)} / 3
</Text>
)}
{!clerkView && (
<Text>
{getEnrollmentSkillPrice(
skill,
enrollment,
freeEnrollmentDetails,
)}
&euro;
</Text>
)}
</div>
))}
</div>
);
};

const DesktopExamsList = ({
enrollment,
}: {
enrollment: ClerkEnrollment | PublicEnrollment;
}) => {
const { t } = usePublicTranslation({
keyPrefix: 'vkt.component.publicEnrollment.steps.preview.examEventDetails',
});
const translateCommon = useCommonTranslation();

const displayExamsList = () => (
const partialExams = [
'writingPartialExam',
'readingComprehensionPartialExam',
'speakingPartialExam',
'speechComprehensionPartialExam',
].filter((exam) => !!enrollment[exam as keyof PartialExamsAndSkills]);

return (
<div className="rows gapped-xxs">
<Text className="bold">
{t('examEventDetails.selectedSkillsLabel')}
{t('selectedPartialExamsLabel')}
{':'}
</Text>
<ul className="public-enrollment__grid__preview__bullet-list">
{partialExams.map((skill, i) => (
{partialExams.map((exam, i) => (
<Text key={i}>
<li>
{translateCommon(`enrollment.partialExamsAndSkills.${skill}`)}
{translateCommon(`enrollment.partialExamsAndSkills.${exam}`)}
</li>
</Text>
))}
</ul>
</div>
);
};

const PhoneSkillsAndExamsList = ({
enrollment,
}: {
enrollment: ClerkEnrollment | PublicEnrollment;
}) => {
const translateCommon = useCommonTranslation();
const { t } = usePublicTranslation({
keyPrefix: 'vkt.component.publicEnrollment.steps.preview',
});
const publicEnrollment = useAppSelector(publicEnrollmentSelector);
const freeEnrollmentDetails =
(enrollment as ClerkEnrollment).freeEnrollmentDetails ||
publicEnrollment.freeEnrollmentDetails;
const skills = ['textualSkill', 'oralSkill'].filter(
(skill) => !!enrollment[skill as keyof PartialExamsAndSkills],
);
const partialExams = [
'writingPartialExam',
'readingComprehensionPartialExam',
'speakingPartialExam',
'speechComprehensionPartialExam',
].filter((exam) => !!enrollment[exam as keyof PartialExamsAndSkills]);

return (
<>
{skills.map((skill) => (
<div key={skill} className="rows gapped">
<div className="rows gapped-xxs">
<Text>
<b>
{t('examEventDetails.phone.selectedSkillLabel')}:{' '}
{translateCommon(`enrollment.partialExamsAndSkills.${skill}`)}
</b>
</Text>
<Text>
<b>{t('educationDetails.freeEnrollmentsLeft')}</b>
</Text>
<Text>
{getFreeEnrollmentsLeft(skill, freeEnrollmentDetails)}/3
</Text>
<Text>
<b>{t('educationDetails.price')}</b>
</Text>
<Text>
{getEnrollmentSkillPrice(
skill,
enrollment,
freeEnrollmentDetails,
)}
&nbsp;&euro;
</Text>
</div>
<Divider />
</div>
))}
<div className="rows gapped-xxs">
<Text>
<b>{t('examEventDetails.selectedPartialExamsLabel')}:</b>
</Text>
<ul>
{partialExams.map((exam) => (
<Text key={exam}>
<li>
{' '}
{translateCommon(`enrollment.partialExamsAndSkills.${exam}`)}
</li>
</Text>
))}
</ul>
</div>
</>
);
};

export const ExamEventDetails = ({
enrollment,
clerkView = false,
}: {
enrollment: PublicEnrollment | ClerkEnrollment;
clerkView?: boolean;
}) => {
const { t } = usePublicTranslation({
keyPrefix: 'vkt.component.publicEnrollment.steps.preview',
});
const translateCommon = useCommonTranslation();
const { isPhone } = useWindowProperties();

return (
<div className="rows gapped">
<H2>{t('examEventDetails.title')}</H2>
{displaySkillsList()}
{displayExamsList()}
{isPhone && <PhoneSkillsAndExamsList enrollment={enrollment} />}
{!isPhone && (
<>
<DesktopSkillsList enrollment={enrollment} clerkView={!!clerkView} />
<DesktopExamsList enrollment={enrollment} />
</>
)}
{!clerkView && (
<div className="rows gapped-xxs">
<Text className="bold">
Expand Down

0 comments on commit 2554b41

Please sign in to comment.