Skip to content

Commit

Permalink
[FEATURE] affiche une alerte d'expiration des lots de places (PIX-14008
Browse files Browse the repository at this point in the history
…) (#10106)
  • Loading branch information
lionelB authored Sep 18, 2024
1 parent 0044849 commit d6c4e33
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 0 deletions.
36 changes: 36 additions & 0 deletions orga/app/components/places/places-lot-alert.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import PixBanner from '@1024pix/pix-ui/components/pix-banner';
import dayjs from 'dayjs';
import { t } from 'ember-intl';
import { STATUSES } from 'pix-orga/models/organization-places-lot.js';

function getLastActivePlacesLot(placesLots) {
return placesLots
.filter((placesLot) => placesLot.status === STATUSES.ACTIVE)
.sort((placesLotA, placesLotB) => placesLotB.expirationDate - placesLotA.expirationDate);
}

function getCountdDownDays(placesLots) {
const [lastActiveLot] = getLastActivePlacesLot(placesLots);
if (!lastActiveLot) return;
return dayjs(lastActiveLot.expirationDate).diff(dayjs(), 'day');
}

function isAlertVisible(placesLots) {
if (!Array.isArray(placesLots)) return false;

const hasPendingLots = placesLots.some((placesLot) => placesLot.status === STATUSES.PENDING);

if (hasPendingLots) return false;

const [lastActiveLot] = getLastActivePlacesLot(placesLots);
if (!lastActiveLot) return false;
return dayjs(lastActiveLot.expirationDate).isBefore(dayjs().add(30, 'days'));
}

<template>
{{#if (isAlertVisible @placesLots)}}
<PixBanner class="places-lots-alert" @type="warning" @withIcon="true">
{{t "banners.last-places-lot-available.message" days=(getCountdDownDays @placesLots)}}
</PixBanner>
{{/if}}
</template>
2 changes: 2 additions & 0 deletions orga/app/styles/components/places/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@
@import 'place-info';
@import 'capacity-alert';
@import 'places-lots';
@import 'places-lots-alert';

3 changes: 3 additions & 0 deletions orga/app/styles/components/places/places-lots-alert.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.places-lots-alert {
margin-top: var(--pix-spacing-8x);
}
1 change: 1 addition & 0 deletions orga/app/templates/authenticated/places.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<Places::Title />

<Places::PlacesLotAlert @placesLots={{@model.placesLots}} />
<Places::CapacityAlert @occupied={{@model.statistics.occupied}} @total={{@model.statistics.total}} />
<Places::Statistics @model={{@model.statistics}} />
<Places::PlaceInfo @hasAnonymousSeat={{@model.statistics.hasAnonymousSeat}} />
Expand Down
125 changes: 125 additions & 0 deletions orga/tests/integration/components/places/places-lot-alert-test.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { render } from '@1024pix/ember-testing-library';
import { t } from 'ember-intl/test-support';
import PlacesLotsAlert from 'pix-orga/components/places/places-lot-alert';
import { STATUSES } from 'pix-orga/models/organization-places-lot';
import { module, test } from 'qunit';
import sinon from 'sinon';

import setupIntlRenderingTest from '../../../helpers/setup-intl-rendering';

module('Integration | Component | Places | PlacesLotsAlert', function (hooks) {
setupIntlRenderingTest(hooks);
let store, clock;
const now = new Date('2021-11-03');

hooks.beforeEach(function () {
store = this.owner.lookup('service:store');
clock = sinon.useFakeTimers({ now });
});

hooks.afterEach(function () {
clock.restore();
});

test('it should show an alert with remaining days before places lot expires', async function (assert) {
// given
const placesLots = [
store.createRecord('organization-places-lot', {
count: 123,
activationDate: new Date('2021-11-01'),
expirationDate: new Date('2021-11-30'),
status: STATUSES.ACTIVE,
}),
];
// when
const screen = await render(<template><PlacesLotsAlert @placesLots={{placesLots}} /></template>);
const banner = screen.getByRole('alert', { value: t('banners.last-places-lot-available.message') });
// then
assert.strictEqual(banner.outerText, t('banners.last-places-lot-available.message', { days: 27 }));
});
test('it should not show an alert if there is one active lot that has an expiration date in more than 1 month', async function (assert) {
// given
const placesLots = [
store.createRecord('organization-places-lot', {
count: 123,
activationDate: new Date('2021-11-01'),
expirationDate: new Date('2021-11-07'),
status: STATUSES.ACTIVE,
}),
store.createRecord('organization-places-lot', {
count: 123,
activationDate: new Date('2021-11-01'),
expirationDate: new Date('2021-12-03'),
status: STATUSES.ACTIVE,
}),
];
// when
const screen = await render(<template><PlacesLotsAlert @placesLots={{placesLots}} /></template>);

// then
assert.notOk(screen.queryByRole('alert', { value: t('banners.last-places-lot-available.message') }));
});
test('it should not show an alert if remaining days before places lot expires in more than 30 days', async function (assert) {
// given
const placesLots = [
store.createRecord('organization-places-lot', {
count: 123,
activationDate: new Date('2021-11-01'),
expirationDate: new Date('2021-12-03'),
status: STATUSES.ACTIVE,
}),
];
// when
const screen = await render(<template><PlacesLotsAlert @placesLots={{placesLots}} /></template>);

// then
assert.notOk(screen.queryByRole('alert', { value: t('banners.last-places-lot-available.message') }));
});
test('it should not show alert if there is `PENDING` placesLots', async function (assert) {
// given
const placesLots = [
store.createRecord('organization-places-lot', {
count: 123,
activationDate: new Date('2021-11-01'),
expirationDate: new Date('2021-11-30'),
status: STATUSES.ACTIVE,
}),
store.createRecord('organization-places-lot', {
count: 123,
activationDate: new Date('2021-12-01'),
expirationDate: new Date('2021-12-30'),
status: STATUSES.PENDING,
}),
];
// when
const screen = await render(<template><PlacesLotsAlert @placesLots={{placesLots}} /></template>);

// then
assert.notOk(screen.queryByRole('alert', { value: t('banners.last-places-lot-available.message') }));
});
test('it should not show alert if there is no ACTIVE placesLots', async function (assert) {
// given
const placesLots = [
store.createRecord('organization-places-lot', {
count: 123,
activationDate: new Date('2020-12-01'),
expirationDate: new Date('2020-12-30'),
status: STATUSES.EXPIRED,
}),
];
// when
const screen = await render(<template><PlacesLotsAlert @placesLots={{placesLots}} /></template>);

// then
assert.notOk(screen.queryByRole('alert', { value: t('banners.last-places-lot-available.message') }));
});
test('it should not show alert if there is no placesLots', async function (assert) {
// given
const placesLots = [];
// when
const screen = await render(<template><PlacesLotsAlert @placesLots={{placesLots}} /></template>);

// then
assert.notOk(screen.queryByRole('alert', { value: t('banners.last-places-lot-available.message') }));
});
});
3 changes: 3 additions & 0 deletions orga/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
"language-availability": {
"message": "Your language is not yet available on Pix Orga. For your convenience, the application will be presented in English. The entire Pix team is working to add your language."
},
"last-places-lot-available": {
"message": "Please note that your seats will expire in {days, number} days."
},
"over-capacity": {
"message": "Please note that you are using more seats than your total capacity."
}
Expand Down
3 changes: 3 additions & 0 deletions orga/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
"language-availability": {
"message": "Votre langue n'est pas encore disponible sur Pix Orga. Pour votre confort, l'application sera présentée en anglais. Toute l'équipe de Pix travaille à l'ajout de votre langue."
},
"last-places-lot-available": {
"message": "Attention, vos places arrivent à échéance dans {days, number} jours."
},
"over-capacity": {
"message": "Attention, vous consommez plus de places que votre capacité totale."
},
Expand Down
3 changes: 3 additions & 0 deletions orga/translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
"language-availability": {
"message": "Jouw taal is nog niet beschikbaar op Pix Orga. Voor jouw gemak wordt de applicatie in het Engels weergegeven. Het Pix-team werkt eraan om jouw taal toe te voegen."
},
"last-places-lot-available": {
"message": "Houd er rekening mee dat je seats over {days, number} dagen verlopen."
},
"over-capacity": {
"message": "Houd er rekening mee dat je meer plaats inneemt dan je totale capaciteit."
},
Expand Down

0 comments on commit d6c4e33

Please sign in to comment.