diff --git a/package-lock.json b/package-lock.json index 940d993db..cce273405 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@emoji-mart/react": "^1.1.1", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@mui/base": "^5.0.0-beta.62", "@mui/icons-material": "^5.14.16", "@mui/material": "^5.14.16", "@mui/x-date-pickers": "^5.0.20", @@ -1778,9 +1779,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.7.tgz", - "integrity": "sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -2757,6 +2758,40 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", + "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "dependencies": { + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz", + "integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", + "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", + "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -3013,6 +3048,66 @@ "react": ">=16" } }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.62", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.62.tgz", + "integrity": "sha512-TzJLCNlrMkSU4bTCdTT+TVUiGx4sjZLhH673UV6YN+rNNP8wJpkWfRSvjDB5HcbH2T0lUamnz643ZnV+8IiMjw==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@floating-ui/react-dom": "^2.1.1", + "@mui/types": "^7.2.19", + "@mui/utils": "^6.1.8", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/base/node_modules/@mui/utils": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.8.tgz", + "integrity": "sha512-O2DWb1kz8hiANVcR7Z4gOB3SvPPsSQGUmStpyBDzde6dJIfBzgV9PbEQOBZd3EBsd1pB+Uv1z5LAJAbymmawrA==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mui/types": "^7.2.19", + "@types/prop-types": "^15.7.13", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^18.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@mui/core-downloads-tracker": { "version": "5.16.7", "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.16.7.tgz", @@ -3188,9 +3283,9 @@ } }, "node_modules/@mui/types": { - "version": "7.2.17", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.17.tgz", - "integrity": "sha512-oyumoJgB6jDV8JFzRqjBo2daUuHpzDjoO/e3IrRhhHo/FxJlaVhET6mcNrKHUq2E+R+q3ql0qAtvQ4rfWHhAeQ==", + "version": "7.2.19", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.19.tgz", + "integrity": "sha512-6XpZEM/Q3epK9RN8ENoXuygnqUQxE+siN/6rGRi2iwJPgBUR25mphYQ9ZI87plGh58YoZ5pp40bFvKYOCDJ3tA==", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, diff --git a/package.json b/package.json index a7257a951..08c0455ac 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@emoji-mart/react": "^1.1.1", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@mui/base": "^5.0.0-beta.62", "@mui/icons-material": "^5.14.16", "@mui/material": "^5.14.16", "@mui/x-date-pickers": "^5.0.20", diff --git a/src/components/app-auto-complete/AppAutoComplete.tsx b/src/components/app-auto-complete/AppAutoComplete.tsx index 4f0981810..e21e231a4 100644 --- a/src/components/app-auto-complete/AppAutoComplete.tsx +++ b/src/components/app-auto-complete/AppAutoComplete.tsx @@ -1,13 +1,12 @@ -import { Fragment, SyntheticEvent } from 'react' - +import React, { Fragment, SyntheticEvent, useState } from 'react' import TextField, { TextFieldProps } from '@mui/material/TextField' import Autocomplete, { createFilterOptions, AutocompleteProps } from '@mui/material/Autocomplete' - +import { FilterOptionsState } from '@mui/base' +import { ChipTypeMap } from '@mui/material/Chip' import Loader from '~/components/loader/Loader' -import { ChipTypeMap, FilterOptionsState } from '@mui/material' const defaultFilterOptions = ( options: T[], @@ -18,10 +17,11 @@ const defaultFilterOptions = ( } type CustomProps = { - textFieldProps?: TextFieldProps + textFieldProps?: TextFieldProps & { helperText?: string; error?: boolean } hideClearIcon?: boolean onChange?: (_: SyntheticEvent, value: string | null) => void | Promise onFocus?: (_: SyntheticEvent, value: string | null) => void | Promise + required?: boolean } & Omit const AppAutoComplete = < @@ -36,10 +36,21 @@ const AppAutoComplete = < options = [], hideClearIcon = false, textFieldProps = {}, + required = false, ...props }: CustomProps< AutocompleteProps >) => { + const [error, setError] = useState(false) + + const handleBlur = () => { + if (required && !props.value) { + setError(true) + } else { + setError(false) + } + } + return ( option === value} options={options} {...props} + onBlur={handleBlur} renderInput={(params) => ( ) }} + error={error || textFieldProps.error} + helperText={ + (error && 'This field is required') || textFieldProps.helperText + } /> )} /> diff --git a/src/components/location-selection-inputs/LocationSelectionInputs.tsx b/src/components/location-selection-inputs/LocationSelectionInputs.tsx index e986e1b29..a67294a36 100644 --- a/src/components/location-selection-inputs/LocationSelectionInputs.tsx +++ b/src/components/location-selection-inputs/LocationSelectionInputs.tsx @@ -111,9 +111,11 @@ const LocationSelectionInputs = < onChange={onChangeCity} onFocus={onFocusCountry} options={cities} + required sx={{ mb: '25px' }} textFieldProps={{ - label: t('common.labels.city') + label: t('common.labels.city'), + required: !!data.country }} value={data.city} />