@internetarchive/donation-monthly-portal 0.0.0-editdate.1 → 0.0.0-editdate.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/form-sections/date.js +37 -42
- package/dist/src/form-sections/date.js.map +1 -1
- package/dist/src/models/plan.d.ts +1 -1
- package/dist/src/models/plan.js +1 -1
- package/dist/src/models/plan.js.map +1 -1
- package/dist/src/plans.js +1 -1
- package/dist/src/plans.js.map +1 -1
- package/dist/test/form-sections/date.test.d.ts +1 -0
- package/dist/test/form-sections/date.test.js +134 -0
- package/dist/test/form-sections/date.test.js.map +1 -0
- package/package.json +1 -1
- package/src/form-sections/date.ts +38 -47
- package/src/models/plan.ts +1 -1
- package/src/plans.ts +1 -1
|
@@ -22,7 +22,7 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
22
22
|
}
|
|
23
23
|
updated(changed) {
|
|
24
24
|
if (changed.has('currentlyEditing') && this.currentlyEditing) {
|
|
25
|
-
this.
|
|
25
|
+
this.dateInput.focus();
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
render() {
|
|
@@ -35,13 +35,13 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
35
35
|
>
|
|
36
36
|
${!this.currentlyEditing
|
|
37
37
|
? html ` <p class="current-date">
|
|
38
|
-
${(_a = this.plan) === null || _a === void 0 ? void 0 : _a.
|
|
38
|
+
${(_a = this.plan) === null || _a === void 0 ? void 0 : _a.nextBillingDateLocale}
|
|
39
39
|
<ia-mgc-update-status .status=${this.updateStatus}
|
|
40
40
|
>${this.updateMessage}</ia-mgc-update-status
|
|
41
41
|
>
|
|
42
42
|
</p>
|
|
43
43
|
<ia-button
|
|
44
|
-
id="edit-date"
|
|
44
|
+
id="open-edit-date-form"
|
|
45
45
|
class="ia-button link"
|
|
46
46
|
.clickHandler=${() => {
|
|
47
47
|
this.currentlyEditing = true;
|
|
@@ -69,16 +69,12 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
69
69
|
await this.updateComplete;
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
|
-
this.
|
|
73
|
-
false;
|
|
72
|
+
this.allowEditing = false;
|
|
74
73
|
await this.updateComplete;
|
|
75
74
|
}
|
|
76
75
|
/* Dispatches edit-date change request */
|
|
77
76
|
requestDateUpdate(e) {
|
|
78
77
|
e.preventDefault();
|
|
79
|
-
console.log('<plan-date> - requestDateUpdate', {
|
|
80
|
-
newValue: this.newDate,
|
|
81
|
-
});
|
|
82
78
|
this.dispatchEvent(new CustomEvent('updateDate', {
|
|
83
79
|
detail: {
|
|
84
80
|
plan: this.plan,
|
|
@@ -90,10 +86,10 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
90
86
|
this.clearInputField();
|
|
91
87
|
this.clearStatusMessaging();
|
|
92
88
|
this.currentlyEditing = false;
|
|
89
|
+
this.allowEditing = false;
|
|
93
90
|
}
|
|
94
91
|
clearInputField() {
|
|
95
|
-
|
|
96
|
-
input.value = '';
|
|
92
|
+
this.dateInput.value = '';
|
|
97
93
|
this.newDate = undefined;
|
|
98
94
|
}
|
|
99
95
|
async clearStatusMessaging() {
|
|
@@ -116,26 +112,23 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
116
112
|
const today = new Date();
|
|
117
113
|
const year = today.getFullYear() + 1; // Allow up to one year in the future
|
|
118
114
|
const month = String(today.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
|
|
119
|
-
|
|
120
|
-
return `${year}-${month}-${lastDayOfMonth}`; // Last day of the month
|
|
115
|
+
return `${year}-${month}-${today.getDate()}`;
|
|
121
116
|
}
|
|
122
117
|
get editDateForm() {
|
|
123
|
-
var _a, _b
|
|
124
|
-
console.log('editdate', {
|
|
125
|
-
min: this.minDate,
|
|
126
|
-
max: this.maxDate,
|
|
127
|
-
plan: this.plan,
|
|
128
|
-
nextBillingDate: (_a = this.plan) === null || _a === void 0 ? void 0 : _a.nextBillingDate,
|
|
129
|
-
lastBillingDate: (_b = this.plan) === null || _b === void 0 ? void 0 : _b.lastBillingDateLocale,
|
|
130
|
-
});
|
|
118
|
+
var _a, _b;
|
|
131
119
|
return html `
|
|
132
120
|
<section>
|
|
133
121
|
<form id="edit-date">
|
|
134
|
-
<p
|
|
122
|
+
<p id="form-info-last-donation-date">
|
|
123
|
+
Last donation date: ${(_a = this.plan) === null || _a === void 0 ? void 0 : _a.lastBillingDateLocale}
|
|
124
|
+
</p>
|
|
135
125
|
|
|
136
|
-
<p
|
|
126
|
+
<p id="form-info-next-donation-date">
|
|
127
|
+
Next donation date: ${(_b = this.plan) === null || _b === void 0 ? void 0 : _b.nextBillingDateLocale}
|
|
128
|
+
</p>
|
|
137
129
|
<div class="date-holder">
|
|
138
130
|
<input
|
|
131
|
+
required
|
|
139
132
|
type="date"
|
|
140
133
|
id="edit-date"
|
|
141
134
|
name="edit-date"
|
|
@@ -143,24 +136,22 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
143
136
|
max=${this.maxDate}
|
|
144
137
|
value=""
|
|
145
138
|
@focus=${() => this.clearStatusMessaging()}
|
|
146
|
-
@change=${async (
|
|
147
|
-
var _a, _b, _c, _d
|
|
139
|
+
@change=${async () => {
|
|
140
|
+
var _a, _b, _c, _d;
|
|
148
141
|
this.clearStatusMessaging();
|
|
149
142
|
await this.updateComplete;
|
|
150
|
-
|
|
151
|
-
console.log('date changed
|
|
152
|
-
const inputValue = e.target.value;
|
|
143
|
+
const inputValue = this.dateInput.value;
|
|
144
|
+
console.log(' ----- date input changed ----- ', inputValue, this.errorMessage);
|
|
153
145
|
if (!inputValue) {
|
|
154
146
|
this.errorMessage = 'Please enter a date';
|
|
155
|
-
this.allowEditing =
|
|
147
|
+
this.allowEditing = false;
|
|
156
148
|
return; // wait until date field returns a valid string
|
|
157
149
|
}
|
|
158
150
|
let validDate;
|
|
159
151
|
try {
|
|
160
|
-
validDate = new Date(
|
|
152
|
+
validDate = new Date(`${inputValue}T00:00:00`);
|
|
161
153
|
}
|
|
162
154
|
catch (error) {
|
|
163
|
-
console.error('Invalid date format:', error);
|
|
164
155
|
this.errorMessage =
|
|
165
156
|
'Please enter a valid date format (YYYY-MM-DD)';
|
|
166
157
|
return; // wait until date field returns a valid string
|
|
@@ -178,16 +169,13 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
178
169
|
this.allowEditing = false;
|
|
179
170
|
return;
|
|
180
171
|
}
|
|
181
|
-
console.log('validDate', validDate);
|
|
182
172
|
const newDate = new Date(validDate).toISOString();
|
|
183
173
|
this.newDate = newDate;
|
|
184
|
-
console.log('newDate', newDate);
|
|
185
|
-
// Check if the date is in the past
|
|
186
174
|
// Check if there has been a donation in the last month
|
|
187
|
-
const hasLastDonationInfo = ((
|
|
188
|
-
new Date((
|
|
175
|
+
const hasLastDonationInfo = ((_a = this.plan) === null || _a === void 0 ? void 0 : _a.payment.lastBillingDate.date) &&
|
|
176
|
+
new Date((_b = this.plan) === null || _b === void 0 ? void 0 : _b.payment.lastBillingDate.date);
|
|
189
177
|
if (hasLastDonationInfo) {
|
|
190
|
-
const lastDonationDate = new Date((
|
|
178
|
+
const lastDonationDate = new Date((_d = (_c = this.plan) === null || _c === void 0 ? void 0 : _c.payment.lastBillingDate.date) !== null && _d !== void 0 ? _d : '');
|
|
191
179
|
const lastDonationMonth = lastDonationDate.getMonth();
|
|
192
180
|
const lastDonationYear = lastDonationDate.getFullYear();
|
|
193
181
|
const thisYear = validDate.getFullYear();
|
|
@@ -196,13 +184,21 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
196
184
|
thisMonth === lastDonationMonth;
|
|
197
185
|
if (isInLastMonth) {
|
|
198
186
|
this.warningMessage =
|
|
199
|
-
'
|
|
187
|
+
'New donation date is in the same month as your last payment.';
|
|
200
188
|
this.allowEditing = true;
|
|
201
189
|
return;
|
|
202
190
|
}
|
|
203
191
|
}
|
|
204
|
-
// Check if
|
|
205
|
-
|
|
192
|
+
// Check if the new date is within the next 12 months
|
|
193
|
+
const twelveMonthsFromNow = new Date();
|
|
194
|
+
twelveMonthsFromNow.setFullYear(twelveMonthsFromNow.getFullYear() + 1);
|
|
195
|
+
twelveMonthsFromNow.setHours(0, 0, 0, 0);
|
|
196
|
+
if (chosenDate > twelveMonthsFromNow) {
|
|
197
|
+
this.errorMessage =
|
|
198
|
+
'New donation date must be within the next 12 months.';
|
|
199
|
+
this.allowEditing = false;
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
206
202
|
this.allowEditing = true;
|
|
207
203
|
}}
|
|
208
204
|
/>
|
|
@@ -232,7 +228,6 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
232
228
|
// eslint-disable-next-line no-param-reassign
|
|
233
229
|
iaButton.isDisabled = true;
|
|
234
230
|
await iaButton.updateComplete;
|
|
235
|
-
// check if request is in range
|
|
236
231
|
this.requestDateUpdate(e);
|
|
237
232
|
}}
|
|
238
233
|
>
|
|
@@ -243,8 +238,8 @@ let MGCEditPlanDate = class MGCEditPlanDate extends LitElement {
|
|
|
243
238
|
>
|
|
244
239
|
</div>
|
|
245
240
|
</div>
|
|
246
|
-
<p class="error">${this.warningMessage}</p>
|
|
247
|
-
<p class="error">${this.errorMessage}</p>
|
|
241
|
+
<p class="error warning-msg">${this.warningMessage}</p>
|
|
242
|
+
<p class="error error-msg">${this.errorMessage}</p>
|
|
248
243
|
</form>
|
|
249
244
|
</section>
|
|
250
245
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../../src/form-sections/date.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n LitElement,\n html,\n PropertyValues,\n nothing,\n css,\n TemplateResult,\n} from 'lit';\nimport { customElement, property, query } from 'lit/decorators.js';\nimport '@internetarchive/donation-form-section';\n\nimport type { MonthlyPlan } from '../models/plan';\nimport '../presentational/ia-button';\nimport type { IauxButton } from '../presentational/ia-button';\nimport '../presentational/mgc-update-status';\n\n@customElement('ia-mgc-edit-date')\nexport class MGCEditPlanDate extends LitElement {\n @property({ type: Object }) plan?: MonthlyPlan;\n\n @property({ type: String }) newDate?: string;\n\n @property({ type: Boolean, reflect: true }) currentlyEditing: boolean = false;\n\n @property({ type: Boolean }) allowEditing: boolean = false;\n\n @property({ type: String }) updateMessage: string = '';\n\n @property({ type: String }) errorMessage: string = '';\n\n @property({ type: String }) warningMessage: string = '';\n\n @property({ type: String }) updateStatus: 'success' | 'fail' | '' = '';\n\n @query('form') form!: HTMLFormElement;\n\n @query('form ia-button#edit-date') formSubmitButton!: IauxButton;\n\n @query('form input[name=\"edit-date\"]')\n dateInput!: HTMLInputElement;\n\n willUpdate(changed: PropertyValues) {\n if (this.dateInput && changed.has('plan') && this.plan) {\n this.dateInput.setAttribute('min', this.minDate);\n this.dateInput.setAttribute('max', this.maxDate);\n }\n }\n\n updated(changed: PropertyValues) {\n if (changed.has('currentlyEditing') && this.currentlyEditing) {\n this.form.focus();\n }\n }\n\n protected render() {\n return html`\n <section>\n <donation-form-section\n badgemode=\"hidebadge\"\n headline=\"Change next donation date\"\n >\n ${!this.currentlyEditing\n ? html` <p class=\"current-date\">\n ${this.plan?.nextBillingDate}\n <ia-mgc-update-status .status=${this.updateStatus}\n >${this.updateMessage}</ia-mgc-update-status\n >\n </p>\n <ia-button\n id=\"edit-date\"\n class=\"ia-button link\"\n .clickHandler=${() => {\n this.currentlyEditing = true;\n this.clearStatusMessaging();\n }}\n >\n Edit...\n </ia-button>`\n : nothing}\n ${this.currentlyEditing ? this.editDateForm : nothing}\n </donation-form-section>\n </section>\n `;\n }\n\n /* External Function that is called by consumer to tell the form there has been data update */\n async dateUpdated(status: 'success' | 'fail') {\n this.clearInputField();\n\n this.updateStatus = status;\n this.updateMessage =\n status === 'success'\n ? 'Date updated'\n : 'Failed to update date, please try again';\n\n if (status === 'success') {\n this.closeForm();\n await this.updateComplete;\n return;\n }\n\n (this.form.querySelector('ia-button#edit-date') as IauxButton).isDisabled =\n false;\n\n await this.updateComplete;\n }\n\n /* Dispatches edit-date change request */\n requestDateUpdate(e: Event): void {\n e.preventDefault();\n console.log('<plan-date> - requestDateUpdate', {\n newValue: this.newDate,\n });\n this.dispatchEvent(\n new CustomEvent('updateDate', {\n detail: {\n plan: this.plan,\n newDate: this.newDate,\n },\n })\n );\n }\n\n closeForm() {\n this.clearInputField();\n this.clearStatusMessaging();\n this.currentlyEditing = false;\n }\n\n clearInputField() {\n const input = this.form.querySelector(\n 'input[name=\"edit-date\"]'\n ) as HTMLInputElement;\n input.value = '';\n this.newDate = undefined;\n }\n\n async clearStatusMessaging() {\n this.errorMessage = '';\n this.warningMessage = '';\n this.updateMessage = '';\n this.updateStatus = '';\n await this.updateComplete;\n }\n\n /* DISPLAY */\n get minDate(): string {\n const today = new Date();\n const tomorrow = new Date(today);\n tomorrow.setDate(today.getDate() + 1); // Set to tomorrow\n const year = tomorrow.getFullYear();\n const month = String(tomorrow.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed\n return `${year}-${month}-${tomorrow.getDate()}`;\n }\n\n get maxDate(): string {\n const today = new Date();\n const year = today.getFullYear() + 1; // Allow up to one year in the future\n const month = String(today.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed\n const lastDayOfMonth = new Date(year, today.getMonth() + 1, 0).getDate();\n return `${year}-${month}-${lastDayOfMonth}`; // Last day of the month\n }\n\n get editDateForm(): TemplateResult {\n console.log('editdate', {\n min: this.minDate,\n max: this.maxDate,\n plan: this.plan,\n nextBillingDate: this.plan?.nextBillingDate,\n lastBillingDate: this.plan?.lastBillingDateLocale,\n });\n return html`\n <section>\n <form id=\"edit-date\">\n <p>Last donation date: ${this.plan?.lastBillingDateLocale}</p>\n\n <p>Next donation date: ${this.plan?.nextBillingDate}</p>\n <div class=\"date-holder\">\n <input\n type=\"date\"\n id=\"edit-date\"\n name=\"edit-date\"\n min=${this.minDate}\n max=${this.maxDate}\n value=\"\"\n @focus=${() => this.clearStatusMessaging()}\n @change=${async (e: Event) => {\n this.clearStatusMessaging();\n await this.updateComplete;\n\n console.log(\n 'date changed',\n (e.target as HTMLInputElement).value\n );\n console.log('date changed THIS', this);\n\n const inputValue = (e.target as HTMLInputElement).value;\n if (!inputValue) {\n this.errorMessage = 'Please enter a date';\n this.allowEditing = true;\n return; // wait until date field returns a valid string\n }\n\n let validDate;\n try {\n validDate = new Date(\n (e.target as HTMLInputElement)?.value as string\n );\n } catch (error) {\n console.error('Invalid date format:', error);\n this.errorMessage =\n 'Please enter a valid date format (YYYY-MM-DD)';\n return; // wait until date field returns a valid string\n }\n\n // Check if minimum date is at least tomorrow\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n const tomorrow = new Date(today);\n tomorrow.setDate(today.getDate() + 1); // Set to tomorrow\n tomorrow.setHours(0, 0, 0, 0);\n const chosenDate = new Date(validDate);\n chosenDate.setHours(0, 0, 0, 0);\n if (chosenDate < today) {\n this.errorMessage = 'Date must be at least tomorrow.';\n this.allowEditing = false;\n return;\n }\n\n console.log('validDate', validDate);\n\n const newDate = new Date(validDate).toISOString();\n this.newDate = newDate;\n console.log('newDate', newDate);\n\n // Check if the date is in the past\n\n // Check if there has been a donation in the last month\n\n const hasLastDonationInfo =\n this.plan?.payment.lastBillingDate.date &&\n new Date(this.plan?.payment.lastBillingDate.date);\n\n if (hasLastDonationInfo) {\n const lastDonationDate = new Date(\n this.plan?.payment.lastBillingDate.date ?? ''\n );\n const lastDonationMonth = lastDonationDate.getMonth();\n const lastDonationYear = lastDonationDate.getFullYear();\n\n const thisYear = validDate.getFullYear();\n const thisMonth = validDate.getMonth();\n const isInLastMonth =\n thisYear === lastDonationYear &&\n thisMonth === lastDonationMonth;\n\n if (isInLastMonth) {\n this.warningMessage =\n 'You have already made a donation this month. Is that cool with you?';\n this.allowEditing = true;\n return;\n }\n }\n // Check if there has been a donation in the last 30 days\n console.log('newDate', newDate);\n\n this.allowEditing = true;\n }}\n />\n </div>\n <div>\n <div class=\"cta-container\">\n <ia-button\n class=\"ia-button secondary\"\n .clickHandler=${(e: Event) => {\n e.preventDefault();\n this.closeForm();\n }}\n >\n Cancel\n </ia-button>\n <ia-button\n id=\"edit-date\"\n class=\"ia-button primary\"\n type=\"submit\"\n .isDisabled=${!this.allowEditing}\n .clickHandler=${async (e: Event, iaButton: IauxButton) => {\n this.clearStatusMessaging();\n\n if (!this.newDate) {\n this.errorMessage = 'Please enter a valid date';\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n (iaButton as IauxButton).isDisabled = true;\n await iaButton.updateComplete;\n\n // check if request is in range\n\n this.requestDateUpdate(e);\n }}\n >\n Update\n </ia-button>\n <ia-mgc-update-status .status=${this.updateStatus}\n >${this.updateMessage}</ia-mgc-update-status\n >\n </div>\n </div>\n <p class=\"error\">${this.warningMessage}</p>\n <p class=\"error\">${this.errorMessage}</p>\n </form>\n </section>\n `;\n }\n\n static styles = css`\n input[name='edit-date'] {\n margin: 10px 0;\n min-width: 140px;\n }\n\n .cta-container {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-content: center;\n justify-content: flex-start;\n align-items: center;\n gap: 10px;\n }\n\n p.error {\n color: var(--mgc-warning-color-dark, #bb0505);\n }\n\n ia-mgc-update-status {\n display: inline-block;\n margin-left: 1rem;\n }\n\n .checkbox-option-container {\n margin: 10px 0;\n display: flex;\n }\n `;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"date.js","sourceRoot":"","sources":["../../../src/form-sections/date.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,UAAU,EACV,IAAI,EAEJ,OAAO,EACP,GAAG,GAEJ,MAAM,KAAK,CAAC;AACb,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,wCAAwC,CAAC;AAGhD,OAAO,6BAA6B,CAAC;AAErC,OAAO,qCAAqC,CAAC;AAG7C,IAAa,eAAe,GAA5B,MAAa,eAAgB,SAAQ,UAAU;IAA/C;;QAK8C,qBAAgB,GAAY,KAAK,CAAC;QAEjD,iBAAY,GAAY,KAAK,CAAC;QAE/B,kBAAa,GAAW,EAAE,CAAC;QAE3B,iBAAY,GAAW,EAAE,CAAC;QAE1B,mBAAc,GAAW,EAAE,CAAC;QAE5B,iBAAY,GAA4B,EAAE,CAAC;IAkTzE,CAAC;IAzSC,UAAU,CAAC,OAAuB;QAChC,IAAI,IAAI,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE;YACtD,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACjD,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;SAClD;IACH,CAAC;IAED,OAAO,CAAC,OAAuB;QAC7B,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE;YAC5D,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;SACxB;IACH,CAAC;IAES,MAAM;;QACd,OAAO,IAAI,CAAA;;;;;;YAMH,CAAC,IAAI,CAAC,gBAAgB;YACtB,CAAC,CAAC,IAAI,CAAA;oBACE,MAAA,IAAI,CAAC,IAAI,0CAAE,qBAAqB;kDACF,IAAI,CAAC,YAAY;uBAC5C,IAAI,CAAC,aAAa;;;;;;kCAMP,GAAG,EAAE;gBACnB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;gBAC7B,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC9B,CAAC;;;6BAGU;YACjB,CAAC,CAAC,OAAO;YACT,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO;;;KAG1D,CAAC;IACJ,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,WAAW,CAAC,MAA0B;QAC1C,IAAI,CAAC,eAAe,EAAE,CAAC;QAEvB,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;QAC3B,IAAI,CAAC,aAAa;YAChB,MAAM,KAAK,SAAS;gBAClB,CAAC,CAAC,cAAc;gBAChB,CAAC,CAAC,yCAAyC,CAAC;QAEhD,IAAI,MAAM,KAAK,SAAS,EAAE;YACxB,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,cAAc,CAAC;YAC1B,OAAO;SACR;QAED,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,MAAM,IAAI,CAAC,cAAc,CAAC;IAC5B,CAAC;IAED,yCAAyC;IACzC,iBAAiB,CAAC,CAAQ;QACxB,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,YAAY,EAAE;YAC5B,MAAM,EAAE;gBACN,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IAED,SAAS;QACP,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5B,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;QAC9B,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED,eAAe;QACb,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;IAC3B,CAAC;IAED,KAAK,CAAC,oBAAoB;QACxB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,CAAC,cAAc,CAAC;IAC5B,CAAC;IAED,aAAa;IACb,IAAI,OAAO;QACT,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB;QACzD,MAAM,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,uBAAuB;QACvF,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;IAClD,CAAC;IAED,IAAI,OAAO;QACT,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,KAAK,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,qCAAqC;QAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,uBAAuB;QACpF,OAAO,GAAG,IAAI,IAAI,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;IAC/C,CAAC;IAED,IAAI,YAAY;;QACd,OAAO,IAAI,CAAA;;;;kCAImB,MAAA,IAAI,CAAC,IAAI,0CAAE,qBAAqB;;;;kCAIhC,MAAA,IAAI,CAAC,IAAI,0CAAE,qBAAqB;;;;;;;;oBAQ9C,IAAI,CAAC,OAAO;oBACZ,IAAI,CAAC,OAAO;;uBAET,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,EAAE;wBAChC,KAAK,IAAI,EAAE;;YACnB,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC5B,MAAM,IAAI,CAAC,cAAc,CAAC;YAE1B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YACxC,OAAO,CAAC,GAAG,CACT,kCAAkC,EAClC,UAAU,EACV,IAAI,CAAC,YAAY,CAClB,CAAC;YAEF,IAAI,CAAC,UAAU,EAAE;gBACf,IAAI,CAAC,YAAY,GAAG,qBAAqB,CAAC;gBAC1C,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;gBAC1B,OAAO,CAAC,+CAA+C;aACxD;YAED,IAAI,SAAS,CAAC;YACd,IAAI;gBACF,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,UAAU,WAAW,CAAC,CAAC;aAChD;YAAC,OAAO,KAAK,EAAE;gBACd,IAAI,CAAC,YAAY;oBACf,+CAA+C,CAAC;gBAClD,OAAO,CAAC,+CAA+C;aACxD;YAED,6CAA6C;YAC7C,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC;YACzB,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3B,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;YACjC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB;YACzD,QAAQ,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9B,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;YACvC,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAChC,IAAI,UAAU,GAAG,KAAK,EAAE;gBACtB,IAAI,CAAC,YAAY,GAAG,iCAAiC,CAAC;gBACtD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;gBAC1B,OAAO;aACR;YAED,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;YAClD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;YAEvB,uDAAuD;YACvD,MAAM,mBAAmB,GACvB,CAAA,MAAA,IAAI,CAAC,IAAI,0CAAE,OAAO,CAAC,eAAe,CAAC,IAAI;gBACvC,IAAI,IAAI,CAAC,MAAA,IAAI,CAAC,IAAI,0CAAE,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YAEpD,IAAI,mBAAmB,EAAE;gBACvB,MAAM,gBAAgB,GAAG,IAAI,IAAI,CAC/B,MAAA,MAAA,IAAI,CAAC,IAAI,0CAAE,OAAO,CAAC,eAAe,CAAC,IAAI,mCAAI,EAAE,CAC9C,CAAC;gBACF,MAAM,iBAAiB,GAAG,gBAAgB,CAAC,QAAQ,EAAE,CAAC;gBACtD,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,WAAW,EAAE,CAAC;gBAExD,MAAM,QAAQ,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;gBACzC,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;gBACvC,MAAM,aAAa,GACjB,QAAQ,KAAK,gBAAgB;oBAC7B,SAAS,KAAK,iBAAiB,CAAC;gBAElC,IAAI,aAAa,EAAE;oBACjB,IAAI,CAAC,cAAc;wBACjB,8DAA8D,CAAC;oBACjE,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;oBACzB,OAAO;iBACR;aACF;YAED,qDAAqD;YACrD,MAAM,mBAAmB,GAAG,IAAI,IAAI,EAAE,CAAC;YACvC,mBAAmB,CAAC,WAAW,CAC7B,mBAAmB,CAAC,WAAW,EAAE,GAAG,CAAC,CACtC,CAAC;YACF,mBAAmB,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAEzC,IAAI,UAAU,GAAG,mBAAmB,EAAE;gBACpC,IAAI,CAAC,YAAY;oBACf,sDAAsD,CAAC;gBACzD,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;gBAC1B,OAAO;aACR;YAED,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC3B,CAAC;;;;;;;gCAOiB,CAAC,CAAQ,EAAE,EAAE;YAC3B,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,CAAC;;;;;;;;8BAQa,CAAC,IAAI,CAAC,YAAY;gCAChB,KAAK,EAAE,CAAQ,EAAE,QAAoB,EAAE,EAAE;YACvD,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAE5B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;gBACjB,IAAI,CAAC,YAAY,GAAG,2BAA2B,CAAC;gBAChD,OAAO;aACR;YAED,6CAA6C;YAC5C,QAAuB,CAAC,UAAU,GAAG,IAAI,CAAC;YAC3C,MAAM,QAAQ,CAAC,cAAc,CAAC;YAE9B,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;QAC5B,CAAC;;;;8CAI6B,IAAI,CAAC,YAAY;mBAC5C,IAAI,CAAC,aAAa;;;;yCAII,IAAI,CAAC,cAAc;uCACrB,IAAI,CAAC,YAAY;;;KAGnD,CAAC;IACJ,CAAC;CAgCF,CAAA;AA9BQ,sBAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BlB,CAAC;AA/T0B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;6CAAoB;AAEnB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;gDAAkB;AAED;IAA3C,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;yDAAmC;AAEjD;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;qDAA+B;AAE/B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;sDAA4B;AAE3B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;qDAA2B;AAE1B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;uDAA6B;AAE5B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;qDAA4C;AAExD;IAAd,KAAK,CAAC,MAAM,CAAC;6CAAwB;AAEH;IAAlC,KAAK,CAAC,0BAA0B,CAAC;yDAA+B;AAGjE;IADC,KAAK,CAAC,8BAA8B,CAAC;kDACT;AAtBlB,eAAe;IAD3B,aAAa,CAAC,kBAAkB,CAAC;GACrB,eAAe,CAiU3B;SAjUY,eAAe","sourcesContent":["import {\n LitElement,\n html,\n PropertyValues,\n nothing,\n css,\n TemplateResult,\n} from 'lit';\nimport { customElement, property, query } from 'lit/decorators.js';\nimport '@internetarchive/donation-form-section';\n\nimport type { MonthlyPlan } from '../models/plan';\nimport '../presentational/ia-button';\nimport type { IauxButton } from '../presentational/ia-button';\nimport '../presentational/mgc-update-status';\n\n@customElement('ia-mgc-edit-date')\nexport class MGCEditPlanDate extends LitElement {\n @property({ type: Object }) plan?: MonthlyPlan;\n\n @property({ type: String }) newDate?: string;\n\n @property({ type: Boolean, reflect: true }) currentlyEditing: boolean = false;\n\n @property({ type: Boolean }) allowEditing: boolean = false;\n\n @property({ type: String }) updateMessage: string = '';\n\n @property({ type: String }) errorMessage: string = '';\n\n @property({ type: String }) warningMessage: string = '';\n\n @property({ type: String }) updateStatus: 'success' | 'fail' | '' = '';\n\n @query('form') form!: HTMLFormElement;\n\n @query('form ia-button#edit-date') formSubmitButton!: IauxButton;\n\n @query('form input[name=\"edit-date\"]')\n dateInput!: HTMLInputElement;\n\n willUpdate(changed: PropertyValues) {\n if (this.dateInput && changed.has('plan') && this.plan) {\n this.dateInput.setAttribute('min', this.minDate);\n this.dateInput.setAttribute('max', this.maxDate);\n }\n }\n\n updated(changed: PropertyValues) {\n if (changed.has('currentlyEditing') && this.currentlyEditing) {\n this.dateInput.focus();\n }\n }\n\n protected render() {\n return html`\n <section>\n <donation-form-section\n badgemode=\"hidebadge\"\n headline=\"Change next donation date\"\n >\n ${!this.currentlyEditing\n ? html` <p class=\"current-date\">\n ${this.plan?.nextBillingDateLocale}\n <ia-mgc-update-status .status=${this.updateStatus}\n >${this.updateMessage}</ia-mgc-update-status\n >\n </p>\n <ia-button\n id=\"open-edit-date-form\"\n class=\"ia-button link\"\n .clickHandler=${() => {\n this.currentlyEditing = true;\n this.clearStatusMessaging();\n }}\n >\n Edit...\n </ia-button>`\n : nothing}\n ${this.currentlyEditing ? this.editDateForm : nothing}\n </donation-form-section>\n </section>\n `;\n }\n\n /* External Function that is called by consumer to tell the form there has been data update */\n async dateUpdated(status: 'success' | 'fail') {\n this.clearInputField();\n\n this.updateStatus = status;\n this.updateMessage =\n status === 'success'\n ? 'Date updated'\n : 'Failed to update date, please try again';\n\n if (status === 'success') {\n this.closeForm();\n await this.updateComplete;\n return;\n }\n\n this.allowEditing = false;\n await this.updateComplete;\n }\n\n /* Dispatches edit-date change request */\n requestDateUpdate(e: Event): void {\n e.preventDefault();\n this.dispatchEvent(\n new CustomEvent('updateDate', {\n detail: {\n plan: this.plan,\n newDate: this.newDate,\n },\n })\n );\n }\n\n closeForm() {\n this.clearInputField();\n this.clearStatusMessaging();\n this.currentlyEditing = false;\n this.allowEditing = false;\n }\n\n clearInputField() {\n this.dateInput.value = '';\n this.newDate = undefined;\n }\n\n async clearStatusMessaging() {\n this.errorMessage = '';\n this.warningMessage = '';\n this.updateMessage = '';\n this.updateStatus = '';\n await this.updateComplete;\n }\n\n /* DISPLAY */\n get minDate(): string {\n const today = new Date();\n const tomorrow = new Date(today);\n tomorrow.setDate(today.getDate() + 1); // Set to tomorrow\n const year = tomorrow.getFullYear();\n const month = String(tomorrow.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed\n return `${year}-${month}-${tomorrow.getDate()}`;\n }\n\n get maxDate(): string {\n const today = new Date();\n const year = today.getFullYear() + 1; // Allow up to one year in the future\n const month = String(today.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed\n return `${year}-${month}-${today.getDate()}`;\n }\n\n get editDateForm(): TemplateResult {\n return html`\n <section>\n <form id=\"edit-date\">\n <p id=\"form-info-last-donation-date\">\n Last donation date: ${this.plan?.lastBillingDateLocale}\n </p>\n\n <p id=\"form-info-next-donation-date\">\n Next donation date: ${this.plan?.nextBillingDateLocale}\n </p>\n <div class=\"date-holder\">\n <input\n required\n type=\"date\"\n id=\"edit-date\"\n name=\"edit-date\"\n min=${this.minDate}\n max=${this.maxDate}\n value=\"\"\n @focus=${() => this.clearStatusMessaging()}\n @change=${async () => {\n this.clearStatusMessaging();\n await this.updateComplete;\n\n const inputValue = this.dateInput.value;\n console.log(\n ' ----- date input changed ----- ',\n inputValue,\n this.errorMessage\n );\n\n if (!inputValue) {\n this.errorMessage = 'Please enter a date';\n this.allowEditing = false;\n return; // wait until date field returns a valid string\n }\n\n let validDate;\n try {\n validDate = new Date(`${inputValue}T00:00:00`);\n } catch (error) {\n this.errorMessage =\n 'Please enter a valid date format (YYYY-MM-DD)';\n return; // wait until date field returns a valid string\n }\n\n // Check if minimum date is at least tomorrow\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n const tomorrow = new Date(today);\n tomorrow.setDate(today.getDate() + 1); // Set to tomorrow\n tomorrow.setHours(0, 0, 0, 0);\n const chosenDate = new Date(validDate);\n chosenDate.setHours(0, 0, 0, 0);\n if (chosenDate < today) {\n this.errorMessage = 'Date must be at least tomorrow.';\n this.allowEditing = false;\n return;\n }\n\n const newDate = new Date(validDate).toISOString();\n this.newDate = newDate;\n\n // Check if there has been a donation in the last month\n const hasLastDonationInfo =\n this.plan?.payment.lastBillingDate.date &&\n new Date(this.plan?.payment.lastBillingDate.date);\n\n if (hasLastDonationInfo) {\n const lastDonationDate = new Date(\n this.plan?.payment.lastBillingDate.date ?? ''\n );\n const lastDonationMonth = lastDonationDate.getMonth();\n const lastDonationYear = lastDonationDate.getFullYear();\n\n const thisYear = validDate.getFullYear();\n const thisMonth = validDate.getMonth();\n const isInLastMonth =\n thisYear === lastDonationYear &&\n thisMonth === lastDonationMonth;\n\n if (isInLastMonth) {\n this.warningMessage =\n 'New donation date is in the same month as your last payment.';\n this.allowEditing = true;\n return;\n }\n }\n\n // Check if the new date is within the next 12 months\n const twelveMonthsFromNow = new Date();\n twelveMonthsFromNow.setFullYear(\n twelveMonthsFromNow.getFullYear() + 1\n );\n twelveMonthsFromNow.setHours(0, 0, 0, 0);\n\n if (chosenDate > twelveMonthsFromNow) {\n this.errorMessage =\n 'New donation date must be within the next 12 months.';\n this.allowEditing = false;\n return;\n }\n\n this.allowEditing = true;\n }}\n />\n </div>\n <div>\n <div class=\"cta-container\">\n <ia-button\n class=\"ia-button secondary\"\n .clickHandler=${(e: Event) => {\n e.preventDefault();\n this.closeForm();\n }}\n >\n Cancel\n </ia-button>\n <ia-button\n id=\"edit-date\"\n class=\"ia-button primary\"\n type=\"submit\"\n .isDisabled=${!this.allowEditing}\n .clickHandler=${async (e: Event, iaButton: IauxButton) => {\n this.clearStatusMessaging();\n\n if (!this.newDate) {\n this.errorMessage = 'Please enter a valid date';\n return;\n }\n\n // eslint-disable-next-line no-param-reassign\n (iaButton as IauxButton).isDisabled = true;\n await iaButton.updateComplete;\n\n this.requestDateUpdate(e);\n }}\n >\n Update\n </ia-button>\n <ia-mgc-update-status .status=${this.updateStatus}\n >${this.updateMessage}</ia-mgc-update-status\n >\n </div>\n </div>\n <p class=\"error warning-msg\">${this.warningMessage}</p>\n <p class=\"error error-msg\">${this.errorMessage}</p>\n </form>\n </section>\n `;\n }\n\n static styles = css`\n input[name='edit-date'] {\n margin: 10px 0;\n min-width: 140px;\n }\n\n .cta-container {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-content: center;\n justify-content: flex-start;\n align-items: center;\n gap: 10px;\n }\n\n p.error {\n color: var(--mgc-warning-color-dark, #bb0505);\n }\n\n ia-mgc-update-status {\n display: inline-block;\n margin-left: 1rem;\n }\n\n .checkbox-option-container {\n margin: 10px 0;\n display: flex;\n }\n `;\n}\n"]}
|
|
@@ -43,7 +43,7 @@ export declare class MonthlyPlan {
|
|
|
43
43
|
setAmount(newAmount: number): void;
|
|
44
44
|
setNextBillingDate(newDate: string): void;
|
|
45
45
|
get startDate(): string;
|
|
46
|
-
get
|
|
46
|
+
get nextBillingDateLocale(): string;
|
|
47
47
|
get lastBillingDateLocale(): string;
|
|
48
48
|
get hasBeenCancelled(): boolean;
|
|
49
49
|
get isTest(): boolean;
|
package/dist/src/models/plan.js
CHANGED
|
@@ -27,7 +27,7 @@ export class MonthlyPlan {
|
|
|
27
27
|
const date = new Date(this.plan.start_date);
|
|
28
28
|
return date.toLocaleDateString();
|
|
29
29
|
}
|
|
30
|
-
get
|
|
30
|
+
get nextBillingDateLocale() {
|
|
31
31
|
const nextBillingDate = new Date(this.payment.nextBillingDate.date).toLocaleDateString(undefined, {
|
|
32
32
|
year: 'numeric',
|
|
33
33
|
month: 'short',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/models/plan.ts"],"names":[],"mappings":"AAoCA,MAAM,OAAO,WAAW;IAOtB,YAAY,IAAU;;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,MAAA,IAAI,CAAC,QAAQ,mCAAI,KAAK,CAAC,CAAC,cAAc;IACxD,CAAC;IAED,IAAI,EAAE;QACJ,yBAAyB;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5C,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED,SAAS,CAAC,SAAiB;QACzB,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IAC/B,CAAC;IAED,kBAAkB,CAAC,OAAe;QAChC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC;QACzE,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,GAAG,OAAO,CAAC;IAC9C,CAAC;IAED,IAAI,SAAS;QACX,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/models/plan.ts"],"names":[],"mappings":"AAoCA,MAAM,OAAO,WAAW;IAOtB,YAAY,IAAU;;QACpB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,MAAA,IAAI,CAAC,QAAQ,mCAAI,KAAK,CAAC,CAAC,cAAc;IACxD,CAAC;IAED,IAAI,EAAE;QACJ,yBAAyB;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;IACzB,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,IAAI,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5C,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED,SAAS,CAAC,SAAiB;QACzB,IAAI,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;IAC/B,CAAC;IAED,kBAAkB,CAAC,OAAe;QAChC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC;QACzE,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,GAAG,OAAO,CAAC;IAC9C,CAAC;IAED,IAAI,SAAS;QACX,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,qBAAqB;QACvB,MAAM,eAAe,GAAG,IAAI,IAAI,CAC9B,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAClC,CAAC,kBAAkB,CAAC,SAAS,EAAE;YAC9B,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,OAAO;YACd,GAAG,EAAE,SAAS;SACf,CAAC,CAAC;QAEH,OAAO,eAAe,aAAf,eAAe,cAAf,eAAe,GAAI,WAAW,CAAC;IACxC,CAAC;IAED,IAAI,qBAAqB;QACvB,MAAM,eAAe,GAAG,IAAI,IAAI,CAC9B,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAClC,CAAC,kBAAkB,CAAC,SAAS,EAAE;YAC9B,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,OAAO;YACd,GAAG,EAAE,SAAS;SACf,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,eAAe,CAAC,CAAC;QAE3D,OAAO,eAAe,aAAf,eAAe,cAAf,eAAe,GAAI,WAAW,CAAC;IACxC,CAAC;IAED,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC;IACxC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC3B,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC/B,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;;IAwBI","sourcesContent":["type BtData = {\n billingDayOfMonth: number;\n nextBillingDate: {\n date: string;\n timezone_type: number;\n timezone: string;\n oldDate?: string; // optional for updates ISO UTC date string\n };\n lastBillingDate: {\n date: string;\n timezone_type: number;\n timezone: string;\n };\n status: string; // active, inactive\n paymentMethodType: string; // cc, paypal, venmo, etc\n last4: string | null;\n cardType: string | null;\n expirationMonth: string | null;\n expirationYear: string | null;\n paypalEmail?: string;\n venmoUsername?: string;\n};\n\ntype Plan = {\n token: string;\n amount: number;\n currency: string;\n start_date: string; // UTC\n is_test: boolean;\n btdata: BtData;\n oldAmount?: number;\n oldDate?: string;\n oldPaymentMethod?: string;\n isCancelled?: boolean;\n};\n\nexport class MonthlyPlan {\n plan: Plan;\n\n currency: string;\n\n payment: BtData;\n\n constructor(plan: Plan) {\n this.plan = plan;\n this.payment = plan.btdata;\n this.currency = plan.currency ?? 'USD'; // not in data\n }\n\n get id(): string {\n // use token as unique id\n return this.plan.token;\n }\n\n get currencySymbol(): string {\n return this.currency === 'USD' ? '$' : '';\n }\n\n get amount(): number {\n return this.plan.amount;\n }\n\n setAmount(newAmount: number) {\n this.plan.oldAmount = this.plan.amount;\n this.plan.amount = newAmount;\n }\n\n setNextBillingDate(newDate: string): void {\n this.payment.nextBillingDate.oldDate = this.payment.nextBillingDate.date;\n this.payment.nextBillingDate.date = newDate;\n }\n\n get startDate(): string {\n const date = new Date(this.plan.start_date);\n return date.toLocaleDateString();\n }\n\n get nextBillingDateLocale(): string {\n const nextBillingDate = new Date(\n this.payment.nextBillingDate.date\n ).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n\n return nextBillingDate ?? 'not found';\n }\n\n get lastBillingDateLocale(): string {\n const lastBillingDate = new Date(\n this.payment.lastBillingDate.date\n ).toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n\n console.log('lastBillingDate from model', lastBillingDate);\n\n return lastBillingDate ?? 'not found';\n }\n\n get hasBeenCancelled(): boolean {\n return this.plan.isCancelled === true;\n }\n\n get isTest(): boolean {\n return this.plan.is_test;\n }\n\n cancelPlan(): void {\n this.plan.isCancelled = true;\n }\n}\n\n/*\n\n{\n \"token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJtYWlsc3luYyIsImlhdCI6MTczODYxNTY3NS41ODA4MTcsIm5iZiI6MTczODYxNTYxNS41ODA4MTcsImV4cCI6MTczODYxNjI3NS41ODA4MTcsImtleSI6eyJwaWQiOiJkd2NrN20iLCJjaWQiOjgwMzUzOCwiYW1vdW50Ijo1LCJwYXltZW50TWV0aG9kVG9rZW4iOiJxMXllYndoaiIsImN1c3RvbWVySWQiOiI4NTQ2MTk4MzUifSwidXNlciI6IkBpc2EtYXQtdGhlLWFyY2hpdmUifQ.TYlkU1ZZLHmj2ahrkTV7JGLmpCPN4BcOeDFPiXVj0pM\",\n \"amount\": 5,\n \"currency\": \"USD\",\n \"start_date\": \"2022-12-09 00:00:00\",\n \"contribution_status_id\": 5,\n \"is_test\": true,\n \"btdata\": {\n \"billingDayOfMonth\": 9,\n \"nextBillingDate\": {\n \"date\": \"2025-02-09 00:00:00.000000\",\n \"timezone_type\": 3,\n \"timezone\": \"UTC\"\n },\n \"status\": \"Active\",\n \"paymentMethodType\": \"creditCard\",\n \"last4\": \"1111\",\n \"cardType\": \"Visa\",\n \"expirationMonth\": \"12\",\n \"expirationYear\": \"2023\"\n }\n}\n */\n"]}
|
package/dist/src/plans.js
CHANGED
package/dist/src/plans.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../../src/plans.ts"],"names":[],"mappings":";AAAA,sCAAsC;AACtC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAI5D,OAAO,4BAA4B,CAAC;AAIpC,IAAa,YAAY,GAAzB,MAAa,YAAa,SAAQ,UAAU;IAA5C;;QAC6B,UAAK,GAAG,EAAE,CAAC;QAEM,YAAO,GAAG,KAAK,CAAC;IA+L9D,CAAC;IA7LW,MAAM;QACd,OAAO,IAAI,CAAA;;;YAGH,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAiB,EAAE,EAAE;;YACrC,IAAI,UAAU,GACZ,MAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,iBAAiB,mCAAI,kBAAkB,CAAC;YACxD,IAAI,UAAU,KAAK,YAAY,EAAE;gBAC/B,UAAU,GAAG,aAAa,CAAC;aAC5B;YACD,MAAM,QAAQ,GAAG,MAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,QAAQ,mCAAI,qBAAqB,CAAC;YACjE,MAAM,KAAK,GAAG,CAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,KAAK;gBAC/B,CAAC,CAAC,MAAM,MAAA,IAAI,CAAC,OAAO,0CAAE,KAAK,EAAE;gBAC7B,CAAC,CAAC,qBAAqB,CAAC;YAE1B,OAAO,IAAI,CAAA;0BACG,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE;;;;;wBAK/C,IAAI,CAAC,QAAQ;wBACb,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,MAAM;;sBAEnC,IAAI,CAAC,MAAM;gBACX,CAAC,CAAC,IAAI,CAAA,uCAAuC;gBAC7C,CAAC,CAAC,OAAO;;;;yBAIN,UAAU;sBACb,CAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,iBAAiB,MAAK,YAAY;gBAChD,CAAC,CAAC,IAAI,CAAA,MAAM,QAAQ;+BACX,KAAK,MAAM;gBACpB,CAAC,CAAC,OAAO;sBACT,CAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,iBAAiB,MAAK,QAAQ;gBAC5C,CAAC,CAAC,IAAI,CAAA;;oCAEQ,UAAU,MAAA,IAAI,CAAC,OAAO,0CAAE,WAAW,EAAE;+BAC1C,MAAA,IAAI,CAAC,OAAO,0CAAE,WAAW;;6BAE3B;gBACP,CAAC,CAAC,OAAO;sBACT,CAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,iBAAiB,MAAK,OAAO;gBAC3C,CAAC,CAAC,IAAI,CAAA;;oCAEQ,UAAU,MAAA,IAAI,CAAC,OAAO,0CAAE,aAAa,EAAE;+BAC5C,MAAA,IAAI,CAAC,OAAO,0CAAE,WAAW;;6BAE3B;gBACP,CAAC,CAAC,OAAO;sBACT,CAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,iBAAiB,MAAK,YAAY;gBAChD,CAAC,CAAC,IAAI,CAAA;;4BAEA,MAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,eAAe,mCAC/B,iBAAiB,IAAI,MAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,cAAc,mCACjD,gBAAgB;6BACb;gBACP,CAAC,CAAC,OAAO;;;;yBAIN,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"plans.js","sourceRoot":"","sources":["../../src/plans.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable no-param-reassign */\nimport { LitElement, html, css, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\n\nimport type { MonthlyPlan } from './models/plan';\n\nimport './presentational/ia-button';\nimport type { IauxButton } from './presentational/ia-button';\n\n@customElement('ia-mgc-plans')\nexport class IauxMgcPlans extends LitElement {\n @property({ type: Array }) plans = [];\n\n @property({ type: Boolean, reflect: true }) canEdit = false;\n\n protected render() {\n return html`\n <section class=\"monthly-giving-circle\">\n <ul>\n ${this.plans.map((plan: MonthlyPlan) => {\n let methodType =\n plan.payment?.paymentMethodType ?? 'Method not found';\n if (methodType === 'creditCard') {\n methodType = 'Credit card';\n }\n const cardType = plan.payment?.cardType ?? 'Card type not found';\n const last4 = plan.payment?.last4\n ? `...${plan.payment?.last4}`\n : 'CC number not found';\n\n return html`\n <li class=${`${plan.plan.isCancelled ? 'cancelled' : ''}`}>\n <div class=\"info\">\n <div class=\"amount\">\n <h3>Amount</h3>\n <p>\n ${plan.currency}\n ${plan.currencySymbol}${plan.amount}/month\n </p>\n ${plan.isTest\n ? html`<p class=\"is-test\">(Test payment)</p>`\n : nothing}\n </div>\n <div class=\"payment-details\">\n <h3>Method</h3>\n <p>${methodType}</p>\n ${plan.payment?.paymentMethodType === 'creditCard'\n ? html`<p>${cardType}</p>\n <p>${last4}</p>`\n : nothing}\n ${plan.payment?.paymentMethodType === 'Paypal'\n ? html`<p>\n Paypal email:\n <a href=${`mailto:${plan.payment?.paypalEmail}`}\n >${plan.payment?.paypalEmail}</a\n >\n </p>`\n : nothing}\n ${plan.payment?.paymentMethodType === 'Venmo'\n ? html`<p>\n Venmo username:\n <a href=${`mailto:${plan.payment?.venmoUsername}`}\n >${plan.payment?.paypalEmail}</a\n >\n </p>`\n : nothing}\n ${plan.payment?.paymentMethodType !== 'creditCard'\n ? html`<p>\n Expires:\n ${plan.payment?.expirationMonth ??\n 'month not found'}/${plan.payment?.expirationYear ??\n 'year not found'}\n </p>`\n : nothing}\n </div>\n <div class=\"next-donation\">\n <h3>Next Donation</h3>\n <p>${plan.nextBillingDateLocale}</p>\n </div>\n </div>\n ${this.planCTA(plan)}\n </li>\n `;\n })}\n </ul>\n </section>\n `;\n }\n\n planCTA(plan: MonthlyPlan) {\n if (!this.canEdit) {\n const mailToText = `mailto:donations@archive.org?subject=I'd like to update my monthly donation`;\n return html`<p class=\"email-edit-plan\">\n Need to update your plan further? Please email us at\n <a href=${mailToText}>donations@archive.org</a>.\n </p>`;\n }\n\n const ctaText = plan.plan.isCancelled\n ? 'Plan is cancelled'\n : 'Manage this monthly donation';\n\n return html`<ia-button\n class=\"ia-button link edit-donation\"\n .isDisabled=${plan.plan.isCancelled}\n .clickHandler=${async (e: Event, iaButton: IauxButton) => {\n // disable button\n iaButton.isDisabled = true;\n // open form\n this.dispatchEvent(\n new CustomEvent('editThisPlan', { detail: { plan } })\n );\n }}\n >${ctaText}</ia-button\n >`;\n }\n\n static styles = css`\n :host {\n max-height: 500px;\n overflow-y: scroll;\n display: block;\n }\n\n .is-test {\n font-size: 0.8rem;\n }\n\n li {\n border: 1px solid #23765d;\n background-color: #eeffee;\n display: block;\n width: inherit;\n }\n li.cancelled {\n background-color: lightgoldenrodyellow;\n }\n table {\n width: 100%;\n text-align: left;\n max-width: 600px;\n }\n\n ul {\n padding: 0;\n list-style-type: none;\n margin: 0;\n }\n\n ul li {\n border: 1px solid #23765d;\n background-color: #eeffee;\n margin: 0.5rem 0;\n padding: 0.5rem 0.5rem 1rem 0.5rem;\n position: relative;\n }\n\n ul li button.edit-donation {\n height: 30px;\n display: block;\n position: absolute;\n bottom: 0;\n }\n\n ul li .info {\n display: grid;\n min-height: 90px;\n grid-template-columns: 0.5fr 1fr 0.5fr;\n grid-template-rows: 1fr;\n gap: 0px 5px;\n grid-auto-flow: row;\n grid-template-areas: 'amount details next-donation';\n }\n\n ul li .info .amount {\n grid-area: amount;\n }\n\n ul li .info .payment-details {\n grid-area: details;\n }\n\n ul li .info .next-donation {\n grid-area: next-donation;\n }\n\n ul li .info > * {\n margin: 0 0 0.5rem 0;\n }\n\n ul li .info > * > * {\n margin: 0;\n }\n\n .email-edit-plan {\n margin-bottom: 0;\n }\n\n @media screen and (max-width: 500px) {\n ul li .info {\n display: block;\n }\n }\n `;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '../../src/form-sections/date';
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
import { html, fixture, expect } from '@open-wc/testing';
|
|
3
|
+
import '../../src/form-sections/date';
|
|
4
|
+
import { MonthlyPlan } from '../../src/models/plan';
|
|
5
|
+
const lastPaymentWasOnTheFirstOfThisMonth = new Date();
|
|
6
|
+
lastPaymentWasOnTheFirstOfThisMonth.setHours(0, 0, 0, 0);
|
|
7
|
+
lastPaymentWasOnTheFirstOfThisMonth.setDate(1);
|
|
8
|
+
console.log('lastPaymentWasOnTheFirstOfThisMonth', lastPaymentWasOnTheFirstOfThisMonth.toISOString());
|
|
9
|
+
const nextMonth = new Date();
|
|
10
|
+
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
|
11
|
+
const nextPaymentFirstOfMonth = new Date(nextMonth);
|
|
12
|
+
nextPaymentFirstOfMonth.setHours(0, 0, 0, 0);
|
|
13
|
+
nextPaymentFirstOfMonth.setDate(1);
|
|
14
|
+
console.log('nextPaymentFirstOfMonth', nextPaymentFirstOfMonth.toISOString());
|
|
15
|
+
const twelveMonthsFromNow = new Date();
|
|
16
|
+
twelveMonthsFromNow.setMonth(twelveMonthsFromNow.getMonth() + 12);
|
|
17
|
+
const twoYearsFromNow = new Date();
|
|
18
|
+
twoYearsFromNow.setFullYear(twoYearsFromNow.getFullYear() + 2);
|
|
19
|
+
twoYearsFromNow.setHours(0, 0, 0, 0);
|
|
20
|
+
const tomorrow = new Date();
|
|
21
|
+
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
22
|
+
const today = new Date();
|
|
23
|
+
today.setHours(0, 0, 0, 0);
|
|
24
|
+
const yesterday = new Date();
|
|
25
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
26
|
+
yesterday.setHours(0, 0, 0, 0);
|
|
27
|
+
const plan = new MonthlyPlan({
|
|
28
|
+
token: 'a.va.lid.T0ken',
|
|
29
|
+
amount: 5,
|
|
30
|
+
currency: 'USD',
|
|
31
|
+
start_date: '2024-07-01 00:00:00',
|
|
32
|
+
is_test: true,
|
|
33
|
+
btdata: {
|
|
34
|
+
billingDayOfMonth: 22,
|
|
35
|
+
nextBillingDate: {
|
|
36
|
+
date: nextPaymentFirstOfMonth.toISOString(),
|
|
37
|
+
timezone_type: 3,
|
|
38
|
+
timezone: 'UTC',
|
|
39
|
+
},
|
|
40
|
+
lastBillingDate: {
|
|
41
|
+
date: lastPaymentWasOnTheFirstOfThisMonth.toISOString(),
|
|
42
|
+
timezone_type: 3,
|
|
43
|
+
timezone: 'UTC',
|
|
44
|
+
},
|
|
45
|
+
status: 'Active',
|
|
46
|
+
paymentMethodType: 'Venmo',
|
|
47
|
+
last4: null,
|
|
48
|
+
cardType: null,
|
|
49
|
+
expirationMonth: null,
|
|
50
|
+
expirationYear: null,
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
describe('<ia-mgc-edit-date>', () => {
|
|
54
|
+
it('can toggle form', async () => {
|
|
55
|
+
var _a, _b, _c, _d;
|
|
56
|
+
const el = await fixture(html `<ia-mgc-edit-date .plan=${plan}></ia-mgc-edit-date>`);
|
|
57
|
+
const amountLabel = (_a = el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.current-date');
|
|
58
|
+
expect(amountLabel).to.exist;
|
|
59
|
+
expect(amountLabel === null || amountLabel === void 0 ? void 0 : amountLabel.textContent).to.contain(plan.nextBillingDateLocale);
|
|
60
|
+
const cta = (_b = el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('ia-button#open-edit-date-form');
|
|
61
|
+
expect(cta).to.exist;
|
|
62
|
+
// does not show form
|
|
63
|
+
expect(el.form).to.not.exist;
|
|
64
|
+
// does show form on Edit... click
|
|
65
|
+
cta.shadowRoot.querySelector('button').click();
|
|
66
|
+
await el.updateComplete;
|
|
67
|
+
expect(el.form).to.exist;
|
|
68
|
+
expect(el.hasAttribute('currentlyediting')).to.be.true;
|
|
69
|
+
// form now displays
|
|
70
|
+
expect(el.form.getAttribute('id')).to.equal('edit-date');
|
|
71
|
+
const lastDateLabel = el.form.querySelector('#form-info-last-donation-date');
|
|
72
|
+
const nextDateLabel = el.form.querySelector('#form-info-next-donation-date');
|
|
73
|
+
expect(lastDateLabel).to.contain.text(plan.lastBillingDateLocale);
|
|
74
|
+
expect(nextDateLabel).to.contain.text(plan.nextBillingDateLocale);
|
|
75
|
+
const requestDateUpdateButton = el.form.querySelector('ia-button#edit-date');
|
|
76
|
+
expect(requestDateUpdateButton).to.exist;
|
|
77
|
+
expect(requestDateUpdateButton.hasAttribute('isdisabled')).to.be.true;
|
|
78
|
+
expect(el.form.getAttribute('id')).to.equal('edit-date');
|
|
79
|
+
// input has min and max range set
|
|
80
|
+
// min is tomorrow, max is 12 months from now
|
|
81
|
+
const dateInput = el.form.querySelector('input');
|
|
82
|
+
expect(dateInput).to.exist;
|
|
83
|
+
expect(dateInput.getAttribute('type')).to.equal('date');
|
|
84
|
+
expect(dateInput.getAttribute('min')).to.equal(`${tomorrow.getFullYear()}-${String(tomorrow.getMonth() + 1).padStart(2, '0')}-${String(tomorrow.getDate()).padStart(2, '0')}`);
|
|
85
|
+
expect(dateInput.getAttribute('max')).to.equal(`${twelveMonthsFromNow.getFullYear()}-${String(twelveMonthsFromNow.getMonth() + 1).padStart(2, '0')}-${String(twelveMonthsFromNow.getDate()).padStart(2, '0')}`);
|
|
86
|
+
// checks if input value is invalid
|
|
87
|
+
// date before today
|
|
88
|
+
dateInput.setAttribute('value', '2008-11-11');
|
|
89
|
+
dateInput.dispatchEvent(new Event('change'));
|
|
90
|
+
await el.updateComplete;
|
|
91
|
+
expect(el.errorMessage).to.contain('Date must be at least tomorrow.');
|
|
92
|
+
expect(requestDateUpdateButton.hasAttribute('isdisabled')).to.be.true;
|
|
93
|
+
// date within 12 months
|
|
94
|
+
const twoYearsFromNowStr = `${twoYearsFromNow.getFullYear()}-${String(twoYearsFromNow.getMonth() + 1).padStart(2, '0')}-${String(twoYearsFromNow.getDate()).padStart(2, '0')}`;
|
|
95
|
+
dateInput.setAttribute('value', twoYearsFromNowStr);
|
|
96
|
+
dateInput.dispatchEvent(new Event('change'));
|
|
97
|
+
await el.updateComplete;
|
|
98
|
+
expect(el.errorMessage).to.contain('New donation date must be within the next 12 months.');
|
|
99
|
+
expect(requestDateUpdateButton.hasAttribute('isdisabled')).to.be.true;
|
|
100
|
+
// sets warning message when chosen date is in the same month as last payment
|
|
101
|
+
const lastDayOfCurrentMonth = new Date();
|
|
102
|
+
lastDayOfCurrentMonth.setHours(0, 0, 0, 0);
|
|
103
|
+
lastDayOfCurrentMonth.setMonth(lastDayOfCurrentMonth.getMonth() + 1);
|
|
104
|
+
lastDayOfCurrentMonth.setDate(0);
|
|
105
|
+
const lastDayOfCurrentMonthStr = `${lastDayOfCurrentMonth.getFullYear()}-${String(lastDayOfCurrentMonth.getMonth() + 1).padStart(2, '0')}-${lastDayOfCurrentMonth.getDate()}`;
|
|
106
|
+
dateInput.setAttribute('value', lastDayOfCurrentMonthStr);
|
|
107
|
+
dateInput.dispatchEvent(new Event('change'));
|
|
108
|
+
await el.updateComplete;
|
|
109
|
+
expect(el.errorMessage).to.contain('');
|
|
110
|
+
expect(el.warningMessage).to.contain('New donation date is in the same month as your last payment.');
|
|
111
|
+
expect(el.allowEditing).to.be.true;
|
|
112
|
+
expect(requestDateUpdateButton.hasAttribute('isdisabled')).to.be.true;
|
|
113
|
+
expect(el.newDate).to.contain(`${lastDayOfCurrentMonth.getFullYear()}-${String(lastDayOfCurrentMonth.getMonth() + 1).padStart(2, '0')}-${String(lastDayOfCurrentMonth.getDate()).padStart(2, '0')}`);
|
|
114
|
+
// can submit when date is valid
|
|
115
|
+
const nextMonthStr = `${nextMonth.getFullYear()}-${String(nextMonth.getMonth() + 1).padStart(2, '0')}-${nextMonth.getDate()}`;
|
|
116
|
+
dateInput.setAttribute('value', nextMonthStr);
|
|
117
|
+
dateInput.dispatchEvent(new Event('change'));
|
|
118
|
+
await el.updateComplete;
|
|
119
|
+
expect(el.errorMessage).to.contain('');
|
|
120
|
+
expect(el.newDate).to.contain(nextMonthStr);
|
|
121
|
+
expect(el.allowEditing).to.be.true;
|
|
122
|
+
expect(requestDateUpdateButton.hasAttribute('isdisabled')).to.be.false;
|
|
123
|
+
console.log(' ~~~ last test, button: ', requestDateUpdateButton);
|
|
124
|
+
// clicking Update fires a Custom Event
|
|
125
|
+
el.addEventListener('updateDate', (event) => {
|
|
126
|
+
console.log('updateDate event received ####', event);
|
|
127
|
+
const { newDate } = event.detail;
|
|
128
|
+
expect(newDate).to.contain(nextMonthStr);
|
|
129
|
+
});
|
|
130
|
+
(_d = (_c = requestDateUpdateButton.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('button')) === null || _d === void 0 ? void 0 : _d.click();
|
|
131
|
+
await el.updateComplete;
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
//# sourceMappingURL=date.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date.test.js","sourceRoot":"","sources":["../../../test/form-sections/date.test.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line import/no-extraneous-dependencies\nimport { html, fixture, expect } from '@open-wc/testing';\n\nimport '../../src/form-sections/date';\nimport type { MGCEditPlanDate } from '../../src/form-sections/date';\nimport { MonthlyPlan } from '../../src/models/plan';\nimport type { IauxButton } from '../../src/presentational/ia-button';\n\nconst lastPaymentWasOnTheFirstOfThisMonth = new Date();\nlastPaymentWasOnTheFirstOfThisMonth.setHours(0, 0, 0, 0);\nlastPaymentWasOnTheFirstOfThisMonth.setDate(1);\nconsole.log(\n 'lastPaymentWasOnTheFirstOfThisMonth',\n lastPaymentWasOnTheFirstOfThisMonth.toISOString()\n);\n\nconst nextMonth = new Date();\nnextMonth.setMonth(nextMonth.getMonth() + 1);\n\nconst nextPaymentFirstOfMonth = new Date(nextMonth);\nnextPaymentFirstOfMonth.setHours(0, 0, 0, 0);\nnextPaymentFirstOfMonth.setDate(1);\nconsole.log('nextPaymentFirstOfMonth', nextPaymentFirstOfMonth.toISOString());\n\nconst twelveMonthsFromNow = new Date();\ntwelveMonthsFromNow.setMonth(twelveMonthsFromNow.getMonth() + 12);\n\nconst twoYearsFromNow = new Date();\ntwoYearsFromNow.setFullYear(twoYearsFromNow.getFullYear() + 2);\ntwoYearsFromNow.setHours(0, 0, 0, 0);\n\nconst tomorrow = new Date();\ntomorrow.setDate(tomorrow.getDate() + 1);\n\nconst today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\nconst yesterday = new Date();\nyesterday.setDate(yesterday.getDate() - 1);\nyesterday.setHours(0, 0, 0, 0);\n\nconst plan = new MonthlyPlan({\n token: 'a.va.lid.T0ken',\n amount: 5,\n currency: 'USD',\n start_date: '2024-07-01 00:00:00',\n is_test: true,\n btdata: {\n billingDayOfMonth: 22,\n nextBillingDate: {\n date: nextPaymentFirstOfMonth.toISOString(),\n timezone_type: 3,\n timezone: 'UTC',\n },\n lastBillingDate: {\n date: lastPaymentWasOnTheFirstOfThisMonth.toISOString(),\n timezone_type: 3,\n timezone: 'UTC',\n },\n status: 'Active',\n paymentMethodType: 'Venmo',\n last4: null,\n cardType: null,\n expirationMonth: null,\n expirationYear: null,\n },\n});\n\ndescribe('<ia-mgc-edit-date>', () => {\n it('can toggle form', async () => {\n const el = await fixture<MGCEditPlanDate>(\n html`<ia-mgc-edit-date .plan=${plan}></ia-mgc-edit-date>`\n );\n\n const amountLabel = el.shadowRoot?.querySelector('.current-date');\n expect(amountLabel).to.exist;\n expect(amountLabel?.textContent).to.contain(plan.nextBillingDateLocale);\n\n const cta = el.shadowRoot?.querySelector('ia-button#open-edit-date-form');\n expect(cta).to.exist;\n\n // does not show form\n expect(el.form).to.not.exist;\n\n // does show form on Edit... click\n cta!.shadowRoot!.querySelector('button')!.click();\n await el.updateComplete;\n\n expect(el.form).to.exist;\n\n expect(el.hasAttribute('currentlyediting')).to.be.true;\n\n // form now displays\n expect(el.form.getAttribute('id')).to.equal('edit-date');\n\n const lastDateLabel = el.form.querySelector(\n '#form-info-last-donation-date'\n );\n const nextDateLabel = el.form.querySelector(\n '#form-info-next-donation-date'\n );\n\n expect(lastDateLabel).to.contain.text(plan.lastBillingDateLocale);\n expect(nextDateLabel).to.contain.text(plan.nextBillingDateLocale);\n\n const requestDateUpdateButton = el.form.querySelector(\n 'ia-button#edit-date'\n ) as IauxButton;\n expect(requestDateUpdateButton).to.exist;\n expect(requestDateUpdateButton!.hasAttribute('isdisabled')).to.be.true;\n\n expect(el.form.getAttribute('id')).to.equal('edit-date');\n\n // input has min and max range set\n // min is tomorrow, max is 12 months from now\n const dateInput = el.form.querySelector('input');\n expect(dateInput).to.exist;\n expect(dateInput!.getAttribute('type')).to.equal('date');\n expect(dateInput!.getAttribute('min')).to.equal(\n `${tomorrow.getFullYear()}-${String(tomorrow.getMonth() + 1).padStart(\n 2,\n '0'\n )}-${String(tomorrow.getDate()).padStart(2, '0')}`\n );\n expect(dateInput!.getAttribute('max')).to.equal(\n `${twelveMonthsFromNow.getFullYear()}-${String(\n twelveMonthsFromNow.getMonth() + 1\n ).padStart(2, '0')}-${String(twelveMonthsFromNow.getDate()).padStart(\n 2,\n '0'\n )}`\n );\n\n // checks if input value is invalid\n // date before today\n dateInput!.setAttribute('value', '2008-11-11');\n dateInput!.dispatchEvent(new Event('change'));\n await el.updateComplete;\n\n expect(el.errorMessage).to.contain('Date must be at least tomorrow.');\n expect(requestDateUpdateButton!.hasAttribute('isdisabled')).to.be.true;\n\n // date within 12 months\n const twoYearsFromNowStr = `${twoYearsFromNow.getFullYear()}-${String(\n twoYearsFromNow.getMonth() + 1\n ).padStart(2, '0')}-${String(twoYearsFromNow.getDate()).padStart(2, '0')}`;\n dateInput!.setAttribute('value', twoYearsFromNowStr);\n dateInput!.dispatchEvent(new Event('change'));\n await el.updateComplete;\n\n expect(el.errorMessage).to.contain(\n 'New donation date must be within the next 12 months.'\n );\n expect(requestDateUpdateButton!.hasAttribute('isdisabled')).to.be.true;\n\n // sets warning message when chosen date is in the same month as last payment\n const lastDayOfCurrentMonth = new Date();\n lastDayOfCurrentMonth.setHours(0, 0, 0, 0);\n lastDayOfCurrentMonth.setMonth(lastDayOfCurrentMonth.getMonth() + 1);\n lastDayOfCurrentMonth.setDate(0);\n\n const lastDayOfCurrentMonthStr = `${lastDayOfCurrentMonth.getFullYear()}-${String(\n lastDayOfCurrentMonth.getMonth() + 1\n ).padStart(2, '0')}-${lastDayOfCurrentMonth.getDate()}`;\n dateInput!.setAttribute('value', lastDayOfCurrentMonthStr);\n dateInput!.dispatchEvent(new Event('change'));\n await el.updateComplete;\n\n expect(el.errorMessage).to.contain('');\n expect(el.warningMessage).to.contain(\n 'New donation date is in the same month as your last payment.'\n );\n expect(el.allowEditing).to.be.true;\n expect(requestDateUpdateButton!.hasAttribute('isdisabled')).to.be.true;\n expect(el.newDate).to.contain(\n `${lastDayOfCurrentMonth.getFullYear()}-${String(\n lastDayOfCurrentMonth.getMonth() + 1\n ).padStart(2, '0')}-${String(lastDayOfCurrentMonth.getDate()).padStart(\n 2,\n '0'\n )}`\n );\n\n // can submit when date is valid\n const nextMonthStr = `${nextMonth.getFullYear()}-${String(\n nextMonth.getMonth() + 1\n ).padStart(2, '0')}-${nextMonth.getDate()}`;\n dateInput!.setAttribute('value', nextMonthStr);\n dateInput!.dispatchEvent(new Event('change'));\n\n await el.updateComplete;\n\n expect(el.errorMessage).to.contain('');\n expect(el.newDate).to.contain(nextMonthStr);\n expect(el.allowEditing).to.be.true;\n expect(requestDateUpdateButton!.hasAttribute('isdisabled')).to.be.false;\n console.log(' ~~~ last test, button: ', requestDateUpdateButton);\n\n // clicking Update fires a Custom Event\n el.addEventListener('updateDate', (event: Event) => {\n console.log('updateDate event received ####', event);\n const { newDate } = (event as CustomEvent).detail;\n expect(newDate).to.contain(nextMonthStr);\n });\n\n requestDateUpdateButton.shadowRoot?.querySelector('button')?.click();\n await el.updateComplete;\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -48,7 +48,7 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
48
48
|
|
|
49
49
|
updated(changed: PropertyValues) {
|
|
50
50
|
if (changed.has('currentlyEditing') && this.currentlyEditing) {
|
|
51
|
-
this.
|
|
51
|
+
this.dateInput.focus();
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -61,13 +61,13 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
61
61
|
>
|
|
62
62
|
${!this.currentlyEditing
|
|
63
63
|
? html` <p class="current-date">
|
|
64
|
-
${this.plan?.
|
|
64
|
+
${this.plan?.nextBillingDateLocale}
|
|
65
65
|
<ia-mgc-update-status .status=${this.updateStatus}
|
|
66
66
|
>${this.updateMessage}</ia-mgc-update-status
|
|
67
67
|
>
|
|
68
68
|
</p>
|
|
69
69
|
<ia-button
|
|
70
|
-
id="edit-date"
|
|
70
|
+
id="open-edit-date-form"
|
|
71
71
|
class="ia-button link"
|
|
72
72
|
.clickHandler=${() => {
|
|
73
73
|
this.currentlyEditing = true;
|
|
@@ -99,18 +99,13 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
|
|
103
|
-
false;
|
|
104
|
-
|
|
102
|
+
this.allowEditing = false;
|
|
105
103
|
await this.updateComplete;
|
|
106
104
|
}
|
|
107
105
|
|
|
108
106
|
/* Dispatches edit-date change request */
|
|
109
107
|
requestDateUpdate(e: Event): void {
|
|
110
108
|
e.preventDefault();
|
|
111
|
-
console.log('<plan-date> - requestDateUpdate', {
|
|
112
|
-
newValue: this.newDate,
|
|
113
|
-
});
|
|
114
109
|
this.dispatchEvent(
|
|
115
110
|
new CustomEvent('updateDate', {
|
|
116
111
|
detail: {
|
|
@@ -125,13 +120,11 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
125
120
|
this.clearInputField();
|
|
126
121
|
this.clearStatusMessaging();
|
|
127
122
|
this.currentlyEditing = false;
|
|
123
|
+
this.allowEditing = false;
|
|
128
124
|
}
|
|
129
125
|
|
|
130
126
|
clearInputField() {
|
|
131
|
-
|
|
132
|
-
'input[name="edit-date"]'
|
|
133
|
-
) as HTMLInputElement;
|
|
134
|
-
input.value = '';
|
|
127
|
+
this.dateInput.value = '';
|
|
135
128
|
this.newDate = undefined;
|
|
136
129
|
}
|
|
137
130
|
|
|
@@ -157,26 +150,23 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
157
150
|
const today = new Date();
|
|
158
151
|
const year = today.getFullYear() + 1; // Allow up to one year in the future
|
|
159
152
|
const month = String(today.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
|
|
160
|
-
|
|
161
|
-
return `${year}-${month}-${lastDayOfMonth}`; // Last day of the month
|
|
153
|
+
return `${year}-${month}-${today.getDate()}`;
|
|
162
154
|
}
|
|
163
155
|
|
|
164
156
|
get editDateForm(): TemplateResult {
|
|
165
|
-
console.log('editdate', {
|
|
166
|
-
min: this.minDate,
|
|
167
|
-
max: this.maxDate,
|
|
168
|
-
plan: this.plan,
|
|
169
|
-
nextBillingDate: this.plan?.nextBillingDate,
|
|
170
|
-
lastBillingDate: this.plan?.lastBillingDateLocale,
|
|
171
|
-
});
|
|
172
157
|
return html`
|
|
173
158
|
<section>
|
|
174
159
|
<form id="edit-date">
|
|
175
|
-
<p
|
|
160
|
+
<p id="form-info-last-donation-date">
|
|
161
|
+
Last donation date: ${this.plan?.lastBillingDateLocale}
|
|
162
|
+
</p>
|
|
176
163
|
|
|
177
|
-
<p
|
|
164
|
+
<p id="form-info-next-donation-date">
|
|
165
|
+
Next donation date: ${this.plan?.nextBillingDateLocale}
|
|
166
|
+
</p>
|
|
178
167
|
<div class="date-holder">
|
|
179
168
|
<input
|
|
169
|
+
required
|
|
180
170
|
type="date"
|
|
181
171
|
id="edit-date"
|
|
182
172
|
name="edit-date"
|
|
@@ -184,30 +174,27 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
184
174
|
max=${this.maxDate}
|
|
185
175
|
value=""
|
|
186
176
|
@focus=${() => this.clearStatusMessaging()}
|
|
187
|
-
@change=${async (
|
|
177
|
+
@change=${async () => {
|
|
188
178
|
this.clearStatusMessaging();
|
|
189
179
|
await this.updateComplete;
|
|
190
180
|
|
|
181
|
+
const inputValue = this.dateInput.value;
|
|
191
182
|
console.log(
|
|
192
|
-
'date changed',
|
|
193
|
-
|
|
183
|
+
' ----- date input changed ----- ',
|
|
184
|
+
inputValue,
|
|
185
|
+
this.errorMessage
|
|
194
186
|
);
|
|
195
|
-
console.log('date changed THIS', this);
|
|
196
187
|
|
|
197
|
-
const inputValue = (e.target as HTMLInputElement).value;
|
|
198
188
|
if (!inputValue) {
|
|
199
189
|
this.errorMessage = 'Please enter a date';
|
|
200
|
-
this.allowEditing =
|
|
190
|
+
this.allowEditing = false;
|
|
201
191
|
return; // wait until date field returns a valid string
|
|
202
192
|
}
|
|
203
193
|
|
|
204
194
|
let validDate;
|
|
205
195
|
try {
|
|
206
|
-
validDate = new Date(
|
|
207
|
-
(e.target as HTMLInputElement)?.value as string
|
|
208
|
-
);
|
|
196
|
+
validDate = new Date(`${inputValue}T00:00:00`);
|
|
209
197
|
} catch (error) {
|
|
210
|
-
console.error('Invalid date format:', error);
|
|
211
198
|
this.errorMessage =
|
|
212
199
|
'Please enter a valid date format (YYYY-MM-DD)';
|
|
213
200
|
return; // wait until date field returns a valid string
|
|
@@ -227,16 +214,10 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
227
214
|
return;
|
|
228
215
|
}
|
|
229
216
|
|
|
230
|
-
console.log('validDate', validDate);
|
|
231
|
-
|
|
232
217
|
const newDate = new Date(validDate).toISOString();
|
|
233
218
|
this.newDate = newDate;
|
|
234
|
-
console.log('newDate', newDate);
|
|
235
|
-
|
|
236
|
-
// Check if the date is in the past
|
|
237
219
|
|
|
238
220
|
// Check if there has been a donation in the last month
|
|
239
|
-
|
|
240
221
|
const hasLastDonationInfo =
|
|
241
222
|
this.plan?.payment.lastBillingDate.date &&
|
|
242
223
|
new Date(this.plan?.payment.lastBillingDate.date);
|
|
@@ -256,13 +237,25 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
256
237
|
|
|
257
238
|
if (isInLastMonth) {
|
|
258
239
|
this.warningMessage =
|
|
259
|
-
'
|
|
240
|
+
'New donation date is in the same month as your last payment.';
|
|
260
241
|
this.allowEditing = true;
|
|
261
242
|
return;
|
|
262
243
|
}
|
|
263
244
|
}
|
|
264
|
-
|
|
265
|
-
|
|
245
|
+
|
|
246
|
+
// Check if the new date is within the next 12 months
|
|
247
|
+
const twelveMonthsFromNow = new Date();
|
|
248
|
+
twelveMonthsFromNow.setFullYear(
|
|
249
|
+
twelveMonthsFromNow.getFullYear() + 1
|
|
250
|
+
);
|
|
251
|
+
twelveMonthsFromNow.setHours(0, 0, 0, 0);
|
|
252
|
+
|
|
253
|
+
if (chosenDate > twelveMonthsFromNow) {
|
|
254
|
+
this.errorMessage =
|
|
255
|
+
'New donation date must be within the next 12 months.';
|
|
256
|
+
this.allowEditing = false;
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
266
259
|
|
|
267
260
|
this.allowEditing = true;
|
|
268
261
|
}}
|
|
@@ -296,8 +289,6 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
296
289
|
(iaButton as IauxButton).isDisabled = true;
|
|
297
290
|
await iaButton.updateComplete;
|
|
298
291
|
|
|
299
|
-
// check if request is in range
|
|
300
|
-
|
|
301
292
|
this.requestDateUpdate(e);
|
|
302
293
|
}}
|
|
303
294
|
>
|
|
@@ -308,8 +299,8 @@ export class MGCEditPlanDate extends LitElement {
|
|
|
308
299
|
>
|
|
309
300
|
</div>
|
|
310
301
|
</div>
|
|
311
|
-
<p class="error">${this.warningMessage}</p>
|
|
312
|
-
<p class="error">${this.errorMessage}</p>
|
|
302
|
+
<p class="error warning-msg">${this.warningMessage}</p>
|
|
303
|
+
<p class="error error-msg">${this.errorMessage}</p>
|
|
313
304
|
</form>
|
|
314
305
|
</section>
|
|
315
306
|
`;
|
package/src/models/plan.ts
CHANGED
package/src/plans.ts
CHANGED