start page

This commit is contained in:
vabene1111
2024-02-29 21:28:44 +01:00
committed by smilerz
parent 17f875863c
commit 8006d7663c
7 changed files with 161 additions and 51 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -32,11 +32,11 @@
"src": "node_modules/@fortawesome/fontawesome-free/webfonts/fa-v4compatibility.woff2" "src": "node_modules/@fortawesome/fontawesome-free/webfonts/fa-v4compatibility.woff2"
}, },
"src/apps/tandoor/main.ts": { "src/apps/tandoor/main.ts": {
"file": "assets/main-OseOyQb7.js", "file": "assets/main-Dn7LZ1Sm.js",
"src": "src/apps/tandoor/main.ts", "src": "src/apps/tandoor/main.ts",
"isEntry": true, "isEntry": true,
"css": [ "css": [
"assets/main-DFkSTGyd.css" "assets/main-C0cQ5WeY.css"
], ],
"assets": [ "assets": [
"assets/brand_logo-D4X97p3N.svg", "assets/brand_logo-D4X97p3N.svg",

View File

@@ -2,44 +2,43 @@
<v-app> <v-app>
<v-app-bar color="tandoor" flat density="comfortable" > <v-app-bar color="tandoor" flat density="comfortable">
<v-img class="ms-2" src="../../assets/brand_logo.svg"></v-img> <v-img class="ms-2" src="../../assets/brand_logo.svg"></v-img>
<global-search-dialog></global-search-dialog> <global-search-dialog></global-search-dialog>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn density="compact" icon="fas fa-ellipsis-v"></v-btn> <v-btn density="compact" icon="fas fa-ellipsis-v"></v-btn>
</v-app-bar> </v-app-bar>
<v-main> <v-main>
<v-container class="pa-0 ma-0 mb-2"> <v-container class="pa-0 ma-0 mb-2">
<router-view></router-view> <router-view></router-view>
</v-container> </v-container>
</v-main> </v-main>
<v-bottom-navigation> <v-bottom-navigation>
<v-btn value="recent" to="/search"> <v-btn value="recent" to="/search">
<v-icon icon="fas fa-book"/> <v-icon icon="fas fa-book"/>
<span>Recipes</span> <span>Recipes</span>
</v-btn> </v-btn>
<v-btn value="favorites" to="/mealplan"> <v-btn value="favorites" to="/mealplan">
<v-icon icon="fas fa-calendar-alt"></v-icon> <v-icon icon="fas fa-calendar-alt"></v-icon>
<span>MealPlan</span> <span>MealPlan</span>
</v-btn> </v-btn>
<v-btn value="nearby" to="/shopping"> <v-btn value="nearby" to="/shopping">
<v-icon icon="fas fa-shopping-cart"></v-icon> <v-icon icon="fas fa-shopping-cart"></v-icon>
<span>Shopping</span> <span>Shopping</span>
</v-btn> </v-btn>
<v-btn value="nearby" to="/books"> <v-btn value="nearby" to="/books">
<v-icon icon="fas fa-book-open"></v-icon> <v-icon icon="fas fa-book-open"></v-icon>
<span>Books</span>
</v-btn>
</v-bottom-navigation>
<span>Books</span>
</v-btn>
</v-bottom-navigation>
</v-app> </v-app>

View File

@@ -0,0 +1,59 @@
<template>
<v-row justify="space-between">
<v-col>
<h2>{{ title }}</h2>
</v-col>
<v-col>
<v-btn density="default" variant="outlined" size="x-small" icon="fas fa-chevron-left" @click="scrollList('left', scroll_id)"></v-btn>
<v-btn density="default" variant="outlined" size="x-small" icon="fas fa-chevron-right" @click="scrollList('right', scroll_id)"></v-btn>
</v-col>
</v-row>
<v-row>
<v-col>
<v-infinite-scroll direction="horizontal" mode="manual" :id="scroll_id">
<div v-for="r in recipes" class="mr-2">
<recipe-card :recipe="r" :show_description="false" :show_keywords="false" style="width: 45vw; height: 30vh"></recipe-card>
</div>
<template #load-more></template>
</v-infinite-scroll>
</v-col>
</v-row>
</template>
<script lang="ts">
import {defineComponent, PropType} from 'vue'
import {Recipe, RecipeOverview} from "@/openapi";
import RecipeCard from "@/components/display/RecipeCard.vue";
export default defineComponent({
name: "HorizontalRecipeScroller",
components: {RecipeCard},
props: {
title: {type: String, required: true},
recipes: {type: Array as PropType<Array<Recipe | RecipeOverview>>, required: true},
},
data() {
return {
scroll_id: Math.random(1000).toString()
}
},
methods: {
scrollList(direction: string, target: string) {
const newRecipeScroll = document.getElementById(target)
if (newRecipeScroll != null) {
newRecipeScroll.scrollLeft = newRecipeScroll.scrollLeft + (200 * ((direction == 'left') ? -1 : 1))
}
}
}
})
</script>
<style scoped>
</style>

View File

@@ -3,19 +3,19 @@
<v-img <v-img
cover cover
height="250" height="50%"
:src="recipe.image" :src="recipe.image"
></v-img> ></v-img>
<v-card-item> <v-card-item>
<v-card-title>{{ recipe.name }}</v-card-title> <v-card-title>{{ recipe.name }}</v-card-title>
<v-card-subtitle> <v-card-subtitle v-if="show_keywords">
<KeywordsComponent :keywords="recipe.keywords"></KeywordsComponent> <KeywordsComponent :keywords="recipe.keywords"></KeywordsComponent>
</v-card-subtitle> </v-card-subtitle>
</v-card-item> </v-card-item>
<v-card-text> <v-card-text v-if="show_description">
<v-row align="center" class="mx-0" v-if="recipe.rating"> <v-row align="center" class="mx-0" v-if="recipe.rating">
<v-rating <v-rating
:model-value="recipe.rating" :model-value="recipe.rating"
@@ -26,7 +26,7 @@
size="small" size="small"
></v-rating> ></v-rating>
<div class="text-grey ms-4"> <div class="text-grey ">
{{ recipe.rating }} {{ recipe.rating }}
</div> </div>
</v-row> </v-row>
@@ -46,7 +46,9 @@ export default defineComponent({
name: "RecipeCard", name: "RecipeCard",
components: {KeywordsComponent}, components: {KeywordsComponent},
props: { props: {
recipe: {} as Recipe recipe: {} as Recipe,
show_keywords: {type: Boolean, required: false},
show_description: {type: Boolean, required: false},
} }
}) })
</script> </script>

View File

@@ -1,42 +1,54 @@
<template> <template>
<v-container>
<horizontal-recipe-scroller title="New Recipes" :recipes="new_recipes"></horizontal-recipe-scroller>
<horizontal-recipe-scroller title="Top Rated" :recipes="high_rated_recipes"></horizontal-recipe-scroller>
</v-container>
<!--TODO ideas for "start page": new recipes, meal plan, "last year/month/cooked long ago", high rated, random keyword --> <!--TODO ideas for "start page": new recipes, meal plan, "last year/month/cooked long ago", high rated, random keyword -->
<!-- <v-row>-->
<!-- <v-col cols="12" sm="3" md="4" v-for="r in recipes" :key="r.id">-->
<!-- <RecipeCardComponent :recipe="r"></RecipeCardComponent>-->
<!-- </v-col>-->
<!-- </v-row>-->
</template> </template>
<script lang="ts"> <script lang="ts">
import {defineComponent} from 'vue' import {defineComponent, ref} from 'vue'
import {ApiApi, Recipe} from "@/openapi"; import {ApiApi, Recipe, RecipeOverview} from "@/openapi";
import KeywordsComponent from "@/components/display/KeywordsBar.vue"; import KeywordsComponent from "@/components/display/KeywordsBar.vue";
import RecipeCardComponent from "@/components/display/RecipeCard.vue"; import RecipeCardComponent from "@/components/display/RecipeCard.vue";
import GlobalSearchDialog from "@/components/inputs/GlobalSearchDialog.vue"; import GlobalSearchDialog from "@/components/inputs/GlobalSearchDialog.vue";
import RecipeCard from "@/components/display/RecipeCard.vue";
import HorizontalRecipeScroller from "@/components/display/HorizontalRecipeScroller.vue";
export default defineComponent({ export default defineComponent({
name: "RecipeSearchPage", name: "RecipeSearchPage",
components: {GlobalSearchDialog, RecipeCardComponent, KeywordsComponent}, components: {HorizontalRecipeScroller, RecipeCard, GlobalSearchDialog, RecipeCardComponent, KeywordsComponent},
computed: { computed: {},
},
data() { data() {
return { return {
recipes: [] as Recipe[], recipes: [] as Recipe[],
items: Array.from({length: 50}, (k, v) => v + 1),
new_recipes: [] as RecipeOverview[],
high_rated_recipes: [] as RecipeOverview[],
} }
}, },
mounted() { mounted() {
const api = new ApiApi()
api.apiRecipeList({_new: 'true'}).then(r => {
if (r.results != undefined) { // TODO why this check, worst case its empty
this.new_recipes = r.results
}
})
api.apiRecipeList({rating: 4}).then(r => {
if (r.results != undefined) { // TODO why this check, worst case its empty
this.high_rated_recipes = r.results
}
})
}, },
methods: { methods: {