166 lines
No EOL
4.6 KiB
JavaScript
166 lines
No EOL
4.6 KiB
JavaScript
import { useState, useEffect, useRef } from 'react';
|
|
import { useAuth } from '../contexts/AuthContext';
|
|
import api from '../utils/api';
|
|
import TripList from './TripList';
|
|
import TripModal from './TripModal';
|
|
import ConfirmDialog from './ConfirmDialog';
|
|
|
|
const Dashboard = () => {
|
|
const { user, logout } = useAuth();
|
|
const [trips, setTrips] = useState([]);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [showTripModal, setShowTripModal] = useState(false);
|
|
const [selectedTrip, setSelectedTrip] = useState(null);
|
|
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
|
const [tripToDelete, setTripToDelete] = useState(null);
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
const [showUserDropdown, setShowUserDropdown] = useState(false);
|
|
const userDropdownRef = useRef(null);
|
|
|
|
useEffect(() => {
|
|
fetchTrips();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const handleClickOutside = (event) => {
|
|
if (userDropdownRef.current && !userDropdownRef.current.contains(event.target)) {
|
|
setShowUserDropdown(false);
|
|
}
|
|
};
|
|
|
|
document.addEventListener('mousedown', handleClickOutside);
|
|
return () => {
|
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
};
|
|
}, []);
|
|
|
|
const fetchTrips = async () => {
|
|
try {
|
|
setIsLoading(true);
|
|
const response = await api.get('/trips');
|
|
setTrips(response.data.data);
|
|
} catch (error) {
|
|
console.error('Error fetching trips:', error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleLogout = async () => {
|
|
await logout();
|
|
};
|
|
|
|
const handleCreateTrip = () => {
|
|
setSelectedTrip(null);
|
|
setShowTripModal(true);
|
|
};
|
|
|
|
const handleEditTrip = (trip) => {
|
|
setSelectedTrip(trip);
|
|
setShowTripModal(true);
|
|
};
|
|
|
|
const handleDeleteTrip = (trip) => {
|
|
setTripToDelete(trip);
|
|
setShowDeleteConfirm(true);
|
|
};
|
|
|
|
const handleTripSubmit = async (tripData) => {
|
|
setIsSubmitting(true);
|
|
try {
|
|
if (selectedTrip) {
|
|
const response = await api.put(`/trips/${selectedTrip.id}`, tripData);
|
|
setTrips(trips.map(trip =>
|
|
trip.id === selectedTrip.id ? response.data.data : trip
|
|
));
|
|
} else {
|
|
const response = await api.post('/trips', tripData);
|
|
setTrips([response.data.data, ...trips]);
|
|
}
|
|
setShowTripModal(false);
|
|
setSelectedTrip(null);
|
|
} catch (error) {
|
|
console.error('Error saving trip:', error);
|
|
throw error;
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
const confirmDeleteTrip = async () => {
|
|
try {
|
|
await api.delete(`/trips/${tripToDelete.id}`);
|
|
setTrips(trips.filter(trip => trip.id !== tripToDelete.id));
|
|
setShowDeleteConfirm(false);
|
|
setTripToDelete(null);
|
|
} catch (error) {
|
|
console.error('Error deleting trip:', error);
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="dashboard">
|
|
<header className="dashboard-header">
|
|
<div className="dashboard-title">
|
|
<h1>TripPlanner</h1>
|
|
</div>
|
|
<div className="user-info">
|
|
<span>Welcome back!</span>
|
|
<div className="user-dropdown" ref={userDropdownRef}>
|
|
<button
|
|
className="user-menu-trigger"
|
|
onClick={() => setShowUserDropdown(!showUserDropdown)}
|
|
>
|
|
{user?.name}
|
|
<span className="dropdown-arrow">▼</span>
|
|
</button>
|
|
{showUserDropdown && (
|
|
<div className="user-dropdown-menu">
|
|
<button onClick={handleLogout} className="dropdown-item">
|
|
🚪 Logout
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<main className="dashboard-content">
|
|
<TripList
|
|
trips={trips}
|
|
isLoading={isLoading}
|
|
onEdit={handleEditTrip}
|
|
onDelete={handleDeleteTrip}
|
|
onCreateTrip={handleCreateTrip}
|
|
/>
|
|
</main>
|
|
|
|
<TripModal
|
|
isOpen={showTripModal}
|
|
onClose={() => {
|
|
setShowTripModal(false);
|
|
setSelectedTrip(null);
|
|
}}
|
|
onSubmit={handleTripSubmit}
|
|
trip={selectedTrip}
|
|
isLoading={isSubmitting}
|
|
/>
|
|
|
|
<ConfirmDialog
|
|
isOpen={showDeleteConfirm}
|
|
onClose={() => {
|
|
setShowDeleteConfirm(false);
|
|
setTripToDelete(null);
|
|
}}
|
|
onConfirm={confirmDeleteTrip}
|
|
title="Delete Trip"
|
|
message={`Are you sure you want to delete "${tripToDelete?.name}"? This action cannot be undone.`}
|
|
confirmText="Delete"
|
|
variant="danger"
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Dashboard; |