diff --git a/apps/scandic-web/components/TempDesignSystem/Form/Country/CountryCombobox.tsx b/apps/scandic-web/components/TempDesignSystem/Form/Country/CountryCombobox.tsx new file mode 100644 index 000000000..962468be9 --- /dev/null +++ b/apps/scandic-web/components/TempDesignSystem/Form/Country/CountryCombobox.tsx @@ -0,0 +1,168 @@ +"use client" + +import { type SyntheticEvent, useMemo, useState } from "react" +import { + Button, + ComboBox, + Input, + Label, + ListBox, + ListBoxItem, + Popover, + useFilter, +} from "react-aria-components" +import { useController } from "react-hook-form" +import { useIntl } from "react-intl" + +import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" +import { Typography } from "@scandic-hotels/design-system/Typography" + +import { countries } from "@/constants/countries" + +import useLang from "@/hooks/useLang" + +import ErrorMessage from "../ErrorMessage" + +import styles from "./country.module.css" + +import type { CountryProps } from "./country" + +const prioCountryCode = ["DE", "DK", "FI", "NO", "SE"] + +export default function CountrySelect({ + // hack used since chrome does not respect autocomplete="off" + autoComplete = "nope", + className = "", + label, + name = "country", + readOnly = false, + registerOptions = {}, +}: CountryProps) { + const lang = useLang() + const intl = useIntl() + + const { startsWith } = useFilter({ sensitivity: "base" }) + const [filterValue, setFilterValue] = useState("") + const { field, formState, fieldState } = useController({ + name, + rules: registerOptions, + }) + + const items = useMemo(() => { + function mapCountry(country: (typeof countries)[number]) { + return { + value: country.code, + label: + intl.formatDisplayName(country.code, { type: "region" }) || + country.name, + } + } + + const collator = new Intl.Collator(lang) + const prioCountries = countries + .filter((c) => prioCountryCode.includes(c.code)) + .map(mapCountry) + .filter((item) => startsWith(item.label, filterValue)) + .sort((a, b) => collator.compare(a.label, b.label)) + + const restCountries = countries + .filter((c) => !prioCountryCode.includes(c.code)) + .map(mapCountry) + .filter((item) => startsWith(item.label, filterValue)) + .sort((a, b) => collator.compare(a.label, b.label)) + + return [...prioCountries, ...restCountries] + }, [filterValue, intl, lang, startsWith]) + + function handleOnInput(evt: SyntheticEvent) { + setFilterValue(evt.currentTarget.value) + const isAutoCompleteEvent = !("inputType" in evt.nativeEvent) + if (isAutoCompleteEvent) { + const { value } = evt.currentTarget + const cc = countries.find((c) => c.name === value || c.code === value) + if (cc) { + field.onChange(cc.code) + } + } + } + + return ( +
+ field.onChange(c ?? "")} + selectedKey={field.value} + menuTrigger="focus" + > + + + + {items.map((item) => ( + + {({ isSelected }) => ( + + {item.label} + + )} + + ))} + + + + +
+ ) +} diff --git a/apps/scandic-web/components/TempDesignSystem/Form/Country/index.tsx b/apps/scandic-web/components/TempDesignSystem/Form/Country/index.tsx index 962468be9..ab376647e 100644 --- a/apps/scandic-web/components/TempDesignSystem/Form/Country/index.tsx +++ b/apps/scandic-web/components/TempDesignSystem/Form/Country/index.tsx @@ -1,21 +1,10 @@ "use client" -import { type SyntheticEvent, useMemo, useState } from "react" -import { - Button, - ComboBox, - Input, - Label, - ListBox, - ListBoxItem, - Popover, - useFilter, -} from "react-aria-components" +import { useMemo } from "react" import { useController } from "react-hook-form" import { useIntl } from "react-intl" -import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" -import { Typography } from "@scandic-hotels/design-system/Typography" +import { Select } from "@scandic-hotels/design-system/Select" import { countries } from "@/constants/countries" @@ -23,15 +12,11 @@ import useLang from "@/hooks/useLang" import ErrorMessage from "../ErrorMessage" -import styles from "./country.module.css" - import type { CountryProps } from "./country" const prioCountryCode = ["DE", "DK", "FI", "NO", "SE"] export default function CountrySelect({ - // hack used since chrome does not respect autocomplete="off" - autoComplete = "nope", className = "", label, name = "country", @@ -41,8 +26,6 @@ export default function CountrySelect({ const lang = useLang() const intl = useIntl() - const { startsWith } = useFilter({ sensitivity: "base" }) - const [filterValue, setFilterValue] = useState("") const { field, formState, fieldState } = useController({ name, rules: registerOptions, @@ -62,36 +45,21 @@ export default function CountrySelect({ const prioCountries = countries .filter((c) => prioCountryCode.includes(c.code)) .map(mapCountry) - .filter((item) => startsWith(item.label, filterValue)) .sort((a, b) => collator.compare(a.label, b.label)) const restCountries = countries .filter((c) => !prioCountryCode.includes(c.code)) .map(mapCountry) - .filter((item) => startsWith(item.label, filterValue)) .sort((a, b) => collator.compare(a.label, b.label)) return [...prioCountries, ...restCountries] - }, [filterValue, intl, lang, startsWith]) - - function handleOnInput(evt: SyntheticEvent) { - setFilterValue(evt.currentTarget.value) - const isAutoCompleteEvent = !("inputType" in evt.nativeEvent) - if (isAutoCompleteEvent) { - const { value } = evt.currentTarget - const cc = countries.find((c) => c.name === value || c.code === value) - if (cc) { - field.onChange(cc.code) - } - } - } + }, [intl, lang]) return (
- field.onChange(c ?? "")} selectedKey={field.value} - menuTrigger="focus" - > - - - - {items.map((item) => ( - - {({ isSelected }) => ( - - {item.label} - - )} - - ))} - - - + data-testid={name} + />
) diff --git a/apps/scandic-web/components/TempDesignSystem/Form/Date/index.tsx b/apps/scandic-web/components/TempDesignSystem/Form/Date/index.tsx index 2f8d27b2c..26758a70e 100644 --- a/apps/scandic-web/components/TempDesignSystem/Form/Date/index.tsx +++ b/apps/scandic-web/components/TempDesignSystem/Form/Date/index.tsx @@ -126,7 +126,6 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) { name={DateName.day} onSelectionChange={(key) => setValue(DateName.day, Number(key))} isRequired - enableFiltering isInvalid={fieldState.invalid} onBlur={field.onBlur} defaultSelectedKey={dateValue?.day} @@ -142,7 +141,6 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) { name={DateName.month} onSelectionChange={(key) => setValue(DateName.month, Number(key))} isRequired - enableFiltering isInvalid={fieldState.invalid} onBlur={field.onBlur} defaultSelectedKey={dateValue?.month} @@ -158,7 +156,6 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) { name={DateName.year} onSelectionChange={(key) => setValue(DateName.year, Number(key))} isRequired - enableFiltering isInvalid={fieldState.invalid} onBlur={field.onBlur} defaultSelectedKey={dateValue?.year}