diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b7dbc73..13361f3 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -11,4 +11,9 @@ import { CalendarComponent } from "./calendar/calendar.component"; }) export class AppComponent { title = 'runningPlans'; + + ngOnInit(): void { + + + } } diff --git a/src/app/calendar/calendar.component.html b/src/app/calendar/calendar.component.html index 4f9c5f9..3347821 100644 --- a/src/app/calendar/calendar.component.html +++ b/src/app/calendar/calendar.component.html @@ -2,6 +2,7 @@ + @@ -9,21 +10,22 @@ - - @for (planWeek of examplePlan.planDetials; track $index) { + @for (planWeek of examplePlan.planDetials; track planWeek.week; let i = $index) { - - @for (workout of planWeek.workouts; track $index) { - + @for (workout of planWeek.workouts; track workout.day; let j = $index) { + } - + }
WeekTotal Milage Monday Tuesday WednesdayFriday Saturday SundayTotal Milage
+
Week {{planWeek.week}}
+ {{planWeek.totalMilage}}
{{workout.type}}
{{workout.totalDistance == 0 ? '' : workout.totalDistance + ' miles'}}
{{workout.description}}
{{planWeek.totalMilage}}
diff --git a/src/app/calendar/calendar.component.scss b/src/app/calendar/calendar.component.scss index fb1566a..f75abae 100644 --- a/src/app/calendar/calendar.component.scss +++ b/src/app/calendar/calendar.component.scss @@ -42,4 +42,8 @@ td { } .completedWorkout:hover { background-color: rgb(89, 161, 89); +} + +.completedWeek { + background-color: rgb(107, 194, 107); } \ No newline at end of file diff --git a/src/app/calendar/calendar.component.ts b/src/app/calendar/calendar.component.ts index 924e894..957c3ef 100644 --- a/src/app/calendar/calendar.component.ts +++ b/src/app/calendar/calendar.component.ts @@ -1,27 +1,45 @@ import { Component } from '@angular/core'; import { examplePlan } from '../testData/examplePlan'; import { Plan } from '../models/plan.model'; +import { CommonModule } from "@angular/common"; +import { Status } from '../models/workout.model'; @Component({ selector: 'calendar', standalone: true, - imports: [], + imports: [CommonModule], templateUrl: './calendar.component.html', styleUrl: './calendar.component.scss' }) export class CalendarComponent { examplePlan: Plan = examplePlan; + status = Status; ngOnInit(): void { } - onCellClick(event: Event) { - const target = event.currentTarget as HTMLElement; - if (target.classList.contains('incompleteWorkout')) { - target.classList.replace('incompleteWorkout', 'completedWorkout') - } else if (target.classList.contains('completedWorkout')) { - target.classList.replace('completedWorkout', 'incompleteWorkout') + onCellClick(weekNum: number, dayNum: number) { + let status = examplePlan.planDetials[weekNum].workouts[dayNum].status + if (status === Status.Incomplete) { + examplePlan.planDetials[weekNum].workouts[dayNum].status = Status.Complete + } else if (status === Status.Complete) { + examplePlan.planDetials[weekNum].workouts[dayNum].status = Status.Incomplete + } + this.checkCompletedWeek(weekNum) + } + + checkCompletedWeek(weekNum: number) { + let completeCount = 0; + examplePlan.planDetials[weekNum].workouts.forEach(workout => { + if (workout.status === Status.Complete) { + completeCount++ + } + }) + if (completeCount === 7) { + examplePlan.planDetials[weekNum].status = Status.Complete + } else { + examplePlan.planDetials[weekNum].status = Status.Incomplete } } } diff --git a/src/app/models/plan.model.ts b/src/app/models/plan.model.ts index 73743d8..17e07b5 100644 --- a/src/app/models/plan.model.ts +++ b/src/app/models/plan.model.ts @@ -12,5 +12,12 @@ export interface Plan { export interface Week { week: number, totalMilage: number, + status: Status, workouts: Workout[] +} + +export enum Status { + Complete = 'complete', + Incomplete = 'incomplete', + Skipped = 'skipped' } \ No newline at end of file diff --git a/src/app/models/workout.model.ts b/src/app/models/workout.model.ts index 91c1a2d..71419a4 100644 --- a/src/app/models/workout.model.ts +++ b/src/app/models/workout.model.ts @@ -2,7 +2,8 @@ export interface Workout { day: number, type: WorkoutType, totalDistance: number, - description: string + description: string, + status: Status } export enum WorkoutType { @@ -16,4 +17,10 @@ export enum WorkoutType { GeneralAerobic = "General Aerobic", Recovery = "Recovery", Rest = "Rest or Crosstrain" +} + +export enum Status { + Complete = 'complete', + Incomplete = 'incomplete', + Skipped = 'skipped' } \ No newline at end of file diff --git a/src/app/testData/examplePlan.ts b/src/app/testData/examplePlan.ts index 2428740..1e2ef60 100644 --- a/src/app/testData/examplePlan.ts +++ b/src/app/testData/examplePlan.ts @@ -1,5 +1,5 @@ import { Plan } from "../models/plan.model"; -import { Workout, WorkoutType } from "../models/workout.model"; +import { Status, Workout, WorkoutType } from "../models/workout.model"; export const examplePlan: Plan = { name: 'Pfitz 18/55', @@ -11,864 +11,1008 @@ export const examplePlan: Plan = { { week: 1, totalMilage: 31, + status: Status.Complete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Complete }, { day: 1, type: WorkoutType.Threshold, totalDistance: 8, - description: '20-25 min LT' + description: '20-25 min LT', + status: Status.Complete }, { day: 2, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Complete }, { day: 3, type: WorkoutType.GeneralAerobic, totalDistance: 8, - description: '' + description: '', + status: Status.Complete }, { day: 4, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Complete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Complete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 11, - description: '' + description: '', + status: Status.Complete } ] }, { week: 2, totalMilage: 33, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.GeneralAerobic, totalDistance: 8, - description: '6 x 10s Hills, 8 x 100m strides' + description: '6 x 10s Hills, 8 x 100m strides', + status: Status.Incomplete }, { day: 2, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 3, type: WorkoutType.GeneralAerobic, totalDistance: 9, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.MarathonPaceLongRun, totalDistance: 12, - description: '8 mi @ marathon pace' + description: '8 mi @ marathon pace', + status: Status.Incomplete } ] }, { week: 3, totalMilage: 39, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.GeneralAerobic, totalDistance: 9, - description: '' + description: '', + status: Status.Incomplete }, { day: 2, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Threshold, totalDistance: 8, - description: '25-30 min LT' + description: '25-30 min LT', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 14, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 4, totalMilage: 40, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.GeneralAerobic, totalDistance: 8, - description: '6 x 10s Hills, 8 x 100m strides' + description: '6 x 10s Hills, 8 x 100m strides', + status: Status.Incomplete }, { day: 2, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 3, type: WorkoutType.GeneralAerobic, totalDistance: 9, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 15, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 5, totalMilage: 42, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.Threshold, totalDistance: 9, - description: '30-35 min LT' + description: '30-35 min LT', + status: Status.Incomplete }, { day: 2, type: WorkoutType.Recovery, totalDistance: 5, - description: '' + description: '', + status: Status.Incomplete }, { day: 3, type: WorkoutType.GeneralAerobic, totalDistance: 9, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.MarathonPaceLongRun, totalDistance: 15, - description: '10 mi @ marathon pace' + description: '10 mi @ marathon pace', + status: Status.Incomplete } ] }, { week: 6, totalMilage: 33, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.GeneralAerobic, totalDistance: 7, - description: '10 x 100m strides' + description: '10 x 100m strides', + status: Status.Incomplete }, { day: 2, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 3, type: WorkoutType.GeneralAerobic, totalDistance: 7, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 11, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 7, totalMilage: 48, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.Threshold, totalDistance: 9, - description: '30-35 min LT' + description: '30-35 min LT', + status: Status.Incomplete }, { day: 2, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 3, type: WorkoutType.MediumLongRun, totalDistance: 11, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.GeneralAerobic, totalDistance: 7, - description: '6 x 10s Hills, 8 x 100m strides' + description: '6 x 10s Hills, 8 x 100m strides', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 17, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 8, totalMilage: 51, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.Recovery, totalDistance: 6, - description: '6x100 strides' + description: '6x100 strides', + status: Status.Incomplete }, { day: 2, type: WorkoutType.MediumLongRun, totalDistance: 12, - description: '' + description: '', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Threshold, totalDistance: 10, - description: '35-40 min LT' + description: '35-40 min LT', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 19, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 9, totalMilage: 46, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.Recovery, totalDistance: 6, - description: '' + description: '', + status: Status.Incomplete }, { day: 2, type: WorkoutType.MediumLongRun, totalDistance: 13, - description: '' + description: '', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Recovery, totalDistance: 6, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 5, - description: '6x100 strides' + description: '6x100 strides', + status: Status.Incomplete }, { day: 6, type: WorkoutType.MarathonPaceLongRun, totalDistance: 16, - description: '12 mi @ marathon pace' + description: '12 mi @ marathon pace', + status: Status.Incomplete } ] }, { week: 10, totalMilage: 40, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.GeneralAerobic, totalDistance: 8, - description: '' + description: '', + status: Status.Incomplete }, { day: 2, type: WorkoutType.VO2Max, totalDistance: 8, - description: '6 x 600m @ 5K pace' + description: '6 x 600m @ 5K pace', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.GeneralAerobic, totalDistance: 7, - description: '6 x 10s Hills, 8 x 100m strides' + description: '6 x 10s Hills, 8 x 100m strides', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 13, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 11, totalMilage: 52, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.Recovery, totalDistance: 6, - description: '6x100 strides' + description: '6x100 strides', + status: Status.Incomplete }, { day: 2, type: WorkoutType.Threshold, totalDistance: 11, - description: '35-45 min LT' + description: '35-45 min LT', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.MediumLongRun, totalDistance: 12, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 19, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 12, totalMilage: 48, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.GeneralAerobic, totalDistance: 10, - description: '' + description: '', + status: Status.Incomplete }, { day: 2, type: WorkoutType.VO2Max, totalDistance: 8, - description: '5 x 600m @ 5K pace' + description: '5 x 600m @ 5K pace', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Recovery, totalDistance: 4, - description: '6x100 strides' + description: '6x100 strides', + status: Status.Incomplete }, { day: 5, type: WorkoutType.VO2Max, totalDistance: 10, - description: '8K-15K Tune Up' + description: '8K-15K Tune Up', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 16, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 13, totalMilage: 48, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.Recovery, totalDistance: 6, - description: '' + description: '', + status: Status.Incomplete }, { day: 2, type: WorkoutType.VO2Max, totalDistance: 9, - description: '5 x 1000m @ 5K pace' + description: '5 x 1000m @ 5K pace', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.MediumLongRun, totalDistance: 11, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 5, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.MarathonPaceLongRun, totalDistance: 17, - description: '14 mi @ marathon pace' + description: '14 mi @ marathon pace', + status: Status.Incomplete } ] }, { week: 14, totalMilage: 48, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.GeneralAerobic, totalDistance: 10, - description: '' + description: '', + status: Status.Incomplete }, { day: 2, type: WorkoutType.VO2Max, totalDistance: 8, - description: '5 x 600m @ 5K pace' + description: '5 x 600m @ 5K pace', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Recovery, totalDistance: 4, - description: '6x100 strides' + description: '6x100 strides', + status: Status.Incomplete }, { day: 5, type: WorkoutType.VO2Max, totalDistance: 10, - description: '8K-15K Tune Up' + description: '8K-15K Tune Up', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 16, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 15, totalMilage: 49, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.Recovery, totalDistance: 6, - description: '' + description: '', + status: Status.Incomplete }, { day: 2, type: WorkoutType.VO2Max, totalDistance: 9, - description: '5 x 1000m @ 5K pace' + description: '5 x 1000m @ 5K pace', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.MediumLongRun, totalDistance: 11, - description: '' + description: '', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 4, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 19, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 16, totalMilage: 41, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.GeneralAerobic, totalDistance: 7, - description: '6 x 10s Hills, 10 x 100m strides' + description: '6 x 10s Hills, 10 x 100m strides', + status: Status.Incomplete }, { day: 2, type: WorkoutType.Recovery, totalDistance: 5, - description: '' + description: '', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Recovery, totalDistance: 4, - description: '4-5 mi w/ 6x100 strides' + description: '4-5 mi w/ 6x100 strides', + status: Status.Incomplete }, { day: 5, type: WorkoutType.VO2Max, totalDistance: 9, - description: '8K-10K Tune Up' + description: '8K-10K Tune Up', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 16, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 17, totalMilage: 31, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.Recovery, totalDistance: 6, - description: '8x100 strides' + description: '8x100 strides', + status: Status.Incomplete }, { day: 2, type: WorkoutType.VO2Max, totalDistance: 8, - description: '5 x 1000m @ 5K pace' + description: '5 x 1000m @ 5K pace', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Recovery, totalDistance: 5, - description: '6x100 strides' + description: '6x100 strides', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.LongRun, totalDistance: 12, - description: '' + description: '', + status: Status.Incomplete } ] }, { week: 18, totalMilage: 16, + status: Status.Incomplete, workouts: [ { day: 0, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 1, type: WorkoutType.Recovery, totalDistance: 5, - description: '8x100 strides' + description: '8x100 strides', + status: Status.Incomplete }, { day: 2, type: WorkoutType.DressRehersal, totalDistance: 5, - description: '2 mi @ marathon pace' + description: '2 mi @ marathon pace', + status: Status.Incomplete }, { day: 3, type: WorkoutType.Rest, totalDistance: 0, - description: '' + description: '', + status: Status.Incomplete }, { day: 4, type: WorkoutType.Recovery, totalDistance: 4, - description: '6x100 strides' + description: '6x100 strides', + status: Status.Incomplete }, { day: 5, type: WorkoutType.Recovery, totalDistance: 2, - description: '' + description: '', + status: Status.Incomplete }, { day: 6, type: WorkoutType.RaceDay, totalDistance: 26.2, - description: '' + description: '', + status: Status.Incomplete } ] }