mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-08 23:58:15 -05:00
books page
This commit is contained in:
@@ -480,6 +480,7 @@
|
|||||||
"Imported": "Imported",
|
"Imported": "Imported",
|
||||||
"Quick actions": "Quick actions",
|
"Quick actions": "Quick actions",
|
||||||
"Ratings": "Ratings",
|
"Ratings": "Ratings",
|
||||||
|
"Actions": "Actions",
|
||||||
"Internal": "Internal",
|
"Internal": "Internal",
|
||||||
"Units": "Units",
|
"Units": "Units",
|
||||||
"Manage_Emails": "Manage Emails",
|
"Manage_Emails": "Manage Emails",
|
||||||
|
|||||||
@@ -176,13 +176,10 @@ import {useDisplay} from "vuetify"
|
|||||||
import VSnackbarQueued from "@/components/display/VSnackbarQueued.vue";
|
import VSnackbarQueued from "@/components/display/VSnackbarQueued.vue";
|
||||||
import MessageListDialog from "@/components/dialogs/MessageListDialog.vue";
|
import MessageListDialog from "@/components/dialogs/MessageListDialog.vue";
|
||||||
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore";
|
||||||
import {TAutomation, TCookLog, TFood, TKeyword, TPropertyType, TSupermarket, TSupermarketCategory, TUnit, TUnitConversion, TUserFile, TViewLog} from "@/types/Models";
|
|
||||||
import NavigationDrawerContextMenu from "@/components/display/NavigationDrawerContextMenu.vue";
|
import NavigationDrawerContextMenu from "@/components/display/NavigationDrawerContextMenu.vue";
|
||||||
import {useDjangoUrls} from "@/composables/useDjangoUrls";
|
import {useDjangoUrls} from "@/composables/useDjangoUrls";
|
||||||
import {onMounted, ref} from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
import {isSpaceAboveLimit} from "@/utils/logic_utils";
|
||||||
import {ApiApi, Space} from "@/openapi";
|
|
||||||
import {isSpaceAboveLimit, isSpaceAtLimit} from "@/utils/logic_utils";
|
|
||||||
|
|
||||||
const {lgAndUp} = useDisplay()
|
const {lgAndUp} = useDisplay()
|
||||||
const {getDjangoUrl} = useDjangoUrls()
|
const {getDjangoUrl} = useDjangoUrls()
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import ModelEditPage from "@/pages/ModelEditPage.vue";
|
|||||||
import RecipeImportPage from "@/pages/RecipeImportPage.vue";
|
import RecipeImportPage from "@/pages/RecipeImportPage.vue";
|
||||||
import IngredientEditorPage from "@/pages/IngredientEditorPage.vue";
|
import IngredientEditorPage from "@/pages/IngredientEditorPage.vue";
|
||||||
import BooksPage from "@/pages/BooksPage.vue";
|
import BooksPage from "@/pages/BooksPage.vue";
|
||||||
|
import BookViewPage from "@/pages/BookViewPage.vue";
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{path: '/', component: StartPage, name: 'view_home'},
|
{path: '/', component: StartPage, name: 'view_home'},
|
||||||
@@ -51,6 +52,7 @@ const routes = [
|
|||||||
{path: '/shopping', component: ShoppingListPage, name: 'view_shopping'},
|
{path: '/shopping', component: ShoppingListPage, name: 'view_shopping'},
|
||||||
{path: '/mealplan', component: MealPlanPage, name: 'view_mealplan'},
|
{path: '/mealplan', component: MealPlanPage, name: 'view_mealplan'},
|
||||||
{path: '/books', component: BooksPage, name: 'BooksPage'},
|
{path: '/books', component: BooksPage, name: 'BooksPage'},
|
||||||
|
{path: '/book/:bookId', component: BookViewPage, name: 'BookViewPage', props: true},
|
||||||
{path: '/recipe/import', component: RecipeImportPage, name: 'RecipeImportPage'},
|
{path: '/recipe/import', component: RecipeImportPage, name: 'RecipeImportPage'},
|
||||||
|
|
||||||
{path: '/recipe/:id', component: RecipeViewPage, name: 'view_recipe', props: true},
|
{path: '/recipe/:id', component: RecipeViewPage, name: 'view_recipe', props: true},
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
"Added_on": "Hinzugefügt am",
|
"Added_on": "Hinzugefügt am",
|
||||||
"Admin": "Admin",
|
"Admin": "Admin",
|
||||||
"Advanced": "Erweitert",
|
"Advanced": "Erweitert",
|
||||||
|
"Advanced Search Settings": "Erweiterte Sucheinstellungen",
|
||||||
"Alignment": "Ausrichtung",
|
"Alignment": "Ausrichtung",
|
||||||
"Amount": "Menge",
|
"Amount": "Menge",
|
||||||
"App": "App",
|
"App": "App",
|
||||||
|
|||||||
93
vue3/src/pages/BookViewPage.vue
Normal file
93
vue3/src/pages/BookViewPage.vue
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<template>
|
||||||
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<v-card>
|
||||||
|
<v-card-text class="pt-2 pb-2">
|
||||||
|
<v-btn variant="flat" @click="router.go(-1)" prepend-icon="fa-solid fa-arrow-left">{{ $t('Back') }}</v-btn>
|
||||||
|
</v-card-text>
|
||||||
|
</v-card>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<h2>{{ book.name }}</h2>
|
||||||
|
<p class="text-disabled">{{ book.description }}</p>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-data-iterator :items="entries" :items-per-page="recipesPerPage" :page="page" @update:page="loadRecipe">
|
||||||
|
<template #default="{items}">
|
||||||
|
<v-card v-for="i in items">
|
||||||
|
<v-card-title>{{i.raw.recipeContent.name}}</v-card-title>
|
||||||
|
<v-card-subtitle>{{i.raw.recipeContent.desciption}}</v-card-subtitle>
|
||||||
|
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
</v-data-iterator>
|
||||||
|
<v-pagination v-model="page" :length="totalItems / recipesPerPage"></v-pagination>
|
||||||
|
</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 {VDataTableUpdateOptions} from "@/vuetify";
|
||||||
|
import {useRouter} from "vue-router";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
bookId: {type: String, required: true},
|
||||||
|
})
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const page = ref(1)
|
||||||
|
const recipesPerPage = ref(1)
|
||||||
|
const totalItems = ref(0)
|
||||||
|
|
||||||
|
const book = ref({} as RecipeBook)
|
||||||
|
const entries = ref([] as RecipeBookEntry[])
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadBook()
|
||||||
|
loadEntries({page: 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(options: VDataTableUpdateOptions){
|
||||||
|
const api = new ApiApi()
|
||||||
|
|
||||||
|
api.apiRecipeBookEntryList({book: props.bookId, page: options.page}).then(r => {
|
||||||
|
entries.value = r.results
|
||||||
|
totalItems.value = r.count
|
||||||
|
}).catch(err => {
|
||||||
|
useMessageStore().addError(ErrorMessageType.FETCH_ERROR, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<model-edit-dialog model="RecipeBook" :item="books[i]"
|
<model-edit-dialog model="RecipeBook" :item="books[i]"
|
||||||
@delete="(arg: RecipeBook) => { books.splice(books.findIndex((value: RecipeBook) => value.id == arg.id!),1)}"></model-edit-dialog>
|
@delete="(arg: RecipeBook) => { books.splice(books.findIndex((value: RecipeBook) => value.id == arg.id!),1)}"></model-edit-dialog>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn>
|
<v-btn :to="{name: 'BookViewPage', params: {bookId: b.id}}">
|
||||||
{{ $t('View') }}
|
{{ $t('View') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
@@ -43,21 +43,39 @@
|
|||||||
|
|
||||||
|
|
||||||
import {onMounted, ref} from "vue";
|
import {onMounted, ref} from "vue";
|
||||||
import {ApiApi, RecipeBook} from "@/openapi";
|
import {ApiApi, RecipeBook, RecipeBookEntry} from "@/openapi";
|
||||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore";
|
||||||
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
|
import ModelEditDialog from "@/components/dialogs/ModelEditDialog.vue";
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
const viewingBook = ref<null | RecipeBook>(null)
|
||||||
|
const viewingBookEntries = ref([] as RecipeBookEntry[])
|
||||||
|
|
||||||
const books = ref([] as RecipeBook[])
|
const books = ref([] as RecipeBook[])
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const api = new ApiApi()
|
loadBooks()
|
||||||
|
})
|
||||||
|
|
||||||
|
function loadBooks() {
|
||||||
|
const api = new ApiApi()
|
||||||
|
loading.value = true
|
||||||
api.apiRecipeBookList().then(r => {
|
api.apiRecipeBookList().then(r => {
|
||||||
books.value = r.results
|
books.value = r.results
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
useMessageStore().addError(ErrorMessageType.FETCH_ERROR)
|
useMessageStore().addError(ErrorMessageType.FETCH_ERROR)
|
||||||
|
}).finally(() => {
|
||||||
|
loading.value = false
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
|
|
||||||
|
function loadBookEntries(recipeBook : RecipeBook){
|
||||||
|
const api = new ApiApi()
|
||||||
|
loading.value = true
|
||||||
|
api.apiRecipeBookEntryList({})
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
Reference in New Issue
Block a user