Skip to content

Commit

Permalink
fix: fixed consent updating in Account section
Browse files Browse the repository at this point in the history
  • Loading branch information
mirovladimitrovski committed Jun 8, 2023
1 parent 3b81892 commit d378708
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 138 deletions.
3 changes: 2 additions & 1 deletion src/components/Account/Account.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import customer from '#test/fixtures/customer.json';
import { useAccountStore } from '#src/stores/AccountStore';
import { renderWithRouter } from '#test/testUtils';
import type { Consent } from '#types/account';
import type { ConsentFieldVariants } from '#src/services/inplayer.account.service';

describe('<Account>', () => {
test('renders and matches snapshot', () => {
useAccountStore.setState({
user: customer,
publisherConsents: Array.of({ name: 'marketing', label: 'Receive Marketing Emails' } as Consent),
publisherConsents: Array.of({ name: 'marketing', label: 'Receive Marketing Emails' } as Consent<ConsentFieldVariants>),
});

const { container } = renderWithRouter(<Account panelClassName={'panel-class'} panelHeaderClassName={'header-class'} canUpdateEmail={true} />);
Expand Down
15 changes: 7 additions & 8 deletions src/components/Account/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true }
);

const [termsConsents, nonTermsConsents] = useMemo(() => {
const terms: Consent[] = [];
const nonTerms: Consent[] = [];
const terms: Consent<ConsentFieldVariants>[] = [];
const nonTerms: Consent<ConsentFieldVariants>[] = [];

publisherConsents?.forEach((consent) => {
if (!Object.hasOwn(consent, 'type') || consent.type === ConsentFieldVariants.CHECKBOX) {
Expand Down Expand Up @@ -268,15 +268,14 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true }
formSection({
label: t('account.terms_and_tracking'),
saveButton: t('account.update_consents'),
onSubmit: (values) => updateConsents(formatConsentsFromValues(publisherConsents, values)),
onSubmit: (values) => updateConsents(formatConsentsFromValues(publisherConsents, { ...values.consentsValues, terms: true })),
content: (section) => (
<>
{termsConsents?.map((consent, index) => (
<Checkbox
key={index}
name={`consents.${consent.name}`}
value={consent.value || ''}
checked={`${section.values.consents?.[consent.name]}` === 'true'}
name={`consentsValues.${consent.name}`}
checked={section.values.consentsValues?.[consent.name] === true}
onChange={section.onChange}
label={formatConsentLabel(consent.label)}
disabled={consent.required || section.isBusy}
Expand All @@ -290,13 +289,13 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true }
formSection({
label: t('account.other_registration_details'),
saveButton: t('account.update_consents'),
onSubmit: (values) => updateConsents(formatConsentsFromValues(nonTermsConsents, values.consentsValues)),
onSubmit: (values) => updateConsents(formatConsentsFromValues(publisherConsents, values.consentsValues)),
content: (section) => (
<div className={styles.customFields}>
{nonTermsConsents.map((consent) => (
<CustomRegisterField
key={consent.name}
type={consent.type as ConsentFieldVariants}
type={consent.type}
name={`consentsValues.${consent.name}`}
options={consent.options}
label={formatConsentLabel(consent.label)}
Expand Down
6 changes: 3 additions & 3 deletions src/components/Account/__snapshots__/Account.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,13 @@ exports[`<Account> > renders and matches snapshot 1`] = `
class="_row_531f07"
>
<input
id="check-box_1235_consents.marketing"
name="consents.marketing"
id="check-box_1235_consentsValues.marketing"
name="consentsValues.marketing"
type="checkbox"
value=""
/>
<label
for="check-box_1235_consents.marketing"
for="check-box_1235_consentsValues.marketing"
>
Receive Marketing Emails
Expand Down
12 changes: 6 additions & 6 deletions src/components/CustomRegisterField/CustomRegisterField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { countries, usStates } from '#static/json';
type Props = {
type: ConsentFieldVariants;
name: string;
value: string;
value: string | boolean;
onChange: ChangeEventHandler<HTMLInputElement>;
} & Partial<{
label: ReactNode;
Expand Down Expand Up @@ -48,16 +48,16 @@ export const CustomRegisterField: FC<Props> = ({ type, name, value = '', onChang
const commonProps = { ...props, name, onChange };

switch (type) {
case ConsentFieldVariants.CHECKBOX:
return <Checkbox {...commonProps} checked={value === true} />;
case ConsentFieldVariants.INPUT:
return <TextField {...commonProps} value={value} />;
return <TextField {...commonProps} value={value as string} />;
case ConsentFieldVariants.RADIO:
return <Radio {...commonProps} values={optionsList} value={value} 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 {...commonProps} options={optionsList} value={value} defaultLabel={props.placeholder} fullWidth />;
default:
return <Checkbox {...commonProps} checked={value === 'true'} />;
return <Dropdown {...commonProps} options={optionsList} value={value as string} defaultLabel={props.placeholder} fullWidth />;
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1548,55 +1548,9 @@ exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="co
</div>
`;
exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="datepicker"> 1`] = `
<div>
<div
class="_checkbox_531f07"
>
<div
class="_row_531f07"
>
<input
id="check-box_1235_name"
name="name"
type="checkbox"
value=""
/>
<label
for="check-box_1235_name"
>
label
</label>
</div>
</div>
</div>
`;
exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="datepicker"> 1`] = `<div />`;
exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="randomstring"> 1`] = `
<div>
<div
class="_checkbox_531f07"
>
<div
class="_row_531f07"
>
<input
id="check-box_1235_name"
name="name"
type="checkbox"
value=""
/>
<label
for="check-box_1235_name"
>
label
</label>
</div>
</div>
</div>
`;
exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="randomstring"> 1`] = `<div />`;
exports[`<CustomRegisterField> > renders and matches snapshot <Dropdown type="select"> 1`] = `
<div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Form/FormSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function FormSection<TData extends GenericFormValues>({
if (!currentTarget) return;

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

if (!isEditing) {
onCancel();
Expand Down
6 changes: 3 additions & 3 deletions src/components/RegistrationForm/RegistrationForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ type Props = {
onSubmit: React.FormEventHandler<HTMLFormElement>;
onChange: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onBlur: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
onConsentChange: (name: string, value: string) => void;
onConsentChange: (name: string, value: string | boolean) => void;
errors: FormErrors<RegistrationFormData>;
values: RegistrationFormData;
loading: boolean;
consentValues: Record<string, string>;
consentValues: Record<string, string | boolean>;
consentErrors: string[];
submitting: boolean;
canSubmit: boolean;
Expand Down Expand Up @@ -72,7 +72,7 @@ const RegistrationForm: React.FC<Props> = ({
if (!currentTarget) return;

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

onConsentChange(name, value);
};
Expand Down
4 changes: 2 additions & 2 deletions src/containers/AccountModal/forms/Registration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ const Registration = () => {
const navigate = useNavigate();
const location = useLocation();
const { t } = useTranslation('account');
const [consentValues, setConsentValues] = useState<Record<string, string>>({});
const [consentValues, setConsentValues] = useState<Record<string, string | boolean>>({});
const [consentErrors, setConsentErrors] = useState<string[]>([]);

const { data, isLoading: publisherConsentsLoading } = useQuery(['consents'], getPublisherConsents);
const publisherConsents = useMemo(() => data?.consents || [], [data]);

const handleChangeConsent = (name: string, value: string) => {
const handleChangeConsent = (name: string, value: string | boolean) => {
setConsentValues((current) => ({
...current,
[name]: value,
Expand Down
23 changes: 19 additions & 4 deletions src/services/cleeng.account.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import jwtDecode from 'jwt-decode';

import { post, put, patch, get } from './cleeng.service';
import { ConsentFieldVariants } from './inplayer.account.service';

import type { Config } from '#types/Config';
import { getOverrideIP } from '#src/utils/common';
Expand Down Expand Up @@ -29,6 +30,8 @@ import type {
UpdateCustomerPayload,
ChangePasswordWithOldPassword,
UpdatePersonalShelves,
CleengConsent,
Consent,
} from '#types/account';
import cleengAuthService from '#src/services/cleeng.auth.service';

Expand Down Expand Up @@ -131,15 +134,27 @@ export async function getUser({ config }: { config: Config }) {
};
}

export const getPublisherConsents: GetPublisherConsents = async (config) => {
export const getPublisherConsents: GetPublisherConsents<ConsentFieldVariants, boolean> = async (config) => {
const { cleeng } = config.integrations;
const response = await get(!!cleeng?.useSandbox, `/publishers/${cleeng?.id}/consents`);

handleErrors(response.errors);

return {
consents: response?.responseData?.consents || [],
};
const consents = ((response?.responseData?.consents || []) as CleengConsent[]).map(
(cleengConsent): Consent<ConsentFieldVariants> => ({
type: ConsentFieldVariants.CHECKBOX,
provider: 'cleeng',
defaultValue: cleengConsent.enabledByDefault,
name: cleengConsent.name,
label: cleengConsent.label,
placeholder: '',
required: cleengConsent.required,
options: {},
version: cleengConsent.version,
}),
);

return { consents };
};

export const getCustomerConsents: GetCustomerConsents = async (payload) => {
Expand Down
64 changes: 24 additions & 40 deletions src/services/inplayer.account.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import InPlayer, { AccountData, Env, RegisterField, UpdateAccountData, FavoritesData, WatchHistory, GetRegisterFieldOption } from '@inplayer-org/inplayer.js';
import InPlayer, { AccountData, Env, UpdateAccountData, FavoritesData, WatchHistory } from '@inplayer-org/inplayer.js';
import i18next from 'i18next';

import type {
AuthData,
Capture,
ChangePassword,
ChangePasswordWithOldPassword,
JwConsent,
Consent,
Customer,
CustomerConsent,
Expand Down Expand Up @@ -153,21 +154,25 @@ export const updateCustomer: UpdateCustomer = async (customer) => {
}
};

export const getPublisherConsents: GetPublisherConsents<ConsentFieldVariants> = async (config) => {
export const getPublisherConsents: GetPublisherConsents<ConsentFieldVariants, string | boolean> = async (config) => {
try {
const { jwp } = config.integrations;
const { data } = await InPlayer.Account.getRegisterFields(jwp?.clientId || '');

const result = data?.collection
// todo 1: update RegisterField.type: string to RegisterField.type: ConsentFieldVariants
// todo 2: implement DATE_PICKER at some point
const result = (data?.collection as JwConsent<ConsentFieldVariants>[])
// todo: implement DATE_PICKER at some point
.filter((field) => (field.type as ConsentFieldVariants) !== ConsentFieldVariants.DATE_PICKER && field.name !== 'email_confirmation')
.map((field) =>
formatPublisherConsents({
...field,
type: field.type as ConsentFieldVariants,
// todo 3: field.option type in SDK is incorrect, remove this line entirely after fixing that
options: field.options as unknown as GetRegisterFieldOption,
.map(
(field): Consent<ConsentFieldVariants> => ({
type: field.type,
provider: 'jwp',
defaultValue: field.type === ConsentFieldVariants.CHECKBOX ? field.default_value === 'true' : field.default_value,
name: field.name,
label: field.label,
placeholder: field.placeholder,
required: field.required,
options: field.options,
version: '1',
}),
);

Expand Down Expand Up @@ -433,41 +438,20 @@ function formatAuth(auth: InPlayerAuthData): AuthData {
};
}

const formatPublisherConsents = <T = string>({
type,
label,
placeholder,
name,
required,
default_value: defaultValue = '',
options,
}: Pick<RegisterField, 'label' | 'name' | 'required'> & {
type: T;
default_value?: string;
placeholder?: string;
options?: GetRegisterFieldOption;
}): Consent<T> => ({
type: type as T,
label,
placeholder,
name,
required,
defaultValue,
broadcasterId: 0,
value: '',
version: '1',
options,
});

function getTermsConsent() {
function getTermsConsent(): Consent<ConsentFieldVariants> {
const termsUrl = '<a href="https://inplayer.com/legal/terms" target="_blank">Terms and Conditions</a>';

return formatPublisherConsents({
return {
type: ConsentFieldVariants.CHECKBOX,
provider: 'jwp',
required: true,
name: 'terms',
label: i18next.t('account:registration.terms_consent', { termsUrl }),
});
defaultValue: false,
placeholder: '',
options: {},
version: '1',
};
}

function parseJson(value: string, fallback = {}) {
Expand Down
7 changes: 4 additions & 3 deletions src/stores/AccountStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import type { PaymentDetail, Subscription, Transaction } from '#types/subscripti
import type { Consent, Customer, CustomerConsent } from '#types/account';
import { createStore } from '#src/stores/utils';
import type { Offer } from '#types/checkout';
import type { ConsentFieldVariants } from '#src/services/inplayer.account.service';

type AccountStore = {
type AccountStore<T = string> = {
loading: boolean;
user: Customer | null;
subscription: Subscription | null;
transactions: Transaction[] | null;
activePayment: PaymentDetail | null;
customerConsents: CustomerConsent[] | null;
publisherConsents: Consent[] | null;
publisherConsents: Consent<T>[] | null;
pendingOffer: Offer | null;
canUpdateEmail: boolean;
canRenewSubscription: boolean;
Expand All @@ -21,7 +22,7 @@ type AccountStore = {
setLoading: (loading: boolean) => void;
};

export const useAccountStore = createStore<AccountStore>('AccountStore', (set) => ({
export const useAccountStore = createStore<AccountStore<ConsentFieldVariants>>('AccountStore', (set) => ({
loading: true,
user: null,
subscription: null,
Expand Down
Loading

0 comments on commit d378708

Please sign in to comment.