From b81cc2c19c4ad55105ae6e319c791bb8dcd92feb Mon Sep 17 00:00:00 2001 From: Roel Mendoza Date: Mon, 15 Jul 2024 20:49:55 -0600 Subject: [PATCH] overrided history api behavior in app --- src/pages/Products/ProductSelectorNav.jsx | 8 +- src/pages/Products/ProductsContext.jsx | 241 +++++++++++++--------- 2 files changed, 145 insertions(+), 104 deletions(-) diff --git a/src/pages/Products/ProductSelectorNav.jsx b/src/pages/Products/ProductSelectorNav.jsx index 372e36c..b1144ea 100644 --- a/src/pages/Products/ProductSelectorNav.jsx +++ b/src/pages/Products/ProductSelectorNav.jsx @@ -3,17 +3,17 @@ import Link from '@mui/material/Link'; import Typography from '@mui/material/Typography'; import NavigateNextIcon from '@mui/icons-material/NavigateNext'; import { useProductsContext } from './ProductsContext'; -import { ProductTypes, Screens } from './ProductsConstants'; +import { ProductTypes } from './ProductsConstants'; const ProductSelectorNav = () => { - const { selectedBrand, selectedCarModel, handleBack, productType } = useProductsContext(); + const { selectedBrand, selectedCarModel, productType, navigateBack, } = useProductsContext(); const handleBackToBrands = () => { - handleBack(Screens.BRANDS); + navigateBack(); } const handleBackToCarModels = () => { - handleBack(Screens.MODELS); + navigateBack(); } const productVerbiage = productType === ProductTypes.CAP ? 'Tapas' : productType === ProductTypes.FAN ? 'Abanicos' : 'Radiadores'; diff --git a/src/pages/Products/ProductsContext.jsx b/src/pages/Products/ProductsContext.jsx index 421bcb9..82bead3 100644 --- a/src/pages/Products/ProductsContext.jsx +++ b/src/pages/Products/ProductsContext.jsx @@ -1,111 +1,152 @@ -import { createContext, useContext, useState } from 'react'; +import { createContext, useContext, useState, useEffect, useCallback } from 'react'; import { ProductTypes, Screens, SearchOptions } from './ProductsConstants'; const ProductsContext = createContext(); -export const useProductsContext = () => useContext(ProductsContext); +export const useProductsContext = () => { + const context = useContext(ProductsContext); + if (context === undefined) { + throw new Error('useProductsContext must be used within a ProductsProvider'); + } + return context; +}; export const ProductsProvider = ({ children }) => { - const [productType, setProductType] = useState(ProductTypes.RADIATOR); - const [currentScreen, setCurrentScreen] = useState(Screens.BRANDS); - const [openDialog, setOpenDialog] = useState(false); - - const [selectedProduct, setSelectedProduct] = useState(null); - const [selectedBrand, setSelectedBrand] = useState(null); - const [selectedCarModel, setSelectedCarModel] = useState(null); - - const [searchTerm, setSearchTerm] = useState(''); - const [searchOption, setSearchOption] = useState(SearchOptions.BRANDS); - - const [loading, setLoading] = useState(false); - - const handleItemSelect = (item, type) => { - switch (type) { - case Screens.BRANDS: - setSelectedBrand(item); - setSearchOption(SearchOptions.MODELS); - setCurrentScreen(Screens.MODELS); - setSelectedBrand(item); - break; - case Screens.MODELS: - setSelectedCarModel(item); - setSearchOption(SearchOptions.PRODUCTS); - setCurrentScreen(Screens.PRODUCTS); - break; - case Screens.PRODUCTS: - setSelectedProduct(item); - break; - default: - console.log('Tipo de selección no reconocido:', type); - } - }; - - - const handleChangeProductType = (newValue) => { - setProductType(newValue); - }; - - const handleOpenDialog = () => { - setOpenDialog(true); - }; - - const handleCloseDialog = () => { - setOpenDialog(false); - }; - - const handleBack = (screen) => { - if (screen === Screens.BRANDS) { - setCurrentScreen(Screens.BRANDS); - setSearchOption(SearchOptions.BRANDS); - setSelectedBrand(null); - setSelectedCarModel(null); - } else if (screen === Screens.MODELS) { - setCurrentScreen(Screens.MODELS); - setSearchOption(SearchOptions.MODELS); - setSelectedCarModel(null); - } - }; - - const handleSearchOptionChange = (value) => { - setSearchTerm(''); - setSelectedBrand(null); + const [productType, setProductType] = useState(ProductTypes.RADIATOR); + const [currentScreen, setCurrentScreen] = useState(Screens.BRANDS); + const [openDialog, setOpenDialog] = useState(false); + const [selectedProduct, setSelectedProduct] = useState(null); + const [selectedBrand, setSelectedBrand] = useState(null); + const [selectedCarModel, setSelectedCarModel] = useState(null); + const [searchTerm, setSearchTerm] = useState(''); + const [searchOption, setSearchOption] = useState(SearchOptions.BRANDS); + const [loading, setLoading] = useState(false); + const [scrollPosition, setScrollPosition] = useState(0); + + const navigateBack = useCallback(() => { + if (openDialog) { + setOpenDialog(false); + return; + } + + switch (currentScreen) { + case Screens.PRODUCTS: + setCurrentScreen(Screens.MODELS); setSelectedCarModel(null); - setSelectedProduct(null); - setSearchOption(value); - - if (value === SearchOptions.BRANDS) { - setCurrentScreen(Screens.BRANDS); - } else if (value === SearchOptions.MODELS) { - setCurrentScreen(Screens.MODELS); - } else { - setCurrentScreen(Screens.PRODUCTS); + break; + case Screens.MODELS: + setCurrentScreen(Screens.BRANDS); + setSelectedBrand(null); + break; + case Screens.BRANDS: + // Comportamiento predeterminado: salir de la aplicación + if (window.history.length > 1) { + window.history.back(); } + break; + default: + break; + } + }, [currentScreen, openDialog]); + + useEffect(() => { + const handlePopState = (event) => { + event.preventDefault(); + navigateBack(); }; + window.addEventListener('popstate', handlePopState); - return ( - - {children} - - ); -}; + return () => { + window.removeEventListener('popstate', handlePopState); + }; + }, [navigateBack]); + + const pushState = useCallback(() => { + window.history.pushState(null, '', window.location.pathname); + }, []); + + const handleItemSelect = (item, type) => { + pushState(); + switch (type) { + case Screens.BRANDS: + setSelectedBrand(item); + setSearchOption(SearchOptions.MODELS); + setCurrentScreen(Screens.MODELS); + break; + case Screens.MODELS: + setSelectedCarModel(item); + setSearchOption(SearchOptions.PRODUCTS); + setCurrentScreen(Screens.PRODUCTS); + break; + case Screens.PRODUCTS: + setSelectedProduct(item); + setScrollPosition(window.pageYOffset); + break; + default: + console.log('Tipo de selección no reconocido:', type); + } + }; + + const handleOpenDialog = () => { + pushState(); + setOpenDialog(true); + }; + + const handleCloseDialog = () => { + navigateBack(); + }; + + const handleChangeProductType = (newValue) => { + setProductType(newValue); + }; + + const handleSearchOptionChange = (value) => { + setSearchTerm(''); + setSearchOption(value); + + if (value === SearchOptions.BRANDS) { + setCurrentScreen(Screens.BRANDS); + } else if (value === SearchOptions.MODELS) { + setCurrentScreen(Screens.MODELS); + } else { + setCurrentScreen(Screens.PRODUCTS); + } + }; + + const value = { + productType, + currentScreen, + openDialog, + selectedProduct, + selectedBrand, + selectedCarModel, + searchTerm, + searchOption, + loading, + scrollPosition, + setProductType, + setCurrentScreen, + setOpenDialog, + setSelectedProduct, + setSelectedBrand, + setSelectedCarModel, + setSearchTerm, + setSearchOption, + setLoading, + setScrollPosition, + handleItemSelect, + handleOpenDialog, + handleCloseDialog, + handleChangeProductType, + handleSearchOptionChange, + navigateBack, + pushState + }; + + return ( + + {children} + + ); +}; \ No newline at end of file