UNPKG

@hhgtech/hhg-components

Version:
1,067 lines (1,009 loc) • 78.4 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var core = require('@mantine/core'); var utils$1 = require('./utils-a2e471bf.js'); var useOutsideClick = require('./useOutsideClick-6c8079f3.js'); var index$1 = require('./index-c2c283f8.js'); var debounce = require('lodash/debounce'); var constants = require('./constants-f334c51a.js'); var styled = require('@emotion/styled'); var miscTheme = require('./miscTheme.js'); var utils = require('./utils-7ba0038a.js'); var index = require('./index-9e79d4c7.js'); var core$1 = require('@hhgtech/icons/core'); var index$2 = require('./index-25f2e7a5.js'); var ChevronDown = require('./ChevronDown-bc6b5063.js'); var paths = require('./paths-ecb0f054.js'); require('./index-1ee4ebb8.js'); require('date-fns/locale'); require('./index-ad7155cf.js'); require('./Locale-59ccf941.js'); require('./constantsSite.js'); require('./constantsDomainLocales.js'); require('./constantsRiskScreener.js'); require('./constantsIsProduction.js'); require('./miscCookieHelper.js'); require('react-loading-skeleton'); require('string-format'); require('./translationsContext-d63b6d32.js'); require('./tslib.es6-92cccef3.js'); require('./other-eb0ff2f6.js'); function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefault(React); var debounce__default = /*#__PURE__*/_interopDefault(debounce); var styled__default = /*#__PURE__*/_interopDefault(styled); const StyledSearchBarWrapper = styled__default["default"].div ``; const StyleWrapperContainer = styled__default["default"].div ` background-color: ${miscTheme.theme.colors.neutral50}; padding-bottom: 1px; ${utils.MediaQueries.mbDown} { padding: 0 16px 10px; } `; const StyleSearchInputContainer = styled__default["default"](index.Container) ` padding: 0 16px; ${utils.MediaQueries.mbDown} { padding: 0; } `; const StyleSearchContent = styled__default["default"].div ` padding: 24px 56px; border-radius: 16px; background-color: ${miscTheme.theme.colors.white}; box-shadow: 0px 0px 1px 0px rgba(0, 0, 0, 0.04), 0px 0px 2px 0px rgba(0, 0, 0, 0.06), 0px 4px 8px 0px rgba(0, 0, 0, 0.04); ${utils.MediaQueries.mbDown} { padding: 16px 16px; border-radius: 0px 0px 12px 12px; } .flex-search-input { flex-direction: row; ${utils.MediaQueries.mbDown} { flex-direction: column; } } `; const SEARCH_KEYWORD_MIN_LENGTH = { 'en-PH': 3, 'tl-PH': 2, 'id-ID': 3, 'vi-VN': 2, 'zh-TW': 0, 'ms-MY': 2, }; const initialState = { isMobile: false, isDebug: false, navigateTo: null, geoLocationPermission: 'unset', geoLocationCoordinates: null, focused: 'none', focusedSpecialty: 'none', searchLocationKeywords: '', searchSpecialtyKeywords: '', searchKeywords: '', selectedLocation: null, selectedSpecialty: null, defaultCity: null, initialCities: [], cities: [], searchResults: {}, initialSearchResults: {}, isLoadingCities: false, isLoadingSearchResults: false, isMobileModalOpened: false, initialSelectedCity: null, autoCompleteDisabled: false, inputSearchPlaceholder: '', locale: 'vi-VN', allSpecialties: [], popularKeys: [], }; var ActionTypes; (function (ActionTypes) { ActionTypes["NavigateTo"] = "navigate to url"; ActionTypes["ClickOutsideInputLocation"] = "click outside input location"; ActionTypes["ClickOutsideInputSearch"] = "click outside input search"; ActionTypes["ClickOutsideInputSearchSpecialty"] = "click outside input search specialty"; ActionTypes["ClickOutsideInputSpecialty"] = "click outside input specialty"; ActionTypes["SelectCurrentLocation"] = "select current location"; ActionTypes["FocusInputLocation"] = "focus input location"; ActionTypes["FocusInputSearch"] = "focus input search"; ActionTypes["FocusInputSearchSpecialty"] = "focus input search specialty"; ActionTypes["ChangeInputLocation"] = "change input location"; ActionTypes["ChangeInputSearch"] = "change input search"; ActionTypes["ClearInputLocation"] = "clear input location"; ActionTypes["ClearInputSearch"] = "clear input search"; ActionTypes["SelectLocation"] = "select location"; ActionTypes["SelectSpecialty"] = "select specialty"; ActionTypes["FetchCitiesStart"] = "fetch cities start"; ActionTypes["FetchCitiesFinish"] = "fetch cities finish"; ActionTypes["FetchSearchResultsStart"] = "fetch search results start"; ActionTypes["FetchSearchResultsComplete"] = "fetch search results complete"; ActionTypes["FetchSearchResultsFinish"] = "fetch search results finish"; ActionTypes["FetchCitiesByGeoIpComplete"] = "fetch cities by geo IP finish"; ActionTypes["FetchCitiesByKeywordComplete"] = "fetch cities by keyword finish"; ActionTypes["DisplayInitialCities"] = "display initial cities"; ActionTypes["DisplayInitialSearchResults"] = "display initial search results"; ActionTypes["UpdateInitialSearchResults"] = "update initial search results"; ActionTypes["GrantGeoLocationPermission"] = "grant geolocation permission"; ActionTypes["DenyGeoLocationPermission"] = "deny geolocation permission"; ActionTypes["OpenMobileModal"] = "open mobile modal"; ActionTypes["CloseMobileModal"] = "close mobile modal"; ActionTypes["UpdateInitialSearchValue"] = "update initial search value"; ActionTypes["SelectSearchResult"] = "select search result"; ActionTypes["SetInputSearchPlaceholder"] = "set input search placeholder"; ActionTypes["FocusInputSpecialty"] = "focus input specialty"; ActionTypes["FetchAllSpecialties"] = "fetch all specialty"; ActionTypes["FetchPopularKeys"] = "fetch popular key by type"; })(ActionTypes || (ActionTypes = {})); function resetSearchLocationKeywords(state) { const { selectedLocation, searchLocationKeywords } = state; if (selectedLocation && searchLocationKeywords !== selectedLocation.name) { return Object.assign(Object.assign({}, state), { searchLocationKeywords: selectedLocation.name }); } return state; } function reducer(state, action) { var _a, _b; if (state.isDebug) { console.log('bookingSearchBar', { action, state }); } switch (action.type) { case ActionTypes.NavigateTo: return Object.assign(Object.assign({}, state), { navigateTo: action.payload, focused: 'none', isMobileModalOpened: false }); case ActionTypes.ClickOutsideInputLocation: { if (state.focused !== 'location') { return state; } return resetSearchLocationKeywords(Object.assign(Object.assign({}, state), { focused: 'none' })); } case ActionTypes.ClickOutsideInputSpecialty: { if (state.focused !== 'specialty') { return state; } return resetSearchLocationKeywords(Object.assign(Object.assign({}, state), { focused: 'none' })); } case ActionTypes.ClickOutsideInputSearch: { if (state.focused !== 'search') { return state; } return Object.assign(Object.assign({}, state), { focused: 'none' }); } case ActionTypes.ClickOutsideInputSearchSpecialty: { if (state.focusedSpecialty !== 'search') { return state; } return Object.assign(Object.assign({}, state), { focusedSpecialty: 'none' }); } case ActionTypes.FocusInputLocation: { const nextState = Object.assign(Object.assign({}, state), { focused: 'location' }); if (((_a = state.selectedLocation) === null || _a === void 0 ? void 0 : _a.id) === constants.ID_OPTION_CURRENT_LOCATION) { nextState.searchLocationKeywords = ''; } return nextState; } case ActionTypes.FocusInputSpecialty: { const nextState = Object.assign(Object.assign({}, state), { focused: 'specialty' }); if (((_b = state.selectedLocation) === null || _b === void 0 ? void 0 : _b.id) === constants.ID_OPTION_CURRENT_LOCATION) { nextState.searchLocationKeywords = ''; } return nextState; } case ActionTypes.FocusInputSearch: const nextState = Object.assign(Object.assign({}, state), { focused: 'search' }); if (state.isMobile) { return resetSearchLocationKeywords(nextState); } return nextState; case ActionTypes.FocusInputSearchSpecialty: { const nextState = Object.assign(Object.assign({}, state), { focusedSpecialty: 'search' }); return nextState; } case ActionTypes.ChangeInputLocation: return Object.assign(Object.assign({}, state), { searchLocationKeywords: action.payload }); case ActionTypes.ChangeInputSearch: { const keyword = action.payload; return Object.assign(Object.assign({}, state), { searchKeywords: keyword, isLoadingSearchResults: keyword.trim().length > SEARCH_KEYWORD_MIN_LENGTH[state.locale] }); } case ActionTypes.SelectCurrentLocation: return Object.assign(Object.assign({}, state), { focused: 'none', selectedLocation: action.payload, searchLocationKeywords: action.payload.name }); case ActionTypes.ClearInputLocation: return Object.assign(Object.assign({}, state), { focused: 'location', cities: state.initialCities, searchLocationKeywords: '' }); case ActionTypes.ClearInputSearch: return Object.assign(Object.assign({}, state), { focused: 'search', searchKeywords: '' }); case ActionTypes.SelectLocation: return Object.assign(Object.assign({}, state), { focused: 'none', selectedLocation: action.payload, searchLocationKeywords: action.payload.name }); case ActionTypes.SelectSpecialty: return Object.assign(Object.assign({}, state), { focused: 'none', selectedSpecialty: action.payload }); case ActionTypes.SelectSearchResult: return Object.assign(Object.assign({}, state), { searchKeywords: action.payload.name, isMobileModalOpened: false, focused: 'none', navigateTo: action.payload.url }); case ActionTypes.FetchCitiesStart: return Object.assign(Object.assign({}, state), { isLoadingCities: true }); case ActionTypes.FetchCitiesFinish: return Object.assign(Object.assign({}, state), { isLoadingCities: false }); case ActionTypes.FetchSearchResultsStart: return Object.assign(Object.assign({}, state), { isLoadingSearchResults: true }); case ActionTypes.FetchSearchResultsFinish: return Object.assign(Object.assign({}, state), { isLoadingSearchResults: false }); case ActionTypes.FetchSearchResultsComplete: { const nextState = Object.assign(Object.assign({}, state), { searchResults: Object.assign(Object.assign({}, state.searchResults), { [action.payload.key]: action.payload.searches }) }); return nextState; } case ActionTypes.FetchCitiesByGeoIpComplete: { let { cities } = action.payload; const { default: defaultCity } = action.payload; cities = cities.filter((c) => c.id !== defaultCity.id); if (defaultCity) { cities.unshift(defaultCity); } if (state.initialSelectedCity && !cities.find((c) => c.id === state.initialSelectedCity.id)) { cities.unshift(state.initialSelectedCity); } const nextState = Object.assign(Object.assign({}, state), { defaultCity, initialCities: cities, cities }); if (state.geoLocationPermission === 'denied' && !state.initialSelectedCity) { nextState.selectedLocation = defaultCity; nextState.searchLocationKeywords = defaultCity.name; } return nextState; } case ActionTypes.FetchCitiesByKeywordComplete: return Object.assign(Object.assign({}, state), { cities: action.payload }); case ActionTypes.DisplayInitialCities: return Object.assign(Object.assign({}, state), { cities: state.initialCities }); case ActionTypes.DisplayInitialSearchResults: return Object.assign(Object.assign({}, state), { searchResults: state.initialSearchResults, isLoadingSearchResults: false }); case ActionTypes.UpdateInitialSearchResults: return Object.assign(Object.assign({}, state), { initialSearchResults: Object.assign(Object.assign({}, state.initialSearchResults), { [action.payload.key]: action.payload.searches }) }); case ActionTypes.GrantGeoLocationPermission: return Object.assign(Object.assign({}, state), { geoLocationPermission: 'granted', geoLocationCoordinates: action.payload }); case ActionTypes.DenyGeoLocationPermission: return Object.assign(Object.assign({}, state), { geoLocationPermission: 'denied', geoLocationCoordinates: null }); case ActionTypes.OpenMobileModal: return Object.assign(Object.assign({}, state), { isMobileModalOpened: true }); case ActionTypes.CloseMobileModal: return Object.assign(Object.assign({}, state), { isMobileModalOpened: false }); case ActionTypes.UpdateInitialSearchValue: return Object.assign(Object.assign({}, state), { searchKeywords: action.payload }); case ActionTypes.SetInputSearchPlaceholder: return Object.assign(Object.assign({}, state), { inputSearchPlaceholder: action.payload }); case ActionTypes.FetchAllSpecialties: return Object.assign(Object.assign({}, state), { allSpecialties: action.payload }); case ActionTypes.FetchPopularKeys: return Object.assign(Object.assign({}, state), { popularKeys: action.payload }); default: return state; } } const StyleSearchInputsWrapper = styled__default["default"].div ` flex: 1; position: relative; ${utils.MediaQueries.mbDown} { width: 100%; display: flex; flex-direction: column; gap: 12px; } `; const StyleResultWrapper$2 = styled__default["default"].div ` position: absolute; top: calc(100% + 2px); width: 100%; border-radius: 4px; background: ${miscTheme.theme.colors.white}; box-shadow: 0px 8px 40px 0px rgba(0, 0, 0, 0.1); z-index: 10; ${utils.MediaQueries.mbDown} { width: calc(100% + 64px); left: -32px; } `; const StyledSearchResultWrapper = styled__default["default"].div ``; const StyleResultHeader = styled__default["default"].div ` display: flex; justify-content: space-between; align-item: center; padding: 9px 14px 9px 22px; background: #f7f9fc; .title { color: ${miscTheme.theme.colors.gray800}; font-size: 14px; font-weight: 600; line-height: 22px; } .btn-see-all { color: ${miscTheme.theme.colors.blue600}; font-size: 14px; line-height: 22px; cursor: pointer; } `; const StyleResultBody = styled__default["default"].div ` padding: 10px 16px; max-height: 400px; overflow: auto; `; const StyleResultItem = styled__default["default"].div ` display: flex; gap: 12px; align-items: center; cursor: pointer; &:hover { background-color: ${miscTheme.theme.colors.blue50}; } .image-item { flex: 0 0 48px; width: 48px; height: 48px; border-radius: 50%; img { object-fit: contain; width: 100%; height: 100%; border-radius: 50%; } } .infor { overflow: hidden; padding: 12px 0; flex: 1; border-bottom: 1px solid ${miscTheme.theme.colors.neutral100}; .title { color: ${miscTheme.theme.colors.gray800}; font-size: 16px; font-weight: 600; line-height: 24px; } .description { overflow: hidden; color: ${miscTheme.theme.colors.gray600}; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; line-height: 18px; display: flex; gap: 8px; align-items: center; margin-top: 5px; svg { flex: 0 0 16px; } .sub-description { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; flex: 1; } } } &.last-item { .infor { border-bottom: none; } } `; styled__default["default"].div ` padding: 0 16px 16px; .search-detail-btn { color: ${miscTheme.theme.colors.blue600}; font-size: 14px; line-height: 22px; cursor: pointer; } `; const SearchResult = ({ state, type, results, location, isLoading, typeInformation, clientSlug = '', dispatch, }) => { const { locale, t } = index$1.useTranslations(); const { selectedLocation } = state; const typeSlug = React.useMemo(() => typeInformation[type].slug, [typeInformation, type]); const handleOnClick = (item) => { let url = ''; switch (type) { case 'service': url = `/${selectedLocation.slug}/${typeSlug}/${item.slug}`; break; case 'doctor': case 'hospital': url = `/${typeSlug}/${item.slug}-${item.id}`; break; } if (url) { dispatch({ type: ActionTypes.NavigateTo, payload: url, }); } }; const handleSeeAll = () => { let url = `/${selectedLocation.slug}/${typeSlug}`; const slugClientUrl = constants.MAPPING_CLIENT_WITH_SLUG[locale][clientSlug]; if (slugClientUrl) { url += `/${slugClientUrl}`; } if ((type === 'doctor' || type === 'hospital') && state.selectedSpecialty.id > 0) { url += `?specialtyId=${state.selectedSpecialty.id}`; } if (url) { dispatch({ type: ActionTypes.NavigateTo, payload: url }); } }; return (React__default["default"].createElement(StyledSearchResultWrapper, null, React__default["default"].createElement(StyleResultHeader, null, React__default["default"].createElement("div", { className: "title" }, t('booking.searchResult.description', { search_type: typeInformation[type].name, search_location: location, })), results.length > 0 && (React__default["default"].createElement("div", { className: "btn-see-all", onClick: handleSeeAll }, t('home.seeAll')))), React__default["default"].createElement(StyleResultBody, null, isLoading && Array(3) .fill(undefined) .map((_, i) => (React__default["default"].createElement(StyleResultItem, { key: type + 'loading' + i, className: i === 2 ? 'last-item' : '' }, React__default["default"].createElement("div", { className: "image-item" }, React__default["default"].createElement(core.Skeleton, { height: 48, circle: true, mb: "xl", animate: true })), React__default["default"].createElement("div", { className: "infor" }, React__default["default"].createElement("div", { className: "title" }, React__default["default"].createElement(core.Skeleton, { height: 8, mt: 10, radius: "xl", animate: true })), React__default["default"].createElement("div", { className: "description" }, React__default["default"].createElement("div", { className: "sub-description" }, React__default["default"].createElement(core.Skeleton, { height: 8, mt: 10, radius: "xl", width: "80%", animate: true }))))))), !isLoading && results && results.length > 0 && (React__default["default"].createElement(React__default["default"].Fragment, null, results.map((item, index) => { var _a, _b; const isLastItem = (results.length > 4 && index === 3) || (results.length <= 4 && index === results.length - 1); let subDescription = ''; if (type === 'hospital') { subDescription = (item === null || item === void 0 ? void 0 : item.address) || ''; } if (type === 'doctor') { subDescription = ((_a = item === null || item === void 0 ? void 0 : item.specialties) === null || _a === void 0 ? void 0 : _a.join(', ')) || ''; } if (type === 'service') { subDescription = ((_b = item === null || item === void 0 ? void 0 : item.hospital_branch) === null || _b === void 0 ? void 0 : _b.name) || ''; } if (index >= 4) { return React__default["default"].createElement(React__default["default"].Fragment, null); } return (React__default["default"].createElement(StyleResultItem, { key: item.id, className: isLastItem ? 'last-item' : '', onClick: () => handleOnClick(item) }, React__default["default"].createElement("div", { className: "image-item" }, React__default["default"].createElement("img", { src: item.logo || item.avatar, alt: item.name })), React__default["default"].createElement("div", { className: "infor" }, React__default["default"].createElement("div", { className: "title" }, item.name), React__default["default"].createElement("div", { className: "description" }, typeInformation[type].icon, React__default["default"].createElement("div", { className: "sub-description" }, subDescription))))); }))), !isLoading && (results === null || results === void 0 ? void 0 : results.length) === 0 && (React__default["default"].createElement(index$2.Text, { size: "sm", color: miscTheme.theme.colors.gray400 }, t('booking.searchBar.noResults')))))); }; const StyleSearchSpecialtyWrapper = styled__default["default"].div ` position: relative; ${utils.MediaQueries.mbDown} { width: 100%; display: flex; flex-direction: column; gap: 12px; } `; const StyleResultWrapper$1 = styled__default["default"].div ` position: absolute; top: calc(100% + 2px); width: calc(100% + 100px); border-radius: 4px; background: ${miscTheme.theme.colors.white}; box-shadow: 0px 8px 40px 0px rgba(0, 0, 0, 0.1); z-index: 10; max-height: 300px; overflow: auto; ${utils.MediaQueries.mbDown} { width: calc(100% + 64px); left: -32px; } `; const StyledSpecialtyItem = styled__default["default"].li ` position: relative; cursor: pointer; padding: 12px 18px; display: flex; align-items: center; gap: 14px; overflow: hidden; .image-item { display: flex; align-items: center; width: 40px; height: 40px; img { width: 100%; object-fit: cover; } svg { width: 40px; } } ${({ isSelected }) => isSelected && ` &::after { content: ${utils$1.checkMarkIconUrl}; top: 50%; right: 18px; position: absolute; transform: translateY(-50%); } `} & + li::before { content: ''; position: absolute; left: 18px; right: 18px; top: 0; height: 1px; background-color: ${miscTheme.theme.colors.neutral100}; } &:not([data-is-denied='true']):hover { background-color: ${miscTheme.theme.colors.neutral50}; } &:last-child:hover { border-bottom-right-radius: 6px; border-bottom-left-radius: 6px; } &:first-child:hover { border-top-right-radius: 6px; border-top-left-radius: 6px; } &[data-is-denied='true'] { cursor: not-allowed; } `; const DoctorIcon = () => (React__default["default"].createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none" }, React__default["default"].createElement("path", { d: "M8.983 14.333q-1.666 0-2.833-1.166Q4.983 12 4.983 10.333v-.366a3.48 3.48 0 0 1-2.258-1.2 3.57 3.57 0 0 1-.909-2.434V3.1a.58.58 0 0 1 .175-.425.58.58 0 0 1 .425-.175h1.4v-.167a.486.486 0 0 1 .5-.5q.217 0 .36.142a.5.5 0 0 1 .14.358v1.334a.485.485 0 0 1-.5.5.484.484 0 0 1-.5-.5V3.5h-1v2.833q0 1.1.784 1.884Q4.383 9 5.483 9t1.883-.783.784-1.884V3.5h-1v.167a.485.485 0 0 1-.5.5.484.484 0 0 1-.5-.5V2.333a.486.486 0 0 1 .5-.5q.217 0 .358.142a.5.5 0 0 1 .142.358V2.5h1.4a.58.58 0 0 1 .425.175.58.58 0 0 1 .175.425v3.233q0 1.4-.908 2.434a3.5 3.5 0 0 1-2.259 1.2v.366q0 1.25.875 2.126a2.9 2.9 0 0 0 2.125.874q1.25 0 2.125-.874a2.9 2.9 0 0 0 .875-2.126V9.25a1.74 1.74 0 0 1-.858-.609 1.6 1.6 0 0 1-.342-1.008q0-.716.5-1.216t1.2-.5q.716 0 1.217.5.5.5.5 1.216 0 .567-.342 1.008t-.875.609v1.083q0 1.667-1.167 2.834-1.166 1.166-2.833 1.166m3.5-6q.3 0 .509-.208a.67.67 0 0 0 .208-.492q0-.3-.208-.508a.7.7 0 0 0-.509-.208q-.3 0-.5.208a.7.7 0 0 0-.2.508q0 .284.2.492t.5.208", fill: "#595959" }))); const ServiceIcon = () => (React__default["default"].createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none" }, React__default["default"].createElement("path", { d: "M6.868 9.265v.974q0 .405.284.69.284.283.69.283t.69-.284.284-.69v-.973h.973q.405 0 .69-.284a.94.94 0 0 0 .284-.689.94.94 0 0 0-.284-.69.94.94 0 0 0-.69-.284h-.973v-.974a.94.94 0 0 0-.284-.69.94.94 0 0 0-.69-.284.94.94 0 0 0-.689.284.94.94 0 0 0-.285.69v.974h-.973a.94.94 0 0 0-.69.283.94.94 0 0 0-.284.69q0 .405.284.69.285.284.69.284zm-3.46 4.868q-.581 0-.994-.413A1.36 1.36 0 0 1 2 12.725v-6.65a1.4 1.4 0 0 1 .563-1.127l4.434-3.333q.369-.282.844-.282.474 0 .846.282l4.434 3.333q.264.193.413.493.15.3.15.633v6.651q0 .58-.414.995a1.36 1.36 0 0 1-.994.413zm0-1.168h8.868q.105 0 .172-.068a.23.23 0 0 0 .068-.172v-6.65a.2.2 0 0 0-.027-.11.3.3 0 0 0-.07-.085L7.983 2.554a.2.2 0 0 0-.142-.052.2.2 0 0 0-.142.052L3.266 5.88a.3.3 0 0 0-.071.086.2.2 0 0 0-.027.108v6.651q0 .105.068.172a.23.23 0 0 0 .172.068", fill: "#595959" }))); const HospitalIcon = () => (React__default["default"].createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none" }, React__default["default"].createElement("path", { d: "M8 8q.55 0 .941-.392.393-.391.392-.941 0-.55-.392-.942A1.28 1.28 0 0 0 8 5.333q-.55 0-.942.392a1.28 1.28 0 0 0-.391.942q0 .55.391.941Q7.45 8 8 8m0 4.9q2.032-1.866 3.017-3.392Q12 7.983 12 6.8q0-1.817-1.158-2.975Q9.682 2.667 8 2.667T5.158 3.825Q4 4.983 4 6.8q0 1.184.983 2.708Q5.966 11.034 8 12.9m0 1.517a.8.8 0 0 1-.5-.183q-2.433-2.151-3.633-3.992T2.667 6.8q0-2.5 1.608-3.983Q5.883 1.332 8 1.333q2.116 0 3.725 1.484T13.333 6.8q0 1.6-1.2 3.442-1.2 1.841-3.633 3.991a.8.8 0 0 1-.5.184", fill: "#8C8C8C" }))); const SpecialtyIcon = () => (React__default["default"].createElement("svg", { width: "16", height: "16", viewBox: "0 0 16 16" }, React__default["default"].createElement("path", { d: "M3.833.5a3.333 3.333 0 1 0 0 6.667 3.333 3.333 0 0 0 0-6.667M10.5.5c-.92 0-1.667.746-1.667 1.667V5.5c0 .92.746 1.667 1.667 1.667h3.333c.921 0 1.667-.746 1.667-1.667V2.167C15.5 1.246 14.754.5 13.833.5zM3.833 8.833a3.333 3.333 0 1 0 0 6.667 3.333 3.333 0 0 0 0-6.667m8.334 0a3.333 3.333 0 1 0 0 6.667 3.333 3.333 0 0 0 0-6.667", fill: "#9AA2AC" }))); const SearchSpecialty = ({ state, isMobile, debouncedFetchSearchResults, selectedLocation, onSpecialtyClick, dispatch, }) => { var _a; const { t, locale } = index$1.useTranslations(); const inputSpecialtyWrapperRef = React.useRef(null); const slugs = React.useMemo(() => constants.LOCALIZED_SLUGS[locale], [locale]); const styleSpecialties = React.useMemo(() => { return { wrapper: { '&:after': { content: '""', width: '1px', height: '20px', backgroundColor: '#E4E8EC', position: 'absolute', right: 0, top: '13px', }, }, input: { border: isMobile ? 'border: 1px solid #d9d9d9' : 'none', height: isMobile ? '40px' : '46px !important', paddingRight: '30px', '&:focus': { boxShadow: isMobile ? 'box-shadow: 0px 0px 0px 2px #91caff' : 'none', }, }, rightSection: { width: '30px', svg: { fontSize: '20px', }, }, }; }, [isMobile]); const handleSearchSpecialtyInputChange = React.useCallback(function handleSearchSpecialtyInputChange(value) { // dispatch({ type: ActionTypes.ChangeInputLocation, payload: value }) // if (value.trim().length > SEARCH_KEYWORD_MIN_LENGTH[state.locale]) { // debouncedFetchSearchResults(value.trim()) // } else { // debouncedFetchSearchResults.cancel() // dispatch({ type: ActionTypes.DisplayInitialCities }) // } console.log(value); }, [debouncedFetchSearchResults, dispatch]); useOutsideClick.useOutsideClick(inputSpecialtyWrapperRef, () => { dispatch({ type: ActionTypes.ClickOutsideInputSpecialty }); }); return (React__default["default"].createElement(StyleSearchSpecialtyWrapper, { ref: inputSpecialtyWrapperRef }, React__default["default"].createElement(core.Input.Wrapper, null, React__default["default"].createElement(core.Input, { size: isMobile ? 'md' : 'lg', placeholder: t('booking.searchPopup.specialties'), value: ((_a = state === null || state === void 0 ? void 0 : state.selectedSpecialty) === null || _a === void 0 ? void 0 : _a.name) || '', rightSection: React__default["default"].createElement(ChevronDown.ChevronDown, null), styles: styleSpecialties, onFocus: () => dispatch({ type: ActionTypes.FocusInputSpecialty }), onChange: (event) => { handleSearchSpecialtyInputChange(event.target.value); } })), state.focused === 'specialty' && (React__default["default"].createElement(StyleResultWrapper$1, null, React__default["default"].createElement(StyledSpecialtyItem, { key: "all-location", role: "button", tabIndex: 0, onClick: () => { if (onSpecialtyClick) { onSpecialtyClick({ name: t('booking.searchBar.allSpecialties'), id: -1, thumbnail: '', total_doctor: 0, slug: slugs.SPECIALTIES, }); } } }, React__default["default"].createElement("div", { className: "image-item" }, React__default["default"].createElement(SpecialtyIcon, null)), React__default["default"].createElement(index$2.Text, { size: "md" }, t('booking.searchBar.allSpecialties'))), state.allSpecialties.map((specialty) => (React__default["default"].createElement(StyledSpecialtyItem, { key: specialty.id, onClick: (evt) => { evt.nativeEvent.stopImmediatePropagation(); if (onSpecialtyClick) { onSpecialtyClick(Object.assign(Object.assign({}, specialty), { total_doctor: 0 })); } }, role: "button", tabIndex: 0, "aria-label": `Select ${specialty.name} as location`, isSelected: (selectedLocation === null || selectedLocation === void 0 ? void 0 : selectedLocation.id) === specialty.id }, React__default["default"].createElement("div", { className: "image-item" }, React__default["default"].createElement("img", { src: specialty.thumbnail, alt: specialty.name })), React__default["default"].createElement(index$2.Text, { size: "md" }, specialty.name)))))))); }; const SearchInputs = ({ state, type, isMobile, isLoading, initalSearchValue, typeInformation, debouncedFetchSearchResults, trackingAttributes, hideSpecialtySelection = false, clientSlug = '', focusSearchInput, onSearch, onEnterSearch, dispatch, }) => { var _a; const { t } = index$1.useTranslations(); const inputSearchWrapperRef = React.useRef(null); const gaAttributes = React.useMemo(() => { if (trackingAttributes) { return { 'data-event-category': trackingAttributes.dataEventCategory, 'data-event-action': trackingAttributes.dataEventAction, 'data-event-label': trackingAttributes.dataEventLabel, }; } else { return {}; } }, [trackingAttributes]); const placeholderSearch = React.useMemo(() => { if (type === 'doctor') { return t('booking.searchBar.placeholder.doctor'); } if (type === 'service') { return t('booking.searchBar.placeholder.service'); } if (type === 'hospital') { return t('booking.searchBar.placeholder.hospital'); } if (type === 'specialty') { return t('booking.searchBar.placeholder.specialty'); } return ''; }, [type]); const styleInputWrapper = React.useMemo(() => { return { root: { flex: 1, '&.hide-specialty-selection': { '.mantine-Input-rightSection': { display: 'none', }, input: { paddingLeft: '48px', }, '.mantine-Input-icon': { left: '0', }, }, }, }; }, []); const styleInput = React.useMemo(() => { return { icon: { left: '165px', }, input: { color: '#262626', '&[data-with-icon="true"]': { paddingLeft: '205px', paddingRight: '16px', }, }, rightSection: { left: 0, width: '165px', padding: '1px', }, }; }, []); const styleInputSpecialties = React.useMemo(() => { return { input: { color: '#262626', }, }; }, []); useOutsideClick.useOutsideClick(inputSearchWrapperRef, () => { dispatch({ type: ActionTypes.ClickOutsideInputSearch }); }); const handleSearchInputChange = React.useCallback(function handleSearchInputChange(value) { dispatch({ type: ActionTypes.ChangeInputSearch, payload: value }); if (typeof onSearch === 'function') { return; } if (value.trim().length > SEARCH_KEYWORD_MIN_LENGTH[state.locale] || initalSearchValue || value.trim().length === 0) { debouncedFetchSearchResults(value.trim(), state, type, clientSlug); } else { debouncedFetchSearchResults.cancel(); dispatch({ type: ActionTypes.DisplayInitialSearchResults }); } }, [dispatch, state, type]); const handleSpecialtyClick = React.useCallback(function handleSpecialtyClick(specialty) { dispatch({ type: ActionTypes.SelectSpecialty, payload: specialty }); focusSearchInput(); }, [dispatch]); const inputOnKeyDown = React.useCallback((e) => { if (e.keyCode === 13) { e.stopPropagation(); e.preventDefault(); onEnterSearch && onEnterSearch(); } }, [onEnterSearch]); return (React__default["default"].createElement(StyleSearchInputsWrapper, { ref: inputSearchWrapperRef }, type === 'specialty' ? (React__default["default"].createElement(core.Input.Wrapper, { styles: styleInputWrapper }, React__default["default"].createElement(core.Input, { icon: React__default["default"].createElement(core$1.Search, null), size: isMobile ? 'md' : 'lg', placeholder: placeholderSearch, styles: styleInputSpecialties, value: state.searchKeywords, onFocus: () => dispatch({ type: ActionTypes.FocusInputSearchSpecialty }), onChange: (event) => { handleSearchInputChange(event.target.value); }, onKeyDown: inputOnKeyDown }))) : (React__default["default"].createElement(React__default["default"].Fragment, null, type === 'service' ? (React__default["default"].createElement(core.Input.Wrapper, { styles: styleInputWrapper }, React__default["default"].createElement(core.Input, { icon: React__default["default"].createElement(core$1.Search, null), size: isMobile ? 'md' : 'lg', name: "search-results", placeholder: placeholderSearch, onFocus: () => dispatch({ type: ActionTypes.FocusInputSearch }), value: state.searchKeywords, onChange: (event) => { handleSearchInputChange(event.target.value); }, onKeyDown: inputOnKeyDown }))) : (React__default["default"].createElement(React__default["default"].Fragment, null, isMobile && !hideSpecialtySelection ? (React__default["default"].createElement(React__default["default"].Fragment, null, React__default["default"].createElement(SearchSpecialty, { state: state, isMobile: isMobile, dispatch: dispatch, debouncedFetchSearchResults: debouncedFetchSearchResults, onSpecialtyClick: handleSpecialtyClick }), React__default["default"].createElement(core.Input.Wrapper, { styles: styleInputWrapper }, React__default["default"].createElement(core.Input, { icon: React__default["default"].createElement(core$1.Search, null), size: "md", placeholder: placeholderSearch, value: state.searchKeywords, name: "search-results", onFocus: () => dispatch({ type: ActionTypes.FocusInputSearch }), onChange: (event) => { handleSearchInputChange(event.target.value); }, onKeyDown: inputOnKeyDown })))) : (React__default["default"].createElement(core.Input.Wrapper, { styles: styleInputWrapper, className: hideSpecialtySelection ? 'hide-specialty-selection' : '' }, React__default["default"].createElement(core.Input, Object.assign({ icon: React__default["default"].createElement(core$1.Search, null), size: "lg", placeholder: placeholderSearch, styles: styleInput, name: "search-results", autoComplete: "off", value: state.searchKeywords, onChange: (event) => { handleSearchInputChange(event.target.value); }, onFocus: () => dispatch({ type: ActionTypes.FocusInputSearch }), onKeyDown: inputOnKeyDown }, gaAttributes, { rightSection: hideSpecialtySelection ? (React__default["default"].createElement(React__default["default"].Fragment, null)) : (React__default["default"].createElement(SearchSpecialty, { state: state, isMobile: isMobile, dispatch: dispatch, debouncedFetchSearchResults: debouncedFetchSearchResults, onSpecialtyClick: handleSpecialtyClick })) })))))), state.focused === 'search' && (React__default["default"].createElement(StyleResultWrapper$2, null, React__default["default"].createElement(SearchResult, { type: type, state: state, results: ((_a = state.searchResults) === null || _a === void 0 ? void 0 : _a[type]) || [], location: state.selectedLocation.name, dispatch: dispatch, isLoading: isLoading, typeInformation: typeInformation, clientSlug: clientSlug }))))))); }; const StyleSearchLocationWrapper = styled__default["default"].div ` position: relative; ${utils.MediaQueries.mbDown} { width: 100%; display: flex; flex-direction: column; gap: 12px; } `; const StyleResultWrapper = styled__default["default"].div ` position: absolute; top: calc(100% + 2px); width: 100%; border-radius: 4px; background: ${miscTheme.theme.colors.white}; box-shadow: 0px 8px 40px 0px rgba(0, 0, 0, 0.1); z-index: 10; ${utils.MediaQueries.mbDown} { width: calc(100% + 64px); left: -32px; } `; const StyledLocationItem = styled__default["default"].li ` position: relative; cursor: pointer; padding: 12px 18px; display: flex; align-items: center; gap: 14px; overflow: hidden; ${({ isSelected }) => isSelected && ` &::after { content: ${utils$1.checkMarkIconUrl}; top: 50%; right: 18px; position: absolute; transform: translateY(-50%); } `} & + li::before { content: ''; position: absolute; left: 18px; right: 18px; top: 0; height: 1px; background-color: ${miscTheme.theme.colors.neutral100}; } &:not([data-is-denied='true']):hover { background-color: ${miscTheme.theme.colors.neutral50}; } &:last-child:hover { border-bottom-right-radius: 6px; border-bottom-left-radius: 6px; } &:first-child:hover { border-top-right-radius: 6px; border-top-left-radius: 6px; } &[data-is-denied='true'] { cursor: not-allowed; } `; const StyledPinIcon = styled__default["default"](utils$1.PinIcon) ` width: 12px; height: 18px; flex: 0 0 12px; `; const SearchLocation = ({ state, isMobile, debouncedFetchCitiesByKeyword, selectedLocation, trackingAttributes, onLocationClick, dispatch, }) => { const { t, locale } = index$1.useTranslations(); const inputLocationWrapperRef = React.useRef(null); const gaAttributes = React.useMemo(() => { if (trackingAttributes) { return { 'data-event-category': trackingAttributes.dataEventCategory, 'data-event-action': trackingAttributes.dataEventAction, 'data-event-label': trackingAttributes.dataEventLabel, }; } else { return {}; } }, [trackingAttributes]); const handleSearchLocationInputChange = React.useCallback(function handleSearchLocationInputChange(value) { dispatch({ type: ActionTypes.ChangeInputLocation, payload: value }); if (value.trim().length > SEARCH_KEYWORD_MIN_LENGTH[state.locale]) { debouncedFetchCitiesByKeyword(value.trim()); } else { debouncedFetchCitiesByKeyword.cancel(); dispatch({ type: ActionTypes.DisplayInitialCities }); } }, [debouncedFetchCitiesByKeyword, dispatch]); useOutsideClick.useOutsideClick(inputLocationWrapperRef, () => { dispatch({ type: ActionTypes.ClickOutsideInputLocation }); }); return (React__default["default"].createElement(StyleSearchLocationWrapper, { ref: inputLocationWrapperRef }, React__default["default"].createElement(core.Input.Wrapper, null, React__default["default"].createElement(core.Input, Object.assign({ size: isMobile ? 'md' : 'lg', placeholder: "Search location", value: state.searchLocationKeywords, onFocus: () => dispatch({ type: ActionTypes.FocusInputLocation }), onChange: (event) => { handleSearchLocationInputChange(event.target.value); } }, gaAttributes))), state.focused === 'location' && (React__default["default"].createElement(StyleResultWrapper, null, React__default["default"].createElement(StyledLocationItem, { key: "all-location", role: "button", tabIndex: 0, onClick: () => { var _a; if (onLocationClick) { onLocationClick({ name: t('booking.searchBar.allLocations'), id: constants.ID_OPTION_ALL_LOCATION, slug: (_a = constants.LOCALIZED_SLUGS[locale]) === null || _a === void 0 ? void 0 : _a.ALL, }); } } }, React__default["default"].createElement(StyledPinIcon, { color: miscTheme.theme.colors.neutral400 }), React__default["default"].createElement(index$2.Text, { size: "md" }, t('booking.searchBar.allLocations'))), state.cities.map((city) => (React__default["default"].createElement(StyledLocationItem, { key: city.id, onClick: (evt) => { evt.nativeEvent.stopImmediatePropagation(); if (onLocationClick) { onLocationClick(city); } }, role: "button", tabIndex: 0, "aria-label": `Select ${city.name} as location`, isSelected: (selectedLocation === null || selectedLocation === void 0 ? void 0 : selectedLocation.id) === city.id }, React__default["default"].createElement(StyledPinIcon, { color: miscTheme.theme.colors.neutral400 }), React__default["default"].createElement(index$2.Text, { size: "md" }, city.name)))))))); }; const StyleSpecialtiesWrapper = styled__default["default"].div ` display: flex; flex-wrap: wrap; row-gap: 8px; column-gap: 20px; ${utils.MediaQueries.mbDown} { margin-top: 12px; } `; const StyleSpecialtyItem = styled__default["default"].div ` display: flex; align-items: center; border-radius: 8px; border: 1px solid ${miscTheme.theme.colors.neutral100}; background: ${miscTheme.theme.colors.white}; padding: 8px 12px 8px 8px; flex: 0 0 calc(33.3% - 13px); gap: 12px; cursor: pointer; &:hover { background: ${miscTheme.theme.colors.blue50}; } ${utils.MediaQueries.tdDown} { flex: 0 0 calc(50% - 10px); } ${utils.MediaQueries.mbDown} { flex: 0 0 100%; border: none; } .image-item { display: flex; align-items: center; width: 40px; height: 40px; img { width: 100%; object-fit: cover; } } .infor { flex: 1; .title { color: ${miscTheme.theme.colors.gray800}; font-size: 14px; font-style: normal; font-weight: 400; line-height: 22px; } .description { color: ${miscTheme.theme.colors.gray600}; font-size: 12px; font-weight: 400; line-height: 18px; } } `; const StyleDivider = styled__default["default"](core.Divider) ` margin: 24px 0 !important; `; const StyleShowMore = styled__default["default"].div ` display: flex; justify-content: center; margin-top: 24px; .show-more { border-radius: 4px; border: 1px solid ${miscTheme.theme.colors.neutral200}; padding: 12px 16px; cursor: pointer; display: inline-block; color: ${miscTheme.theme.colors.gray800}; font-size: 16px; font-weight: 600; line-height: 24px; ${utils.MediaQueries.mbDown} { width: 100%; text-align: center; } } `; const SearchResultSpecialties = ({ state, isMobile, specialties, isLoading, dispatch, }) => { const { t, locale } = index$1.useTranslations(); const { selectedLocation } = state; const slugs = React.useMemo(() => constants.LOCALIZED_SLUGS[locale], [locale]); const handleOnClick = (specialtySlug) => { let url = ''; if (specialtySlug === constants.SLUG_VACIN_ID) { url = `/${selectedLocation.slug}/${slugs.HOSPITAL}/${constants.CLIENT_KEY.GSK}/`; dispatch({ type: ActionTypes.ClickOutsideInputSearchSpecialty }); } else { url = `/${selectedLocation.slug}/${slugs.DOCTOR}/${specialtySlug}`; } dispatch({ type: ActionTypes.NavigateTo, payload: url }); }; const handleShowMore = () => { const url = `/${slugs.SPECIALTIES}`; dispatch({ type: ActionTypes.NavigateTo, payload: url }); }; const showSeeMore = React.useMemo(() => { return (specialties.length >= 9 || state.searchKeywords.trim().length <= SEARCH_KEYWORD_MIN_LENGTH[state.locale]); }, [state.searchKeywords, specialties]); return (React__default["default"].createElement(React__default["default"].Fragment, null, !isMobile && React__default["default"].createElement(StyleDivider, { color: "#E4E8EC" }), React__default["default"].createElement(StyleSpecialtiesWrapper, null, specialties.length > 0 && !isLoading && (React__default["default"].createElement(React__default["default"].Fragment, null, specialties.map((specialty, index) => { if (index >= 9) { return React__default["default"].createElement(React__default["default"].Fragment, null); } return (React__default["default"].createElement(StyleSpecialtyItem, { key: specialty.id, onClick: () => handleOnClick(specialty.slug) }, React__default["default"].createElement("div", { className: "image-item" }, React__default["default"].createElement("img", { src: specialty.thumbnail, alt: specialty.name })), React__default["default"].createElement("div", { className: "infor" }, React__default["default"].createElement("div", { className: "title" }, specialty.name)))); }))), specialties.length === 0 && !isLoading && (React__default["default"].createElement(index$2.Text, { size: "sm", color: miscTheme.theme.colors.gray400 }, t('booking.searchBar.noResults'))), isLoading &&