Untitled
unknown
plain_text
12 days ago
28 kB
3
Indexable
Never
I have this full code. Why on mobile version the modal is not open (that have "HotelRoomMobileCard" component) and I get this error on my application? TypeError: Cannot read properties of null (reading 'scrollIntoView') And here's the full code: import { Button, Stars, Tooltip, Typography } from '@cvccorp-components/core'; import CustomTooltip from '@cvccorp-components/flight-components/components/Common/CustomTooltip'; import Air from '@cvccorp-components/icons/dist/Air'; import DropLeft from '@cvccorp-components/icons/dist/DropLeft'; import DropRight from '@cvccorp-components/icons/dist/DropRight'; import { useMediaQuery } from '@material-ui/core'; import Grid from '@material-ui/core/Grid'; import Skeleton from '@material-ui/lab/Skeleton'; import clsx from 'clsx'; import React, { useEffect, useState } from 'react'; import Slider from 'react-slick'; import 'slick-carousel/slick/slick-theme.css'; import 'slick-carousel/slick/slick.css'; import Cookies from 'universal-cookie'; import { useStyles } from './styles'; import { useSearch } from '../../context/Search/provider'; import { ICharter, IHotel, IRoom } from '../../models'; import { formatNumber, formatPrice } from '../../utils'; import { getAmenitiesIcons } from '../../utils/getAmenitiesIcons'; import { getNoImage, imageResize } from '../../utils/getImage'; import Badge from '../Badge'; import { HotelRoomCard } from '../HotelRoomCard'; import { HotelRoomFullCard } from '../HotelRoomFullCard'; import { HotelRoomMobileCard } from '../HotelRoomMobileCard'; import { useMaps } from '../Maps/context'; import dangerIcon from '../../../assets/img/dangerRegular.svg'; import dangerRiskIcon from '../../../assets/img/dangerRisk.svg'; import { useSeller } from '../../context/Seller/provider'; import { IException } from '../../models/Error'; import PackagesService from '../../services/PackagesService'; import { dataLayerCharter, setDL } from '../../utils/dataLayer'; import { detailExclusivePackageDataLayer } from '../../utils/detailExclusivePackageDataLayer'; import { limitString } from '../../utils/limitString'; import { ModalConfirm } from '../ModalConfirm'; import { ModalItineraryDayByDay } from '../ModalItineraryDayByDay'; import { ModalListRoom } from '../ModalListRoom/ModalListVoos'; import { PackagePromotion } from '../PackagePromotion'; import { PromotionTag } from '../PromotionTag'; import { HotelSlider } from '../Summary/HotelSlider'; export interface IHotelCardProps { charter: ICharter; changePackAlert: boolean; onSelect: (charter: ICharter) => void; isSelected?: boolean; className?: string; } export interface DCR { confirmed: Number; reserved: Number; available: Number; } export const HotelCard: React.FC<IHotelCardProps> = ({ charter, isSelected, onSelect, className, changePackAlert }) => { const { showAlterListType, setShowAlterList, showRoomsSelectedHotel, setShowRoomsSelectedHotel, setShowHotelDetail, charterSelected, setHotelDetailData, selectedRate, isVendor } = useSearch(); const classes = useStyles({}); const [showRooms, setShowRooms] = useState(showAlterListType === 'Room'); const { showMap, setInitialZoom } = useMaps(); const [showConfirmChange, setShowConfirmChange] = useState<boolean>(false); const [currentHotelIndex, setCurrentHotelIndex] = useState(0); const { assistedSaleMessage } = useSeller(); const [showModal, setShowModal] = useState(false); useEffect(() => { cookies.remove('PackageToken', { path: '/' }); }, []); const onSelectHotel = () => { clickSelectHotelDL(); if (changePackAlert) { setShowConfirmChange(true); } else { handleSelectHotel(); } }; const onConfirmChange = () => { handleSelectHotel(); setShowConfirmChange(false); }; const onCloseConfirmChange = () => { setShowConfirmChange(false); }; const [getDCRHotels, setDCRHotels] = useState({} as DCR); const [styleTooltip, setStyleTooltip] = useState(false); const cookies = new Cookies(); const charterHotelSelected = () => { let hotel: IHotel = null; if (isSelected) { hotel = charterSelected?.hotels?.[currentHotelIndex]; } else { hotel = charter.hotels[currentHotelIndex]; } const room = hotel?.rooms?.find((item: IRoom) => item?.selected === true); if (!room && isSelected && hotel?.rooms?.length > 0) { hotel.rooms[0].selected = true; } return hotel; }; const getHasMultipleHotels = () => { if (isSelected) { return charterSelected?.hotels?.length > 1; } return charter.hotels.length > 1; }; const charterTitleSelected = () => { if (isSelected) { return charterSelected?.title && charterSelected?.title; } return charter?.title && charter?.title; }; const selectedRoom = () => { let room = charterHotelSelected()?.rooms?.find((item: IRoom) => item?.selected === true); if (!room && charterHotelSelected()) { room = charterHotelSelected().rooms[0]; } return room; }; const showTaxes = () => { let pWithTax = 0; let pWithoutTax = 0; const rate = selectedRoom()?.rates?.[0]; if (rate?.promotionItem?.promotion !== undefined && rate?.promotionItem?.promotion !== null) { const { priceWithTax, priceWithoutTax } = rate?.promotionItem.promotion; pWithTax = priceWithTax; pWithoutTax = priceWithoutTax; } else { const { priceWithTax, priceWithoutTax } = rate; pWithTax = priceWithTax || 0; pWithoutTax = priceWithoutTax || 0; } return formatPrice(pWithTax - pWithoutTax); }; const showTotal = () => { const rate = selectedRoom().rates[0]; if (rate?.promotionItem?.promotion !== undefined && rate?.promotionItem?.promotion !== null) { return rate?.promotionItem.promotion.priceWithTax; } return rate?.priceWithTax; }; const handleSelectHotel = () => { charter.hotels[0].rooms.forEach((_room: IRoom, index: number) => { _room.selected = index === 0; }); onSelect(charter); }; const handleChangeRoomClick = () => { if (showRooms && showRoomsSelectedHotel && showAlterListType === 'Room') { window.location.hash = '#freteRecommend'; setShowAlterList('None'); } setShowRoomsSelectedHotel(!showRoomsSelectedHotel); setShowRooms(!showRooms); }; const handleSelectRoom = (room: IRoom, indexRoom: number) => { const temp = charter; temp.hotels[0].rooms.forEach((_room: IRoom, index: number) => { _room.selected = _room?.name === room?.name && index === indexRoom; }); onSelect(temp); setShowRooms(false); setShowRoomsSelectedHotel(false); dataLayerCharter('click-pacote-exclusivo', charterSelected); }; const NextArrow = (props) => { const handleClick = (e) => { if (props.onClick) props.onClick(e); e.stopPropagation(); }; return ( <button type="button" className={clsx(classes.arrows, classes.arrowRight)} onClick={(e) => { handleClick(e); }} > <DropRight size="medium" /> </button> ); }; const PrevArrow = (props) => { const handleClick = (e) => { if (props.onClick) props.onClick(e); e.stopPropagation(); }; return ( <button type="button" className={clsx(classes.arrows, classes.arrowLeft)} onClick={(e) => { handleClick(e); }} > <DropLeft size="medium" /> </button> ); }; const showMaps = () => { clickDetailsDL('Veja no mapa'); setInitialZoom(18); showMap(charterHotelSelected()); }; const changeStyleTooltip = () => { setStyleTooltip(true); checkCookiesDcr(); }; const checkCookiesDcr = () => { if (cookies.get('PackageToken')) { const cookieDCRTokenObject = cookies.get('PackageToken'); const cookieDCRSplit = cookieDCRTokenObject.split('|'); const cookieDCRObjectParsed = JSON.parse(cookieDCRSplit[1]); const cookieDCRToken = cookieDCRSplit[0]; const charterPackageToken = charter.packageToken; return cookieDCRToken === charterPackageToken ? setDCRHotels(cookieDCRObjectParsed) : loadDCRHotel(); } loadDCRHotel(); }; const loadDCRHotel = async () => { try { setDCRHotels(null); const packageToken = charter.packageToken; const { data: getDCR, config } = await PackagesService.getDCR(packageToken); const getDCRHotels0 = getDCR.dcr.hotels[0]; cookies.set('PackageToken', ${packageToken}|${JSON.stringify(getDCRHotels0)}, { path: '/', maxAge: 120 }); const otherParams = { duration: config.meta.durationTime, durationUnit: config.meta.unitTime, frendlyMessage: 'Hotel DCR' }; assistedSaleMessage('SUCCESS', 6, 'DCR', null, otherParams); return setDCRHotels(getDCRHotels0); } catch (error) { const err: IException = error; const otherParams = { frendlyMessage: 'Erro ao carregar hotel DCR', duration: err?.config?.meta?.durationTime || 0, durationUnit: err?.config?.meta?.unitTime || 'milisseconds' }; assistedSaleMessage('ERROR', 4, 'DCR', err, otherParams); } }; const RenderValue = () => { const existsPromo = selectedRoom()?.rates[0].promotionItem?.promotion !== null && selectedRoom()?.rates[0].promotionItem?.promotion !== undefined; return ( <Grid container justify={isMobile ? 'space-between' : 'center'} alignItems="center" xs={12} className={classes.totalValues}> <Grid container justify={isMobile ? 'space-between' : 'center'} alignItems="center" item xs={12}> <span className={clsx(classes.fontGrayRegular2, classes.fontSize14)}>{Total do ${isVendor ? 'pacote':'combo CVC'}}</span> </Grid> {existsPromo ? ( <PackagePromotion value={selectedRoom()?.rates[0]?.priceWithTax} promotion={showTotal()} /> ) : ( <Grid container justify={isMobile ? 'flex-end' : 'center'} alignItems="baseline" xs={12} wrap="nowrap" className={classes.value}> <div className={clsx(classes.toInfo)}> <div className={clsx(classes.fontBlackBold, classes.fontSize14)}>R$</div> </div> <span className={clsx(classes.fontBlackBold, classes.fontSize26)}>{formatNumber(showTotal())}</span> </Grid> )} </Grid> ); }; const onMouseOut = () => { setStyleTooltip(false); }; const clickDetailsDL = (label) => { const dlObject = { event: 'pacote_engajamento', category: 'pacote_exclusivo_detalhe_conteudo_outro-hotel', action: 'click', label }; setDL(dlObject); }; const clickDetailExclusivePackage = () => { detailExclusivePackageDataLayer(); }; const clickSelectHotelDL = () => { const dlObject = { event: 'pacote_engajamento', category: 'pacote_exclusivo_novo_hotel', action: 'click', label: 'Selecionar Hotel' }; setDL(dlObject); dataLayerCharter('click-pacote-exclusivo', charterSelected); }; const getDiff = () => { const [currentRoomRate] = selectedRoom().rates; if (currentRoomRate?.promotionItem?.promotion) { return ( currentRoomRate?.promotionItem?.promotion?.priceWithTax - (selectedRate?.promotionItem?.promotion?.priceWithTax || selectedRate.priceWithTax) ); } return currentRoomRate?.priceWithTax - (selectedRate?.promotionItem?.promotion?.priceWithTax || selectedRate.priceWithTax); }; const isTablet = useMediaQuery('(max-width: 1024px) and (min-width:768px)'); const isMobile = useMediaQuery('(max-width: 767px) and (min-width:1px)'); let isRisk = false; if (isVendor) isRisk = charter?.hotels?.[0]?.risk && charter?.hotels?.[0]?.risk === 'HIGH'; const isPromotion = (selectedRoom()?.rates && selectedRoom()?.rates.length > 0 && selectedRoom().rates[0].promotionItem?.promotion) || (selectedRoom()?.rates && selectedRoom()?.rates.length > 0 && selectedRoom().rates[0].promotionItem?.hasCombo); const roomImg = charterHotelSelected()?.links && charterHotelSelected()?.links?.images && charterHotelSelected()?.links?.images?.[0]; const getTooltip = () => { const typography = ( <Typography type="body1regular" className={classes.baggageTooltipText}> {charterHotelSelected()?.name} {' - '} {charterTitleSelected()} </Typography> ); return ( <CustomTooltip title={typography} placement="top"> <div> {charterHotelSelected()?.name} {' - '} {charterHotelSelected()?.name.length > 30 ? limitString(charterTitleSelected(), 55) : limitString(charterTitleSelected(), 70)} </div> </CustomTooltip> ); }; const { location } = charter?.destination; return ( <Grid container xs={12} className={clsx(className, classes.rootContainer, { [classes.multiHotelsWrapper]: getHasMultipleHotels() })} > {getHasMultipleHotels() && ( <div className={classes.multiHotelsContainer}> <span> Pacote para {location?.city} - {location?.state} - {location?.country} </span> <HotelSlider hotels={charter.hotels} activeHotelIndex={currentHotelIndex} onChangeHotelIndex={(index) => setCurrentHotelIndex(index)} /> </div> )} <Grid className={clsx(classes.root, !charter.airProtection ? classes.rootHotel : classes.rootNoHotel, { [classes.dangerContainer]: isRisk })} container justify="space-between" xs={12} > {charter.airProtection && ( <Grid className={classes.colNoHotel} item container alignItems="center"> <Grid item className={classes.colNoHotelIcon}> <Air className={classes.colNoHotelIconAir} /> </Grid> <Grid item container xs={10} direction="column"> <Typography type="headline3" className={classes.colNoHotelTitle}> Somente passagem aérea </Typography> <Typography type="body1regular" className={classes.colNoHotelInfo}> Selecione esta opção caso queira apenas o voo, sem hotel incluso. </Typography> </Grid> </Grid> )} {!charter.airProtection && ( <Grid className={classes.colImage} item> <Slider infinite={true} speed={500} slidesToShow={1} touchThreshold={100} nextArrow={<NextArrow />} prevArrow={<PrevArrow />}> {charterHotelSelected().links && charterHotelSelected().links.images && charterHotelSelected().links.images.map((img, index) => ( <div key={index} className={classes.carousel}> <img // src={${getBaseImage('h_314,w_314')}${img.href}} src={imageResize(img.href, '314', '314')} className={classes.imgCarousel} onError={({ currentTarget }) => { currentTarget.onerror = null; currentTarget.src = getNoImage('h_314,w_314'); }} alt="Imagem" /> </div> ))} {(!charterHotelSelected().links || !charterHotelSelected().links.images || !charterHotelSelected().links.images.length) && ( <div className={classes.carousel}> <img src={getNoImage('h_314,w_314')} className={classes.imgCarousel} alt="Imagem" /> </div> )} </Slider> </Grid> )} {!charter.airProtection && ( <Grid className={classes.colContent} item container> <Grid container justify="space-between"> <Grid item container> <Grid item xs={12}> <Typography type="headline6">{getTooltip()}</Typography> </Grid> <Grid item xs={12} className={clsx(classes.addressBlock)}> <span className={clsx(classes.fontGrayRegular, classes.fontSize12)}> {limitString(charterHotelSelected()?.location.address, 20)} <span className={classes.pipeMap}>|</span> </span> <a className={classes.link1} onClick={() => showMaps()}> Veja no mapa </a> </Grid> <Grid item container alignItems="center" xs={12} className={clsx(classes.amenitiesBlock)}> <Grid item className={clsx(classes.marginRight16)}> <Stars stars={charterHotelSelected().award} size="small" /> {charterHotelSelected() .amenities?.slice(0, 5) .map((a, i) => getAmenitiesIcons(a.code, a.name, 'small', classes.iconButtonStyle))} </Grid> </Grid> <Grid item container xs={12} className={clsx(classes.linksBlock)}> <Grid item> <a className={clsx(classes.link1, classes.marginRight16)} onClick={() => { clickDetailsDL('Detalhes do hotel'); clickDetailExclusivePackage(); setHotelDetailData(charterHotelSelected()); setShowHotelDetail(true); }} > Detalhes </a> <a className={clsx(classes.link1, classes.marginRight16)} onClick={() => { clickDetailsDL('Roteiro'); setShowModal(true); }} > Roteiro </a> <ModalItineraryDayByDay charter={charter} isOpen={showModal} onClose={() => setShowModal(false)} baseClasses={classes} /> <Tooltip label={ getDCRHotels ? ( <Grid> <Grid className={classes.regNeutralSize3}> <span>Disponíveis</span> <span className={classes.marginLeftQuant}>{getDCRHotels.available}</span> <br /> </Grid> <Grid className={classes.regNeutralSize3}> <span>Confirmados</span> <span className={classes.marginConfQuant}>{getDCRHotels.confirmed}</span> <br /> </Grid> <Grid className={classes.regNeutralSize3}> <span>Reservados</span> <span className={classes.marginLeftQuant}>{getDCRHotels.reserved}</span> <br /> </Grid> </Grid> ) : ( <div> <Skeleton className={classes.skeletonTooltip} variant="text" width="100%" height={23} /> <Skeleton className={classes.skeletonTooltip} variant="text" width="100%" height={23} /> <Skeleton className={classes.skeletonTooltip} variant="text" width="100%" height={23} /> </div> ) } className={styleTooltip ? classes.tooltipisPreferentialOpen : classes.tooltipisPreferential} > {isVendor && ( <a onClick={() => { clickDetailsDL('Disponibilidade'); changeStyleTooltip(); }} onMouseOut={() => { onMouseOut(); }} className={clsx(classes.link1, classes.marginRight16)} > Disponibilidade </a> )} </Tooltip> </Grid> {/* <Grid item> <a className={classes.link1} onClick={() => {}}>Roteiro de atividades</a> </Grid> */} </Grid> </Grid> <Grid item container className={classes.roomBox}> <HotelRoomCard qtyRooms={charterHotelSelected().rooms.length} room={selectedRoom()} showChangeRoom={true} alteringRoom={showRooms} onChangeRoomClick={handleChangeRoomClick} /> </Grid> </Grid> </Grid> )} <Grid className={classes.colPrice} item container> <Grid container direction="column" justify="space-between"> <Grid item container> {isRisk && ( <Grid container justify="flex-end" alignItems="center" xs={12} className={classes.promotionTag}> <Badge type="danger" text="Malha prioritária" />{' '} </Grid> )} {isPromotion && ( <Grid container justify="flex-end" alignItems="center" xs={12} className={classes.promotionTag}> <PromotionTag promotionItem={selectedRoom().rates[0].promotionItem} /> </Grid> )} <Grid container justify="space-between" alignItems="center" xs={12}> <span className={clsx(classes.fontBlackBold, classes.fontSize11, classes.marginBottom5px)}>{Valor do ${isVendor ?'pacote':'combo CVC'} com este hotel: }</span> </Grid> <Grid container justify="space-between" alignItems="center" xs={12}> <span className={clsx(classes.fontGrayRegular, classes.fontSize12)}>Valor por viajante: </span> <span className={clsx(classes.fontBlackBold, classes.fontSize12)}> {formatPrice(selectedRoom()?.rates[0]?.pricePerPaxWithoutTax)} </span> </Grid> <Grid container justify="space-between" alignItems="center" xs={12}> <span className={clsx(classes.fontGrayRegular, classes.fontSize12)}>Taxas</span> <span className={clsx(classes.fontBlackBold, classes.fontSize12)}>{showTaxes()}</span> </Grid> {!!getDiff() && ( <Grid container justify="space-between" alignItems="center" xs={12}> <span className={clsx(classes.fontGrayRegular, classes.fontSize12)}>Diferença</span> <span className={clsx(classes.fontOrangeBold, classes.fontSize12)}>{formatPrice(getDiff())}</span> </Grid> )} </Grid> <Grid item container> <RenderValue /> <Grid container justify="center" alignItems="flex-end" xs={12}> <Button disabled={isSelected} onClick={onSelectHotel} color="secondary" className={classes.mobileBtn} label={ isSelected ? !charter.airProtection ? 'Hotel selecionado' : 'Selecionado' : !charter.airProtection ? 'Selecionar hotel' : 'Selecionar' } variant="contained" size="small" /> </Grid> <span className={classes.installments}>Taxas Inclusas | <strong>Em até 12x</strong></span> </Grid> </Grid> </Grid> </Grid> {/* IS TABLET AQUI */} {isTablet && !isMobile && ( <ModalListRoom openModal={showRooms} onClose={() => { setShowRooms(false); setShowAlterList('None'); }} isRoom={true} > <Grid container item xs={12} className={classes.roomsContainer2}> {charterHotelSelected().rooms.map((room, index) => ( <HotelRoomFullCard key={index} room={room} onSelect={(room) => { handleSelectRoom(room, index); }} className={classes.cardRoom} isSelected={room.selected} selectedRate={selectedRate} /> ))} </Grid> </ModalListRoom> )} {showRooms && !isTablet && !isMobile && ( <Grid container item xs={12} className={classes.roomsContainer}> {charterHotelSelected().rooms.map((room, index) => ( <HotelRoomFullCard key={index} room={room} onSelect={(room) => { handleSelectRoom(room, index); }} className={classes.cardRoom} isSelected={room.selected} selectedRate={selectedRate} /> ))} </Grid> )} {isMobile && ( <ModalListRoom openModal={showRooms} onClose={() => { setShowRooms(false); setShowAlterList('None'); }} isRoom={true} > <Grid container item xs={12} className={classes.roomsContainer3}> {charterHotelSelected().rooms.map((room, index) => ( <HotelRoomMobileCard key={index} room={room} onSelect={(room) => { handleSelectRoom(room, index); }} img={roomImg} className={classes.cardRoom} isSelected={room.selected} selectedRate={selectedRate} /> ))} </Grid> </ModalListRoom> )} {changePackAlert && !isRisk && ( <> <Grid container item xs={12} className={classes.changeAlert}> <img src={dangerIcon} /> {charter.airProtection ? ( <Typography type="headline7">A seleção deste item impactará automaticamente na alteração do voo selecionado.</Typography> ) : ( <Typography type="headline7"> Este hotel não está relacionado ao voo selecionado. Ao selecioná-lo, o voo será automaticamente alterado. </Typography> )} </Grid> </> )} {changePackAlert && isRisk && ( <> <Grid container item xs={12} className={classes.highRiskAlert}> <img src={dangerRiskIcon} /> <Typography type="headline7"> Malha Prioritária - Este hotel não está relacionado ao voo selecionado </Typography> </Grid> </> )} {!changePackAlert && isRisk && ( <> <Grid container item xs={12} className={classes.highRiskAlert}> <img src={dangerRiskIcon} /> <Typography type="headline7"> Malha Prioritária </Typography> </Grid> </> )} {changePackAlert && ( <> {showConfirmChange && !charter.airProtection ? ( <ModalConfirm alert="hotel" open={showConfirmChange} confirmFunction={onConfirmChange} closeFunction={onCloseConfirmChange} /> ) : ( <ModalConfirm alert="airProtection" open={showConfirmChange} confirmFunction={onConfirmChange} closeFunction={onCloseConfirmChange} /> )} </> )} </Grid> ); };
Leave a Comment