diff --git a/src/App.js b/src/App.js index 05b8ad0e..f9981ff4 100644 --- a/src/App.js +++ b/src/App.js @@ -5,6 +5,7 @@ import { ThemeProvider } from './context'; import { ToastProvider, BottomNavigation } from './components/ui'; import Header from './components/Header.jsx'; import Footer from './components/Footer.jsx'; +import ScrollToTop from './components/ScrollToTop.jsx'; import AppRoutes from './router/index.jsx'; import './App.css'; @@ -39,6 +40,7 @@ function App() { +
diff --git a/src/components/Hero.css b/src/components/Hero.css index e046e44f..04ed4ead 100644 --- a/src/components/Hero.css +++ b/src/components/Hero.css @@ -207,6 +207,11 @@ } @media (max-width: 768px) { + /* Hide globe on mobile to prevent cutoff issues */ + .hero__globe-container { + display: none !important; + } + .hero--small { min-height: 250px; padding: var(--space-10) 0; diff --git a/src/components/ScrollToTop.jsx b/src/components/ScrollToTop.jsx new file mode 100644 index 00000000..4df24f01 --- /dev/null +++ b/src/components/ScrollToTop.jsx @@ -0,0 +1,18 @@ +import { useEffect } from 'react'; +import { useLocation } from 'react-router-dom'; + +/** + * ScrollToTop Component + * Scrolls to top of page on route changes + */ +const ScrollToTop = () => { + const { pathname } = useLocation(); + + useEffect(() => { + window.scrollTo(0, 0); + }, [pathname]); + + return null; +}; + +export default ScrollToTop; diff --git a/src/components/ui/BottomNavigation.jsx b/src/components/ui/BottomNavigation.jsx index c18cd20e..aa2682ed 100644 --- a/src/components/ui/BottomNavigation.jsx +++ b/src/components/ui/BottomNavigation.jsx @@ -17,7 +17,7 @@ const BottomNavigation = ({ isAuthenticated = false }) => { { path: '/recommendations', icon: 'star', label: 'Recs', requiresAuth: true }, { path: '/favourites', icon: 'heart', label: 'Saved', requiresAuth: true }, { path: '/navigation', icon: 'navigation', label: 'Navigate' }, - { path: isAuthenticated ? '/profile' : '/login', icon: 'user', label: isAuthenticated ? 'Profile' : 'Login' }, + // Profile button removed - accessible via header user dropdown ]; const filteredItems = navItems.filter(item => !item.requiresAuth || isAuthenticated); diff --git a/src/pages/NavigationPage.jsx b/src/pages/NavigationPage.jsx index 88b13d5f..3c5c0682 100644 --- a/src/pages/NavigationPage.jsx +++ b/src/pages/NavigationPage.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useState, useEffect, useCallback, useRef } from 'react'; import { useSearchParams } from 'react-router-dom'; import { navigationAPI } from '../api'; import { useTranslation } from '../i18n'; @@ -42,6 +42,9 @@ const NavigationPage = () => { const [routeGeometry, setRouteGeometry] = useState(null); const [routeError, setRouteError] = useState(null); // For impossible routes + // Ref for auto-scrolling to results + const resultsRef = useRef(null); + // Reverse geocode when route data changes const geocodeLocations = useCallback(async () => { if (!routeData) return; @@ -153,6 +156,13 @@ const NavigationPage = () => { } setRouteData(routeInfo); + + // Auto-scroll to map on mobile after route calculation + setTimeout(() => { + if (resultsRef.current) { + resultsRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }, 100); } catch (err) { setError(err.message || t('errorCalculatingRoute')); console.error('Error calculating route:', err); @@ -320,7 +330,7 @@ const NavigationPage = () => {
{/* Results */} -
+
{routeData ? (
diff --git a/src/pages/PlaceDetailsPage.css b/src/pages/PlaceDetailsPage.css index 4ccdb441..3a91d876 100644 --- a/src/pages/PlaceDetailsPage.css +++ b/src/pages/PlaceDetailsPage.css @@ -646,7 +646,8 @@ @media (max-width: 768px) { .place-hero { - padding: var(--space-12) 0 var(--space-16); + padding: var(--space-12) 0 var(--space-24); + /* Increased bottom padding for action buttons */ } .place-title { @@ -659,11 +660,19 @@ } .place-actions-bar { - flex-direction: column; + flex-direction: row; + /* Keep horizontal on mobile */ + flex-wrap: wrap; + justify-content: center; + margin-top: calc(-1 * var(--space-24)); + /* Adjust overlap */ } - .place-actions-bar button { - width: 100%; + .place-actions-bar button, + .place-actions-bar a { + flex: 1 1 auto; + min-width: 100px; + max-width: 150px; } .place-description-card, @@ -689,4 +698,32 @@ .star-btn { font-size: 1.5rem; } +} + +/* Extra small screens (iPhone SE, small phones) */ +@media (max-width: 480px) { + .place-hero { + padding: var(--space-10) 0 calc(var(--space-32) + var(--space-20)); + /* Increased bottom padding for 3 stacked buttons */ + } + + .place-title { + font-size: var(--text-2xl); + } + + .place-actions-bar { + flex-direction: column; + /* Stack vertically on very small screens */ + align-items: stretch; + gap: var(--space-2); + margin-top: calc(-1 * (var(--space-32) + var(--space-16))); + /* Move buttons higher up to stay inside hero */ + } + + .place-actions-bar button, + .place-actions-bar a { + min-width: auto; + max-width: none; + width: 100%; + } } \ No newline at end of file diff --git a/src/pages/RecommendationsPage.css b/src/pages/RecommendationsPage.css index 23952d24..d70485b9 100644 --- a/src/pages/RecommendationsPage.css +++ b/src/pages/RecommendationsPage.css @@ -49,7 +49,8 @@ } .filters-bar--open { - max-height: 200px; + max-height: 500px; + /* Increased for mobile to show Apply button */ opacity: 1; margin-top: var(--space-4); }