Skip to content

Commit

Permalink
fix: improve summary for subscriptions starting soon
Browse files Browse the repository at this point in the history
Closes #148
  • Loading branch information
pheekus committed Jan 17, 2024
1 parent fd5c4e2 commit 4815d14
Show file tree
Hide file tree
Showing 28 changed files with 233 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,32 @@ describe('AdminSubscriptionCard', () => {
expect(price).to.have.attribute('infer', '');
});

it('renders a special status in line 2 for subscriptions that start soon', async () => {
const router = createRouter();
const href = 'https://demo.api/hapi/subscriptions/0';
const data = await getTestData<Resource<Rels.Subscription>>(href, router);

const element = await fixture<Card>(html`
<foxy-admin-subscription-card
locale-codes="https://demo.api/hapi/property_helpers/7"
@fetch=${(evt: FetchEvent) => router.handleEvent(evt)}
>
</foxy-admin-subscription-card>
`);

data.first_failed_transaction_date = null;
data.start_date = new Date(Date.now() + 3600000).toISOString();
data.is_active = true;
data.end_date = null;
element.data = data;

await waitUntil(() => element.isBodyReady, '', { timeout: 5000 });
const price = await getByKey(element, 'subscription_will_be_active');

expect(price).to.exist;
expect(price).to.have.attribute('infer', '');
});

it('renders customer email in line 3 from embedded fx:transaction_template', async () => {
type Subscription = Resource<Rels.Subscription, { zoom: 'transaction_template' }>;

Expand Down
17 changes: 13 additions & 4 deletions src/elements/public/AdminSubscriptionCard/AdminSubscriptionCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,15 @@ export class AdminSubscriptionCard extends Base<Data> {
}

private get __statusOptions() {
const d = this.data;
const date = d?.first_failed_transaction_date ?? d?.end_date ?? d?.next_transaction_date;
if (date) return { date };
const data = this.data;

if (data === null) return;
if (data.first_failed_transaction_date) return { date: data.first_failed_transaction_date };
if (data.end_date) return { date: data.end_date };
if (data.is_active === false) return {};
if (new Date(data.start_date) > new Date()) return { date: data.start_date };

return { date: data.next_transaction_date };
}

private get __currencyCode() {
Expand Down Expand Up @@ -329,7 +335,10 @@ export class AdminSubscriptionCard extends Base<Data> {
return hasEnded ? 'subscription_will_be_cancelled' : 'subscription_cancelled';
}

return `subscription_${data.is_active ? 'active' : 'inactive'}`;
if (data.is_active === false) return 'subscription_inactive';
if (new Date(data.start_date) > new Date()) return 'subscription_will_be_active';

return 'subscription_active';
}

private get __priceKey() {
Expand Down
20 changes: 20 additions & 0 deletions src/elements/public/SubscriptionCard/SubscriptionCard.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,26 @@ describe('SubscriptionCard', () => {
expect(control).to.have.attribute('ns', 'subscription-card');
});

it('once loaded, renders a special status for subscriptions that start soon', async () => {
const href = './hapi/subscriptions/0?zoom=last_transaction,transaction_template:items';
const data = await getTestData<Data>(href);

data.first_failed_transaction_date = null;
data.start_date = new Date(Date.now() + 3600000).toISOString();
data.end_date = null;

const layout = html`<foxy-subscription-card lang="es" .data=${data}></foxy-subscription-card>`;
const element = await fixture<SubscriptionCard>(layout);
const control = await getByTestId(element, 'status');
const options = { date: data.start_date };

expect(control).to.have.property('localName', 'foxy-i18n');
expect(control).to.have.attribute('options', JSON.stringify(options));
expect(control).to.have.attribute('lang', 'es');
expect(control).to.have.attribute('key', 'subscription_will_be_active');
expect(control).to.have.attribute('ns', 'subscription-card');
});

it('once loaded, renders a special status for inactive subscriptions', async () => {
const href = './hapi/subscriptions/0?zoom=last_transaction,transaction_template:items';
const data = await getTestData<Data>(href);
Expand Down
33 changes: 20 additions & 13 deletions src/elements/public/SubscriptionCard/SubscriptionCard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class SubscriptionCard extends Base<Data> {
}

private __getSummaryOptions() {
if (!this.in({ idle: 'snapshot' })) return {};
if (this.data === null) return {};
const items = this.data._embedded['fx:transaction_template']._embedded['fx:items'];

return {
Expand All @@ -131,31 +131,38 @@ export class SubscriptionCard extends Base<Data> {
}

private __getStatusOptions() {
if (!this.in({ idle: 'snapshot' })) return {};
return {
date:
this.data.first_failed_transaction_date ??
this.data.end_date ??
this.data.next_transaction_date,
};
const data = this.data;

if (data === null) return {};
if (data.first_failed_transaction_date) return { date: data.first_failed_transaction_date };
if (data.end_date) return { date: data.end_date };
if (data.is_active === false) return {};
if (new Date(data.start_date) > new Date()) return { date: data.start_date };

return { date: data.next_transaction_date };
}

private __getPriceOptions() {
if (!this.in({ idle: 'snapshot' })) return {};
if (this.data === null) return {};

const transaction = this.data._embedded['fx:last_transaction'];
const amount = `${transaction.total_order} ${transaction.currency_code}`;
return { ...parseFrequency(this.data.frequency), amount };
}

private __getStatusKey() {
if (this.data?.first_failed_transaction_date) return 'subscription_failed';
const data = this.data;

if (this.data?.end_date) {
const hasEnded = new Date(this.data.end_date).getTime() > Date.now();
if (data === null) return;
if (data.first_failed_transaction_date) return 'subscription_failed';
if (data.end_date) {
const hasEnded = new Date(data.end_date).getTime() > Date.now();
return hasEnded ? 'subscription_will_be_cancelled' : 'subscription_cancelled';
}

return `subscription_${this.data?.is_active ? 'active' : 'inactive'}`;
if (data.is_active === false) return 'subscription_inactive';
if (new Date(data.start_date) > new Date()) return 'subscription_will_be_active';

return 'subscription_active';
}
}
30 changes: 26 additions & 4 deletions src/elements/public/SubscriptionForm/SubscriptionForm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,28 @@ describe('SubscriptionForm', () => {
expect(control).to.have.attribute('ns', 'subscription-form');
});

it('once loaded, renders a special status for active subscriptions in subtitle', async () => {
const href = './hapi/subscriptions/0?zoom=last_transaction,transaction_template:items';
const data = await getTestData<Data>(href);

data.first_failed_transaction_date = null;
data.start_date = new Date(Date.now() + 3600000).toISOString();
data.end_date = null;

const element = await fixture<Form>(html`
<foxy-subscription-form lang="es" .data=${data}></foxy-subscription-form>
`);

const control = await getByTestId(element, 'header-subtitle');
const options = { date: data.start_date };

expect(control).to.have.property('localName', 'foxy-i18n');
expect(control).to.have.attribute('options', JSON.stringify(options));
expect(control).to.have.attribute('lang', 'es');
expect(control).to.have.attribute('key', 'subscription_will_be_active');
expect(control).to.have.attribute('ns', 'subscription-form');
});

it('once loaded, renders a special status for inactive subscriptions in subtitle', async () => {
const href = './hapi/subscriptions/0?zoom=last_transaction,transaction_template:items';
const data = await getTestData<Data>(href);
Expand Down Expand Up @@ -1995,13 +2017,13 @@ describe('SubscriptionForm', () => {
expect(control).to.have.attribute('disabledcontrols', '');

element.setAttribute('disabled', '');
await element.updateComplete;
await element.requestUpdate();

expect(control).to.have.attribute('disabledcontrols', 'not=*');

element.removeAttribute('disabled');
element.setAttribute('disabledcontrols', 'end-date:form:submit');
await element.updateComplete;
await element.requestUpdate();

expect(control).to.have.attribute('disabledcontrols', 'submit');
});
Expand All @@ -2014,13 +2036,13 @@ describe('SubscriptionForm', () => {
expect(control).to.have.attribute('readonlycontrols', '');

element.setAttribute('readonly', '');
await element.updateComplete;
await element.requestUpdate();

expect(control).to.have.attribute('readonlycontrols', 'not=*');

element.removeAttribute('readonly');
element.setAttribute('readonlycontrols', 'end-date:form:end-date');
await element.updateComplete;
await element.requestUpdate();

expect(control).to.have.attribute('readonlycontrols', 'end-date');
});
Expand Down
12 changes: 9 additions & 3 deletions src/elements/public/SubscriptionForm/SubscriptionForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,17 @@ export class SubscriptionForm extends Base<Data> {
key = 'subscription_failed';
} else if (data.end_date) {
date = data.end_date;
const hasEnded = new Date(date).getTime() > Date.now();
const hasEnded = new Date(data.end_date).getTime() > Date.now();
key = hasEnded ? 'subscription_will_be_cancelled' : 'subscription_cancelled';
} else if (!data.is_active) {
date = '';
key = 'subscription_inactive';
} else if (new Date(data.start_date) > new Date()) {
date = data.start_date;
key = 'subscription_will_be_active';
} else {
date = data.next_transaction_date ?? new Date().toISOString();
key = `subscription_${data.is_active ? 'active' : 'inactive'}`;
date = data.next_transaction_date;
key = 'subscription_active';
}

const text = html`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,18 @@ describe('SubscriptionsTable', () => {
date = subscription.first_failed_transaction_date;
key = 'subscription_failed';
} else if (subscription.end_date) {
const dateAsObject = new Date(subscription.end_date);
const hasEnded = dateAsObject.getTime() > Date.now();
key = hasEnded ? 'subscription_will_be_cancelled' : 'subscription_cancelled';
date = subscription.end_date;
const hasEnded = new Date(subscription.end_date).getTime() > Date.now();
key = hasEnded ? 'subscription_will_be_cancelled' : 'subscription_cancelled';
} else if (!subscription.is_active) {
date = '';
key = 'subscription_inactive';
} else if (new Date(subscription.start_date) > new Date()) {
date = subscription.start_date;
key = 'subscription_will_be_active';
} else {
date = subscription.next_transaction_date;
key = `subscription_${subscription.is_active ? 'active' : 'inactive'}`;
key = 'subscription_active';
}

expect(statusRef).to.have.deep.property('options', { date });
Expand Down
42 changes: 20 additions & 22 deletions src/elements/public/SubscriptionsTable/SubscriptionsTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,40 +49,38 @@ export class SubscriptionsTable extends TranslatableMixin(Table, 'subscriptions-

static statusColumn: Column<Data> = {
hideBelow: 'sm',
cell: ctx => {
let color: string;
cell: ({ ns, lang, data, html }) => {
let color = 'bg-contrast-5 text-secondary';
let date: string;
let key: string;

if (ctx.data.first_failed_transaction_date) {
date = ctx.data.first_failed_transaction_date;
key = 'subscription_failed';
if (data.first_failed_transaction_date) {
color = 'bg-error-10 text-error';
} else if (ctx.data.end_date) {
date = ctx.data.end_date;
const dateAsObject = new Date(date);
const hasEnded = dateAsObject.getTime() > Date.now();
date = data.first_failed_transaction_date;
key = 'subscription_failed';
} else if (data.end_date) {
date = data.end_date;
const hasEnded = new Date(data.end_date).getTime() > Date.now();
key = hasEnded ? 'subscription_will_be_cancelled' : 'subscription_cancelled';
color = hasEnded ? 'bg-success-10 text-success' : 'bg-contrast-5 text-tertiary';
} else if (!data.is_active) {
date = '';
key = 'subscription_inactive';
} else if (new Date(data.start_date) > new Date()) {
date = data.start_date;
key = 'subscription_will_be_active';
} else {
date = ctx.data.next_transaction_date;

if (ctx.data.is_active) {
key = 'subscription_active';
color = 'bg-success-10 text-success';
} else {
key = 'subscription_inactive';
color = 'bg-contrast-5 text-tertiary';
}
color = 'bg-success-10 text-success';
date = data.next_transaction_date;
key = 'subscription_active';
}

return ctx.html`
return html`
<foxy-i18n
data-testclass="i18n statuses"
class="px-s py-xs text-m font-medium block whitespace-normal rounded ${color}"
lang=${ctx.lang}
lang=${lang}
key=${key}
ns=${ctx.ns}
ns=${ns}
.options=${{ date }}
>
</foxy-i18n>
Expand Down
2 changes: 2 additions & 0 deletions src/static/schemas/admin-subscription-card.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"subscription_failed": { "type": "string", "default": "Payment failed on {{date, date}}" },
"subscription_inactive": { "type": "string", "default": "Inactive" },
"subscription_will_be_cancelled": { "type": "string", "default": "Ends on {{date, date}}" },
"subscription_will_be_active": { "type": "string", "default": "Starts on {{date, date}}" },
"summary": { "type": "string", "default": "{{ firstItem.name }}" },
"summary_plural": {
"type": "string",
Expand Down Expand Up @@ -57,6 +58,7 @@
"subscription_failed",
"subscription_inactive",
"subscription_will_be_cancelled",
"subscription_will_be_active",
"summary",
"summary_plural",
"summary_approximate",
Expand Down
10 changes: 10 additions & 0 deletions src/static/schemas/cart-form.json
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@
"type": "string",
"default": "Ends on {{date, date}}"
},
"subscription_will_be_active": {
"type": "string",
"default": "Starts on {{date, date}}"
},
"transaction_plural": { "type": "string", "default": "Transactions" },
"twice_a_month": { "type": "string", "default": "Twice a month" },
"undo_cancel": { "type": "string", "default": "Review" },
Expand Down Expand Up @@ -392,6 +396,7 @@
"subscription_failed",
"subscription_inactive",
"subscription_will_be_cancelled",
"subscription_will_be_active",
"transaction_plural",
"twice_a_month",
"undo_cancel",
Expand Down Expand Up @@ -444,6 +449,10 @@
"type": "string",
"default": "Ends on {{date, date}}"
},
"subscription_will_be_active": {
"type": "string",
"default": "Starts on {{date, date}}"
},
"transaction_summary": {
"type": "string",
"default": "{{most_expensive_item.name}}"
Expand Down Expand Up @@ -477,6 +486,7 @@
"subscription_inactive",
"subscription_plural",
"subscription_will_be_cancelled",
"subscription_will_be_active",
"transaction_summary",
"twice_a_month",
"weekly",
Expand Down
Loading

0 comments on commit 4815d14

Please sign in to comment.