trip-planner/frontend/src/components/TripDetail.jsx

121 lines
3.3 KiB
React
Raw Normal View History

import { useState, useEffect, useMemo } from 'react';
import { useParams, useNavigate, Link } from 'react-router-dom';
import { formatDate } from '../utils/dateFormatter';
import { useTrip } from '../hooks/useTrip';
import PlannablesList from './plannables/PlannablesList';
import TripTimeline from './timeline/TripTimeline';
import axios from 'axios';
import './TripDetail.css';
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000';
const TripDetail = () => {
const { id } = useParams();
const navigate = useNavigate();
const [trip, setTrip] = useState(null);
const [plannableItems, setPlannableItems] = useState([]);
const { fetchTrip, loading, error } = useTrip();
useEffect(() => {
const loadTrip = async () => {
try {
const tripData = await fetchTrip(id);
setTrip(tripData);
} catch (err) {
console.error('Error loading trip:', err);
}
};
loadTrip();
}, [id, fetchTrip]);
useEffect(() => {
const loadPlannableItems = async () => {
try {
const token = localStorage.getItem('token');
const response = await axios.get(`${API_URL}/api/trips/${id}/plannables`, {
headers: { Authorization: `Bearer ${token}` }
});
setPlannableItems(response.data.data || []);
} catch (err) {
console.error('Error loading plannable items:', err);
}
};
if (id) {
loadPlannableItems();
}
}, [id]);
// Memoize trip dates display to prevent unnecessary re-renders
const tripDatesDisplay = useMemo(() => {
if (!trip) return null;
return (
<div className="trip-dates">
<span className="date-label">Start:</span>
<span className="date-value">{formatDate(trip.start_date)}</span>
<span className="date-separator"></span>
<span className="date-label">End:</span>
<span className="date-value">{formatDate(trip.end_date)}</span>
</div>
);
}, [trip]);
if (loading) {
return (
<div className="trip-detail-loading">
<div className="spinner"></div>
<p>Loading trip details...</p>
</div>
);
}
if (error) {
return (
<div className="trip-detail-error">
<h2>Error</h2>
<p>{error}</p>
<Link to="/" className="btn-back">Back to Dashboard</Link>
</div>
);
}
if (!trip) {
return null;
}
return (
<div className="trip-detail">
<header className="trip-detail-header">
<div className="header-nav">
<Link to="/" className="btn-back"> Back to Dashboard</Link>
</div>
<div className="header-content">
<h1>{trip.name}</h1>
{trip.description && (
<p className="trip-description">{trip.description}</p>
)}
{tripDatesDisplay}
</div>
</header>
<div className="trip-detail-content">
<div className="trip-detail-sidebar">
<PlannablesList tripId={trip.id} onItemsChange={(items) => setPlannableItems(items)} />
</div>
<div className="trip-detail-main">
<TripTimeline
trip={trip}
plannableItems={plannableItems}
onScheduleSuccess={() => {
// Optional: refresh plannable items if needed
}}
/>
</div>
</div>
</div>
);
};
export default TripDetail;