- navigate('/')}
- >
+
+
+
Planventure
-
- {isAuthenticated ? (
- <>
-
-
- >
- ) : (
- <>
-
-
- >
- )}
-
+
);
diff --git a/planventure-client/src/components/overview/AccommodationCard.jsx b/planventure-client/src/components/overview/AccommodationCard.jsx
deleted file mode 100644
index d890064..0000000
--- a/planventure-client/src/components/overview/AccommodationCard.jsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import {
- Card,
- CardContent,
- Typography,
- Box,
- IconButton,
- Button,
- TextField,
- Stack,
- Collapse
-} from '@mui/material';
-import {
- Edit as EditIcon,
- Delete as DeleteIcon,
- Save as SaveIcon,
- Cancel as CancelIcon,
- Hotel as HotelIcon
-} from '@mui/icons-material';
-import { useState } from 'react';
-
-const AccommodationCard = ({ accommodation, onUpdate, onDelete }) => {
- const [isEditing, setIsEditing] = useState(false);
- const [editedData, setEditedData] = useState(accommodation);
-
- const handleSave = () => {
- onUpdate(editedData);
- setIsEditing(false);
- };
-
- if (isEditing) {
- return (
-
-
-
- setEditedData({ ...editedData, name: e.target.value })}
- />
- setEditedData({ ...editedData, address: e.target.value })}
- />
- setEditedData({ ...editedData, checkIn: e.target.value })}
- InputLabelProps={{ shrink: true }}
- />
- setEditedData({ ...editedData, checkOut: e.target.value })}
- InputLabelProps={{ shrink: true }}
- />
- setEditedData({ ...editedData, bookingRef: e.target.value })}
- />
-
- } onClick={() => setIsEditing(false)}>
- Cancel
-
- } variant="contained" onClick={handleSave}>
- Save
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
-
- {accommodation.name}
-
-
- {accommodation.address}
-
-
- Check-in: {new Date(accommodation.checkIn).toLocaleString()}
-
-
- Check-out: {new Date(accommodation.checkOut).toLocaleString()}
-
- {accommodation.bookingRef && (
-
- Booking Reference: {accommodation.bookingRef}
-
- )}
-
-
- setIsEditing(true)}>
-
-
- onDelete(accommodation.id)} color="error">
-
-
-
-
-
-
- );
-};
-
-export default AccommodationCard;
diff --git a/planventure-client/src/components/overview/EmptyOverviewSection.jsx b/planventure-client/src/components/overview/EmptyOverviewSection.jsx
deleted file mode 100644
index 92ef903..0000000
--- a/planventure-client/src/components/overview/EmptyOverviewSection.jsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import {
- Box,
- Typography,
- Button,
- Paper
-} from '@mui/material';
-import { Add as AddIcon } from '@mui/icons-material';
-
-const EmptyOverviewSection = ({ title, description, onAdd }) => {
- return (
-
-
- No {title} Added Yet
-
-
- {description}
-
- }
- onClick={onAdd}
- >
- Add {title}
-
-
- );
-};
-
-export default EmptyOverviewSection;
diff --git a/planventure-client/src/components/overview/TransportationCard.jsx b/planventure-client/src/components/overview/TransportationCard.jsx
deleted file mode 100644
index 0a9b412..0000000
--- a/planventure-client/src/components/overview/TransportationCard.jsx
+++ /dev/null
@@ -1,131 +0,0 @@
-import {
- Card,
- CardContent,
- Typography,
- Box,
- IconButton,
- Button,
- TextField,
- Stack,
- MenuItem
-} from '@mui/material';
-import {
- Edit as EditIcon,
- Delete as DeleteIcon,
- Save as SaveIcon,
- Cancel as CancelIcon
-} from '@mui/icons-material';
-import { useState } from 'react';
-
-const TransportationCard = ({ transport, onUpdate, onDelete }) => {
- const [isEditing, setIsEditing] = useState(false);
- const [editedData, setEditedData] = useState(transport);
-
- const handleSave = () => {
- onUpdate(editedData);
- setIsEditing(false);
- };
-
- if (isEditing) {
- return (
-
-
-
- setEditedData({ ...editedData, type: e.target.value })}
- >
-
-
-
-
-
- setEditedData({ ...editedData, from: e.target.value })}
- />
- setEditedData({ ...editedData, to: e.target.value })}
- />
- setEditedData({ ...editedData, departure: e.target.value })}
- InputLabelProps={{ shrink: true }}
- />
- setEditedData({ ...editedData, arrival: e.target.value })}
- InputLabelProps={{ shrink: true }}
- />
- setEditedData({ ...editedData, bookingRef: e.target.value })}
- />
-
- } onClick={() => setIsEditing(false)}>
- Cancel
-
- } variant="contained" onClick={handleSave}>
- Save
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
-
- {transport.type.charAt(0).toUpperCase() + transport.type.slice(1)}
-
-
- {transport.from} → {transport.to}
-
-
- Departure: {new Date(transport.departure).toLocaleString()}
-
-
- Arrival: {new Date(transport.arrival).toLocaleString()}
-
- {transport.bookingRef && (
-
- Booking Reference: {transport.bookingRef}
-
- )}
-
-
- setIsEditing(true)}>
-
-
- onDelete(transport.id)} color="error">
-
-
-
-
-
-
- );
-};
-
-export default TransportationCard;
diff --git a/planventure-client/src/components/routing/ProtectedRoute.jsx b/planventure-client/src/components/routing/ProtectedRoute.jsx
index b5ee8c5..7158242 100644
--- a/planventure-client/src/components/routing/ProtectedRoute.jsx
+++ b/planventure-client/src/components/routing/ProtectedRoute.jsx
@@ -1,23 +1,11 @@
import { Navigate, useLocation } from 'react-router-dom';
import { useAuth } from '../../context/AuthContext';
-import { CircularProgress } from '@mui/material';
const ProtectedRoute = ({ children }) => {
- const { isAuthenticated, loading } = useAuth();
+ const { isAuthenticated, token } = useAuth();
const location = useLocation();
- console.log('ProtectedRoute - Auth State:', { isAuthenticated, loading });
-
- if (loading) {
- return (
-
-
-
- );
- }
-
- if (!isAuthenticated) {
- console.log('Not authenticated, redirecting to login...');
+ if (!isAuthenticated || !token) {
return ;
}
diff --git a/planventure-client/src/components/trips/EditTripForm.jsx b/planventure-client/src/components/trips/EditTripForm.jsx
deleted file mode 100644
index bdb7cff..0000000
--- a/planventure-client/src/components/trips/EditTripForm.jsx
+++ /dev/null
@@ -1,173 +0,0 @@
-import { useState, useEffect } from 'react';
-import {
- Box,
- TextField,
- Button,
- Typography,
- Alert,
- Paper
-} from '@mui/material';
-import { DatePicker } from '@mui/x-date-pickers/DatePicker';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import dayjs from 'dayjs';
-import { useNavigate } from 'react-router-dom';
-import { tripService } from '../../services/tripService';
-
-const EditTripForm = ({ trip }) => {
- const navigate = useNavigate();
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState('');
- const [formData, setFormData] = useState({
- title: trip?.title || '',
- destination: trip?.destination || '',
- startDate: trip?.start_date ? dayjs(trip.start_date) : dayjs(),
- endDate: trip?.end_date ? dayjs(trip.end_date) : dayjs().add(1, 'day')
- });
-
- // Add useEffect to update form data when trip prop changes
- useEffect(() => {
- if (trip) {
- setFormData({
- title: trip.title || '',
- destination: trip.destination || '',
- startDate: dayjs(trip.start_date),
- endDate: dayjs(trip.end_date)
- });
- }
- }, [trip]);
-
- const handleSubmit = async (e) => {
- e.preventDefault();
- setLoading(true);
- setError('');
-
- try {
- const tripData = {
- title: formData.title,
- destination: formData.destination,
- start_date: formData.startDate.format('YYYY-MM-DD'),
- end_date: formData.endDate.format('YYYY-MM-DD'),
- };
-
- await tripService.updateTrip(trip.id, tripData);
- navigate(`/trips/${trip.id}`);
- } catch (err) {
- setError(err.message || 'Failed to update trip');
- } finally {
- setLoading(false);
- }
- };
-
- const handleChange = (e) => {
- const { name, value } = e.target;
- setFormData(prev => ({
- ...prev,
- [name]: value
- }));
- };
-
- const isDateRangeValid = () => {
- return formData.endDate.isAfter(formData.startDate) ||
- formData.endDate.isSame(formData.startDate);
- };
-
- const isFormValid = () => {
- return formData.title?.trim() &&
- formData.destination?.trim() &&
- isDateRangeValid() &&
- !loading;
- };
-
- return (
-
-
-
- Edit Trip
-
-
- {error && (
-
- {error}
-
- )}
-
-
-
-
-
-
- {
- setFormData(prev => ({ ...prev, startDate: newValue }));
- }}
- slotProps={{
- textField: { fullWidth: true }
- }}
- />
-
- {
- setFormData(prev => ({ ...prev, endDate: newValue }));
- }}
- minDate={formData.startDate}
- slotProps={{
- textField: {
- fullWidth: true,
- error: !isDateRangeValid(),
- helperText: !isDateRangeValid() ? 'End date must be after start date' : ''
- }
- }}
- />
-
-
-
-
-
-
-
-
- );
-};
-
-export default EditTripForm;
diff --git a/planventure-client/src/components/trips/NewTripForm.jsx b/planventure-client/src/components/trips/NewTripForm.jsx
deleted file mode 100644
index f7855a9..0000000
--- a/planventure-client/src/components/trips/NewTripForm.jsx
+++ /dev/null
@@ -1,163 +0,0 @@
-import { useState } from 'react';
-import {
- Box,
- TextField,
- Button,
- Typography,
- Alert,
- Paper
-} from '@mui/material';
-import { DatePicker } from '@mui/x-date-pickers/DatePicker';
-import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
-import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
-import dayjs from 'dayjs';
-import { useNavigate } from 'react-router-dom';
-import { tripService } from '../../services/tripService';
-
-const NewTripForm = () => {
- const navigate = useNavigate();
- const [loading, setLoading] = useState(false);
- const [error, setError] = useState('');
- const [formData, setFormData] = useState({
- title: '',
- destination: '',
- startDate: dayjs(),
- endDate: dayjs().add(7, 'day')
- });
-
- const handleSubmit = async (e) => {
- e.preventDefault();
- setLoading(true);
- setError('');
-
- try {
- const tripData = {
- title: formData.title,
- destination: formData.destination,
- start_date: formData.startDate.format('YYYY-MM-DD'),
- end_date: formData.endDate.format('YYYY-MM-DD'),
- status: 'Upcoming'
- };
-
- const response = await tripService.createTrip(tripData);
- navigate('/dashboard');
- } catch (err) {
- setError(err.message || 'Failed to create trip');
- } finally {
- setLoading(false);
- }
- };
-
- const handleChange = (e) => {
- const { name, value } = e.target;
- setFormData(prev => ({
- ...prev,
- [name]: value
- }));
- };
-
- const isDateRangeValid = () => {
- return formData.endDate.isAfter(formData.startDate) ||
- formData.endDate.isSame(formData.startDate);
- };
-
- const isFormValid = () => {
- return formData.title &&
- formData.destination &&
- isDateRangeValid() &&
- !loading;
- };
-
- return (
-
-
-
- Plan a New Trip
-
-
- {error && (
-
- {error}
-
- )}
-
-
-
-
-
-
- {
- setFormData(prev => ({ ...prev, startDate: newValue }));
- }}
- minDate={dayjs()}
- slotProps={{
- textField: { fullWidth: true }
- }}
- />
-
- {
- setFormData(prev => ({ ...prev, endDate: newValue }));
- }}
- minDate={formData.startDate}
- slotProps={{
- textField: {
- fullWidth: true,
- error: !isDateRangeValid(),
- helperText: !isDateRangeValid() ? 'End date must be after start date' : ''
- }
- }}
- />
-
-
-
-
-
-
-
-
- );
-};
-
-export default NewTripForm;
diff --git a/planventure-client/src/components/trips/TripCard.jsx b/planventure-client/src/components/trips/TripCard.jsx
deleted file mode 100644
index be94f4d..0000000
--- a/planventure-client/src/components/trips/TripCard.jsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import {
- Card,
- CardContent,
- CardMedia,
- Typography,
- CardActions,
- Button,
- Chip,
- Box,
- Skeleton
-} from '@mui/material';
-import {
- LocationOn,
- DateRange,
- ArrowForward
-} from '@mui/icons-material';
-import { useNavigate } from 'react-router-dom';
-
-const TripCard = ({ trip, loading }) => {
- const navigate = useNavigate();
-
- if (loading) {
- return (
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-
- return (
-
-
-
- {trip.title}
-
-
-
-
- {trip.destination}
-
-
-
-
-
- {new Date(trip.start_date).toLocaleDateString()} - {new Date(trip.end_date).toLocaleDateString()}
-
-
-
-
- }
- onClick={() => navigate(`/trips/${trip.id}`)}
- >
- View Details
-
-
-
- );
-};
-
-export default TripCard;
diff --git a/planventure-client/src/components/trips/TripList.jsx b/planventure-client/src/components/trips/TripList.jsx
deleted file mode 100644
index 15be031..0000000
--- a/planventure-client/src/components/trips/TripList.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import { useState, useEffect } from 'react';
-import {
- Grid,
- Typography,
- Box,
- Alert,
- Button
-} from '@mui/material';
-import { Add as AddIcon } from '@mui/icons-material';
-import TripCard from './TripCard';
-import { useNavigate } from 'react-router-dom';
-import { tripService } from '../../services/tripService';
-
-const TripList = ({ WelcomeMessage, ErrorState }) => {
- const [trips, setTrips] = useState([]);
- const [loading, setLoading] = useState(true);
- const [error, setError] = useState(null);
- const navigate = useNavigate();
-
- useEffect(() => {
- const fetchTrips = async () => {
- try {
- setLoading(true);
- const data = await tripService.getAllTrips();
- console.log('TripList received data:', data); // Debug log
-
- if (!data || !data.trips) {
- console.error('Invalid data format:', data);
- setError('Unexpected data format received');
- return;
- }
-
- setTrips(data.trips);
- } catch (err) {
- console.error('TripList error:', err);
- setError(err.message);
- } finally {
- setLoading(false);
- }
- };
-
- fetchTrips();
- }, []);
-
- // Loading state with skeleton cards
- if (loading) {
- return (
-
- {[1, 2, 3].map((skeleton) => (
-
-
-
- ))}
-
- );
- }
-
- // Error state
- if (error) {
- return ;
- }
-
- // Empty state
- if (trips.length === 0) {
- return ;
- }
-
- // Loaded state with trips
- return (
-
- {trips.map((trip) => (
-
-
-
- ))}
-
-
-
-
- );
-};
-
-export default TripList;
diff --git a/planventure-client/src/context/AuthContext.jsx b/planventure-client/src/context/AuthContext.jsx
index fdfabc8..be58f12 100644
--- a/planventure-client/src/context/AuthContext.jsx
+++ b/planventure-client/src/context/AuthContext.jsx
@@ -1,48 +1,15 @@
-import { createContext, useContext, useState, useEffect } from 'react';
+import { createContext, useContext, useState } from 'react';
const AuthContext = createContext(null);
export const AuthProvider = ({ children }) => {
const [isAuthenticated, setIsAuthenticated] = useState(false);
- const [token, setToken] = useState(null);
- const [loading, setLoading] = useState(true);
-
- useEffect(() => {
- // Check for token in localStorage on initial load
- const storedToken = localStorage.getItem('token');
- if (storedToken) {
- setToken(storedToken);
- setIsAuthenticated(true);
- }
- setLoading(false);
- }, []);
-
- const login = (authData) => {
- // Handle the new response structure
- const token = authData.token;
- localStorage.setItem('token', token);
- setToken(token);
- setIsAuthenticated(true);
- };
-
- const logout = () => {
- localStorage.removeItem('token');
- setToken(null);
- setIsAuthenticated(false);
- };
const value = {
isAuthenticated,
- token,
- loading,
- login,
- logout
+ setIsAuthenticated
};
- if (loading) {
- return null; // or a loading spinner
- }
-
return {children};
};
diff --git a/planventure-client/src/data/itineraryTemplates.js b/planventure-client/src/data/itineraryTemplates.js
deleted file mode 100644
index e463561..0000000
--- a/planventure-client/src/data/itineraryTemplates.js
+++ /dev/null
@@ -1,18 +0,0 @@
-export const defaultTemplate = {
- activity: [
- { time: '09:00', activity: 'Breakfast', type: 'food' },
- { time: '10:00', activity: 'Morning Activity', type: 'activity' },
- { time: '12:30', activity: 'Lunch', type: 'food' },
- { time: '14:00', activity: 'Afternoon Activity', type: 'activity' },
- { time: '16:00', activity: 'Free Time / Rest', type: 'activity' },
- { time: '19:00', activity: 'Dinner', type: 'food' }
- ]
-};
-
-export const generateTemplateForDate = (date) => {
- return defaultTemplate.activity.map(item => ({
- ...item,
- id: `${date}-${Date.now()}-${Math.random()}`,
- location: ''
- }));
-};
diff --git a/planventure-client/src/layouts/AuthLayout.jsx b/planventure-client/src/layouts/AuthLayout.jsx
deleted file mode 100644
index eda5865..0000000
--- a/planventure-client/src/layouts/AuthLayout.jsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import { Box, Container } from '@mui/material';
-import Navbar from '../components/navigation/Navbar';
-import Footer from '../components/navigation/Footer';
-
-const AuthLayout = ({ children }) => {
- return (
-
-
-
-
- {children}
-
-
-
-
- );
-};
-
-export default AuthLayout;
\ No newline at end of file
diff --git a/planventure-client/src/layouts/DashboardLayout.jsx b/planventure-client/src/layouts/DashboardLayout.jsx
deleted file mode 100644
index dd681ed..0000000
--- a/planventure-client/src/layouts/DashboardLayout.jsx
+++ /dev/null
@@ -1,167 +0,0 @@
-import { useState } from 'react';
-import {
- Box,
- Drawer,
- List,
- ListItem,
- ListItemButton,
- ListItemIcon,
- ListItemText,
- IconButton,
- useTheme,
- useMediaQuery,
- Divider,
- Typography
-} from '@mui/material';
-import {
- Menu as MenuIcon,
- Dashboard as DashboardIcon,
- Map as MapIcon,
- ListAlt as ListAltIcon,
- Settings as SettingsIcon,
- ChevronLeft as ChevronLeftIcon
-} from '@mui/icons-material';
-import { useNavigate, useLocation } from 'react-router-dom';
-import Navbar from '../components/navigation/Navbar';
-
-const DRAWER_WIDTH = 240;
-
-const menuItems = [
- { text: 'Dashboard', icon: , path: '/dashboard' },
- { text: 'My Trips', icon: , path: '/trips' },
- { text: 'Trip Planner', icon: , path: '/planner' },
- { text: 'Settings', icon: , path: '/settings' },
-];
-
-const DashboardLayout = ({ children }) => {
- const [mobileOpen, setMobileOpen] = useState(false);
- const theme = useTheme();
- const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
- const navigate = useNavigate();
- const location = useLocation();
-
- const handleDrawerToggle = () => {
- setMobileOpen(!mobileOpen);
- };
-
- const drawer = (
-
-
-
- Planventure
-
- {isMobile && (
-
-
-
- )}
-
-
-
- {menuItems.map((item) => (
- {
- navigate(item.path);
- if (isMobile) handleDrawerToggle();
- }}
- selected={location.pathname === item.path}
- sx={{
- '&.Mui-selected': {
- backgroundColor: 'primary.light',
- '&:hover': {
- backgroundColor: 'primary.light',
- },
- },
- }}
- >
-
- {item.icon}
-
-
-
- ))}
-
-
- );
-
- return (
-
-
-
-
-
-
-
-
- {/* Mobile drawer */}
-
- {drawer}
-
-
- {/* Desktop drawer */}
-
- {drawer}
-
-
-
-
- {children}
-
-
- );
-};
-
-export default DashboardLayout;
diff --git a/planventure-client/src/pages/Dashboard.jsx b/planventure-client/src/pages/Dashboard.jsx
deleted file mode 100644
index 026fc07..0000000
--- a/planventure-client/src/pages/Dashboard.jsx
+++ /dev/null
@@ -1,112 +0,0 @@
-import { useNavigate } from 'react-router-dom';
-import { Box, Typography, Grid, Paper, Button } from '@mui/material';
-import { Add as AddIcon } from '@mui/icons-material';
-import TripList from '../components/trips/TripList';
-import { useAuth } from '../context/AuthContext';
-import travelingSvg from '../assets/undraw_traveling_yhxq.svg';
-
-const Dashboard = () => {
- const { user } = useAuth();
-const navigate = useNavigate();
-
- const WelcomeMessage = () => (
-
-
-
- Welcome to Planventure!
-
-
- Ready to start planning your next adventure? Create your first trip and let us help you organize everything from destinations to activities.
-
- }
- onClick={() => navigate('/trips/new')}
- >
- Plan Your First Trip
-
-
- );
-
- const ErrorState = () => (
-
-
-
- Oops! Looks like our compass is spinning! 🧭
-
-
- We're having trouble loading your adventures. Don't worry, even the best travelers sometimes lose their way! Try refreshing the page or come back later.
-
-
-
- );
-
- return (
-
-
- My Trips
-
-
-
-
-
- );
-};
-
-export default Dashboard;
diff --git a/planventure-client/src/pages/EditTripPage.jsx b/planventure-client/src/pages/EditTripPage.jsx
deleted file mode 100644
index 939bc4b..0000000
--- a/planventure-client/src/pages/EditTripPage.jsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { useState, useEffect } from 'react';
-import { useParams, useNavigate } from 'react-router-dom';
-import { Box, Alert, Button, Skeleton } from '@mui/material';
-import EditTripForm from '../components/trips/EditTripForm';
-import { tripService } from '../services/tripService';
-
-const EditTripPage = () => {
- const { tripId } = useParams();
- const navigate = useNavigate();
- const [trip, setTrip] = useState(null);
- const [loading, setLoading] = useState(true);
- const [error, setError] = useState(null);
-
- useEffect(() => {
- const fetchTrip = async () => {
- try {
- const response = await tripService.getTrip(tripId);
- if (!response || !response.trip) {
- throw new Error('Trip not found');
- }
- setTrip(response.trip);
- } catch (err) {
- setError(err.message);
- } finally {
- setLoading(false);
- }
- };
-
- fetchTrip();
- }, [tripId]);
-
- if (loading) {
- return (
-
-
-
- );
- }
-
- if (error) {
- return (
-
- navigate('/dashboard')}>
- Back to Dashboard
-
- }
- >
- {error}
-
-
- );
- }
-
- if (!trip) {
- return null;
- }
-
- return ;
-};
-
-export default EditTripPage;
diff --git a/planventure-client/src/pages/Home.jsx b/planventure-client/src/pages/Home.jsx
index c9a6684..f115ebb 100644
--- a/planventure-client/src/pages/Home.jsx
+++ b/planventure-client/src/pages/Home.jsx
@@ -1,10 +1,7 @@
-import { Box, Button, Container, Typography } from '@mui/material';
-import { useNavigate } from 'react-router-dom';
+import { Box, Typography, Container } from '@mui/material';
import planventureLogo from '../assets/planventure-logo.svg';
const Home = () => {
- const navigate = useNavigate();
-
return (
{
>
Your next adventure begins here. Start planning unforgettable trips with our intuitive planning tools and make every journey memorable.
-
);
diff --git a/planventure-client/src/pages/LoginPage.jsx b/planventure-client/src/pages/LoginPage.jsx
deleted file mode 100644
index e55f63d..0000000
--- a/planventure-client/src/pages/LoginPage.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import AuthLayout from '../layouts/AuthLayout';
-import LoginForm from '../components/auth/LoginForm';
-
-const LoginPage = () => {
- return (
-
-
-
- );
-};
-
-export default LoginPage;
diff --git a/planventure-client/src/pages/NewTripPage.jsx b/planventure-client/src/pages/NewTripPage.jsx
deleted file mode 100644
index 096aca4..0000000
--- a/planventure-client/src/pages/NewTripPage.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { Container } from '@mui/material';
-import NewTripForm from '../components/trips/NewTripForm';
-
-const NewTripPage = () => {
- return (
-
-
-
- );
-};
-
-export default NewTripPage;
diff --git a/planventure-client/src/pages/SignupPage.jsx b/planventure-client/src/pages/SignupPage.jsx
deleted file mode 100644
index 275efc5..0000000
--- a/planventure-client/src/pages/SignupPage.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import AuthLayout from '../layouts/AuthLayout';
-import SignupForm from '../components/auth/SignupForm';
-
-const SignUpPage = () => {
- return (
-
-
-
- );
-};
-
-export default SignUpPage;
\ No newline at end of file
diff --git a/planventure-client/src/pages/TripDetailsPage.jsx b/planventure-client/src/pages/TripDetailsPage.jsx
deleted file mode 100644
index d085007..0000000
--- a/planventure-client/src/pages/TripDetailsPage.jsx
+++ /dev/null
@@ -1,347 +0,0 @@
-import { useState, useEffect } from 'react';
-import { useParams, useNavigate } from 'react-router-dom';
-import {
- Box,
- Paper,
- Typography,
- Tabs,
- Tab,
- Button,
- Skeleton,
- Alert,
- Chip,
- Stack,
- Divider
-} from '@mui/material';
-import {
- AccessTime,
- LocationOn,
- Edit as EditIcon,
- ArrowBack as ArrowBackIcon
-} from '@mui/icons-material';
-import { tripService } from '../services/tripService';
-import dayjs from 'dayjs';
-import ItineraryDay from '../components/itinerary/ItineraryDay';
-import { generateTemplateForDate } from '../data/itineraryTemplates';
-import EmptyItinerary from '../components/itinerary/EmptyItinerary';
-import AccommodationCard from '../components/overview/AccommodationCard';
-import TransportationCard from '../components/overview/TransportationCard';
-import EmptyOverviewSection from '../components/overview/EmptyOverviewSection';
-import { Add as AddIcon } from '@mui/icons-material';
-
-const TabPanel = ({ children, value, index }) => (
-
- {value === index && children}
-
-);
-
-const TripDetailsPage = () => {
- const { tripId } = useParams();
- const navigate = useNavigate();
- const [trip, setTrip] = useState(null);
- const [loading, setLoading] = useState(true);
- const [error, setError] = useState(null);
- const [tabValue, setTabValue] = useState(0);
- const [itinerary, setItinerary] = useState({});
- const [accommodations, setAccommodations] = useState([]);
- const [transportation, setTransportation] = useState([]);
-
- useEffect(() => {
- const fetchTripDetails = async () => {
- try {
- setLoading(true);
- const response = await tripService.getTrip(tripId);
- console.log('TripDetailsPage received:', response);
-
- if (!response || !response.trip) {
- throw new Error('Trip not found');
- }
-
- setTrip(response.trip);
- } catch (err) {
- console.error('Error fetching trip:', err);
- setError(err.message || 'Failed to load trip details');
- } finally {
- setLoading(false);
- }
- };
-
- if (tripId) {
- fetchTripDetails();
- }
- }, [tripId]);
-
- const handleTabChange = (event, newValue) => {
- setTabValue(newValue);
- };
-
- const handleAddSlot = (date, newSlot) => {
- setItinerary(prev => ({
- ...prev,
- [date]: [...(prev[date] || []), newSlot]
- }));
- };
-
- const handleUpdateSlot = (date, updatedSlot) => {
- setItinerary(prev => ({
- ...prev,
- [date]: prev[date].map(slot =>
- slot.id === updatedSlot.id ? updatedSlot : slot
- )
- }));
- };
-
- const handleDeleteSlot = (date, slotId) => {
- setItinerary(prev => ({
- ...prev,
- [date]: prev[date].filter(slot => slot.id !== slotId)
- }));
- };
-
- const handleCreateEmptyItinerary = () => {
- const dates = getDatesArray(trip.start_date, trip.end_date);
- const emptyItinerary = dates.reduce((acc, date) => {
- acc[date] = [];
- return acc;
- }, {});
- setItinerary(emptyItinerary);
- };
-
- const handleUseTemplate = () => {
- const dates = getDatesArray(trip.start_date, trip.end_date);
- const templateItinerary = dates.reduce((acc, date) => {
- acc[date] = generateTemplateForDate(date);
- return acc;
- }, {});
- setItinerary(templateItinerary);
- };
-
- const handleAddAccommodation = () => {
- const newAccommodation = {
- id: Date.now(),
- name: '',
- address: '',
- checkIn: new Date().toISOString().slice(0, 16),
- checkOut: new Date().toISOString().slice(0, 16),
- bookingRef: ''
- };
- setAccommodations([...accommodations, newAccommodation]);
- };
-
- const handleAddTransportation = () => {
- const newTransport = {
- id: Date.now(),
- type: 'flight',
- from: '',
- to: '',
- departure: new Date().toISOString().slice(0, 16),
- arrival: new Date().toISOString().slice(0, 16),
- bookingRef: ''
- };
- setTransportation([...transportation, newTransport]);
- };
-
- if (loading) {
- return (
-
-
-
-
- );
- }
-
- if (error) {
- return (
-
- navigate('/dashboard')}>
- Back to Dashboard
-
- }
- >
- {error}
-
-
- );
- }
-
- if (!trip) {
- return (
-
-
- Trip not found
-
-
- );
- }
-
- return (
-
- }
- onClick={() => navigate('/dashboard')}
- sx={{ mb: 3 }}
- >
- Back to Dashboard
-
-
-
-
-
-
- {trip.title}
-
-
- }
- label={trip.destination}
- color="primary"
- variant="outlined"
- />
- }
- label={`${dayjs(trip.start_date).format('MMM D')} - ${dayjs(trip.end_date).format('MMM D, YYYY')}`}
- variant="outlined"
- />
-
-
- }
- onClick={() => navigate(`/trips/${tripId}/edit`)}
- >
- Edit Trip
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Accommodations
- {accommodations.length > 0 && (
- }
- onClick={handleAddAccommodation}
- >
- Add Accommodation
-
- )}
-
-
- {accommodations.length === 0 ? (
-
- ) : (
- accommodations.map(accommodation => (
- {
- setAccommodations(accommodations.map(acc =>
- acc.id === updated.id ? updated : acc
- ));
- }}
- onDelete={(id) => {
- setAccommodations(accommodations.filter(acc => acc.id !== id));
- }}
- />
- ))
- )}
-
-
-
-
- Transportation
- {transportation.length > 0 && (
- }
- onClick={handleAddTransportation}
- >
- Add Transportation
-
- )}
-
-
- {transportation.length === 0 ? (
-
- ) : (
- transportation.map(transport => (
- {
- setTransportation(transportation.map(t =>
- t.id === updated.id ? updated : t
- ));
- }}
- onDelete={(id) => {
- setTransportation(transportation.filter(t => t.id !== id));
- }}
- />
- ))
- )}
-
-
-
-
-
-
-
- Itinerary
-
- {Object.keys(itinerary).length === 0 ? (
-
- ) : (
- trip && getDatesArray(trip.start_date, trip.end_date).map(date => (
-
- ))
- )}
-
-
-
-
- );
-};
-
-// Helper function to generate dates array
-const getDatesArray = (startDate, endDate) => {
- const dates = [];
- let currentDate = dayjs(startDate);
- const lastDate = dayjs(endDate);
-
- while (currentDate.isBefore(lastDate) || currentDate.isSame(lastDate, 'day')) {
- dates.push(currentDate.format('YYYY-MM-DD'));
- currentDate = currentDate.add(1, 'day');
- }
-
- return dates;
-};
-
-export default TripDetailsPage;
diff --git a/planventure-client/src/routes/routes.jsx b/planventure-client/src/routes/routes.jsx
index 9097253..32f72ce 100644
--- a/planventure-client/src/routes/routes.jsx
+++ b/planventure-client/src/routes/routes.jsx
@@ -1,11 +1,4 @@
import Home from '../pages/Home';
-import LoginPage from '../pages/LoginPage';
-import SignUpPage from '../pages/SignUpPage';
-import Dashboard from '../pages/Dashboard';
-import DashboardLayout from '../layouts/DashboardLayout';
-import NewTripPage from '../pages/NewTripPage';
-import TripDetailsPage from '../pages/TripDetailsPage';
-import EditTripPage from '../pages/EditTripPage';
export const publicRoutes = [
{
@@ -14,33 +7,13 @@ export const publicRoutes = [
},
{
path: '/login',
- element: ,
+ element: , // Temporarily using Home component
},
- {
- path: '/signup',
- element: ,
- }
];
export const protectedRoutes = [
- {
- path: '/dashboard',
- element: ,
- },
{
path: '/trips',
- element: ,
- },
- {
- path: '/trips/new',
- element: ,
- },
- {
- path: '/trips/:tripId',
- element: ,
- },
- {
- path: '/trips/:tripId/edit',
- element: ,
+ element: , // Temporarily using Home component
}
];
\ No newline at end of file
diff --git a/planventure-client/src/services/api.jsx b/planventure-client/src/services/api.jsx
index 7cd477c..43b4aa0 100644
--- a/planventure-client/src/services/api.jsx
+++ b/planventure-client/src/services/api.jsx
@@ -1,68 +1,21 @@
-const BASE_URL = 'http://localhost:5000';
-
-const getAuthHeaders = () => {
- const token = localStorage.getItem('token');
- return {
- 'Content-Type': 'application/json',
- 'Authorization': token ? `Bearer ${token}` : '',
- };
-};
-
-const handleResponse = async (response) => {
- if (response.status === 401) {
- localStorage.removeItem('token');
- window.location.href = '/login';
- throw new Error('Session expired. Please login again.');
- }
-
- if (response.status === 404) {
- throw new Error('Trip not found');
- }
-
- const data = await response.json();
- if (!response.ok) {
- throw new Error(data.error || data.message || 'Request failed');
- }
-
- console.log('API Response:', data); // Debug log
- return data;
-};
+const BASE_URL = import.meta.env.BASE_API_URL || 'http://localhost:5000';
export const api = {
get: async (endpoint) => {
- const response = await fetch(`${BASE_URL}${endpoint}`, {
- headers: getAuthHeaders(),
- });
- return handleResponse(response);
+ const response = await fetch(`${BASE_URL}${endpoint}`);
+ return response.json();
},
post: async (endpoint, data) => {
const response = await fetch(`${BASE_URL}${endpoint}`, {
method: 'POST',
- headers: getAuthHeaders(),
- body: JSON.stringify(data),
- });
- return handleResponse(response);
- },
-
- put: async (endpoint, data) => {
- const response = await fetch(`${BASE_URL}${endpoint}`, {
- method: 'PUT',
- headers: getAuthHeaders(),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
body: JSON.stringify(data),
});
- return handleResponse(response);
+ return response.json();
},
-
- auth: {
- login: async (credentials) => {
- return api.post('/auth/login', credentials);
- },
-
- register: async (userData) => {
- return api.post('/auth/register', userData);
- }
- }
};
export default api;
\ No newline at end of file
diff --git a/planventure-client/src/services/tripService.jsx b/planventure-client/src/services/tripService.jsx
deleted file mode 100644
index b0061f7..0000000
--- a/planventure-client/src/services/tripService.jsx
+++ /dev/null
@@ -1,72 +0,0 @@
-import { api } from './api';
-
-export const tripService = {
- getAllTrips: async () => {
- try {
- console.log('Fetching trips with auth token:', localStorage.getItem('token')); // Debug log
- const response = await api.get('/api/trips');
- console.log('Trips response:', response); // Debug log
- return response;
- } catch (error) {
- console.error('Error in getAllTrips:', error); // Debug log
- if (error.message.includes('Session expired')) {
- // Handle session expiration specifically
- return { trips: [] };
- }
- throw error;
- }
- },
-
- createTrip: async (tripData) => {
- try {
- const response = await api.post('/api/trips', tripData);
- return response.data;
- } catch (error) {
- throw new Error(error.response?.data?.message || 'Failed to create trip');
- }
- },
-
- getTrip: async (tripId) => {
- try {
- console.log('Fetching trip with ID:', tripId);
- const response = await api.get(`/api/trips/${tripId}`);
- console.log('Raw trip response:', response);
-
- // If the response itself is the trip data
- if (response && response.id) {
- return { trip: response };
- }
-
- // If the trip is nested in a data or trips property
- if (response && (response.data || response.trips)) {
- return { trip: response.data || response.trips };
- }
-
- throw new Error('Invalid response format from server');
- } catch (error) {
- console.error('Error in getTrip:', error);
- throw new Error(error.message || 'Failed to fetch trip details');
- }
- },
-
- updateTrip: async (tripId, tripData) => {
- try {
- console.log('Updating trip:', tripId, tripData);
- const response = await api.put(`/api/trips/${tripId}`, tripData);
- console.log('Update response:', response);
- return response;
- } catch (error) {
- console.error('Error in updateTrip:', error);
- throw new Error(error.message || 'Failed to update trip');
- }
- },
-
- deleteTrip: async (tripId) => {
- try {
- const response = await api.delete(`/api/trips/${tripId}`);
- return response.data;
- } catch (error) {
- throw new Error(error.response?.data?.message || 'Failed to delete trip');
- }
- }
-};