Compare commits
5 Commits
bc16fffcdb
...
f5eaf97083
Author | SHA1 | Date |
---|---|---|
![]() |
f5eaf97083 | |
![]() |
cdbbd64cdd | |
![]() |
8c5f2d7bc2 | |
![]() |
bdadf65e46 | |
![]() |
dd76eacb82 |
|
@ -1,9 +0,0 @@
|
|||
export default class inventoryAPI {
|
||||
static async save(drinks) {
|
||||
localStorage.setItem("inventory", JSON.stringify(drinks));
|
||||
}
|
||||
|
||||
static async load() {
|
||||
return JSON.parse(localStorage.getItem("inventory") || "[]");
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import { inventory } from "../stores/inventory"
|
||||
import { drinks } from "../stores/drinks";
|
||||
import inventoryApi from "../stores/api";
|
||||
|
||||
export let drinkName: string;
|
||||
|
||||
|
@ -8,6 +9,15 @@
|
|||
let amountBottles: number;
|
||||
|
||||
const saveInventory = () => {
|
||||
// If there is not a timestamp entry yet, create one.
|
||||
if ( !$inventory.some(item => "timestamp" in item)) {
|
||||
let _unixTime = Date.now();
|
||||
let _date = new Date(_unixTime).toLocaleDateString();
|
||||
let _time = new Date(_unixTime).toLocaleTimeString();
|
||||
$inventory = [{
|
||||
timestamp: _date + " um " + _time
|
||||
}, ...$inventory];
|
||||
}
|
||||
// Check if a drink is already in the inventory. If yes, then update the amounts. If not, add it.
|
||||
if ($inventory.some(item => item.name === drinkName)) {
|
||||
$inventory.forEach(item => {
|
||||
|
@ -27,8 +37,22 @@
|
|||
...$inventory,
|
||||
];
|
||||
}
|
||||
console.log($inventory);
|
||||
inventoryApi.save($inventory);
|
||||
};
|
||||
|
||||
const loadAmountsFromInventory = () => {
|
||||
$inventory.forEach(item => {
|
||||
if (item.name === drinkName) {
|
||||
amountContainers = item.amountContainers;
|
||||
amountBottles = item.amountBottles;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
loadAmountsFromInventory();
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<div class="box">
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
<script lang="ts">
|
||||
import inventoryApi from "../stores/api";
|
||||
import { inventory } from "../stores/inventory";
|
||||
import Success from "./Success.svelte";
|
||||
|
||||
export let finishKind = "";
|
||||
let windowIsVisible = "";
|
||||
let name = "";
|
||||
let comment = "";
|
||||
|
||||
let successWindow;
|
||||
|
||||
export const showWindow = () => windowIsVisible = "is-active";
|
||||
|
||||
const closeWindow = () => {
|
||||
windowIsVisible = "";
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="modal {windowIsVisible}">
|
||||
<div class="modal-background"/>
|
||||
<div class="modal-card">
|
||||
|
||||
{#if finishKind === "reset"}
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">Inventur neu beginnen ❌</p>
|
||||
<button class="delete" aria-label="close" on:click={closeWindow}></button>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<p>Bist du dir sicher, dass du die Inventur abbrechen willst? Damit werden alle bereits eingegebenen Werte zurückgesetzt.</p>
|
||||
</section>
|
||||
<footer class="modal-card-foot">
|
||||
<button class="button is-danger" on:click={inventoryApi.reset}>Ja, Reset!</button>
|
||||
<button class="button" on:click={closeWindow}>Abbrechen</button>
|
||||
</footer>
|
||||
|
||||
{:else if finishKind === "finish"}
|
||||
<!--Prevent saving empty inventories-->
|
||||
{#if $inventory.length > 0}
|
||||
<header class="modal-card-head">
|
||||
<p class="modal-card-title">Inventur abschließen ✅</p>
|
||||
<button class="delete" aria-label="close" on:click={closeWindow}></button>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<p>
|
||||
Vielen Dank, dass du eine Inventur gemacht hast! 🫶
|
||||
<br>
|
||||
Bitte gib noch deinen <strong>Namen</strong> ein. Außerdem hast du hier noch Platz für irgendwelche <strong>Kommentare</strong> zu deiner Inventur.
|
||||
</p>
|
||||
<br>
|
||||
<div class="field">
|
||||
<input class="input is-primary" type="text" placeholder="Name" bind:value={name} />
|
||||
</div>
|
||||
<div class="field">
|
||||
<textarea class="textarea is-info" placeholder="Kommentare" bind:value={comment} />
|
||||
</div>
|
||||
</section>
|
||||
<footer class="modal-card-foot">
|
||||
{#if name.length > 0}
|
||||
<button class="button is-primary" on:click={() => {
|
||||
// TODO: Hier muss dann der Request an das Backend rausgehen!
|
||||
closeWindow();
|
||||
successWindow.showWindow();
|
||||
setTimeout(() => inventoryApi.reset(), 2000);
|
||||
}}>Abschließen</button>
|
||||
{:else}
|
||||
<button class="button" disabled>Abschließen</button>
|
||||
{/if}
|
||||
<button class="button" on:click={closeWindow}>Abbrechen</button>
|
||||
</footer>
|
||||
{:else}
|
||||
<section class="modal-card-body">
|
||||
<p>Du hast noch gar keine Daten erfasst... 🤓</p>
|
||||
</section>
|
||||
<footer class="modal-card-foot">
|
||||
<button class="button" on:click={closeWindow}>Zurück</button>
|
||||
</footer>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Success bind:this={successWindow} />
|
|
@ -1,9 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { inventory } from "../stores/inventory";
|
||||
</script>
|
||||
|
||||
<article class="message is-info">
|
||||
<div class="message-header">
|
||||
<p>Hallo! Schön, dass du eine Inventur machen möchtest. :)</p>
|
||||
<p>Hallo! Schön, dass du eine Inventur machen möchtest. 🙂</p>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
<p>
|
||||
|
@ -11,18 +12,20 @@
|
|||
<br>
|
||||
Dein Fortschritt wird gespeichert, bis du mit Klick auf <span class="tag is-primary"><strong>Abschluss</strong></span> die Inventur abschließt.
|
||||
<br>
|
||||
Wenn du neu starten möchtest, klicke auf <span class="tag is-danger"><strong>Reset</strong></span>.
|
||||
<br><br>
|
||||
Zurück hierher kommst du, wenn du oben auf das Spartacus-Logo klickst.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</article>
|
||||
|
||||
{#if $inventory.some(item => "timestamp" in item)}
|
||||
<article class="message is-link">
|
||||
<div class="message-body">
|
||||
<p>
|
||||
ℹ️ Inventur begonnen am TBD
|
||||
<!-- Wenn schon was im local storage liegt, sollte der Zeitpunkt der Erstellung hier genannt werden -->
|
||||
Du hast <strong>am {$inventory.at(-1).timestamp}</strong> auf deinem aktuellen Gerät eine Inventur gestartet.
|
||||
<br>
|
||||
Klicke oben rechts auf <span class="tag is-danger"><strong>Reset</strong></span>, wenn du deinen Fortschritt löschen möchtest.
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
{/if}
|
|
@ -2,12 +2,18 @@
|
|||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
|
||||
<script lang="ts">
|
||||
import { activeCategory, drinks } from "../stores/drinks.js";
|
||||
import { onMount } from "svelte";
|
||||
import Drink from "./Drink.svelte";
|
||||
import Info from "./Info.svelte";
|
||||
import { activeCategory, drinks, inventory } from "../stores/inventory.js";
|
||||
import inventoryApi from "../stores/api";
|
||||
|
||||
$: filteredDrinks = $drinks.filter(drink => drink.type == $activeCategory);
|
||||
|
||||
onMount(async () => {
|
||||
$inventory = await inventoryApi.load();
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<section class="section">
|
||||
|
@ -15,9 +21,24 @@
|
|||
{#if $activeCategory == ""}
|
||||
<Info />
|
||||
{:else}
|
||||
<div class="block">
|
||||
<div class="subtitle">
|
||||
{#if $activeCategory === "beer"}
|
||||
<strong>Bier 🍺</strong>
|
||||
{:else if $activeCategory === "fizzyDrink"}
|
||||
<strong>Brause & Wasser 💧</strong>
|
||||
{:else if $activeCategory === "wine"}
|
||||
<strong>Wein 🍷</strong>
|
||||
{:else}
|
||||
<strong>Schnaps & Sirup 🥃</strong>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="block">
|
||||
{#each filteredDrinks as drink (drink.name)}
|
||||
<Drink drinkName={drink.name} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</section>
|
|
@ -2,13 +2,34 @@
|
|||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
|
||||
<script lang="ts">
|
||||
import { activeCategory } from "../stores/drinks";
|
||||
import { activeCategory } from "../stores/inventory";
|
||||
import { inventory } from "../stores/inventory";
|
||||
import Finish from "./Finish.svelte";
|
||||
|
||||
let sparti_logo = "./src/assets/sparti_logo.png";
|
||||
let resetOrFinish = "";
|
||||
let modalWindow;
|
||||
let burgerMenuActive = "";
|
||||
|
||||
const drinkCategories = [
|
||||
{name: "beer", friendlyName: "Bier"},
|
||||
{name: "fizzyDrink", friendlyName: "Brause & Wasser"},
|
||||
{name: "wine", friendlyName: "Wein"},
|
||||
{name: "spirit", friendlyName: "Schnaps & Sirup"},
|
||||
]
|
||||
|
||||
const setActiveCategory = (category: string) => {
|
||||
$activeCategory = category;
|
||||
}
|
||||
|
||||
const setFinishKind = (kind: string) => {
|
||||
resetOrFinish = kind;
|
||||
}
|
||||
|
||||
const toggleBurgerMenu = () => {
|
||||
burgerMenuActive = burgerMenuActive === "is-active" ? "" : "is-active"
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<nav class="navbar is-light is-spaced has-shadow is-fixed-top">
|
||||
|
@ -16,39 +37,56 @@
|
|||
<a on:click={() => setActiveCategory("")} class="navbar-item">
|
||||
<img src={sparti_logo} />
|
||||
</a>
|
||||
|
||||
<a role="button" class="navbar-burger {burgerMenuActive}" on:click={toggleBurgerMenu} aria-label="menu" aria-expanded="false" data-target="spartacusNavbar">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
<div class="navbar-menu {burgerMenuActive}" id="spartacusNavbar">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" on:click={() => setActiveCategory("beer")}>
|
||||
Bier
|
||||
</a>
|
||||
<a class="navbar-item" on:click={() => setActiveCategory("fizzyDrink")}>
|
||||
Brause & Wasser
|
||||
</a>
|
||||
<a class="navbar-item" on:click={() => setActiveCategory("wine")}>
|
||||
Wein & Sekt
|
||||
</a>
|
||||
<a class="navbar-item" on:click={() => setActiveCategory("spirit")}>
|
||||
Schnaps & Sirup
|
||||
{#each drinkCategories as category (category.name)}
|
||||
<a class="navbar-item" on:click={() => {
|
||||
setActiveCategory(category.name);
|
||||
toggleBurgerMenu();
|
||||
}
|
||||
}>
|
||||
{category.friendlyName}
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item">
|
||||
<div class="buttons">
|
||||
<a on:click={() => console.log("TBD")} class="button is-primary">
|
||||
<a on:click={
|
||||
() => {
|
||||
setFinishKind("finish");
|
||||
modalWindow.showWindow()
|
||||
}
|
||||
} class="button is-primary">
|
||||
<strong>Abschluss</strong>
|
||||
<!-- Hier sollte dann auch ein Name eingegeben werden -->
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{#if $inventory.length > 0}
|
||||
<div class="navbar-item">
|
||||
<div class="buttons">
|
||||
<a on:click={() => console.log("TBD")} class="button is-danger">
|
||||
<a on:click={
|
||||
() => {
|
||||
setFinishKind("reset");
|
||||
modalWindow.showWindow()
|
||||
}
|
||||
} class="button is-danger">
|
||||
<strong>Reset</strong>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<Finish bind:this={modalWindow} finishKind={resetOrFinish} />
|
|
@ -0,0 +1,25 @@
|
|||
<script lang="ts">
|
||||
let windowIsVisible = "";
|
||||
|
||||
export const showWindow = () => windowIsVisible = "is-active";
|
||||
|
||||
const closeWindow = () => {
|
||||
windowIsVisible = "";
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="modal {windowIsVisible}">
|
||||
<div class="modal-background"/>
|
||||
<div class="card">
|
||||
<div class="card-content">
|
||||
<p class="title">
|
||||
Inventur abgeschlossen. Danke! ✨
|
||||
</p>
|
||||
<p class="subtitle">
|
||||
Die Seite wird gleich automatisch neu geladen...
|
||||
</p>
|
||||
<!--Just a small, decorative, indefinite progress bar-->
|
||||
<progress class="progress is-small is-primary" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,14 @@
|
|||
export default class inventoryApi {
|
||||
static async save(drinks) {
|
||||
localStorage.setItem("drinks", JSON.stringify(drinks));
|
||||
}
|
||||
|
||||
static async load() {
|
||||
return JSON.parse(localStorage.getItem("drinks") || "[]");
|
||||
}
|
||||
|
||||
static async reset() {
|
||||
localStorage.removeItem("drinks");
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
import { readable, writable } from "svelte/store"
|
||||
|
||||
export const drinks = readable([
|
||||
// Biere
|
||||
{ name: "Sternburg Export (0,5 l)", type: "beer" },
|
||||
{ name: "PU (0,5 l)", type: "beer" },
|
||||
{ name: "Gösser Radler (0,5 l)", type: "beer" },
|
||||
{ name: "Paulaner Hefe alkoholfrei (0,5 l)", type: "beer" },
|
||||
{ name: "Augustiner Lagerbier Hell (0,5 l)", type: "beer" },
|
||||
{ name: "Störtebeker Atlantik-Ale (0,33 l)", type: "beer" },
|
||||
|
||||
// Brause & Wasser
|
||||
{ name: "Soli Mate (0,5 l)", type: "fizzyDrink" },
|
||||
{ name: "Schneiders Spezi (0,5 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Cola (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Zitrone (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Orange (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Apfelschorle (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Rhabarber (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Märkisch Kristall Classic PET (0,5 l)", type: "fizzyDrink" },
|
||||
{ name: "Märkisch Kristall Naturelle PET (0,5 l)", type: "fizzyDrink" },
|
||||
{ name: "Afri Cola (1,0 l)", type: "fizzyDrink" },
|
||||
{ name: "Tonic Water Bad Liebenwerder (1,0 l)", type: "fizzyDrink" },
|
||||
{ name: "Bitter Lemon Bad Liebenwerder (1,0 l)", type: "fizzyDrink" },
|
||||
{ name: "Ginger Ale Bad Liebenwerder (1,0 l)", type: "fizzyDrink" },
|
||||
{ name: "ChariTea Black (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "ChariTea Green (0,33 l)", type: "fizzyDrink" },
|
||||
|
||||
// Wein & Sekt
|
||||
{ name: "OBC Cidre Stark (0,33 l)", type: "wine" },
|
||||
{ name: "OBC Cidre Classic (0,33 l)", type: "wine" },
|
||||
{ name: "Pinot Grigio (0,75 l)", type: "wine" },
|
||||
{ name: "Rotwein Montepulciano (1,5 l)", type: "wine" },
|
||||
{ name: "Lehmann Hausmarke Frizzante (0,75 l)", type: "wine" },
|
||||
|
||||
// Schnaps & Sirup
|
||||
{ name: "Vodka Partisan Black (1,0 l)", type: "spirit" },
|
||||
{ name: "Gordon's London Dry Gin (1,0 l)", type: "spirit" },
|
||||
{ name: "Absinth Tabu Classic 55% (1,0 l)", type: "spirit" },
|
||||
{ name: "Tequila Jose Cuervo Silver (1,0 l)", type: "spirit" },
|
||||
{ name: "Havanna (1,0 l)", type: "spirit" },
|
||||
{ name: "'51' Cachaca (1,0 l)", type: "spirit" },
|
||||
{ name: "Berliner Luft (0,7 l)", type: "spirit" },
|
||||
])
|
||||
|
||||
export const activeCategory = writable("")
|
|
@ -1,3 +1,48 @@
|
|||
import { writable } from "svelte/store"
|
||||
import { readable, writable } from "svelte/store"
|
||||
|
||||
export const drinks = readable([
|
||||
// Biere
|
||||
{ name: "Sternburg Export (0,5 l)", type: "beer" },
|
||||
{ name: "PU (0,5 l)", type: "beer" },
|
||||
{ name: "Gösser Radler (0,5 l)", type: "beer" },
|
||||
{ name: "Paulaner Hefe alkoholfrei (0,5 l)", type: "beer" },
|
||||
{ name: "Augustiner Lagerbier Hell (0,5 l)", type: "beer" },
|
||||
{ name: "Störtebeker Atlantik-Ale (0,33 l)", type: "beer" },
|
||||
|
||||
// Brause & Wasser
|
||||
{ name: "Soli Mate (0,5 l)", type: "fizzyDrink" },
|
||||
{ name: "Schneiders Spezi (0,5 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Cola (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Zitrone (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Orange (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Apfelschorle (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Proviant Rhabarber (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "Märkisch Kristall Classic PET (0,5 l)", type: "fizzyDrink" },
|
||||
{ name: "Märkisch Kristall Naturelle PET (0,5 l)", type: "fizzyDrink" },
|
||||
{ name: "Afri Cola (1,0 l)", type: "fizzyDrink" },
|
||||
{ name: "Tonic Water Bad Liebenwerder (1,0 l)", type: "fizzyDrink" },
|
||||
{ name: "Bitter Lemon Bad Liebenwerder (1,0 l)", type: "fizzyDrink" },
|
||||
{ name: "Ginger Ale Bad Liebenwerder (1,0 l)", type: "fizzyDrink" },
|
||||
{ name: "ChariTea Black (0,33 l)", type: "fizzyDrink" },
|
||||
{ name: "ChariTea Green (0,33 l)", type: "fizzyDrink" },
|
||||
|
||||
// Wein & Sekt
|
||||
{ name: "OBC Cidre Stark (0,33 l)", type: "wine" },
|
||||
{ name: "OBC Cidre Classic (0,33 l)", type: "wine" },
|
||||
{ name: "Pinot Grigio (0,75 l)", type: "wine" },
|
||||
{ name: "Rotwein Montepulciano (1,5 l)", type: "wine" },
|
||||
{ name: "Lehmann Hausmarke Frizzante (0,75 l)", type: "wine" },
|
||||
|
||||
// Schnaps & Sirup
|
||||
{ name: "Vodka Partisan Black (1,0 l)", type: "spirit" },
|
||||
{ name: "Gordon's London Dry Gin (1,0 l)", type: "spirit" },
|
||||
{ name: "Absinth Tabu Classic 55% (1,0 l)", type: "spirit" },
|
||||
{ name: "Tequila Jose Cuervo Silver (1,0 l)", type: "spirit" },
|
||||
{ name: "Havanna (1,0 l)", type: "spirit" },
|
||||
{ name: "'51' Cachaca (1,0 l)", type: "spirit" },
|
||||
{ name: "Berliner Luft (0,7 l)", type: "spirit" },
|
||||
])
|
||||
|
||||
export const activeCategory = writable("")
|
||||
|
||||
export const inventory = writable([])
|
Loading…
Reference in New Issue