#11 - Add total hours per career, per category and per course.

This commit is contained in:
Luciano Giacchetta 2025-08-20 17:59:45 -03:00
parent 3fa78d78c8
commit 663b256112
5 changed files with 69 additions and 13 deletions

View File

@ -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<Careers[]> {
const careers = await directus.request(
@ -16,6 +17,11 @@ export async function getCareers(): Promise<Careers[]> {
'name',
'level',
'category',
{
modules: [
'duration'
]
}
],
},
],
@ -23,5 +29,41 @@ export async function getCareers(): Promise<Careers[]> {
],
})
);
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;
}

View File

@ -48,7 +48,7 @@ const FeaturesComponent = (await import(`../../sections/${career.slug}/${career.
<DescriptionComponent />
</CareerSection>
<Cta />
<CareerProgram list={career.courses.map(c => c.codyops_courses_id)} />
<CareerProgram career={career} />
<Cta />
</Main>
</Root>

View File

@ -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<string, Courses[]>);
}, {} as Record<string, { courses: Courses[]; totalCategoryMinutes: number }>);
---
<section id="program" class="container content-space-t-3 career__section">
<h2 class="career-subtitle text-white text-center mb-5">Programa de Carrera</h2>
<div class="text-center text-white mb-4">
Total Carrera: {career.totalCareerHours?.toFixed(1)} horas
</div>
<div class="accordion accordion-btn-icon-start">
{groupedCourses && Object.entries(groupedCourses).map(([category, courses]) => (
{groupedCourses && Object.entries(groupedCourses).map(([category, { courses, totalCategoryMinutes }]) => (
<div class="accordion-item">
<div class="accordion-header" id={`heading-${toSnakeCase(category)}`}>
<a
@ -46,7 +56,7 @@ const groupedCourses = list?.reduce((acc, course) => {
<!-- End Col -->
<div class="col-lg-6">
{/* Hours will be calculated and displayed here if needed */}
<span class="small text-white">{(totalCategoryMinutes / 60).toFixed(1)} hours</span>
</div>
<!-- End Col -->
</div>
@ -87,7 +97,7 @@ const groupedCourses = list?.reduce((acc, course) => {
<!-- End Col -->
<div class="col-lg-6">
{/* Hours will be displayed here if needed */}
<span class="small text-white">{course.totalCourseHours?.toFixed(1)} hours</span>
</div>
<!-- End Col -->
</div>

View File

@ -15,6 +15,8 @@ export interface Careers {
courses: {
codyops_courses_id: Courses;
}[];
totalCareerHours?: number;
totalCareerMinutes?: number;
}
export interface CodyopsCareers {

View File

@ -25,6 +25,8 @@ export interface Courses {
codyops_careers?: {
codyops_careers_id?: Partial<Careers>;
};
totalCourseHours?: number;
totalCourseMinutes?: number;
}
export interface CodyopsCourses {