Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions frontend/src/components/DiveSiteCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const DiveSiteListCard = ({
}) => {
return (
<div
className={`dive-item bg-white rounded-xl shadow-sm border border-gray-100 p-6 hover:shadow-md hover:-translate-y-1 transition-all duration-200 relative ${compactLayout ? 'p-4' : 'p-6'}`}
className={`dive-item bg-white rounded-xl shadow-sm border border-gray-100 border-l-4 border-l-[rgb(45,107,138)] p-6 hover:shadow-md hover:-translate-y-1 transition-all duration-200 relative ${compactLayout ? 'p-4' : 'p-6'}`}
>
<div className='flex gap-4 sm:gap-6'>
{site.thumbnail && (
Expand Down Expand Up @@ -245,7 +245,7 @@ export const DiveSiteGridCard = ({
handleFilterChange,
}) => {
return (
<div className='dive-item bg-white rounded-xl shadow-sm border border-gray-100 flex flex-col hover:shadow-md hover:-translate-y-1 transition-all duration-200 overflow-hidden'>
<div className='dive-item bg-white rounded-xl shadow-sm border border-gray-100 border-l-4 border-l-[rgb(45,107,138)] flex flex-col hover:shadow-md hover:-translate-y-1 transition-all duration-200 overflow-hidden'>
{site.thumbnail && (
<Link
to={getMediaLink(site)}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/DivingCentersDesktopSearchBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const DivingCentersDesktopSearchBar = ({
return (
<div
data-testid='diving-centers-desktop-search-bar'
className={`p-4 border-b border-gray-200 ${className}`}
className={`px-3 sm:px-4 mb-3 sm:mb-4 ${className}`}
>
<div className='max-w-2xl mx-auto'>
<FuzzySearchInput
Expand Down
22 changes: 11 additions & 11 deletions frontend/src/components/DivingCentersResponsiveFilterBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,30 +168,30 @@ const DivingCentersResponsiveFilterBar = ({
<div className='flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 sm:gap-4 p-4'>
{/* Quick Filters */}
{showQuickFilters && (
<div className='flex items-center gap-2 overflow-x-auto'>
<div className='flex items-center gap-2 sm:ml-2 w-full sm:w-auto justify-center sm:justify-end overflow-x-auto'>
{reviewsEnabled && (
<button
onClick={() => onQuickFilter('min_rating')}
className={`flex-shrink-0 px-3 py-2 text-sm rounded-lg transition-colors ${
className={`flex items-center gap-1 px-3 py-2 text-sm rounded-md transition-colors ${
quickFilter === 'min_rating'
? 'bg-blue-100 text-blue-700 border border-blue-300'
: 'bg-gray-100 text-gray-600 border border-gray-200 hover:bg-gray-200'
? 'bg-blue-100 text-blue-700 border border-blue-300 shadow-sm'
: 'bg-gray-50 text-gray-600 border border-gray-200 hover:bg-gray-100 active:bg-gray-200'
}`}
>
<Star className='h-4 w-4 inline mr-1' />
4+ Stars
<Star className='h-4 w-4' />
<span>4+ Stars</span>
</button>
)}
<button
onClick={() => onQuickFilter('country')}
className={`flex-shrink-0 px-3 py-2 text-sm rounded-lg transition-colors ${
className={`flex items-center gap-1 px-3 py-2 text-sm rounded-md transition-colors ${
quickFilter === 'country'
? 'bg-blue-100 text-blue-700 border border-blue-300'
: 'bg-gray-100 text-gray-600 border border-gray-200 hover:bg-gray-200'
? 'bg-blue-100 text-blue-700 border border-blue-300 shadow-sm'
: 'bg-gray-50 text-gray-600 border border-gray-200 hover:bg-gray-100 active:bg-gray-200'
}`}
>
<MapPin className='h-4 w-4 inline mr-1' />
Greece
<MapPin className='h-4 w-4' />
<span>Greece</span>
</button>
</div>
)}
Expand Down
21 changes: 17 additions & 4 deletions frontend/src/components/PageHeader.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import PropTypes from 'prop-types';
import React from 'react';

import Breadcrumbs from './Breadcrumbs';

Expand All @@ -9,16 +8,29 @@ import Breadcrumbs from './Breadcrumbs';
* A functional header for internal utility pages (Dives, Dive Sites, etc.)
* that replaces marketing-heavy heroes.
*/
const PageHeader = ({ title, breadcrumbItems = [], actions = [], className = '' }) => {
const PageHeader = ({
title,
titleIcon: TitleIcon,
breadcrumbItems = [],
actions = [],
className = '',
}) => {
return (
<div className={`mb-8 ${className}`}>
{/* Navigation Context */}
{breadcrumbItems.length > 0 && <Breadcrumbs items={breadcrumbItems} />}
{breadcrumbItems.length > 0 && (
<div className='mb-3 sm:mb-4'>
<Breadcrumbs items={breadcrumbItems} />
</div>
)}

<div className='flex flex-col lg:flex-row lg:items-center lg:justify-between gap-6'>
{/* Title Group */}
<div className='flex-1 min-w-0'>
<h1 className='text-3xl font-bold text-gray-900 tracking-tight'>{title}</h1>
<h1 className='text-3xl font-bold text-gray-900 tracking-tight flex items-center gap-3'>
{TitleIcon && <TitleIcon className='w-7 h-7 text-gray-700' aria-hidden='true' />}
<span>{title}</span>
</h1>
</div>

{/* Action Toolbar */}
Expand Down Expand Up @@ -71,6 +83,7 @@ const PageHeader = ({ title, breadcrumbItems = [], actions = [], className = ''

PageHeader.propTypes = {
title: PropTypes.string.isRequired,
titleIcon: PropTypes.elementType,
breadcrumbItems: PropTypes.array,
actions: PropTypes.arrayOf(
PropTypes.shape({
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/ResponsiveFilterBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ const ResponsiveFilterBar = ({
className={`flex items-center gap-2 px-4 py-2 rounded-lg transition-colors ${
showFilters
? 'bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800 shadow-sm'
: 'bg-gray-100 text-gray-700 hover:bg-gray-200 active:bg-gray-300'
: 'bg-blue-100 text-blue-700 hover:bg-blue-200 active:bg-blue-300'
}`}
>
<Filter className='h-4 w-4' />
Expand Down
13 changes: 6 additions & 7 deletions frontend/src/pages/DiveRoutes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { useState, useEffect, useCallback } from 'react';
import { useQuery } from 'react-query';
import { Link, useNavigate, useSearchParams } from 'react-router-dom';

import Breadcrumbs from '../components/Breadcrumbs';
import DesktopSearchBar from '../components/DesktopSearchBar';
import EmptyState from '../components/EmptyState';
import ErrorPage from '../components/ErrorPage';
Expand Down Expand Up @@ -146,11 +145,11 @@ const DiveRoutes = () => {
return (
<div className='min-h-screen bg-gray-50'>
<div className='max-w-[95vw] xl:max-w-[1600px] mx-auto px-3 sm:px-4 lg:px-6 xl:px-8 py-4 sm:py-6 lg:py-8'>
{/* Breadcrumbs */}
<Breadcrumbs items={[{ label: 'Dive Routes' }]} />

{/* Page Header */}
<PageHeader title='Dive Routes' actions={[]} />
<PageHeader
title='Dive Routes'
titleIcon={Route}
breadcrumbItems={[{ label: 'Dive Routes' }]}
/>

{/* Responsive Filter Bar */}
<div className='mb-8'>
Expand Down Expand Up @@ -344,7 +343,7 @@ const DiveRoutes = () => {
return (
<div
key={route.id}
className={`bg-white rounded-xl shadow-sm border border-gray-100 hover:shadow-md hover:-translate-y-1 transition-all duration-200 flex flex-col ${compactLayout ? 'p-4' : 'p-6'}`}
className={`bg-white rounded-xl shadow-sm border border-gray-100 border-l-4 border-l-[rgb(45,107,138)] hover:shadow-md hover:-translate-y-1 transition-all duration-200 flex flex-col ${compactLayout ? 'p-4' : 'p-6'}`}
>
{/* Header: Title & Type */}
<div className='mb-2'>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/pages/DiveSites.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,7 @@ const DiveSites = () => {
<div className='max-w-[95vw] xl:max-w-[1600px] mx-auto px-3 sm:px-4 lg:px-6 xl:px-8 py-4 sm:py-6 lg:py-8'>
<PageHeader
title='Dive Sites'
titleIcon={Map}
breadcrumbItems={[{ label: 'Dive Sites' }]}
actions={[
{
Expand Down
58 changes: 25 additions & 33 deletions frontend/src/pages/DiveTrips.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { Link, useNavigate, useSearchParams, useLocation } from 'react-router-do

import DesktopSearchBar from '../components/DesktopSearchBar';
import FuzzySearchInput from '../components/FuzzySearchInput';
import HeroSection from '../components/HeroSection';
import PageHeader from '../components/PageHeader';
import RateLimitError from '../components/RateLimitError';
import ResponsiveFilterBar from '../components/ResponsiveFilterBar';
import { useAuth } from '../contexts/AuthContext';
Expand Down Expand Up @@ -673,37 +673,29 @@ const DiveTrips = () => {
<div className='min-h-screen bg-gray-50'>
{/* Mobile-First Responsive Container */}
<div className='max-w-[95vw] xl:max-w-[1600px] mx-auto px-3 sm:px-4 lg:px-6 xl:px-8 py-4 sm:py-6 lg:py-8'>
{/* Hero Section */}
<HeroSection
<PageHeader
title='Dive Trips'
subtitle='Discover upcoming dive trips from local diving centers'
background='ocean'
size='large'
showLogo={false}
logoBackground={true}
threeColumnLayout={true}
>
<div className='flex flex-col justify-center gap-3 sm:flex-row sm:gap-36'>
<button
onClick={() => {
navigate('/map?type=dive-trips');
}}
className='bg-blue-600 hover:bg-blue-700 text-white px-12 py-2 text-sm sm:text-base font-semibold min-w-[200px] whitespace-nowrap rounded-lg flex items-center gap-2 transition-all duration-200 hover:scale-105'
>
<Compass className='w-5 h-5' />
Explore Map
</button>
{user && (
<button
onClick={() => navigate('/dive-trips/create')}
className='bg-green-600 hover:bg-green-700 text-white px-12 py-2 text-sm sm:text-base font-semibold min-w-[200px] whitespace-nowrap rounded-lg flex items-center gap-2 transition-all duration-200 hover:scale-105'
>
<Plus size={20} />
Create Trip
</button>
)}
</div>
</HeroSection>
titleIcon={Calendar}
breadcrumbItems={[{ label: 'Dive Trips' }]}
actions={[
{
label: 'Explore Map',
icon: Compass,
onClick: () => navigate('/map?type=dive-trips'),
variant: 'primary',
},
...(user
? [
{
label: 'Create Trip',
icon: Plus,
onClick: () => navigate('/dive-trips/create'),
variant: 'secondary',
},
]
: []),
]}
/>

{/* Desktop Search Bar - Only visible on desktop/tablet and for authenticated users */}
{!isMobile && user && (
Expand Down Expand Up @@ -986,7 +978,7 @@ const DiveTrips = () => {
return (
<div
key={trip.id}
className={`dive-item bg-white rounded-lg shadow-sm border border-gray-200 p-6 transition-shadow ${
className={`dive-item bg-white rounded-lg shadow-sm border border-gray-200 border-l-4 border-l-[rgb(45,107,138)] p-6 transition-shadow ${
compactLayout ? 'p-4' : 'p-6'
} ${
isBlurred ? 'pointer-events-none relative overflow-hidden' : 'hover:shadow-md'
Expand Down Expand Up @@ -1357,7 +1349,7 @@ const DiveTrips = () => {
return (
<div
key={trip.id}
className={`dive-item bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden transition-shadow ${
className={`dive-item bg-white rounded-lg shadow-sm border border-gray-200 border-l-4 border-l-[rgb(45,107,138)] overflow-hidden transition-shadow ${
compactLayout ? 'p-4' : 'p-6'
} ${isBlurred ? 'pointer-events-none relative' : 'hover:shadow-md'}`}
style={
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/pages/Dives.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ import {
MessageCircle,
Globe,
MapPin,
Anchor,
} from 'lucide-react';
import { useState, useEffect, useCallback, lazy, Suspense } from 'react';
import { toast } from 'react-hot-toast';
import { useQuery, useMutation, useQueryClient } from 'react-query';
import { Link, useNavigate, useSearchParams, useLocation } from 'react-router-dom';

import api from '../api';
import Breadcrumbs from '../components/Breadcrumbs';
import DesktopSearchBar from '../components/DesktopSearchBar';
import EmptyState from '../components/EmptyState';
import ErrorPage from '../components/ErrorPage';
Expand Down Expand Up @@ -909,6 +909,7 @@ const Dives = () => {
<div className='max-w-[95vw] xl:max-w-[1600px] mx-auto px-3 sm:px-4 lg:px-6 xl:px-8 py-4 sm:py-6 lg:py-8'>
<PageHeader
title='Dive Log'
titleIcon={Anchor}
breadcrumbItems={[{ label: 'Dive Log' }]}
actions={[
{
Expand Down Expand Up @@ -1060,7 +1061,7 @@ const Dives = () => {
{dives?.map(dive => (
<div
key={dive.id}
className={`dive-item rounded-xl shadow-sm border border-gray-100 p-6 hover:shadow-md hover:-translate-y-1 transition-all duration-200 ${
className={`dive-item rounded-xl shadow-sm border border-gray-100 border-l-4 border-l-[rgb(45,107,138)] p-6 hover:shadow-md hover:-translate-y-1 transition-all duration-200 ${
dive.is_private ? 'bg-purple-50/30' : 'bg-white'
} ${compactLayout ? 'p-4' : 'p-6'}`}
>
Expand Down Expand Up @@ -1308,7 +1309,7 @@ const Dives = () => {
{dives?.map(dive => (
<div
key={dive.id}
className={`dive-item rounded-xl shadow-sm border border-gray-100 flex flex-col hover:shadow-md hover:-translate-y-1 transition-all duration-200 ${
className={`dive-item rounded-xl shadow-sm border border-gray-100 border-l-4 border-l-[rgb(45,107,138)] flex flex-col hover:shadow-md hover:-translate-y-1 transition-all duration-200 ${
dive.is_private ? 'bg-purple-50/30' : 'bg-white'
}`}
>
Expand Down
Loading
Loading