mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 06:23:34 -07:00
Recipe Data Table
This commit is contained in:
parent
8a68278290
commit
ee68f95d4b
1 changed files with 110 additions and 138 deletions
|
@ -62,7 +62,7 @@
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script setup lang="ts">
|
||||||
import UserAvatar from "../User/UserAvatar.vue";
|
import UserAvatar from "../User/UserAvatar.vue";
|
||||||
import RecipeChip from "./RecipeChips.vue";
|
import RecipeChip from "./RecipeChips.vue";
|
||||||
import type { Recipe, RecipeCategory, RecipeTool } from "~/lib/api/types/recipe";
|
import type { Recipe, RecipeCategory, RecipeTool } from "~/lib/api/types/recipe";
|
||||||
|
@ -70,8 +70,6 @@ import { useUserApi } from "~/composables/api";
|
||||||
import type { UserSummary } from "~/lib/api/types/user";
|
import type { UserSummary } from "~/lib/api/types/user";
|
||||||
import type { RecipeTag } from "~/lib/api/types/household";
|
import type { RecipeTag } from "~/lib/api/types/household";
|
||||||
|
|
||||||
const INPUT_EVENT = "update:modelValue";
|
|
||||||
|
|
||||||
interface ShowHeaders {
|
interface ShowHeaders {
|
||||||
id: boolean;
|
id: boolean;
|
||||||
owner: boolean;
|
owner: boolean;
|
||||||
|
@ -84,140 +82,114 @@ interface ShowHeaders {
|
||||||
dateAdded: boolean;
|
dateAdded: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineNuxtComponent({
|
interface Props {
|
||||||
components: { RecipeChip, UserAvatar },
|
loading?: boolean;
|
||||||
props: {
|
recipes?: Recipe[];
|
||||||
modelValue: {
|
showHeaders?: ShowHeaders;
|
||||||
type: Array as PropType<Recipe[]>,
|
}
|
||||||
required: false,
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
default: () => [],
|
loading: false,
|
||||||
},
|
recipes: () => [],
|
||||||
loading: {
|
showHeaders: () => ({
|
||||||
type: Boolean,
|
id: true,
|
||||||
required: false,
|
owner: false,
|
||||||
default: false,
|
tags: true,
|
||||||
},
|
categories: true,
|
||||||
recipes: {
|
tools: true,
|
||||||
type: Array as () => Recipe[],
|
recipeServings: true,
|
||||||
default: () => [],
|
recipeYieldQuantity: true,
|
||||||
},
|
recipeYield: true,
|
||||||
showHeaders: {
|
dateAdded: true,
|
||||||
type: Object as () => ShowHeaders,
|
}),
|
||||||
required: false,
|
|
||||||
default: () => {
|
|
||||||
return {
|
|
||||||
id: true,
|
|
||||||
owner: false,
|
|
||||||
tags: true,
|
|
||||||
categories: true,
|
|
||||||
recipeServings: true,
|
|
||||||
recipeYieldQuantity: true,
|
|
||||||
recipeYield: true,
|
|
||||||
dateAdded: true,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
emits: ["click", "update:modelValue"],
|
|
||||||
setup(props, context) {
|
|
||||||
const i18n = useI18n();
|
|
||||||
const $auth = useMealieAuth();
|
|
||||||
const groupSlug = $auth.user.value?.groupSlug;
|
|
||||||
const router = useRouter();
|
|
||||||
const selected = computed({
|
|
||||||
get: () => props.modelValue,
|
|
||||||
set: value => context.emit(INPUT_EVENT, value),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initialize sort state with default sorting by dateAdded descending
|
|
||||||
const sortBy = ref([{ key: "dateAdded", order: "desc" }]);
|
|
||||||
|
|
||||||
const headers = computed(() => {
|
|
||||||
const hdrs: Array<{ title: string; value: string; align?: string; sortable?: boolean }> = [];
|
|
||||||
|
|
||||||
if (props.showHeaders.id) {
|
|
||||||
hdrs.push({ title: i18n.t("general.id"), value: "id" });
|
|
||||||
}
|
|
||||||
if (props.showHeaders.owner) {
|
|
||||||
hdrs.push({ title: i18n.t("general.owner"), value: "userId", align: "center", sortable: true });
|
|
||||||
}
|
|
||||||
hdrs.push({ title: i18n.t("general.name"), value: "name", sortable: true });
|
|
||||||
if (props.showHeaders.categories) {
|
|
||||||
hdrs.push({ title: i18n.t("recipe.categories"), value: "recipeCategory", sortable: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.showHeaders.tags) {
|
|
||||||
hdrs.push({ title: i18n.t("tag.tags"), value: "tags", sortable: true });
|
|
||||||
}
|
|
||||||
if (props.showHeaders.tools) {
|
|
||||||
hdrs.push({ title: i18n.t("tool.tools"), value: "tools", sortable: true });
|
|
||||||
}
|
|
||||||
if (props.showHeaders.recipeServings) {
|
|
||||||
hdrs.push({ title: i18n.t("recipe.servings"), value: "recipeServings", sortable: true });
|
|
||||||
}
|
|
||||||
if (props.showHeaders.recipeYieldQuantity) {
|
|
||||||
hdrs.push({ title: i18n.t("recipe.yield"), value: "recipeYieldQuantity", sortable: true });
|
|
||||||
}
|
|
||||||
if (props.showHeaders.recipeYield) {
|
|
||||||
hdrs.push({ title: i18n.t("recipe.yield-text"), value: "recipeYield", sortable: true });
|
|
||||||
}
|
|
||||||
if (props.showHeaders.dateAdded) {
|
|
||||||
hdrs.push({ title: i18n.t("general.date-added"), value: "dateAdded", sortable: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
return hdrs;
|
|
||||||
});
|
|
||||||
|
|
||||||
function formatDate(date: string) {
|
|
||||||
try {
|
|
||||||
return i18n.d(Date.parse(date), "medium");
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============
|
|
||||||
// Group Members
|
|
||||||
const api = useUserApi();
|
|
||||||
const members = ref<UserSummary[]>([]);
|
|
||||||
|
|
||||||
async function refreshMembers() {
|
|
||||||
const { data } = await api.groups.fetchMembers();
|
|
||||||
if (data) {
|
|
||||||
members.value = data.items;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterItems(item: RecipeTag | RecipeCategory | RecipeTool, itemType: string) {
|
|
||||||
if (!groupSlug || !item.id) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
router.push(`/g/${groupSlug}?${itemType}=${item.id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
refreshMembers();
|
|
||||||
});
|
|
||||||
|
|
||||||
function getMember(id: string) {
|
|
||||||
if (members.value[0]) {
|
|
||||||
return members.value.find(m => m.id === id)?.fullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
return i18n.t("general.none");
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
selected,
|
|
||||||
sortBy,
|
|
||||||
groupSlug,
|
|
||||||
headers,
|
|
||||||
formatDate,
|
|
||||||
members,
|
|
||||||
getMember,
|
|
||||||
filterItems,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
defineEmits<{
|
||||||
|
click: [];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const selected = defineModel<Recipe[]>({ default: () => [] });
|
||||||
|
|
||||||
|
const i18n = useI18n();
|
||||||
|
const $auth = useMealieAuth();
|
||||||
|
const groupSlug = $auth.user.value?.groupSlug;
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
// Initialize sort state with default sorting by dateAdded descending
|
||||||
|
const sortBy = ref([{ key: "dateAdded", order: "desc" as const }]);
|
||||||
|
|
||||||
|
const headers = computed(() => {
|
||||||
|
const hdrs: Array<{ title: string; value: string; align?: "center" | "start" | "end"; sortable?: boolean }> = [];
|
||||||
|
|
||||||
|
if (props.showHeaders.id) {
|
||||||
|
hdrs.push({ title: i18n.t("general.id"), value: "id" });
|
||||||
|
}
|
||||||
|
if (props.showHeaders.owner) {
|
||||||
|
hdrs.push({ title: i18n.t("general.owner"), value: "userId", align: "center", sortable: true });
|
||||||
|
}
|
||||||
|
hdrs.push({ title: i18n.t("general.name"), value: "name", sortable: true });
|
||||||
|
if (props.showHeaders.categories) {
|
||||||
|
hdrs.push({ title: i18n.t("recipe.categories"), value: "recipeCategory", sortable: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.showHeaders.tags) {
|
||||||
|
hdrs.push({ title: i18n.t("tag.tags"), value: "tags", sortable: true });
|
||||||
|
}
|
||||||
|
if (props.showHeaders.tools) {
|
||||||
|
hdrs.push({ title: i18n.t("tool.tools"), value: "tools", sortable: true });
|
||||||
|
}
|
||||||
|
if (props.showHeaders.recipeServings) {
|
||||||
|
hdrs.push({ title: i18n.t("recipe.servings"), value: "recipeServings", sortable: true });
|
||||||
|
}
|
||||||
|
if (props.showHeaders.recipeYieldQuantity) {
|
||||||
|
hdrs.push({ title: i18n.t("recipe.yield"), value: "recipeYieldQuantity", sortable: true });
|
||||||
|
}
|
||||||
|
if (props.showHeaders.recipeYield) {
|
||||||
|
hdrs.push({ title: i18n.t("recipe.yield-text"), value: "recipeYield", sortable: true });
|
||||||
|
}
|
||||||
|
if (props.showHeaders.dateAdded) {
|
||||||
|
hdrs.push({ title: i18n.t("general.date-added"), value: "dateAdded", sortable: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
return hdrs;
|
||||||
|
});
|
||||||
|
|
||||||
|
function formatDate(date: string) {
|
||||||
|
try {
|
||||||
|
return i18n.d(Date.parse(date), "medium");
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============
|
||||||
|
// Group Members
|
||||||
|
const api = useUserApi();
|
||||||
|
const members = ref<UserSummary[]>([]);
|
||||||
|
|
||||||
|
async function refreshMembers() {
|
||||||
|
const { data } = await api.groups.fetchMembers();
|
||||||
|
if (data) {
|
||||||
|
members.value = data.items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterItems(item: RecipeTag | RecipeCategory | RecipeTool, itemType: string) {
|
||||||
|
if (!groupSlug || !item.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
router.push(`/g/${groupSlug}?${itemType}=${item.id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
refreshMembers();
|
||||||
|
});
|
||||||
|
|
||||||
|
function getMember(id: string) {
|
||||||
|
if (members.value[0]) {
|
||||||
|
return members.value.find(m => m.id === id)?.fullName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i18n.t("general.none");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue