diff --git a/public/locales/en/user.json b/public/locales/en/user.json index 2eb2f0f3c..2bdcf2ed8 100644 --- a/public/locales/en/user.json +++ b/public/locales/en/user.json @@ -24,6 +24,7 @@ "firstname": "First name", "hide_password": "Hide password", "lastname": "Last name", + "other_registration_details": "Other registration details", "password": "Password", "save": "Save", "security": "Security", diff --git a/public/locales/en/video.json b/public/locales/en/video.json index 81d666b73..e47285932 100644 --- a/public/locales/en/video.json +++ b/public/locales/en/video.json @@ -8,7 +8,6 @@ "current_episode": "Current episode", "current_video": "Current video", "episode": "episode", - "episode_not_found": "Episode not found", "episodes": "Episodes", "favorite": "Favorite", "favorites_warning": "Maximum amount of favorite videos exceeded. You can only add up to {{maxCount}} favorite videos. Please delete one and repeat the operation.", diff --git a/public/locales/es/user.json b/public/locales/es/user.json index 49db1493e..3bbc58e24 100644 --- a/public/locales/es/user.json +++ b/public/locales/es/user.json @@ -24,6 +24,7 @@ "firstname": "Nombre", "hide_password": "Ocultar contraseña", "lastname": "Apellido", + "other_registration_details": "Otros detalles de registro", "password": "Contraseña", "save": "Guardar", "security": "Seguridad", diff --git a/public/locales/es/video.json b/public/locales/es/video.json index 891642940..01899bb34 100644 --- a/public/locales/es/video.json +++ b/public/locales/es/video.json @@ -8,7 +8,6 @@ "current_episode": "Episodio actual", "current_video": "Video actual", "episode": "episodio", - "episode_not_found": "Episodio no encontrado", "episodes": "Episodios", "favorite": "Favorito", "favorites_warning": "Se ha alcanzado el máximo de videos favoritos. Solo puedes agregar hasta {{maxCount}} videos favoritos. Por favor, elimina uno y repite la operación.", diff --git a/src/components/Account/Account.module.scss b/src/components/Account/Account.module.scss index f71f8a498..9ecf55a78 100644 --- a/src/components/Account/Account.module.scss +++ b/src/components/Account/Account.module.scss @@ -3,3 +3,9 @@ flex-direction: column; gap: 1rem; } + +.customFields { + display: flex; + flex-direction: column; + gap: 0.5em; +} \ No newline at end of file diff --git a/src/components/Account/Account.tsx b/src/components/Account/Account.tsx index 4ecaeea9c..e6078d8b6 100644 --- a/src/components/Account/Account.tsx +++ b/src/components/Account/Account.tsx @@ -8,6 +8,7 @@ import { useMutation } from 'react-query'; import styles from './Account.module.scss'; import type { FormSectionContentArgs, FormSectionProps } from '#components/Form/FormSection'; +import type { ConsentFieldVariants } from '#src/services/inplayer.account.service'; import Alert from '#components/Alert/Alert'; import Visibility from '#src/icons/Visibility'; import VisibilityOff from '#src/icons/VisibilityOff'; @@ -17,8 +18,9 @@ import IconButton from '#components/IconButton/IconButton'; import TextField from '#components/TextField/TextField'; import Checkbox from '#components/Checkbox/Checkbox'; import HelperText from '#components/HelperText/HelperText'; +import CustomRegisterField from '#components/CustomRegisterField/CustomRegisterField'; import useToggle from '#src/hooks/useToggle'; -import { formatConsentsFromValues, formatConsentValues } from '#src/utils/collection'; +import { formatConsentsFromValues, formatConsents, formatConsentValues } from '#src/utils/collection'; import { addQueryParam } from '#src/utils/location'; import { useAccountStore } from '#src/stores/AccountStore'; import { logDev } from '#src/utils/common'; @@ -64,15 +66,25 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true } shallow, ); - const consentValues = useMemo(() => formatConsentValues(publisherConsents, customerConsents), [publisherConsents, customerConsents]); + const [termsConsents, nonTermsConsents] = useMemo(() => { + const terms = (publisherConsents || []).filter((consent) => consent.name === 'terms'); + const nonTerms = publisherConsents?.filter((consent) => consent.name !== 'terms'); + + return [terms, nonTerms]; + }, [publisherConsents]); + + const consents = useMemo(() => formatConsents(publisherConsents, customerConsents), [publisherConsents, customerConsents]); + + const consentsValues = useMemo(() => formatConsentValues(publisherConsents, customerConsents), [publisherConsents, customerConsents]); const initialValues = useMemo( () => ({ ...customer, - consents: consentValues, + consents, + consentsValues, confirmationPassword: '', }), - [customer, consentValues], + [customer, consents, consentsValues], ); const formatConsentLabel = (label: string): string | JSX.Element => { @@ -250,7 +262,7 @@ const Account = ({ panelClassName, panelHeaderClassName, canUpdateEmail = true } onSubmit: (values) => updateConsents(formatConsentsFromValues(publisherConsents, values)), content: (section) => ( <> - {publisherConsents?.map((consent, index) => ( + {termsConsents?.map((consent, index) => ( ), }), + ...(nonTermsConsents + ? [ + formSection({ + label: t('account.other_registration_details'), + saveButton: t('account.update_consents'), + onSubmit: (values) => updateConsents(formatConsentsFromValues(nonTermsConsents, values.consentsValues)), + content: (section) => ( +
+ {nonTermsConsents.map((consent) => ( + + ))} +
+ ), + }), + ] + : []), ...(canExportAccountData ? [ formSection({ diff --git a/src/components/Account/__snapshots__/Account.test.tsx.snap b/src/components/Account/__snapshots__/Account.test.tsx.snap index 98154ca18..797ea34d4 100644 --- a/src/components/Account/__snapshots__/Account.test.tsx.snap +++ b/src/components/Account/__snapshots__/Account.test.tsx.snap @@ -138,29 +138,29 @@ exports[` > renders and matches snapshot 1`] = ` account.terms_and_tracking +
+
+
+
+
+

+ account.other_registration_details +

+
-
- - -
-
+ class="_customFields_c968f7" + />
void; + onChange: ChangeEventHandler; } & Partial<{ label: ReactNode; placeholder: string; @@ -26,17 +26,6 @@ type Props = { export type CustomRegisterFieldCommonProps = Props; export const CustomRegisterField: FC = ({ type, name, value = '', onChange, ...props }) => { - const changeHandler: ChangeEventHandler = useCallback( - (e) => { - if (type === ConsentFieldVariants.CHECKBOX) { - onChange(name, `${e.target.checked}`); - } else { - onChange(name, e.target.value); - } - }, - [type, name, onChange], - ); - const optionsList = useMemo(() => { const optionsObject = (() => { switch (type) { @@ -56,7 +45,7 @@ export const CustomRegisterField: FC = ({ type, name, value = '', onChang return Object.entries(optionsObject).map(([value, label]) => ({ value, label })); }, [type, props.options]); - const commonProps = { ...props, name, onChange: changeHandler }; + const commonProps = { ...props, name, onChange }; switch (type) { case ConsentFieldVariants.CHECKBOX: diff --git a/src/components/Form/Form.tsx b/src/components/Form/Form.tsx index 2cd74d220..903026ee6 100644 --- a/src/components/Form/Form.tsx +++ b/src/components/Form/Form.tsx @@ -75,7 +75,7 @@ function Form({ isLoading, initialValues, onRes }} > {children?.map((props, i) => ( - + key={i} {...props} /> ))} ); diff --git a/src/components/Form/FormSection.tsx b/src/components/Form/FormSection.tsx index 8bb326a53..4946e0918 100644 --- a/src/components/Form/FormSection.tsx +++ b/src/components/Form/FormSection.tsx @@ -57,7 +57,7 @@ export function FormSection({ 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(); diff --git a/src/components/RegistrationForm/RegistrationForm.tsx b/src/components/RegistrationForm/RegistrationForm.tsx index ad0e17c3a..60c589bdf 100644 --- a/src/components/RegistrationForm/RegistrationForm.tsx +++ b/src/components/RegistrationForm/RegistrationForm.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { type ChangeEventHandler } from 'react'; import { useLocation } from 'react-router'; import { useTranslation } from 'react-i18next'; import DOMPurify from 'dompurify'; @@ -68,6 +68,15 @@ const RegistrationForm: React.FC = ({ return label; }; + const changeHandler: ChangeEventHandler = ({ currentTarget }) => { + if (!currentTarget) return; + + const { name, type } = currentTarget; + const value = type === 'checkbox' ? `${(currentTarget as HTMLInputElement).checked}` : currentTarget.value; + + onConsentChange(name, value); + }; + if (loading) { return (
@@ -127,7 +136,7 @@ const RegistrationForm: React.FC = ({ required={consent.required} error={consentErrors?.includes(consent.name)} helperText={consentErrors?.includes(consent.name) ? t('registration.consent_required') : undefined} - onChange={onConsentChange} + onChange={changeHandler} /> ))}
diff --git a/src/utils/collection.ts b/src/utils/collection.ts index d6fdd2ef0..8bc50bd9a 100644 --- a/src/utils/collection.ts +++ b/src/utils/collection.ts @@ -69,6 +69,24 @@ const formatConsentValues = (publisherConsents: Consent[] | null = [], customerC if (!publisherConsents || !customerConsents) { return {}; } + + const values: Record = {}; + + publisherConsents?.forEach((publisherConsent) => { + const consent = customerConsents?.find((customerConsent) => customerConsent.name === publisherConsent.name); + + if (consent) { + values[publisherConsent.name] = consent.value ?? ''; + } + }); + + return values; +}; + +const formatConsents = (publisherConsents: Consent[] | null = [], customerConsents: CustomerConsent[] | null = []) => { + if (!publisherConsents || !customerConsents) { + return {}; + } const values: Record = {}; publisherConsents?.forEach((publisherConsent) => { if (customerConsents?.find((customerConsent) => customerConsent.name === publisherConsent.name && customerConsent.state === 'accepted')) { @@ -102,7 +120,8 @@ const formatConsentsFromValues = (publisherConsents: Consent[] | null, values?: consents.push({ name: consent.name, version: consent.version, - state: values.consents[consent.name] ? 'accepted' : 'declined', + state: values[consent.name] ? 'accepted' : 'declined', + value: `${values[consent.name] ?? ''}`, }); }); @@ -124,6 +143,7 @@ const checkConsentsFromValues = (publisherConsents: Consent[], consents: Record< name: consent.name, version: consent.version, state: consents[consent.name] ? 'accepted' : 'declined', + value: `${consents[consent.name] ?? ''}`, }); }); @@ -158,6 +178,7 @@ export { findPlaylistImageForWidth, generatePlaylistPlaceholder, formatConsentValues, + formatConsents, formatConsentsFromValues, extractConsentValues, checkConsentsFromValues,