added trips page
This commit is contained in:
parent
86c84b42e9
commit
5b0a51a6f4
|
@ -1,13 +1,7 @@
|
|||
<script>
|
||||
import Button from "./Button.svelte";
|
||||
|
||||
export let title = 'Past Trips';
|
||||
export let desc = 'Click to view all past trips';
|
||||
export let title = 'Your Trips';
|
||||
export let desc = 'Click to view all your trips';
|
||||
export let onClick = () => {};
|
||||
|
||||
// change if there is a button
|
||||
export let buttonText = '+ Plan a new trip';
|
||||
export let onButtonClick = undefined;
|
||||
</script>
|
||||
|
||||
<div class="bottom-bar">
|
||||
|
@ -17,10 +11,6 @@
|
|||
<h2>{title}</h2>
|
||||
<p class="hint">{desc}</p>
|
||||
</div>
|
||||
|
||||
{#if typeof onButtonClick === 'function'}
|
||||
<Button text={buttonText} type="single" onClick={onButtonClick} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -61,12 +61,12 @@
|
|||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin: 0;
|
||||
font-size: 1rem;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.date-text h3 {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
|
|
110
src/lib/components/Nav.svelte
Normal file
110
src/lib/components/Nav.svelte
Normal file
|
@ -0,0 +1,110 @@
|
|||
<script lang="ts">
|
||||
import { Colors } from '$lib/constants/Colors';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
let title = "Travel App";
|
||||
export let activeTab = "Home";
|
||||
|
||||
function handleNavigation(tab: "Home" | "Planner" | "Memory") {
|
||||
activeTab = tab;
|
||||
if (tab === 'Home') {
|
||||
goto('/');
|
||||
} else if (tab === 'Planner') {
|
||||
goto('/trips');
|
||||
} else {
|
||||
console.log("will be implemented later");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<nav>
|
||||
<div class="logo">{title}</div>
|
||||
<div class="right-nav">
|
||||
<div class="menu">
|
||||
<button
|
||||
class:active={activeTab === "Home"}
|
||||
onclick={() => handleNavigation("Home")}>
|
||||
Home
|
||||
</button>
|
||||
<button
|
||||
class:active={activeTab === "Planner"}
|
||||
onclick={() => handleNavigation("Planner")}>
|
||||
Planner
|
||||
</button>
|
||||
<button
|
||||
class:active={activeTab === "Memory"}
|
||||
onclick={() => handleNavigation("Memory")}>
|
||||
Memory
|
||||
</button>
|
||||
</div>
|
||||
<div class="profile">
|
||||
<button class="profile-btn" aria-label="Open profile">
|
||||
<i class="fa-regular fa-user fa-xl" style="color: {Colors.black}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<style>
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem 2rem;
|
||||
border-bottom: 1px solid var(--gray-100);
|
||||
background-color: var(--white);
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.right-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.menu button {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem 1rem;
|
||||
color: var(--gray-400);
|
||||
transition: all 0.2s ease;
|
||||
min-width: 100px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.menu button.active {
|
||||
color: var(--black);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.menu button:hover {
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.profile-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
opacity: 0.3;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.profile-btn:hover {
|
||||
background-color: var(--gray-100);
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
165
src/lib/components/NewTripPopup.svelte
Normal file
165
src/lib/components/NewTripPopup.svelte
Normal file
|
@ -0,0 +1,165 @@
|
|||
<script>
|
||||
import { Colors } from '$lib/constants/Colors';
|
||||
import { goto } from '$app/navigation';
|
||||
import Button from './Button.svelte';
|
||||
|
||||
export let showPopup = false;
|
||||
export let fromPage = 'home';
|
||||
|
||||
let destination = "";
|
||||
let startDate = "";
|
||||
let endDate = "";
|
||||
let friends = "";
|
||||
|
||||
function handleCancel() {
|
||||
showPopup = false;
|
||||
destination = "";
|
||||
startDate = "";
|
||||
endDate = "";
|
||||
friends = "";
|
||||
}
|
||||
|
||||
function handleStart() {
|
||||
console.log(destination, startDate, endDate, friends);
|
||||
goto(`/itinerary?from=${fromPage}`);
|
||||
handleCancel();
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if showPopup}
|
||||
<div class="overlay">
|
||||
<div class="popup">
|
||||
<h1>Start a New Plan</h1>
|
||||
|
||||
<div class="input-form">
|
||||
<label for="destination">Destination</label>
|
||||
<input
|
||||
type="text"
|
||||
id="destination"
|
||||
bind:value={destination}
|
||||
placeholder="Where do you want to go?"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="date-group">
|
||||
<div class="input-form">
|
||||
<label for="start-date">Start Date</label>
|
||||
<input
|
||||
type="date"
|
||||
id="start-date"
|
||||
bind:value={startDate}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="input-form">
|
||||
<label for="end-date">End Date</label>
|
||||
<input
|
||||
type="date"
|
||||
id="end-date"
|
||||
bind:value={endDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-form">
|
||||
<label for="trip-friends">
|
||||
<span class="invite-label">
|
||||
+ Invite Friends
|
||||
<i class="fa-solid fa-user-group" style="color: {Colors.gray.dark800}"></i>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="trip-friends"
|
||||
bind:value={friends}
|
||||
placeholder="Enter email addresses"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<Button text="Cancel" type="gray" onClick={handleCancel} />
|
||||
<Button text="Start" type="blue" onClick={handleStart} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.popup {
|
||||
background: var(--white);
|
||||
padding: 2rem;
|
||||
border-radius: 20px;
|
||||
width: 80%;
|
||||
max-width: 560px;
|
||||
box-shadow: 0 0px 20px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.popup h1 {
|
||||
margin: 0 0 2rem 0;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.input-form {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.input-form label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
color: var(--gray-800);
|
||||
}
|
||||
|
||||
.input-form input {
|
||||
width: 95.3%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid var(--gray-200);
|
||||
border-radius: 8px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline-color: var(--planner-600);
|
||||
}
|
||||
|
||||
.date-group {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.date-group .input-form {
|
||||
flex: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.date-group .input-form input {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.invite-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
</style>
|
69
src/lib/components/TripCard.svelte
Normal file
69
src/lib/components/TripCard.svelte
Normal file
|
@ -0,0 +1,69 @@
|
|||
<script>
|
||||
export let destination = '';
|
||||
export let startDate = '';
|
||||
export let endDate = '';
|
||||
export let image = '';
|
||||
</script>
|
||||
|
||||
<div class="trip-card">
|
||||
<div class="image" style="background-image: url({image})">
|
||||
<!-- Image placeholder if no image provided -->
|
||||
{#if !image}
|
||||
<div class="placeholder">
|
||||
<i class="fa-solid fa-image" style="color: var(--gray-400)"></i>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="info">
|
||||
<h3>{destination}</h3>
|
||||
<p class="date">{startDate} - {endDate}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.trip-card {
|
||||
background: var(--white);
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
cursor: pointer;
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
.trip-card:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.image {
|
||||
height: 160px;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-color: var(--gray-100);
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.info {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.info h3 {
|
||||
margin: 0;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.date {
|
||||
margin: 0.25rem 0 0 0;
|
||||
font-size: 0.8rem;
|
||||
color: var(--gray-400);
|
||||
}
|
||||
</style>
|
|
@ -1,288 +1,56 @@
|
|||
<script>
|
||||
import '../app.css';
|
||||
import { goto } from '$app/navigation';
|
||||
import { Colors } from '$lib/constants/Colors';
|
||||
import WorldMap from '$lib/components/WorldMap.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import BottomBar from '$lib/components/BottomBar.svelte';
|
||||
import NewTripPopup from '$lib/components/NewTripPopup.svelte';
|
||||
import Nav from '$lib/components/Nav.svelte';
|
||||
|
||||
let title = "Travel App";
|
||||
let activeTab = "Planner";
|
||||
let showNewTripPopup = false;
|
||||
let destination = "";
|
||||
let startDate = "";
|
||||
let endDate = "";
|
||||
let friends = "";
|
||||
|
||||
const GOOGLE_PLACES_API_KEY = import.meta.env.VITE_GOOGLE_PLACES_API_KEY;
|
||||
|
||||
|
||||
function handleNewTrip() {
|
||||
showNewTripPopup = true;
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
showNewTripPopup = false;
|
||||
destination = "";
|
||||
startDate = "";
|
||||
endDate = "";
|
||||
friends = "";
|
||||
}
|
||||
|
||||
function handleStart() {
|
||||
console.log(destination, startDate, endDate, friends);
|
||||
goto('/itinerary');
|
||||
}
|
||||
|
||||
function handlePastTrip() {
|
||||
console.log("let's see the past trip");
|
||||
showNewTripPopup = true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<nav>
|
||||
<div class="logo">{title}</div>
|
||||
<div class="right-nav">
|
||||
<div class="menu">
|
||||
<button
|
||||
class:active={activeTab === "Planner"}
|
||||
onclick={() => activeTab = "Planner"}>
|
||||
Planner
|
||||
</button>
|
||||
<button
|
||||
class:active={activeTab === "Memory"}
|
||||
onclick={() => activeTab = "Memory"}>
|
||||
Memory
|
||||
</button>
|
||||
</div>
|
||||
<div class="profile">
|
||||
<button class="profile-btn" aria-label="Open profile">
|
||||
<i class="fa-regular fa-user fa-xl" style="color: {Colors.black}"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="map-container">
|
||||
|
||||
<main>
|
||||
<Nav activeTab="Home" />
|
||||
|
||||
<div class="map-container">
|
||||
<WorldMap />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="floating-button">
|
||||
<Button text="+ Plan a new trip" type="single" onClick={handleNewTrip} />
|
||||
</div>
|
||||
|
||||
<BottomBar onClick={handlePastTrip} onButtonClick={handleNewTrip} />
|
||||
<BottomBar onClick={() => goto('/trips')} />
|
||||
|
||||
{#if showNewTripPopup}
|
||||
<!-- (optional) add onclick={handleCancel} -->
|
||||
<div class="overlay">
|
||||
<div class="popup">
|
||||
<h1>Start a New Plan</h1>
|
||||
|
||||
<div class="input-form">
|
||||
<label for="destination">Destination</label>
|
||||
<input
|
||||
type="text"
|
||||
id="destination"
|
||||
bind:value={destination}
|
||||
placeholder="Where do you want to go?"
|
||||
/>
|
||||
</div>
|
||||
<NewTripPopup bind:showPopup={showNewTripPopup} fromPage="home" />
|
||||
</main>
|
||||
|
||||
<div class="date-group">
|
||||
<div class="input-form">
|
||||
<label for="start-date">Start Date</label>
|
||||
<input
|
||||
type="date"
|
||||
id="start-date"
|
||||
bind:value={startDate}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="input-form">
|
||||
<label for="end-date">End Date</label>
|
||||
<input
|
||||
type="date"
|
||||
id="end-date"
|
||||
bind:value={endDate}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-form">
|
||||
<label for="trip-friends">
|
||||
<span class="invite-label">
|
||||
+ Invite Friends
|
||||
<i class="fa-solid fa-user-group" style="color: {Colors.gray.dark800}"></i>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="trip-friends"
|
||||
bind:value={friends}
|
||||
placeholder="Enter email addresses"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<Button text="Cancel" type="gray" onClick={handleCancel} />
|
||||
<Button text="Start" type="blue" onClick={handleStart} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
<style>
|
||||
main {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: var(--gray-50);
|
||||
font-family: 'Inter', sans-serif;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem 2rem;
|
||||
border-bottom: 1px solid var(--gray-100);
|
||||
background-color: var(--white);
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.right-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.menu button {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem 1rem;
|
||||
color:var(--gray-400);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.menu button.active {
|
||||
color: var(--black);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.menu button:hover {
|
||||
color: var(--black);
|
||||
}
|
||||
|
||||
.profile-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
opacity: 0.3;
|
||||
cursor: pointer;
|
||||
padding: 0.5rem;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.profile-btn:hover {
|
||||
background-color: var(--gray-100);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.map-container {
|
||||
.map-container {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
background-color: var(--gray-50);
|
||||
/* overflow: hidden; */
|
||||
}
|
||||
}
|
||||
|
||||
/* Popup Styling */
|
||||
.overlay {
|
||||
.floating-button {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.popup {
|
||||
background: var(--white);
|
||||
padding: 2rem;
|
||||
border-radius: 20px;
|
||||
width: 80%;
|
||||
max-width: 560px;
|
||||
box-shadow: 0 0px 20px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.popup h1 {
|
||||
margin: 0 0 2rem 0;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
/* color: var(--planner-600); */
|
||||
}
|
||||
|
||||
.input-form {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.input-form label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
color: var(--gray-800);
|
||||
}
|
||||
|
||||
.input-form input {
|
||||
width: 95.3%;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid var(--gray-200);
|
||||
border-radius: 8px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline-color: var(--planner-600);
|
||||
}
|
||||
|
||||
.date-group {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.date-group .input-form {
|
||||
flex: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.date-group .input-form input{
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.invite-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
bottom: 2rem;
|
||||
right: 2rem;
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
|
@ -1,14 +1,13 @@
|
|||
<script lang="ts">
|
||||
import '../../app.css';
|
||||
import { goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
import { Colors } from '$lib/constants/Colors';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import ProfilePicture from '$lib/components/ProfilePicture.svelte';
|
||||
import BottomBar from '$lib/components/BottomBar.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import ItineraryDate from '$lib/components/ItineraryDate.svelte';
|
||||
import { page } from '$app/state';
|
||||
|
||||
// Placeholder data obtained from the popup
|
||||
let destination = "Taiwan";
|
||||
|
@ -16,7 +15,7 @@
|
|||
let startDate = "27/04/2025";
|
||||
let endDate = "30/04/2025";
|
||||
let places: string[] = [];
|
||||
const place_placeholder = { name: 'Somewhere', desc: 'desc of the place'}
|
||||
const place_placeholder = { name: 'Somewhere'}
|
||||
const places_placeholder = Array(3).fill(place_placeholder);
|
||||
|
||||
// Array of dates between startDate to endDate
|
||||
|
@ -40,7 +39,15 @@
|
|||
}
|
||||
|
||||
function handleBack() {
|
||||
goto('/');
|
||||
// Get the 'from' parameter from the URL
|
||||
const fromPage = page.url.searchParams.get('from');
|
||||
console.log(`fromPage = ${fromPage}`);
|
||||
|
||||
if (fromPage === 'trips') {
|
||||
goto('/trips');
|
||||
} else {
|
||||
goto('/');
|
||||
}
|
||||
}
|
||||
|
||||
function handleAddPlace() {
|
||||
|
@ -142,7 +149,7 @@
|
|||
|
||||
<div class="map-section">
|
||||
<div class="map"></div>
|
||||
<BottomBar desc={desc} onClick={handlePastTrip} />
|
||||
<BottomBar title="Past Trips" desc={desc} onClick={handlePastTrip} />
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
@ -160,6 +167,8 @@
|
|||
box-sizing: border-box;
|
||||
padding: 0.5rem 0rem 0rem 0rem;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.map-section {
|
||||
|
@ -176,10 +185,11 @@
|
|||
|
||||
header {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: 0 2rem 1.5rem 1rem;
|
||||
margin-bottom: 3rem;
|
||||
margin-bottom: 1rem;
|
||||
border-bottom: 1px solid var(--gray-100);
|
||||
}
|
||||
|
||||
|
@ -229,6 +239,10 @@
|
|||
|
||||
.content {
|
||||
padding: 0 1.5rem 0 1.5rem;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
|
@ -262,6 +276,7 @@
|
|||
|
||||
.section-text h2 {
|
||||
margin: 0;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
|
@ -272,11 +287,12 @@
|
|||
|
||||
.button-group {
|
||||
position: sticky;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--white);
|
||||
padding: 1.5rem 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
margin-top: auto;
|
||||
}
|
||||
</style>
|
207
src/routes/trips/+page.svelte
Normal file
207
src/routes/trips/+page.svelte
Normal file
|
@ -0,0 +1,207 @@
|
|||
<script lang="ts">
|
||||
import '../../app.css';
|
||||
import TripCard from '$lib/components/TripCard.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import NewTripPopup from '$lib/components/NewTripPopup.svelte';
|
||||
import Nav from '$lib/components/Nav.svelte';
|
||||
|
||||
interface Trip {
|
||||
destination: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
imageUrl: string;
|
||||
}
|
||||
|
||||
let activeTab = "Ongoing Trips";
|
||||
let showNewTripPopup = false;
|
||||
let contentContainer: HTMLElement;
|
||||
|
||||
// Sample data, replace with actual data later
|
||||
const sample_trip = {
|
||||
destination: "Taiwan",
|
||||
startDate: "04.27.2025",
|
||||
endDate: "04.30.2025",
|
||||
imageUrl: ""
|
||||
}
|
||||
let ongoingTrips = Array(3).fill(sample_trip);
|
||||
|
||||
// let pastTrips: Trip[] = [];
|
||||
let pastTrips = Array(14).fill(sample_trip);
|
||||
|
||||
function handleNewTrip() {
|
||||
showNewTripPopup = true;
|
||||
}
|
||||
|
||||
function handleTabChange(tab: string) {
|
||||
activeTab = tab;
|
||||
contentContainer.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<Nav activeTab="Planner" />
|
||||
|
||||
<div class="content" bind:this={contentContainer}>
|
||||
<div class="header">
|
||||
<h1>Your Trips</h1>
|
||||
</div>
|
||||
|
||||
<div class="tabs">
|
||||
<button
|
||||
class:active={activeTab === "Ongoing Trips"}
|
||||
onclick={() => handleTabChange("Ongoing Trips")}>
|
||||
Ongoing Trips
|
||||
</button>
|
||||
<button
|
||||
class:active={activeTab === "Past Trips"}
|
||||
onclick={() => handleTabChange("Past Trips")}>
|
||||
Past Trips
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="trips-container">
|
||||
{#if activeTab === "Ongoing Trips"}
|
||||
{#if ongoingTrips.length === 0}
|
||||
<div class="empty-state">
|
||||
<p>There is no ongoing trip</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="trips-grid">
|
||||
{#each ongoingTrips as trip}
|
||||
<TripCard {...trip} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
{#if pastTrips.length === 0}
|
||||
<div class="empty-state">
|
||||
<p>There is no past trip</p>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="trips-grid">
|
||||
{#each pastTrips as trip}
|
||||
<TripCard {...trip} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="floating-button">
|
||||
<Button text="+ Plan a new trip" type="single" onClick={handleNewTrip} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NewTripPopup bind:showPopup={showNewTripPopup} fromPage="trips" />
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
height: 100vh;
|
||||
background-color: var(--white);
|
||||
font-family: 'Inter', sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 0 1rem 2rem 1rem;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding-top: 2rem;
|
||||
padding-left: 1rem;
|
||||
background-color: var(--white);
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
display: flex;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding-top: 1.5rem;
|
||||
padding-left: 1rem;
|
||||
background-color: var(--white);
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.tabs button {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
padding: 0.75rem 0;
|
||||
color: var(--gray-400);
|
||||
transition: color 0.3s ease;
|
||||
position: relative;
|
||||
min-width: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tabs button:hover {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.tabs button.active {
|
||||
color: var(--planner-600);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tabs button.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: var(--planner-600);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.trips-container {
|
||||
flex: 1;
|
||||
padding: 0 1rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.trips-grid {
|
||||
display: grid;
|
||||
padding-top: 1.5rem;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
margin-top: -10rem;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--gray-400);
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.floating-button {
|
||||
position: fixed;
|
||||
bottom: 2rem;
|
||||
right: 2rem;
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user