Skip to content

Commit

Permalink
feat: implement "datepicker" as the last custom register field
Browse files Browse the repository at this point in the history
  • Loading branch information
mirovladimitrovski committed Jun 15, 2023
1 parent a84c6da commit d66d5da
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 40 deletions.
14 changes: 7 additions & 7 deletions src/components/Account/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true }
name="firstName"
label={t('account.firstname')}
value={section.values.firstName || ''}
onChange={section.onChange}
onChange={section.onChangeEvent}
error={!!section.errors?.firstName}
helperText={section.errors?.firstName}
disabled={section.isBusy}
Expand All @@ -202,7 +202,7 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true }
name="lastName"
label={t('account.lastname')}
value={section.values.lastName || ''}
onChange={section.onChange}
onChange={section.onChangeEvent}
error={!!section.errors?.lastName}
helperText={section.errors?.lastName}
disabled={section.isBusy}
Expand All @@ -227,7 +227,7 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true }
name="email"
label={t('account.email')}
value={section.values.email || ''}
onChange={section.onChange}
onChange={section.onChangeEvent}
error={!!section.errors?.email}
helperText={section.errors?.email}
disabled={section.isBusy}
Expand All @@ -239,7 +239,7 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true }
name="confirmationPassword"
label={t('account.confirm_password')}
value={section.values.confirmationPassword}
onChange={section.onChange}
onChange={section.onChangeEvent}
error={!!section.errors?.confirmationPassword}
helperText={section.errors?.confirmationPassword}
type={viewPassword ? 'text' : 'password'}
Expand Down Expand Up @@ -270,7 +270,7 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true }
key={index}
name={`consentsValues.${consent.name}`}
checked={section.values.consentsValues?.[consent.name] === true}
onChange={section.onChange}
onChange={section.onChangeEvent}
label={formatConsentLabel(consent.label)}
disabled={consent.required || section.isBusy}
/>
Expand All @@ -295,8 +295,8 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true }
label={formatConsentLabel(consent.label)}
placeholder={consent.placeholder}
value={section.values.consentsValues[consent.name]}
disabled={consent.required || section.isBusy}
onChange={section.onChange}
disabled={(consent.type === ConsentFieldVariants.CHECKBOX && consent.required) || section.isBusy}
onChange={(name, value) => section.onChangeValue(name, value)}
/>
))}
</div>
Expand Down
27 changes: 20 additions & 7 deletions src/components/CustomRegisterField/CustomRegisterField.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { type FC, type ChangeEventHandler, type ReactNode, useMemo } from 'react';
import { type FC, type ChangeEventHandler, type ReactNode, useMemo, useCallback } from 'react';
import type { GetRegisterFieldOption } from '@inplayer-org/inplayer.js';

import Checkbox from '#components/Checkbox/Checkbox';
import TextField from '#components/TextField/TextField';
import Radio from '#components/Radio/Radio';
import Dropdown from '#components/Dropdown/Dropdown';
import DateField from '#components/DateField/DateField';
import { ConsentFieldVariants } from '#src/services/inplayer.account.service';
import { countries, usStates } from '#static/json';

type Props = {
type: ConsentFieldVariants;
name: string;
value: string | boolean;
onChange: ChangeEventHandler<HTMLInputElement>;
onChange: (name: string, value: string | boolean) => void;
} & Partial<{
label: ReactNode;
placeholder: string;
Expand All @@ -25,7 +26,7 @@ type Props = {

export type CustomRegisterFieldCommonProps = Props;

export const CustomRegisterField: FC<Props> = ({ type, value = '', ...props }) => {
export const CustomRegisterField: FC<Props> = ({ type, name, value = '', onChange, ...props }) => {
const optionsList = useMemo(() => {
const optionsObject = (() => {
switch (type) {
Expand All @@ -45,17 +46,29 @@ export const CustomRegisterField: FC<Props> = ({ type, value = '', ...props }) =
return Object.entries(optionsObject).map(([value, label]) => ({ value, label }));
}, [type, props.options]);

const changeHandler: ChangeEventHandler<HTMLInputElement> = useCallback(
({ currentTarget }) => {
const value = type === ConsentFieldVariants.CHECKBOX ? (currentTarget as HTMLInputElement).checked : currentTarget.value;
onChange(name, value);
},
[type, name, onChange],
);

const commonProps = { ...props, name, onChange: changeHandler };

switch (type) {
case ConsentFieldVariants.CHECKBOX:
return <Checkbox {...props} checked={value === true} />;
return <Checkbox {...commonProps} checked={value === true} />;
case ConsentFieldVariants.INPUT:
return <TextField {...props} value={value as string} />;
return <TextField {...commonProps} value={value as string} />;
case ConsentFieldVariants.RADIO:
return <Radio {...props} values={optionsList} value={value as string} header={props.label} />;
return <Radio {...commonProps} values={optionsList} value={value as string} header={props.label} />;
case ConsentFieldVariants.GENERAL_SELECT:
case ConsentFieldVariants.COUNTRY_SELECT:
case ConsentFieldVariants.US_STATE_SELECT:
return <Dropdown {...props} options={optionsList} value={value as string} defaultLabel={props.placeholder} fullWidth />;
return <Dropdown {...commonProps} options={optionsList} value={value as string} defaultLabel={props.placeholder} fullWidth />;
case ConsentFieldVariants.DATE_PICKER:
return <DateField {...commonProps} value={value as string} onChange={(dateString: string) => onChange(name, dateString)} />;
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1548,7 +1548,56 @@ exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="co
</div>
`;
exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="datepicker"> 1`] = `<div />`;
exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="datepicker"> 1`] = `
<div>
<div
class="_dateField_eb6974"
>
<label
class="_label_eb6974"
for="text-field_1235_name"
>
label
<span>
optional
</span>
</label>
<div
class="_container_eb6974"
>
<input
class="_input_eb6974"
id="text-field_1235_name"
maxlength="2"
name="date"
placeholder="dd"
type="number"
value=""
/>
/
<input
class="_input_eb6974"
id="text-field_1235_name"
maxlength="2"
name="month"
placeholder="mm"
type="number"
value=""
/>
/
<input
class="_input_eb6974"
id="text-field_1235_name"
maxlength="4"
name="year"
placeholder="yyyy"
type="number"
value=""
/>
</div>
</div>
</div>
`;
exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="randomstring"> 1`] = `<div />`;
Expand Down
4 changes: 2 additions & 2 deletions src/components/DateField/DateField.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, type ReactNode } from 'react';
import classNames from 'classnames';
import { useTranslation } from 'react-i18next';

Expand All @@ -9,7 +9,7 @@ import useOpaqueId from '#src/hooks/useOpaqueId';

type Props = {
className?: string;
label?: string;
label?: ReactNode;
placeholder?: string;
name?: string;
value: string;
Expand Down
28 changes: 18 additions & 10 deletions src/components/Form/FormSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export interface FormSectionContentArgs<T extends GenericFormValues, TErrors> {
values: T;
isEditing: boolean;
isBusy: boolean;
onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onChangeEvent: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onChangeValue: (name: string, value: string | boolean) => void;
errors?: TErrors | undefined;
}

Expand Down Expand Up @@ -52,13 +53,8 @@ export function FormSection<TData extends GenericFormValues>({

const isEditing = sectionId === activeSectionId;

const onChange = useCallback(
function onChange({ currentTarget }: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>) {
if (!currentTarget) return;

const { name, type } = currentTarget;
const value = type === 'checkbox' ? (currentTarget as HTMLInputElement).checked : currentTarget.value;

const onChangeValue = useCallback(
(name: string, value: string | boolean) => {
if (!isEditing) {
onCancel();
}
Expand Down Expand Up @@ -88,6 +84,18 @@ export function FormSection<TData extends GenericFormValues>({
[isEditing, onCancel, sectionId, setFormState],
);

const onChangeEvent = useCallback(
function onChange({ currentTarget }: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>) {
if (!currentTarget) return;

const { name, type } = currentTarget;
const value = type === 'checkbox' ? (currentTarget as HTMLInputElement).checked : currentTarget.value;

onChangeValue(name, value);
},
[onChangeValue],
);

const handleSubmit = useCallback(
async function handleSubmit(event?: React.FormEvent) {
event && event.preventDefault();
Expand Down Expand Up @@ -155,10 +163,10 @@ export function FormSection<TData extends GenericFormValues>({
{content &&
(isEditing ? (
<form className={styles.flexBox} noValidate onSubmit={(event) => event.preventDefault()}>
{content({ values, isEditing, isBusy, onChange, errors: formErrors })}
{content({ values, isEditing, isBusy, onChangeEvent, onChangeValue, errors: formErrors })}
</form>
) : (
<div className={styles.flexBox}>{content({ values, isEditing, isBusy, onChange })}</div>
<div className={styles.flexBox}>{content({ values, isEditing, isBusy, onChangeEvent, onChangeValue })}</div>
))}
{(saveButton || editButton || cancelButton) && (
<div className={styles.controls}>
Expand Down
13 changes: 2 additions & 11 deletions src/components/RegistrationForm/RegistrationForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { type ChangeEventHandler } from 'react';
import React from 'react';
import { useLocation } from 'react-router';
import { useTranslation } from 'react-i18next';
import DOMPurify from 'dompurify';
Expand Down Expand Up @@ -68,15 +68,6 @@ const RegistrationForm: React.FC<Props> = ({
return label;
};

const changeHandler: ChangeEventHandler<HTMLInputElement> = ({ currentTarget }) => {
if (!currentTarget) return;

const { name, type } = currentTarget;
const value = type === 'checkbox' ? (currentTarget as HTMLInputElement).checked : currentTarget.value;

onConsentChange(name, value);
};

if (loading) {
return (
<div style={{ height: 400 }}>
Expand Down Expand Up @@ -137,7 +128,7 @@ const RegistrationForm: React.FC<Props> = ({
required={consent.required}
error={consentErrors?.includes(consent.name)}
helperText={consentErrors?.includes(consent.name) ? t('registration.consent_required') : undefined}
onChange={changeHandler}
onChange={onConsentChange}
/>
))}
</div>
Expand Down
3 changes: 1 addition & 2 deletions src/services/inplayer.account.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,7 @@ export const getPublisherConsents: GetPublisherConsents<ConsentFieldVariants, st
const { data } = await InPlayer.Account.getRegisterFields(jwp?.clientId || '');

const result = data?.collection
// todo: implement DATE_PICKER at some point
.filter((field) => (field.type as ConsentFieldVariants) !== ConsentFieldVariants.DATE_PICKER && field.name !== 'email_confirmation')
.filter((field) => field.name !== 'email_confirmation')
.map(
(field): Consent<ConsentFieldVariants> => ({
type: field.type as ConsentFieldVariants,
Expand Down

0 comments on commit d66d5da

Please sign in to comment.