update
This commit is contained in:
4400
ui/package-lock.json
generated
4400
ui/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,9 @@
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-node-resolve": "^11.0.0",
|
||||
"@rollup/plugin-typescript": "^8.0.0",
|
||||
"@tsconfig/svelte": "^2.0.0",
|
||||
"npm": "^8.0.0",
|
||||
"rollup": "^2.3.4",
|
||||
"rollup-plugin-css-only": "^3.1.0",
|
||||
"rollup-plugin-livereload": "^2.0.0",
|
||||
@@ -19,10 +22,8 @@
|
||||
"svelte": "^3.0.0",
|
||||
"svelte-check": "^2.0.0",
|
||||
"svelte-preprocess": "^4.0.0",
|
||||
"@rollup/plugin-typescript": "^8.0.0",
|
||||
"typescript": "^4.0.0",
|
||||
"tslib": "^2.0.0",
|
||||
"@tsconfig/svelte": "^2.0.0"
|
||||
"typescript": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"sirv-cli": "^1.0.0"
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
import Home from "./routes/Home.svelte";
|
||||
import PackageLists from "./routes/PackageLists.svelte";
|
||||
import PackageList from "./routes/PackageList.svelte";
|
||||
import Preparation from "./routes/Preparation.svelte";
|
||||
import Trips from "./routes/Trips.svelte";
|
||||
|
||||
function normalize(path) {
|
||||
return path.replace(/\/+$/, '') + "/";
|
||||
@@ -27,10 +29,20 @@
|
||||
} else if (urlParts[0] == "lists" && urlParts.length == 1) {
|
||||
console.log("=> PackageLists");
|
||||
currentRoute = PackageLists;
|
||||
} else if (urlParts[0] == "trips" && urlParts.length == 1) {
|
||||
console.log("=> Trips");
|
||||
currentRoute = Trips;
|
||||
} else if (urlParts[0] == "lists" && urlParts.length == 2) {
|
||||
console.log("=> PackageList");
|
||||
currentRoute = PackageList;
|
||||
data = {id: urlParts[1]};
|
||||
} else if (urlParts.length == 5
|
||||
&& urlParts[0] == "lists"
|
||||
&& urlParts[2] == "items"
|
||||
&& urlParts[4] == "preparation") {
|
||||
console.log("=> PackageList");
|
||||
currentRoute = Preparation;
|
||||
data = {list_id: urlParts[1], item_id: urlParts[3]};
|
||||
} else {
|
||||
console.log("No matching route found");
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
export let data;
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div>
|
||||
{data.name}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
<script lang="ts">
|
||||
export let list;
|
||||
export let id;
|
||||
export let items;
|
||||
export let redirect;
|
||||
|
||||
$: has_sizes = list.items.some(l => l.size.type != "None");
|
||||
$: has_counts = list.items.some(l => l.count > 1);
|
||||
$: has_counts = items.some(l => l.count > 1);
|
||||
$: has_preparations = items.some(l => l.preparation.steps.length > 0);
|
||||
//has_sizes = items.some(l => l.size.type != "None");
|
||||
|
||||
let has_sizes = false;
|
||||
let has_preparations = false;
|
||||
let has_counts = false;
|
||||
|
||||
const navigateToPreparation = (item_id) => {
|
||||
redirect(`/lists/${id}/items/${item_id}/preparation`);
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div>
|
||||
<table class="table-auto w-full">
|
||||
<thead>
|
||||
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
|
||||
@@ -16,41 +27,52 @@
|
||||
{#if has_counts}
|
||||
<th class="p-3">Count</th>
|
||||
{/if}
|
||||
{#if has_preparations}
|
||||
<th class="p-3">Preparation Steps</th>
|
||||
{/if}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each list.items as item}
|
||||
<tr class="border">
|
||||
<td class="p-3">{item.name}</td>
|
||||
{#if has_sizes }
|
||||
<td class="p-3">
|
||||
{#if item.size.type == "None"}
|
||||
{:else if item.size.type == "Gram"}
|
||||
{#if item.size.value == 1}
|
||||
{item.size.value} Gram
|
||||
{:else}
|
||||
{item.size.value} Grams
|
||||
{/if}
|
||||
{:else if item.size.type == "Pack"}
|
||||
{#if item.size.value == 1}
|
||||
{item.size.value} Pack
|
||||
{:else}
|
||||
{item.size.value} Packs
|
||||
{/if}
|
||||
{#each items as item}
|
||||
<tr class="border">
|
||||
<td class="p-3">{item.name}</td>
|
||||
{#if has_sizes }
|
||||
<td class="p-3">
|
||||
{#if item.size.type == "None"}
|
||||
{:else if item.size.type == "Gram"}
|
||||
{#if item.size.value == 1}
|
||||
{item.size.value} Gram
|
||||
{:else}
|
||||
{item.size.value} {item.size.type}
|
||||
{item.size.value} Grams
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
{#if has_counts}
|
||||
<td class="p-3">
|
||||
{#if item.count > 1}
|
||||
{item.count}
|
||||
{:else if item.size.type == "Pack"}
|
||||
{#if item.size.value == 1}
|
||||
{item.size.value} Pack
|
||||
{:else}
|
||||
{item.size.value} Packs
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
</tr>
|
||||
{:else}
|
||||
{item.size.value} {item.size.type}
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
{#if has_counts}
|
||||
<td class="p-3">
|
||||
{#if item.count > 1}
|
||||
{item.count}
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
{#if has_preparations}
|
||||
<td class="p-3">
|
||||
{#if item.preparation.steps.length > 0}
|
||||
{item.preparation.steps.length} steps
|
||||
<button on:click={() => navigateToPreparation(item.id)}>Show preparation steps</button>
|
||||
{/if}
|
||||
</td>
|
||||
{/if}
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -11,4 +11,5 @@
|
||||
Welcome to Packager, your helper for your next trip!
|
||||
</div>
|
||||
<button on:click={navigateToPackageLists}>Lists</button>
|
||||
<button on:click={() => redirect("/trips/")}>Trips</button>
|
||||
</main>
|
||||
|
||||
@@ -1,35 +1,134 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import PackageListTable from "../components/PackageListTable.svelte"
|
||||
|
||||
export let redirect;
|
||||
export let data;
|
||||
|
||||
const resetActiveElement = () => {
|
||||
activeElement = {
|
||||
name: "",
|
||||
count: 1,
|
||||
preparationsteps: [],
|
||||
};
|
||||
};
|
||||
|
||||
let activeElement;
|
||||
resetActiveElement();
|
||||
|
||||
export const url = `/lists/${data.id}`
|
||||
|
||||
async function getList() {
|
||||
let response = await fetch(`http://localhost:9000/v1/lists/${data.id}`, {
|
||||
let sidebarActive = true;
|
||||
|
||||
const toggleSidebar = () => {
|
||||
sidebarActive = !sidebarActive;
|
||||
}
|
||||
|
||||
const apply = async () => {
|
||||
const response = await fetch(`http://localhost:9000/v1/lists/${data.id}/items`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: activeElement.name,
|
||||
count: activeElement.count,
|
||||
}),
|
||||
cache: "no-store",
|
||||
});
|
||||
|
||||
const d = await response.json();
|
||||
|
||||
console.log(d);
|
||||
items = [...items, d];
|
||||
console.log(items[0]);
|
||||
console.log(d);
|
||||
|
||||
resetActiveElement();
|
||||
sidebarActive = false;
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
resetActiveElement();
|
||||
sidebarActive = false;
|
||||
}
|
||||
|
||||
async function getItems(id) {
|
||||
let response = await fetch(`http://localhost:9000/v1/lists/${id}/items`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json"
|
||||
},
|
||||
cache: "no-store",
|
||||
});
|
||||
let list = await response.json();
|
||||
return list;
|
||||
items = await response.json();
|
||||
}
|
||||
|
||||
async function getList() {
|
||||
const response = await fetch(`http://localhost:9000/v1/lists/${data.id}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json"
|
||||
},
|
||||
cache: "no-store",
|
||||
})
|
||||
|
||||
list = await response.json();
|
||||
}
|
||||
|
||||
let list = {name: ""};
|
||||
let items = [];
|
||||
|
||||
onMount(async () => {
|
||||
await getList();
|
||||
await getItems(data.id);
|
||||
});
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div>
|
||||
{#await getList()}
|
||||
<p>Loading</p>
|
||||
{:then list}
|
||||
<div class="container mx-auto">
|
||||
<h2 class="text-3xl mt-12 mb-20 font-semibold text-center mb-5 mt-3">{list.name}</h2>
|
||||
<PackageListTable list={list} />
|
||||
<h2 class="text-3xl mt-12 mb-20 font-semibold text-center mb-5 mt-3">{list.name}</h2>
|
||||
<div class="container mx-auto grid grid-cols-12 gap-1 items-start justify-items-stretch">
|
||||
<div class="col-start-1 col-end-9">
|
||||
<PackageListTable items={items} id={list.id} {redirect}/>
|
||||
<button class="p-3 w-full mt-3 border border-gray-200 bg-indigo-300" on:click={toggleSidebar}>Add new item</button>
|
||||
</div>
|
||||
{:catch error}
|
||||
<p>Error: {error}</p>
|
||||
{/await}
|
||||
<div class="col-start-9 col-end-10"/>
|
||||
<div class="col-start-10 col-end-13">
|
||||
{#if sidebarActive}
|
||||
<div>
|
||||
<label for="name">Name</label>
|
||||
<input
|
||||
class="w-full"
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
bind:value={activeElement.name}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label for="count">Count</label>
|
||||
<input
|
||||
class="w-full"
|
||||
type="number"
|
||||
id="count"
|
||||
name="count"
|
||||
bind:value={activeElement.count}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
{#each activeElement.preparationsteps as step}
|
||||
{step}
|
||||
{/each}
|
||||
</div>
|
||||
<div class="flex flex-row mt-6 justify-between w-full">
|
||||
<button type="submit" class="p-3 border border-gray-200 bg-green-300" on:click={() => apply()}>Apply</button>
|
||||
<button class="p-3 border border-gray-200 bg-red-300" on:click={() => cancel()}>Cancel</button>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
@@ -20,19 +20,28 @@
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div>
|
||||
{#await getLists()}
|
||||
<p>Loading</p>
|
||||
{:then lists}
|
||||
<div class="m-2 grid grid-cols-3 gap-5 items-start grid-flow-row">
|
||||
{#each lists as list}
|
||||
<div class="p-3 border rounded-lg border-gray-300 shadow hover:shadow-xl bg-gray-100 bg-opacity-30 hover:bg-opacity-100">
|
||||
<PackageList id={list.id} name={list.name} items={list.items} on:select={e => redirect(url + e.detail.id)} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:catch error}
|
||||
<p>Something went wrong</p>
|
||||
{/await}
|
||||
<div class="container mx-auto mt-12">
|
||||
<table class="table-auto w-full">
|
||||
<thead>
|
||||
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
|
||||
<th class="p-3">Name</th>
|
||||
<th class="p-3"># Items</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#await getLists()}
|
||||
<p>Loading</p>
|
||||
{:then lists}
|
||||
{#each lists as list}
|
||||
<tr class="border" on:click={e => redirect(url + list.id)}>
|
||||
<td class="p-3">{list.name}</td>
|
||||
<td class="p-3">{list.items.length}</td>
|
||||
</tr>
|
||||
{/each}
|
||||
{:catch error}
|
||||
<p>Error: {error}</p>
|
||||
{/await}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
41
ui/src/routes/Preparation.svelte
Normal file
41
ui/src/routes/Preparation.svelte
Normal file
@@ -0,0 +1,41 @@
|
||||
<script lang="ts">
|
||||
export let redirect;
|
||||
export let data;
|
||||
|
||||
async function getSteps() {
|
||||
let response = await fetch(`http://localhost:9000/v1/lists/${data.list_id}/items/${data.item_id}/preparation`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json"
|
||||
},
|
||||
cache: "no-store",
|
||||
});
|
||||
let list = await response.json();
|
||||
return list;
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<table class="table-auto w-full">
|
||||
<thead>
|
||||
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
|
||||
<th class="p-3">Name</th>
|
||||
<th class="p-3">Start</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#await getSteps()}
|
||||
<p>Loading</p>
|
||||
{:then steps}
|
||||
{#each steps as step}
|
||||
<tr class="border">
|
||||
<td class="p-3">{step.name}</td>
|
||||
<td class="p-3">{step.start.days} days before</td>
|
||||
</tr>
|
||||
{/each}
|
||||
{:catch error}
|
||||
<p>Error: {error}</p>
|
||||
{/await}
|
||||
</tbody>
|
||||
</table>
|
||||
</main>
|
||||
64
ui/src/routes/Trips.svelte
Normal file
64
ui/src/routes/Trips.svelte
Normal file
@@ -0,0 +1,64 @@
|
||||
<script lang="ts">
|
||||
export let redirect;
|
||||
export let data;
|
||||
|
||||
export const url = "/trips/"
|
||||
|
||||
async function getTrips() {
|
||||
let response = await fetch("http://localhost:9000/v1/trips", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Accept": "application/json"
|
||||
},
|
||||
cache: "no-store",
|
||||
});
|
||||
let trips = await response.json();
|
||||
return trips;
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<div class="container mx-auto mt-12">
|
||||
<h2 class="text-3xl mt-12 mb-20 font-semibold text-center mb-5 mt-3">Trips</h2>
|
||||
<table class="table-auto w-full">
|
||||
<thead>
|
||||
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
|
||||
<th class="p-3">Name</th>
|
||||
<th class="p-3">Date</th>
|
||||
<th class="p-3">Days</th>
|
||||
<th class="p-3">State</th>
|
||||
<th class="p-3">Package Lists</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#await getTrips()}
|
||||
<p>Loading</p>
|
||||
{:then trips}
|
||||
{#each trips as trip}
|
||||
<tr class="border" on:click={e => redirect(url + trip.id)}>
|
||||
<td class="p-3">{trip.name}</td>
|
||||
<td class="p-3">{trip.date}</td>
|
||||
<td class="p-3">{trip.parameters.days}</td>
|
||||
{#if trip.state == "active"}
|
||||
<td class="p-3 bg-green-100">{trip.state}</td>
|
||||
{:else if trip.state == "planned"}
|
||||
<td class="p-3 bg-blue-100">{trip.state}</td>
|
||||
{:else}
|
||||
<td class="p-3">{trip.state}</td>
|
||||
{/if}
|
||||
<td class="p-3">
|
||||
<ul>
|
||||
{#each trip.packageLists as list}
|
||||
<li><button on:click={() => redirect(`/lists/${list.id}`)}>{list.name}</button></li>
|
||||
{/each}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
{:catch error}
|
||||
<p>Error: {error}</p>
|
||||
{/await}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
Reference in New Issue
Block a user