enrecipes/app/components/EditRecipe.vue

915 lines
27 KiB
Vue
Raw Normal View History

2020-10-14 19:32:32 +00:00
<template>
2020-11-10 18:28:48 +00:00
<Page @loaded="onPageLoad" @unloaded="releaseBackEvent">
2020-10-14 19:32:32 +00:00
<ActionBar :flat="viewIsScrolled ? false : true">
2020-11-02 11:36:53 +00:00
<GridLayout rows="*" columns="auto, *, auto">
2020-11-10 18:28:48 +00:00
<MDButton
variant="text"
2020-11-02 11:36:53 +00:00
class="bx"
2020-10-14 19:32:32 +00:00
:text="icon.back"
automationText="Back"
col="0"
@tap="navigateBack"
/>
2020-10-21 17:54:45 +00:00
<Label class="title orkm" :text="title" col="1" />
2020-11-10 18:28:48 +00:00
<MDButton
variant="text"
2020-11-23 09:49:58 +00:00
v-if="hasChanges && !saving"
2020-10-14 19:32:32 +00:00
class="bx"
:text="icon.save"
col="2"
2020-11-02 11:36:53 +00:00
@tap="saveOperation"
2020-10-14 19:32:32 +00:00
/>
2020-11-23 09:49:58 +00:00
<MDActivityIndicator col="2" v-if="saving" :busy="saving" />
2020-10-14 19:32:32 +00:00
</GridLayout>
</ActionBar>
<ScrollView
width="100%"
height="100%"
@scroll="onScroll"
2020-11-23 09:49:58 +00:00
scrollBarIndicatorVisible="true"
>
<StackLayout width="100%" padding="0 0 128">
<AbsoluteLayout>
<StackLayout
width="100%"
:height="screenWidth"
class="imageHolder"
verticalAlignment="center"
>
<Image
v-if="recipeContent.imageSrc"
:src="recipeContent.imageSrc"
stretch="aspectFill"
2020-10-14 19:32:32 +00:00
width="100%"
:height="screenWidth"
/>
<Label
v-else
horizontalAlignment="center"
class="bx"
fontSize="160"
:text="icon.image"
/>
</StackLayout>
<transition :name="recipeContent.imageSrc ? 'null' : 'bounce'">
<MDFloatingActionButton
v-if="showFab"
:top="screenWidth - 44"
:left="screenWidth - 88"
class="bx"
src="res://camera"
@tap="imageHandler"
/>
</transition>
</AbsoluteLayout>
<StackLayout margin="0 16">
<AbsoluteLayout class="inputField">
<TextField
hint="My Healthy Recipe"
v-model="recipeContent.title"
@loaded="setInputTypeText($event, 'words')"
/>
<Label top="0" class="fieldLabel" text="Title" />
</AbsoluteLayout>
<AbsoluteLayout class="inputField">
<TextField
:text="recipeContent.category"
editable="false"
@focus="modalOpen === false && showCategories(true)"
@tap="showCategories(false)"
/>
<Label top="0" class="fieldLabel" text="Category" />
</AbsoluteLayout>
<GridLayout columns="*, 8, *">
<AbsoluteLayout class="inputField" col="0">
<TextField
ref="yieldQuantity"
v-model="recipeContent.yield.quantity"
hint="1"
keyboardType="number"
/>
<Label top="0" class="fieldLabel" text="Yield quantity" />
2020-10-14 19:32:32 +00:00
</AbsoluteLayout>
<AbsoluteLayout class="inputField" col="2">
2020-10-14 19:32:32 +00:00
<TextField
:text="recipeContent.yield.unit"
editable="false"
@focus="modalOpen === false && showYieldUnits(true)"
@tap="showYieldUnits(false)"
2020-10-14 19:32:32 +00:00
/>
<Label top="0" class="fieldLabel" text="Yield measured in" />
2020-10-14 19:32:32 +00:00
</AbsoluteLayout>
</GridLayout>
<GridLayout columns="*, 8, *">
<AbsoluteLayout class="inputField" col="0">
<TextField
ref="timeRequired"
:text="timeRequired"
editable="false"
@focus="modalOpen === false && setTimeRequired(true)"
@tap="setTimeRequired(false)"
/>
<Label top="0" class="fieldLabel" text="Time required" />
</AbsoluteLayout>
</GridLayout>
<StackLayout class="hr" margin="24 16"></StackLayout>
</StackLayout>
<StackLayout margin="0 16">
<Label text="Ingredients" class="sectionTitle" />
<GridLayout
columns="*,8,auto,8,auto,8,auto"
v-for="(ingredient, index) in recipeContent.ingredients"
:key="index"
>
<TextField
ref="ingredient"
@loaded="focusField($event, 'sentence')"
col="0"
v-model="recipeContent.ingredients[index].item"
:hint="`Item ${index + 1}`"
returnKeyType="next"
/>
<TextField
width="68"
col="2"
v-model="recipeContent.ingredients[index].quantity"
hint="1.00"
keyboardType="number"
returnKeyType="next"
/>
<TextField
width="68"
col="4"
v-model="recipeContent.ingredients[index].unit"
hint="Unit"
editable="false"
@focus="modalOpen === false && showUnits($event, true, index)"
@tap="showUnits($event, false, index)"
/>
2020-11-10 18:28:48 +00:00
<MDButton
variant="text"
col="6"
class="bx closeBtn"
:text="icon.close"
@tap="removeIngredient(index)"
2020-10-14 19:32:32 +00:00
/>
</GridLayout>
<MDButton
variant="text"
class="text-btn orkm"
text="+ ADD INGREDIENT"
@tap="addIngredient()"
/>
2020-10-14 19:32:32 +00:00
<StackLayout class="hr" margin="24 16"></StackLayout>
</StackLayout>
2020-10-14 19:32:32 +00:00
<StackLayout margin="0 16">
<Label text="Instructions" class="sectionTitle" />
<GridLayout
columns="*,8,auto"
v-for="(instruction, index) in recipeContent.instructions"
:key="index"
>
<TextView
@loaded="focusField($event, 'multiLine')"
col="0"
:hint="`Step ${index + 1}`"
v-model="recipeContent.instructions[index]"
/>
2020-11-10 18:28:48 +00:00
<MDButton
variant="text"
col="2"
class="bx closeBtn"
:text="icon.close"
@tap="removeInstruction(index)"
2020-10-14 19:32:32 +00:00
/>
</GridLayout>
<MDButton
variant="text"
class="text-btn orkm"
text="+ ADD STEP"
@tap="addInstruction"
/>
<StackLayout class="hr" margin="24 16"></StackLayout>
</StackLayout>
2020-10-14 19:32:32 +00:00
<StackLayout margin="0 16">
<Label text="Notes" class="sectionTitle" />
<GridLayout
columns="*,8,auto"
v-for="(note, index) in recipeContent.notes"
:key="index"
>
<TextView
@loaded="focusField($event, 'multiLine')"
col="0"
:hint="`Note ${index + 1}`"
v-model="recipeContent.notes[index]"
/>
2020-11-10 18:28:48 +00:00
<MDButton
variant="text"
col="2"
class="bx closeBtn"
:text="icon.close"
@tap="removeNote(index)"
2020-11-10 18:28:48 +00:00
/>
</GridLayout>
<MDButton
variant="text"
class="text-btn orkm"
text="+ ADD NOTE"
@tap="addNote"
/>
<StackLayout class="hr" margin="24 16"></StackLayout>
</StackLayout>
2020-10-14 19:32:32 +00:00
<StackLayout margin="0 16">
<Label text="References" class="sectionTitle" />
<GridLayout
columns="*,8,auto"
v-for="(reference, index) in recipeContent.references"
:key="index"
>
<TextView
@loaded="focusField($event, 'multiLine')"
col="0"
v-model="recipeContent.references[index]"
hint="Text or Website/Video URL"
/>
2020-11-10 18:28:48 +00:00
<MDButton
variant="text"
col="2"
class="bx closeBtn"
:text="icon.close"
@tap="removeReference(index)"
2020-10-14 19:32:32 +00:00
/>
</GridLayout>
<MDButton
variant="text"
class="text-btn orkm"
text="+ ADD REFERENCE"
@tap="addReference"
/>
<StackLayout class="hr" margin="24 16"></StackLayout>
</StackLayout>
2020-11-15 10:51:10 +00:00
2020-11-23 09:49:58 +00:00
<StackLayout margin="0 16 24">
<Label text="Combinations" class="sectionTitle" />
<GridLayout
columns="*,8,auto"
v-for="(combination, index) in recipeContent.combinations"
:key="index"
>
<TextField
class="combinationToken"
col="0"
:text="getCombinationTitle(combination)"
editable="false"
/>
2020-11-15 10:51:10 +00:00
<MDButton
variant="text"
col="2"
class="bx closeBtn"
:text="icon.close"
@tap="removeCombination(combination)"
2020-11-15 10:51:10 +00:00
/>
</GridLayout>
<MDButton
variant="text"
class="text-btn orkm"
text="+ ADD COMBINATION"
@tap="showCombinations"
/>
2020-10-14 19:32:32 +00:00
</StackLayout>
</StackLayout>
</ScrollView>
2020-10-14 19:32:32 +00:00
</Page>
</template>
<script>
import {
AndroidApplication,
2020-11-10 18:28:48 +00:00
Application,
ApplicationSettings,
File,
getFileAccess,
2020-11-10 18:28:48 +00:00
ImageSource,
knownFolders,
2020-11-10 18:28:48 +00:00
path,
Screen,
2020-11-02 11:36:53 +00:00
Utils,
2020-11-15 10:51:10 +00:00
ObservableArray,
} from "@nativescript/core"
2020-11-10 18:28:48 +00:00
import * as Permissions from "@nativescript-community/perms"
import * as Toast from "nativescript-toast"
2020-11-11 13:50:33 +00:00
import * as Filepicker from "nativescript-plugin-filepicker"
2020-11-10 18:28:48 +00:00
import { ImageCropper } from "nativescript-imagecropper"
2020-10-14 19:32:32 +00:00
import { mapState, mapActions } from "vuex"
2020-10-22 18:36:50 +00:00
2020-10-21 17:54:45 +00:00
import ActionDialog from "./modal/ActionDialog.vue"
2020-11-15 10:51:10 +00:00
import ActionDialogWithSearch from "./modal/ActionDialogWithSearch.vue"
2020-10-21 17:54:45 +00:00
import ConfirmDialog from "./modal/ConfirmDialog.vue"
import PromptDialog from "./modal/PromptDialog.vue"
2020-11-02 11:36:53 +00:00
import ListPicker from "./modal/ListPicker.vue"
2020-10-21 17:54:45 +00:00
2020-11-23 09:49:58 +00:00
import * as utils from "~/shared/utils"
2020-10-14 19:32:32 +00:00
export default {
2020-11-23 09:49:58 +00:00
props: ["recipeID", "selectedCategory", "filterFavorites", "filterTrylater"],
2020-10-14 19:32:32 +00:00
data() {
return {
2020-10-21 17:54:45 +00:00
title: "New recipe",
2020-10-14 19:32:32 +00:00
viewIsScrolled: false,
recipeContent: {
imageSrc: null,
title: undefined,
category: "Undefined",
2020-11-02 11:36:53 +00:00
timeRequired: "00:00",
yield: {
quantity: undefined,
unit: "Servings",
},
ingredients: [],
instructions: [],
notes: [],
references: [],
2020-11-15 10:51:10 +00:00
combinations: [],
2020-10-26 20:49:54 +00:00
isFavorite: false,
2020-11-23 09:49:58 +00:00
tried: true,
2020-11-02 11:36:53 +00:00
lastTried: null,
2020-10-26 20:49:54 +00:00
lastModified: null,
},
tempRecipeContent: {},
2020-10-21 17:54:45 +00:00
blockModal: false,
2020-11-11 13:50:33 +00:00
modalOpen: false,
newRecipeID: null,
showFab: false,
2020-11-23 09:49:58 +00:00
saving: false,
2020-11-10 18:28:48 +00:00
cacheImagePath: null,
2020-11-15 10:51:10 +00:00
unSyncCombinations: [],
2020-10-14 19:32:32 +00:00
}
},
computed: {
2020-11-02 11:36:53 +00:00
...mapState([
"icon",
"units",
"yieldUnits",
"recipes",
"categories",
"currentComponent",
]),
2020-10-14 19:32:32 +00:00
screenWidth() {
2020-10-22 18:36:50 +00:00
return Screen.mainScreen.widthDIPs
2020-10-14 19:32:32 +00:00
},
2020-11-10 18:28:48 +00:00
appTheme() {
return Application.systemAppearance()
},
hasChanges() {
return (
JSON.stringify(this.recipeContent) !==
JSON.stringify(this.tempRecipeContent)
)
2020-10-14 19:32:32 +00:00
},
2020-11-10 18:28:48 +00:00
timeRequired() {
2020-11-02 11:36:53 +00:00
let t = this.recipeContent.timeRequired.split(":")
let h = parseInt(t[0])
let m = parseInt(t[1])
2020-11-11 13:50:33 +00:00
return h ? (m ? `${h} hr ${m} min` : `${h} hr`) : `${m} min`
2020-11-02 11:36:53 +00:00
},
2020-10-14 19:32:32 +00:00
},
methods: {
2020-10-26 20:49:54 +00:00
...mapActions([
"setCurrentComponentAction",
"addRecipeAction",
"overwriteRecipeAction",
"addCategoryAction",
2020-11-02 11:36:53 +00:00
"addYieldUnitAction",
2020-11-15 10:51:10 +00:00
"unSyncCombinationsAction",
2020-10-26 20:49:54 +00:00
]),
2020-11-10 18:28:48 +00:00
onPageLoad() {
this.showFab = true
},
2020-11-02 11:36:53 +00:00
// HELPERS
2020-11-11 13:50:33 +00:00
focusField(args, type) {
2020-11-15 10:51:10 +00:00
if (type) this.setInputTypeText(args, type)
2020-11-02 11:36:53 +00:00
if (!args.object.text) {
args.object.focus()
2020-11-15 21:13:06 +00:00
setTimeout((e) => Utils.ad.showSoftInput(args.object.android), 10)
2020-11-02 11:36:53 +00:00
}
},
2020-11-11 13:50:33 +00:00
setInputTypeText(args, type) {
let field = args.object
switch (type) {
case "words":
field.android.setInputType(
android.text.InputType.TYPE_CLASS_TEXT |
android.text.InputType.TYPE_TEXT_FLAG_CAP_WORDS |
android.text.InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
)
break
case "sentence":
field.android.setInputType(
android.text.InputType.TYPE_CLASS_TEXT |
android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES |
android.text.InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
)
break
case "multiLine":
field.android.setInputType(
android.text.InputType.TYPE_CLASS_TEXT |
android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE |
android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES |
android.text.InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
)
break
default:
break
}
},
getRandomID() {
let res = ""
let chars = "abcdefghijklmnopqrstuvwxyz0123456789"
for (let i = 0; i < 10; i++) {
res += chars.charAt(Math.floor(Math.random() * chars.length))
}
return res
2020-10-21 17:54:45 +00:00
},
2020-11-11 13:50:33 +00:00
setTimeRequired(focus) {
this.modalOpen = true
2020-11-02 11:36:53 +00:00
let time = this.recipeContent.timeRequired.split(":")
let hr = time[0]
let min = time[1]
this.$showModal(ListPicker, {
props: {
2020-11-11 13:50:33 +00:00
title: "Time required",
2020-11-02 11:36:53 +00:00
action: "SET",
selectedHr: hr,
selectedMin: min,
},
}).then((result) => {
if (result) {
this.recipeContent.timeRequired = result
2020-11-11 13:50:33 +00:00
this.modalOpen = false
if (focus) this.addIngredient()
2020-10-21 17:54:45 +00:00
}
})
2020-10-14 19:32:32 +00:00
},
onScroll(args) {
args.scrollY
? (this.viewIsScrolled = true)
: (this.viewIsScrolled = false)
},
2020-11-02 11:36:53 +00:00
// DATA LIST
2020-11-11 13:50:33 +00:00
showCategories(focus) {
this.modalOpen = true
2020-10-21 17:54:45 +00:00
this.releaseBackEvent()
this.$showModal(ActionDialog, {
props: {
title: "Category",
list: [...this.categories],
2020-11-10 18:28:48 +00:00
// height: "420",
action: "ADD NEW",
2020-10-21 17:54:45 +00:00
},
}).then((action) => {
2020-11-10 18:28:48 +00:00
if (action == "ADD NEW") {
2020-10-21 17:54:45 +00:00
this.$showModal(PromptDialog, {
props: {
title: "New category",
action: "ADD",
},
2020-10-26 20:49:54 +00:00
}).then((category) => {
2020-10-21 17:54:45 +00:00
this.hijackBackEvent()
2020-10-26 20:49:54 +00:00
if (category.length) {
this.recipeContent.category = category
this.addCategoryAction(category)
2020-11-11 13:50:33 +00:00
if (focus) this.autoFocusField("yieldQuantity")
this.modalOpen = false
2020-10-21 17:54:45 +00:00
}
})
} else if (action) {
this.recipeContent.category = action
this.hijackBackEvent()
2020-11-11 13:50:33 +00:00
if (focus) this.autoFocusField("yieldQuantity")
this.modalOpen = false
2020-10-21 17:54:45 +00:00
} else {
this.hijackBackEvent()
2020-10-14 19:32:32 +00:00
}
2020-10-21 17:54:45 +00:00
})
2020-10-14 19:32:32 +00:00
},
2020-11-11 13:50:33 +00:00
autoFocusField(ref) {
this.$refs[ref].nativeView.focus()
setTimeout(() => {
Utils.ad.showSoftInput(this.$refs[ref].nativeView.android)
}, 1)
},
showYieldUnits(focus) {
this.modalOpen = true
2020-11-02 11:36:53 +00:00
this.releaseBackEvent()
this.$showModal(ActionDialog, {
props: {
title: "Yield measured in",
list: [...this.yieldUnits],
2020-11-10 18:28:48 +00:00
// height: "420",
action: "ADD NEW",
2020-11-02 11:36:53 +00:00
},
}).then((action) => {
2020-11-10 18:28:48 +00:00
if (action == "ADD NEW") {
2020-11-02 11:36:53 +00:00
this.$showModal(PromptDialog, {
props: {
title: "New yield unit",
action: "ADD",
},
}).then((yieldUnit) => {
this.hijackBackEvent()
if (yieldUnit.length) {
this.recipeContent.yield.unit = yieldUnit
this.addYieldUnitAction(yieldUnit)
2020-11-11 13:50:33 +00:00
this.modalOpen = false
if (focus) this.autoFocusField("timeRequired")
2020-11-02 11:36:53 +00:00
}
})
} else if (action) {
this.recipeContent.yield.unit = action
this.hijackBackEvent()
2020-11-11 13:50:33 +00:00
this.modalOpen = false
if (focus) this.autoFocusField("timeRequired")
2020-11-02 11:36:53 +00:00
} else {
this.hijackBackEvent()
}
})
},
2020-11-15 21:13:06 +00:00
showUnits(e, focus, index) {
2020-11-11 13:50:33 +00:00
this.modalOpen = true
2020-11-02 11:36:53 +00:00
this.releaseBackEvent()
this.$showModal(ActionDialog, {
props: {
title: "Unit",
list: [...this.units],
},
}).then((action) => {
this.hijackBackEvent()
2020-11-11 13:50:33 +00:00
if (action) {
e.object.text = action
this.modalOpen = false
2020-11-15 21:13:06 +00:00
if (focus) {
if (this.recipeContent.ingredients.length - 1 === index) {
this.addIngredient()
} else {
this.$refs.ingredient[index + 1].nativeView.focus()
setTimeout(
(e) =>
Utils.ad.showSoftInput(
this.$refs.ingredient[index + 1].nativeView.android
),
10
)
}
}
2020-11-11 13:50:33 +00:00
}
2020-11-02 11:36:53 +00:00
})
},
// NAVIGATION HANDLERS
2020-10-14 19:32:32 +00:00
navigateBack() {
2020-11-10 18:28:48 +00:00
if (this.hasChanges) {
2020-10-21 17:54:45 +00:00
this.blockModal = true
this.$showModal(ConfirmDialog, {
props: {
title: "Unsaved changes",
2020-10-21 17:54:45 +00:00
description:
2020-11-10 18:28:48 +00:00
"Are you sure you want to discard unsaved changes to this recipe?",
cancelButtonText: "DISCARD",
2020-11-10 18:28:48 +00:00
okButtonText: "KEEP EDITING",
2020-10-21 17:54:45 +00:00
},
}).then((action) => {
this.blockModal = false
2020-11-10 18:28:48 +00:00
if (action != null && !action) {
2020-10-21 17:54:45 +00:00
this.$navigateBack()
this.releaseBackEvent()
}
})
} else {
this.$navigateBack()
this.releaseBackEvent()
}
},
hijackBackEvent() {
2020-10-22 18:36:50 +00:00
AndroidApplication.on(
AndroidApplication.activityBackPressedEvent,
2020-10-21 17:54:45 +00:00
this.backEvent
)
},
releaseBackEvent() {
2020-10-22 18:36:50 +00:00
AndroidApplication.off(
AndroidApplication.activityBackPressedEvent,
2020-10-21 17:54:45 +00:00
this.backEvent
)
},
backEvent(args) {
2020-11-10 18:28:48 +00:00
if (this.hasChanges && !this.blockModal) {
2020-10-21 17:54:45 +00:00
args.cancel = true
this.navigateBack()
}
2020-10-14 19:32:32 +00:00
},
2020-11-02 11:36:53 +00:00
// DATA HANDLERS
imageHandler() {
if (this.recipeContent.imageSrc) {
this.blockModal = true
this.$showModal(ConfirmDialog, {
props: {
title: "Recipe photo",
cancelButtonText: "REMOVE",
okButtonText: "REPLACE PHOTO",
},
}).then((action) => {
this.blockModal = false
if (action) {
2020-11-11 15:49:06 +00:00
this.permissionCheck(this.permissionConfirmation, this.imagePicker)
} else if (action != null) {
2020-11-02 11:36:53 +00:00
this.recipeContent.imageSrc = null
this.releaseBackEvent()
}
})
} else {
2020-11-10 18:28:48 +00:00
this.permissionCheck(this.permissionConfirmation, this.imagePicker)
2020-11-06 09:07:41 +00:00
}
},
2020-11-10 18:28:48 +00:00
permissionConfirmation() {
2020-11-06 09:07:41 +00:00
return this.$showModal(ConfirmDialog, {
props: {
title: "Grant permission",
description:
2020-11-10 18:28:48 +00:00
"EnRecipes requires storage permission in order to set recipe photo.",
2020-11-06 09:07:41 +00:00
cancelButtonText: "NOT NOW",
okButtonText: "CONTINUE",
},
})
},
permissionCheck(confirmation, action) {
if (!ApplicationSettings.getBoolean("storagePermissionAsked", false)) {
confirmation().then((e) => {
if (e) {
2020-11-10 18:28:48 +00:00
Permissions.request("photo").then((status) => {
switch (status[0]) {
case "authorized":
action()
break
case "never_ask_again":
ApplicationSettings.setBoolean("storagePermissionAsked", true)
break
case "denied":
Toast.makeText("Permission denied").show()
break
default:
break
}
2020-11-06 09:07:41 +00:00
})
}
})
} else {
2020-11-10 18:28:48 +00:00
Permissions.check("photo").then((res) => {
res[0] !== "authorized"
2020-11-23 09:49:58 +00:00
? confirmation().then((e) => e && utils.openAppSettingsPage())
2020-11-10 18:28:48 +00:00
: action()
2020-11-06 09:07:41 +00:00
})
}
},
2020-11-02 11:36:53 +00:00
imagePicker() {
2020-11-10 18:28:48 +00:00
ApplicationSettings.setBoolean("storagePermissionAsked", true)
this.cacheImagePath = path.join(
knownFolders.temp().path,
`${this.getRandomID()}.jpg`
)
2020-11-11 13:50:33 +00:00
Filepicker.create({
2020-11-10 18:28:48 +00:00
mode: "single",
2020-11-11 13:50:33 +00:00
extensions: ["png", "jpeg", "jpg"],
2020-10-14 19:32:32 +00:00
})
2020-11-10 18:28:48 +00:00
.present()
.then((selection) => {
2020-11-11 13:50:33 +00:00
let imgPath = selection[0]
2020-11-10 18:28:48 +00:00
ImageSource.fromFile(imgPath).then((image) => {
ImageCropper.prototype
.show(
image,
{
2020-11-11 15:49:06 +00:00
width: 1080,
height: 1080,
2020-11-10 18:28:48 +00:00
},
{
hideBottomControls: true,
toolbarTitle: "Crop photo",
statusBarColor: "#ff5200",
toolbarTextColor:
this.appTheme == "light" ? "#212529" : "#f1f3f5",
toolbarColor:
this.appTheme == "light" ? "#f1f3f5" : "#212529",
cropFrameColor: "#ff5200",
}
)
.then((cropped) => {
cropped.image.saveToFile(this.cacheImagePath, "jpg", 75)
this.recipeContent.imageSrc = this.cacheImagePath
})
})
})
2020-10-14 19:32:32 +00:00
},
2020-11-11 15:49:06 +00:00
2020-11-10 18:28:48 +00:00
// INPUT FIELD HANDLERS
fieldDeletionConfirm(item) {
return this.$showModal(ConfirmDialog, {
props: {
title: `Delete ${item}?`,
cancelButtonText: "CANCEL",
okButtonText: "DELETE",
},
})
},
2020-10-14 19:32:32 +00:00
addIngredient() {
this.recipeContent.ingredients.push({
2020-10-21 17:54:45 +00:00
item: "",
2020-10-14 19:32:32 +00:00
quantity: null,
unit: "unit",
})
},
removeIngredient(index) {
2020-11-10 18:28:48 +00:00
if (this.recipeContent.ingredients[index].item.length) {
this.fieldDeletionConfirm("ingredient").then((res) => {
if (res) {
this.recipeContent.ingredients.splice(index, 1)
}
})
} else this.recipeContent.ingredients.splice(index, 1)
2020-10-14 19:32:32 +00:00
},
addInstruction() {
this.recipeContent.instructions.push("")
},
removeInstruction(index) {
2020-11-10 18:28:48 +00:00
if (this.recipeContent.instructions[index].length) {
this.fieldDeletionConfirm("instruction").then((res) => {
res && this.recipeContent.instructions.splice(index, 1)
2020-11-10 18:28:48 +00:00
})
} else this.recipeContent.instructions.splice(index, 1)
2020-10-14 19:32:32 +00:00
},
2020-11-15 10:51:10 +00:00
getCombinationTitle(id) {
return this.recipes.filter((e) => e.id === id)[0].title
},
showCombinations() {
let existingCombinations = [
...this.recipeContent.combinations,
this.recipeContent.id,
]
let filteredRecipes = this.recipes.filter(
(e) => !existingCombinations.includes(e.id)
)
this.$showModal(ActionDialogWithSearch, {
props: {
title: "Select a recipe",
recipes: filteredRecipes,
},
}).then((res) => {
if (res) {
this.recipeContent.combinations.push(res)
}
})
},
removeCombination(id) {
let index = this.recipeContent.combinations.indexOf(id)
this.fieldDeletionConfirm("combination").then((res) => {
if (res) {
this.recipeContent.combinations.splice(index, 1)
this.unSyncCombinations.push(id)
}
})
},
2020-10-14 19:32:32 +00:00
addNote() {
this.recipeContent.notes.push("")
},
removeNote(index) {
2020-11-10 18:28:48 +00:00
if (this.recipeContent.notes[index].length) {
this.fieldDeletionConfirm("note").then((res) => {
2020-11-15 10:51:10 +00:00
if (res) this.recipeContent.notes.splice(index, 1)
2020-11-10 18:28:48 +00:00
})
} else this.recipeContent.notes.splice(index, 1)
2020-10-14 19:32:32 +00:00
},
addReference() {
this.recipeContent.references.push("")
},
removeReference(index) {
2020-11-10 18:28:48 +00:00
if (this.recipeContent.references[index].length) {
this.fieldDeletionConfirm("reference").then((res) => {
if (res) {
this.recipeContent.references.splice(index, 1)
}
})
} else this.recipeContent.references.splice(index, 1)
2020-10-14 19:32:32 +00:00
},
2020-11-10 18:28:48 +00:00
// SAVE OPERATION
2020-11-02 11:36:53 +00:00
clearEmptyFields() {
if (!this.recipeContent.title)
this.recipeContent.title = "Untitled Recipe"
if (!this.recipeContent.yield.quantity)
this.recipeContent.yield.quantity = 1
this.recipeContent.ingredients = this.recipeContent.ingredients.filter(
(e) => e.item
)
let vm = this
function clearEmpty(arr) {
vm.recipeContent[arr] = vm.recipeContent[arr].filter((e) => e)
}
clearEmpty("instructions")
clearEmpty("notes")
clearEmpty("references")
},
saveOperation() {
2020-11-23 09:49:58 +00:00
this.saving = true
2020-11-02 11:36:53 +00:00
this.clearEmptyFields()
this.recipeContent.lastModified = new Date()
2020-11-10 18:28:48 +00:00
if (this.cacheImagePath) {
let recipeImage = path.join(
knownFolders
.documents()
.getFolder("EnRecipes")
.getFolder("Images").path,
`${this.getRandomID()}.jpg`
)
let binarySource = File.fromPath(this.cacheImagePath).readSync()
File.fromPath(recipeImage).writeSync(binarySource)
this.recipeContent.imageSrc = recipeImage
knownFolders.temp().clear()
}
2020-11-02 11:36:53 +00:00
if (this.recipeContent.imageSrc) {
2020-11-10 18:28:48 +00:00
if (
this.tempRecipeContent.imageSrc &&
this.tempRecipeContent.imageSrc !== this.recipeContent.imageSrc
) {
getFileAccess().deleteFile(this.tempRecipeContent.imageSrc)
}
2020-11-02 11:36:53 +00:00
} else if (this.tempRecipeContent.imageSrc) {
getFileAccess().deleteFile(this.tempRecipeContent.imageSrc)
}
2020-11-15 10:51:10 +00:00
this.unSyncCombinationsAction({
id: this.recipeID,
combinations: this.unSyncCombinations,
})
2020-11-10 18:28:48 +00:00
this.saveRecipe()
2020-11-02 11:36:53 +00:00
},
saveRecipe() {
if (this.recipeID) {
this.overwriteRecipeAction({
id: this.recipeID,
recipe: this.recipeContent,
})
} else {
this.recipeContent.id = this.newRecipeID
this.addRecipeAction({
id: this.newRecipeID,
recipe: this.recipeContent,
})
}
2020-11-11 15:49:06 +00:00
setTimeout(() => {
2020-11-23 09:49:58 +00:00
this.saving = false
2020-11-11 15:49:06 +00:00
}, 100)
2020-11-02 11:36:53 +00:00
this.$navigateBack()
2020-10-14 19:32:32 +00:00
},
},
2020-10-26 20:49:54 +00:00
created() {
setTimeout((e) => {
this.setCurrentComponentAction("EditRecipe")
}, 500)
this.title = this.recipeID ? "Edit recipe" : "New recipe"
2020-11-10 18:28:48 +00:00
2020-10-26 20:49:54 +00:00
if (this.recipeID) {
let recipe = this.recipes.filter((e) => e.id === this.recipeID)[0]
Object.assign(this.recipeContent, JSON.parse(JSON.stringify(recipe)))
2020-11-02 11:36:53 +00:00
Object.assign(
this.tempRecipeContent,
JSON.parse(JSON.stringify(this.recipeContent))
)
2020-10-26 20:49:54 +00:00
} else {
2020-11-10 18:28:48 +00:00
if (this.selectedCategory)
this.recipeContent.category = this.selectedCategory
if (this.filterFavorites) this.recipeContent.isFavorite = true
Object.assign(
this.tempRecipeContent,
JSON.parse(JSON.stringify(this.recipeContent))
)
2020-11-10 18:28:48 +00:00
2020-10-26 20:49:54 +00:00
this.newRecipeID = this.getRandomID()
}
this.hijackBackEvent()
},
2020-10-14 19:32:32 +00:00
}
</script>