1
0
mirror of https://github.com/TandoorRecipes/recipes.git synced 2026-01-11 17:16:59 -05:00
Files
recipes/vue3/src/pages/BookViewPage.vue
2025-02-15 09:50:40 +01:00

139 lines
5.0 KiB
Vue

<template>
<v-container>
<v-row>
<v-col>
<v-card>
<v-card-title>{{ book.name }}
<v-btn class="float-right" variant="flat" :to="{name: 'BooksPage'}" prepend-icon="$books" v-if="mdAndUp">{{ $t('Books') }}</v-btn>
</v-card-title>
<v-card-text v-if="book.shared && book.shared.length > 0">
<v-chip-group>
<v-label class="me-2">{{ $t('shared_with') }}</v-label>
<v-chip v-for="u in book.shared">{{ u.displayName }}</v-chip>
</v-chip-group>
</v-card-text>
<v-card-text class="text-disabled">
{{ book.description }}
</v-card-text>
<v-expansion-panels v-model="toc">
<v-expansion-panel>
<v-expansion-panel-title>{{ $t('Table_of_Contents') }}</v-expansion-panel-title>
<v-expansion-panel-text>
<v-list>
<v-list-item v-for="(entry, i) in entries" :key="entry.id" @click="page = i; toc = false">
{{ entry.recipeContent.name }}
</v-list-item>
</v-list>
</v-expansion-panel-text>
</v-expansion-panel>
</v-expansion-panels>
</v-card>
</v-col>
</v-row>
<v-row>
<v-col class="text-center">
<v-pagination :model-value="page + 1" @update:model-value="value => page = value - 1" :length="totalItems" @next="page = page + (mdAndUp ? 2 : 1)"
@prev="page = page - (mdAndUp ? 2 : 1)"></v-pagination>
</v-col>
</v-row>
<v-row>
<v-col cols="12">
<v-window v-model="page" show-arrows>
<template #next>
<v-btn icon="fa-solid fa-chevron-right" variant="plain" @click="page = page + (mdAndUp ? 2 : 1)"></v-btn>
</template>
<template #prev>
<v-btn icon="fa-solid fa-chevron-left" variant="plain" @click="page = page - (mdAndUp ? 2 : 1)"></v-btn>
</template>
<v-window-item v-for="(entry, i) in entries" :key="entry.id">
<v-row>
<v-col cols="12" md="6">
<book-entry-card :recipe-overview="entries[i].recipeContent"></book-entry-card>
<div class="text-center mt-1">
<span class="text-disabled">{{ i + 1 }}</span>
</div>
</v-col>
<v-col cols="6" v-if="mdAndUp && entries.length > i + 1">
<book-entry-card :recipe-overview="entries[i + 1].recipeContent"></book-entry-card>
<div class="text-center mt-1">
<span class="text-disabled">{{ i + 2 }}</span>
</div>
</v-col>
</v-row>
</v-window-item>
</v-window>
</v-col>
</v-row>
</v-container>
</template>
<script setup lang="ts">
import {onMounted, ref} from "vue";
import {ApiApi, RecipeBook, RecipeBookEntry} from "@/openapi";
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
import {useRouter} from "vue-router";
import RecipeImage from "@/components/display/RecipeImage.vue";
import {useDisplay} from "vuetify";
import BookEntryCard from "@/components/display/BookEntryCard.vue";
const props = defineProps({
bookId: {type: String, required: true},
})
const {mdAndUp} = useDisplay()
const router = useRouter()
const loading = ref(false)
const toc = ref(false)
const page = ref(0)
const totalItems = ref(0)
const book = ref({} as RecipeBook)
const entries = ref([] as RecipeBookEntry[])
onMounted(() => {
loadBook()
entries.value = []
loadEntries(1)
})
/**
* load the given book
*/
function loadBook() {
const api = new ApiApi()
loading.value = true
api.apiRecipeBookRetrieve({id: props.bookId}).then(r => {
book.value = r
}).catch(err => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
}).finally(() => {
loading.value = false
})
}
function loadEntries(page: number) {
const api = new ApiApi()
api.apiRecipeBookEntryList({book: props.bookId, page: page}).then(r => {
entries.value = entries.value.concat(r.results)
totalItems.value = r.count
if (r.next) {
loadEntries(page + 1)
}
}).catch(err => {
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
})
}
</script>
<style scoped></style>