From 964f00e564ddc31fd90126d7c60da1a7d7463dba Mon Sep 17 00:00:00 2001 From: Du Peng Date: Thu, 29 Jun 2023 18:01:09 +0200 Subject: [PATCH 1/3] (feat) re-make event reservation item view --- .../events/event-reservation-item.tsx | 97 +++++++++++++++++++ .../src/javascript/models/reservation.ts | 30 +++++- .../templates/admin/members/edit.html | 38 ++------ app/frontend/templates/dashboard/events.html | 42 ++------ app/views/api/members/show.json.jbuilder | 4 + config/locales/app.logged.en.yml | 12 +++ config/locales/app.logged.fr.yml | 12 +++ 7 files changed, 170 insertions(+), 65 deletions(-) create mode 100644 app/frontend/src/javascript/components/events/event-reservation-item.tsx diff --git a/app/frontend/src/javascript/components/events/event-reservation-item.tsx b/app/frontend/src/javascript/components/events/event-reservation-item.tsx new file mode 100644 index 000000000..cc3cc89e3 --- /dev/null +++ b/app/frontend/src/javascript/components/events/event-reservation-item.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { react2angular } from 'react2angular'; +import { Reservation } from '../../models/reservation'; +import FormatLib from '../../lib/format'; +import { IApplication } from '../../models/application'; + +declare const Application: IApplication; + +interface EventReservationItemProps { + reservation: Reservation; +} + +/** + * event reservation item component + */ +export const EventReservationItem: React.FC = ({ reservation }) => { + const { t } = useTranslation('logged'); + + /** + * Return the formatted localized date of the event + */ + const formatDate = (): string => { + return `${FormatLib.date(reservation.start_at)} ${FormatLib.time(reservation.start_at)} - ${FormatLib.time(reservation.end_at)}`; + }; + + /** + * Build the ticket for event price category user reservation + */ + const buildTicket = (ticket) => { + return ( + <> +
{t('app.logged.event_reservation_item.NUMBER_of_NAME_places_reserved', { NUMBER: ticket.booked, NAME: ticket.price_category.name })}
+ {reservation.booking_users_attributes.filter(u => u.event_price_category_id === ticket.event_price_category_id).map(u => { + return ( +
{u.name}
+ ); + })} + + ); + }; + + /** + * Return the pre-registration status + */ + const preRegistrationStatus = () => { + if (!reservation.validated_at && !reservation.canceled_at && !reservation.is_paid) { + return t('app.logged.event_reservation_item.in_the_process_of_validation'); + } else if (reservation.validated_at && !reservation.canceled_at && !reservation.is_paid) { + return t('app.logged.event_reservation_item.settle_your_payment'); + } else if (reservation.is_paid && !reservation.canceled_at) { + return t('app.logged.event_reservation_item.paid'); + } else if (reservation.canceled_at) { + return t('app.logged.event_reservation_item.paid'); + } + }; + + return ( +
+
+
{t('app.logged.event_reservation_item.event')}
+
{reservation.event_title}
+ {reservation.event_type === 'family' && + {t('app.logged.event_reservation_item.family')} + } + {reservation.event_type === 'nominative' && + {t('app.logged.event_reservation_item.nominative')} + } + {reservation.event_pre_registration && + {t('app.logged.event_reservation_item.pre_registration')} + } + {formatDate()} +
+
+
+
{t('app.logged.event_reservation_item.NUMBER_normal_places_reserved', { NUMBER: reservation.nb_reserve_places })}
+ {reservation.booking_users_attributes.filter(u => !u.event_price_category_id).map(u => { + return ( +
{u.name}
+ ); + })} + {reservation.tickets.map(ticket => { + return buildTicket(ticket); + })} +
+ {reservation.event_pre_registration && +
+
{t('app.logged.event_reservation_item.tracking_your_reservation')}
+ {preRegistrationStatus()} +
+ } +
+
+ ); +}; + +Application.Components.component('eventReservationItem', react2angular(EventReservationItem, ['reservation'])); diff --git a/app/frontend/src/javascript/models/reservation.ts b/app/frontend/src/javascript/models/reservation.ts index db950a40d..f5abfe7b9 100644 --- a/app/frontend/src/javascript/models/reservation.ts +++ b/app/frontend/src/javascript/models/reservation.ts @@ -30,7 +30,7 @@ export interface Reservation { name: string }, nb_reserve_places?: number, - tickets_attributes?: { + tickets_attributes?: Array<{ event_price_category_id: number, event_price_category?: { id: number, @@ -40,18 +40,38 @@ export interface Reservation { name: string } }, - booked: boolean, + booked: number, created_at?: TDateISO - }, + }>, + tickets?: Array<{ + event_price_category_id: number, + event_price_category?: { + id: number, + price_category_id: number, + price_category: { + id: number, + name: string + } + }, + booked: number, + created_at?: TDateISO + }>, total_booked_seats?: number, created_at?: TDateISO, - booking_users_attributes?: { + booking_users_attributes?: Array<{ id: number, name: string, event_price_category_id: number, booked_id: number, booked_type: string, - } + }>, + start_at: TDateISO, + end_at: TDateISO, + event_type?: string, + event_title?: string, + event_pre_registration?: boolean + validated_at?: TDateISO, + is_paid?: boolean, } export interface ReservationIndexFilter extends ApiFilter { diff --git a/app/frontend/templates/admin/members/edit.html b/app/frontend/templates/admin/members/edit.html index 752bffe3a..287a61911 100644 --- a/app/frontend/templates/admin/members/edit.html +++ b/app/frontend/templates/admin/members/edit.html @@ -207,29 +207,11 @@

{{ 'app.admin.members_edit.next_events' | translate }}

-
    -
  • - {{r.reservable.title}} - {{ r.start_at | amDateFormat:'LLL' }} - {{ r.end_at | amDateFormat:'LT' }} - -
    - {{ 'app.admin.members_edit.NUMBER_full_price_tickets_reserved' }} - -
    - {{bu.name}} - {{bu.name}} -
    -
    - -
    - {{ 'app.admin.members_edit.NUMBER_NAME_tickets_reserved' }} - -
    - {{bu.name}} - {{bu.name}} -
    -
    -
  • -
+
+
+ +
+
{{ 'app.admin.members_edit.no_upcoming_events' }}
@@ -240,11 +222,11 @@

{{ 'app.admin.members_edit.passed_events' | translate }}

-
    -
  • - {{r.reservable.title}} - {{ r.start_at | amDateFormat:'LLL' }} - {{ r.end_at | amDateFormat:'LT' }} -
  • -
+
+
+ +
+
{{ 'app.admin.members_edit.no_passed_events' }}
diff --git a/app/frontend/templates/dashboard/events.html b/app/frontend/templates/dashboard/events.html index 9af91bd8f..c632dafa8 100644 --- a/app/frontend/templates/dashboard/events.html +++ b/app/frontend/templates/dashboard/events.html @@ -16,33 +16,11 @@

{{ 'app.logged.dashboard.events.your_next_events' | translate }}

-
    -
  • - {{r.reservable.title}} - - - {{ r.start_at | amDateFormat:'LLL' }} - {{ r.end_at | amDateFormat:'LT' }} -
    - - {{ 'app.logged.dashboard.events.NUMBER_normal_places_reserved' }} - - -
    - {{bu.name}} -
    - -
    - - {{ 'app.logged.dashboard.events.NUMBER_of_NAME_places_reserved' }} - - -
    - {{bu.name}} -
    -
    -
  • -
+
+
+ +
+
{{ 'app.logged.dashboard.events.no_events_to_come' }}
@@ -53,11 +31,11 @@

{{ 'app.logged.dashboard.events.your_previous_events' | translate }}

-
    -
  • - {{r.reservable.title}} - {{ r.start_at | amDateFormat:'LLL' }} - {{ r.end_at | amDateFormat:'LT' }} -
  • -
+
+
+ +
+
{{ 'app.logged.dashboard.events.no_passed_events' }}
diff --git a/app/views/api/members/show.json.jbuilder b/app/views/api/members/show.json.jbuilder index 051b19718..28bdadf3f 100644 --- a/app/views/api/members/show.json.jbuilder +++ b/app/views/api/members/show.json.jbuilder @@ -85,6 +85,10 @@ json.events_reservations @member.reservations.where(reservable_type: 'Event').jo json.reservable sr.reservation.reservable json.reservable_type 'Event' json.event_type sr.reservation.reservable.event_type + json.event_title sr.reservation.reservable.title + json.event_pre_registration sr.reservation.reservable.pre_registration + json.validated_at sr.validated_at + json.is_paid sr.reservation.invoice_items.count.positive? json.canceled_at sr.canceled_at json.booking_users_attributes sr.reservation.booking_users.order(booked_type: :desc) do |bu| json.id bu.id diff --git a/config/locales/app.logged.en.yml b/config/locales/app.logged.en.yml index f284fbc5d..8698bc923 100644 --- a/config/locales/app.logged.en.yml +++ b/config/locales/app.logged.en.yml @@ -37,6 +37,18 @@ en: edit_profile: "Change my data" after_edition_info_html: "Once your data are up to date, click on the synchronization button below, or disconnect then reconnect for your changes to take effect." sync_profile: "Sync my profile" + event_reservation_item: + event: "Event" + family: "Family" + nominative: "Nominative" + pre_registration: "Pre-registration" + NUMBER_normal_places_reserved: "{NUMBER} {NUMBER, plural, =0{} =1{normal place reserved} other{normal places reserved}}" + NUMBER_of_NAME_places_reserved: "{NUMBER} {NUMBER, plural, =0{} =1{of {NAME} place reserved} other{of {NAME} places reserved}}" + tracking_your_reservation: "Tracking your reservation" + in_the_process_of_validation: "In the process of validation" + settle_your_payment: "Come to the reception desk to settle" + paid: "Paid" + canceled: "Canceled" dashboard: #dashboard: public profile profile: diff --git a/config/locales/app.logged.fr.yml b/config/locales/app.logged.fr.yml index 24550f9d1..f9a41a3e9 100644 --- a/config/locales/app.logged.fr.yml +++ b/config/locales/app.logged.fr.yml @@ -37,6 +37,18 @@ fr: edit_profile: "Modifier mes données" after_edition_info_html: "Une fois que vos données sont à jour, cliquez sur le bouton de synchronisation ci-dessous, ou déconnectez-vous puis reconnectez-vous pour que vos changements prennent effet." sync_profile: "Synchroniser mon profil" + event_reservation_item: + event: 'Événement' + family: 'Famille' + nominative: 'Nominatif' + pre_registration: 'Pré-inscription' + NUMBER_normal_places_reserved: "{NUMBER} {NUMBER, plural, =0{} =1{place normale réservée} other{places normales réservées}}" + NUMBER_of_NAME_places_reserved: "{NUMBER} {NUMBER, plural, =0{} =1{place {NAME} réservée} other{places {NAME} réservées}}" + tracking_your_reservation: "Suivi de votre réservation" + in_the_process_of_validation: "En cours de validation" + settle_your_payment: "Venez régler à l'accueil" + paid: "Payé" + canceled: "Annulé" dashboard: #dashboard: public profile profile: From 5f8717914d3421f15b1d5179164e963e82cfe350 Mon Sep 17 00:00:00 2001 From: Vincent Date: Fri, 30 Jun 2023 16:41:13 +0200 Subject: [PATCH 2/3] (ui) Events dashboard layout --- .../events/event-reservation-item.tsx | 45 +++++++------- app/frontend/src/stylesheets/application.scss | 8 ++- .../modules/events/event-reservation.scss | 60 +++++++++++++++++++ .../modules/events/events-dashboard.scss | 5 ++ app/frontend/templates/dashboard/events.html | 6 +- 5 files changed, 98 insertions(+), 26 deletions(-) create mode 100644 app/frontend/src/stylesheets/modules/events/event-reservation.scss create mode 100644 app/frontend/src/stylesheets/modules/events/events-dashboard.scss diff --git a/app/frontend/src/javascript/components/events/event-reservation-item.tsx b/app/frontend/src/javascript/components/events/event-reservation-item.tsx index cc3cc89e3..d9cd2ca4c 100644 --- a/app/frontend/src/javascript/components/events/event-reservation-item.tsx +++ b/app/frontend/src/javascript/components/events/event-reservation-item.tsx @@ -30,10 +30,10 @@ export const EventReservationItem: React.FC = ({ rese const buildTicket = (ticket) => { return ( <> -
{t('app.logged.event_reservation_item.NUMBER_of_NAME_places_reserved', { NUMBER: ticket.booked, NAME: ticket.price_category.name })}
+ {reservation.booking_users_attributes.filter(u => u.event_price_category_id === ticket.event_price_category_id).map(u => { return ( -
{u.name}
+

{u.name}

); })} @@ -58,25 +58,30 @@ export const EventReservationItem: React.FC = ({ rese return (
-
{t('app.logged.event_reservation_item.event')}
-
{reservation.event_title}
- {reservation.event_type === 'family' && - {t('app.logged.event_reservation_item.family')} - } - {reservation.event_type === 'nominative' && - {t('app.logged.event_reservation_item.nominative')} - } - {reservation.event_pre_registration && - {t('app.logged.event_reservation_item.pre_registration')} - } - {formatDate()} +
+ +

{reservation.event_title}

+ {formatDate()} +
+
+ {/* {reservation.event_type === 'family' && + {t('app.logged.event_reservation_item.family')} + } + {reservation.event_type === 'nominative' && + {t('app.logged.event_reservation_item.nominative')} + } */} + {reservation.event_pre_registration && + // eslint-disable-next-line fabmanager/no-bootstrap, fabmanager/no-utilities + {t('app.logged.event_reservation_item.pre_registration')} + } +
-
-
{t('app.logged.event_reservation_item.NUMBER_normal_places_reserved', { NUMBER: reservation.nb_reserve_places })}
+
+ {reservation.booking_users_attributes.filter(u => !u.event_price_category_id).map(u => { return ( -
{u.name}
+

{u.name}

); })} {reservation.tickets.map(ticket => { @@ -84,9 +89,9 @@ export const EventReservationItem: React.FC = ({ rese })}
{reservation.event_pre_registration && -
-
{t('app.logged.event_reservation_item.tracking_your_reservation')}
- {preRegistrationStatus()} +
+ +

{preRegistrationStatus()}

}
diff --git a/app/frontend/src/stylesheets/application.scss b/app/frontend/src/stylesheets/application.scss index cf9ff38aa..2d793e9d2 100644 --- a/app/frontend/src/stylesheets/application.scss +++ b/app/frontend/src/stylesheets/application.scss @@ -47,11 +47,13 @@ @import "modules/dashboard/reservations/prepaid-packs-panel"; @import "modules/dashboard/reservations/reservations-dashboard"; @import "modules/dashboard/reservations/reservations-panel"; -@import "modules/events/event"; -@import "modules/events/events"; @import "modules/events/event-form"; +@import "modules/events/event-reservation"; +@import "modules/events/event"; +@import "modules/events/events-dashboard"; +@import "modules/events/events-settings"; +@import "modules/events/events"; @import "modules/events/update-recurrent-modal"; -@import "modules/events/events-settings.scss"; @import "modules/family-account/child-form"; @import "modules/family-account/child-item"; @import "modules/family-account/children-dashboard"; diff --git a/app/frontend/src/stylesheets/modules/events/event-reservation.scss b/app/frontend/src/stylesheets/modules/events/event-reservation.scss new file mode 100644 index 000000000..eacfb1ec2 --- /dev/null +++ b/app/frontend/src/stylesheets/modules/events/event-reservation.scss @@ -0,0 +1,60 @@ +.event-reservation { + display: flex; + flex-direction: column; + gap: 1.6rem; + + &-item { + padding: 1.6rem 1.6rem 0; + display: flex; + flex-direction: column; + background-color: var(--gray-soft-lightest); + border-radius: var(--border-radius); + + label { + margin: 0; + @include text-xs; + color: var(--gray-hard-light); + } + p { + margin: 0; + @include text-base(600); + } + .date { @include text-sm; } + + &__event { + padding-bottom: 1.2rem; + display: flex; + justify-content: space-between; + align-items: center; + gap: 1.6rem; + border-bottom: 1px solid var(--gray-soft-dark); + } + + &__reservation { + display: flex; + + & > div { + padding: 1.2rem 1.6rem 1.2rem 0; + flex: 1; + } + .list { + display: flex; + flex-direction: column; + row-gap: 0.5rem; + label:not(:first-of-type) { + margin-top: 1rem; + } + } + .name { @include text-sm(500); } + + .status { + padding-left: 1.6rem; + display: flex; + flex-direction: column; + justify-content: center; + border-left: 1px solid var(--gray-soft-dark); + } + } + + } +} \ No newline at end of file diff --git a/app/frontend/src/stylesheets/modules/events/events-dashboard.scss b/app/frontend/src/stylesheets/modules/events/events-dashboard.scss new file mode 100644 index 000000000..7c6c70bc9 --- /dev/null +++ b/app/frontend/src/stylesheets/modules/events/events-dashboard.scss @@ -0,0 +1,5 @@ +.events-dashboard { + max-width: 1600px; + margin: 0 auto; + padding-bottom: 6rem; +} \ No newline at end of file diff --git a/app/frontend/templates/dashboard/events.html b/app/frontend/templates/dashboard/events.html index c632dafa8..f9333495d 100644 --- a/app/frontend/templates/dashboard/events.html +++ b/app/frontend/templates/dashboard/events.html @@ -8,7 +8,7 @@ -
+
@@ -16,8 +16,8 @@

{{ 'app.logged.dashboard.events.your_next_events' | translate }}

-
-
+
+
From 85d052684c380a80c8336a6a13968dbd3e6ca521 Mon Sep 17 00:00:00 2001 From: Du Peng Date: Fri, 30 Jun 2023 16:46:31 +0200 Subject: [PATCH 3/3] (i18n) update translates --- config/locales/app.admin.en.yml | 2 +- config/locales/app.admin.fr.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index 670227373..c456b3065 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -158,7 +158,7 @@ en: family: "Event family" pre_registration: "Pre-registration" pre_registration_help: "If this option is checked, administrators and managers must validate registrations before they become final." - pre_registration_end_date: "Pre-registration end date" + pre_registration_end_date: "Deadline for pre-registration" plan_form: ACTION_title: "{ACTION, select, create{New} other{Update the}} plan" tab_settings: "Settings" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index a1e0d39b7..8a5768272 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -158,7 +158,7 @@ fr: family: "Evénement famille" pre_registration: "Pré-inscription" pre_registration_help: "Si cette option est cochée, les administrateurs et les gestionnaires devent valider les inscriptions avant qu'elles ne soient définitives." - pre_registration_end_date: "Date de fin de pré-inscription" + pre_registration_end_date: "Date limite de pré-inscription" plan_form: ACTION_title: "{ACTION, select, create{Nouvelle} other{Mettre à jour la}} formule d'abonnement" tab_settings: "Paramètres"