Skip to content

Commit f9e4475

Browse files
authored
Merge branch 'develop' into filip/v19/filter-out-providers-by-cap
2 parents b6768af + c3b2bdf commit f9e4475

9 files changed

Lines changed: 765 additions & 342 deletions

File tree

assets/js/web-components/prpl-badge-progress-bar.js

Lines changed: 171 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -13,188 +13,186 @@
1313
customElements.define(
1414
'prpl-badge-progress-bar',
1515
class extends HTMLElement {
16-
constructor( badgeId, points, maxPoints, brandingId = 0 ) {
17-
// Get parent class properties
16+
/**
17+
* Observed attributes, defined the attributes that will trigger the attributeChangedCallback.
18+
*/
19+
static get observedAttributes() {
20+
return [ 'data-badge-id', 'data-points', 'data-max-points' ];
21+
}
22+
23+
/**
24+
* Constructor, ran when the element is instantiated.
25+
*/
26+
constructor() {
1827
super();
19-
badgeId = badgeId || this.getAttribute( 'data-badge-id' );
20-
points = points || this.getAttribute( 'data-points' );
21-
maxPoints = maxPoints || this.getAttribute( 'data-max-points' );
22-
brandingId = brandingId || this.getAttribute( 'data-branding-id' );
23-
const progress = ( points / maxPoints ) * 100;
24-
25-
this.innerHTML = `
26-
<div class="prpl-badge-progress-bar-container" style="padding: 1rem 0;">
27-
<div
28-
class="prpl-badge-progress-bar"
29-
style="
30-
width: 100%;
31-
height: 1rem;
32-
background-color: var(--prpl-color-gauge-remain);
33-
border-radius: 0.5rem;
34-
position: relative;"
35-
>
36-
<div
37-
class="prpl-badge-progress-bar-progress"
38-
style="
39-
width: ${ progress }%;
40-
height: 100%;
41-
background-color: var(--prpl-color-monthly);
42-
border-radius: 0.5rem;"
43-
></div>
44-
<prpl-badge
45-
badge-id="${ badgeId }"
46-
style="
47-
display:flex;
48-
width: 7.5rem;
49-
height: auto;
50-
position: absolute;
51-
left: calc(${ progress }% - 3.75rem);
52-
top: -2.5rem;"
53-
branding-id="${ brandingId }"
54-
></prpl-badge>
55-
</div>
56-
</div>
57-
`;
28+
this.attachShadow( { mode: 'open' } );
29+
this.state = {
30+
badgeId: this.getAttribute( 'data-badge-id' ) || '',
31+
points: parseInt( this.getAttribute( 'data-points' ) || 0 ),
32+
maxPoints: parseInt(
33+
this.getAttribute( 'data-max-points' ) || 10
34+
),
35+
};
5836
}
59-
}
60-
);
6137

62-
/**
63-
* Update the previous month badge progress bar.
64-
*
65-
* @param {number} pointsDiff The points difference.
66-
*
67-
* @return {void}
68-
*/
69-
// eslint-disable-next-line no-unused-vars
70-
const prplUpdatePreviousMonthBadgeProgressBar = ( pointsDiff ) => {
71-
const progressBars = document.querySelectorAll(
72-
'.prpl-previous-month-badge-progress-bar-wrapper prpl-badge-progress-bar'
73-
);
74-
75-
// Bail early if no badge progress bars are found.
76-
if ( ! progressBars.length ) {
77-
return;
78-
}
38+
/**
39+
* Get the points.
40+
*/
41+
get points() {
42+
return parseInt( this.state.points );
43+
}
7944

80-
// Get the 1st incomplete badge progress bar.
81-
const progressBar =
82-
parseInt( progressBars[ 0 ]?.getAttribute( 'data-points' ) ) >=
83-
parseInt( progressBars[ 0 ]?.getAttribute( 'data-max-points' ) )
84-
? progressBars[ 1 ]
85-
: progressBars[ 0 ];
45+
/**
46+
* Set the points.
47+
*/
48+
set points( v ) {
49+
v = Math.max( 0, Math.min( v, this.maxPoints ) );
50+
this.state.points = v;
51+
this.setAttribute( 'data-points', v );
52+
}
8653

87-
// Bail early if no badge progress bar is found.
88-
if ( ! progressBar ) {
89-
return;
90-
}
54+
/**
55+
* Get the max points.
56+
*/
57+
get maxPoints() {
58+
return parseInt( this.state.maxPoints );
59+
}
9160

92-
// Get the badge progress bar properties.
93-
const badgeId = progressBar.getAttribute( 'data-badge-id' );
94-
const badgePoints = progressBar.getAttribute( 'data-points' );
95-
const badgeMaxPoints = progressBar.getAttribute( 'data-max-points' );
96-
const badgeProgress = customElements.get( 'prpl-badge-progress-bar' );
97-
const badgeNewPoints = parseInt( badgePoints ) + pointsDiff;
98-
const brandingId = progressBar.getAttribute( 'data-branding-id' );
99-
100-
// Create a new badge progress bar.
101-
const newProgressBar = new badgeProgress(
102-
badgeId,
103-
badgeNewPoints,
104-
badgeMaxPoints,
105-
brandingId
106-
);
107-
newProgressBar.setAttribute( 'data-badge-id', badgeId );
108-
newProgressBar.setAttribute( 'data-points', badgeNewPoints );
109-
newProgressBar.setAttribute( 'data-max-points', badgeMaxPoints );
110-
newProgressBar.setAttribute( 'data-branding-id', brandingId );
111-
112-
// Replace the old badge progress bar with the new one.
113-
progressBar.replaceWith( newProgressBar );
114-
115-
// Update the remaining points.
116-
const remainingPointsEl = document.querySelector(
117-
`.prpl-previous-month-badge-progress-bar-wrapper[data-badge-id="${ badgeId }"] .prpl-previous-month-badge-progress-bar-remaining`
118-
);
119-
120-
if ( remainingPointsEl ) {
121-
// The points in the remaining points element are updated in the prplUpdatePreviousMonthBadgeCounters function.
122-
123-
remainingPointsEl.setAttribute(
124-
'data-remaining',
125-
badgeMaxPoints - badgeNewPoints
126-
);
127-
}
61+
/**
62+
* Set the max points.
63+
*/
64+
set maxPoints( v ) {
65+
this.state.maxPoints = v;
66+
this.setAttribute( 'data-max-points', v );
67+
}
12868

129-
// Update the previous month badge points number.
130-
const badgePointsNumberEl = document.querySelector(
131-
`.prpl-previous-month-badge-progress-bar-wrapper[data-badge-id="${ badgeId }"] .prpl-widget-previous-ravi-points-number`
132-
);
133-
if ( badgePointsNumberEl ) {
134-
badgePointsNumberEl.textContent = badgeNewPoints + 'pt';
135-
}
69+
/**
70+
* Get the progress percent.
71+
*/
72+
get progressPercent() {
73+
return ( this.points / this.maxPoints ) * 100;
74+
}
13675

137-
// If the previous month badge is completed, update badge elements.
138-
if ( badgeNewPoints >= parseInt( badgeMaxPoints ) ) {
139-
document
140-
.querySelectorAll(
141-
`.prpl-badge-row-wrapper .prpl-badge prpl-badge[complete="false"][badge-id="${ badgeId }"]`
142-
)
143-
?.forEach( ( badge ) => {
144-
badge.setAttribute( 'complete', 'true' );
145-
} );
146-
147-
// Remove the previous month badge progress bar.
148-
document
149-
.querySelector(
150-
`.prpl-previous-month-badge-progress-bar-wrapper[data-badge-id="${ badgeId }"]`
151-
)
152-
?.remove();
153-
154-
// If there are no more progress bars, remove the previous month badge progress bar wrapper.
155-
if (
156-
! document.querySelector(
157-
'.prpl-previous-month-badge-progress-bar-wrapper'
158-
)
159-
) {
160-
document
161-
.querySelector(
162-
'.prpl-previous-month-badge-progress-bars-wrapper'
163-
)
164-
?.remove();
76+
/**
77+
* Connected callback, ran after the element is connected to the DOM.
78+
*/
79+
connectedCallback() {
80+
this.render();
16581
}
166-
}
167-
};
16882

169-
/**
170-
* Update the previous month badge counters.
171-
*
172-
* @param {number} pointsDiff The points difference.
173-
*
174-
* @return {void}
175-
*/
176-
// eslint-disable-next-line no-unused-vars
177-
const prplUpdatePreviousMonthBadgeCounters = ( pointsDiff ) => {
178-
const remainingPointsEls = document.querySelectorAll(
179-
`.prpl-previous-month-badge-progress-bar-wrapper .prpl-previous-month-badge-progress-bar-remaining`
180-
);
181-
182-
if ( ! remainingPointsEls.length ) {
183-
return;
184-
}
83+
/**
84+
* Attribute changed callback, ran on page load and when an observed attribute is changed.
85+
*
86+
* @param {string} name The name of the attribute that was changed.
87+
* @param {string} oldVal The old value of the attribute.
88+
* @param {string} newVal The new value of the attribute.
89+
*/
90+
attributeChangedCallback( name, oldVal, newVal ) {
91+
if ( oldVal === newVal ) {
92+
return;
93+
}
94+
95+
// Convert attribute name to camelCase, remove "data-" or "aria-" prefix if present.
96+
const camelCaseName = name
97+
.replace( /^(data|aria)-/, '' )
98+
// Convert kebab-case to camelCase
99+
.replace( /-([a-z])/g, ( _, chr ) => chr.toUpperCase() );
100+
101+
// Update state.
102+
this.state[ camelCaseName ] = newVal;
103+
104+
// Update progress.
105+
this.updateProgress();
106+
107+
// Dispatch event.
108+
this.dispatchEvent(
109+
new CustomEvent( 'prlp-badge-progress-bar-update', {
110+
detail: {
111+
points: this.state.points,
112+
maxPoints: this.state.maxPoints,
113+
badgeId: this.state.badgeId,
114+
element: this,
115+
},
116+
bubbles: true,
117+
composed: true,
118+
} )
119+
);
120+
}
121+
122+
/**
123+
* Render the gauge.
124+
*/
125+
render() {
126+
this.shadowRoot.innerHTML = `
127+
<style>
128+
.container {
129+
padding: 1rem 0;
130+
}
131+
.bar {
132+
width: 100%;
133+
height: 1rem;
134+
background-color: var(--prpl-color-gauge-remain);
135+
border-radius: 0.5rem;
136+
position: relative;
137+
}
138+
.progress {
139+
height: 100%;
140+
background-color: var(--prpl-color-monthly);
141+
border-radius: 0.5rem;
142+
transition: width 0.4s ease;
143+
}
144+
prpl-badge {
145+
display: flex;
146+
width: 7.5rem;
147+
height: auto;
148+
position: absolute;
149+
top: -2.5rem;
150+
transition: left 0.4s ease;
151+
152+
&::after {
153+
content: "!";
154+
display: flex;
155+
align-items: center;
156+
justify-content: center;
157+
width: 20px;
158+
height: 20px;
159+
background-color: var(--prpl-color-alert-error);
160+
border: 2px solid #fff;
161+
border-radius: 50%;
162+
position: absolute;
163+
top: 10%;
164+
right: 25%;
165+
color: #fff;
166+
}
167+
}
168+
</style>
169+
<div class="container">
170+
<div class="bar">
171+
<div class="progress"></div>
172+
<prpl-badge
173+
badge-id="${ this.state.badgeId }"
174+
branding-id="${ this.state.brandingId }">
175+
</prpl-badge>
176+
</div>
177+
</div>
178+
`;
185179

186-
remainingPointsEls.forEach( ( pointsEl ) => {
187-
const totalPoints = pointsEl.getAttribute(
188-
'data-remaining-total-points'
189-
);
190-
pointsEl.setAttribute(
191-
'data-remaining-total-points',
192-
totalPoints - pointsDiff
193-
);
194-
195-
const numberEl = pointsEl.querySelector( '.number' );
196-
if ( numberEl ) {
197-
numberEl.textContent = totalPoints - pointsDiff;
180+
this.progressEl = this.shadowRoot.querySelector( '.progress' );
181+
this.badgeEl = this.shadowRoot.querySelector( 'prpl-badge' );
182+
183+
this.updateProgress();
198184
}
199-
} );
200-
};
185+
186+
/**
187+
* Update the progress.
188+
*/
189+
updateProgress() {
190+
if ( ! this.progressEl || ! this.badgeEl ) {
191+
return;
192+
}
193+
194+
this.progressEl.style.width = `${ this.progressPercent }%`;
195+
this.badgeEl.style.left = `calc(${ this.progressPercent }% - 3.75rem)`;
196+
}
197+
}
198+
);

assets/js/web-components/prpl-badge.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ customElements.define(
3535
src="${ url }"
3636
alt="${ badgeName }"
3737
onerror="this.onerror=null;this.src='${ progressPlannerBadge.placeholderImageUrl }';"
38+
style="max-width: 100%; height: auto%;"
3839
/>
3940
`;
4041
}

0 commit comments

Comments
 (0)