Organizers Page

This commit is contained in:
Kuchenpirat 2025-07-30 12:18:05 +00:00
commit 48d836beeb

View file

@ -122,9 +122,8 @@
</div>
</template>
<script lang="ts">
<script setup lang="ts">
import Fuse from "fuse.js";
import { useContextPresets } from "~/composables/use-context-presents";
import RecipeOrganizerDialog from "~/components/Domain/Recipe/RecipeOrganizerDialog.vue";
import { Organizer, type RecipeOrganizer } from "~/lib/api/types/non-generated";
@ -138,27 +137,18 @@ interface GenericItem {
onHand: boolean;
}
export default defineNuxtComponent({
components: {
RecipeOrganizerDialog,
},
props: {
items: {
type: Array as () => GenericItem[],
required: true,
},
icon: {
type: String,
required: true,
},
itemType: {
type: String as () => RecipeOrganizer,
required: true,
},
},
emits: ["update", "delete"],
setup(props, { emit }) {
const state = reactive({
const props = defineProps<{
items: GenericItem[];
icon: string;
itemType: RecipeOrganizer;
}>();
const emit = defineEmits<{
update: [item: GenericItem];
delete: [id: string];
}>();
const state = reactive({
// Search Options
options: {
ignoreLocation: true,
@ -171,24 +161,24 @@ export default defineNuxtComponent({
minMatchCharLength: 1,
keys: ["name"],
},
});
});
const $auth = useMealieAuth();
const route = useRoute();
const groupSlug = computed(() => route.params.groupSlug as string || $auth.user?.value?.groupSlug || "");
const $auth = useMealieAuth();
const route = useRoute();
const groupSlug = computed(() => route.params.groupSlug as string || $auth.user?.value?.groupSlug || "");
// =================================================================
// Context Menu
// =================================================================
// Context Menu
const dialogs = ref({
const dialogs = ref({
organizer: false,
update: false,
delete: false,
});
});
const presets = useContextPresets();
const presets = useContextPresets();
const translationKey = computed<string>(() => {
const translationKey = computed<string>(() => {
const typeMap = {
categories: "category.category",
tags: "tag.tag",
@ -197,58 +187,58 @@ export default defineNuxtComponent({
households: "household.household",
};
return typeMap[props.itemType] || "";
});
});
const deleteTarget = ref<GenericItem | null>(null);
const updateTarget = ref<GenericItem | null>(null);
const deleteTarget = ref<GenericItem | null>(null);
const updateTarget = ref<GenericItem | null>(null);
function confirmDelete(item: GenericItem) {
function confirmDelete(item: GenericItem) {
deleteTarget.value = item;
dialogs.value.delete = true;
}
}
function deleteOne() {
function deleteOne() {
if (!deleteTarget.value) {
return;
}
emit("delete", deleteTarget.value.id);
}
}
function openUpdateDialog(item: GenericItem) {
function openUpdateDialog(item: GenericItem) {
updateTarget.value = deepCopy(item);
dialogs.value.update = true;
}
}
function updateOne() {
function updateOne() {
if (!updateTarget.value) {
return;
}
emit("update", updateTarget.value);
}
}
// ================================================================
// Search Functions
// ================================================================
// Search Functions
const searchString = useRouteQuery("q", "");
const searchString = useRouteQuery("q", "");
const fuse = computed(() => {
const fuse = computed(() => {
return new Fuse(props.items, state.options);
});
});
const fuzzyItems = computed<GenericItem[]>(() => {
const fuzzyItems = computed<GenericItem[]>(() => {
if (searchString.value.trim() === "") {
return props.items;
}
const result = fuse.value.search(searchString.value.trim() as string);
return result.map(x => x.item);
});
});
// =================================================================
// Sorted Items
// =================================================================
// Sorted Items
const itemsSorted = computed(() => {
const itemsSorted = computed(() => {
const byLetter: { [key: string]: Array<GenericItem> } = {};
if (!fuzzyItems.value) {
@ -266,28 +256,9 @@ export default defineNuxtComponent({
});
return byLetter;
});
function isTitle(str: number | string) {
return typeof str === "string" && str.length === 1;
}
return {
groupSlug,
isTitle,
dialogs,
confirmDelete,
openUpdateDialog,
updateOne,
updateTarget,
deleteOne,
deleteTarget,
Organizer,
presets,
itemsSorted,
searchString,
translationKey,
};
},
});
function isTitle(str: number | string) {
return typeof str === "string" && str.length === 1;
}
</script>