-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Kuwait Theme: Activity Check-in component #2562
base: master
Are you sure you want to change the base?
Changes from all commits
159645c
07bcafb
ee4368c
9e14a60
9dd342b
f28ac57
4956ce9
3270e63
5bf2187
cb938ff
2ddffcd
c250894
3ee0a20
6f3d529
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,27 @@ | ||
import { PlhParentPointCounterComponent } from "./parent-point-counter/parent-point-counter.component"; | ||
import { PlhParentPointBoxComponent } from "./parent-point-box/parent-point-box.component"; | ||
import { PlhModuleListItemComponent } from "./plh-kids-kw/components/module-list-item/module-list-item.component"; | ||
import { PlhActivityCheckInComponent } from "./plh-kids-kw/components/activity-check-in/activity-check-in.component"; | ||
|
||
export { PlhParentPointCounterComponent, PlhParentPointBoxComponent, PlhModuleListItemComponent }; | ||
export { | ||
PlhParentPointCounterComponent, | ||
PlhParentPointBoxComponent, | ||
PlhModuleListItemComponent, | ||
PlhActivityCheckInComponent, | ||
}; | ||
|
||
export const PLH_COMPONENTS = [ | ||
PlhParentPointCounterComponent, | ||
PlhParentPointBoxComponent, | ||
PlhModuleListItemComponent, | ||
PlhActivityCheckInComponent, | ||
]; | ||
|
||
export const PLH_COMPONENT_MAPPING = { | ||
parent_point_counter: PlhParentPointCounterComponent, | ||
parent_point_box: PlhParentPointBoxComponent, | ||
plh_module_list_item: PlhModuleListItemComponent, | ||
plh_activity_check_in: PlhActivityCheckInComponent, | ||
}; | ||
|
||
export type PLHComponentName = keyof typeof PLH_COMPONENT_MAPPING; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
@if (daysLeft >= 1) { | ||
<div | ||
class="activity-container" | ||
[attr.data-language-direction]="templateTranslateService.languageDirection()" | ||
> | ||
<div class="wrapper"> | ||
<div class="progress-tracker"> | ||
<div class="wrapper"> | ||
<div class="progress-bar-container"> | ||
<div | ||
class="progress-bar" | ||
[ngStyle]="{ | ||
width: progressPercentage + '%' | ||
}" | ||
></div> | ||
</div> | ||
</div> | ||
<div class="countdown-text">In {{ daysLeft }} day{{ daysLeft > 1 ? "s" : "" }}</div> | ||
</div> | ||
|
||
<div class="image"> | ||
<img [src]="params.lockedImageAsset | plhAsset" /> | ||
</div> | ||
<div class="details"> | ||
<div class="title"> | ||
<h4>{{ params.title }}</h4> | ||
</div> | ||
<div class="icon"> | ||
<img [src]="params.lockedIconAsset | plhAsset" /> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
} @else { | ||
<div class="activity-container"> | ||
<div class="wrapper unlocked"> | ||
<div class="image"> | ||
<img [src]="params.unlockedImageAsset | plhAsset" /> | ||
</div> | ||
<div class="details"> | ||
<div class="title"> | ||
<h4>{{ params.title }}</h4> | ||
</div> | ||
<div class="icon"> | ||
<img [src]="params.unlockedIconAsset | plhAsset" /> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; | ||
import { IonicModule } from "@ionic/angular"; | ||
|
||
import { PlhActivityCheckInComponent } from "./activity-check-in.component"; | ||
|
||
describe("ActivityCheckInComponent", () => { | ||
let component: PlhActivityCheckInComponent; | ||
let fixture: ComponentFixture<PlhActivityCheckInComponent>; | ||
|
||
beforeEach(waitForAsync(() => { | ||
TestBed.configureTestingModule({ | ||
declarations: [PlhActivityCheckInComponent], | ||
imports: [IonicModule.forRoot()], | ||
}).compileComponents(); | ||
|
||
fixture = TestBed.createComponent(PlhActivityCheckInComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
})); | ||
|
||
it("should create", () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { Component, OnInit } from "@angular/core"; | ||
import { TemplateBaseComponent } from "src/app/shared/components/template/components/base"; | ||
import { TemplateTranslateService } from "src/app/shared/components/template/services/template-translate.service"; | ||
import { getNumberParamFromTemplateRow, getStringParamFromTemplateRow } from "src/app/shared/utils"; | ||
|
||
interface IActivityCheckInParams { | ||
/* TEMPLATE PARAMETER: "activity_id". The activity identifier attached at the bottom of the component */ | ||
id: string; | ||
/* TEMPLATE PARAMETER: "title". The title attached at the bottom of the component */ | ||
title?: string; | ||
/* TEMPLATE PARAMETER: "locked_icon_asset". The icon that shows when the activity is locked */ | ||
lockedIconAsset?: string; | ||
/* TEMPLATE PARAMETER: "locked_image_asset". The illustration that shows when the activity is locked */ | ||
lockedImageAsset?: string; | ||
/* TEMPLATE PARAMETER: "unlocked_icon_asset". The icon that shows when the activity is unlocked */ | ||
unlockedIconAsset?: string; | ||
/* TEMPLATE PARAMETER: "unlocked_image_asset". The illustration that shows when the activity is locked */ | ||
unlockedImageAsset?: string; | ||
/* TEMPLATE PARAMETER: "days_to_count_down". The illustration that shows when the activity is locked */ | ||
countDownDays?: number; | ||
} | ||
|
||
@Component({ | ||
selector: "plh-activity-check-in", | ||
templateUrl: "./activity-check-in.component.html", | ||
styleUrls: ["./activity-check-in.component.scss"], | ||
}) | ||
export class PlhActivityCheckInComponent extends TemplateBaseComponent implements OnInit { | ||
params: Partial<IActivityCheckInParams> = {}; | ||
|
||
daysLeft: number; // Progress of days left | ||
progressPercentage: number = 16; // Initial progress | ||
|
||
private unlockDate: Date; | ||
|
||
constructor(public templateTranslateService: TemplateTranslateService) { | ||
super(); | ||
} | ||
|
||
ngOnInit() { | ||
this.getParams(); | ||
this.daysLeft = this.params.countDownDays; | ||
if (this._row.value) { | ||
this.checkInTimer(); | ||
} | ||
} | ||
|
||
private getParams() { | ||
this.params.id = getStringParamFromTemplateRow(this._row, "activity_id", null); | ||
this.params.title = getStringParamFromTemplateRow(this._row, "title", null); | ||
this.params.lockedIconAsset = getStringParamFromTemplateRow( | ||
this._row, | ||
"locked_icon_asset", | ||
null | ||
); | ||
this.params.lockedImageAsset = getStringParamFromTemplateRow( | ||
this._row, | ||
"locked_image_asset", | ||
null | ||
); | ||
this.params.unlockedIconAsset = getStringParamFromTemplateRow( | ||
this._row, | ||
"unlocked_icon_asset", | ||
null | ||
); | ||
this.params.unlockedImageAsset = getStringParamFromTemplateRow( | ||
this._row, | ||
"unlocked_image_asset", | ||
null | ||
); | ||
this.params.countDownDays = getNumberParamFromTemplateRow(this._row, "days_to_count_down", 6); | ||
} | ||
|
||
private getLocalStorageKey(): string { | ||
return `activity_${this.params.id}`; | ||
} | ||
|
||
// Calculates the days until check in | ||
private checkInTimer() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This logic will need to be reworked to handle how we actually plan on managing the unlock dates of the various activities. @esmeetewinkel, is that something we should discuss in our next meeting? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes let's discuss in our next meeting. My initial thoughts are in my comment below |
||
const localStorageKey = this.getLocalStorageKey(); | ||
const storedDate = localStorage.getItem(localStorageKey); | ||
if (storedDate) { | ||
this.unlockDate = new Date(storedDate); | ||
} else { | ||
this.unlockDate = this.getMidnightOfDate(new Date()); | ||
this.unlockDate.setDate(this.unlockDate.getDate() + this.params.countDownDays); | ||
localStorage.setItem(localStorageKey, this.unlockDate.toISOString()); | ||
} | ||
const dailyInterval = this.getMillisecondsUntilMidnight(); // Count until midnight | ||
setTimeout(() => { | ||
this.updateProgress(); | ||
setInterval(() => this.updateProgress(), 24 * 60 * 60 * 1000); | ||
}, dailyInterval); | ||
} | ||
|
||
// Update the progress bar and unlock state | ||
private updateProgress(): void { | ||
const now = this.getMidnightOfDate(new Date()); | ||
this.daysLeft = this.unlockDate.getTime() - now.getTime(); | ||
|
||
if (now < this.unlockDate) { | ||
this.daysLeft = Math.ceil( | ||
(this.unlockDate.getTime() - now.getTime()) / (24 * 60 * 60 * 1000) | ||
); | ||
this.progressPercentage = | ||
((this.params.countDownDays - this.daysLeft) / this.params.countDownDays) * 100; | ||
} else { | ||
this.progressPercentage = 16; | ||
localStorage.removeItem(this.getLocalStorageKey()); | ||
} | ||
} | ||
|
||
// Get the number of milliseconds until midnight. | ||
private getMillisecondsUntilMidnight(): number { | ||
const now = new Date(); | ||
const midnight = this.getMidnightOfDate(now); | ||
midnight.setDate(midnight.getDate() + 1); | ||
return midnight.getTime() - now.getTime(); | ||
} | ||
|
||
// Get the midnight of a given date. | ||
private getMidnightOfDate(date: Date): Date { | ||
const midnight = new Date(date); | ||
midnight.setHours(0, 0, 0, 0); | ||
return midnight; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be renamed
activity_id
to improve clarity for authors