From ff6ebc0e4dc8da85ae998850c46eb35169cbd41e Mon Sep 17 00:00:00 2001 From: Jumpy Squirrel Date: Tue, 12 Dec 2023 16:51:30 +0100 Subject: [PATCH 1/2] feat(#213): early bird discount and full invoices --- src/apis/attsrv.ts | 37 ++++-- .../funnels/register/steps/ticket/level.tsx | 11 +- src/config.ts | 105 ++++++++++++++++++ src/localizations/de-DE.ftl | 51 +++++++++ src/localizations/en-US.ftl | 51 +++++++++ src/state/models/autosave.ts | 12 +- src/util/config-types.ts | 2 + 7 files changed, 252 insertions(+), 17 deletions(-) diff --git a/src/apis/attsrv.ts b/src/apis/attsrv.ts index 8c41a94..3c156b6 100644 --- a/src/apis/attsrv.ts +++ b/src/apis/attsrv.ts @@ -190,6 +190,8 @@ const attendeeDtoFromRegistrationInfo = (registrationInfo: RegistrationInfo): At && registrationInfo.ticketLevel.addons['stage-pass'].selected, 'tshirt': !(config.ticketLevels[registrationInfo.ticketLevel.level].includes?.includes('tshirt') ?? false) && registrationInfo.ticketLevel.addons.tshirt.selected, + 'early': registrationInfo.ticketLevel.addons.early.selected, + 'door': registrationInfo.ticketLevel.addons.door.selected, }), user_comments: registrationInfo.optionalInfo.comments, }) @@ -203,6 +205,28 @@ const registrationInfoFromAttendeeDto = (attendeeDto: AttendeeDto): Registration const days = eachDayOfInterval(Interval.fromDateTimes(config.dayTicketStartDate, config.dayTicketEndDate)) const level = packages.has('sponsor2') ? 'super-sponsor' : packages.has('sponsor') ? 'sponsor' : 'standard' + // parse all hidden addons, so they show up in the invoice box + const hiddenAddons = Object.fromEntries( + Object.entries(config.addons) + .filter(([,addon]) => addon.hidden) + .map(([id, _addon]) => { + return [id, { selected: packages.has(id), options: {} }] + }), + ) + const addons = { + ...hiddenAddons, + 'stage-pass': { + selected: (config.ticketLevels[level].includes?.includes('stage-pass') ?? false) || packages.has('stage'), + options: {}, + }, + tshirt: { + selected: (config.ticketLevels[level].includes?.includes('tshirt') ?? false) || packages.has('tshirt'), + options: { + size: tshirtFromApi(attendeeDto.tshirt_size) as RegistrationInfo['ticketLevel']['addons']['tshirt']['options']['size'], + }, + }, + } + return { preferredLocale: attendeeDto.registration_language, /* eslint-disable @typescript-eslint/indent */ @@ -222,18 +246,7 @@ const registrationInfoFromAttendeeDto = (attendeeDto: AttendeeDto): Registration /* eslint-enable @typescript-eslint/indent */ ticketLevel: { level, - addons: { - 'stage-pass': { - selected: (config.ticketLevels[level].includes?.includes('stage-pass') ?? false) || packages.has('stage'), - options: {}, - }, - tshirt: { - selected: (config.ticketLevels[level].includes?.includes('tshirt') ?? false) || packages.has('tshirt'), - options: { - size: tshirtFromApi(attendeeDto.tshirt_size) as RegistrationInfo['ticketLevel']['addons']['tshirt']['options']['size'], - }, - }, - }, + addons, }, personalInfo: { nickname: attendeeDto.nickname, diff --git a/src/components/funnels/funnels/register/steps/ticket/level.tsx b/src/components/funnels/funnels/register/steps/ticket/level.tsx index a41db14..7be1b22 100644 --- a/src/components/funnels/funnels/register/steps/ticket/level.tsx +++ b/src/components/funnels/funnels/register/steps/ticket/level.tsx @@ -74,10 +74,13 @@ const TicketLevel = (_: ReadonlyRouteComponentProps) => {

Select add-ons

- {Object.entries(config.addons).filter(([, addon]) => !(addon.unavailableFor?.type?.includes(ticketType.type) ?? false)).map(([id, addon]) => - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - , - )} + {Object.entries(config.addons) + .filter(([, addon]) => !addon.hidden) + .filter(([, addon]) => !(addon.unavailableFor?.type?.includes(ticketType.type) ?? false)) + .map(([id, addon]) => + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + , + )}
diff --git a/src/config.ts b/src/config.ts index b1749e7..ed698b6 100644 --- a/src/config.ts +++ b/src/config.ts @@ -13,6 +13,7 @@ import { DateTime } from 'luxon' const apiPath = (path: string) => process.env.GATSBY_API_BASE_URL === undefined ? withPrefix(path) : `${process.env.GATSBY_API_BASE_URL}${path}` const config = checkConfig({ + version: 1, // increment to prevent loading from local storage (new year, pricing changes, default packages) eventName: 'Eurofurence', registrationLaunch: DateTime.fromISO('2023-01-21T12:30:23+02:00'), registrationExpirationDate: DateTime.fromISO('2024-09-22', { zone: 'Europe/Berlin' }), @@ -58,6 +59,7 @@ const config = checkConfig({ unavailableFor: { type: ['day'], }, + hidden: false, }, 'tshirt': { price: 20, @@ -68,6 +70,109 @@ const config = checkConfig({ items: ['XS', 'wXS', 'S', 'wS', 'M', 'wM', 'L', 'wL', 'XL', 'wXL', 'XXL', 'wXXL', 'm3XL', 'w3XL', 'm4XL', 'w4XL'], }, }, + hidden: false, + }, + 'early': { + price: -5, + default: true, // don't forget to increment version when changing this + options: {}, + hidden: true, + }, + 'door': { + price: 10, + default: false, // don't forget to increment version when changing this + options: {}, + hidden: true, + }, + 'dealer-half': { + price: 50, + default: false, + options: {}, + hidden: true, + }, + 'dealer-full': { + price: 100, + default: false, + options: {}, + hidden: true, + }, + 'dealer-double': { + price: 200, + default: false, + options: {}, + hidden: true, + }, + 'dealer-quad': { + price: 400, + default: false, + options: {}, + hidden: true, + }, + 'boat-trip': { + price: 35, + default: false, + options: {}, + hidden: true, + }, + 'boat-vip': { + price: 15, + default: false, + options: {}, + hidden: true, + }, + 'boat-benefactor': { + price: 100, + default: false, + options: {}, + hidden: true, + }, + 'artshow-table-half': { + price: 5, + default: false, + options: {}, + hidden: true, + }, + 'artshow-table-full': { + price: 10, + default: false, + options: {}, + hidden: true, + }, + 'artshow-table-double': { + price: 20, + default: false, + options: {}, + hidden: true, + }, + 'artshow-table-quad': { + price: 40, + default: false, + options: {}, + hidden: true, + }, + 'artshow-panel-half': { + price: 10, + default: false, + options: {}, + hidden: true, + }, + 'artshow-panel-full': { + price: 20, + default: false, + options: {}, + hidden: true, + }, + 'artshow-panel-double': { + price: 40, + default: false, + options: {}, + hidden: true, + }, + 'artshow-panel-quad': { + price: 80, + default: false, + options: {}, + hidden: true, }, }, rooms: [ diff --git a/src/localizations/de-DE.ftl b/src/localizations/de-DE.ftl index 46db633..a1ab88b 100644 --- a/src/localizations/de-DE.ftl +++ b/src/localizations/de-DE.ftl @@ -56,6 +56,57 @@ invoice-item-definition-register-ticket-addons-tshirt = .name = T-Shirt .extra = {$size} +invoice-item-definition-register-ticket-addons-early = + .name = Frühbucher + +invoice-item-definition-register-ticket-addons-door = + .name = Walk-in Zuschlag + +invoice-item-definition-register-ticket-addons-dealer-half = + .name = Dealer (halber Tisch) + +invoice-item-definition-register-ticket-addons-dealer-full = + .name = Dealer (1 Tisch) + +invoice-item-definition-register-ticket-addons-dealer-double = + .name = Dealer (2 Tische) + +invoice-item-definition-register-ticket-addons-dealer-quad = + .name = Dealer (4 Tische) + +invoice-item-definition-register-ticket-addons-boat-trip = + .name = Bootsfahrt + +invoice-item-definition-register-ticket-addons-boat-vip = + .name = Boot VIP + +invoice-item-definition-register-ticket-addons-boat-benefactor = + .name = Bootssponsor + +invoice-item-definition-register-ticket-addons-artshow-table-half = + .name = Artshow (halber Tisch) + +invoice-item-definition-register-ticket-addons-artshow-table-full = + .name = Artshow (1 Tisch) + +invoice-item-definition-register-ticket-addons-artshow-table-double = + .name = Artshow (2 Tische) + +invoice-item-definition-register-ticket-addons-artshow-table-quad = + .name = Artshow (4 Tische) + +invoice-item-definition-register-ticket-addons-artshow-panel-half = + .name = Artshow (halbes Panel) + +invoice-item-definition-register-ticket-addons-artshow-panel-full = + .name = Artshow (1 Panel) + +invoice-item-definition-register-ticket-addons-artshow-panel-double = + .name = Artshow (2 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-quad = + .name = Artshow (4 Panels) + invoice-item-definition-other = .name = Sonstige diff --git a/src/localizations/en-US.ftl b/src/localizations/en-US.ftl index b715cc4..e6bec82 100644 --- a/src/localizations/en-US.ftl +++ b/src/localizations/en-US.ftl @@ -56,6 +56,57 @@ invoice-item-definition-register-ticket-addons-tshirt = .name = T-shirt .extra = {$size} +invoice-item-definition-register-ticket-addons-early = + .name = Early Bird + +invoice-item-definition-register-ticket-addons-door = + .name = At the door + +invoice-item-definition-register-ticket-addons-dealer-half = + .name = Dealer (Half a Table) + +invoice-item-definition-register-ticket-addons-dealer-full = + .name = Dealer (1 Table) + +invoice-item-definition-register-ticket-addons-dealer-double = + .name = Dealer (2 Tables) + +invoice-item-definition-register-ticket-addons-dealer-quad = + .name = Dealer (4 Tables) + +invoice-item-definition-register-ticket-addons-boat-trip = + .name = Boat Trip + +invoice-item-definition-register-ticket-addons-boat-vip = + .name = Boat VIP + +invoice-item-definition-register-ticket-addons-boat-benefactor = + .name = Boat Sponsor + +invoice-item-definition-register-ticket-addons-artshow-table-half = + .name = Artshow (Half a Table) + +invoice-item-definition-register-ticket-addons-artshow-table-full = + .name = Artshow (1 Table) + +invoice-item-definition-register-ticket-addons-artshow-table-double = + .name = Artshow (2 Tables) + +invoice-item-definition-register-ticket-addons-artshow-table-quad = + .name = Artshow (4 Tables) + +invoice-item-definition-register-ticket-addons-artshow-panel-half = + .name = Artshow (Half a Panel) + +invoice-item-definition-register-ticket-addons-artshow-panel-full = + .name = Artshow (1 Panel) + +invoice-item-definition-register-ticket-addons-artshow-panel-double = + .name = Artshow (2 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-quad = + .name = Artshow (4 Panels) + invoice-item-definition-other = .name = Other fees diff --git a/src/state/models/autosave.ts b/src/state/models/autosave.ts index 9dc48c0..ced9696 100644 --- a/src/state/models/autosave.ts +++ b/src/state/models/autosave.ts @@ -2,6 +2,7 @@ import { DateTime } from 'luxon' import { load, remove, save } from '~/util/local-storage' import { UserInfo } from './auth' import { RegistrationInfo } from './register' +import config from '~/config' /* eslint-disable @typescript-eslint/indent */ type DeepDateToString = @@ -17,6 +18,7 @@ type DeepDateToString = export interface SaveData { readonly userInfo?: UserInfo readonly registrationInfo?: Partial + readonly version?: number } type SerializedSaveData = DeepDateToString @@ -36,6 +38,7 @@ const serialize = (saveData: SaveData): SerializedSaveData => ({ dateOfBirth: saveData.registrationInfo.personalInfo.dateOfBirth.toISODate(), }, }, + version: config.version, }) const deserialize = (saveData: SerializedSaveData): SaveData => ({ @@ -58,7 +61,14 @@ const deserialize = (saveData: SerializedSaveData): SaveData => ({ export const loadAutosave = (): SaveData | null => { const saveData = load('redux-state') - return saveData === null ? null : deserialize(saveData) + if (saveData === null) { + return null + } else if (saveData.version !== config.version) { + // do not load old registration infos (previous year, configuration changes, ...) + return null + } else { + return deserialize(saveData) + } } export const saveAutosave = (saveData: SaveData) => { diff --git a/src/util/config-types.ts b/src/util/config-types.ts index 5b69a09..be71711 100644 --- a/src/util/config-types.ts +++ b/src/util/config-types.ts @@ -23,6 +23,7 @@ type AddonConfig = { readonly unavailableFor?: { readonly type?: readonly ('day' | 'full')[] } + readonly hidden: boolean } type RoomConfig = { @@ -32,6 +33,7 @@ type RoomConfig = { } type Config>> = { + readonly version: number readonly eventName: string readonly registrationLaunch: DateTime readonly registrationExpirationDate: DateTime From 5bc9891b0fb8ad12a0755ef59469aead9b9edd0d Mon Sep 17 00:00:00 2001 From: Jumpy Squirrel Date: Wed, 13 Dec 2023 13:46:31 +0100 Subject: [PATCH 2/2] feat(#213): user feedback --- src/config.ts | 60 +++++++++++++++++++++++++++++++++---- src/localizations/de-DE.ftl | 36 ++++++++++++++++++---- src/localizations/en-US.ftl | 36 ++++++++++++++++++---- 3 files changed, 114 insertions(+), 18 deletions(-) diff --git a/src/config.ts b/src/config.ts index ed698b6..ab48aaa 100644 --- a/src/config.ts +++ b/src/config.ts @@ -132,19 +132,43 @@ const config = checkConfig({ options: {}, hidden: true, }, - 'artshow-table-full': { + 'artshow-table-one': { price: 10, default: false, options: {}, hidden: true, }, - 'artshow-table-double': { + 'artshow-table-oneandhalf': { + price: 15, + default: false, + options: {}, + hidden: true, + }, + 'artshow-table-two': { price: 20, default: false, options: {}, hidden: true, }, - 'artshow-table-quad': { + 'artshow-table-twoandhalf': { + price: 25, + default: false, + options: {}, + hidden: true, + }, + 'artshow-table-three': { + price: 30, + default: false, + options: {}, + hidden: true, + }, + 'artshow-table-threeandhalf': { + price: 35, + default: false, + options: {}, + hidden: true, + }, + 'artshow-table-four': { price: 40, default: false, options: {}, @@ -156,19 +180,43 @@ const config = checkConfig({ options: {}, hidden: true, }, - 'artshow-panel-full': { + 'artshow-panel-one': { price: 20, default: false, options: {}, hidden: true, }, - 'artshow-panel-double': { + 'artshow-panel-oneandhalf': { + price: 30, + default: false, + options: {}, + hidden: true, + }, + 'artshow-panel-two': { price: 40, default: false, options: {}, hidden: true, }, - 'artshow-panel-quad': { + 'artshow-panel-twoandhalf': { + price: 50, + default: false, + options: {}, + hidden: true, + }, + 'artshow-panel-three': { + price: 60, + default: false, + options: {}, + hidden: true, + }, + 'artshow-panel-threeandhalf': { + price: 70, + default: false, + options: {}, + hidden: true, + }, + 'artshow-panel-four': { price: 80, default: false, options: {}, diff --git a/src/localizations/de-DE.ftl b/src/localizations/de-DE.ftl index a1ab88b..faa8272 100644 --- a/src/localizations/de-DE.ftl +++ b/src/localizations/de-DE.ftl @@ -86,25 +86,49 @@ invoice-item-definition-register-ticket-addons-boat-benefactor = invoice-item-definition-register-ticket-addons-artshow-table-half = .name = Artshow (halber Tisch) -invoice-item-definition-register-ticket-addons-artshow-table-full = +invoice-item-definition-register-ticket-addons-artshow-table-one = .name = Artshow (1 Tisch) -invoice-item-definition-register-ticket-addons-artshow-table-double = +invoice-item-definition-register-ticket-addons-artshow-table-oneandhalf = + .name = Artshow (1,5 Tische) + +invoice-item-definition-register-ticket-addons-artshow-table-two = .name = Artshow (2 Tische) -invoice-item-definition-register-ticket-addons-artshow-table-quad = +invoice-item-definition-register-ticket-addons-artshow-table-twoandhalf = + .name = Artshow (2,5 Tische) + +invoice-item-definition-register-ticket-addons-artshow-table-three = + .name = Artshow (3 Tische) + +invoice-item-definition-register-ticket-addons-artshow-table-threeandhalf = + .name = Artshow (3,5 Tische) + +invoice-item-definition-register-ticket-addons-artshow-table-four = .name = Artshow (4 Tische) invoice-item-definition-register-ticket-addons-artshow-panel-half = .name = Artshow (halbes Panel) -invoice-item-definition-register-ticket-addons-artshow-panel-full = +invoice-item-definition-register-ticket-addons-artshow-panel-one = .name = Artshow (1 Panel) -invoice-item-definition-register-ticket-addons-artshow-panel-double = +invoice-item-definition-register-ticket-addons-artshow-panel-oneandhalf = + .name = Artshow (1,5 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-two = .name = Artshow (2 Panels) -invoice-item-definition-register-ticket-addons-artshow-panel-quad = +invoice-item-definition-register-ticket-addons-artshow-panel-twoandhalf = + .name = Artshow (2,5 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-three = + .name = Artshow (3 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-threeandhalf = + .name = Artshow (3,5 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-four = .name = Artshow (4 Panels) invoice-item-definition-other = diff --git a/src/localizations/en-US.ftl b/src/localizations/en-US.ftl index e6bec82..e515fe1 100644 --- a/src/localizations/en-US.ftl +++ b/src/localizations/en-US.ftl @@ -86,25 +86,49 @@ invoice-item-definition-register-ticket-addons-boat-benefactor = invoice-item-definition-register-ticket-addons-artshow-table-half = .name = Artshow (Half a Table) -invoice-item-definition-register-ticket-addons-artshow-table-full = +invoice-item-definition-register-ticket-addons-artshow-table-one = .name = Artshow (1 Table) -invoice-item-definition-register-ticket-addons-artshow-table-double = +invoice-item-definition-register-ticket-addons-artshow-table-oneandhalf = + .name = Artshow (1.5 Tables) + +invoice-item-definition-register-ticket-addons-artshow-table-two = .name = Artshow (2 Tables) -invoice-item-definition-register-ticket-addons-artshow-table-quad = +invoice-item-definition-register-ticket-addons-artshow-table-twoandhalf = + .name = Artshow (2.5 Tables) + +invoice-item-definition-register-ticket-addons-artshow-table-three = + .name = Artshow (3 Tables) + +invoice-item-definition-register-ticket-addons-artshow-table-threeandhalf = + .name = Artshow (3.5 Tables) + +invoice-item-definition-register-ticket-addons-artshow-table-four = .name = Artshow (4 Tables) invoice-item-definition-register-ticket-addons-artshow-panel-half = .name = Artshow (Half a Panel) -invoice-item-definition-register-ticket-addons-artshow-panel-full = +invoice-item-definition-register-ticket-addons-artshow-panel-one = .name = Artshow (1 Panel) -invoice-item-definition-register-ticket-addons-artshow-panel-double = +invoice-item-definition-register-ticket-addons-artshow-panel-oneandhalf = + .name = Artshow (1.5 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-two = .name = Artshow (2 Panels) -invoice-item-definition-register-ticket-addons-artshow-panel-quad = +invoice-item-definition-register-ticket-addons-artshow-panel-twoandhalf = + .name = Artshow (2.5 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-three = + .name = Artshow (3 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-threeandhalf = + .name = Artshow (3.5 Panels) + +invoice-item-definition-register-ticket-addons-artshow-panel-four = .name = Artshow (4 Panels) invoice-item-definition-other =