Skip to content

Commit

Permalink
fix: diploma creation for existing programs
Browse files Browse the repository at this point in the history
  • Loading branch information
DJ1TJOO committed Aug 16, 2024
1 parent 269bd4e commit 8b45604
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"use server";

import { listCurriculaByProgram, listGearTypesByCurriculum } from "~/lib/nwd";
import {
listCompletedCompetenciesByStudentCurriculumId,
listCurriculaByProgram,
listGearTypesByCurriculum,
retrieveStudentCurriculumByPersonIdAndCurriculumId,
} from "~/lib/nwd";

export async function getCurriculaByProgram(programId: string) {
return await listCurriculaByProgram(programId, true);
Expand All @@ -9,3 +14,25 @@ export async function getCurriculaByProgram(programId: string) {
export async function getGearTypesByCurriculum(curriculumId: string) {
return await listGearTypesByCurriculum(curriculumId);
}

export async function getCompletedCompetencies(
personId: string,
curriculumId: string,
gearTypeId: string,
) {
const studentCurriculum =
await retrieveStudentCurriculumByPersonIdAndCurriculumId(
personId,
curriculumId,
gearTypeId,
);

if (!studentCurriculum) {
return null;
}

const completedCompetencies =
await listCompletedCompetenciesByStudentCurriculumId(studentCurriculum.id);

return completedCompetencies.map((cc) => cc.competencyId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import type {
} from "~/lib/nwd";
import { createCertificate } from "../_actions/create";
import {
getCompletedCompetencies,
getCurriculaByProgram,
getGearTypesByCurriculum,
} from "../_actions/fetch";
Expand Down Expand Up @@ -93,16 +94,26 @@ function CreateDialogClient({
setIsOpen(false);
}

if (result.message === "Error" && Object.keys(result.errors).length < 1) {
toast.error("Er is iets misgegaan");
}

return result;
};

const [state, formAction] = useActionState(submit, undefined);

const [selectedPerson, setSelectedPerson] = useState<
(typeof persons)[number] | null
>(null);
const [selectedProgram, setSelectedProgram] = useState<string | null>(null);
const [selectedGearType, setSelectedGearType] = useState<string | null>(null);
const [selectedCurriculum, setSelectedCurriculum] = useState<
Awaited<ReturnType<typeof listCurriculaByProgram>>[number] | null
>(null);
const [completedCompetencies, setCompletedCompetencies] = useState<Awaited<
ReturnType<typeof getCompletedCompetencies>
> | null>(null);

const [programQuery, setProgramQuery] = useState("");
const [personQuery, setPersonQuery] = useState("");
Expand Down Expand Up @@ -131,6 +142,7 @@ function CreateDialogClient({
const [curriculum] = await getCurriculaByProgram(selectedProgram);

if (!curriculum) {
setCompletedCompetencies(null);
setSelectedCurriculum(null);
setGearTypes([]);
return;
Expand All @@ -144,6 +156,24 @@ function CreateDialogClient({
void fetchCurricula();
}, [selectedProgram]);

useEffect(() => {
async function fetchCompletedCompetencies() {
if (!selectedPerson || !selectedCurriculum || !selectedGearType) {
return;
}

const completedCompetencies = await getCompletedCompetencies(
selectedPerson.id,
selectedCurriculum.id,
selectedGearType,
);

setCompletedCompetencies(completedCompetencies ?? []);
}

void fetchCompletedCompetencies();
}, [selectedPerson, selectedCurriculum, selectedGearType]);

return (
<>
<Button
Expand Down Expand Up @@ -171,6 +201,8 @@ function CreateDialogClient({
onClose={() => setPersonQuery("")}
virtual={{ options: filteredPersons }}
multiple={false}
value={selectedPerson}
onChange={(value) => setSelectedPerson(value)}
>
<div
className={clsx([
Expand Down Expand Up @@ -369,6 +401,7 @@ function CreateDialogClient({
setSelectedGearType(null);
setGearTypes([]);
setSelectedCurriculum(null);
setCompletedCompetencies(null);
}}
invalid={!!state?.errors.curriculumId}
>
Expand Down Expand Up @@ -414,15 +447,20 @@ function CreateDialogClient({

<Fieldset>
<Legend>Modules</Legend>
{selectedCurriculum ? (
{selectedCurriculum && completedCompetencies !== null ? (
<div className="grid grid-cols-1 lg:grid-cols-2 mt-2 gap-x-4">
<CheckboxGroup>
<Legend>Kernmodules</Legend>
{selectedCurriculum.modules
.sort((a, b) => a.weight - b.weight)
.filter((module) => module.isRequired)
.map((module) => (
<CheckboxField key={module.id}>
<CheckboxField
key={module.id}
disabled={module.competencies.every((c) =>
completedCompetencies?.includes(c.id),
)}
>
<Checkbox
name="competencies[]"
value={module.competencies
Expand Down
24 changes: 19 additions & 5 deletions apps/web/src/lib/nwd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -746,11 +746,13 @@ export const createCompletedCertificate = async (
});

// Start student curriculum
const { id: studentCurriculumId } = await Student.Curriculum.start({
curriculumId,
personId,
gearTypeId,
});
const { id: studentCurriculumId } = await Student.Curriculum.findOrEnroll(
{
curriculumId,
personId,
gearTypeId,
},
);

// Start certificate
const { id: certificateId } = await Student.Certificate.startCertificate({
Expand Down Expand Up @@ -1341,6 +1343,18 @@ export const retrieveStudentAllocationWithCurriculumForPerson = cache(
},
);

export const retrieveStudentCurriculumByPersonIdAndCurriculumId = cache(
async (personId: string, curriculumId: string, gearTypeId: string) => {
return makeRequest(async () => {
return await Student.Curriculum.find({
personId,
curriculumId,
gearTypeId,
});
});
},
);

export const listCompletedCompetenciesByStudentCurriculumId = cache(
async (studentCurriculumId: string) => {
return makeRequest(async () => {
Expand Down
27 changes: 27 additions & 0 deletions packages/core/src/models/student/curriculum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,33 @@ export const start = withZod(
},
)

export const find = withZod(
insertSchema.pick({
personId: true,
curriculumId: true,
gearTypeId: true,
}),
successfulCreateResponse.nullable(),
async (input) => {
const query = useQuery()

const studentCurriculum = await query
.select({ id: s.studentCurriculum.id })
.from(s.studentCurriculum)
.where(
and(
eq(s.studentCurriculum.personId, input.personId),
eq(s.studentCurriculum.curriculumId, input.curriculumId),
eq(s.studentCurriculum.gearTypeId, input.gearTypeId),
isNull(s.studentCurriculum.deletedAt),
),
)
.then(possibleSingleRow)

return studentCurriculum ?? null
},
)

export const findOrEnroll = withZod(
insertSchema.pick({
personId: true,
Expand Down

0 comments on commit 8b45604

Please sign in to comment.