Files
voyage/src/routes/log/+page.svelte

278 lines
7.5 KiB
Svelte

<script lang="ts">
export let data;
let adventures: Adventure[] = [];
import AdventureCard from "$lib/components/AdventureCard.svelte";
import type { Adventure } from "$lib/utils/types";
import {
addAdventure,
clearAdventures,
getAdventures,
getNextId,
saveEdit,
} from "../../services/adventureService";
import { onMount } from "svelte";
import { exportData } from "../../services/export";
import { importData } from "../../services/import";
import exportFile from "$lib/assets/exportFile.svg";
import deleteIcon from "$lib/assets/deleteIcon.svg";
import SucessToast from "$lib/components/SucessToast.svelte";
import mapDrawing from "$lib/assets/adventure_map.svg";
import EditModal from "$lib/components/EditModal.svelte";
import { generateRandomString } from "$lib";
let newName = "";
let newLocation = "";
let editId: number = NaN;
let editName: string = "";
let editLocation: string = "";
let editCreated: string = "";
let isShowingToast: boolean = false;
let toastAction: string = "";
// Sets the adventures array to the data from the server
onMount(async () => {
console.log(data);
adventures = data.result.adventures;
});
function showToast(action: string) {
toastAction = action;
isShowingToast = true;
console.log("showing toast");
setTimeout(() => {
isShowingToast = false;
toastAction = "";
console.log("hiding toast");
}, 3000);
}
const createNewAdventure = () => {
let currentDate = new Date();
let dateString = currentDate.toISOString().slice(0, 10); // Get date in "yyyy-mm-dd" format
// post to /api/visits
fetch("/api/visits", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: newName,
location: newLocation,
created: dateString,
}),
})
.then((response) => response.json())
.then((data) => {
console.log("Success:", data);
let newId = data.id;
console.log("New ID: " + newId);
console.log("New Name: " + newName);
adventures = [
...adventures,
{
id: newId,
name: newName,
location: newLocation,
created: dateString,
},
];
newName = ""; // Reset newName and newLocation after adding adventure
newLocation = "";
showToast("added");
})
.catch((error) => {
console.error("Error:", error);
});
};
// function triggerRemoveAdventure(event: { detail: number }) {
// removeAdventure(event);
// showToast("removed");
// adventures = getAdventures();
// // remove from data.result.adventures
// data.result.adventures = data.result.adventures.filter(
// (adventure: Adventure) => adventure.id !== event.detail,
// );
// }
function saveAdventure(event: { detail: Adventure }) {
console.log("Event" + event.detail);
saveEdit(event.detail);
editId = NaN;
editName = "";
editLocation = "";
editCreated = "";
adventures = getAdventures();
showToast("edited");
}
function editAdventure(event: { detail: number }) {
const adventure = adventures.find(
(adventure) => adventure.id === event.detail,
);
if (adventure) {
editId = adventure.id;
editName = adventure.name;
editLocation = adventure.location;
editCreated = adventure.created;
}
}
function shareLink() {
let key = generateRandomString();
let data = JSON.stringify(adventures);
fetch("/api/share", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ key, data }),
})
.then((response) => response.json())
.then((data) => {
console.log("Success:", data);
let url = window.location.origin + "/shared/" + key;
navigator.clipboard.writeText(url);
})
.catch((error) => {
console.error("Error:", error);
});
}
function handleClose() {
editId = NaN;
editName = "";
editLocation = "";
editCreated = "";
}
function deleteData() {
clearAdventures();
adventures = getAdventures();
showToast("deleted");
}
function removeAdventure(event: { detail: number }) {
console.log("Event ID " + event.detail);
// send delete request to server at /api/visits
fetch("/api/visits", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ id: event.detail }),
})
.then((response) => response.json())
.then((data) => {
console.log("Success:", data);
// remove adventure from array where id matches
adventures = adventures.filter(
(adventure) => adventure.id !== event.detail,
);
showToast("removed");
})
.catch((error) => {
console.error("Error:", error);
});
}
</script>
<div class="flex justify-center items-center w-full mt-4 mb-4">
<article class="prose">
<h2 class="text-center">Add new Location</h2>
</article>
</div>
<div class="flex flex-row items-center justify-center gap-4">
<form on:submit={createNewAdventure} class="flex gap-2">
<input
type="text"
bind:value={newName}
placeholder="Adventure Name"
class="input input-bordered w-full max-w-xs"
/>
<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>
{#if adventures.length != 0}
<div class="flex justify-center items-center w-full mt-4 mb-4">
<article class="prose">
<h1 class="text-center">My Visited Adventure Locations</h1>
</article>
</div>
{/if}
{#if isShowingToast}
<SucessToast action={toastAction} />
{/if}
{#if !Number.isNaN(editId)}
<EditModal
bind:editId
bind:editName
bind:editLocation
bind:editCreated
on:submit={saveAdventure}
on:close={handleClose}
/>
{/if}
<div
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 adventures as adventure (adventure.id)}
<AdventureCard
type="mylog"
id={adventure.id}
name={adventure.name}
location={adventure.location}
created={adventure.created}
on:edit={editAdventure}
on:remove={removeAdventure}
/>
{/each}
</div>
{#if adventures.length == 0}
<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 adventures.length != 0}
<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={async () => {
window.location.href = exportData();
}}
>
<img src={exportFile} class="inline-block -mt-1" alt="Logo" /> Save as File
</button>
<button class="btn btn-neutral" on:click={deleteData}>
<img src={deleteIcon} class="inline-block -mt-1" alt="Logo" /> Delete Data
</button>
<button class="btn btn-neutral" on:click={shareLink}>
<img src={deleteIcon} class="inline-block -mt-1" alt="Logo" /> Share as Link
</button>
</div>
{/if}