Switch between List and Grid view fix #1
This commit is contained in:
+47
-6
@@ -1,11 +1,15 @@
|
||||
<script setup>
|
||||
import { ref, computed, onBeforeUnmount } from "vue";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { faMinus, faPlus, faPlay, faStop, faTrash, faArrowDown } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faMinus, faPlus, faPlay, faStop, faTrash, faArrowDown, faList, faGrip, faDownload, faUpload } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
// App Einstellungen
|
||||
const view = ref(loadView());
|
||||
|
||||
const MIN_BPM = 20;
|
||||
const MAX_BPM = 300;
|
||||
const STORAGE_KEY = "ClickPresets"
|
||||
const STORAGE_KEY_PRESETS = "ClickPresets"
|
||||
const STORAGE_KEY_VIEW = "ClickView"
|
||||
|
||||
// Reaktiver Zustand (für die UI)
|
||||
const bpm = ref(120);
|
||||
@@ -116,7 +120,7 @@ onBeforeUnmount(() => {
|
||||
//PRESETS
|
||||
function loadPresets() {
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY);
|
||||
const raw = localStorage.getItem(STORAGE_KEY_PRESETS);
|
||||
return raw ? JSON.parse(raw) : [];
|
||||
} catch (error) {
|
||||
console.error("Presets could not be loaded:", error);
|
||||
@@ -129,13 +133,13 @@ function addPreset() {
|
||||
const preset = { tempo: bpm.value, id: nextId };
|
||||
presets.value.push(preset);
|
||||
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(presets.value));
|
||||
localStorage.setItem(STORAGE_KEY_PRESETS, JSON.stringify(presets.value));
|
||||
}
|
||||
|
||||
function deletePreset() {
|
||||
presets.value = presets.value.filter(f => f.id != selectedPreset.value.id);
|
||||
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(presets.value));
|
||||
localStorage.setItem(STORAGE_KEY_PRESETS, JSON.stringify(presets.value));
|
||||
stop();
|
||||
selectedPreset = ref(null);
|
||||
}
|
||||
@@ -153,6 +157,24 @@ const sortedPresets = computed(() =>
|
||||
[...presets.value].sort((a, b) => a.tempo - b.tempo)
|
||||
);
|
||||
|
||||
// App View
|
||||
|
||||
function loadView() {
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY_VIEW);
|
||||
return raw || "grid";
|
||||
} catch (error) {
|
||||
console.error("View settings could not be loaded:", error);
|
||||
return "grid";
|
||||
}
|
||||
}
|
||||
|
||||
function switchView(val) {
|
||||
view.value = val;
|
||||
localStorage.setItem(STORAGE_KEY_VIEW, val);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -193,7 +215,7 @@ const sortedPresets = computed(() =>
|
||||
<div id="presets">
|
||||
<h1>Presets</h1>
|
||||
<h2 id="presetsMessage" v-if="presets.length == 0">No Presets defined</h2>
|
||||
<div id="presetsItems">
|
||||
<div id="presetsItems" :class="{ list: view == 'list', grid: view == 'grid' }">
|
||||
<button v-for="preset in sortedPresets" :key="preset.id" class="presetItem" :class="{ selected: selectedPreset === preset }" @click="startPreset(preset)">
|
||||
<h2>{{ preset.tempo }}</h2>
|
||||
BPM
|
||||
@@ -201,4 +223,23 @@ const sortedPresets = computed(() =>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
<div class="left">
|
||||
<button>
|
||||
<font-awesome-icon :icon="faUpload" size="xl" />
|
||||
</button>
|
||||
<button>
|
||||
<font-awesome-icon :icon="faDownload" size="xl" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="grow"></div>
|
||||
<div class="right">
|
||||
<button v-if="view == 'grid'" @click="switchView('list')">
|
||||
<font-awesome-icon :icon="faList" size="xl" />
|
||||
</button>
|
||||
<button v-if="view == 'list'" @click="switchView('grid')">
|
||||
<font-awesome-icon :icon="faGrip" size="xl" />
|
||||
</button>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
+40
-8
@@ -20,6 +20,19 @@ main {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
border-top-style: solid;
|
||||
border-top-color: var(--light-gray);
|
||||
border-top-width: 1px;
|
||||
}
|
||||
|
||||
footer button {
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
body,
|
||||
textarea,
|
||||
input,
|
||||
@@ -29,9 +42,7 @@ pre {
|
||||
}
|
||||
|
||||
body,
|
||||
button,
|
||||
a,
|
||||
label {
|
||||
button {
|
||||
color: var(--dark);
|
||||
}
|
||||
|
||||
@@ -119,21 +130,38 @@ button#stop {
|
||||
|
||||
#presetsItems {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#presetsItems.list {
|
||||
flex-direction: column;
|
||||
width: stretch;
|
||||
}
|
||||
|
||||
#presetsItems.grid {
|
||||
align-self: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.presetItem {
|
||||
min-width: 86px;
|
||||
display: flex;
|
||||
border-width: 1px;
|
||||
border-color: var(--light-gray);
|
||||
border-style: solid;
|
||||
border-radius: 4px;
|
||||
margin: 4px;
|
||||
padding: 4px;
|
||||
text-align: center;
|
||||
background-color: var(--white);
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
#presetsItems.list .presetItem {
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
#presetsItems.grid .presetItem {
|
||||
min-width: 86px;
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.presetItem.selected {
|
||||
@@ -150,4 +178,8 @@ input[type="number"]::-webkit-inner-spin-button {
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
|
||||
.grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
Reference in New Issue
Block a user