From 663b256112e292ee88270638591821024d5e243a Mon Sep 17 00:00:00 2001 From: Luciano Giacchetta Date: Wed, 20 Aug 2025 17:59:45 -0300 Subject: [PATCH] #11 - Add total hours per career, per category and per course. --- src/libs/careers.ts | 44 ++++++++++++++++++- src/pages/carreras/[slug].astro | 2 +- .../career-program/career-program.astro | 32 +++++++++----- src/types/codyops-careers.ts | 2 + src/types/codyops-courses.ts | 2 + 5 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/libs/careers.ts b/src/libs/careers.ts index e8e2795..b688e5a 100644 --- a/src/libs/careers.ts +++ b/src/libs/careers.ts @@ -1,6 +1,7 @@ import directus from './directus'; import { readItems, type Query } from '@directus/sdk'; import type { CodyopsCareers, Careers } from '../types/codyops-careers'; +import { sumTimes } from '../utils/time'; export async function getCareers(): Promise { const careers = await directus.request( @@ -16,6 +17,11 @@ export async function getCareers(): Promise { 'name', 'level', 'category', + { + modules: [ + 'duration' + ] + } ], }, ], @@ -23,5 +29,41 @@ export async function getCareers(): Promise { ], }) ); - return careers; + + const careersWithCalculatedHours = careers.map(career => { + let totalCareerMinutes = 0; + + const coursesWithCalculatedHours = career.courses.map(courseItem => { + const course = courseItem.codyops_courses_id; + if (course && course.modules) { + const moduleDurations = course.modules + .map(module => module.duration) + .filter((duration): duration is string => duration !== undefined && duration !== null); // Filter out undefined/null + const { hours, minutes } = sumTimes(moduleDurations); + const totalCourseMinutes = (hours * 60) + minutes; + totalCareerMinutes += totalCourseMinutes; + return { + ...courseItem, + codyops_courses_id: { + ...course, + totalCourseHours: hours + (minutes / 60), // Store as decimal hours + totalCourseMinutes: totalCourseMinutes, + } + }; + } + return courseItem; + }); + + const totalCareerHours = Math.floor(totalCareerMinutes / 60); + const remainingCareerMinutes = totalCareerMinutes % 60; + + return { + ...career, + courses: coursesWithCalculatedHours, + totalCareerHours: totalCareerHours + (remainingCareerMinutes / 60), // Store as decimal hours + totalCareerMinutes: totalCareerMinutes, + }; + }); + + return careersWithCalculatedHours; } diff --git a/src/pages/carreras/[slug].astro b/src/pages/carreras/[slug].astro index 3b5d8e7..62e0548 100644 --- a/src/pages/carreras/[slug].astro +++ b/src/pages/carreras/[slug].astro @@ -48,7 +48,7 @@ const FeaturesComponent = (await import(`../../sections/${career.slug}/${career. - c.codyops_courses_id)} /> + diff --git a/src/sections/global/career-program/career-program.astro b/src/sections/global/career-program/career-program.astro index d088a84..4ab4f4d 100644 --- a/src/sections/global/career-program/career-program.astro +++ b/src/sections/global/career-program/career-program.astro @@ -1,29 +1,39 @@ --- import type { Courses } from '../../../types/codyops-courses'; +import type { Careers } from '../../../types/codyops-careers'; import { toSnakeCase, fromSnakeCase } from '../../../utils'; type Props = { - list?: Courses[]; + career: Careers; }; -const { list }: Props = Astro.props; +const { career }: Props = Astro.props; // Group courses by category -const groupedCourses = list?.reduce((acc, course) => { - const category = course.category; - if (!acc[category]) { - acc[category] = []; +const groupedCourses = career.courses?.reduce((acc, courseItem) => { + const course = courseItem.codyops_courses_id; + if (course) { + const category = course.category; + if (!acc[category]) { + acc[category] = { courses: [], totalCategoryMinutes: 0 }; + } + acc[category].courses.push(course); + if (course.totalCourseMinutes) { + acc[category].totalCategoryMinutes += course.totalCourseMinutes; + } } - acc[category].push(course); return acc; -}, {} as Record); +}, {} as Record); ---

Programa de Carrera

+
+ Total Carrera: {career.totalCareerHours?.toFixed(1)} horas +