Skip to content

Commit

Permalink
feat: Select price category for a signup
Browse files Browse the repository at this point in the history
  • Loading branch information
jorilindell committed Jan 24, 2024
1 parent 0a4368b commit 24558ad
Show file tree
Hide file tree
Showing 39 changed files with 821 additions and 110 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ NEXT_PUBLIC_MATOMO_PHP_TRACKER_FILE=matomo.php
NEXT_PUBLIC_MATOMO_ENABLED=false

NEXT_PUBLIC_LINKED_EVENTS_URL=https://linkedevents-api.dev.hel.ninja/linkedevents-dev/v1
NEXT_PUBLIC_WEB_STORE_INTEGRATION_ENABLED=false
1 change: 1 addition & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ OIDC_CLIENT_SECRET=<linkedregistrations-ui client secret>
OIDC_LINKED_EVENTS_API_SCOPE=linkedevents-api-dev

NEXT_PUBLIC_LINKED_EVENTS_URL=http://linkedevents-backend:8080/v1
NEXT_PUBLIC_WEB_STORE_INTEGRATION_ENABLED=true
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ ARG NEXTAUTH_URL

ARG NEXT_ENV

ARG NEXT_PUBLIC_WEB_STORE_INTEGRATION_ENABLED

RUN yarn build

# ============================================================
Expand Down
47 changes: 24 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,29 +72,30 @@ Use .env.local for development.

cp .env.local.example .env.local

| Name | Description |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| PORT | Port where app is running. Default is 3001 |
| NEXT_PUBLIC_LINKED_EVENTS_URL | linkedevents api base url |
| NEXT_PUBLIC_ENVIRONMENT | Environment used in Sentry. Use local for development |
| NEXT_PUBLIC_SENTRY_DSN | Sentry DSN. |
| SENTRY_URL | Url of Sentry instance. Default is https://sentry.test.hel.ninja |
| SENTRY_ORG | Sentry organization. Default is city-of-helsinki |
| SENTRY_PROJECT | Sentry project. Default is linkedregistrations-ui |
| SENTRY_AUTH_TOKEN | Sentry authentication token. |
| OIDC_ISSUER | Keycloak SSO service base url. Default is https://tunnistus.hel.fi/auth/realms/helsinki-tunnistus |
| OIDC_API_TOKENS_URL | Keycloak api tokens url. Default is https://tunnistus.hel.fi/auth/realms/helsinki-tunnistus/protocol/openid-connect/token/ |
| OIDC_CLIENT_ID | Client id. Default is linkedregistrations-ui |
| OIDC_CLIENT_SECRET | Secret of the oidc client |
| OIDC_LINKED_EVENTS_API_SCOPE | Linked Events API scope. Default is linkedevents-api |
| NEXT_PUBLIC_MATOMO_URL | Base url of the Matomo. Defualt is //matomo.hel.fi/ |
| NEXT_PUBLIC_MATOMO_SITE_ID | Site id in the Matomo. Default is 70 |
| NEXT_PUBLIC_MATOMO_JS_TRACKER_FILE | JavaScript tracker file name. Default is matomo.js |
| NEXT_PUBLIC_MATOMO_PHP_TRACKER_FILE | PHP tracker file name. Default is matomo.php |
| NEXT_PUBLIC_MATOMO_ENABLED | Flag to enable matomo. Default is false. |
| NEXTAUTH_SECRET | next-auth secret |
| NEXTAUTH_URL | Canonical url of the site used by next-auth |
| NEXT_ENV | 'development' or 'production' |
| Name | Description |
| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| PORT | Port where app is running. Default is 3001 |
| NEXT_PUBLIC_LINKED_EVENTS_URL | linkedevents api base url |
| NEXT_PUBLIC_ENVIRONMENT | Environment used in Sentry. Use local for development |
| NEXT_PUBLIC_SENTRY_DSN | Sentry DSN. |
| SENTRY_URL | Url of Sentry instance. Default is https://sentry.test.hel.ninja |
| SENTRY_ORG | Sentry organization. Default is city-of-helsinki |
| SENTRY_PROJECT | Sentry project. Default is linkedregistrations-ui |
| SENTRY_AUTH_TOKEN | Sentry authentication token. |
| OIDC_ISSUER | Keycloak SSO service base url. Default is https://tunnistus.hel.fi/auth/realms/helsinki-tunnistus |
| OIDC_API_TOKENS_URL | Keycloak api tokens url. Default is https://tunnistus.hel.fi/auth/realms/helsinki-tunnistus/protocol/openid-connect/token/ |
| OIDC_CLIENT_ID | Client id. Default is linkedregistrations-ui |
| OIDC_CLIENT_SECRET | Secret of the oidc client |
| OIDC_LINKED_EVENTS_API_SCOPE | Linked Events API scope. Default is linkedevents-api |
| NEXT_PUBLIC_MATOMO_URL | Base url of the Matomo. Defualt is //matomo.hel.fi/ |
| NEXT_PUBLIC_MATOMO_SITE_ID | Site id in the Matomo. Default is 70 |
| NEXT_PUBLIC_MATOMO_JS_TRACKER_FILE | JavaScript tracker file name. Default is matomo.js |
| NEXT_PUBLIC_MATOMO_PHP_TRACKER_FILE | PHP tracker file name. Default is matomo.php |
| NEXT_PUBLIC_MATOMO_ENABLED | Flag to enable matomo. Default is false. |
| NEXTAUTH_SECRET | next-auth secret |
| NEXTAUTH_URL | Canonical url of the site used by next-auth |
| NEXT_ENV | 'development' or 'production' |
| NEXT_PUBLIC_WEB_STORE_INTEGRATION_ENABLED | Flag to enable Tapla integration. Default is false |

## Url parameters

Expand Down
1 change: 1 addition & 0 deletions public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"title": "Strong identification is required"
},
"titleServerErrorSummary": "Form contains following errors",
"total": "In total",
"validation": {
"age": {
"max": "The maximum age is {{max}} y.",
Expand Down
2 changes: 2 additions & 0 deletions public/locales/en/signup.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"labelFirstName": "First name",
"labelLastName": "Last name",
"labelPhoneNumber": "Telephone number",
"labelPriceGroup": "Price group",
"labelStreetAddress": "Street address",
"labelZipcode": "Postcode",
"placeholderCity": "Enter city",
Expand All @@ -107,6 +108,7 @@
"placeholderFirstName": "Enter the registrant's first name",
"placeholderLastName": "Enter the registrant's last name",
"placeholderPhoneNumber": "+358 44 1234 567",
"placeholderPriceGroup": "Select price group",
"placeholderStreetAddress": "Enter a street address",
"placeholderZipcode": "Enter postcode",
"signupDefaultTitle": "Participant {{index}}",
Expand Down
1 change: 1 addition & 0 deletions public/locales/fi/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
"title": "Vahva tunnistautuminen vaaditaan"
},
"titleServerErrorSummary": "Lomakkeella on seuraavat virheet",
"total": "Yhteensä",
"validation": {
"age": {
"max": "Yläikäraja on {{max}}v.",
Expand Down
2 changes: 2 additions & 0 deletions public/locales/fi/signup.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"labelFirstName": "Etunimi",
"labelLastName": "Sukunimi",
"labelPhoneNumber": "Puhelinnumero",
"labelPriceGroup": "Asiakasryhmä",
"labelStreetAddress": "Katuosoite",
"labelZipcode": "Postinumero",
"placeholderCity": "Syötä kaupunki",
Expand All @@ -107,6 +108,7 @@
"placeholderFirstName": "Syötä ilmoittautujan etunimi",
"placeholderLastName": "Syötä ilmoittautujan sukunimi",
"placeholderPhoneNumber": "+358 44 1234 567",
"placeholderPriceGroup": "Valitse asiakasryhmä",
"placeholderStreetAddress": "Syötä katuosoite",
"placeholderZipcode": "Syötä postinumero",
"signupDefaultTitle": "Osallistuja {{index}}",
Expand Down
1 change: 1 addition & 0 deletions public/locales/sv/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
"title": "Stark identifiering krävs"
},
"titleServerErrorSummary": "Formuläret innehåller följande fel",
"total": "Totalt",
"validation": {
"age": {
"max": "Maxåldern är {{max}} år.",
Expand Down
2 changes: 2 additions & 0 deletions public/locales/sv/signup.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"labelFirstName": "Förnamn",
"labelLastName": "Efternamn",
"labelPhoneNumber": "Telefonnummer",
"labelPriceGroup": "Prisgrupp",
"labelStreetAddress": "Gatuadress",
"labelZipcode": "Postnummer",
"placeholderCity": "Ange staden",
Expand All @@ -107,6 +108,7 @@
"placeholderFirstName": "Ange registrantens förnamn",
"placeholderLastName": "Ange registrantens efternamn",
"placeholderPhoneNumber": "+358 44 1234 567",
"placeholderPriceGroup": "Välj prisgrupp",
"placeholderStreetAddress": "Ange en gatuadress",
"placeholderZipcode": "Ange postnummer",
"signupDefaultTitle": "Deltagare {{index}}",
Expand Down
3 changes: 2 additions & 1 deletion src/__tests__/Pages.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ const signupGroupValues: SignupGroupFormFields = {
id: TEST_SIGNUP_ID,
inWaitingList: false,
lastName: 'Last name',
phoneNumber: '+358 44 123 4567',
phoneNumber: '0441234567',
priceGroup: '',
streetAddress: 'Street address',
zipcode: '00100',
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import classNames from 'classnames';
import { FC, PropsWithChildren } from 'react';

import LoadingSpinner from '../loadingSpinner/LoadingSpinner';

import styles from './comboboxLoadingSpinner.module.scss';

export type ComboboxLoadingSpinnerProps = {
isLoading?: boolean;
};

const ComboboxLoadingSpinner: FC<
PropsWithChildren<ComboboxLoadingSpinnerProps>
> = ({ children, isLoading }) => {
return (
<div className={styles.comboboxLoadingSpinner}>
{children}
{isLoading && (
<div className={classNames(styles.loadingSpinnerWrapper)}>
<LoadingSpinner
className={styles.loadingSpinner}
isLoading={isLoading}
small={true}
/>
</div>
)}
</div>
);
};

export default ComboboxLoadingSpinner;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.comboboxLoadingSpinner {
position: relative;
}

.loadingSpinnerWrapper {
position: absolute;
top: 2.75rem;
right: var(--spacing-2-xl);
}

.loadingSpinner {
padding: 0;
}
31 changes: 20 additions & 11 deletions src/common/components/singleSelect/SingleSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import classNames from 'classnames';
import { Select, SingleSelectProps } from 'hds-react';
import { Select, SingleSelectProps as HdsSingleSelectProps } from 'hds-react';
import { useTranslation } from 'next-i18next';
import React from 'react';

Expand All @@ -8,24 +8,33 @@ import {
getA11ySelectionMessage,
getA11yStatusMessage,
} from '../../../utils/accessibilityUtils';
import ComboboxLoadingSpinner, {
ComboboxLoadingSpinnerProps,
} from '../comboboxLoadingSpinner/ComboboxLoadingSpinner';
import styles from '../select/select.module.scss';

const SingleSelect: React.FC<SingleSelectProps<OptionType>> = ({
export type SingleSelectProps = ComboboxLoadingSpinnerProps &
HdsSingleSelectProps<OptionType>;

const SingleSelect: React.FC<SingleSelectProps> = ({
className,
isLoading,
...rest
}) => {
const { t } = useTranslation('common');

return (
<Select
{...rest}
className={classNames(className, styles.select)}
getA11yStatusMessage={(options) => getA11yStatusMessage(options, t)}
getA11ySelectionMessage={
/* istanbul ignore next */
(options) => getA11ySelectionMessage(options, t)
}
/>
<ComboboxLoadingSpinner isLoading={isLoading}>
<Select
{...rest}
className={classNames(className, styles.select)}
getA11yStatusMessage={(options) => getA11yStatusMessage(options, t)}
getA11ySelectionMessage={
/* istanbul ignore next */
(options) => getA11ySelectionMessage(options, t)
}
/>
</ComboboxLoadingSpinner>
);
};

Expand Down
42 changes: 42 additions & 0 deletions src/domain/priceGroup/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { OptionType } from '../../types';
import { LocalisedObject, Meta, stringOrNull } from '../api/types';

export type PriceGroup = {
id: number;
created_by: stringOrNull;
created_time: stringOrNull;
description: LocalisedObject;
is_free: boolean;
last_modified_by: stringOrNull;
last_modified_time: stringOrNull;
publisher: stringOrNull;
};

export type PriceGroupDense = {
id: number;
description: LocalisedObject;
};

export type RegistrationPriceGroup = {
id: number;
price_group: PriceGroupDense;
price: stringOrNull;
vat_percentage: stringOrNull;
price_without_vat: stringOrNull;
vat: stringOrNull;
};

export type PriceGroupsQueryVariables = {
description?: string;
isFree?: boolean;
page?: number;
pageSize?: number;
publisher?: string[];
};

export type PriceGroupsResponse = {
meta: Meta;
data: PriceGroup[];
};

export type PriceGroupOption = OptionType & { isFree: boolean };
2 changes: 2 additions & 0 deletions src/domain/registration/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
stringOrNull,
} from '../api/types';
import { Event } from '../event/types';
import { RegistrationPriceGroup } from '../priceGroup/types';
import { Signup } from '../signup/types';

export type Registration = {
Expand All @@ -29,6 +30,7 @@ export type Registration = {
maximum_group_size: numberOrNull;
minimum_attendee_capacity: numberOrNull;
publisher: string;
registration_price_groups: RegistrationPriceGroup[];
remaining_attendee_capacity: numberOrNull;
remaining_waiting_list_capacity: numberOrNull;
signups: Signup[] | null;
Expand Down
14 changes: 13 additions & 1 deletion src/domain/signup/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { fakeContactPerson, fakeSignup } from '../../../utils/mockDataUtils';
import {
fakeContactPerson,
fakeSignup,
fakeSignupPriceGroup,
} from '../../../utils/mockDataUtils';
import { registration } from '../../registration/__mocks__/registration';
import {
NOTIFICATIONS,
Expand Down Expand Up @@ -121,6 +125,7 @@ describe('getSignupGroupInitialValuesFromSignup function', () => {
id: TEST_SIGNUP_ID,
last_name: null,
phone_number: null,
price_group: null,
street_address: null,
zipcode: null,
})
Expand All @@ -136,6 +141,7 @@ describe('getSignupGroupInitialValuesFromSignup function', () => {
inWaitingList: false,
lastName: '',
phoneNumber: '',
priceGroup: '',
streetAddress: '',
zipcode: '',
},
Expand Down Expand Up @@ -164,6 +170,7 @@ describe('getSignupGroupInitialValuesFromSignup function', () => {
const expectedNativeLanguage = 'fi';
const expectedNotifications = [NOTIFICATIONS.EMAIL];
const expectedPhoneNumber = '+358 44 123 4567';
const expectedPriceGroup = '1';
const expectedServiceLanguage = 'sv';
const expectedStreetAddress = 'Test address';
const expectedUserConsent = true;
Expand Down Expand Up @@ -204,6 +211,7 @@ describe('getSignupGroupInitialValuesFromSignup function', () => {
id: TEST_SIGNUP_ID,
last_name: expectedLastName,
phone_number: expectedPhoneNumber,
price_group: fakeSignupPriceGroup({ registration_price_group: 1 }),
street_address: expectedStreetAddress,
user_consent: expectedUserConsent,
zipcode: expectedZip,
Expand All @@ -220,6 +228,7 @@ describe('getSignupGroupInitialValuesFromSignup function', () => {
inWaitingList: false,
lastName: expectedLastName,
phoneNumber: expectedPhoneNumber,
priceGroup: expectedPriceGroup,
streetAddress: expectedStreetAddress,
zipcode: expectedZip,
},
Expand Down Expand Up @@ -295,6 +304,7 @@ describe('getUpdateSignupPayload function', () => {
nativeLanguage = 'fi',
notifications = [NOTIFICATIONS.EMAIL],
phoneNumber = '0441234567',
priceGroup = '1',
serviceLanguage = 'sv',
streetAddress = 'Street address',
zipcode = '00100';
Expand All @@ -308,6 +318,7 @@ describe('getUpdateSignupPayload function', () => {
inWaitingList: false,
lastName,
phoneNumber,
priceGroup,
streetAddress,
zipcode,
},
Expand Down Expand Up @@ -353,6 +364,7 @@ describe('getUpdateSignupPayload function', () => {
id: TEST_SIGNUP_ID,
last_name: lastName,
phone_number: phoneNumber,
price_group: { registration_price_group: 1 },
registration: registration.id,
street_address: streetAddress,
user_consent: false,
Expand Down
Loading

0 comments on commit 24558ad

Please sign in to comment.