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

Merge pull request #51 from seanmorley15/development

Development
This commit is contained in:
Sean Morley 2024-04-28 12:04:26 -04:00 committed by GitHub
commit aec34a617f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 437 additions and 323 deletions

View file

@ -9,7 +9,4 @@ services:
- ORIGIN=http://localhost:3000 - ORIGIN=http://localhost:3000
- SKIP_DB_WAIT=true - SKIP_DB_WAIT=true
# Only necessary for externaly hosted databases such as NeonDB # Only necessary for externaly hosted databases such as NeonDB
volumes: # docker compose -f ./compose-dev.yml up --build
- ./sql:/sql
# docker compose -f ./compose-dev.yml up --build

View file

@ -11,8 +11,6 @@ services:
# Only necessary for externaly hosted databases such as NeonDB # Only necessary for externaly hosted databases such as NeonDB
depends_on: depends_on:
- db - db
volumes:
- ./sql:/sql
db: db:
image: postgres image: postgres
environment: environment:

View file

@ -4,38 +4,31 @@
import calendar from "$lib/assets/calendar.svg"; import calendar from "$lib/assets/calendar.svg";
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import { desc } from "drizzle-orm"; import { desc } from "drizzle-orm";
import type { Adventure } from "$lib/utils/types";
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
export let type: String; export let type: String;
export let name: String | undefined = undefined; export let adventure: Adventure;
export let location: String | undefined = undefined;
export let date: String | undefined = undefined; // export let name: String | undefined = undefined;
export let id: Number | undefined = undefined; // export let location: String | undefined = undefined;
export let regionId: String | undefined = undefined; // export let date: String | undefined = undefined;
export let visited: Boolean | undefined = undefined; // export let id: Number | undefined = undefined;
export let countryCode: String | undefined = undefined;
function remove() { function remove() {
dispatch("remove", id); dispatch("remove", adventure.id);
} }
function edit() { function edit() {
dispatch("edit", id); dispatch("edit", adventure.id);
} }
function add() { function add() {
dispatch("add", { name, location }); dispatch("add", adventure);
}
function markVisited() {
dispatch("markVisited", regionId);
visited = true;
}
function removeVisit() {
dispatch("removeVisit", regionId);
visited = false;
} }
function moreInfo() { function moreInfo() {
goto(`/worldtravel/${countryCode}/${regionId}`); console.log(adventure.id);
goto(`/adventure/${adventure.id}`);
} }
</script> </script>
@ -43,26 +36,39 @@
class="card min-w-max lg:w-96 md:w-80 sm:w-60 xs:w-40 bg-primary-content shadow-xl overflow-hidden text-base-content" class="card min-w-max lg:w-96 md:w-80 sm:w-60 xs:w-40 bg-primary-content shadow-xl overflow-hidden text-base-content"
> >
<div class="card-body"> <div class="card-body">
<h2 class="card-title overflow-ellipsis">{name}</h2> <h2 class="card-title overflow-ellipsis">{adventure.name}</h2>
{#if location && location !== ""} {#if adventure.location && adventure.location !== ""}
<div class="inline-flex items-center"> <div class="inline-flex items-center">
<iconify-icon icon="mdi:map-marker" class="text-xl"></iconify-icon> <iconify-icon icon="mdi:map-marker" class="text-xl"></iconify-icon>
<p class="ml-.5">{location}</p> <p class="ml-.5">{adventure.location}</p>
</div> </div>
{/if} {/if}
{#if date && date !== ""} {#if adventure.date && adventure.date !== ""}
<div class="inline-flex items-center"> <div class="inline-flex items-center">
<iconify-icon icon="mdi:calendar" class="text-xl"></iconify-icon> <iconify-icon icon="mdi:calendar" class="text-xl"></iconify-icon>
<p class="ml-1">{date}</p> <p class="ml-1">{adventure.date}</p>
</div> </div>
{/if} {/if}
<div class="card-actions justify-end"> <div class="card-actions justify-end">
{#if type == "mylog"} {#if type == "mylog"}
<button class="btn btn-primary" on:click={edit}>Edit</button> <button class="btn btn-primary" on:click={moreInfo}
<button class="btn btn-secondary" on:click={remove}>Remove</button> ><iconify-icon icon="mdi:launch" class="text-2xl"
></iconify-icon></button
>
<button class="btn btn-primary" on:click={edit}
><iconify-icon icon="mdi:file-document-edit" class="text-2xl"
></iconify-icon></button
>
<button class="btn btn-secondary" on:click={remove}
><iconify-icon icon="mdi:trash-can-outline" class="text-2xl"
></iconify-icon></button
>
{/if} {/if}
{#if type == "featured"} {#if type == "featured"}
<button class="btn btn-primary" on:click={add}>Add</button> <button class="btn btn-primary" on:click={add}
><iconify-icon icon="mdi:plus" class="text-2xl"
></iconify-icon></button
>
{/if} {/if}
</div> </div>
</div> </div>

View file

@ -1,15 +1,12 @@
<script lang="ts"> <script lang="ts">
export let editId: number = NaN; export let adventureToEdit: Adventure;
export let editName: string = "";
export let editLocation: string = "";
export let editdate: string = "";
import { createEventDispatcher } from "svelte"; import { createEventDispatcher } from "svelte";
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";
let modal: HTMLDialogElement; let modal: HTMLDialogElement;
let originalName = editName; let originalName = adventureToEdit.name;
onMount(() => { onMount(() => {
modal = document.getElementById("my_modal_1") as HTMLDialogElement; modal = document.getElementById("my_modal_1") as HTMLDialogElement;
@ -19,14 +16,8 @@
}); });
function submit() { function submit() {
const adventureEdited: Adventure = { dispatch("submit", adventureToEdit);
id: editId, console.log(adventureToEdit);
name: editName,
location: editLocation,
date: editdate,
};
dispatch("submit", adventureEdited);
console.log(adventureEdited);
} }
function close() { function close() {
@ -56,7 +47,7 @@
<input <input
type="text" type="text"
id="name" id="name"
bind:value={editName} bind:value={adventureToEdit.name}
class="input input-bordered w-full max-w-xs" class="input input-bordered w-full max-w-xs"
/> />
</div> </div>
@ -65,16 +56,25 @@
<input <input
type="text" type="text"
id="location" id="location"
bind:value={editLocation} bind:value={adventureToEdit.location}
class="input input-bordered w-full max-w-xs" class="input input-bordered w-full max-w-xs"
/> />
</div> </div>
<div> <div>
<label for="date">date</label> <label for="date">Date</label>
<input <input
type="date" type="date"
id="date" id="date"
bind:value={editdate} bind:value={adventureToEdit.date}
class="input input-bordered w-full max-w-xs"
/>
</div>
<div>
<label for="date">Description</label>
<input
type="text"
id="description"
bind:value={adventureToEdit.description}
class="input input-bordered w-full max-w-xs" class="input input-bordered w-full max-w-xs"
/> />
</div> </div>

View file

@ -0,0 +1,95 @@
<script lang="ts">
let newAdventure: Adventure;
newAdventure = {
id: -1,
type: "mylog",
name: "",
location: "",
date: "",
};
import { createEventDispatcher } from "svelte";
import type { Adventure } from "$lib/utils/types";
const dispatch = createEventDispatcher();
import { onMount } from "svelte";
let modal: HTMLDialogElement;
onMount(() => {
modal = document.getElementById("my_modal_1") as HTMLDialogElement;
if (modal) {
modal.showModal();
}
});
function create() {
dispatch("create", newAdventure);
console.log(newAdventure);
}
function close() {
dispatch("close");
}
function handleKeydown(event: KeyboardEvent) {
if (event.key === "Escape") {
close();
}
}
</script>
<dialog id="my_modal_1" class="modal">
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div class="modal-box" role="dialog" on:keydown={handleKeydown} tabindex="0">
<h3 class="font-bold text-lg">New Adventure</h3>
<p class="py-4">Press ESC key or click the button below to close</p>
<div
class="modal-action items-center"
style="display: flex; flex-direction: column; align-items: center; width: 100%;"
>
<form method="dialog" style="width: 100%;">
<div>
<label for="name">Name</label>
<input
type="text"
id="name"
bind:value={newAdventure.name}
class="input input-bordered w-full max-w-xs"
/>
</div>
<div>
<label for="location">Location</label>
<input
type="text"
id="location"
bind:value={newAdventure.location}
class="input input-bordered w-full max-w-xs"
/>
</div>
<div>
<label for="date">date</label>
<input
type="date"
id="date"
bind:value={newAdventure.date}
class="input input-bordered w-full max-w-xs"
/>
</div>
<div>
<label for="date">Description</label>
<input
type="text"
id="description"
bind:value={newAdventure.description}
class="input input-bordered w-full max-w-xs"
/>
</div>
<button class="btn btn-primary mr-4 mt-4" on:click={create}>Save</button
>
<!-- if there is a button in form, it will close the modal -->
<button class="btn mt-4" on:click={close}>Close</button>
</form>
</div>
</div>
</dialog>

View file

@ -78,6 +78,10 @@
<button class="btn btn-primary my-2 md:my-0 md:mr-4" on:click={goToLog} <button class="btn btn-primary my-2 md:my-0 md:mr-4" on:click={goToLog}
>My Log</button >My Log</button
> >
<!-- <button
class="btn btn-primary my-2 md:my-0 md:mr-4"
on:click={() => goto("/planner")}>Planner</button
> -->
{/if} {/if}
<button <button
class="btn btn-primary my-2 md:my-0 md:mr-4" class="btn btn-primary my-2 md:my-0 md:mr-4"

View file

@ -7,7 +7,10 @@
<div class="card w-96 shadow-xl bg-primary-content"> <div class="card w-96 shadow-xl bg-primary-content">
<div class="card-body"> <div class="card-body">
<h2 class="card-title">{user.first_name} {user.last_name}</h2> <h2 class="card-title">{user.first_name} {user.last_name}</h2>
<p>{user.username} - {user.icon}</p> <p>
{user.username}{#if user.icon}
- {user.icon}{/if}
</p>
<p>Last Login: {user.last_login}</p> <p>Last Login: {user.last_login}</p>
<p>date: {user.signup_date}</p> <p>date: {user.signup_date}</p>
<p>{user.role}</p> <p>{user.role}</p>

View file

@ -1,192 +1,56 @@
{ {
"quotes": [ "quotes": [
{ {
"quote": "Believe you can and you're halfway there.", "quote": "A journey of a thousand miles begins with a single step.",
"author": "Theodore Roosevelt" "author": "Lao Tzu"
}, },
{ {
"quote": "The only way to do great work is to love what you do.", "quote": "If we were meant to stay in one place, wed have roots instead of feet.",
"author": "Steve Jobs" "author": "Rachel Wolchin"
}, },
{ {
"quote": "In the middle of every difficulty lies opportunity.", "quote": "Adventure isnt hanging on a rope off the side of a mountain. Adventure is an attitude that we must apply to the day to day obstacles in life.",
"author": "Albert Einstein" "author": "John Amatt"
}, },
{ {
"quote": "The future belongs to those who believe in the beauty of their dreams.", "quote": "Wherever you go, go with all your heart.",
"author": "Eleanor Roosevelt" "author": "Confucius"
}, },
{ {
"quote": "It does not matter how slowly you go as long as you do not stop.", "quote": "Until you step into the unknown, you dont know what youre made of.",
"author": "Confucius" "author": "Roy T. Bennett"
}, },
{ {
"quote": "Success is not final, failure is not fatal: It is the courage to continue that counts.", "quote": "You cant control the past, but you can control where you go next.",
"author": "Winston Churchill" "author": "Kirsten Hubbard"
}, },
{ {
"quote": "The only limit to our realization of tomorrow will be our doubts of today.", "quote": "Life isnt about finding yourself. Life is about creating yourself.",
"author": "Franklin D. Roosevelt" "author": "George Bernard Shaw"
}, },
{ {
"quote": "Don't watch the clock; do what it does. Keep going.", "quote": "It is not the mountain we conquer, but ourselves.",
"author": "Sam Levenson" "author": "Edmund Hillary"
}, },
{ {
"quote": "You are never too old to set another goal or to dream a new dream.", "quote": "I am not the same, having seen the moon shine on the other side of the world.",
"author": "C.S. Lewis" "author": "Mary Anne Radmacher"
}, },
{ {
"quote": "The only person you are destined to become is the person you decide to be.", "quote": "A mind that is stretched by a new experience can never go back to its old dimensions.",
"author": "Ralph Waldo Emerson" "author": "Oliver Wendell Holmes"
}, },
{ {
"quote": "Happiness is not something ready-made. It comes from your own actions.", "quote": "Life is short and the world is wide.",
"author": "Dalai Lama" "author": "Simon Raven"
}, },
{ {
"quote": "Life is what happens when you're busy making other plans.", "quote": "Only those who risk going too far can possibly find out how far they can go.",
"author": "John Lennon" "author": "T.S. Eliot"
}, },
{ {
"quote": "You miss 100% of the shots you don't take.", "quote": "Believe you can and you're halfway there.",
"author": "Wayne Gretzky" "author": "Theodore Roosevelt"
}, }
{ ]
"quote": "The best time to plant a tree was 20 years ago. The second best time is now.",
"author": "Chinese Proverb"
},
{
"quote": "The only way to achieve the impossible is to believe it is possible.",
"author": "Charles Kingsleigh"
},
{
"quote": "Don't count the days, make the days count.",
"author": "Muhammad Ali"
},
{
"quote": "You don't have to be great to start, but you have to start to be great.",
"author": "Zig Ziglar"
},
{
"quote": "You can't go back and change the beginning, but you can start where you are and change the ending.",
"author": "C.S. Lewis"
},
{
"quote": "Dream big and dare to fail.",
"author": "Norman Vaughan"
},
{
"quote": "The secret of getting ahead is getting started.",
"author": "Mark Twain"
},
{
"quote": "Everything you can imagine is real.",
"author": "Pablo Picasso"
},
{
"quote": "You must be the change you wish to see in the world.",
"author": "Mahatma Gandhi"
},
{
"quote": "If you want to lift yourself up, lift up someone else.",
"author": "Booker T. Washington"
},
{
"quote": "Believe in yourself and all that you are. Know that there is something inside you that is greater than any obstacle.",
"author": "Christian D. Larson"
},
{
"quote": "The journey of a thousand miles begins with one step.",
"author": "Lao Tzu"
},
{
"quote": "Life isn't about waiting for the storm to pass, it's about learning to dance in the rain.",
"author": "Vivian Greene"
},
{
"quote": "You are never too old to set another goal or to dream a new dream.",
"author": "Les Brown"
},
{
"quote": "Your time is limited, don't waste it living someone else's life.",
"author": "Steve Jobs"
},
{
"quote": "Don't let yesterday take up too much of today.",
"author": "Will Rogers"
},
{
"quote": "The only thing standing between you and your goal is the story you keep telling yourself as to why you can't achieve it.",
"author": "Jordan Belfort"
},
{
"quote": "The future belongs to those who prepare for it today.",
"author": "Malcolm X"
},
{
"quote": "The greatest glory in living lies not in never falling, but in rising every time we fall.",
"author": "Nelson Mandela"
},
{
"quote": "It's not what happens to you, but how you react to it that matters.",
"author": "Epictetus"
},
{
"quote": "When one door of happiness closes, another opens, but often we look so long at the closed door that we do not see the one that has been opened for us.",
"author": "Helen Keller"
},
{
"quote": "The only thing that stands between you and your dream is the will to try and the belief that it is actually possible.",
"author": "Joel Brown"
},
{
"quote": "Success is walking from failure to failure with no loss of enthusiasm.",
"author": "Winston Churchill"
},
{
"quote": "Believe in yourself! Have faith in your abilities! Without a humble but reasonable confidence in your own powers you cannot be successful or happy.",
"author": "Norman Vincent Peale"
},
{
"quote": "The greatest adventure is what lies ahead.",
"author": "J.R.R. Tolkien"
},
{
"quote": "What you get by achieving your goals is not as important as what you become by achieving your goals.",
"author": "Zig Ziglar"
},
{
"quote": "To be yourself in a world that is constantly trying to make you something else is the greatest accomplishment.",
"author": "Ralph Waldo Emerson"
},
{
"quote": "What lies behind us and what lies before us are tiny matters compared to what lies within us.",
"author": "Ralph Waldo Emerson"
},
{
"quote": "The best and most beautiful things in the world cannot be seen or even touched - they must be felt with the heart.",
"author": "Helen Keller"
},
{
"quote": "I can't change the direction of the wind, but I can adjust my sails to always reach my destination.",
"author": "Jimmy Dean"
},
{
"quote": "If you're going through hell, keep going.",
"author": "Winston Churchill"
},
{
"quote": "Nothing is impossible, the word itself says 'I'm possible'!",
"author": "Audrey Hepburn"
},
{
"quote": "Keep your face always toward the sunshine - and shadows will fall behind you.",
"author": "Walt Whitman"
},
{
"quote": "Success is not the key to happiness. Happiness is the key to success. If you love what you are doing, you will be successful.",
"author": "Albert Schweitzer"
}
]
} }

View file

@ -1,8 +1,12 @@
import type { LayoutServerLoad, PageServerLoad } from "./$types"; import type { LayoutServerLoad, PageServerLoad } from "./$types";
let USING_VERCEL: string; let USING_VERCEL: string;
try { try {
USING_VERCEL = require("$env/static/private").USING_VERCEL; const env = await import("$env/static/private");
} catch (error) {} USING_VERCEL = env.USING_VERCEL;
} catch (error) {
USING_VERCEL = "false";
}
export const load: LayoutServerLoad = async (event) => { export const load: LayoutServerLoad = async (event) => {
if (event.locals.user) { if (event.locals.user) {

View file

@ -14,6 +14,8 @@
if (data.usingVercel === "true") { if (data.usingVercel === "true") {
inject(); inject();
injectSpeedInsights(); injectSpeedInsights();
} else {
// console.log("Not using Vercel");
} }
let isServerSetup = data.isServerSetup; let isServerSetup = data.isServerSetup;

View file

@ -35,9 +35,17 @@ export const actions: Actions = {
// change the theme only if it is one of the allowed themes // change the theme only if it is one of the allowed themes
if ( if (
theme && theme &&
["light", "dark", "night", "retro", "forest", "aqua", "forest"].includes( [
theme "light",
) "dark",
"night",
"retro",
"forest",
"aqua",
"forest",
"garden",
"emerald",
].includes(theme)
) { ) {
cookies.set("colortheme", theme, { cookies.set("colortheme", theme, {
path: "/", path: "/",

View file

@ -0,0 +1,32 @@
import { redirect } from "@sveltejs/kit";
import type { PageServerLoad } from "./$types";
import { db } from "$lib/db/db.server";
import { and, eq } from "drizzle-orm";
import { adventureTable } from "$lib/db/schema";
export const load = (async (event) => {
if (!event.locals.user) {
return redirect(302, "/login");
}
let adventureUserId = await db
.select({ userId: adventureTable.userId })
.from(adventureTable)
.where(eq(adventureTable.id, Number(event.params.id)))
.limit(1)
.execute();
console.log(adventureUserId);
if (
adventureUserId &&
adventureUserId[0]?.userId !== event.locals.user.id &&
adventureUserId !== null
) {
return redirect(302, "/log");
}
let adventure = await event.fetch(`/api/adventure?id=${event.params.id}`);
return { adventure: await adventure.json() };
}) satisfies PageServerLoad;

View file

@ -0,0 +1,66 @@
<script lang="ts">
import type { Adventure } from "$lib/utils/types";
import { onMount } from "svelte";
import type { PageData } from "./$types";
import { goto } from "$app/navigation";
export let data: PageData;
let adventure: Adventure;
onMount(() => {
if (data.adventure.adventure) {
adventure = data.adventure.adventure[0];
} else {
goto("/404");
}
});
</script>
{#if !adventure}
<div class="flex justify-center items-center w-full mt-16">
<span class="loading loading-spinner w-24 h-24"></span>
</div>
{:else}
{#if adventure.name}
<h1 class="text-center font-extrabold text-4xl mb-2">{adventure.name}</h1>
{/if}
{#if adventure.location}
<p class="text-center text-2xl">
<iconify-icon icon="mdi:map-marker" class="text-xl -mb-0.5"
></iconify-icon>{adventure.location}
</p>
{/if}
{#if adventure.date}
<p class="text-center text-lg mt-4 pl-16 pr-16">
Visited on: {adventure.date}
</p>
{/if}
{#if adventure.rating !== undefined && adventure.rating !== null}
<div class="flex justify-center items-center">
<div class="rating" aria-readonly="true">
{#each Array.from({ length: 5 }, (_, i) => i + 1) as star}
<input
type="radio"
name="rating-1"
class="mask mask-star"
checked={star <= adventure.rating}
disabled
/>
{/each}
</div>
</div>
{/if}
{#if adventure.description}
<p class="text-center text-lg mt-4 pl-16 pr-16">{adventure.description}</p>
{/if}
{#if adventure.imageUrl}
<div class="flex content-center justify-center">
<img
src={adventure.imageUrl}
alt={adventure.name}
class="w-50 mt-4 align-middle rounded-lg shadow-lg"
/>
</div>
{/if}
{/if}

View file

@ -0,0 +1,45 @@
import { db } from "$lib/db/db.server";
import { adventureTable } from "$lib/db/schema";
import { json, type RequestEvent, type RequestHandler } from "@sveltejs/kit";
import { and, eq } from "drizzle-orm";
/**
* Handles the GET request for retrieving an adventure by ID.
* @param {Request} request - The request object.
* @param {Response} response - The response object.
* @returns {Promise<void>} - A promise that resolves when the request is handled.
*/
export const GET: RequestHandler = async ({ url, locals }) => {
const id = url.searchParams.get("id");
const user = locals.user;
if (!user) {
return json({ error: "Unauthorized" }, { status: 401 });
}
if (!id) {
return json({ error: "Missing adventure ID" }, { status: 400 });
}
const adventure = await db
.select()
.from(adventureTable)
.where(
and(
eq(adventureTable.id, Number(id)), // Convert id to number
eq(adventureTable.userId, user.id),
eq(adventureTable.type, "mylog")
)
)
.limit(1)
.execute();
if (adventure.length === 0) {
return json({ error: "Adventure not found" }, { status: 404 });
}
// console.log("GET /api/adventure?id=", id);
// console.log("User:", user);
return json({ adventure }, { status: 200 });
};

View file

@ -86,7 +86,7 @@ export async function POST(event: RequestEvent): Promise<Response> {
const { newAdventure } = await event.request.json(); const { newAdventure } = await event.request.json();
console.log(newAdventure); console.log(newAdventure);
const { name, location, date } = newAdventure; const { name, location, date, description } = newAdventure;
// insert the adventure to the user's visited list // insert the adventure to the user's visited list
await db await db
@ -97,6 +97,7 @@ export async function POST(event: RequestEvent): Promise<Response> {
name: name, name: name,
location: location, location: location,
date: date, date: date,
description: description,
}) })
.execute(); .execute();
let res = await db let res = await db
@ -107,7 +108,8 @@ export async function POST(event: RequestEvent): Promise<Response> {
eq(adventureTable.userId, event.locals.user.id), eq(adventureTable.userId, event.locals.user.id),
eq(adventureTable.name, name), eq(adventureTable.name, name),
eq(adventureTable.location, location), eq(adventureTable.location, location),
eq(adventureTable.date, date) eq(adventureTable.date, date),
eq(adventureTable.description, description)
) )
) )
.execute(); .execute();
@ -142,7 +144,7 @@ export async function PUT(event: RequestEvent): Promise<Response> {
// get properties from the body // get properties from the body
const { newAdventure } = await event.request.json(); const { newAdventure } = await event.request.json();
console.log(newAdventure); console.log(newAdventure);
const { name, location, date, id } = newAdventure; const { name, location, date, id, description } = newAdventure;
// update the adventure in the user's visited list // update the adventure in the user's visited list
await db await db
@ -151,6 +153,7 @@ export async function PUT(event: RequestEvent): Promise<Response> {
name: name, name: name,
location: location, location: location,
date: date, date: date,
description: description,
}) })
.where( .where(
and( and(
@ -162,7 +165,7 @@ export async function PUT(event: RequestEvent): Promise<Response> {
return new Response( return new Response(
JSON.stringify({ JSON.stringify({
adventure: { id, name, location, date }, adventure: { id, name, location, date, description },
message: { message: "Adventure updated" }, message: { message: "Adventure updated" },
}), }),
{ {

View file

@ -10,11 +10,10 @@
count = value; count = value;
}); });
async function add(event: CustomEvent<{ name: string; location: string }>) { async function add(event: CustomEvent<Adventure>) {
let newAdventure: Adventure = { let newAdventure: Adventure = {
name: event.detail.name, name: event.detail.name,
location: event.detail.location, location: event.detail.location,
date: "",
type: "mylog", type: "mylog",
id: -1, id: -1,
}; };
@ -47,14 +46,7 @@
class="grid xl:grid-cols-3 lg:grid-cols-3 md:grid-cols-2 sm:grid-cols-1 gap-4 mt-4 content-center auto-cols-auto ml-6 mr-6" class="grid xl:grid-cols-3 lg:grid-cols-3 md:grid-cols-2 sm:grid-cols-1 gap-4 mt-4 content-center auto-cols-auto ml-6 mr-6"
> >
{#each data.result as adventure (adventure.id)} {#each data.result as adventure (adventure.id)}
<AdventureCard <AdventureCard type="featured" on:add={add} {adventure} />
type="featured"
on:add={add}
name={adventure.name}
location={adventure.location}
date=""
id={NaN}
/>
{/each} {/each}
</div> </div>

View file

@ -13,14 +13,14 @@
import EditModal from "$lib/components/EditModal.svelte"; import EditModal from "$lib/components/EditModal.svelte";
import { generateRandomString } from "$lib"; import { generateRandomString } from "$lib";
import { visitCount } from "$lib/utils/stores/visitCountStore"; import { visitCount } from "$lib/utils/stores/visitCountStore";
import MoreFieldsInput from "$lib/components/MoreFieldsInput.svelte";
let newName = ""; let newName = "";
let newLocation = ""; let newLocation = "";
let editId: number = NaN; let isShowingMoreFields = false;
let editName: string = "";
let editLocation: string = ""; let adventureToEdit: Adventure | undefined;
let editdate: string = "";
let isShowingToast: boolean = false; let isShowingToast: boolean = false;
let toastAction: string = ""; let toastAction: string = "";
@ -59,16 +59,13 @@
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
} }
const createNewAdventure = () => { const createNewAdventure = (event: { detail: Adventure }) => {
let currentDate = new Date();
let dateString = currentDate.toISOString().slice(0, 10); // Get date in "yyyy-mm-dd" format
// post to /api/visits
let newAdventure: Adventure = { let newAdventure: Adventure = {
type: "mylog", type: "mylog",
name: newName, name: event.detail.name,
location: newLocation, location: event.detail.location,
date: dateString, date: event.detail.date,
description: event.detail.description,
id: -1, id: -1,
}; };
@ -90,9 +87,10 @@
{ {
id: newId, id: newId,
type: "mylog", type: "mylog",
name: newName, name: event.detail.name,
location: newLocation, location: event.detail.location,
date: dateString, date: event.detail.date,
description: event.detail.description,
}, },
]; ];
newName = ""; // Reset newName and newLocation after adding adventure newName = ""; // Reset newName and newLocation after adding adventure
@ -114,6 +112,7 @@
location: event.detail.location, location: event.detail.location,
date: event.detail.date, date: event.detail.date,
id: event.detail.id, id: event.detail.id,
description: event.detail.description,
}; };
// put request to /api/visits with id and advneture data // put request to /api/visits with id and advneture data
@ -133,10 +132,7 @@
adventures = adventures.map((adventure) => adventures = adventures.map((adventure) =>
adventure.id === event.detail.id ? event.detail : adventure adventure.id === event.detail.id ? event.detail : adventure
); );
editId = NaN; adventureToEdit = undefined;
editName = "";
editLocation = "";
editdate = "";
showToast("Adventure edited successfully!"); showToast("Adventure edited successfully!");
}) })
.catch((error) => { .catch((error) => {
@ -149,10 +145,7 @@
(adventure) => adventure.id === event.detail (adventure) => adventure.id === event.detail
); );
if (adventure) { if (adventure) {
editId = adventure.id || 0; adventureToEdit = adventure;
editName = adventure.name || "";
editLocation = adventure.location || "";
editdate = adventure.date || "";
} }
} }
@ -179,10 +172,8 @@
} }
function handleClose() { function handleClose() {
editId = NaN; adventureToEdit = undefined;
editName = ""; isShowingMoreFields = false;
editLocation = "";
editdate = "";
} }
function deleteData() { function deleteData() {
@ -238,21 +229,13 @@
</div> </div>
<div class="flex flex-row items-center justify-center gap-4"> <div class="flex flex-row items-center justify-center gap-4">
<form on:submit={createNewAdventure} class="flex gap-2"> <button
<input type="button"
type="text" class="btn btn-secondary"
bind:value={newName} on:click={() => (isShowingMoreFields = !isShowingMoreFields)}
placeholder="Adventure Name" >
class="input input-bordered w-full max-w-xs" Show More Fields
/> </button>
<input
type="text"
bind:value={newLocation}
placeholder="Adventure Location"
class="input input-bordered w-full max-w-xs"
/>
<input class="btn btn-primary" type="submit" value="Add Adventure" />
</form>
</div> </div>
{#if adventures.length != 0} {#if adventures.length != 0}
<div class="flex justify-center items-center w-full mt-4 mb-4"> <div class="flex justify-center items-center w-full mt-4 mb-4">
@ -272,12 +255,17 @@
<SucessToast action={toastAction} /> <SucessToast action={toastAction} />
{/if} {/if}
{#if !Number.isNaN(editId)} {#if isShowingMoreFields}
<MoreFieldsInput
on:create={createNewAdventure}
on:close={handleClose}
on:submit={saveAdventure}
/>
{/if}
{#if adventureToEdit && adventureToEdit.id != undefined}
<EditModal <EditModal
bind:editId bind:adventureToEdit
bind:editName
bind:editLocation
bind:editdate
on:submit={saveAdventure} on:submit={saveAdventure}
on:close={handleClose} on:close={handleClose}
/> />
@ -288,11 +276,8 @@
> >
{#each adventures as adventure (adventure.id)} {#each adventures as adventure (adventure.id)}
<AdventureCard <AdventureCard
{adventure}
type="mylog" type="mylog"
id={adventure.id}
name={adventure.name}
location={adventure.location}
date={adventure.date}
on:edit={editAdventure} on:edit={editAdventure}
on:remove={removeAdventure} on:remove={removeAdventure}
/> />

View file

View file

@ -0,0 +1 @@
<h1>Welcome to the planner</h1>

View file

@ -8,7 +8,7 @@ import {
userVisitedWorldTravel, userVisitedWorldTravel,
} from "$lib/db/schema"; } from "$lib/db/schema";
import type { DatabaseUser } from "$lib/server/auth"; import type { DatabaseUser } from "$lib/server/auth";
import { count } from "drizzle-orm"; import { count, eq } from "drizzle-orm";
export const load: PageServerLoad = async (event) => { export const load: PageServerLoad = async (event) => {
let users: DatabaseUser[] = []; let users: DatabaseUser[] = [];
@ -26,6 +26,7 @@ export const load: PageServerLoad = async (event) => {
visitCount = (await db visitCount = (await db
.select({ count: count() }) .select({ count: count() })
.from(adventureTable) .from(adventureTable)
.where(eq(adventureTable.type, "mylog"))
.execute()) as unknown as number; .execute()) as unknown as number;
userCount = (await db userCount = (await db
.select({ count: count() }) .select({ count: count() })

View file

@ -2,6 +2,10 @@
import { enhance } from "$app/forms"; import { enhance } from "$app/forms";
let loading = false; let loading = false;
function toggleLoad() {
loading = !loading;
}
</script> </script>
<h1 class="text-center font-bold text-4xl">AdventureLog Setup</h1> <h1 class="text-center font-bold text-4xl">AdventureLog Setup</h1>
@ -16,7 +20,7 @@
<h2 class="text-center font-bold text-2xl mt-6">Create Admin User</h2> <h2 class="text-center font-bold text-2xl mt-6">Create Admin User</h2>
<div class="flex justify-center"> <div class="flex justify-center">
<form method="post" use:enhance class="w-full max-w-xs"> <form method="post" use:enhance={toggleLoad} class="w-full max-w-xs">
<label for="username">Username</label> <label for="username">Username</label>
<input <input
name="username" name="username"
@ -59,4 +63,4 @@
name="description" name="description"
content="Setup AdventureLog with your admin account" content="Setup AdventureLog with your admin account"
/> />
</svelte:head>; </svelte:head>

View file

@ -2,6 +2,7 @@
import type { Adventure } from "$lib/utils/types"; import type { Adventure } from "$lib/utils/types";
export let data; export let data;
let array = data.adventureArray as Adventure[]; let array = data.adventureArray as Adventure[];
console.log(array);
import AdventureCard from "$lib/components/AdventureCard.svelte"; import AdventureCard from "$lib/components/AdventureCard.svelte";
</script> </script>
@ -20,13 +21,7 @@
class="grid xl:grid-cols-3 lg:grid-cols-3 md:grid-cols-2 sm:grid-cols-1 gap-4 mt-4 content-center auto-cols-auto ml-6 mr-6" class="grid xl:grid-cols-3 lg:grid-cols-3 md:grid-cols-2 sm:grid-cols-1 gap-4 mt-4 content-center auto-cols-auto ml-6 mr-6"
> >
{#each array as adventure (adventure.id)} {#each array as adventure (adventure.id)}
<AdventureCard <AdventureCard type="shared" {adventure} />
type="shared"
id={adventure.id}
name={adventure.name}
location={adventure.location}
date={adventure.date}
/>
{/each} {/each}
</div> </div>

View file

@ -61,4 +61,4 @@
name="description" name="description"
content="Signup for AdventureLog to start logging your adventures!" content="Signup for AdventureLog to start logging your adventures!"
/> />
</svelte:head>; </svelte:head>

View file

@ -6,6 +6,15 @@ export default {
}, },
plugins: [require("@tailwindcss/typography"), require("daisyui")], plugins: [require("@tailwindcss/typography"), require("daisyui")],
daisyui: { daisyui: {
themes: ["light", "dark", "night", "retro", "forest", "aqua", "garden"], themes: [
"light",
"dark",
"night",
"retro",
"forest",
"aqua",
"garden",
"emerald",
],
}, },
}; };