diff --git a/apps/scandic-web/components/Forms/Edit/Profile/FormContent/index.tsx b/apps/scandic-web/components/Forms/Edit/Profile/FormContent/index.tsx index 7f75e3efc..4cbd6f7b6 100644 --- a/apps/scandic-web/components/Forms/Edit/Profile/FormContent/index.tsx +++ b/apps/scandic-web/components/Forms/Edit/Profile/FormContent/index.tsx @@ -4,24 +4,27 @@ import { useIntl } from "react-intl" import { Divider } from "@scandic-hotels/design-system/Divider" import CountrySelect from "@scandic-hotels/design-system/Form/Country" +import Phone from "@scandic-hotels/design-system/Form/Phone" import { Select } from "@scandic-hotels/design-system/Select" import { Typography } from "@scandic-hotels/design-system/Typography" -import { getLocalizedLanguageOptions } from "@/constants/languages" +import { + getDefaultCountryFromLang, + getLocalizedLanguageOptions, +} from "@/constants/languages" import DateSelect from "@/components/TempDesignSystem/Form/Date" import Input from "@/components/TempDesignSystem/Form/Input" import PasswordInput from "@/components/TempDesignSystem/Form/PasswordInput" -import Phone from "@/components/TempDesignSystem/Form/Phone" import useLang from "@/hooks/useLang" import { getFormattedCountryList } from "@/utils/countries" import { getErrorMessage } from "@/utils/getErrorMessage" -import { editProfileErrors } from "../schema" - import styles from "./formContent.module.css" -export default function FormContent() { +import type { FieldErrors } from "react-hook-form" + +export default function FormContent({ errors }: { errors: FieldErrors }) { const intl = useIntl() const lang = useLang() const languageOptions = getLocalizedLanguageOptions(lang) @@ -66,7 +69,8 @@ export default function FormContent() { countries={getFormattedCountryList(intl)} errorMessage={getErrorMessage( intl, - editProfileErrors.COUNTRY_REQUIRED + // @ts-expect-error countryCode doesn't exist schema not available + errors?.address?.countryCode?.message?.toString() )} label={intl.formatMessage({ defaultMessage: "Country", @@ -86,6 +90,15 @@ export default function FormContent() { data-hj-suppress /> - + diff --git a/apps/scandic-web/components/Forms/Signup/index.tsx b/apps/scandic-web/components/Forms/Signup/index.tsx index ef50be9fa..2719ecdc0 100644 --- a/apps/scandic-web/components/Forms/Signup/index.tsx +++ b/apps/scandic-web/components/Forms/Signup/index.tsx @@ -10,6 +10,7 @@ import { logger } from "@scandic-hotels/common/logger" import { Button } from "@scandic-hotels/design-system/Button" import Checkbox from "@scandic-hotels/design-system/Form/Checkbox" import CountrySelect from "@scandic-hotels/design-system/Form/Country" +import Phone from "@scandic-hotels/design-system/Form/Phone" import { Typography } from "@scandic-hotels/design-system/Typography" import { trpc } from "@scandic-hotels/trpc/client" import { @@ -27,7 +28,6 @@ import { import DateSelect from "@/components/TempDesignSystem/Form/Date" import Input from "@/components/TempDesignSystem/Form/Input" import PasswordInput from "@/components/TempDesignSystem/Form/PasswordInput" -import Phone from "@/components/TempDesignSystem/Form/Phone" import Link from "@/components/TempDesignSystem/Link" import { toast } from "@/components/TempDesignSystem/Toasts" import { useFormTracking } from "@/components/TrackingSDK/hooks" @@ -98,7 +98,11 @@ export default function SignupForm({ title }: SignUpFormProps) { shouldFocusError: true, }) - const { control, subscribe } = methods + const { + control, + subscribe, + formState: { errors }, + } = methods const { trackFormSubmit } = useFormTracking("signup", subscribe, control) @@ -174,7 +178,7 @@ export default function SignupForm({ title }: SignUpFormProps) { countries={getFormattedCountryList(intl)} errorMessage={getErrorMessage( intl, - signupErrors.COUNTRY_REQUIRED + errors.address?.countryCode?.message )} label={intl.formatMessage({ defaultMessage: "Country", @@ -192,6 +196,15 @@ export default function SignupForm({ title }: SignUpFormProps) { type="email" /> { setValue("firstName", guest.firstName ?? "") @@ -65,7 +70,7 @@ export default function ModifyContact({ countries={getFormattedCountryList(intl)} errorMessage={getErrorMessage( intl, - signupErrors.COUNTRY_REQUIRED + errors.countryCode?.message?.toString() )} label={intl.formatMessage({ defaultMessage: "Country", @@ -86,6 +91,15 @@ export default function ModifyContact({
= { [Lang.da]: "Dansk", @@ -82,8 +82,8 @@ export function getLocalizedLanguageOptions(currentLang: Lang) { }) } -export function getDefaultCountryFromLang(lang: Lang): LowerCaseCountryCode { - const countryMap: Record = { +export function getDefaultCountryFromLang(lang: Lang): Lowercase { + const countryMap: Record> = { sv: "se", da: "dk", fi: "fi", diff --git a/apps/scandic-web/components/TempDesignSystem/Form/Phone/index.tsx b/packages/design-system/lib/components/Form/Phone/index.tsx similarity index 64% rename from apps/scandic-web/components/TempDesignSystem/Form/Phone/index.tsx rename to packages/design-system/lib/components/Form/Phone/index.tsx index 773d8de23..b7172a28e 100644 --- a/apps/scandic-web/components/TempDesignSystem/Form/Phone/index.tsx +++ b/packages/design-system/lib/components/Form/Phone/index.tsx @@ -1,9 +1,9 @@ -"use client" -import "react-international-phone/style.css" +'use client' +import 'react-international-phone/style.css' -import { useEffect, useMemo } from "react" -import { TextField } from "react-aria-components" -import { useFormContext, useWatch } from "react-hook-form" +import { useEffect, useMemo } from 'react' +import { TextField } from 'react-aria-components' +import { useFormContext, useWatch } from 'react-hook-form' import { buildCountryData, CountrySelector, @@ -12,53 +12,48 @@ import { parseCountry, type ParsedCountry, usePhoneInput, -} from "react-international-phone" -import { useIntl } from "react-intl" +} from 'react-international-phone' -import Body from "@scandic-hotels/design-system/Body" -import { ErrorMessage } from "@scandic-hotels/design-system/Form/ErrorMessage" -import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import { Input } from "@scandic-hotels/design-system/Input" -import { Label } from "@scandic-hotels/design-system/Label" +import Body from '../../Body' +import { ErrorMessage } from '../ErrorMessage' +import { MaterialIcon } from '../../Icons/MaterialIcon' +import { Input } from '../../Input' +import { Label } from '../../Label' -import { getDefaultCountryFromLang } from "@/constants/languages" +import styles from './phone.module.css' -import useLang from "@/hooks/useLang" -import { getErrorMessage } from "@/utils/getErrorMessage" - -import styles from "./phone.module.css" - -import type { PhoneProps } from "@/types/components/form/phone" +import type { PhoneProps } from './phone' export default function Phone({ - ariaLabel = "Phone number input", - className = "", - countrySelectorName = "phoneNumberCC", + ariaLabel = 'Phone number input', + className = '', + countryLabel = 'Country code', + countrySelectorName = 'phoneNumberCC', + countriesWithTranslatedName, + defaultCountryCode, disabled = false, + errorMessage, label, - name = "phoneNumber", + name = 'phoneNumber', placeholder, readOnly = false, registerOptions = { required: true, }, }: PhoneProps) { - const intl = useIntl() - const lang = useLang() - const countries = useMemo(() => { return defaultCountries.map((dc) => { - const country = parseCountry(dc) - const translatedCountryName = intl.formatDisplayName( - country.iso2.toUpperCase(), - { type: "region" } + const parsedCountry = parseCountry(dc) + const country = countriesWithTranslatedName?.find( + (country) => country.code === parsedCountry.iso2.toUpperCase() ) + const translatedCountryName = country?.displayName ?? country?.name if (translatedCountryName) { - country.name = translatedCountryName + parsedCountry.name = translatedCountryName } - return buildCountryData(country) + return buildCountryData(parsedCountry) }) - }, [intl]) + }, [countriesWithTranslatedName]) const { formState, getFieldState, register, setValue } = useFormContext() const fieldState = getFieldState(name) @@ -69,9 +64,7 @@ export default function Phone({ const { country, setCountry } = usePhoneInput({ countries, - defaultCountry: phoneNumberCC - ? phoneNumberCC - : getDefaultCountryFromLang(lang), + defaultCountry: phoneNumberCC ? phoneNumberCC : defaultCountryCode, }) function handleSelectCountry(value: ParsedCountry) { @@ -98,7 +91,7 @@ export default function Phone({ dropdownArrowClassName={styles.arrow} flagClassName={styles.flag} onSelect={handleSelectCountry} - preferredCountries={["de", "dk", "fi", "no", "se", "gb"]} + preferredCountries={['de', 'dk', 'fi', 'no', 'se', 'gb']} selectedCountry={country.iso2} renderButtonWrapper={(props) => (
diff --git a/apps/scandic-web/components/TempDesignSystem/Form/Phone/phone.module.css b/packages/design-system/lib/components/Form/Phone/phone.module.css similarity index 98% rename from apps/scandic-web/components/TempDesignSystem/Form/Phone/phone.module.css rename to packages/design-system/lib/components/Form/Phone/phone.module.css index 8f1451105..f988d0d55 100644 --- a/apps/scandic-web/components/TempDesignSystem/Form/Phone/phone.module.css +++ b/packages/design-system/lib/components/Form/Phone/phone.module.css @@ -79,7 +79,7 @@ } } -.select[aria-expanded="true"] .chevron { +.select[aria-expanded='true'] .chevron { transform: rotate(180deg); } diff --git a/apps/scandic-web/types/components/form/phone.ts b/packages/design-system/lib/components/Form/Phone/phone.ts similarity index 50% rename from apps/scandic-web/types/components/form/phone.ts rename to packages/design-system/lib/components/Form/Phone/phone.ts index 264cbfd49..cdfa79eee 100644 --- a/apps/scandic-web/types/components/form/phone.ts +++ b/packages/design-system/lib/components/Form/Phone/phone.ts @@ -1,14 +1,19 @@ -import type { CountryCode } from "libphonenumber-js" -import type { RegisterOptions } from "react-hook-form" - -export type LowerCaseCountryCode = Lowercase +import type { RegisterOptions } from 'react-hook-form' export interface PhoneProps { ariaLabel?: string className?: string + countryLabel?: string countrySelectorName?: string + countriesWithTranslatedName: { + code: string + displayName?: string + name: string + }[] disabled?: boolean + errorMessage?: string label: string + defaultCountryCode: string name?: string placeholder?: string readOnly?: boolean diff --git a/packages/design-system/package.json b/packages/design-system/package.json index eac136fb4..e01acd66d 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -17,6 +17,7 @@ "./Form/Checkbox": "./dist/components/Form/Checkbox/index.js", "./Form/Country": "./dist/components/Form/Country/index.js", "./Form/ErrorMessage": "./dist/components/Form/ErrorMessage/index.js", + "./Form/Phone": "./dist/components/Form/Phone/index.js", "./Form/RadioCard": "./dist/components/Form/RadioCard/index.js", "./Input": "./dist/components/Input/index.js", "./Label": "./dist/components/Label/index.js", @@ -152,7 +153,8 @@ "react": "^19.1.0", "react-aria-components": "^1.8.0", "react-dom": "^19.1.0", - "react-hook-form": "^7.56.2" + "react-hook-form": "^7.56.2", + "react-international-phone": "^4.5.0" }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", diff --git a/yarn.lock b/yarn.lock index 45cab49f9..6c7a04b6b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6734,6 +6734,7 @@ __metadata: react-aria-components: ^1.8.0 react-dom: ^19.1.0 react-hook-form: ^7.56.2 + react-international-phone: ^4.5.0 languageName: unknown linkType: soft