1
0
Fork 0
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:
Cody 2024-10-25 02:07:44 -05:00 committed by GitHub
parent ae9276b55c
commit 2240ab01d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -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,