mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2026-01-01 04:10:06 -05:00
some more things in recipe view
This commit is contained in:
@@ -1,35 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app>
|
<v-app>
|
||||||
<v-layout>
|
|
||||||
<v-navigation-drawer v-model="drawer"
|
|
||||||
:rail="rail"
|
|
||||||
permanent
|
|
||||||
@click="rail = false">
|
|
||||||
<v-list-item @click="drawer = false">
|
|
||||||
<v-img src="../../assets/logo_color.svg" height="48px" v-if="rail"></v-img>
|
|
||||||
<v-img src="../../assets/brand_logo.svg" max-height="64px" v-if="!rail"></v-img>
|
|
||||||
</v-list-item>
|
|
||||||
<v-divider></v-divider>
|
|
||||||
<v-list density="compact" nav>
|
|
||||||
<v-list-item prepend-icon="fas fa-book" title="Home" value="home"></v-list-item>
|
|
||||||
<v-list-item prepend-icon="fas fa-calendar-alt" title="My Account" value="account"></v-list-item>
|
|
||||||
<v-list-item prepend-icon="fas fa-shopping-cart" title="Users" value="users"></v-list-item>
|
|
||||||
<v-list-item prepend-icon="fas fa-book-open" title="Users" value="users"></v-list-item>
|
|
||||||
</v-list>
|
|
||||||
<v-divider></v-divider>
|
|
||||||
</v-navigation-drawer>
|
|
||||||
|
|
||||||
<v-app-bar color="tandoor" flat>
|
|
||||||
|
<v-app-bar color="tandoor" flat density="compact" >
|
||||||
<template v-slot:prepend>
|
<template v-slot:prepend>
|
||||||
<v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
|
Tandoor Brand Logo
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-btn density="compact" icon="fas fa-search"></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 fluid class="pa-0 ma-0">
|
<v-container class="pa-0 ma-0">
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</v-container>
|
</v-container>
|
||||||
</v-main>
|
</v-main>
|
||||||
@@ -57,7 +42,7 @@
|
|||||||
<span>Books</span>
|
<span>Books</span>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-bottom-navigation>
|
</v-bottom-navigation>
|
||||||
</v-layout>
|
|
||||||
|
|
||||||
|
|
||||||
</v-app>
|
</v-app>
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ const routes = [
|
|||||||
{path: '/', redirect: '/search', name: 'index'},
|
{path: '/', redirect: '/search', name: 'index'},
|
||||||
{path: '/search', component: RecipeSearchPage, name: 'view_search'},
|
{path: '/search', component: RecipeSearchPage, name: 'view_search'},
|
||||||
{path: '/shopping', component: ShoppingListPage, name: 'view_shopping'},
|
{path: '/shopping', component: ShoppingListPage, name: 'view_shopping'},
|
||||||
|
{path: '/mealplan', component: ShoppingListPage, name: 'view_mealplan'},
|
||||||
|
{path: '/books', component: ShoppingListPage, name: 'view_books'},
|
||||||
{path: '/recipe/:id', component: RecipeViewPage, name: 'view_recipe', props: true},
|
{path: '/recipe/:id', component: RecipeViewPage, name: 'view_recipe', props: true},
|
||||||
{path: '/recipe/edit/:id', component: RecipeViewPage, name: 'view_recipe', props: true},
|
{path: '/recipe/edit/:id', component: RecipeViewPage, name: 'edit_recipe', props: true},
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {Keyword} from "@/openapi";
|
|||||||
import {PropType} from "vue";
|
import {PropType} from "vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'KeywordsComponent',
|
name: 'KeywordsBar',
|
||||||
mixins: [],
|
mixins: [],
|
||||||
props: {
|
props: {
|
||||||
keywords: Array as PropType<Array<Keyword>>,
|
keywords: Array as PropType<Array<Keyword>>,
|
||||||
@@ -39,11 +39,11 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {defineComponent} from 'vue'
|
import {defineComponent} from 'vue'
|
||||||
import KeywordsComponent from "@/components/display/KeywordsComponent.vue";
|
import KeywordsComponent from "@/components/display/KeywordsBar.vue";
|
||||||
import {Recipe} from "@/openapi";
|
import {Recipe} from "@/openapi";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "RecipeCardComponent",
|
name: "RecipeCard",
|
||||||
components: {KeywordsComponent},
|
components: {KeywordsComponent},
|
||||||
props: {
|
props: {
|
||||||
recipe: {} as Recipe
|
recipe: {} as Recipe
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-card to="/search">
|
|
||||||
<v-card-title><i class="fas fa-chevron-left mr-3"></i>{{ recipe.name }}</v-card-title>
|
|
||||||
</v-card>
|
|
||||||
|
|
||||||
<v-img cover lazy :src="recipe.image"></v-img>
|
<v-img cover lazy :src="recipe.image"></v-img>
|
||||||
|
|
||||||
|
|
||||||
<v-card>
|
<v-card>
|
||||||
|
|
||||||
|
<v-card-title>{{ recipe.name }}</v-card-title>
|
||||||
|
|
||||||
<v-container>
|
<v-container>
|
||||||
<v-row class="text-center text-body-2">
|
<v-row class="text-center text-body-2">
|
||||||
<v-col class="pt-1 pb-1">
|
<v-col class="pt-1 pb-1">
|
||||||
@@ -19,8 +18,14 @@
|
|||||||
<div class="text-grey">Waiting Time</div>
|
<div class="text-grey">Waiting Time</div>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col class="pt-1 pb-1">
|
<v-col class="pt-1 pb-1">
|
||||||
<i class="fas fa-calendar-alt"></i> {{ recipe.servings }} <br/>
|
<NumberScalerDialog :number="recipe.servings" @change="recipe.servings = $event.number" title="Servings">
|
||||||
<div class="text-grey"><span v-if="recipe?.servingsText">{{ recipe.servingsText }}</span><span v-else>Servings</span></div>
|
<template #activator>
|
||||||
|
<i class="fas fa-calendar-alt"></i> {{ recipe.servings }} <br/>
|
||||||
|
<div class="text-grey"><span v-if="recipe?.servingsText">{{ recipe.servingsText }}</span><span v-else>Servings</span></div>
|
||||||
|
</template>
|
||||||
|
</NumberScalerDialog>
|
||||||
|
|
||||||
|
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
</v-row>
|
</v-row>
|
||||||
@@ -28,7 +33,7 @@
|
|||||||
|
|
||||||
<v-card-subtitle v-if="recipe?.description"> {{ recipe.description }}</v-card-subtitle>
|
<v-card-subtitle v-if="recipe?.description"> {{ recipe.description }}</v-card-subtitle>
|
||||||
<v-card-subtitle>
|
<v-card-subtitle>
|
||||||
<KeywordsComponent :keywords="recipe?.keywords"></KeywordsComponent>
|
<KeywordsBar :keywords="recipe?.keywords"></KeywordsBar>
|
||||||
</v-card-subtitle>
|
</v-card-subtitle>
|
||||||
|
|
||||||
|
|
||||||
@@ -42,44 +47,33 @@
|
|||||||
<v-icon icon="fas fa-hourglass-half" class="mr-2"></v-icon>
|
<v-icon icon="fas fa-hourglass-half" class="mr-2"></v-icon>
|
||||||
{{ recipe.waitingTime }} min
|
{{ recipe.waitingTime }} min
|
||||||
</v-chip>
|
</v-chip>
|
||||||
|
<v-chip size="small" color="primary" label>
|
||||||
|
<v-icon icon="fas fa-calendar" class="mr-2"></v-icon>
|
||||||
|
{{ recipe.lastCooked }}
|
||||||
|
</v-chip>
|
||||||
|
<v-rating v-model="recipe.rating" color="tandoor"></v-rating>
|
||||||
|
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
</v-card>
|
</v-card>
|
||||||
|
|
||||||
<v-btn color="primary" id="id_btn_test">test</v-btn>
|
|
||||||
|
|
||||||
<v-dialog
|
|
||||||
activator="parent">
|
|
||||||
|
|
||||||
|
|
||||||
<template #default>
|
|
||||||
<v-card title="Servings">
|
|
||||||
<v-card-text>
|
|
||||||
<v-btn>{{recipe.servings / 2}}</v-btn>
|
|
||||||
<v-text-field v-model="recipe.servings">
|
|
||||||
<template #append><v-btn @click="recipe.servings++">+</v-btn></template>
|
|
||||||
<template #prepend><v-btn @click="recipe.servings--">-</v-btn></template>
|
|
||||||
</v-text-field>
|
|
||||||
<v-btn>{{recipe.servings * 2}}</v-btn>
|
|
||||||
</v-card-text>
|
|
||||||
|
|
||||||
|
|
||||||
</v-card>
|
|
||||||
</template>
|
|
||||||
</v-dialog>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
import {defineComponent, PropType} from 'vue'
|
import {defineComponent, PropType} from 'vue'
|
||||||
import {Recipe} from "@/openapi";
|
import {Recipe} from "@/openapi"
|
||||||
import KeywordsComponent from "@/components/display/KeywordsComponent.vue";
|
import KeywordsBar from "@/components/display/KeywordsBar.vue"
|
||||||
|
import NumberScalerDialog from "@/components/inputs/NumberScalerDialog.vue"
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "RecipeViewComponent",
|
name: "RecipeView",
|
||||||
components: {KeywordsComponent},
|
components: {NumberScalerDialog, KeywordsBar},
|
||||||
props: {
|
props: {
|
||||||
recipe: {} as PropType<Recipe>
|
recipe: {
|
||||||
|
type: Object as PropType<Recipe>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
98
vue3/src/components/inputs/NumberScalerDialog.vue
Normal file
98
vue3/src/components/inputs/NumberScalerDialog.vue
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<template>
|
||||||
|
<v-dialog width="500" activator="parent" v-model="dialog">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<slot name="activator">
|
||||||
|
<v-btn v-bind="props" text="Open Dialog"></v-btn>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:default="{ isActive }">
|
||||||
|
<v-card :title="title">
|
||||||
|
<v-card-text>
|
||||||
|
Change Number
|
||||||
|
</v-card-text>
|
||||||
|
|
||||||
|
<v-card-text>
|
||||||
|
<v-btn-group divided color="primary">
|
||||||
|
<v-btn @click="updateNumber( 'half')"><i class="fas fa-divide"></i> 2
|
||||||
|
</v-btn>
|
||||||
|
<v-btn @click="updateNumber( 'sub')"><i class="fas fa-minus"></i>
|
||||||
|
</v-btn>
|
||||||
|
<v-btn @click="updateNumber('prompt')">
|
||||||
|
{{ mutable_number }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn @click="updateNumber( 'add')"><i class="fas fa-plus"></i>
|
||||||
|
</v-btn>
|
||||||
|
<v-btn @click="updateNumber('double')"><i class="fas fa-times"></i> 2
|
||||||
|
</v-btn>
|
||||||
|
</v-btn-group>
|
||||||
|
|
||||||
|
<v-text-field type="number" v-model.number="mutable_number" @change="updateNumber('set')"></v-text-field>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-btn rounded variant="outlined" @click="dialog = false">Close</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
|
||||||
|
import {defineComponent} from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "NumberScalerDialog",
|
||||||
|
emits: {
|
||||||
|
change(payload: { number: number }) {
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
number: {type: Number, default: 0},
|
||||||
|
title: {type: String, default: 'Number'}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialog: false,
|
||||||
|
mutable_number: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
number: function (newVal) {
|
||||||
|
this.mutable_number = newVal
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.mutable_number = this.number
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* perform given operation on linked number
|
||||||
|
* @param operation update mode
|
||||||
|
*/
|
||||||
|
updateNumber: function (operation: string) {
|
||||||
|
if (operation === 'half') {
|
||||||
|
this.mutable_number = this.number / 2
|
||||||
|
}
|
||||||
|
if (operation === 'double') {
|
||||||
|
this.mutable_number = this.number * 2
|
||||||
|
}
|
||||||
|
if (operation === 'add') {
|
||||||
|
this.mutable_number = this.number + 1
|
||||||
|
}
|
||||||
|
if (operation === 'sub') {
|
||||||
|
this.mutable_number = this.number - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$emit('change', {number: this.mutable_number})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {defineComponent} from 'vue'
|
import {defineComponent} from 'vue'
|
||||||
import {ApiApi, Recipe} from "@/openapi";
|
import {ApiApi, Recipe} from "@/openapi";
|
||||||
import KeywordsComponent from "@/components/display/KeywordsComponent.vue";
|
import KeywordsComponent from "@/components/display/KeywordsBar.vue";
|
||||||
import RecipeCardComponent from "@/components/display/RecipeCardComponent.vue";
|
import RecipeCardComponent from "@/components/display/RecipeCard.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "RecipeSearchPage",
|
name: "RecipeSearchPage",
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<RecipeViewComponent :recipe="recipe"></RecipeViewComponent>
|
<RecipeView :recipe="recipe"></RecipeView>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {defineComponent} from 'vue'
|
import {defineComponent} from 'vue'
|
||||||
import {ApiApi, Recipe} from "@/openapi";
|
import {ApiApi, Recipe} from "@/openapi";
|
||||||
import RecipeViewComponent from "@/components/display/RecipeViewComponent.vue";
|
import RecipeView from "@/components/display/RecipeView.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "RecipeSearchPage",
|
name: "RecipeSearchPage",
|
||||||
components: {RecipeViewComponent},
|
components: {RecipeView},
|
||||||
props: {
|
props: {
|
||||||
id: Number
|
id: {type: String, required: true}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user