Skip to content

Commit

Permalink
Merge pull request #2562 from IDEMSInternational/feature-kw-check-in-…
Browse files Browse the repository at this point in the history
…component

Kuwait Theme: Activity Check-in component
  • Loading branch information
jfmcquade authored Jan 3, 2025
2 parents 6af7ee8 + 2f7d62f commit 87fe053
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 2 deletions.
4 changes: 4 additions & 0 deletions packages/components/plh/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
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";
import { PlhCompletionModalComponent } from "./plh-kids-kw/components/completion-modal/completion-modal.component";
import { PlhModuleDetailsHeaderComponent } from "./plh-kids-kw/components/module-details-header/module-details-header.component";
import { PlhBottomNavigationBarComponent } from "./plh-kids-kw/components/bottom-navigation-bar/bottom-navigation-bar.component";
Expand All @@ -9,6 +10,7 @@ export {
PlhParentPointCounterComponent,
PlhParentPointBoxComponent,
PlhModuleListItemComponent,
PlhActivityCheckInComponent,
PlhCompletionModalComponent,
PlhModuleDetailsHeaderComponent,
PlhBottomNavigationBarComponent,
Expand All @@ -18,6 +20,7 @@ export const PLH_COMPONENTS = [
PlhParentPointCounterComponent,
PlhParentPointBoxComponent,
PlhModuleListItemComponent,
PlhActivityCheckInComponent,
PlhCompletionModalComponent,
PlhModuleDetailsHeaderComponent,
PlhBottomNavigationBarComponent,
Expand All @@ -28,6 +31,7 @@ export const PLH_COMPONENT_MAPPING = {
parent_point_box: PlhParentPointBoxComponent,
plh_module_details_header: PlhModuleDetailsHeaderComponent,
plh_module_list_item: PlhModuleListItemComponent,
plh_activity_check_in: PlhActivityCheckInComponent,
plh_completion_modal: PlhCompletionModalComponent,
plh_bottom_nav: PlhBottomNavigationBarComponent,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@if (locked()) {
<div
class="activity-container"
[attr.data-language-direction]="templateTranslateService.languageDirection()"
>
@if (params.countdownStartDate) {
<div class="progress-tracker">
<div class="progress-bar-container">
<div
class="progress-bar"
[ngStyle]="{
width: progressPercentage() + '%'
}"
></div>
</div>
<div class="countdown-text">{{ countdownText() }}</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>
} @else {
<div
class="activity-container"
(click)="triggerActions('click')"
[attr.data-language-direction]="templateTranslateService.languageDirection()"
>
<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,85 @@
.activity-container {
max-width: 168px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.progress-tracker {
width: 100%;
padding: 0 12px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.progress-bar-container {
width: 40%;
background-color: var(--ion-color-gray-200);
height: 14px;
border-radius: 50px;
overflow: hidden;
.progress-bar {
border-radius: 50px;
height: 100%;
background-color: #e0b160;
transition:
width 0.5s ease,
background-color 0.5s ease;
}
}
.countdown-text {
margin-left: 8px;
color: var(--ion-color-gray-600);
font-weight: var(--font-weight-medium);
}
}
.image {
height: 150px;
img {
padding: 4px;
height: 100%;
width: 100%;
object-fit: contain;
}
}
.details {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
width: fit-content;
margin: 0 auto;
.title h4 {
text-align: center;
color: var(--ion-color-gray-600);
font-weight: var(--font-weight-bold);
}
.icon {
display: flex;
align-items: center;
margin: 0 4px;
img {
width: 28px;
}
}
}
}
.activity-container[data-language-direction~="rtl"] {
.progress-tracker {
.progress-bar-container {
margin-right: 0;
margin-left: 6px;
}
}
.image {
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
}
.details {
.icon {
img {
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
}
}
}
}
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,124 @@
import { Component, computed, OnInit, signal } from "@angular/core";
import { addDays, differenceInCalendarDays, isValid, parseISO, startOfDay } from "date-fns";
import { TemplateBaseComponent } from "src/app/shared/components/template/components/base";
import { TemplateTranslateService } from "src/app/shared/components/template/services/template-translate.service";
import {
getNumberParamFromTemplateRow,
getParamFromTemplateRow,
getStringParamFromTemplateRow,
} from "src/app/shared/utils";

interface IActivityCheckInParams {
/* 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: "countdown_start_date". The date when the countdown is initially started */
countdownStartDate?: Date;
/* TEMPLATE PARAMETER: "countdown_days". The number of days after the start date that the activity is unlocked */
countDownDays?: number;
/* TEMPLATE PARAMETER: "countdown_text_list". A list of text strings relating to the number of days left to countdown, in order from fewest to most */
countdownTextList?: string[];
}

@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> = {};

daysUntilUnlock = signal(Infinity);
locked = computed(() => {
// If no start date is provided, activity should be locked
if (!this.params.countdownStartDate) return true;
return this.daysUntilUnlock() && this.daysUntilUnlock() > 0;
});
countdownText = computed(() => {
const targetIndex = Math.min(
this.daysUntilUnlock() - 1,
this.params.countdownTextList.length - 1
);
return this.params.countdownTextList[targetIndex];
});
progressPercentage = computed(() => {
if (this.daysUntilUnlock() === Infinity) return 0;
return (
((this.params.countDownDays - (this.daysUntilUnlock() || 0)) / this.params.countDownDays) *
100
);
});

constructor(public templateTranslateService: TemplateTranslateService) {
super();
}

ngOnInit() {
this.getParams();
this.calculateDaysUntilUnlock();
}

private getParams() {
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, "countdown_days", 6);
const countdownStartDate = getParamFromTemplateRow(this._row, "countdown_start_date", null);
let parsedDate = null;
if (countdownStartDate) {
const attemptDate = new Date(countdownStartDate);
if (isValid(attemptDate)) {
parsedDate = attemptDate;
} else {
const attemptISO = parseISO(countdownStartDate);
if (isValid(attemptISO)) {
parsedDate = attemptISO;
}
}
}
this.params.countdownStartDate = parsedDate;

let countdownTextList = getParamFromTemplateRow(this._row, "countdown_text_list", []);
if (typeof countdownTextList === "string") {
countdownTextList = countdownTextList.split(",").map((text) => text.trim());
}
this.params.countdownTextList = countdownTextList;
}

private calculateDaysUntilUnlock() {
if (this.params.countDownDays === 0) this.daysUntilUnlock.set(0);
if (this.params.countdownStartDate && this.params.countDownDays) {
const unlockDate = addDays(this.params.countdownStartDate, this.params.countDownDays);
const daysRemaining = differenceInCalendarDays(
startOfDay(unlockDate),
startOfDay(new Date())
);
this.daysUntilUnlock.set(Math.max(daysRemaining, 0));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class TmplNumberComponent
this.displayValue = this.min_value;
}
// assign any previously saved value
if (this._row.value) {
if (this._row.value || this._row.value === 0) {
this.displayValue = this._row.value;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ $progress-colour: var(--task-progress-bar-color, var(--ion-color-primary));
.task-progress-wheel {
.progress-container {
position: relative;
width: 150px;
max-width: 150px;
height: 150px;
margin-bottom: 48px;
}
Expand Down

0 comments on commit 87fe053

Please sign in to comment.