mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-02 20:15:24 +02:00
feat: Shopping list UI overhaul - collapsible labels (#4378)
Co-authored-by: Kuchenpirat <24235032+Kuchenpirat@users.noreply.github.com>
This commit is contained in:
parent
ae9276b55c
commit
2240ab01d2
1 changed files with 51 additions and 10 deletions
|
@ -57,18 +57,22 @@
|
|||
<!-- View By Label -->
|
||||
<div v-else>
|
||||
<div v-for="(value, key) in itemsByLabel" :key="key" class="mb-6">
|
||||
<div class="text-left">
|
||||
<v-btn
|
||||
:color="getLabelColor(value[0]) ? getLabelColor(value[0]) : '#959595'"
|
||||
:style="{
|
||||
<v-btn
|
||||
:color="getLabelColor(value[0]) ? getLabelColor(value[0]) : '#959595'"
|
||||
:style="{
|
||||
'color': getTextColor(getLabelColor(value[0])),
|
||||
'letter-spacing': 'normal',
|
||||
}"
|
||||
>
|
||||
{{ key }}
|
||||
@click="toggleShowLabel(key)"
|
||||
>
|
||||
<v-icon>
|
||||
{{ labelOpenState[key] ? $globals.icons.chevronDown : $globals.icons.chevronRight }}
|
||||
</v-icon>
|
||||
{{ key }}
|
||||
</v-btn>
|
||||
</div>
|
||||
<v-divider/>
|
||||
<v-divider/>
|
||||
<v-expand-transition group>
|
||||
<div v-show="labelOpenState[key]">
|
||||
<draggable :value="value" handle=".handle" delay="250" :delay-on-touch-only="true" @start="loadingCounter += 1" @end="loadingCounter -= 1" @input="updateIndexUncheckedByLabel(key, $event)">
|
||||
<v-lazy v-for="(item, index) in value" :key="item.id" class="ml-2 my-2">
|
||||
<ShoppingListItem
|
||||
|
@ -83,7 +87,9 @@
|
|||
@delete="deleteListItem(item)"
|
||||
/>
|
||||
</v-lazy>
|
||||
</draggable>
|
||||
</draggable>
|
||||
</div>
|
||||
</v-expand-transition>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -301,7 +307,7 @@
|
|||
<script lang="ts">
|
||||
import draggable from "vuedraggable";
|
||||
|
||||
import { defineComponent, useRoute, computed, ref, toRefs, onUnmounted, useContext, reactive } from "@nuxtjs/composition-api";
|
||||
import { defineComponent, useRoute, computed, ref, toRefs, onUnmounted, useContext, reactive, watch } from "@nuxtjs/composition-api";
|
||||
import { useIdle, useToggle } from "@vueuse/core";
|
||||
import { useCopyList } from "~/composables/use-copy";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
|
@ -463,6 +469,39 @@ export default defineComponent({
|
|||
};
|
||||
});
|
||||
|
||||
// =====================================
|
||||
// Collapsables
|
||||
const labelOpenState = ref<{ [key: string]: boolean }>({});
|
||||
|
||||
const initializeLabelOpenStates = () => {
|
||||
if (!shoppingList.value?.listItems) return;
|
||||
|
||||
const existingLabels = new Set(Object.keys(labelOpenState.value));
|
||||
let hasChanges = false;
|
||||
|
||||
for (const item of shoppingList.value.listItems) {
|
||||
const labelName = item.label?.name;
|
||||
if (labelName && !existingLabels.has(labelName) && !(labelName in labelOpenState.value)) {
|
||||
labelOpenState.value[labelName] = true;
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasChanges) {
|
||||
labelOpenState.value = { ...labelOpenState.value };
|
||||
}
|
||||
};
|
||||
|
||||
const labelNames = computed(() =>
|
||||
new Set(shoppingList.value?.listItems?.map(item => item.label?.name).filter(Boolean) ?? [])
|
||||
);
|
||||
|
||||
watch(labelNames, initializeLabelOpenStates, { immediate: true });
|
||||
|
||||
function toggleShowLabel(key: string) {
|
||||
labelOpenState.value[key] = !labelOpenState.value[key];
|
||||
}
|
||||
|
||||
const [showChecked, toggleShowChecked] = useToggle(false);
|
||||
|
||||
// =====================================
|
||||
|
@ -1090,6 +1129,8 @@ export default defineComponent({
|
|||
shoppingList,
|
||||
showChecked,
|
||||
sortByLabels,
|
||||
labelOpenState,
|
||||
toggleShowLabel,
|
||||
toggleShowChecked,
|
||||
uncheckAll,
|
||||
openUncheckAll,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue