2024-01-13 02:00:15 +00:00
|
|
|
<template>
|
|
|
|
|
<div>
|
2024-01-13 08:43:15 +00:00
|
|
|
<div v-if="!id && !recipe">
|
2024-05-04 01:52:31 +00:00
|
|
|
<input class="recipe-link" type="text" v-model="link" placeholder="Link to Recipe" /> <br />
|
2024-01-13 02:00:15 +00:00
|
|
|
<button @click="parseLink">Parse</button>
|
2024-05-04 01:52:31 +00:00
|
|
|
<button @click="createFromScratch">Create from Scratch</button>
|
2024-01-13 02:00:15 +00:00
|
|
|
</div>
|
2024-01-13 08:43:15 +00:00
|
|
|
|
2024-01-13 03:22:10 +00:00
|
|
|
<div v-if="parse_failed">
|
2024-01-13 02:00:15 +00:00
|
|
|
<p>Recipe not found</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
2024-01-13 03:22:10 +00:00
|
|
|
<div v-if="!parse_failed && recipe">
|
2024-01-13 08:43:15 +00:00
|
|
|
<div class="image-container" v-if="image_styling" :style="image_styling" ></div>
|
2024-01-13 02:00:15 +00:00
|
|
|
<h1><input class="recipe-name" type="text" :value="recipe.name"></h1>
|
2024-01-13 08:43:15 +00:00
|
|
|
<h3 class="recipe-link"><a :href="recipe.link">View Recipe</a></h3>
|
|
|
|
|
<h2>Ingredients</h2>
|
2024-01-13 02:00:15 +00:00
|
|
|
<ul>
|
|
|
|
|
<li v-for="ingredient in recipe.ingredients" :key="ingredient.line">
|
2024-01-14 02:12:19 +00:00
|
|
|
<p class="ingredient-line">
|
|
|
|
|
<ingredient-line
|
|
|
|
|
:ingredient="ingredient"
|
|
|
|
|
@update-ingredient="updateIngredient"
|
|
|
|
|
@update-product-link="updateProduct"
|
|
|
|
|
@delete-item="deleteIngredient" />
|
|
|
|
|
</p>
|
|
|
|
|
<button @click="deleteIngredient(ingredient)">Delete</button>
|
2024-01-13 02:00:15 +00:00
|
|
|
</li>
|
|
|
|
|
</ul>
|
2024-01-13 03:22:10 +00:00
|
|
|
<button class="submit-btn" @click="saveRecipe">Save</button>
|
2024-01-13 02:00:15 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
input {
|
|
|
|
|
border: 0;
|
|
|
|
|
border-bottom: 1px solid #ccc;
|
|
|
|
|
font-size: large;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
input.recipe-link {
|
|
|
|
|
width: 80%;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-13 08:43:15 +00:00
|
|
|
.image-container {
|
|
|
|
|
max-height: 20vh;
|
|
|
|
|
min-height: 20vh;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-13 02:00:15 +00:00
|
|
|
input.recipe-name {
|
|
|
|
|
width: 100%;
|
2024-01-13 08:43:15 +00:00
|
|
|
font-weight: bold;
|
|
|
|
|
font-size: larger;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.recipe-link {
|
|
|
|
|
color: #0000EE;
|
|
|
|
|
text-decoration: none;
|
2024-01-13 02:00:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ul {
|
2024-01-17 13:34:42 +00:00
|
|
|
padding: 0;
|
2024-01-13 02:00:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
li {
|
|
|
|
|
list-style: none;
|
2024-01-14 02:12:19 +00:00
|
|
|
display: flex;
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
border: 1px solid #ccc;
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
padding: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.ingredient-line {
|
|
|
|
|
flex: 1;
|
|
|
|
|
margin: 0;
|
|
|
|
|
margin-right: 1em;
|
2024-01-13 02:00:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
|
|
|
|
import data from '@/data.js'
|
|
|
|
|
import IngredientLine from './IngredientLine.vue'
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
props: {
|
|
|
|
|
id: { type: Number, optional: true }
|
|
|
|
|
},
|
|
|
|
|
components: {
|
|
|
|
|
IngredientLine
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
2024-01-13 03:22:10 +00:00
|
|
|
link: this.$route.query.url ?? "",
|
|
|
|
|
parse_failed: false,
|
2024-01-13 02:00:15 +00:00
|
|
|
recipe: null,
|
2024-01-13 08:43:15 +00:00
|
|
|
chefs: [],
|
2024-01-13 02:00:15 +00:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
2024-01-13 03:22:10 +00:00
|
|
|
this.refreshRecipe();
|
|
|
|
|
},
|
2024-01-13 08:43:15 +00:00
|
|
|
computed: {
|
|
|
|
|
image_styling() {
|
|
|
|
|
if (this.recipe?.image_urls && this.recipe.image_urls[0]) {
|
|
|
|
|
const image = this.recipe.image_urls[0];
|
|
|
|
|
// linear-gradient(to bottom, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0) 100%), url('https://i2.wp.com/www.downshiftology.com/wp-content/uploads/2019/04/steamed-broccoli-4.jpg') center/cover no-repeat;
|
|
|
|
|
return {background: `linear-gradient(to bottom, rgba(255, 255, 255, 0.8) 0%, rgba(255, 255, 255, 0) 100%), url('${image}') center/cover no-repeat` }
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
},
|
2024-01-13 03:22:10 +00:00
|
|
|
methods: {
|
|
|
|
|
parseLink() {
|
|
|
|
|
this.$router.push({ path: '/recipes/add', query: { url: this.link }})
|
|
|
|
|
this.refreshRecipe();
|
|
|
|
|
},
|
2024-01-17 09:17:22 +00:00
|
|
|
async refreshRecipe() {
|
2024-01-13 07:00:55 +00:00
|
|
|
if (this.id) {
|
2024-01-17 09:17:22 +00:00
|
|
|
this.recipe = await data.getRecipe(this.id);
|
|
|
|
|
this.link = this.recipe.link;
|
2024-01-13 07:00:55 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else if (this.link) {
|
2024-01-17 09:17:22 +00:00
|
|
|
this.recipe = await data.parseRecipe(this.link);
|
|
|
|
|
this.parse_failed = !this.recipe;
|
2024-01-13 07:00:55 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2024-01-13 03:22:10 +00:00
|
|
|
this.recipe = null;
|
|
|
|
|
}
|
2024-01-13 02:00:15 +00:00
|
|
|
},
|
2024-01-17 09:17:22 +00:00
|
|
|
async updateProduct(ingredient, product_link) {
|
2024-01-17 12:18:33 +00:00
|
|
|
const product = await data.parseProduct(ingredient, product_link);
|
2024-05-04 01:52:31 +00:00
|
|
|
this.recipe.ingredients = this.recipe.ingredients.map(i => i.name == ingredient.name ? { ...i, product, product_id: product.id } : i);
|
2024-01-13 02:00:15 +00:00
|
|
|
},
|
2024-01-17 09:17:22 +00:00
|
|
|
async updateIngredient(ingredient, line) {
|
|
|
|
|
const newIngredients = await data.parseIngredients([line]);
|
2024-01-17 12:18:33 +00:00
|
|
|
const newIngredient = newIngredients[0];
|
|
|
|
|
if (!newIngredient?.product) {
|
|
|
|
|
newIngredient.product = ingredient.product;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.recipe.ingredients = this.recipe.ingredients.map(i => i == ingredient ? newIngredient : i);
|
2024-01-13 02:00:15 +00:00
|
|
|
},
|
2024-01-13 06:36:02 +00:00
|
|
|
deleteIngredient(ingredient) {
|
|
|
|
|
this.recipe.ingredients = this.recipe.ingredients.filter(i => i != ingredient);
|
|
|
|
|
},
|
2024-01-17 09:17:22 +00:00
|
|
|
async saveRecipe() {
|
|
|
|
|
const recipe = await data.saveRecipe(this.recipe);
|
|
|
|
|
if (recipe?.id) {
|
|
|
|
|
this.$router.push(`/recipes/${recipe.id}`);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
alert('Failed to save recipe');
|
2024-05-04 01:52:31 +00:00
|
|
|
},
|
|
|
|
|
async createFromScratch() {
|
|
|
|
|
this.recipe = {
|
|
|
|
|
id: 0,
|
|
|
|
|
name: 'My new recipe',
|
|
|
|
|
link: '',
|
|
|
|
|
ingredients: [],
|
|
|
|
|
image_urls: []
|
|
|
|
|
}
|
2024-01-13 03:22:10 +00:00
|
|
|
}
|
2024-01-13 02:00:15 +00:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
</script>
|