before ns migrate

This commit is contained in:
Vishnu Raghav B 2020-10-21 23:24:45 +05:30
parent eb9e2da756
commit ce53ddb126
40 changed files with 1437 additions and 1613 deletions

View file

@ -11,7 +11,7 @@
android {
defaultConfig {
minSdkVersion 17
minSdkVersion 23
generatedDensities = []
}
aaptOptions {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 550 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 664 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -1,10 +1,11 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:gravity="fill">
<item>
<shape android:shape="rectangle">
<solid android:color="@android:color/white" />
</shape>
</item>
<item>
<bitmap android:gravity="center" android:src="@drawable/logo" />
</item>
</layer-list>
<item>
<shape android:shape="rectangle">
<!-- <solid android:color="@android:color/white" /> -->
<solid android:color="#ff7043" />
</shape>
</item>
<item android:left="64dp" android:right="64dp">
<bitmap android:gravity="center" android:src="@drawable/logo" />
</item>
</layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -1,4 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ns_accent">#ff7043</color>
</resources>
<color name="ns_primary">
#FFFFFF
</color>
<color name="ns_primaryDark">
#ff7043
</color>
<color name="ns_accent">
#ff7043
</color>
</resources>

View file

@ -1,23 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Application theme -->
<style name="AppTheme" parent="AppThemeBase">
<item name="android:datePickerStyle">@style/SpinnerDatePicker</item>
<item name="android:timePickerStyle">@style/SpinnerTimePicker</item>
</style>
<!-- Default style for DatePicker - in spinner mode -->
<style name="SpinnerDatePicker" parent="android:Widget.Material.Light.DatePicker">
<item name="android:datePickerMode">spinner</item>
</style>
<!-- Default style for TimePicker - in spinner mode -->
<style name="SpinnerTimePicker" parent="android:Widget.Material.Light.TimePicker">
<item name="android:timePickerMode">spinner</item>
</style>
<style name="NativeScriptToolbarStyle" parent="NativeScriptToolbarStyleBase">
<item name="android:elevation">4dp</item>
</style>
</resources>
<!-- Application theme -->
<style name="AppTheme" parent="AppThemeBase">
<item name="android:datePickerStyle">
@style/SpinnerDatePicker
</item>
<item name="android:timePickerStyle">
@style/SpinnerTimePicker
</item>
</style>
<!-- Default style for DatePicker - in spinner mode -->
<style name="SpinnerDatePicker" parent="android:Widget.Material.Light.DatePicker">
<item name="android:datePickerMode">
spinner
</item>
</style>
<!-- Default style for TimePicker - in spinner mode -->
<style name="SpinnerTimePicker" parent="android:Widget.Material.Light.TimePicker">
<item name="android:timePickerMode">
spinner
</item>
</style>
<style name="NativeScriptToolbarStyle" parent="NativeScriptToolbarStyleBase">
<item name="android:elevation">
0dp
</item>
</style>
</resources>

View file

@ -9,7 +9,4 @@
<color name="ns_accent">
#ff7043
</color>
<color name="ns_blue">
#272734
</color>
</resources>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">NativeScript-Vue Application</string>
<string name="title_activity_kimera">NativeScript-Vue Application</string>
<string name="app_name">EnRecipes</string>
<string name="title_activity_kimera">EnRecipes</string>
</resources>

View file

@ -12,7 +12,7 @@
<item name="android:windowBackground">@drawable/splash_screen</item>
<item name="android:windowActionBarOverlay">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentStatus">false</item>
</style>
<style name="LaunchScreenTheme" parent="LaunchScreenThemeBase">

View file

@ -37,7 +37,8 @@ Page {
.ns-light {
Page,
ActionBar,
SearchBar {
SearchBar,
TabView {
background: $grayL4;
color: $grayD4;
}
@ -58,8 +59,10 @@ Page {
.fieldLabel {
background: $grayL4;
}
.recipe-li,
.option-highlight {
background: $grayL2;
}
.recipe-li {
background: white;
}
.sd-item,
@ -102,7 +105,8 @@ Page {
.ns-dark {
Page,
ActionBar,
SearchBar {
SearchBar,
TabView {
background: $grayD4;
color: $grayL4;
}
@ -169,9 +173,10 @@ Page {
TextField,
TextView,
TimePickerField {
width: 100%;
border-width: 1;
font-size: 15;
padding: 16;
font-size: 14;
padding: 14;
margin: 8 0 0 0;
border-radius: 4;
placeholder-color: $gray;
@ -195,7 +200,8 @@ ActionBar {
padding: 0;
height: 64;
.bx {
padding: 16;
padding: 16 12;
vertical-alignment: center;
}
.leftAction {
padding: 16 16 16 4;
@ -207,8 +213,8 @@ ActionBar {
padding: 0;
}
SearchBar {
width: 100%;
font-size: 16;
margin-top: 4;
}
.title {
padding-left: 8;
@ -219,15 +225,25 @@ SearchBar {
// Side Drawer
.sd-item {
border-radius: 4;
padding: 12 16;
font-size: 14;
padding: 0 16;
height: 48;
font-size: 16;
vertical-alignment: center;
// prettier-ignore
.bx, Label {
vertical-alignment: center;
}
}
.sd-group-header {
padding: 12;
width: 100%;
padding: 8 8 16;
font-size: 12;
}
// Home
RadListView {
margin-bottom: 128;
}
.recipe-li {
margin: 8 16;
border-radius: 6;
@ -235,6 +251,7 @@ SearchBar {
margin: 4 0;
}
.recipe-cat {
font-size: 12;
padding: 0;
margin: 0;
}
@ -248,21 +265,18 @@ SearchBar {
padding: 0;
}
.recipe-favorite {
font-size: 14;
padding: 14 12 0 0;
font-size: 12;
padding: 14 8 0 0;
}
.recipe-cat,
.recipe-favorite {
color: $orange;
}
.recipe-favorite.hide {
opacity: 0;
}
}
// Settings
.group-header {
padding: 12;
padding: 8;
color: #ff7043;
}
.main-container {
@ -317,22 +331,27 @@ SearchBar {
}
.view-title {
font-size: 22;
line-height: 6;
margin-bottom: 16;
}
.view-ingredient {
font-size: 14;
line-height: 6;
margin-top: 12;
padding-bottom: 16;
}
.view-favorited {
color: #ff7043;
}
.activity-indicator {
background: #ff7043;
}
.view-count {
font-size: 10;
width: 20;
height: 20;
padding: 3 0 0;
margin-left: 6;
padding-top: 3%;
margin: 0 0 0 6;
text-align: center;
border-radius: 100;
}
@ -342,7 +361,7 @@ SearchBar {
.view-reference {
font-size: 14;
line-height: 6;
padding: 0 0 12 24;
padding: 0 0 16 24;
margin: 0 0 0 15;
border-width: 0 0 0 2;
}
@ -368,3 +387,7 @@ SearchBar {
padding: 16;
margin: 8 0 0 0;
}
.closeBtn {
padding: 4;
margin-top: 16;
}

View file

@ -1,5 +1,5 @@
<template>
<Page>
<Page @loaded="setCurrentComponent">
<ActionBar :flat="viewIsScrolled ? false : true">
<!-- Settings Actionbar -->
<GridLayout rows="*" columns="auto, *" class="actionBarContainer">
@ -10,7 +10,7 @@
@tap="showDrawer"
col="0"
/>
<Label class="title orkm" :text="title" col="1" />
<Label class="title orkm" text="About" col="1" />
</GridLayout>
</ActionBar>
<ScrollView scrollBarIndicatorVisible="false">
@ -85,9 +85,12 @@ import { mapState, mapActions } from "vuex"
export default {
props: ["highlight", "viewIsScrolled", "showDrawer", "title"],
computed: {
...mapState(["icon"]),
...mapState(["icon",'currentComponent']),
},
methods: {
setCurrentComponent() {
this.$store.dispatch("setCurrentComponent", "About")
},
openURL(args, url) {
this.highlight(args)
utils.openUrl(url)

View file

@ -6,10 +6,10 @@
drawerContentSize="270"
showOverNavigation="true"
gesturesEnabled="true"
drawerTransition="RevealTransition"
drawerTransition="SlideInOnTopTransition"
>
<GridLayout
rows="auto, auto, *, auto, auto"
rows="*, auto"
columns="*"
~drawerContent
padding="8"
@ -17,62 +17,65 @@
>
<StackLayout row="0">
<StackLayout
@tap="localNavigation('EnRecipes', 'EnRecipes', true, false)"
v-for="(item, index) in topmenu"
:key="index"
@tap="navigateTo(item.component, false, false)"
orientation="horizontal"
class="sd-item orkm"
:class="{
'selected-sd-item':
currentComponent === 'EnRecipes' &&
!filterFavorites &&
!selectedCategory,
'selected-sd-item': currentComponent === item.component,
}"
>
<Label class="bx" :text="icon.home" margin="0 24 0 0" />
<Label verticalAlignment="center" text="Home" />
<Label class="bx" :text="icon[item.icon]" margin="0 24 0 0" />
<Label :text="item.title" />
</StackLayout>
<StackLayout
@tap="localNavigation('Favorites', 'Favorites', true, false)"
orientation="horizontal"
class="sd-item orkm"
:class="{
'selected-sd-item':
currentComponent === 'EnRecipes' && filterFavorites,
}"
<StackLayout class="hr m-10"></StackLayout>
<GridLayout
class="sd-group-header orkm"
rows="auto"
columns="*, auto"
>
<Label class="bx" :text="icon.heart" margin="0 24 0 0" />
<Label verticalAlignment="center" text="Favorites" />
</StackLayout>
</StackLayout>
<StackLayout
orientation="horizontal"
row="1"
class="sd-group-header orkr"
>
<Label text="Categories" />
</StackLayout>
<ScrollView row="2" scrollBarIndicatorVisible="false">
<StackLayout>
<StackLayout
@tap="localNavigation(item, item, false, true)"
v-for="(item, index) in categories"
:key="index"
orientation="horizontal"
class="sd-item orkm"
:class="{
'selected-sd-item':
currentComponent === 'EnRecipes' && selectedCategory == item,
}"
>
<Label class="bx" :text="icon.label" margin="0 24 0 0" />
<Label verticalAlignment="center" :text="item" />
<Label col="0" text="Categories" />
<Label
@tap="toggleCatEdit"
col="2"
:text="catEditMode ? 'DONE' : 'RENAME'"
/>
</GridLayout>
<ScrollView height="100%">
<StackLayout>
<GridLayout
@tap="navigateTo(item, false, true)"
v-for="(item, index) in categories"
:key="index"
class="sd-item orkm"
:class="{
'selected-sd-item': currentComponent == item,
}"
columns="auto, *, auto"
>
<Label
col="0"
class="bx"
:text="icon.label"
margin="0 24 0 0"
/>
<Label col="1" :text="item" />
<Label
v-if="catEditMode"
@tap="editCategory(item)"
col="2"
class="bx"
:text="icon.edit"
/>
</GridLayout>
</StackLayout>
</StackLayout>
</ScrollView>
<StackLayout row="3" class="hr m-10"></StackLayout>
<StackLayout row="4">
</ScrollView>
</StackLayout>
<StackLayout row="1">
<StackLayout class="hr m-10"></StackLayout>
<StackLayout
@tap="navigateTo(item.component, item.title)"
@tap="navigateTo(item.component, true, false)"
v-for="(item, index) in bottommenu"
:key="index"
orientation="horizontal"
@ -82,19 +85,30 @@
}"
>
<Label class="bx" :text="icon[item.icon]" margin="0 24 0 0" />
<Label verticalAlignment="center" :text="item.title" />
<Label :text="item.title" />
</StackLayout>
<StackLayout
orientation="horizontal"
class="sd-item orkm"
@tap="donate"
>
<Label class="bx" :text="icon.donate" margin="0 24 0 0" />
<Label text="Donate" />
</StackLayout>
</StackLayout>
</GridLayout>
<GridLayout ~mainContent rows="*" columns="*">
<Frame id="main-frame">
<Frame ref="mainFrame" id="main-frame">
<!-- Home -->
<EnRecipes
:selectedCategory="selectedCategory"
ref="enrecipes"
:filterFavorites="filterFavorites"
:title="title"
:filterMustTry="filterMustTry"
:selectedCategory="selectedCategory"
:showDrawer="showDrawer"
:hijackGlobalBackEvent="hijackGlobalBackEvent"
:releaseGlobalBackEvent="releaseGlobalBackEvent"
/>
</Frame>
</GridLayout>
@ -104,15 +118,20 @@
<script>
import * as utils from "tns-core-modules/utils/utils"
import { isAndroid } from "tns-core-modules/platform"
import * as application from "tns-core-modules/application"
import { getString } from "application-settings"
import Theme from "@nativescript/theme"
import * as Toast from "nativescript-toast"
import EnRecipes from "./EnRecipes.vue"
import Settings from "./Settings.vue"
import About from "./About.vue"
import PromptDialog from "./modal/PromptDialog.vue"
import { mapState } from "vuex"
import { Couchbase, ConcurrencyMode } from "nativescript-couchbase-plugin"
let page
export default {
components: {
@ -122,12 +141,26 @@ export default {
},
data() {
return {
title: "EnRecipes",
selectedCategory: null,
filterFavorites: false,
searchQuery: "",
showSearch: false,
currentComponent: "EnRecipes",
filterMustTry: false,
topmenu: [
{
title: "Home",
component: "EnRecipes",
icon: "home",
},
{
title: "Favorites",
component: "Favorites",
icon: "heart",
},
{
title: "Must-Try",
component: "Must-Try",
icon: "musttry",
},
],
bottommenu: [
{
title: "Settings",
@ -140,10 +173,11 @@ export default {
icon: "info",
},
],
catEditMode: false,
}
},
computed: {
...mapState(["recipes", "icon"]),
...mapState(["recipes", "categories", "icon", "currentComponent"]),
categories() {
let arr = this.recipes.map((e) => {
return e.category
@ -152,6 +186,39 @@ export default {
},
},
methods: {
toggleCatEdit() {
this.catEditMode = !this.catEditMode
this.setComponent("EnRecipes")
this.filterFavorites = this.filterMustTry = false
this.selectedCategory = null
this.$refs.enrecipes.updateFilter()
},
setComponent(comp) {
this.$store.dispatch("setCurrentComponent", comp)
},
editCategory(item) {
this.releaseGlobalBackEvent()
this.$showModal(PromptDialog, {
props: {
title: `Rename category`,
hint: item,
action: "RENAME",
},
}).then((result) => {
this.hijackGlobalBackEvent()
if (result.length) {
if (this.categories.includes(result)) {
Toast.makeText("Category already exists!", "long").show()
} else {
this.$store.dispatch("renameCategory", {
current: item,
updated: result,
})
this.catEditMode = false
}
}
})
},
highlight(args) {
let temp = args.object.className
args.object.className = `${temp} option-highlight`
@ -159,70 +226,103 @@ export default {
args.object.className = temp
}, 100)
},
// Navigation
setSelectedCategory(e) {
this.selectedCategory = e.item
this.closeDrawer()
},
removeBackEvent() {
application.android.off(
application.AndroidApplication.activityBackPressedEvent,
this.backEvent
)
},
backEvent(args) {
args.cancel = true
if (this.$refs.drawer.nativeView.getIsOpen()) this.closeDrawer()
else if (this.currentComponent !== "EnRecipes") {
this.$navigateBack({ frame: "main-frame" })
this.currentComponent = "EnRecipes"
} else if (this.filterFavorites || this.selectedCategory) {
this.title = "EnRecipes"
this.filterFavorites = false
this.selectedCategory = null
this.removeBackEvent()
}
},
localNavigation(to, title, filter, filterCategory) {
// navigateBackToHome
hijackGlobalBackEvent() {
application.android.on(
application.AndroidApplication.activityBackPressedEvent,
this.backEvent
this.globalBackEvent
)
if (this.currentComponent !== "EnRecipes") {
this.currentComponent = "EnRecipes"
this.$navigateBack({ frame: "main-frame" })
}
this.filterFavorites = false
this.selectedCategory = null
this.title = title
console.log(title)
if (filter) {
if (to === "Favorites") this.filterFavorites = true
} else if (filterCategory) this.selectedCategory = to
if (!this.filterFavorites && !this.selectedCategory)
this.removeBackEvent()
this.closeDrawer()
},
navigateTo(to, title) {
this.currentComponent = title
this.$navigateTo(to, {
frame: "main-frame",
// transition: {
// name: "slide",
// duration: 250,
// curve: "easeIn",
// },
props: {
highlight: this.highlight,
viewIsScrolled: this.viewIsScrolled,
showDrawer: this.showDrawer,
title,
},
backstackVisible: false,
})
this.closeDrawer()
releaseGlobalBackEvent() {
application.android.off(
application.AndroidApplication.activityBackPressedEvent,
this.globalBackEvent
)
},
globalBackEvent(args) {
function preventDefault() {
args.cancel = true
}
let vm = this
function isFiltered() {
vm.filterFavorites
? vm.setComponent("Favorites")
: vm.filterMustTry
? vm.setComponent("Must-Try")
: vm.selectedCategory
? vm.setComponent(vm.selectedCategory)
: vm.setComponent("EnRecipes")
}
if (this.$refs.drawer && this.$refs.drawer.nativeView.getIsOpen()) {
preventDefault()
this.closeDrawer()
this.catEditMode = false
} else if (
["Favorites", "Must-Try", this.selectedCategory].includes(
this.currentComponent
)
) {
preventDefault()
this.setComponent("EnRecipes")
this.filterFavorites = this.filterMustTry = false
this.selectedCategory = null
this.$refs.enrecipes.updateFilter()
this.releaseGlobalBackEvent()
}
},
navigateTo(to, isTrueComponent, isCategory) {
if (isTrueComponent) {
this.$navigateTo(to, {
frame: "main-frame",
props: {
highlight: this.highlight,
viewIsScrolled: this.viewIsScrolled,
showDrawer: this.showDrawer,
restartApp: this.restartApp,
hijackGlobalBackEvent: this.hijackGlobalBackEvent,
releaseGlobalBackEvent: this.releaseGlobalBackEvent,
},
backstackVisible: false,
})
this.closeDrawer()
} else if (!this.catEditMode) {
this.releaseGlobalBackEvent()
this.hijackGlobalBackEvent()
this.setComponent(to)
this.$navigateBack({ frame: "main-frame", backstackVisible: false })
this.filterFavorites = to === "Favorites" ? true : false
this.filterMustTry = to === "Must-Try" ? true : false
this.selectedCategory = isCategory ? to : null
this.$refs.enrecipes.updateFilter()
this.closeDrawer()
}
},
restartApp() {
// Code from nativescript-master-technology
const mStartActivity = new android.content.Intent(
application.android.context,
application.android.startActivity.getClass()
)
const mPendingIntentId = parseInt(Math.random() * 100000, 10)
const mPendingIntent = android.app.PendingIntent.getActivity(
application.android.context,
mPendingIntentId,
mStartActivity,
android.app.PendingIntent.FLAG_CANCEL_CURRENT
)
const mgr = application.android.context.getSystemService(
android.content.Context.ALARM_SERVICE
)
mgr.set(
android.app.AlarmManager.RTC,
java.lang.System.currentTimeMillis() + 100,
mPendingIntent
)
android.os.Process.killProcess(android.os.Process.myPid())
},
showDrawer() {
this.$refs.drawer.nativeView.showDrawer()
@ -230,6 +330,14 @@ export default {
closeDrawer() {
this.$refs.drawer.nativeView.closeDrawer()
},
donate(args) {
this.highlight(args)
utils.openUrl("https://www.vishnuraghav.com/donate/")
},
},
created() {
let themeName = getString("application-theme", "Light")
Theme.setMode(Theme[themeName])
},
}
</script>

View file

@ -1,5 +1,5 @@
<template>
<Page>
<Page @loaded="setCurrentComponent" @unloaded="releaseBackEvent">
<ActionBar :flat="viewIsScrolled ? false : true">
<GridLayout rows="*" columns="auto, *, auto," class="actionBarContainer">
<Label
@ -9,7 +9,8 @@
col="0"
@tap="navigateBack"
/>
<Label class="title orkm" text="New recipe" col="1" />
<Label class="title orkm" :text="title" col="1" />
<Label
v-if="hasEnoughDetails"
class="bx"
@ -46,7 +47,7 @@
horizontalAlignment="center"
class="bx"
fontSize="160"
:text="icon.dish"
:text="icon.image"
/>
</StackLayout>
<StackLayout
@ -75,17 +76,14 @@
<StackLayout margin="0 16">
<AbsoluteLayout class="inputField">
<TextField
width="100%"
hint="My Healthy Recipe"
v-model="recipeContent.title"
autocapitalizationType="words"
maxLength="32"
/>
<Label top="0" class="fieldLabel" text="Title" />
</AbsoluteLayout>
<AbsoluteLayout class="inputField">
<TextField
width="100%"
v-model="recipeContent.category"
editable="false"
@tap="showCategories()"
@ -95,7 +93,6 @@
<GridLayout columns="*, 8, *">
<AbsoluteLayout class="inputField" col="0">
<TimePickerField
width="100%"
timeFormat="HH:mm"
pickerTitle="Approx. preparation time"
@timeChange="onPrepTimeChange"
@ -105,7 +102,6 @@
</AbsoluteLayout>
<AbsoluteLayout class="inputField" col="2">
<TimePickerField
width="100%"
timeFormat="HH:mm"
pickerTitle="Approx. cooking time"
@timeChange="onCookTimeChange"
@ -157,11 +153,8 @@
@tap="showUnits($event)"
/>
<Label
verticalAlignment="center"
col="6"
padding="4"
margin="8 0 0 0"
class="bx"
class="bx closeBtn"
:text="icon.close"
@tap="removeIngredient(index)"
/>
@ -189,18 +182,9 @@
v-model="recipeContent.instructions[index]"
editable="true"
/>
<!-- <TextField
col="0"
v-model="recipeContent.instructions[index]"
:hint="`Step ${index + 1}`"
/> -->
<Label
verticalAlignment="center"
col="2"
padding="4"
margin="8 0 0 0"
class="bx"
class="bx closeBtn"
:text="icon.close"
@tap="removeInstruction(index)"
/>
@ -228,11 +212,8 @@
editable="true"
/>
<Label
verticalAlignment="center"
col="2"
padding="4"
margin="8 0 0 0"
class="bx"
class="bx closeBtn"
:text="icon.close"
@tap="removeNote(index)"
/>
@ -259,11 +240,8 @@
hint="Website or Video URL"
/>
<Label
verticalAlignment="center"
col="2"
padding="4"
margin="8 0 0 0"
class="bx"
class="bx closeBtn"
:text="icon.close"
@tap="removeReference(index)"
/>
@ -284,32 +262,17 @@
import { screen } from "tns-core-modules/platform"
import { Mediafilepicker } from "nativescript-mediafilepicker"
import { mapState, mapActions } from "vuex"
import * as application from "tns-core-modules/application"
import ActionDialog from "./modal/ActionDialog.vue"
import PromptDialog from "./modal/PromptDialog.vue"
import ConfirmDialog from "./modal/ConfirmDialog.vue"
export default {
props: ["recipeIndex", "selectedCategory"],
data() {
return {
title: "New recipe",
viewIsScrolled: false,
units: [
"unit",
"tsp",
"Tbsp",
"oz",
"cup",
"pt",
"qt",
"lb",
"gal",
"ml",
"L",
"mg",
"g",
"kg",
"mm",
"cm",
"m",
"in",
"°C",
"°F",
],
recipeContent: {
imageSrc: null,
title: null,
@ -319,7 +282,7 @@ export default {
portionSize: 1,
ingredients: [
{
item: null,
item: "",
quantity: null,
unit: "unit",
},
@ -328,71 +291,97 @@ export default {
notes: [""],
references: [""],
isFavorite: false,
tried: false,
lastModified: null,
},
categories: [
"Appetizers",
"BBQ",
"Beverages",
"Breads",
"Breakfast",
"Desserts",
"Dinner",
"Drinks",
"Healthy",
"Lunch",
"Main dishes",
"Meat",
"Noodles",
"Pasta",
"Poultry",
"Rice",
"Salads",
"Sauces",
"Seafood",
"Side dishes",
"Snacks",
"Soups",
"Vegan",
"Vegetarian",
"ADD NEW CATEGORY",
],
tempRecipeContent: {},
blockModal: false,
}
},
computed: {
...mapState(["icon"]),
...mapState(["icon", "units", "categories", "currentComponent", "recipes"]),
screenWidth() {
return screen.mainScreen.widthDIPs
},
hasEnoughDetails() {
let recipe = this.recipeContent
return recipe.title && recipe.category
if (this.recipeIndex) {
return (
JSON.stringify(this.recipeContent) !==
JSON.stringify(this.tempRecipeContent)
)
} else {
return this.recipeContent.title
}
},
},
methods: {
setTime(time) {
if (Date.parse(this.recipeContent[time])) {
let date = new Date(this.recipeContent[time])
setCurrentComponent() {
setTimeout((e) => {
this.$store.dispatch("setCurrentComponent", "EditRecipe")
}, 500)
this.title = this.recipeIndex >= 0 ? "Edit recipe" : "New recipe"
if (this.recipeIndex >= 0) {
Object.assign(this.recipeContent, this.recipes[this.recipeIndex])
Object.assign(this.tempRecipeContent, this.recipes[this.recipeIndex])
} else {
if (this.selectedCategory)
this.recipeContent.category = this.selectedCategory
Object.assign(this.tempRecipeContent, this.recipeContent)
}
this.hijackBackEvent()
},
setTime(key, time) {
if (Date.parse(time)) {
let date = new Date(time)
let h = date.getHours()
let m = date.getMinutes()
this.recipeContent[time] =
this.recipeContent[key] =
(h < 10 ? "0" + h : h) + ":" + (m < 10 ? "0" + m : m)
}
// console.log(this.recipeContent[time])
},
clearEmptyFields() {
if (!this.recipeContent.portionSize) {
this.recipeContent.portionSize = 1
}
if (!this.recipeContent.category) {
this.recipeContent.category = "Undefined"
}
this.recipeContent.ingredients.forEach((e, i) => {
if (!e.item.length) {
this.recipeContent.ingredients.splice(i, 1)
}
})
let vm = this
function removeEmpty(arr) {
vm.recipeContent[arr].forEach((e, i) => {
if (!e.length) {
vm.recipeContent[arr].splice(i, 1)
}
})
}
removeEmpty("instructions")
removeEmpty("notes")
removeEmpty("references")
},
saveRecipe() {
this.setTime("prepTime")
this.setTime("cookTime")
// console.log(this.recipeContent)
this.$store.dispatch("addRecipe", this.recipeContent)
this.clearEmptyFields()
this.recipeContent.lastModified = new Date()
if (this.recipeIndex >= 0) {
this.$store.dispatch("overwriteRecipe", {
index: this.recipeIndex,
recipe: this.recipeContent,
})
} else {
this.$store.dispatch("addRecipe", this.recipeContent)
}
this.$navigateBack()
},
onPrepTimeChange(args) {
this.recipeContent.prepTime = args.value
this.setTime("prepTime", args.value)
},
onCookTimeChange(args) {
this.recipeContent.cookTime = args.value
this.setTime("cookTime", args.value)
},
onScroll(args) {
args.scrollY
@ -400,25 +389,77 @@ export default {
: (this.viewIsScrolled = false)
},
showCategories() {
action("Select a category", "Cancel", [...this.categories]).then(
(result) => {
if (result != "Cancel") this.recipeContent.category = result
}
)
},
navigateBack() {
confirm({
message:
"Are you sure you want discard unsaved changes to this recipe?",
cancelButtonText: "Keep Editing",
okButtonText: "Discard",
}).then((res) => {
if (res) {
this.$navigateBack()
this.releaseBackEvent()
this.$showModal(ActionDialog, {
props: {
title: "Category",
list: [...this.categories],
height: "75%",
action: "NEW CATEGORY",
},
}).then((action) => {
if (action == "NEW CATEGORY") {
this.$showModal(PromptDialog, {
props: {
title: "New category",
action: "ADD",
},
}).then((result) => {
this.hijackBackEvent()
if (result.length) {
this.recipeContent.category = result
this.$store.dispatch("addCategory", result)
}
})
} else if (action) {
this.recipeContent.category = action
this.hijackBackEvent()
} else {
this.hijackBackEvent()
}
})
},
navigateBack() {
if (this.hasEnoughDetails) {
this.blockModal = true
this.$showModal(ConfirmDialog, {
props: {
title: "Discard changes",
description:
"Are you sure you want discard unsaved changes to this recipe?",
cancelButtonText: "KEEP EDITING",
okButtonText: "DISCARD",
},
}).then((action) => {
this.blockModal = false
if (action) {
this.$navigateBack()
this.releaseBackEvent()
}
})
} else {
this.$navigateBack()
this.releaseBackEvent()
}
},
hijackBackEvent() {
application.android.on(
application.AndroidApplication.activityBackPressedEvent,
this.backEvent
)
},
releaseBackEvent() {
application.android.off(
application.AndroidApplication.activityBackPressedEvent,
this.backEvent
)
},
backEvent(args) {
if (this.hasEnoughDetails && !this.blockModal) {
args.cancel = true
this.navigateBack()
}
},
takePicture() {
let mediafilepicker = new Mediafilepicker()
let vm = this
@ -462,7 +503,7 @@ export default {
},
removePicture() {
confirm({
title: "Delete Recipe Photo",
title: "Delete Photo",
message: "Are you sure you want to delete the recipe photo?",
okButtonText: "Delete",
cancelButtonText: "Cancel",
@ -473,7 +514,7 @@ export default {
addIngredient() {
this.recipeContent.ingredients.push({
item: null,
item: "",
quantity: null,
unit: "unit",
})
@ -504,11 +545,17 @@ export default {
},
showUnits(e) {
action("Select measuring unit", "Cancel", [...this.units]).then(
(result) => {
if (result != "Cancel") e.object.text = result
}
)
this.releaseBackEvent()
this.$showModal(ActionDialog, {
props: {
title: "Unit",
list: [...this.units],
height: "75%",
},
}).then((action) => {
this.hijackBackEvent()
if (action) e.object.text = action
})
},
},
}

View file

@ -1,12 +1,12 @@
<template>
<Page>
<Page @loaded="setCurrentComponent">
<ActionBar :flat="viewIsScrolled ? false : true">
<!-- Search Actionbar -->
<GridLayout
v-if="showSearch"
rows="*"
columns="auto, *"
class="actionBarContainer"
verticalAlignment="center"
>
<Label
class="bx leftAction"
@ -15,20 +15,20 @@
col="0"
@tap="closeSearch"
/>
<!-- @loaded="searchBarLoaded" -->
<SearchBar
@loaded="searchBarLoaded"
id="searchField"
col="1"
hint="Search"
textFieldHintColor="#bdbdbd"
v-model="searchQuery"
@textChange="updateFilter"
@clear="updateFilter"
/>
</GridLayout>
<!-- Home Actionbar -->
<GridLayout
v-else
rows="*"
columns="auto, *, auto,"
columns="auto, *, auto, auto"
class="actionBarContainer"
>
<Label
@ -38,84 +38,61 @@
@tap="showDrawer"
col="0"
/>
<Label class="title orkm" :text="title" col="1" />
<Label
class="bx"
:text="icon.search"
col="2"
@tap="showSearch = true"
/>
<Label class="title orkm" :text="currentComponent" col="1" />
<Label class="bx" :text="icon.search" col="2" @tap="openSearch" />
<Label class="bx" :text="icon.sort" col="3" @tap="sortDialog" />
</GridLayout>
</ActionBar>
<AbsoluteLayout>
<RadListView
v-if="filteredRecipes.length"
ref="listView"
for="recipe in filteredRecipes"
itemHeight="112"
for="recipe in recipes"
swipeActions="true"
@itemSwipeProgressChanged="onSwiping"
@itemSwipeProgressEnded="onSwipeEnded"
@scrolled="onScroll($event)"
@itemTap="viewRecipe"
:filteringFunction="filterFunction"
:sortingFunction="sortFunction"
>
<v-template>
<GridLayout
class="recipe-li"
rows="128"
columns="auto, *, auto"
androidElevation="2"
rows="112"
columns="112, *"
androidElevation="1"
>
<Image
src="res://icon"
stretch="fill"
col="0"
width="128"
height="128"
/>
<StackLayout
class="recipe-info"
col="1"
horizontalAlignment="left"
verticalAlignment="top"
>
<Label :text="recipe.category" class="orkm h4 recipe-cat" />
<Image col="0" src="res://icon" stretch="fill" />
<StackLayout class="recipe-info" col="1">
<Label :text="recipe.category" class="orkm recipe-cat" />
<Label :text="recipe.title" class="orkm recipe-title" />
<Label
:text="recipeTotalTime(recipe.prepTime, recipe.cookTime)"
class="h4 recipe-time"
/>
</StackLayout>
<Label
verticalAlignment="top"
col="2"
class="bx recipe-favorite"
:class="{ hide: !recipe.isFavorite }"
:text="icon.heart"
/>
</GridLayout>
</v-template>
<v-template name="itemswipe">
<GridLayout columns="auto, *, auto">
<StackLayout
id="favorite-action"
col="0"
class="swipe-item left"
verticalAlignment="top"
>
<Label class="bx" padding="8 6 0 0" :text="icon.heart" />
</StackLayout>
<StackLayout
id="delete-action"
col="2"
class="swipe-item right"
verticalAlignment="top"
>
<GridLayout columns="*, auto">
<StackLayout id="delete-action" col="1" class="swipe-item right">
<Label class="bx" padding="8 0 0 6" :text="icon.trash" />
</StackLayout>
</GridLayout>
</v-template>
<v-template name="footer">
<StackLayout height="128"></StackLayout>
</v-template>
</RadListView>
<Label
v-if="!recipes.length && !filterFavorites && !filterMustTry"
class="noResults"
horizontalAlignment="center"
text='Click the "+" icon to add a new recipe.'
textAlignment="center"
textWrap="true"
/>
<Label
v-if="!filteredRecipes.length && searchQuery"
class="noResults"
@ -134,12 +111,15 @@
textAlignment="center"
textWrap="true"
/>
<GridLayout
id="btnFabContainer"
rows="*,88"
columns="*,88"
v-if="!showSearch"
>
<Label
v-if="!filteredRecipes.length && filterMustTry && !searchQuery"
class="noResults"
horizontalAlignment="center"
text="Your Must-Try recipes will be listed here."
textAlignment="center"
textWrap="true"
/>
<GridLayout id="btnFabContainer" rows="*,88" columns="*,88">
<Label
row="1"
col="1"
@ -157,15 +137,25 @@
import * as utils from "tns-core-modules/utils/utils"
import * as application from "tns-core-modules/application"
import * as gestures from "tns-core-modules/ui/gestures"
import * as Toast from "nativescript-toast"
import { ObservableArray } from "tns-core-modules/data/observable-array"
import EditRecipe from "./EditRecipe.vue"
import ViewRecipe from "./ViewRecipe.vue"
import ActionDialog from "./modal/ActionDialog.vue"
import ConfirmDialog from "./modal/ConfirmDialog.vue"
import { mapState, mapActions } from "vuex"
export default {
props: ["filterFavorites", "selectedCategory", "title", "showDrawer"],
props: [
"filterFavorites",
"filterMustTry",
"selectedCategory",
"showDrawer",
"hijackGlobalBackEvent",
"releaseGlobalBackEvent",
],
components: {
EditRecipe,
ViewRecipe,
@ -173,80 +163,182 @@ export default {
data() {
return {
searchQuery: "",
showSearch: false,
viewIsScrolled: false,
leftAction: false,
showSearch: false,
// leftAction: false,
rightAction: false,
sortType: "Natural order",
}
},
computed: {
...mapState(["recipes", "icon"]),
recipesByCategory() {
return this.recipes.reduce((acc, e) => {
acc[e.category] = [...(acc[e.category] || []), e]
return acc
}, {})
},
...mapState(["recipes", "icon", "currentComponent"]),
filteredRecipes() {
if (this.selectedCategory) {
return this.recipesByCategory[this.selectedCategory].filter((e) => {
if (e.title.toLowerCase().includes(this.searchQuery)) return e
})
} else if (this.filterFavorites) {
console.log("fav")
return this.recipes.filter((e) => {
if (e.isFavorite) {
if (e.title.toLowerCase().includes(this.searchQuery)) return e
}
})
if (this.filterFavorites) {
return this.recipes.filter(
(e) =>
e.isFavorite && e.title.toLowerCase().includes(this.searchQuery)
)
} else if (this.filterMustTry) {
return this.recipes.filter(
(e) => !e.tried && e.title.toLowerCase().includes(this.searchQuery)
)
} else if (this.selectedCategory) {
return this.recipes.filter(
(e) =>
e.category === this.selectedCategory &&
e.title.toLowerCase().includes(this.searchQuery)
)
} else {
return this.recipes.filter((e) => {
if (e.title.toLowerCase().includes(this.searchQuery)) return e
})
return this.recipes.filter((e) =>
e.title.toLowerCase().includes(this.searchQuery)
)
}
},
},
methods: {
openSearch() {
this.showSearch = true
this.hijackLocalBackEvent()
},
hijackLocalBackEvent() {
this.releaseGlobalBackEvent()
application.android.on(
application.AndroidApplication.activityBackPressedEvent,
this.searchBackEvent
)
},
releaseLocalBackEvent() {
application.android.off(
application.AndroidApplication.activityBackPressedEvent,
this.searchBackEvent
)
this.hijackGlobalBackEvent()
},
searchBackEvent(args) {
args.cancel = true
this.closeSearch()
},
closeSearch() {
this.searchQuery = ""
utils.ad.dismissSoftInput()
this.showSearch = false
this.updateFilter()
this.releaseLocalBackEvent()
},
sortDialog() {
this.releaseGlobalBackEvent()
this.$showModal(ActionDialog, {
props: {
title: "Sort by",
list: ["Natural order", "Title", "Duration", "Last modified"],
height: "auto",
},
}).then((action) => {
if (action && action !== "Cancel" && this.sortType !== action) {
this.sortType = action
this.updateSort()
}
this.hijackGlobalBackEvent()
})
},
updateSort() {
let listView = this.$refs.listView.nativeView
listView.sortingFunction = undefined
listView.sortingFunction = this.sortFunction
},
sortFunction(item, otherItem) {
const titleOrder = item.title
.toLowerCase()
.localeCompare(otherItem.title.toLowerCase(), "en", {
ignorePunctuation: true,
})
let d1 = this.recipeDuration(item.prepTime, item.cookTime)
let d2 = this.recipeDuration(otherItem.prepTime, otherItem.cookTime)
let ld1 = new Date(item.lastModified)
let ld2 = new Date(otherItem.lastModified)
switch (this.sortType) {
case "Title":
return titleOrder > 0 ? -1 : titleOrder < 0 ? 1 : 0
break
case "Duration":
return d1 > d2 ? -1 : d1 < d2 ? 1 : 0
break
case "Last modified":
return ld1 < ld2 ? -1 : ld1 > ld2 ? 1 : 0
break
default:
return 0
break
}
},
setComponent(comp) {
this.$store.dispatch("setCurrentComponent", comp)
this.hijackGlobalBackEvent()
},
updateFilter() {
let listView = this.$refs.listView.nativeView
setTimeout((e) => {
listView.filteringFunction = undefined
listView.filteringFunction = this.filterFunction
}, 1)
},
filterFunction(item) {
if (this.filterFavorites) {
return item.isFavorite
? item.title.toLowerCase().includes(this.searchQuery)
: false
} else if (this.filterMustTry) {
return item.tried
? false
: item.title.toLowerCase().includes(this.searchQuery)
} else if (this.selectedCategory) {
return item.category === this.selectedCategory
? item.title.toLowerCase().includes(this.searchQuery)
: false
} else {
return item.title.toLowerCase().includes(this.searchQuery)
}
},
setCurrentComponent() {
this.filterFavorites
? this.setComponent("Favorites")
: this.filterMustTry
? this.setComponent("Must-Try")
: this.selectedCategory
? this.setComponent(this.selectedCategory)
: this.setComponent("EnRecipes")
},
onSwiping({ data, object }) {
const swipeLimits = data.swipeLimits
const swipeView = object
const leftItem = swipeView.getViewById("favorite-action")
const rightItem = swipeView.getViewById("delete-action")
swipeLimits.left = leftItem.getMeasuredWidth() - 12
swipeLimits.right = rightItem.getMeasuredWidth() - 12
swipeLimits.threshold = swipeLimits.left - 4
if (data.x > swipeLimits.threshold) {
this.leftAction = true
this.$refs.listView.notifySwipeToExecuteFinished()
} else if (data.x < -swipeLimits.threshold) {
swipeLimits.threshold = swipeLimits.right - 6
if (data.x < -swipeLimits.threshold) {
this.rightAction = true
this.$refs.listView.notifySwipeToExecuteFinished()
swipeView.notifySwipeToExecuteFinished()
}
},
onSwipeEnded({ index }) {
let context = this.recipes.indexOf(this.filteredRecipes[index])
if (this.leftAction) this.toggleFavorite(context)
else if (this.rightAction) this.deleteRecipe()
this.leftAction = this.rightAction = false
if (this.rightAction) this.deleteRecipe(index)
this.rightAction = false
},
toggleFavorite(index) {
this.$store.dispatch("toggleFavorite", index)
deleteRecipe(index) {
this.$showModal(ConfirmDialog, {
props: {
title: "Delete recipe",
description: `Are you sure you want to delete the recipe "${this.recipes[index].title}"?`,
cancelButtonText: "CANCEL",
okButtonText: "DELETE",
},
}).then((action) => {
if (action) {
this.$store.dispatch("deleteRecipe", index)
}
})
},
deleteRecipe() {
alert("Are you sure you want to delete?")
},
// swipeAction(args, index) {
// let vm = this
// args.object.on(gestures.GestureTypes.swipe, function(args) {
// console.log("Swipe Direction: " + args.direction)
// if (args.direction === 1) {
// vm.filteredRecipes[index].isFavorite = !vm.filteredRecipes[index]
// .isFavorite
// console.log(vm.filteredRecipes[index].isFavorite)
// }
// })
// },
recipeTotalTime(prepTime, cookTime) {
getTotalTime(prepTime, cookTime) {
let pT = prepTime.split(":")
let cT = cookTime.split(":")
let hrs = parseInt(pT[0]) + parseInt(cT[0])
@ -255,42 +347,26 @@ export default {
hrs += Math.floor(mins / 60)
mins -= 60
}
return {
hrs,
mins,
}
},
recipeTotalTime(prepTime, cookTime) {
let { hrs, mins } = this.getTotalTime(prepTime, cookTime)
return hrs ? `${hrs}h ${mins}m` : `${mins}m`
},
recipeDuration(prepTime, cookTime) {
let { hrs, mins } = this.getTotalTime(prepTime, cookTime)
return `${hrs}${mins}`
},
onScroll(args) {
args.scrollOffset
? (this.viewIsScrolled = true)
: (this.viewIsScrolled = false)
},
// SearchBar
searchBarLoaded() {
application.android.on(
application.AndroidApplication.activityBackPressedEvent,
this.backEvent
)
},
backEvent(args) {
if (this.showSearch) {
args.cancel = true
this.closeSearch()
}
this.removeBackEvent()
},
removeBackEvent() {
application.android.off(
application.AndroidApplication.activityBackPressedEvent,
this.backEvent
)
},
closeSearch() {
this.searchQuery = ""
this.showSearch = false
utils.ad.dismissSoftInput()
},
FabTapped() {
alert("fab tapped")
},
addRecipe() {
this.releaseGlobalBackEvent()
this.$navigateTo(EditRecipe, {
transition: {
name: "slide",
@ -299,11 +375,11 @@ export default {
},
props: {
viewIsScrolled: this.viewIsScrolled,
selectedCategory: this.selectedCategory,
},
})
},
viewRecipe({ item }) {
// console.log(item)
this.$navigateTo(ViewRecipe, {
transition: {
name: "fade",
@ -311,7 +387,9 @@ export default {
curve: "easeIn",
},
props: {
recipe: item,
recipeIndex: this.recipes.indexOf(item),
hijackGlobalBackEvent: this.hijackGlobalBackEvent,
releaseGlobalBackEvent: this.releaseGlobalBackEvent,
},
})
},

View file

@ -1,5 +1,5 @@
<template>
<Page>
<Page @loaded="setCurrentComponent">
<ActionBar :flat="viewIsScrolled ? false : true">
<!-- Settings Actionbar -->
<GridLayout rows="*" columns="auto, *" class="actionBarContainer">
@ -10,7 +10,7 @@
@tap="showDrawer"
col="0"
/>
<Label class="title orkm" :text="title" col="1" />
<Label class="title orkm" text="Settings" col="1" />
</GridLayout>
</ActionBar>
<ScrollView scrollBarIndicatorVisible="false">
@ -22,6 +22,7 @@
class="option"
@tap="selectThemes"
>
<!-- @tap="selectThemes" -->
<Label verticalAlignment="center" class="bx" :text="icon.theme" />
<StackLayout>
<Label text="Theme" class="option-title" />
@ -57,16 +58,24 @@
</template>
<script>
import { Menu } from "nativescript-menu"
import * as permissions from "nativescript-permissions"
import * as application from "tns-core-modules/application"
import { getString, setString } from "application-settings"
import Theme from "@nativescript/theme"
import ActionDialog from "./modal/ActionDialog.vue"
import ConfirmDialog from "./modal/ConfirmDialog.vue"
import { mapState, mapActions } from "vuex"
export default {
props: ["highlight", "viewIsScrolled", "showDrawer", "title"],
props: [
"highlight",
"viewIsScrolled",
"showDrawer",
"restartApp",
"hijackGlobalBackEvent",
"releaseGlobalBackEvent",
],
data() {
return {
interface: {
@ -98,23 +107,44 @@ export default {
}
},
computed: {
...mapState(["icon"]),
...mapState(["icon", "currentComponent"]),
},
methods: {
setCurrentComponent() {
this.$store.dispatch("setCurrentComponent", "Settings")
this.releaseGlobalBackEvent()
},
showDialog(args) {
this.highlight(args)
this.$showModal(ActionDialog)
},
selectThemes(args) {
this.highlight(args)
let btn = args.object
Menu.popup({
view: btn,
actions: this.themesArray,
this.$showModal(ActionDialog, {
props: {
title: "Theme",
list: ["Light", "Dark"],
height: "96",
},
}).then((action) => {
if (action && action !== "Cancel" && this.themeName !== action) {
this.$showModal(ConfirmDialog, {
props: {
title: "App Reload Required",
description:
"The app needs to be reloaded for the theme change to take effect.",
cancelButtonText: "CANCEL",
okButtonText: "RELOAD",
},
}).then((result) => {
if (result) {
this.interface.theme.subTitle = this.themeName = action
setString("application-theme", action)
setTimeout((e) => this.restartApp(), 250)
}
})
}
})
.then((action) => {
this.interface.theme.subTitle = this.themeName = action.title
console.log(this.themeName)
setString("application-theme", action.title)
Theme.toggleMode()
})
.catch(console.log)
},
selectBackupDir(args) {
this.highlight(args)

View file

@ -1,41 +1,48 @@
<template>
<Page>
<ActionBar margin="0" flat="true">
<Page @loaded="setCurrentComponent">
<ActionBar height="128" margin="0" flat="true">
<GridLayout
rows="*"
columns="auto, *, auto,auto"
rows="64, 64"
columns="auto, *, auto,auto, auto"
class="actionBarContainer"
>
<Label
row="0"
col="0"
class="bx leftAction"
:text="icon.back"
automationText="Back"
@tap="navigateBack"
verticalAlignment="top"
@tap="$navigateBack()"
/>
<Label
class="title orkm"
:text="recipe.title"
lineHeight="4"
<ScrollView
row="1"
col="1"
textWrap="true"
verticalAlignment="bottom"
/>
<Label
col="2"
class="bx"
:text="icon.share"
@tap=""
verticalAlignment="top"
/>
colSpan="3"
orientation="horizontal"
scrollBarIndicatorVisible="false"
>
<Label
class="title orkm"
:text="recipe.title"
verticalAlignment="bottom"
/>
</ScrollView>
<Label row="0" col="2" class="bx" :text="icon.share" @tap="" />
<Label
row="0"
col="3"
class="bx"
:class="{ 'view-favorited': recipe.isFavorite }"
:text="recipe.isFavorite ? icon.heart : icon.heartOutline"
@tap="toggleFavorite"
verticalAlignment="top"
/>
<Label
row="0"
col="4"
class="bx"
:class="{ 'view-favorited': !recipe.tried }"
:text="recipe.tried ? icon.musttryOutline : icon.musttry"
@tap="toggleMustTry"
/>
</GridLayout>
</ActionBar>
@ -43,7 +50,7 @@
<TabView androidElevation="0" width="100%" height="100%">
<TabViewItem title="Overview">
<ScrollView scrollBarIndicatorVisible="false">
<StackLayout class="">
<StackLayout>
<StackLayout
width="100%"
:height="screenWidth"
@ -62,13 +69,13 @@
horizontalAlignment="center"
class="bx"
fontSize="160"
:text="icon.dish"
:text="icon.image"
/>
</StackLayout>
<StackLayout margin="16 16 128">
<StackLayout margin="16 16 144">
<Label class="view-cat orkm" :text="recipe.category" />
<Label
class="view-title p-b-8 orkm"
class="view-title orkm"
:text="recipe.title"
textWrap="true"
/>
@ -88,9 +95,9 @@
</StackLayout>
</ScrollView>
</TabViewItem>
<TabViewItem title="Ingredients" v-if="recipe.ingredients[0].item">
<TabViewItem title="Ingredients" v-if="recipe.ingredients.length">
<ScrollView scrollBarIndicatorVisible="false">
<StackLayout padding="16 16 128">
<StackLayout padding="16 16 124">
<AbsoluteLayout class="inputField">
<TextField
width="50%"
@ -101,7 +108,7 @@
</AbsoluteLayout>
<StackLayout margin="24 0 8 0">
<Label
class="view-title p-b-8 orkm"
class="view-title orkm"
:text="
`Ingredients for ${portionScale}${
portionScale > 1
@ -128,9 +135,9 @@
</StackLayout>
</ScrollView>
</TabViewItem>
<TabViewItem title="Instructions" v-if="recipe.instructions[0].length">
<TabViewItem title="Instructions" v-if="recipe.instructions.length">
<ScrollView scrollBarIndicatorVisible="false">
<StackLayout padding="16 16 128">
<StackLayout padding="32 16 132">
<GridLayout
columns="auto ,*"
v-for="(instruction, index) in recipe.instructions"
@ -158,9 +165,9 @@
</StackLayout>
</ScrollView>
</TabViewItem>
<TabViewItem title="Notes" v-if="recipe.notes[0].length">
<TabViewItem title="Notes" v-if="recipe.notes.length">
<ScrollView scrollBarIndicatorVisible="false">
<StackLayout padding="16 16 128">
<StackLayout padding="32 16 132">
<GridLayout
columns="auto ,*"
v-for="(note, index) in recipe.notes"
@ -184,9 +191,9 @@
</StackLayout>
</ScrollView>
</TabViewItem>
<TabViewItem title="References" v-if="recipe.references[0].length">
<TabViewItem title="References" v-if="recipe.references.length">
<ScrollView scrollBarIndicatorVisible="false">
<StackLayout padding="16 16 128">
<StackLayout padding="32 16 132">
<GridLayout
columns="auto ,*"
v-for="(reference, index) in recipe.references"
@ -214,6 +221,7 @@
</TabView>
<GridLayout id="btnFabContainer" rows="*,88" columns="*,88">
<Label
v-if="!busy"
row="1"
col="1"
class="bx btnFab"
@ -221,6 +229,7 @@
androidElevation="8"
@tap="editRecipe"
/>
<ActivityIndicator v-else row="1" col="1" :busy="busy" />
</GridLayout>
</AbsoluteLayout>
</Page>
@ -229,18 +238,26 @@
<script>
import { screen } from "tns-core-modules/platform"
import * as utils from "tns-core-modules/utils/utils"
import { getNumber, setNumber } from "application-settings"
import * as Toast from "nativescript-toast"
import EditRecipe from "./EditRecipe.vue"
import { mapState, mapActions } from "vuex"
export default {
props: ["recipe"],
props: ["recipeIndex", "hijackGlobalBackEvent", "releaseGlobalBackEvent"],
data() {
return {
busy: false,
portionScale: 1,
}
},
computed: {
...mapState(["icon", "recipes"]),
recipe() {
return this.recipes[this.recipeIndex]
},
screenWidth() {
return screen.mainScreen.widthDIPs
},
@ -254,18 +271,33 @@ export default {
roundedQuantity(quantity, unit) {
return Math.round(quantity * this.isPortionScalePositive * 100) / 100
},
// indexChange(args) {
// let newIndex = args.value
// console.log("Current tab index: " + newIndex)
// },
navigateBack() {
this.$navigateBack()
},
editRecipe() {
alert("edit recipe")
this.busy = true
this.$navigateTo(EditRecipe, {
transition: {
name: "slide",
duration: 250,
curve: "easeIn",
},
props: {
recipeIndex: this.recipeIndex,
},
// backstackVisible: false,
})
},
toggleFavorite() {
this.$store.dispatch("toggleFavorite", this.recipes.indexOf(this.recipe))
this.recipe.isFavorite
? Toast.makeText("Removed from Favorites").show()
: Toast.makeText("Added to Favorites").show()
this.$store.dispatch("toggleFavorite", this.recipeIndex)
},
toggleMustTry() {
this.recipe.tried
? Toast.makeText("Added to Must-Try").show()
: Toast.makeText("Removed from Must-Try").show()
this.$store.dispatch("toggleMustTry", this.recipeIndex)
},
getTime(time) {
let t = time.split(":")
@ -276,14 +308,13 @@ export default {
openURL(args, url) {
utils.openUrl(url)
},
setCurrentComponent() {
this.releaseGlobalBackEvent()
this.busy = false
setTimeout((e) => {
this.$store.dispatch("setCurrentComponent", "ViewRecipe")
}, 500)
},
},
}
</script>
<style lang="scss" scoped>
ActionBar {
height: 128;
}
.actionBarContainer .bx {
margin-top: 4;
}
</style>

View file

@ -0,0 +1,64 @@
<template>
<Page>
<StackLayout class="dialogContainer">
<Label class="dialogTitle orkm" :text="title" />
<StackLayout class="actionsContainer">
<ListView
width="100%"
:height="height"
for="item in list"
@itemTap="tapAction"
separatorColor="transparent"
>
<v-template>
<StackLayout class="actionItem">
<Label :text="item" />
</StackLayout>
</v-template>
</ListView>
</StackLayout>
<GridLayout rows="auto" columns="auto, *, auto">
<Label
v-if="action"
col="0"
class="cancel orkm pull-left"
:text="action"
@tap="$modal.close(action)"
/>
<Label
col="2"
class="cancel orkm pull-right"
text="CANCEL"
@tap="$modal.close(false)"
/>
</GridLayout>
</StackLayout>
</Page>
</template>
<script>
export default {
props: ["title", "list", "height", "action"],
methods: {
tapAction({ item }) {
this.$modal.close(item)
},
},
}
</script>
<style lang="scss" scoped>
.dialogTitle {
padding: 24 24 12;
font-size: 20;
}
.actionItem {
width: 100%;
font-size: 16;
padding: 8 20;
}
.cancel {
padding: 24;
font-size: 12;
color: #ff7043;
}
</style>

View file

@ -0,0 +1,45 @@
<template>
<Page>
<StackLayout class="dialogContainer">
<Label class="dialogTitle orkm" :text="title" />
<Label class="dialogDescription" :text="description" textWrap="true" />
<StackLayout
orientation="horizontal"
class="actionsContainer"
horizontalAlignment="right"
>
<Label
class="action orkm pull-right"
:text="cancelButtonText"
@tap="$modal.close(false)"
/>
<Label
class="action orkm pull-right"
:text="okButtonText"
@tap="$modal.close(true)"
/>
</StackLayout>
</StackLayout>
</Page>
</template>
<script>
export default {
props: ["title", "description", "cancelButtonText", "okButtonText"],
}
</script>
<style lang="scss" scoped>
.dialogTitle {
padding: 24 24 12;
font-size: 20;
}
.dialogDescription {
font-size: 16;
padding: 0 24 16;
}
.action {
padding: 24 24 24 8;
font-size: 12;
color: #ff7043;
}
</style>

View file

@ -0,0 +1,49 @@
<template>
<Page>
<StackLayout class="dialogContainer">
<Label class="dialogTitle orkm" :text="title" />
<TextField
width="100%"
:hint="hint"
v-model="category"
autocapitalizationType="words"
/>
<StackLayout orientation="horizontal" horizontalAlignment="right">
<Label class="action orkm" text="CANCEL" @tap="$modal.close(false)" />
<Label
class="action orkm"
:text="action"
@tap="$modal.close(category)"
/>
</StackLayout>
</StackLayout>
</Page>
</template>
<script>
export default {
props: ["title", "hint", "action"],
data() {
return {
category: null,
}
},
}
</script>
<style lang="scss" scoped>
TextField {
margin: 0 24 16;
}
.dialogContainer {
padding: 0 24;
}
.dialogTitle {
padding: 24 0 12;
font-size: 20;
}
.action {
padding: 24 0 24 32;
font-size: 12;
color: #ff7043;
}
</style>

View file

@ -1,55 +1,25 @@
// import VueDevtools from "nativescript-vue-devtools"
import Vue from "nativescript-vue"
import App from "./components/App"
import RadListView from "nativescript-ui-listview/vue"
// Vue.registerElement(
// "RadListView",
// () => require("nativescript-ui-listview/vue").RadListView
// )
Vue.use(RadListView)
// Vue.use(VueDevtools)
// Vue.registerElement(
// "CheckBox",
// () => require("@nstudio/nativescript-checkbox").CheckBox,
// {
// model: {
// prop: "checked",
// event: "checkedChange",
// },
// }
// )
import DateTimePicker from "nativescript-datetimepicker/vue"
Vue.use(DateTimePicker)
// import VueDevtools from 'nativescript-vue-devtools'
// import { TNSFontIcon, fonticon } from 'nativescript-fonticon'
// TNSFontIcon.debug = true
// TNSFontIcon.paths = {
// // bx: './assets/boxicons.css',
// fa: './assets/fontawesome.css',
// }
// TNSFontIcon.loadCss()
// Vue.filter('fonticon', fonticon)
if (TNS_ENV !== "production") {
// Vue.use(VueDevtools)
}
import store from "./store"
// Prints Vue logs when --env.production is *NOT* set while building
Vue.config.silent = TNS_ENV === "production"
import RadListView from "nativescript-ui-listview/vue"
Vue.use(RadListView)
import DateTimePicker from "nativescript-datetimepicker/vue"
Vue.use(DateTimePicker)
Vue.registerElement(
"RadSideDrawer",
() => require("nativescript-ui-sidedrawer").RadSideDrawer
)
if (TNS_ENV !== "production") {
// Vue.use(VueDevtools)
}
// Prints Vue logs when --env.production is *NOT* set while building
Vue.config.silent = TNS_ENV === "production"
new Vue({
store,
render: (h) => h("frame", [h(App)]),

View file

@ -6,188 +6,178 @@ Vue.use(Vuex)
export default new Vuex.Store({
state: {
recipes: [
{
imageSrc: null,
title: "Mediterranean Salad",
category: "Salads",
prepTime: "00:10",
cookTime: "00:20",
portionSize: 1,
ingredients: [
{
item: "Cucumbers, Seeded And Sliced",
quantity: 3,
unit: null,
},
{
item: "Crumbled Feta Cheese",
quantity: 1.5,
unit: "cup",
},
{
item: "Black Olives, Pitted And Sliced",
quantity: 1,
unit: "cup",
},
{
item: "Diced Roma Tomatoes",
quantity: 3,
unit: "cup",
},
{
item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
quantity: 0.3,
unit: "cup",
},
{
item: "Onion, Sliced",
quantity: 1.5,
unit: null,
},
{
item: "Cucumbers, Seeded And Sliced",
quantity: 3,
unit: null,
},
{
item: "Crumbled Feta Cheese",
quantity: 1.5,
unit: "cup",
},
{
item: "Black Olives, Pitted And Sliced",
quantity: 1,
unit: "cup",
},
{
item: "Diced Roma Tomatoes",
quantity: 3,
unit: "cup",
},
{
item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
quantity: 0.3,
unit: "cup",
},
{
item: "Onion, Sliced",
quantity: 1.5,
unit: null,
},
{
item: "Cucumbers, Seeded And Sliced",
quantity: 3,
unit: null,
},
{
item: "Crumbled Feta Cheese",
quantity: 1.5,
unit: "cup",
},
{
item: "Black Olives, Pitted And Sliced",
quantity: 1,
unit: "cup",
},
{
item: "Diced Roma Tomatoes",
quantity: 3,
unit: "cup",
},
{
item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
quantity: 0.3,
unit: "cup",
},
{
item: "Onion, Sliced",
quantity: 1.5,
unit: null,
},
],
instructions: [
"In a large salad bowl, toss together the cucumbers, feta cheese, olives, roma tomatoes, sun-dried tomatoes, 2 tablespoons reserved sun-dried tomato oil, and red onion.",
"Chill until serving.",
"In a large salad bowl, toss together the cucumbers, feta cheese, olives, roma tomatoes, sun-dried tomatoes, 2 tablespoons reserved sun-dried tomato oil, and red onion. In a large salad bowl, toss together the cucumbers, feta cheese, olives, roma tomatoes, sun-dried tomatoes, 2 tablespoons reserved sun-dried tomato oil, and red onion.",
"Chill until serving.",
"Chill until serving.",
"In a large salad bowl, toss together the cucumbers, feta cheese, olives, roma tomatoes, sun-dried tomatoes, 2 tablespoons reserved sun-dried tomato oil, and red onion.",
"Chill until serving.",
"Chill until serving.",
"Chill until serving.",
"Chill until serving.",
"Chill until serving.",
],
notes: [
"Per Serving: 130.6 calories; protein 5.5g 11% DV; carbohydrates 9.3g 3% DV; fat 8.8g 14% DV; cholesterol 25mg 8% DV; sodium 486.4mg 20% DV.",
"Per Serving: 130.6 calories; protein 5.5g 11% DV; carbohydrates 9.3g 3% DV; fat 8.8g 14% DV; cholesterol 25mg 8% DV; sodium 486.4mg 20% DV.",
"Per Serving: 130.6 calories; protein 5.5g 11% DV; carbohydrates 9.3g 3% DV; fat 8.8g 14% DV; cholesterol 25mg 8% DV; sodium 486.4mg 20% DV.",
],
references: [
"https://www.allrecipes.com/recipe/14403/mediterranean-greek-salad/",
"https://www.allrecipes.com/recipe/14403/mediterranean-greek-salad/",
"https://www.allrecipes.com/recipe/14403/mediterranean-greek-salad/",
"https://www.allrecipes.com/recipe/14403/mediterranean-greek-salad/",
],
isFavorite: true,
},
{
imageSrc: null,
title: "Fresh Tomato Sauce",
category: "Sauces",
prepTime: "00:20",
cookTime: "00:25",
portionSize: 1,
ingredients: [
{
item: null,
quantity: null,
unit: null,
},
],
instructions: [""],
notes: [""],
references: [""],
isFavorite: true,
},
{
imageSrc: null,
title: "Creamy Mushroom Herb Pasta",
category: "Lunch",
prepTime: "00:45",
cookTime: "00:25",
portionSize: 1,
ingredients: [
{
item: null,
quantity: null,
unit: null,
},
],
instructions: [""],
notes: [""],
references: [""],
isFavorite: false,
},
{
imageSrc: null,
title: "Grilled Cheese Sandwich",
category: "Lunch",
prepTime: "00:20",
cookTime: "00:10",
portionSize: 1,
ingredients: [
{
item: null,
quantity: null,
unit: null,
},
],
instructions: [""],
notes: [""],
references: [""],
isFavorite: false,
},
// {
// imageSrc: null,
// title: "Mediterranean Salad",
// category: "Salads",
// prepTime: "12:25",
// cookTime: "00:30",
// portionSize: 1,
// ingredients: [
// {
// item: "Cucumbers, Seeded And Sliced",
// quantity: 3,
// unit: "unit",
// },
// {
// item: "Crumbled Feta Cheese",
// quantity: 1.5,
// unit: "cup",
// },
// {
// item: "Black Olives, Pitted And Sliced",
// quantity: 1,
// unit: "cup",
// },
// {
// item: "Diced Roma Tomatoes",
// quantity: 3,
// unit: "cup",
// },
// {
// item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
// quantity: 0.3,
// unit: "cup",
// },
// {
// item: "Onion, Sliced",
// quantity: 1.5,
// unit: "unit",
// },
// {
// item: "Cucumbers, Seeded And Sliced",
// quantity: 3,
// unit: "unit",
// },
// {
// item: "Crumbled Feta Cheese",
// quantity: 1.5,
// unit: "cup",
// },
// {
// item: "Black Olives, Pitted And Sliced",
// quantity: 1,
// unit: "cup",
// },
// {
// item: "Diced Roma Tomatoes",
// quantity: 3,
// unit: "cup",
// },
// {
// item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
// quantity: 0.3,
// unit: "cup",
// },
// {
// item: "Onion, Sliced",
// quantity: 1.5,
// unit: "unit",
// },
// {
// item: "Cucumbers, Seeded And Sliced",
// quantity: 3,
// unit: "unit",
// },
// {
// item: "Crumbled Feta Cheese",
// quantity: 1.5,
// unit: "cup",
// },
// {
// item: "Black Olives, Pitted And Sliced",
// quantity: 1,
// unit: "cup",
// },
// {
// item: "Diced Roma Tomatoes",
// quantity: 3,
// unit: "cup",
// },
// {
// item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
// quantity: 0.3,
// unit: "cup",
// },
// {
// item: "Onion, Sliced",
// quantity: 1.5,
// unit: "unit",
// },
// ],
// instructions: [
// "In a large salad bowl, toss together the cucumbers, feta cheese, olives, roma tomatoes, sun-dried tomatoes, 2 tablespoons reserved sun-dried tomato oil, and red onion.",
// "Chill until serving.",
// "In a large salad bowl, toss together the cucumbers, feta cheese, olives, roma tomatoes, sun-dried tomatoes, 2 tablespoons reserved sun-dried tomato oil, and red onion. In a large salad bowl, toss together the cucumbers, feta cheese, olives, roma tomatoes, sun-dried tomatoes, 2 tablespoons reserved sun-dried tomato oil, and red onion.",
// "Chill until serving.",
// "Chill until serving.",
// "In a large salad bowl, toss together the cucumbers, feta cheese, olives, roma tomatoes, sun-dried tomatoes, 2 tablespoons reserved sun-dried tomato oil, and red onion.",
// "Chill until serving.",
// "Chill until serving.",
// "Chill until serving.",
// "Chill until serving.",
// "Chill until serving.",
// ],
// notes: [
// "Per Serving: 130.6 calories; protein 5.5g 11% DV; carbohydrates 9.3g 3% DV; fat 8.8g 14% DV; cholesterol 25mg 8% DV; sodium 486.4mg 20% DV.",
// "Per Serving: 130.6 calories; protein 5.5g 11% DV; carbohydrates 9.3g 3% DV; fat 8.8g 14% DV; cholesterol 25mg 8% DV; sodium 486.4mg 20% DV.",
// "Per Serving: 130.6 calories; protein 5.5g 11% DV; carbohydrates 9.3g 3% DV; fat 8.8g 14% DV; cholesterol 25mg 8% DV; sodium 486.4mg 20% DV.",
// ],
// references: [
// "https://www.allrecipes.com/recipe/14403/mediterranean-greek-salad/",
// "https://www.allrecipes.com/recipe/14403/mediterranean-greek-salad/",
// "https://www.allrecipes.com/recipe/14403/mediterranean-greek-salad/",
// "https://www.allrecipes.com/recipe/14403/mediterranean-greek-salad/",
// ],
// isFavorite: true,
// tried: false,
// lastModified: "2020-10-18T17:37:51.798Z",
// },
// {
// imageSrc: null,
// title: "Fresh Tomato Sauce",
// category: "Sauces",
// prepTime: "00:45",
// cookTime: "00:35",
// portionSize: 1,
// ingredients: [],
// instructions: [],
// notes: [],
// references: [],
// isFavorite: true,
// tried: true,
// lastModified: "2020-10-15T17:37:51.798Z",
// },
// {
// imageSrc: null,
// title: "Creamy Mushroom Herb Pasta",
// category: "Lunch",
// prepTime: "00:10",
// cookTime: "00:15",
// portionSize: 1,
// ingredients: [],
// instructions: [],
// notes: [],
// references: [],
// isFavorite: false,
// tried: false,
// lastModified: "2020-10-12T17:37:51.798Z",
// },
// {
// imageSrc: null,
// title: "Grilled Cheese Sandwich",
// category: "Lunch",
// prepTime: "00:50",
// cookTime: "00:12",
// portionSize: 1,
// ingredients: [],
// instructions: [],
// notes: [],
// references: [],
// isFavorite: false,
// tried: true,
// lastModified: "2020-10-03T17:37:51.798Z",
// },
],
viewIsScrolled: false,
icon: {
@ -202,7 +192,7 @@ export default new Vuex.Store({
sort: "\ueb2b",
plus: "\ueb89",
close: "\uec4e",
dish: "\uea71",
image: "\ueae9",
back: "\ue988",
save: "\uee48",
camera: "\uecc2",
@ -216,22 +206,127 @@ export default new Vuex.Store({
file: "\ued60",
user: "\uee8e",
trash: "\uee83",
donate: "\ued41",
musttry: "\uec96",
musttryOutline: "\ue9bb",
},
units: [
"unit",
"tsp",
"Tbsp",
"oz",
"cup",
"pt",
"qt",
"lb",
"gal",
"ml",
"L",
"mg",
"g",
"kg",
"mm",
"cm",
"m",
"in",
"°C",
"°F",
],
categories: [
"Appetizers",
"BBQ",
"Beverages",
"Breads",
"Breakfast",
"Desserts",
"Dinner",
"Drinks",
"Healthy",
"Lunch",
"Main dishes",
"Meat",
"Noodles",
"Pasta",
"Poultry",
"Rice",
"Salads",
"Sauces",
"Seafood",
"Side dishes",
"Snacks",
"Soups",
"Undefined",
"Vegan",
"Vegetarian",
],
currentComponent: "EnRecipes",
},
mutations: {
addRecipe(state, recipe) {
state.recipes.push(recipe)
},
addCategory(state, category) {
let a = state.categories.filter((e) => e === category).length
if (a == 0) {
state.categories.push(category)
state.categories.sort()
}
},
overwriteRecipe(state, { index, recipe }) {
Object.assign(state.recipes[index], recipe)
},
deleteRecipe(state, index) {
state.recipes.splice(index, 1)
},
toggleFavorite(state, index) {
state.recipes[index].isFavorite = !state.recipes[index].isFavorite
},
toggleMustTry(state, index) {
state.recipes[index].tried = !state.recipes[index].tried
},
setCurrentComponent(state, comp) {
state.currentComponent = comp
},
renameCategory(state, { current, updated }) {
let a = state.categories.filter((e) => e === updated).length
if (a == 0) {
// add updated category to categories
state.categories.splice(state.categories.indexOf(current), 1)
state.categories.push(updated)
state.categories.sort()
// rename all occurences
state.recipes.forEach((e, i) => {
if (e.category == current) {
state.recipes[i].category = updated
}
})
}
},
},
actions: {
addRecipe({ commit }, recipe) {
commit("addRecipe", recipe)
},
addCategory({ commit }, category) {
commit("addCategory", category)
},
overwriteRecipe({ commit }, updatedRecipe) {
commit("overwriteRecipe", updatedRecipe)
},
deleteRecipe({ commit }, index) {
commit("deleteRecipe", index)
},
toggleFavorite({ commit }, index) {
commit("toggleFavorite", index)
},
toggleMustTry({ commit }, index) {
commit("toggleMustTry", index)
},
setCurrentComponent({ commit }, comp) {
commit("setCurrentComponent", comp)
},
renameCategory({ commit }, category) {
commit("renameCategory", category)
},
},
})

1022
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -19,20 +19,15 @@
},
"dependencies": {
"@nativescript/theme": "^2.2.1",
"@nstudio/nativescript-checkbox": "^1.0.0",
"@vue/devtools": "^5.3.3",
"nativescript-camera": "^4.5.0",
"nativescript-couchbase-plugin": "^0.9.6",
"nativescript-datetimepicker": "^1.2.3",
"nativescript-fonticon": "^2.0.2",
"nativescript-mediafilepicker": "^4.0.0",
"nativescript-menu": "^1.1.6",
"nativescript-permissions": "^1.3.9",
"nativescript-socketio": "^3.3.1",
"nativescript-toasty": "^3.0.0-alpha.2",
"nativescript-toast": "^2.0.0",
"nativescript-ui-listview": "^8.2.0",
"nativescript-ui-sidedrawer": "^8.0.1",
"nativescript-vue": "^2.6.1",
"nativescript-vue-devtools": "^1.4.0",
"tns-core-modules": "^6.5.1",
"vuex": "^3.3.0"
},