1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-08-05 13:15:18 +02:00

Merge pull request #55 from seanmorley15/development

Development
This commit is contained in:
Sean Morley 2024-05-05 15:51:24 -04:00 committed by GitHub
commit 25f773eaa9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 682 additions and 85 deletions

View file

@ -31,6 +31,10 @@
console.log(adventure.id); console.log(adventure.id);
goto(`/adventure/${adventure.id}`); goto(`/adventure/${adventure.id}`);
} }
function markVisited() {
console.log(adventure.id);
dispatch("markVisited", adventure);
}
</script> </script>
<div <div
@ -77,6 +81,10 @@
> >
{/if} {/if}
{#if type == "planner"} {#if type == "planner"}
<button class="btn btn-success" on:click={markVisited}
><iconify-icon icon="mdi:check-bold" class="text-2xl"
></iconify-icon></button
>
<button class="btn btn-primary" on:click={moreInfo} <button class="btn btn-primary" on:click={moreInfo}
><iconify-icon icon="mdi:launch" class="text-2xl" ><iconify-icon icon="mdi:launch" class="text-2xl"
></iconify-icon></button ></iconify-icon></button

View file

@ -15,6 +15,7 @@
import type { Adventure } from "$lib/utils/types"; import type { Adventure } from "$lib/utils/types";
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
import { onMount } from "svelte"; import { onMount } from "svelte";
import { addActivityType } from "$lib";
let modal: HTMLDialogElement; let modal: HTMLDialogElement;
onMount(() => { onMount(() => {
@ -25,7 +26,7 @@
}); });
function create() { function create() {
addActivityType(); activitySetup();
if (newAdventure.name.trim() === "") { if (newAdventure.name.trim() === "") {
alert("Name is required"); alert("Name is required");
return; return;
@ -46,15 +47,9 @@
let activityInput: string = ""; let activityInput: string = "";
function addActivityType() { function activitySetup() {
if (activityInput.trim() !== "") { newAdventure = addActivityType(activityInput, newAdventure);
const activities = activityInput activityInput = "";
.split(" ")
.filter((activity) => activity.trim() !== "");
newAdventure.activityTypes = activities;
activityInput = "";
}
console.log(newAdventure.activityTypes);
} }
</script> </script>

View file

@ -4,6 +4,7 @@
import type { Adventure } from "$lib/utils/types"; import type { Adventure } from "$lib/utils/types";
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
import { onMount } from "svelte"; import { onMount } from "svelte";
import { addActivityType } from "$lib";
let modal: HTMLDialogElement; let modal: HTMLDialogElement;
console.log(adventureToEdit.id); console.log(adventureToEdit.id);
@ -19,7 +20,7 @@
}); });
function submit() { function submit() {
addActivityType(); activitySetup();
dispatch("submit", adventureToEdit); dispatch("submit", adventureToEdit);
console.log(adventureToEdit); console.log(adventureToEdit);
} }
@ -36,15 +37,9 @@
let activityInput: string = ""; let activityInput: string = "";
function addActivityType() { function activitySetup() {
if (activityInput.trim() !== "") { adventureToEdit = addActivityType(activityInput, adventureToEdit);
const activities = activityInput activityInput = "";
.split(",")
.filter((activity) => activity.trim() !== "");
adventureToEdit.activityTypes = activities;
activityInput = "";
}
console.log(adventureToEdit.activityTypes);
} }
</script> </script>

View file

@ -0,0 +1,169 @@
<script lang="ts">
import { enhance } from "$app/forms";
import { visitCount } from "$lib/utils/stores/visitCountStore";
import { goto } from "$app/navigation";
import type { DatabaseUser } from "$lib/server/auth";
export let user: any;
import UserAvatar from "./UserAvatar.svelte";
import { onMount } from "svelte";
import InfoModal from "./InfoModal.svelte";
import infoIcon from "$lib/assets/info.svg";
import type { SubmitFunction } from "@sveltejs/kit";
async function goHome() {
goto("/");
}
async function goToLog() {
goto("/log");
}
async function goToFeatured() {
goto("/featured");
}
async function toToLogin() {
goto("/login");
}
async function goToSignup() {
goto("/signup");
}
async function goToWorldTravel() {
goto("/worldtravel");
}
const submitUpdateTheme: SubmitFunction = ({ action }) => {
const theme = action.searchParams.get("theme");
if (theme) {
document.documentElement.setAttribute("data-theme", theme);
}
};
let count = 0;
let infoModalOpen = false;
function showModal() {
infoModalOpen = true;
}
function closeModal() {
infoModalOpen = false;
}
// get value from fetch /api/visitcount
$: if (user) {
onMount(async () => {
const res = await fetch("/api/visitcount");
const data = await res.json();
visitCount.set(data.visitCount);
});
}
visitCount.subscribe((value) => {
count = value;
});
// Set the visit count to the number of adventures stored in local storage
const isBrowser = typeof window !== "undefined";
if (isBrowser) {
const storedAdventures = localStorage.getItem("adventures");
}
</script>
<div class="navbar bg-base-100 flex flex-col md:flex-row">
<div class="navbar-start flex justify-around md:justify-start">
<button
class="btn btn-primary my-2 md:my-0 md:mr-4 md:ml-2"
on:click={goHome}>Home</button
>
{#if user}
<button class="btn btn-primary my-2 md:my-0 md:mr-4" on:click={goToLog}
>My Log</button
>
<button
class="btn btn-primary my-2 md:my-0 md:mr-4"
on:click={() => goto("/planner")}>Planner</button
>
<!-- <button
class="btn btn-primary my-2 md:my-0 md:mr-4"
on:click={() => goto("/planner")}>Planner</button
> -->
{/if}
<button
class="btn btn-primary my-2 md:my-0 md:mr-4"
on:click={goToWorldTravel}>World Tavel Log</button
>
<button class="btn btn-primary my-2 md:my-0" on:click={goToFeatured}
>Featured</button
>
</div>
<div class="navbar-center flex justify-center md:justify-center">
<a class="btn btn-ghost text-xl" href="/">AdventureLog 🗺️</a>
</div>
{#if infoModalOpen}
<InfoModal on:close={closeModal} />
{/if}
<div class="navbar-end flex justify-around md:justify-end mr-4">
{#if !user}
<button class="btn btn-primary ml-4" on:click={toToLogin}>Login</button>
<button class="btn btn-primary ml-4" on:click={goToSignup}>Signup</button>
{/if}
{#if user}
<p class="font-bold">Adventures: {count}</p>
<UserAvatar {user} />
{/if}
<button class="btn btn-neutral ml-4 btn-circle" on:click={showModal}
><iconify-icon icon="mdi:information" class="text-xl"
></iconify-icon></button
>
<div class="dropdown dropdown-bottom dropdown-end">
<div tabindex="0" role="button" class="btn m-1 ml-4">
<iconify-icon icon="mdi:theme-light-dark" class="text-xl"
></iconify-icon>
</div>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<ul
tabindex="0"
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52"
>
<form method="POST" use:enhance={submitUpdateTheme}>
<li>
<button formaction="/?/setTheme&theme=light"
>Light<iconify-icon icon="mdi:weather-sunny" class="text-xl"
></iconify-icon></button
>
</li>
<li>
<button formaction="/?/setTheme&theme=dark"
>Dark<iconify-icon icon="mdi:weather-night" class="text-xl"
></iconify-icon></button
>
</li>
<li>
<button formaction="/?/setTheme&theme=night"
>Night<iconify-icon icon="mdi:weather-night" class="text-xl"
></iconify-icon></button
>
</li>
<!-- <li><button formaction="/?/setTheme&theme=nord">Nord</button></li> -->
<!-- <li><button formaction="/?/setTheme&theme=retro">Retro</button></li> -->
<li>
<button formaction="/?/setTheme&theme=forest"
>Forest<iconify-icon icon="mdi:forest" class="text-xl"
></iconify-icon></button
>
<button formaction="/?/setTheme&theme=garden"
>Garden<iconify-icon icon="mdi:flower" class="text-xl"
></iconify-icon></button
>
<button formaction="/?/setTheme&theme=aqua"
>Aqua<iconify-icon icon="mdi:water" class="text-xl"
></iconify-icon></button
>
</li>
</form>
</ul>
</div>
</div>
</div>

View file

@ -68,55 +68,90 @@
} }
</script> </script>
<div class="navbar bg-base-100 flex flex-col md:flex-row"> <div class="navbar bg-base-100">
<div class="navbar-start flex justify-around md:justify-start"> <div class="navbar-start">
<button <div class="dropdown">
class="btn btn-primary my-2 md:my-0 md:mr-4 md:ml-2" <div tabindex="0" role="button" class="btn btn-ghost lg:hidden">
on:click={goHome}>Home</button <svg
> xmlns="http://www.w3.org/2000/svg"
{#if user} class="h-5 w-5"
<button class="btn btn-primary my-2 md:my-0 md:mr-4" on:click={goToLog} fill="none"
>My Log</button viewBox="0 0 24 24"
stroke="currentColor"
><path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h8m-8 6h16"
/></svg
>
</div>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<ul
tabindex="0"
class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow bg-base-100 rounded-box w-52 gap-2"
> >
<button <li>
class="btn btn-primary my-2 md:my-0 md:mr-4" <button on:click={() => goto("/log")}>My Log</button>
on:click={() => goto("/planner")}>Planner</button </li>
> <li>
<button on:click={() => goto("/planner")}>Planner</button>
<!-- <button </li>
class="btn btn-primary my-2 md:my-0 md:mr-4" <li>
on:click={() => goto("/planner")}>Planner</button <button on:click={() => goto("/worldtravel")}>World Travel</button>
> --> </li>
{/if} <li>
<button <button on:click={() => goto("/featured")}>Featured</button>
class="btn btn-primary my-2 md:my-0 md:mr-4" </li>
on:click={goToWorldTravel}>World Tavel Log</button {#if !user}
> <li>
<button class="btn btn-primary my-2 md:my-0" on:click={goToFeatured} <button class="btn btn-primary" on:click={toToLogin}>Login</button>
>Featured</button </li>
> <li>
</div> <button class="btn btn-primary" on:click={goToSignup}>Signup</button
<div class="navbar-center flex justify-center md:justify-center"> >
</li>
{/if}
</ul>
</div>
<a class="btn btn-ghost text-xl" href="/">AdventureLog 🗺️</a> <a class="btn btn-ghost text-xl" href="/">AdventureLog 🗺️</a>
</div> </div>
<div class="navbar-center hidden lg:flex">
{#if infoModalOpen} <ul class="menu menu-horizontal px-1 gap-2">
<InfoModal on:close={closeModal} /> <li>
{/if} <button class="btn btn-neutral" on:click={() => goto("/log")}
<div class="navbar-end flex justify-around md:justify-end mr-4"> >My Log</button
{#if !user} >
<button class="btn btn-primary ml-4" on:click={toToLogin}>Login</button> </li>
<button class="btn btn-primary ml-4" on:click={goToSignup}>Signup</button> <li>
{/if} <button class="btn btn-neutral" on:click={() => goto("/planner")}
>Planner</button
>
</li>
<li>
<button class="btn btn-neutral" on:click={() => goto("/worldtravel")}
>World Travel</button
>
</li>
<li>
<button class="btn btn-neutral" on:click={() => goto("/featured")}
>Featured</button
>
</li>
{#if !user}
<li>
<button class="btn btn-primary" on:click={toToLogin}>Login</button>
</li>
<li>
<button class="btn btn-primary" on:click={goToSignup}>Signup</button>
</li>
{/if}
</ul>
</div>
<div class="navbar-end">
{#if user} {#if user}
<p class="font-bold">Adventures: {count}</p>
<UserAvatar {user} /> <UserAvatar {user} />
{/if} {/if}
<button class="btn btn-neutral ml-4 btn-circle" on:click={showModal}
><iconify-icon icon="mdi:information" class="text-xl"
></iconify-icon></button
>
<div class="dropdown dropdown-bottom dropdown-end"> <div class="dropdown dropdown-bottom dropdown-end">
<div tabindex="0" role="button" class="btn m-1 ml-4"> <div tabindex="0" role="button" class="btn m-1 ml-4">
<iconify-icon icon="mdi:theme-light-dark" class="text-xl" <iconify-icon icon="mdi:theme-light-dark" class="text-xl"

View file

@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { enhance } from "$app/forms"; import { enhance } from "$app/forms";
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import InfoModal from "./InfoModal.svelte";
export let user: any; export let user: any;
let icon: string = ""; let icon: string = "";
@ -17,6 +18,8 @@
async function navToLog() { async function navToLog() {
goto("/log"); goto("/log");
} }
let isInfoModalOpen: boolean = false;
</script> </script>
<div class="dropdown dropdown-bottom dropdown-end" tabindex="0" role="button"> <div class="dropdown dropdown-bottom dropdown-end" tabindex="0" role="button">
@ -42,8 +45,17 @@
<button on:click={() => goto("/settings/admin")}>Admin Settings</button> <button on:click={() => goto("/settings/admin")}>Admin Settings</button>
</li> </li>
{/if} {/if}
<li>
<button on:click={() => (isInfoModalOpen = true)}
>About AdventureLog</button
>
</li>
<form method="post"> <form method="post">
<li><button formaction="/?/logout">Logout</button></li> <li><button formaction="/?/logout">Logout</button></li>
</form> </form>
</ul> </ul>
</div> </div>
{#if isInfoModalOpen}
<InfoModal on:close={() => (isInfoModalOpen = false)} />
{/if}

View file

@ -1,5 +1,6 @@
import inspirationalQuotes from "./json/quotes.json"; import inspirationalQuotes from "./json/quotes.json";
import countryCodes from "./json/countries.json"; import countryCodes from "./json/countries.json";
import type { Adventure } from "./utils/types";
/** /**
* Converts a country code to its corresponding country name. * Converts a country code to its corresponding country name.
@ -8,7 +9,8 @@ import countryCodes from "./json/countries.json";
*/ */
export function countryCodeToName(countryCode: string): string | null { export function countryCodeToName(countryCode: string): string | null {
// Look up the country name using the provided country code // Look up the country name using the provided country code
const countryName = countryCodes[countryCode.toLowerCase() as keyof typeof countryCodes]; const countryName =
countryCodes[countryCode.toLowerCase() as keyof typeof countryCodes];
// Return the country name if found, otherwise return null // Return the country name if found, otherwise return null
return countryName || null; return countryName || null;
} }
@ -19,10 +21,10 @@ export function countryCodeToName(countryCode: string): string | null {
* @param country - The 2 digit country code representing the desired flag. * @param country - The 2 digit country code representing the desired flag.
* @returns The URL of the flag image. * @returns The URL of the flag image.
*/ */
export function getFlag(size:number,country: string) { export function getFlag(size: number, country: string) {
return `https://flagcdn.com/h${size}/${country}.png`; return `https://flagcdn.com/h${size}/${country}.png`;
} }
/** /**
* Generates a random string consisting of alphanumeric characters. * Generates a random string consisting of alphanumeric characters.
* @returns {string} The randomly generated string. * @returns {string} The randomly generated string.
@ -48,5 +50,30 @@ export function getRandomQuote() {
const randomIndex = Math.floor(Math.random() * quotes.length); const randomIndex = Math.floor(Math.random() * quotes.length);
let quoteString = quotes[randomIndex].quote; let quoteString = quotes[randomIndex].quote;
let authorString = quotes[randomIndex].author; let authorString = quotes[randomIndex].author;
return "\"" + quoteString + "\" - " + authorString; return '"' + quoteString + '" - ' + authorString;
}
/**
* Adds activity types to the adventure.
*
* @param activityInput - The input string containing activity types separated by commas.
* @param adventureToEdit - The adventure object to which the activity types will be added.
* @returns The adventure object with the updated activity types.
*/
export function addActivityType(
activityInput: string,
adventureToEdit: Adventure
) {
if (activityInput.trim() !== "") {
const activities = activityInput
.split(",")
.filter((activity) => activity.trim() !== "");
// trims the whitespace from the activities
for (let i = 0; i < activities.length; i++) {
activities[i] = activities[i].trim();
}
adventureToEdit.activityTypes = activities;
activityInput = "";
}
return adventureToEdit;
} }

View file

@ -12,26 +12,281 @@
} }
</script> </script>
<div class="flex flex-col items-center justify-center"> <!--
{#if data.user && data.user.username != ""} // v0 by Vercel.
<h1 class="mb-6 text-4xl font-extrabold"> // https://v0.dev/t/PyTNahbwxVP
Welcome {data.user.first_name}. Let's get Exploring! -->
</h1>
{:else}
<h1 class="mb-6 text-4xl font-extrabold">Welcome. Let's get Exploring!</h1>
{/if}
<img src={campingDrawing} class="w-1/4 mb-4" alt="Logo" /> <section class="w-full py-12 md:py-24 lg:py-32">
<button on:click={navToLog} class="btn btn-primary mb-4">Open Log</button> <div class="container px-4 md:px-6">
<div
<div class="stats shadow"> class="grid gap-6 lg:grid-cols-[1fr_550px] lg:gap-12 xl:grid-cols-[1fr_650px]"
<div class="stat"> >
<div class="stat-title">Logged Adventures</div> <div class="flex flex-col justify-center space-y-4">
<div class="stat-value text-center">{$visitCount}</div> <div class="space-y-2">
<!-- <div class="stat-desc">21% more than last month</div> --> <h1
class="text-3xl font-bold tracking-tighter sm:text-5xl xl:text-6xl/none"
>
Discover the World's Most Thrilling Adventures
</h1>
<p class="max-w-[600px] text-gray-500 md:text-xl dark:text-gray-400">
Discover and plan your next epic adventure with our cutting-edge
travel app. Explore breathtaking destinations, create custom
itineraries, and stay connected on the go.
</p>
</div>
<div class="flex flex-col gap-2 min-[400px]:flex-row">
<button
on:click={() => goto("/log")}
class="inline-flex h-10 items-center justify-center rounded-md bg-gray-900 px-8 text-sm font-medium text-gray-50 shadow transition-colors hover:bg-gray-900/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-gray-950 disabled:pointer-events-none disabled:opacity-50 dark:bg-gray-50 dark:text-gray-900 dark:hover:bg-gray-50/90 dark:focus-visible:ring-gray-300"
>
Go To AdventureLog
</button>
</div>
</div>
<img
src="https://images.unsplash.com/photo-1463693396721-8ca0cfa2b3b5?q=80&w=2940&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
width="550"
height="550"
alt="Hero"
class="mx-auto aspect-video overflow-hidden rounded-xl object-cover sm:w-full lg:order-last"
/>
</div> </div>
</div> </div>
</div> </section>
<section class="w-full py-12 md:py-24 lg:py-32 bg-gray-100 dark:bg-gray-800">
<div class="container px-4 md:px-6">
<div
class="flex flex-col items-center justify-center space-y-4 text-center"
>
<div class="space-y-2">
<div
class="inline-block rounded-lg bg-gray-100 px-3 py-1 text-sm dark:bg-gray-800"
>
Key Features
</div>
<h2 class="text-3xl font-bold tracking-tighter sm:text-5xl">
Discover, Plan, and Explore with Ease
</h2>
<p
class="max-w-[900px] text-gray-500 md:text-xl/relaxed lg:text-base/relaxed xl:text-xl/relaxed dark:text-gray-400"
>
Our adventure travel app is designed to simplify your journey,
providing you with the tools and resources to plan, pack, and navigate
your next epic adventure.
</p>
</div>
</div>
<div
class="mx-auto grid max-w-5xl items-center gap-6 py-12 lg:grid-cols-2 lg:gap-12"
>
<!-- svelte-ignore a11y-img-redundant-alt -->
<img
src="https://images.unsplash.com/photo-1516738901171-8eb4fc13bd20?q=80&w=2940&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
width="550"
height="310"
alt="Image"
class="mx-auto aspect-video overflow-hidden rounded-xl object-cover object-center sm:w-full lg:order-last"
/>
<div class="flex flex-col justify-center space-y-4">
<ul class="grid gap-6">
<li>
<div class="grid gap-1">
<h3 class="text-xl font-bold">Trip Planning</h3>
<p class="text-gray-500 dark:text-gray-400">
Easily create custom itineraries and get real-time updates on
your trip.
</p>
</div>
</li>
<li>
<div class="grid gap-1">
<h3 class="text-xl font-bold">Packing Lists</h3>
<p class="text-gray-500 dark:text-gray-400">
Never forget a thing with our comprehensive packing lists.
</p>
</div>
</li>
<li>
<div class="grid gap-1">
<h3 class="text-xl font-bold">Destination Guides</h3>
<p class="text-gray-500 dark:text-gray-400">
Discover the best attractions, activities, and hidden gems in
your destination.
</p>
</div>
</li>
</ul>
</div>
</div>
</div>
</section>
<!-- <section class="w-full py-12 md:py-24 lg:py-32 border-t">
<div
class="container grid items-center justify-center gap-4 px-4 text-center md:px-6"
>
<div class="space-y-3">
<h2 class="text-3xl font-bold tracking-tighter md:text-4xl/tight">
Explore the World's Most Breathtaking Destinations
</h2>
<p
class="mx-auto max-w-[600px] text-gray-500 md:text-xl/relaxed lg:text-base/relaxed xl:text-xl/relaxed dark:text-gray-400"
>
F
</p>
</div>
<div
aria-roledescription="carousel"
class="relative w-full max-w-5xl"
role="region"
>
<div class="overflow-hidden">
<div class="flex -ml-4" style="transform: translate3d(0px, 0px, 0px);">
<div
aria-roledescription="slide"
class="min-w-0 shrink-0 grow-0 basis-full pl-4 md:basis-1/2 lg:basis-1/3"
role="group"
>
<div class="p-1">
<div
class="rounded-lg border bg-card text-card-foreground shadow-sm"
data-v0-t="card"
>
<img
src="/placeholder.svg"
width="400"
height="300"
alt="Destination"
class="aspect-[4/3] overflow-hidden rounded-t-xl object-cover"
/>
<div class="space-y-2 p-4">
<h3 class="text-xl font-bold">Machu Pic</h3>
<p class="text-gray-500 dark:text-gray-400"></p>
</div>
</div>
</div>
</div>
<div
aria-roledescription="slide"
class="min-w-0 shrink-0 grow-0 basis-full pl-4 md:basis-1/2 lg:basis-1/3"
role="group"
>
<div class="p-1">
<div
class="rounded-lg border bg-card text-card-foreground shadow-sm"
data-v0-t="card"
>
<img
src="/placeholder.svg"
width="400"
height="300"
alt="Destination"
class="aspect-[4/3] overflow-hidden rounded-t-xl object-cover"
/>
<div class="space-y-2 p-4">
<h3 class="text-xl font-bold">Patagonia, Argentina</h3>
<p class="text-gray-500 dark:text-gray-400"></p>
</div>
</div>
</div>
</div>
<div
aria-roledescription="slide"
class="min-w-0 shrink-0 grow-0 basis-full pl-4 md:basis-1/2 lg:basis-1/3"
role="group"
>
<div class="p-1">
<div
class="rounded-lg border bg-card text-card-foreground shadow-sm"
data-v0-t="card"
>
<img
src="/placeholder.svg"
width="400"
height="300"
alt="Destination"
class="aspect-[4/3] overflow-hidden rounded-t-xl object-cover"
/>
<div class="space-y-2 p-4">
<h3 class="text-xl font-bold">Bali, Indonesia</h3>
<p class="text-gray-500 dark:text-gray-400">
Discover lush jungles, stunning beaches, and ancient
temples.
</p>
</div>
</div>
</div>
</div>
<div
aria-roledescription="slide"
class="min-w-0 shrink-0 grow-0 basis-full pl-4 md:basis-1/2 lg:basis-1/3"
role="group"
>
<div class="p-1">
<div
class="rounded-lg border bg-card text-card-foreground shadow-sm"
data-v0-t="card"
>
<img
src="/placeholder.svg"
width="400"
height="300"
alt="Destination"
class="aspect-[4/3] overflow-hidden rounded-t-xl object-cover"
/>
<div class="space-y-2 p-4">
<h3 class="text-xl font-bold">Banff, Canada</h3>
<p class="text-gray-500 dark:text-gray-400"></p>
</div>
</div>
</div>
</div>
</div>
</div>
<button
class="inline-flex items-center justify-center whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground absolute h-8 w-8 rounded-full -left-12 top-1/2 -translate-y-1/2"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="h-4 w-4"
>
<path d="m12 19-7-7 7-7"></path>
<path d="M19 12H5"></path>
</svg>
<span class="sr-only">Previous slide</span>
</button>
<button
class="inline-flex items-center justify-center whitespace-nowrap text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground absolute h-8 w-8 rounded-full -right-12 top-1/2 -translate-y-1/2"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="h-4 w-4"
>
<path d="M5 12h14"></path>
<path d="m12 5 7 7-7 7"></path>
</svg>
<span class="sr-only">Next slide</span>
</button>
</div>
</div>
</section> -->
<svelte:head> <svelte:head>
<title>Home | AdventureLog</title> <title>Home | AdventureLog</title>

View file

@ -180,7 +180,7 @@ export async function PUT(event: RequestEvent): Promise<Response> {
}); });
} }
const { name, location, date, description, activityTypes, id, rating } = const { name, location, date, description, activityTypes, id, rating, type } =
body.detailAdventure; body.detailAdventure;
if (!name) { if (!name) {
@ -189,11 +189,18 @@ export async function PUT(event: RequestEvent): Promise<Response> {
}); });
} }
if (type == "featured") {
return error(400, {
message: "Featured adventures cannot be created at the moment",
});
}
// update the adventure in the user's visited list // update the adventure in the user's visited list
await db await db
.update(adventureTable) .update(adventureTable)
.set({ .set({
name: name, name: name,
type: type,
location: location, location: location,
date: date, date: date,
description: description, description: description,

View file

@ -8,6 +8,7 @@
saveAdventure, saveAdventure,
removeAdventure, removeAdventure,
addAdventure, addAdventure,
changeType,
} from "../../services/adventureService.js"; } from "../../services/adventureService.js";
import SucessToast from "$lib/components/SucessToast.svelte"; import SucessToast from "$lib/components/SucessToast.svelte";
import mapDrawing from "$lib/assets/adventure_map.svg"; import mapDrawing from "$lib/assets/adventure_map.svg";
@ -87,6 +88,18 @@
showToast("Failed to add adventure"); showToast("Failed to add adventure");
} }
}; };
async function markVisited(event: { detail: Adventure }) {
let initialLength: number = plans.length;
let newArray = await changeType(event.detail, "mylog", plans);
if (newArray.length + 1 == initialLength) {
plans = newArray;
showToast("Adventure moved to visit log!");
} else {
showToast("Failed to moves adventure");
}
adventureToEdit = undefined;
}
</script> </script>
{#if isShowingToast} {#if isShowingToast}
@ -131,6 +144,7 @@
type="planner" type="planner"
on:edit={editPlan} on:edit={editPlan}
on:remove={remove} on:remove={remove}
on:markVisited={markVisited}
/> />
{/each} {/each}
</div> </div>
@ -153,3 +167,52 @@
type="planner" type="planner"
/> />
{/if} {/if}
<!-- ----------------------- -->
<!-- {#if plans.length == 0 && !isLoading}
<div class="flex flex-col items-center justify-center mt-16">
<article class="prose mb-4"><h2>Add some adventures!</h2></article>
<img src={mapDrawing} width="25%" alt="Logo" />
</div>
{/if}
{#if plans.length != 0 && !isLoading}
<div class="flex justify-center items-center w-full mt-4">
<article class="prose">
<h2 class="text-center">Actions</h2>
</article>
</div>
<div
class="flex flex-row items-center justify-center mt-2 gap-4 mb-4 flex-wrap"
>
<button class="btn btn-neutral" on:click={exportData}>
<img src={exportFile} class="inline-block -mt-1" alt="Logo" /> Save as File
</button>
<button class="btn btn-neutral" on:click={() => (confirmModalOpen = true)}>
<img src={deleteIcon} class="inline-block -mt-1" alt="Logo" /> Delete Data
</button>
<button class="btn btn-neutral" on:click={shareLink}>
<iconify-icon icon="mdi:share-variant" class="text-xl"></iconify-icon> Share
as Link
</button>
</div>
{/if}
{#if confirmModalOpen}
<ConfirmModal
on:close={handleClose}
on:confirm={deleteData}
title="Delete all Adventures"
isWarning={false}
message="Are you sure you want to delete all adventures?"
/>
{/if} -->
<svelte:head>
<title>My Plans | AdventureLog</title>
<meta
name="description"
content="Create and manage your adventure plans here!"
/>
</svelte:head>

View file

@ -124,6 +124,37 @@ export async function addAdventure(
return adventureArray; return adventureArray;
} }
export async function changeType(
newAdventure: Adventure,
newType: string,
adventureArray: Adventure[]
) {
newAdventure.type = newType;
let detailAdventure = newAdventure;
const response = await fetch("/api/visits", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ detailAdventure }),
});
if (response.ok) {
// remove adventure from array where id matches
adventureArray = adventureArray.filter(
(existingAdventure) => existingAdventure.id !== newAdventure.id
);
// showToast("Adventure removed successfully!");
} else {
console.error("Error:", response.statusText);
adventureArray = [];
}
console.log(adventureArray);
return adventureArray;
}
/** /**
* Increments the visit count by the specified amount. * Increments the visit count by the specified amount.
* @param {number} amount - The amount to increment the visit count by. * @param {number} amount - The amount to increment the visit count by.