before ns migrate
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 17
|
minSdkVersion 23
|
||||||
generatedDensities = []
|
generatedDensities = []
|
||||||
}
|
}
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
|
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 550 B |
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 461 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 664 B |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 472 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 780 B |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 5.6 KiB |
|
@ -1,10 +1,11 @@
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:gravity="fill">
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:gravity="fill">
|
||||||
<item>
|
<item>
|
||||||
<shape android:shape="rectangle">
|
<shape android:shape="rectangle">
|
||||||
<solid android:color="@android:color/white" />
|
<!-- <solid android:color="@android:color/white" /> -->
|
||||||
</shape>
|
<solid android:color="#ff7043" />
|
||||||
</item>
|
</shape>
|
||||||
<item>
|
</item>
|
||||||
<bitmap android:gravity="center" android:src="@drawable/logo" />
|
<item android:left="64dp" android:right="64dp">
|
||||||
</item>
|
<bitmap android:gravity="center" android:src="@drawable/logo" />
|
||||||
|
</item>
|
||||||
</layer-list>
|
</layer-list>
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 680 B |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 861 B |
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 10 KiB |
|
@ -1,4 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<color name="ns_accent">#ff7043</color>
|
<color name="ns_primary">
|
||||||
|
#FFFFFF
|
||||||
|
</color>
|
||||||
|
<color name="ns_primaryDark">
|
||||||
|
#ff7043
|
||||||
|
</color>
|
||||||
|
<color name="ns_accent">
|
||||||
|
#ff7043
|
||||||
|
</color>
|
||||||
</resources>
|
</resources>
|
|
@ -1,23 +1,29 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<!-- Application theme -->
|
||||||
<!-- Application theme -->
|
<style name="AppTheme" parent="AppThemeBase">
|
||||||
<style name="AppTheme" parent="AppThemeBase">
|
<item name="android:datePickerStyle">
|
||||||
<item name="android:datePickerStyle">@style/SpinnerDatePicker</item>
|
@style/SpinnerDatePicker
|
||||||
<item name="android:timePickerStyle">@style/SpinnerTimePicker</item>
|
</item>
|
||||||
</style>
|
<item name="android:timePickerStyle">
|
||||||
|
@style/SpinnerTimePicker
|
||||||
<!-- Default style for DatePicker - in spinner mode -->
|
</item>
|
||||||
<style name="SpinnerDatePicker" parent="android:Widget.Material.Light.DatePicker">
|
</style>
|
||||||
<item name="android:datePickerMode">spinner</item>
|
<!-- Default style for DatePicker - in spinner mode -->
|
||||||
</style>
|
<style name="SpinnerDatePicker" parent="android:Widget.Material.Light.DatePicker">
|
||||||
|
<item name="android:datePickerMode">
|
||||||
<!-- Default style for TimePicker - in spinner mode -->
|
spinner
|
||||||
<style name="SpinnerTimePicker" parent="android:Widget.Material.Light.TimePicker">
|
</item>
|
||||||
<item name="android:timePickerMode">spinner</item>
|
</style>
|
||||||
</style>
|
<!-- Default style for TimePicker - in spinner mode -->
|
||||||
|
<style name="SpinnerTimePicker" parent="android:Widget.Material.Light.TimePicker">
|
||||||
<style name="NativeScriptToolbarStyle" parent="NativeScriptToolbarStyleBase">
|
<item name="android:timePickerMode">
|
||||||
<item name="android:elevation">4dp</item>
|
spinner
|
||||||
</style>
|
</item>
|
||||||
|
</style>
|
||||||
|
<style name="NativeScriptToolbarStyle" parent="NativeScriptToolbarStyleBase">
|
||||||
|
<item name="android:elevation">
|
||||||
|
0dp
|
||||||
|
</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
|
@ -9,7 +9,4 @@
|
||||||
<color name="ns_accent">
|
<color name="ns_accent">
|
||||||
#ff7043
|
#ff7043
|
||||||
</color>
|
</color>
|
||||||
<color name="ns_blue">
|
|
||||||
#272734
|
|
||||||
</color>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">NativeScript-Vue Application</string>
|
<string name="app_name">EnRecipes</string>
|
||||||
<string name="title_activity_kimera">NativeScript-Vue Application</string>
|
<string name="title_activity_kimera">EnRecipes</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<item name="android:windowBackground">@drawable/splash_screen</item>
|
<item name="android:windowBackground">@drawable/splash_screen</item>
|
||||||
|
|
||||||
<item name="android:windowActionBarOverlay">true</item>
|
<item name="android:windowActionBarOverlay">true</item>
|
||||||
<item name="android:windowTranslucentStatus">true</item>
|
<item name="android:windowTranslucentStatus">false</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="LaunchScreenTheme" parent="LaunchScreenThemeBase">
|
<style name="LaunchScreenTheme" parent="LaunchScreenThemeBase">
|
||||||
|
|
63
app/app.scss
|
@ -37,7 +37,8 @@ Page {
|
||||||
.ns-light {
|
.ns-light {
|
||||||
Page,
|
Page,
|
||||||
ActionBar,
|
ActionBar,
|
||||||
SearchBar {
|
SearchBar,
|
||||||
|
TabView {
|
||||||
background: $grayL4;
|
background: $grayL4;
|
||||||
color: $grayD4;
|
color: $grayD4;
|
||||||
}
|
}
|
||||||
|
@ -58,8 +59,10 @@ Page {
|
||||||
.fieldLabel {
|
.fieldLabel {
|
||||||
background: $grayL4;
|
background: $grayL4;
|
||||||
}
|
}
|
||||||
.recipe-li,
|
|
||||||
.option-highlight {
|
.option-highlight {
|
||||||
|
background: $grayL2;
|
||||||
|
}
|
||||||
|
.recipe-li {
|
||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
.sd-item,
|
.sd-item,
|
||||||
|
@ -102,7 +105,8 @@ Page {
|
||||||
.ns-dark {
|
.ns-dark {
|
||||||
Page,
|
Page,
|
||||||
ActionBar,
|
ActionBar,
|
||||||
SearchBar {
|
SearchBar,
|
||||||
|
TabView {
|
||||||
background: $grayD4;
|
background: $grayD4;
|
||||||
color: $grayL4;
|
color: $grayL4;
|
||||||
}
|
}
|
||||||
|
@ -169,9 +173,10 @@ Page {
|
||||||
TextField,
|
TextField,
|
||||||
TextView,
|
TextView,
|
||||||
TimePickerField {
|
TimePickerField {
|
||||||
|
width: 100%;
|
||||||
border-width: 1;
|
border-width: 1;
|
||||||
font-size: 15;
|
font-size: 14;
|
||||||
padding: 16;
|
padding: 14;
|
||||||
margin: 8 0 0 0;
|
margin: 8 0 0 0;
|
||||||
border-radius: 4;
|
border-radius: 4;
|
||||||
placeholder-color: $gray;
|
placeholder-color: $gray;
|
||||||
|
@ -195,7 +200,8 @@ ActionBar {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
height: 64;
|
height: 64;
|
||||||
.bx {
|
.bx {
|
||||||
padding: 16;
|
padding: 16 12;
|
||||||
|
vertical-alignment: center;
|
||||||
}
|
}
|
||||||
.leftAction {
|
.leftAction {
|
||||||
padding: 16 16 16 4;
|
padding: 16 16 16 4;
|
||||||
|
@ -207,8 +213,8 @@ ActionBar {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
SearchBar {
|
SearchBar {
|
||||||
|
width: 100%;
|
||||||
font-size: 16;
|
font-size: 16;
|
||||||
margin-top: 4;
|
|
||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
padding-left: 8;
|
padding-left: 8;
|
||||||
|
@ -219,15 +225,25 @@ SearchBar {
|
||||||
// Side Drawer
|
// Side Drawer
|
||||||
.sd-item {
|
.sd-item {
|
||||||
border-radius: 4;
|
border-radius: 4;
|
||||||
padding: 12 16;
|
padding: 0 16;
|
||||||
font-size: 14;
|
height: 48;
|
||||||
|
font-size: 16;
|
||||||
|
vertical-alignment: center;
|
||||||
|
// prettier-ignore
|
||||||
|
.bx, Label {
|
||||||
|
vertical-alignment: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.sd-group-header {
|
.sd-group-header {
|
||||||
padding: 12;
|
width: 100%;
|
||||||
|
padding: 8 8 16;
|
||||||
font-size: 12;
|
font-size: 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Home
|
// Home
|
||||||
|
RadListView {
|
||||||
|
margin-bottom: 128;
|
||||||
|
}
|
||||||
.recipe-li {
|
.recipe-li {
|
||||||
margin: 8 16;
|
margin: 8 16;
|
||||||
border-radius: 6;
|
border-radius: 6;
|
||||||
|
@ -235,6 +251,7 @@ SearchBar {
|
||||||
margin: 4 0;
|
margin: 4 0;
|
||||||
}
|
}
|
||||||
.recipe-cat {
|
.recipe-cat {
|
||||||
|
font-size: 12;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
@ -248,21 +265,18 @@ SearchBar {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
.recipe-favorite {
|
.recipe-favorite {
|
||||||
font-size: 14;
|
font-size: 12;
|
||||||
padding: 14 12 0 0;
|
padding: 14 8 0 0;
|
||||||
}
|
}
|
||||||
.recipe-cat,
|
.recipe-cat,
|
||||||
.recipe-favorite {
|
.recipe-favorite {
|
||||||
color: $orange;
|
color: $orange;
|
||||||
}
|
}
|
||||||
.recipe-favorite.hide {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
.group-header {
|
.group-header {
|
||||||
padding: 12;
|
padding: 8;
|
||||||
color: #ff7043;
|
color: #ff7043;
|
||||||
}
|
}
|
||||||
.main-container {
|
.main-container {
|
||||||
|
@ -317,22 +331,27 @@ SearchBar {
|
||||||
}
|
}
|
||||||
.view-title {
|
.view-title {
|
||||||
font-size: 22;
|
font-size: 22;
|
||||||
|
line-height: 6;
|
||||||
|
margin-bottom: 16;
|
||||||
}
|
}
|
||||||
.view-ingredient {
|
.view-ingredient {
|
||||||
font-size: 14;
|
font-size: 14;
|
||||||
line-height: 6;
|
line-height: 6;
|
||||||
margin-top: 12;
|
padding-bottom: 16;
|
||||||
}
|
}
|
||||||
.view-favorited {
|
.view-favorited {
|
||||||
color: #ff7043;
|
color: #ff7043;
|
||||||
}
|
}
|
||||||
|
.activity-indicator {
|
||||||
|
background: #ff7043;
|
||||||
|
}
|
||||||
|
|
||||||
.view-count {
|
.view-count {
|
||||||
font-size: 10;
|
font-size: 10;
|
||||||
width: 20;
|
width: 20;
|
||||||
height: 20;
|
height: 20;
|
||||||
padding: 3 0 0;
|
padding-top: 3%;
|
||||||
margin-left: 6;
|
margin: 0 0 0 6;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 100;
|
border-radius: 100;
|
||||||
}
|
}
|
||||||
|
@ -342,7 +361,7 @@ SearchBar {
|
||||||
.view-reference {
|
.view-reference {
|
||||||
font-size: 14;
|
font-size: 14;
|
||||||
line-height: 6;
|
line-height: 6;
|
||||||
padding: 0 0 12 24;
|
padding: 0 0 16 24;
|
||||||
margin: 0 0 0 15;
|
margin: 0 0 0 15;
|
||||||
border-width: 0 0 0 2;
|
border-width: 0 0 0 2;
|
||||||
}
|
}
|
||||||
|
@ -368,3 +387,7 @@ SearchBar {
|
||||||
padding: 16;
|
padding: 16;
|
||||||
margin: 8 0 0 0;
|
margin: 8 0 0 0;
|
||||||
}
|
}
|
||||||
|
.closeBtn {
|
||||||
|
padding: 4;
|
||||||
|
margin-top: 16;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page @loaded="setCurrentComponent">
|
||||||
<ActionBar :flat="viewIsScrolled ? false : true">
|
<ActionBar :flat="viewIsScrolled ? false : true">
|
||||||
<!-- Settings Actionbar -->
|
<!-- Settings Actionbar -->
|
||||||
<GridLayout rows="*" columns="auto, *" class="actionBarContainer">
|
<GridLayout rows="*" columns="auto, *" class="actionBarContainer">
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
@tap="showDrawer"
|
@tap="showDrawer"
|
||||||
col="0"
|
col="0"
|
||||||
/>
|
/>
|
||||||
<Label class="title orkm" :text="title" col="1" />
|
<Label class="title orkm" text="About" col="1" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
|
@ -85,9 +85,12 @@ import { mapState, mapActions } from "vuex"
|
||||||
export default {
|
export default {
|
||||||
props: ["highlight", "viewIsScrolled", "showDrawer", "title"],
|
props: ["highlight", "viewIsScrolled", "showDrawer", "title"],
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon"]),
|
...mapState(["icon",'currentComponent']),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setCurrentComponent() {
|
||||||
|
this.$store.dispatch("setCurrentComponent", "About")
|
||||||
|
},
|
||||||
openURL(args, url) {
|
openURL(args, url) {
|
||||||
this.highlight(args)
|
this.highlight(args)
|
||||||
utils.openUrl(url)
|
utils.openUrl(url)
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
drawerContentSize="270"
|
drawerContentSize="270"
|
||||||
showOverNavigation="true"
|
showOverNavigation="true"
|
||||||
gesturesEnabled="true"
|
gesturesEnabled="true"
|
||||||
drawerTransition="RevealTransition"
|
drawerTransition="SlideInOnTopTransition"
|
||||||
>
|
>
|
||||||
<GridLayout
|
<GridLayout
|
||||||
rows="auto, auto, *, auto, auto"
|
rows="*, auto"
|
||||||
columns="*"
|
columns="*"
|
||||||
~drawerContent
|
~drawerContent
|
||||||
padding="8"
|
padding="8"
|
||||||
|
@ -17,62 +17,65 @@
|
||||||
>
|
>
|
||||||
<StackLayout row="0">
|
<StackLayout row="0">
|
||||||
<StackLayout
|
<StackLayout
|
||||||
@tap="localNavigation('EnRecipes', 'EnRecipes', true, false)"
|
v-for="(item, index) in topmenu"
|
||||||
|
:key="index"
|
||||||
|
@tap="navigateTo(item.component, false, false)"
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
class="sd-item orkm"
|
class="sd-item orkm"
|
||||||
:class="{
|
:class="{
|
||||||
'selected-sd-item':
|
'selected-sd-item': currentComponent === item.component,
|
||||||
currentComponent === 'EnRecipes' &&
|
|
||||||
!filterFavorites &&
|
|
||||||
!selectedCategory,
|
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.home" margin="0 24 0 0" />
|
<Label class="bx" :text="icon[item.icon]" margin="0 24 0 0" />
|
||||||
<Label verticalAlignment="center" text="Home" />
|
<Label :text="item.title" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout class="hr m-10"></StackLayout>
|
||||||
@tap="localNavigation('Favorites', 'Favorites', true, false)"
|
<GridLayout
|
||||||
orientation="horizontal"
|
class="sd-group-header orkm"
|
||||||
class="sd-item orkm"
|
rows="auto"
|
||||||
:class="{
|
columns="*, auto"
|
||||||
'selected-sd-item':
|
|
||||||
currentComponent === 'EnRecipes' && filterFavorites,
|
|
||||||
}"
|
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon.heart" margin="0 24 0 0" />
|
<Label col="0" text="Categories" />
|
||||||
<Label verticalAlignment="center" text="Favorites" />
|
<Label
|
||||||
</StackLayout>
|
@tap="toggleCatEdit"
|
||||||
</StackLayout>
|
col="2"
|
||||||
<StackLayout
|
:text="catEditMode ? 'DONE' : 'RENAME'"
|
||||||
orientation="horizontal"
|
/>
|
||||||
row="1"
|
</GridLayout>
|
||||||
class="sd-group-header orkr"
|
<ScrollView height="100%">
|
||||||
>
|
<StackLayout>
|
||||||
<Label text="Categories" />
|
<GridLayout
|
||||||
</StackLayout>
|
@tap="navigateTo(item, false, true)"
|
||||||
<ScrollView row="2" scrollBarIndicatorVisible="false">
|
v-for="(item, index) in categories"
|
||||||
<StackLayout>
|
:key="index"
|
||||||
<StackLayout
|
class="sd-item orkm"
|
||||||
@tap="localNavigation(item, item, false, true)"
|
:class="{
|
||||||
v-for="(item, index) in categories"
|
'selected-sd-item': currentComponent == item,
|
||||||
:key="index"
|
}"
|
||||||
orientation="horizontal"
|
columns="auto, *, auto"
|
||||||
class="sd-item orkm"
|
>
|
||||||
:class="{
|
<Label
|
||||||
'selected-sd-item':
|
col="0"
|
||||||
currentComponent === 'EnRecipes' && selectedCategory == item,
|
class="bx"
|
||||||
}"
|
:text="icon.label"
|
||||||
>
|
margin="0 24 0 0"
|
||||||
<Label class="bx" :text="icon.label" margin="0 24 0 0" />
|
/>
|
||||||
<Label verticalAlignment="center" :text="item" />
|
<Label col="1" :text="item" />
|
||||||
|
<Label
|
||||||
|
v-if="catEditMode"
|
||||||
|
@tap="editCategory(item)"
|
||||||
|
col="2"
|
||||||
|
class="bx"
|
||||||
|
:text="icon.edit"
|
||||||
|
/>
|
||||||
|
</GridLayout>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</StackLayout>
|
</ScrollView>
|
||||||
</ScrollView>
|
</StackLayout>
|
||||||
|
<StackLayout row="1">
|
||||||
<StackLayout row="3" class="hr m-10"></StackLayout>
|
<StackLayout class="hr m-10"></StackLayout>
|
||||||
<StackLayout row="4">
|
|
||||||
<StackLayout
|
<StackLayout
|
||||||
@tap="navigateTo(item.component, item.title)"
|
@tap="navigateTo(item.component, true, false)"
|
||||||
v-for="(item, index) in bottommenu"
|
v-for="(item, index) in bottommenu"
|
||||||
:key="index"
|
:key="index"
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
|
@ -82,19 +85,30 @@
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<Label class="bx" :text="icon[item.icon]" margin="0 24 0 0" />
|
<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>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
|
||||||
<GridLayout ~mainContent rows="*" columns="*">
|
<GridLayout ~mainContent rows="*" columns="*">
|
||||||
<Frame id="main-frame">
|
<Frame ref="mainFrame" id="main-frame">
|
||||||
<!-- Home -->
|
<!-- Home -->
|
||||||
<EnRecipes
|
<EnRecipes
|
||||||
:selectedCategory="selectedCategory"
|
ref="enrecipes"
|
||||||
:filterFavorites="filterFavorites"
|
:filterFavorites="filterFavorites"
|
||||||
:title="title"
|
:filterMustTry="filterMustTry"
|
||||||
|
:selectedCategory="selectedCategory"
|
||||||
:showDrawer="showDrawer"
|
:showDrawer="showDrawer"
|
||||||
|
:hijackGlobalBackEvent="hijackGlobalBackEvent"
|
||||||
|
:releaseGlobalBackEvent="releaseGlobalBackEvent"
|
||||||
/>
|
/>
|
||||||
</Frame>
|
</Frame>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
@ -104,15 +118,20 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as utils from "tns-core-modules/utils/utils"
|
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 * 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 EnRecipes from "./EnRecipes.vue"
|
||||||
import Settings from "./Settings.vue"
|
import Settings from "./Settings.vue"
|
||||||
import About from "./About.vue"
|
import About from "./About.vue"
|
||||||
|
import PromptDialog from "./modal/PromptDialog.vue"
|
||||||
import { mapState } from "vuex"
|
import { mapState } from "vuex"
|
||||||
|
|
||||||
|
import { Couchbase, ConcurrencyMode } from "nativescript-couchbase-plugin"
|
||||||
|
|
||||||
let page
|
let page
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
@ -122,12 +141,26 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
title: "EnRecipes",
|
|
||||||
selectedCategory: null,
|
selectedCategory: null,
|
||||||
filterFavorites: false,
|
filterFavorites: false,
|
||||||
searchQuery: "",
|
filterMustTry: false,
|
||||||
showSearch: false,
|
topmenu: [
|
||||||
currentComponent: "EnRecipes",
|
{
|
||||||
|
title: "Home",
|
||||||
|
component: "EnRecipes",
|
||||||
|
icon: "home",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Favorites",
|
||||||
|
component: "Favorites",
|
||||||
|
icon: "heart",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Must-Try",
|
||||||
|
component: "Must-Try",
|
||||||
|
icon: "musttry",
|
||||||
|
},
|
||||||
|
],
|
||||||
bottommenu: [
|
bottommenu: [
|
||||||
{
|
{
|
||||||
title: "Settings",
|
title: "Settings",
|
||||||
|
@ -140,10 +173,11 @@ export default {
|
||||||
icon: "info",
|
icon: "info",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
catEditMode: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["recipes", "icon"]),
|
...mapState(["recipes", "categories", "icon", "currentComponent"]),
|
||||||
categories() {
|
categories() {
|
||||||
let arr = this.recipes.map((e) => {
|
let arr = this.recipes.map((e) => {
|
||||||
return e.category
|
return e.category
|
||||||
|
@ -152,6 +186,39 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
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) {
|
highlight(args) {
|
||||||
let temp = args.object.className
|
let temp = args.object.className
|
||||||
args.object.className = `${temp} option-highlight`
|
args.object.className = `${temp} option-highlight`
|
||||||
|
@ -159,70 +226,103 @@ export default {
|
||||||
args.object.className = temp
|
args.object.className = temp
|
||||||
}, 100)
|
}, 100)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
setSelectedCategory(e) {
|
setSelectedCategory(e) {
|
||||||
this.selectedCategory = e.item
|
this.selectedCategory = e.item
|
||||||
this.closeDrawer()
|
this.closeDrawer()
|
||||||
},
|
},
|
||||||
removeBackEvent() {
|
hijackGlobalBackEvent() {
|
||||||
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
|
|
||||||
application.android.on(
|
application.android.on(
|
||||||
application.AndroidApplication.activityBackPressedEvent,
|
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) {
|
releaseGlobalBackEvent() {
|
||||||
this.currentComponent = title
|
application.android.off(
|
||||||
this.$navigateTo(to, {
|
application.AndroidApplication.activityBackPressedEvent,
|
||||||
frame: "main-frame",
|
this.globalBackEvent
|
||||||
// transition: {
|
)
|
||||||
// name: "slide",
|
},
|
||||||
// duration: 250,
|
globalBackEvent(args) {
|
||||||
// curve: "easeIn",
|
function preventDefault() {
|
||||||
// },
|
args.cancel = true
|
||||||
props: {
|
}
|
||||||
highlight: this.highlight,
|
let vm = this
|
||||||
viewIsScrolled: this.viewIsScrolled,
|
function isFiltered() {
|
||||||
showDrawer: this.showDrawer,
|
vm.filterFavorites
|
||||||
title,
|
? vm.setComponent("Favorites")
|
||||||
},
|
: vm.filterMustTry
|
||||||
backstackVisible: false,
|
? vm.setComponent("Must-Try")
|
||||||
})
|
: vm.selectedCategory
|
||||||
this.closeDrawer()
|
? 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() {
|
showDrawer() {
|
||||||
this.$refs.drawer.nativeView.showDrawer()
|
this.$refs.drawer.nativeView.showDrawer()
|
||||||
|
@ -230,6 +330,14 @@ export default {
|
||||||
closeDrawer() {
|
closeDrawer() {
|
||||||
this.$refs.drawer.nativeView.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>
|
</script>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page @loaded="setCurrentComponent" @unloaded="releaseBackEvent">
|
||||||
<ActionBar :flat="viewIsScrolled ? false : true">
|
<ActionBar :flat="viewIsScrolled ? false : true">
|
||||||
<GridLayout rows="*" columns="auto, *, auto," class="actionBarContainer">
|
<GridLayout rows="*" columns="auto, *, auto," class="actionBarContainer">
|
||||||
<Label
|
<Label
|
||||||
|
@ -9,7 +9,8 @@
|
||||||
col="0"
|
col="0"
|
||||||
@tap="navigateBack"
|
@tap="navigateBack"
|
||||||
/>
|
/>
|
||||||
<Label class="title orkm" text="New recipe" col="1" />
|
<Label class="title orkm" :text="title" col="1" />
|
||||||
|
|
||||||
<Label
|
<Label
|
||||||
v-if="hasEnoughDetails"
|
v-if="hasEnoughDetails"
|
||||||
class="bx"
|
class="bx"
|
||||||
|
@ -46,7 +47,7 @@
|
||||||
horizontalAlignment="center"
|
horizontalAlignment="center"
|
||||||
class="bx"
|
class="bx"
|
||||||
fontSize="160"
|
fontSize="160"
|
||||||
:text="icon.dish"
|
:text="icon.image"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout
|
<StackLayout
|
||||||
|
@ -75,17 +76,14 @@
|
||||||
<StackLayout margin="0 16">
|
<StackLayout margin="0 16">
|
||||||
<AbsoluteLayout class="inputField">
|
<AbsoluteLayout class="inputField">
|
||||||
<TextField
|
<TextField
|
||||||
width="100%"
|
|
||||||
hint="My Healthy Recipe"
|
hint="My Healthy Recipe"
|
||||||
v-model="recipeContent.title"
|
v-model="recipeContent.title"
|
||||||
autocapitalizationType="words"
|
autocapitalizationType="words"
|
||||||
maxLength="32"
|
|
||||||
/>
|
/>
|
||||||
<Label top="0" class="fieldLabel" text="Title" />
|
<Label top="0" class="fieldLabel" text="Title" />
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
<AbsoluteLayout class="inputField">
|
<AbsoluteLayout class="inputField">
|
||||||
<TextField
|
<TextField
|
||||||
width="100%"
|
|
||||||
v-model="recipeContent.category"
|
v-model="recipeContent.category"
|
||||||
editable="false"
|
editable="false"
|
||||||
@tap="showCategories()"
|
@tap="showCategories()"
|
||||||
|
@ -95,7 +93,6 @@
|
||||||
<GridLayout columns="*, 8, *">
|
<GridLayout columns="*, 8, *">
|
||||||
<AbsoluteLayout class="inputField" col="0">
|
<AbsoluteLayout class="inputField" col="0">
|
||||||
<TimePickerField
|
<TimePickerField
|
||||||
width="100%"
|
|
||||||
timeFormat="HH:mm"
|
timeFormat="HH:mm"
|
||||||
pickerTitle="Approx. preparation time"
|
pickerTitle="Approx. preparation time"
|
||||||
@timeChange="onPrepTimeChange"
|
@timeChange="onPrepTimeChange"
|
||||||
|
@ -105,7 +102,6 @@
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
<AbsoluteLayout class="inputField" col="2">
|
<AbsoluteLayout class="inputField" col="2">
|
||||||
<TimePickerField
|
<TimePickerField
|
||||||
width="100%"
|
|
||||||
timeFormat="HH:mm"
|
timeFormat="HH:mm"
|
||||||
pickerTitle="Approx. cooking time"
|
pickerTitle="Approx. cooking time"
|
||||||
@timeChange="onCookTimeChange"
|
@timeChange="onCookTimeChange"
|
||||||
|
@ -157,11 +153,8 @@
|
||||||
@tap="showUnits($event)"
|
@tap="showUnits($event)"
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label
|
||||||
verticalAlignment="center"
|
|
||||||
col="6"
|
col="6"
|
||||||
padding="4"
|
class="bx closeBtn"
|
||||||
margin="8 0 0 0"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.close"
|
:text="icon.close"
|
||||||
@tap="removeIngredient(index)"
|
@tap="removeIngredient(index)"
|
||||||
/>
|
/>
|
||||||
|
@ -189,18 +182,9 @@
|
||||||
v-model="recipeContent.instructions[index]"
|
v-model="recipeContent.instructions[index]"
|
||||||
editable="true"
|
editable="true"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- <TextField
|
|
||||||
col="0"
|
|
||||||
v-model="recipeContent.instructions[index]"
|
|
||||||
:hint="`Step ${index + 1}`"
|
|
||||||
/> -->
|
|
||||||
<Label
|
<Label
|
||||||
verticalAlignment="center"
|
|
||||||
col="2"
|
col="2"
|
||||||
padding="4"
|
class="bx closeBtn"
|
||||||
margin="8 0 0 0"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.close"
|
:text="icon.close"
|
||||||
@tap="removeInstruction(index)"
|
@tap="removeInstruction(index)"
|
||||||
/>
|
/>
|
||||||
|
@ -228,11 +212,8 @@
|
||||||
editable="true"
|
editable="true"
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label
|
||||||
verticalAlignment="center"
|
|
||||||
col="2"
|
col="2"
|
||||||
padding="4"
|
class="bx closeBtn"
|
||||||
margin="8 0 0 0"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.close"
|
:text="icon.close"
|
||||||
@tap="removeNote(index)"
|
@tap="removeNote(index)"
|
||||||
/>
|
/>
|
||||||
|
@ -259,11 +240,8 @@
|
||||||
hint="Website or Video URL"
|
hint="Website or Video URL"
|
||||||
/>
|
/>
|
||||||
<Label
|
<Label
|
||||||
verticalAlignment="center"
|
|
||||||
col="2"
|
col="2"
|
||||||
padding="4"
|
class="bx closeBtn"
|
||||||
margin="8 0 0 0"
|
|
||||||
class="bx"
|
|
||||||
:text="icon.close"
|
:text="icon.close"
|
||||||
@tap="removeReference(index)"
|
@tap="removeReference(index)"
|
||||||
/>
|
/>
|
||||||
|
@ -284,32 +262,17 @@
|
||||||
import { screen } from "tns-core-modules/platform"
|
import { screen } from "tns-core-modules/platform"
|
||||||
import { Mediafilepicker } from "nativescript-mediafilepicker"
|
import { Mediafilepicker } from "nativescript-mediafilepicker"
|
||||||
import { mapState, mapActions } from "vuex"
|
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 {
|
export default {
|
||||||
|
props: ["recipeIndex", "selectedCategory"],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
title: "New recipe",
|
||||||
viewIsScrolled: false,
|
viewIsScrolled: false,
|
||||||
units: [
|
|
||||||
"unit",
|
|
||||||
"tsp",
|
|
||||||
"Tbsp",
|
|
||||||
"oz",
|
|
||||||
"cup",
|
|
||||||
"pt",
|
|
||||||
"qt",
|
|
||||||
"lb",
|
|
||||||
"gal",
|
|
||||||
"ml",
|
|
||||||
"L",
|
|
||||||
"mg",
|
|
||||||
"g",
|
|
||||||
"kg",
|
|
||||||
"mm",
|
|
||||||
"cm",
|
|
||||||
"m",
|
|
||||||
"in",
|
|
||||||
"°C",
|
|
||||||
"°F",
|
|
||||||
],
|
|
||||||
recipeContent: {
|
recipeContent: {
|
||||||
imageSrc: null,
|
imageSrc: null,
|
||||||
title: null,
|
title: null,
|
||||||
|
@ -319,7 +282,7 @@ export default {
|
||||||
portionSize: 1,
|
portionSize: 1,
|
||||||
ingredients: [
|
ingredients: [
|
||||||
{
|
{
|
||||||
item: null,
|
item: "",
|
||||||
quantity: null,
|
quantity: null,
|
||||||
unit: "unit",
|
unit: "unit",
|
||||||
},
|
},
|
||||||
|
@ -328,71 +291,97 @@ export default {
|
||||||
notes: [""],
|
notes: [""],
|
||||||
references: [""],
|
references: [""],
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
|
tried: false,
|
||||||
|
lastModified: null,
|
||||||
},
|
},
|
||||||
categories: [
|
tempRecipeContent: {},
|
||||||
"Appetizers",
|
blockModal: false,
|
||||||
"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",
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon"]),
|
...mapState(["icon", "units", "categories", "currentComponent", "recipes"]),
|
||||||
screenWidth() {
|
screenWidth() {
|
||||||
return screen.mainScreen.widthDIPs
|
return screen.mainScreen.widthDIPs
|
||||||
},
|
},
|
||||||
hasEnoughDetails() {
|
hasEnoughDetails() {
|
||||||
let recipe = this.recipeContent
|
if (this.recipeIndex) {
|
||||||
return recipe.title && recipe.category
|
return (
|
||||||
|
JSON.stringify(this.recipeContent) !==
|
||||||
|
JSON.stringify(this.tempRecipeContent)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return this.recipeContent.title
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setTime(time) {
|
setCurrentComponent() {
|
||||||
if (Date.parse(this.recipeContent[time])) {
|
setTimeout((e) => {
|
||||||
let date = new Date(this.recipeContent[time])
|
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 h = date.getHours()
|
||||||
let m = date.getMinutes()
|
let m = date.getMinutes()
|
||||||
|
|
||||||
this.recipeContent[time] =
|
this.recipeContent[key] =
|
||||||
(h < 10 ? "0" + h : h) + ":" + (m < 10 ? "0" + m : m)
|
(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() {
|
saveRecipe() {
|
||||||
this.setTime("prepTime")
|
this.clearEmptyFields()
|
||||||
this.setTime("cookTime")
|
this.recipeContent.lastModified = new Date()
|
||||||
// console.log(this.recipeContent)
|
if (this.recipeIndex >= 0) {
|
||||||
|
this.$store.dispatch("overwriteRecipe", {
|
||||||
this.$store.dispatch("addRecipe", this.recipeContent)
|
index: this.recipeIndex,
|
||||||
|
recipe: this.recipeContent,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$store.dispatch("addRecipe", this.recipeContent)
|
||||||
|
}
|
||||||
this.$navigateBack()
|
this.$navigateBack()
|
||||||
},
|
},
|
||||||
onPrepTimeChange(args) {
|
onPrepTimeChange(args) {
|
||||||
this.recipeContent.prepTime = args.value
|
this.setTime("prepTime", args.value)
|
||||||
},
|
},
|
||||||
onCookTimeChange(args) {
|
onCookTimeChange(args) {
|
||||||
this.recipeContent.cookTime = args.value
|
this.setTime("cookTime", args.value)
|
||||||
},
|
},
|
||||||
onScroll(args) {
|
onScroll(args) {
|
||||||
args.scrollY
|
args.scrollY
|
||||||
|
@ -400,25 +389,77 @@ export default {
|
||||||
: (this.viewIsScrolled = false)
|
: (this.viewIsScrolled = false)
|
||||||
},
|
},
|
||||||
showCategories() {
|
showCategories() {
|
||||||
action("Select a category", "Cancel", [...this.categories]).then(
|
this.releaseBackEvent()
|
||||||
(result) => {
|
this.$showModal(ActionDialog, {
|
||||||
if (result != "Cancel") this.recipeContent.category = result
|
props: {
|
||||||
}
|
title: "Category",
|
||||||
)
|
list: [...this.categories],
|
||||||
},
|
height: "75%",
|
||||||
navigateBack() {
|
action: "NEW CATEGORY",
|
||||||
confirm({
|
},
|
||||||
message:
|
}).then((action) => {
|
||||||
"Are you sure you want discard unsaved changes to this recipe?",
|
if (action == "NEW CATEGORY") {
|
||||||
cancelButtonText: "Keep Editing",
|
this.$showModal(PromptDialog, {
|
||||||
okButtonText: "Discard",
|
props: {
|
||||||
}).then((res) => {
|
title: "New category",
|
||||||
if (res) {
|
action: "ADD",
|
||||||
this.$navigateBack()
|
},
|
||||||
|
}).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() {
|
takePicture() {
|
||||||
let mediafilepicker = new Mediafilepicker()
|
let mediafilepicker = new Mediafilepicker()
|
||||||
let vm = this
|
let vm = this
|
||||||
|
@ -462,7 +503,7 @@ export default {
|
||||||
},
|
},
|
||||||
removePicture() {
|
removePicture() {
|
||||||
confirm({
|
confirm({
|
||||||
title: "Delete Recipe Photo",
|
title: "Delete Photo",
|
||||||
message: "Are you sure you want to delete the recipe photo?",
|
message: "Are you sure you want to delete the recipe photo?",
|
||||||
okButtonText: "Delete",
|
okButtonText: "Delete",
|
||||||
cancelButtonText: "Cancel",
|
cancelButtonText: "Cancel",
|
||||||
|
@ -473,7 +514,7 @@ export default {
|
||||||
|
|
||||||
addIngredient() {
|
addIngredient() {
|
||||||
this.recipeContent.ingredients.push({
|
this.recipeContent.ingredients.push({
|
||||||
item: null,
|
item: "",
|
||||||
quantity: null,
|
quantity: null,
|
||||||
unit: "unit",
|
unit: "unit",
|
||||||
})
|
})
|
||||||
|
@ -504,11 +545,17 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
showUnits(e) {
|
showUnits(e) {
|
||||||
action("Select measuring unit", "Cancel", [...this.units]).then(
|
this.releaseBackEvent()
|
||||||
(result) => {
|
this.$showModal(ActionDialog, {
|
||||||
if (result != "Cancel") e.object.text = result
|
props: {
|
||||||
}
|
title: "Unit",
|
||||||
)
|
list: [...this.units],
|
||||||
|
height: "75%",
|
||||||
|
},
|
||||||
|
}).then((action) => {
|
||||||
|
this.hijackBackEvent()
|
||||||
|
if (action) e.object.text = action
|
||||||
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page @loaded="setCurrentComponent">
|
||||||
<ActionBar :flat="viewIsScrolled ? false : true">
|
<ActionBar :flat="viewIsScrolled ? false : true">
|
||||||
<!-- Search Actionbar -->
|
<!-- Search Actionbar -->
|
||||||
<GridLayout
|
<GridLayout
|
||||||
v-if="showSearch"
|
v-if="showSearch"
|
||||||
rows="*"
|
|
||||||
columns="auto, *"
|
columns="auto, *"
|
||||||
class="actionBarContainer"
|
class="actionBarContainer"
|
||||||
|
verticalAlignment="center"
|
||||||
>
|
>
|
||||||
<Label
|
<Label
|
||||||
class="bx leftAction"
|
class="bx leftAction"
|
||||||
|
@ -15,20 +15,20 @@
|
||||||
col="0"
|
col="0"
|
||||||
@tap="closeSearch"
|
@tap="closeSearch"
|
||||||
/>
|
/>
|
||||||
|
<!-- @loaded="searchBarLoaded" -->
|
||||||
<SearchBar
|
<SearchBar
|
||||||
@loaded="searchBarLoaded"
|
|
||||||
id="searchField"
|
|
||||||
col="1"
|
col="1"
|
||||||
hint="Search"
|
hint="Search"
|
||||||
textFieldHintColor="#bdbdbd"
|
textFieldHintColor="#bdbdbd"
|
||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
|
@textChange="updateFilter"
|
||||||
|
@clear="updateFilter"
|
||||||
/>
|
/>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
<!-- Home Actionbar -->
|
<!-- Home Actionbar -->
|
||||||
<GridLayout
|
<GridLayout
|
||||||
v-else
|
v-else
|
||||||
rows="*"
|
columns="auto, *, auto, auto"
|
||||||
columns="auto, *, auto,"
|
|
||||||
class="actionBarContainer"
|
class="actionBarContainer"
|
||||||
>
|
>
|
||||||
<Label
|
<Label
|
||||||
|
@ -38,84 +38,61 @@
|
||||||
@tap="showDrawer"
|
@tap="showDrawer"
|
||||||
col="0"
|
col="0"
|
||||||
/>
|
/>
|
||||||
<Label class="title orkm" :text="title" col="1" />
|
<Label class="title orkm" :text="currentComponent" col="1" />
|
||||||
<Label
|
<Label class="bx" :text="icon.search" col="2" @tap="openSearch" />
|
||||||
class="bx"
|
<Label class="bx" :text="icon.sort" col="3" @tap="sortDialog" />
|
||||||
:text="icon.search"
|
|
||||||
col="2"
|
|
||||||
@tap="showSearch = true"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<AbsoluteLayout>
|
<AbsoluteLayout>
|
||||||
<RadListView
|
<RadListView
|
||||||
v-if="filteredRecipes.length"
|
|
||||||
ref="listView"
|
ref="listView"
|
||||||
for="recipe in filteredRecipes"
|
itemHeight="112"
|
||||||
|
for="recipe in recipes"
|
||||||
swipeActions="true"
|
swipeActions="true"
|
||||||
@itemSwipeProgressChanged="onSwiping"
|
@itemSwipeProgressChanged="onSwiping"
|
||||||
@itemSwipeProgressEnded="onSwipeEnded"
|
@itemSwipeProgressEnded="onSwipeEnded"
|
||||||
@scrolled="onScroll($event)"
|
@scrolled="onScroll($event)"
|
||||||
@itemTap="viewRecipe"
|
@itemTap="viewRecipe"
|
||||||
|
:filteringFunction="filterFunction"
|
||||||
|
:sortingFunction="sortFunction"
|
||||||
>
|
>
|
||||||
<v-template>
|
<v-template>
|
||||||
<GridLayout
|
<GridLayout
|
||||||
class="recipe-li"
|
class="recipe-li"
|
||||||
rows="128"
|
rows="112"
|
||||||
columns="auto, *, auto"
|
columns="112, *"
|
||||||
androidElevation="2"
|
androidElevation="1"
|
||||||
>
|
>
|
||||||
<Image
|
<Image col="0" src="res://icon" stretch="fill" />
|
||||||
src="res://icon"
|
<StackLayout class="recipe-info" col="1">
|
||||||
stretch="fill"
|
<Label :text="recipe.category" class="orkm recipe-cat" />
|
||||||
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" />
|
|
||||||
<Label :text="recipe.title" class="orkm recipe-title" />
|
<Label :text="recipe.title" class="orkm recipe-title" />
|
||||||
<Label
|
<Label
|
||||||
:text="recipeTotalTime(recipe.prepTime, recipe.cookTime)"
|
:text="recipeTotalTime(recipe.prepTime, recipe.cookTime)"
|
||||||
class="h4 recipe-time"
|
class="h4 recipe-time"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<Label
|
|
||||||
verticalAlignment="top"
|
|
||||||
col="2"
|
|
||||||
class="bx recipe-favorite"
|
|
||||||
:class="{ hide: !recipe.isFavorite }"
|
|
||||||
:text="icon.heart"
|
|
||||||
/>
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</v-template>
|
</v-template>
|
||||||
|
|
||||||
<v-template name="itemswipe">
|
<v-template name="itemswipe">
|
||||||
<GridLayout columns="auto, *, auto">
|
<GridLayout columns="*, auto">
|
||||||
<StackLayout
|
<StackLayout id="delete-action" col="1" class="swipe-item right">
|
||||||
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"
|
|
||||||
>
|
|
||||||
<Label class="bx" padding="8 0 0 6" :text="icon.trash" />
|
<Label class="bx" padding="8 0 0 6" :text="icon.trash" />
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</v-template>
|
</v-template>
|
||||||
|
<v-template name="footer">
|
||||||
|
<StackLayout height="128"></StackLayout>
|
||||||
|
</v-template>
|
||||||
</RadListView>
|
</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
|
<Label
|
||||||
v-if="!filteredRecipes.length && searchQuery"
|
v-if="!filteredRecipes.length && searchQuery"
|
||||||
class="noResults"
|
class="noResults"
|
||||||
|
@ -134,12 +111,15 @@
|
||||||
textAlignment="center"
|
textAlignment="center"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
/>
|
/>
|
||||||
<GridLayout
|
<Label
|
||||||
id="btnFabContainer"
|
v-if="!filteredRecipes.length && filterMustTry && !searchQuery"
|
||||||
rows="*,88"
|
class="noResults"
|
||||||
columns="*,88"
|
horizontalAlignment="center"
|
||||||
v-if="!showSearch"
|
text="Your Must-Try recipes will be listed here."
|
||||||
>
|
textAlignment="center"
|
||||||
|
textWrap="true"
|
||||||
|
/>
|
||||||
|
<GridLayout id="btnFabContainer" rows="*,88" columns="*,88">
|
||||||
<Label
|
<Label
|
||||||
row="1"
|
row="1"
|
||||||
col="1"
|
col="1"
|
||||||
|
@ -157,15 +137,25 @@
|
||||||
import * as utils from "tns-core-modules/utils/utils"
|
import * as utils from "tns-core-modules/utils/utils"
|
||||||
import * as application from "tns-core-modules/application"
|
import * as application from "tns-core-modules/application"
|
||||||
import * as gestures from "tns-core-modules/ui/gestures"
|
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 { ObservableArray } from "tns-core-modules/data/observable-array"
|
||||||
|
|
||||||
import EditRecipe from "./EditRecipe.vue"
|
import EditRecipe from "./EditRecipe.vue"
|
||||||
import ViewRecipe from "./ViewRecipe.vue"
|
import ViewRecipe from "./ViewRecipe.vue"
|
||||||
|
import ActionDialog from "./modal/ActionDialog.vue"
|
||||||
|
import ConfirmDialog from "./modal/ConfirmDialog.vue"
|
||||||
import { mapState, mapActions } from "vuex"
|
import { mapState, mapActions } from "vuex"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ["filterFavorites", "selectedCategory", "title", "showDrawer"],
|
props: [
|
||||||
|
"filterFavorites",
|
||||||
|
"filterMustTry",
|
||||||
|
"selectedCategory",
|
||||||
|
"showDrawer",
|
||||||
|
"hijackGlobalBackEvent",
|
||||||
|
"releaseGlobalBackEvent",
|
||||||
|
],
|
||||||
components: {
|
components: {
|
||||||
EditRecipe,
|
EditRecipe,
|
||||||
ViewRecipe,
|
ViewRecipe,
|
||||||
|
@ -173,80 +163,182 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
searchQuery: "",
|
searchQuery: "",
|
||||||
showSearch: false,
|
|
||||||
viewIsScrolled: false,
|
viewIsScrolled: false,
|
||||||
leftAction: false,
|
showSearch: false,
|
||||||
|
// leftAction: false,
|
||||||
rightAction: false,
|
rightAction: false,
|
||||||
|
sortType: "Natural order",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["recipes", "icon"]),
|
...mapState(["recipes", "icon", "currentComponent"]),
|
||||||
recipesByCategory() {
|
|
||||||
return this.recipes.reduce((acc, e) => {
|
|
||||||
acc[e.category] = [...(acc[e.category] || []), e]
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
},
|
|
||||||
filteredRecipes() {
|
filteredRecipes() {
|
||||||
if (this.selectedCategory) {
|
if (this.filterFavorites) {
|
||||||
return this.recipesByCategory[this.selectedCategory].filter((e) => {
|
return this.recipes.filter(
|
||||||
if (e.title.toLowerCase().includes(this.searchQuery)) return e
|
(e) =>
|
||||||
})
|
e.isFavorite && e.title.toLowerCase().includes(this.searchQuery)
|
||||||
} else if (this.filterFavorites) {
|
)
|
||||||
console.log("fav")
|
} else if (this.filterMustTry) {
|
||||||
return this.recipes.filter((e) => {
|
return this.recipes.filter(
|
||||||
if (e.isFavorite) {
|
(e) => !e.tried && e.title.toLowerCase().includes(this.searchQuery)
|
||||||
if (e.title.toLowerCase().includes(this.searchQuery)) return e
|
)
|
||||||
}
|
} else if (this.selectedCategory) {
|
||||||
})
|
return this.recipes.filter(
|
||||||
|
(e) =>
|
||||||
|
e.category === this.selectedCategory &&
|
||||||
|
e.title.toLowerCase().includes(this.searchQuery)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return this.recipes.filter((e) => {
|
return this.recipes.filter((e) =>
|
||||||
if (e.title.toLowerCase().includes(this.searchQuery)) return e
|
e.title.toLowerCase().includes(this.searchQuery)
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
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 }) {
|
onSwiping({ data, object }) {
|
||||||
const swipeLimits = data.swipeLimits
|
const swipeLimits = data.swipeLimits
|
||||||
const swipeView = object
|
const swipeView = object
|
||||||
const leftItem = swipeView.getViewById("favorite-action")
|
|
||||||
const rightItem = swipeView.getViewById("delete-action")
|
const rightItem = swipeView.getViewById("delete-action")
|
||||||
swipeLimits.left = leftItem.getMeasuredWidth() - 12
|
|
||||||
swipeLimits.right = rightItem.getMeasuredWidth() - 12
|
swipeLimits.right = rightItem.getMeasuredWidth() - 12
|
||||||
swipeLimits.threshold = swipeLimits.left - 4
|
swipeLimits.threshold = swipeLimits.right - 6
|
||||||
if (data.x > swipeLimits.threshold) {
|
if (data.x < -swipeLimits.threshold) {
|
||||||
this.leftAction = true
|
|
||||||
this.$refs.listView.notifySwipeToExecuteFinished()
|
|
||||||
} else if (data.x < -swipeLimits.threshold) {
|
|
||||||
this.rightAction = true
|
this.rightAction = true
|
||||||
this.$refs.listView.notifySwipeToExecuteFinished()
|
swipeView.notifySwipeToExecuteFinished()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSwipeEnded({ index }) {
|
onSwipeEnded({ index }) {
|
||||||
let context = this.recipes.indexOf(this.filteredRecipes[index])
|
if (this.rightAction) this.deleteRecipe(index)
|
||||||
if (this.leftAction) this.toggleFavorite(context)
|
this.rightAction = false
|
||||||
else if (this.rightAction) this.deleteRecipe()
|
|
||||||
this.leftAction = this.rightAction = false
|
|
||||||
},
|
},
|
||||||
toggleFavorite(index) {
|
deleteRecipe(index) {
|
||||||
this.$store.dispatch("toggleFavorite", 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() {
|
getTotalTime(prepTime, cookTime) {
|
||||||
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) {
|
|
||||||
let pT = prepTime.split(":")
|
let pT = prepTime.split(":")
|
||||||
let cT = cookTime.split(":")
|
let cT = cookTime.split(":")
|
||||||
let hrs = parseInt(pT[0]) + parseInt(cT[0])
|
let hrs = parseInt(pT[0]) + parseInt(cT[0])
|
||||||
|
@ -255,42 +347,26 @@ export default {
|
||||||
hrs += Math.floor(mins / 60)
|
hrs += Math.floor(mins / 60)
|
||||||
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`
|
return hrs ? `${hrs}h ${mins}m` : `${mins}m`
|
||||||
},
|
},
|
||||||
|
recipeDuration(prepTime, cookTime) {
|
||||||
|
let { hrs, mins } = this.getTotalTime(prepTime, cookTime)
|
||||||
|
return `${hrs}${mins}`
|
||||||
|
},
|
||||||
onScroll(args) {
|
onScroll(args) {
|
||||||
args.scrollOffset
|
args.scrollOffset
|
||||||
? (this.viewIsScrolled = true)
|
? (this.viewIsScrolled = true)
|
||||||
: (this.viewIsScrolled = false)
|
: (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() {
|
addRecipe() {
|
||||||
|
this.releaseGlobalBackEvent()
|
||||||
this.$navigateTo(EditRecipe, {
|
this.$navigateTo(EditRecipe, {
|
||||||
transition: {
|
transition: {
|
||||||
name: "slide",
|
name: "slide",
|
||||||
|
@ -299,11 +375,11 @@ export default {
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
viewIsScrolled: this.viewIsScrolled,
|
viewIsScrolled: this.viewIsScrolled,
|
||||||
|
selectedCategory: this.selectedCategory,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
viewRecipe({ item }) {
|
viewRecipe({ item }) {
|
||||||
// console.log(item)
|
|
||||||
this.$navigateTo(ViewRecipe, {
|
this.$navigateTo(ViewRecipe, {
|
||||||
transition: {
|
transition: {
|
||||||
name: "fade",
|
name: "fade",
|
||||||
|
@ -311,7 +387,9 @@ export default {
|
||||||
curve: "easeIn",
|
curve: "easeIn",
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
recipe: item,
|
recipeIndex: this.recipes.indexOf(item),
|
||||||
|
hijackGlobalBackEvent: this.hijackGlobalBackEvent,
|
||||||
|
releaseGlobalBackEvent: this.releaseGlobalBackEvent,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page @loaded="setCurrentComponent">
|
||||||
<ActionBar :flat="viewIsScrolled ? false : true">
|
<ActionBar :flat="viewIsScrolled ? false : true">
|
||||||
<!-- Settings Actionbar -->
|
<!-- Settings Actionbar -->
|
||||||
<GridLayout rows="*" columns="auto, *" class="actionBarContainer">
|
<GridLayout rows="*" columns="auto, *" class="actionBarContainer">
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
@tap="showDrawer"
|
@tap="showDrawer"
|
||||||
col="0"
|
col="0"
|
||||||
/>
|
/>
|
||||||
<Label class="title orkm" :text="title" col="1" />
|
<Label class="title orkm" text="Settings" col="1" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
|
@ -22,6 +22,7 @@
|
||||||
class="option"
|
class="option"
|
||||||
@tap="selectThemes"
|
@tap="selectThemes"
|
||||||
>
|
>
|
||||||
|
<!-- @tap="selectThemes" -->
|
||||||
<Label verticalAlignment="center" class="bx" :text="icon.theme" />
|
<Label verticalAlignment="center" class="bx" :text="icon.theme" />
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
<Label text="Theme" class="option-title" />
|
<Label text="Theme" class="option-title" />
|
||||||
|
@ -57,16 +58,24 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Menu } from "nativescript-menu"
|
|
||||||
import * as permissions from "nativescript-permissions"
|
import * as permissions from "nativescript-permissions"
|
||||||
import * as application from "tns-core-modules/application"
|
import * as application from "tns-core-modules/application"
|
||||||
|
|
||||||
import { getString, setString } from "application-settings"
|
import { getString, setString } from "application-settings"
|
||||||
import Theme from "@nativescript/theme"
|
import Theme from "@nativescript/theme"
|
||||||
|
import ActionDialog from "./modal/ActionDialog.vue"
|
||||||
|
import ConfirmDialog from "./modal/ConfirmDialog.vue"
|
||||||
|
|
||||||
import { mapState, mapActions } from "vuex"
|
import { mapState, mapActions } from "vuex"
|
||||||
export default {
|
export default {
|
||||||
props: ["highlight", "viewIsScrolled", "showDrawer", "title"],
|
props: [
|
||||||
|
"highlight",
|
||||||
|
"viewIsScrolled",
|
||||||
|
"showDrawer",
|
||||||
|
"restartApp",
|
||||||
|
"hijackGlobalBackEvent",
|
||||||
|
"releaseGlobalBackEvent",
|
||||||
|
],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
interface: {
|
interface: {
|
||||||
|
@ -98,23 +107,44 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon"]),
|
...mapState(["icon", "currentComponent"]),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setCurrentComponent() {
|
||||||
|
this.$store.dispatch("setCurrentComponent", "Settings")
|
||||||
|
this.releaseGlobalBackEvent()
|
||||||
|
},
|
||||||
|
showDialog(args) {
|
||||||
|
this.highlight(args)
|
||||||
|
this.$showModal(ActionDialog)
|
||||||
|
},
|
||||||
selectThemes(args) {
|
selectThemes(args) {
|
||||||
this.highlight(args)
|
this.highlight(args)
|
||||||
let btn = args.object
|
this.$showModal(ActionDialog, {
|
||||||
Menu.popup({
|
props: {
|
||||||
view: btn,
|
title: "Theme",
|
||||||
actions: this.themesArray,
|
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) {
|
selectBackupDir(args) {
|
||||||
this.highlight(args)
|
this.highlight(args)
|
||||||
|
|
|
@ -1,41 +1,48 @@
|
||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page @loaded="setCurrentComponent">
|
||||||
<ActionBar margin="0" flat="true">
|
<ActionBar height="128" margin="0" flat="true">
|
||||||
<GridLayout
|
<GridLayout
|
||||||
rows="*"
|
rows="64, 64"
|
||||||
columns="auto, *, auto,auto"
|
columns="auto, *, auto,auto, auto"
|
||||||
class="actionBarContainer"
|
class="actionBarContainer"
|
||||||
>
|
>
|
||||||
<Label
|
<Label
|
||||||
|
row="0"
|
||||||
col="0"
|
col="0"
|
||||||
class="bx leftAction"
|
class="bx leftAction"
|
||||||
:text="icon.back"
|
:text="icon.back"
|
||||||
automationText="Back"
|
automationText="Back"
|
||||||
@tap="navigateBack"
|
@tap="$navigateBack()"
|
||||||
verticalAlignment="top"
|
|
||||||
/>
|
/>
|
||||||
<Label
|
<ScrollView
|
||||||
class="title orkm"
|
row="1"
|
||||||
:text="recipe.title"
|
|
||||||
lineHeight="4"
|
|
||||||
col="1"
|
col="1"
|
||||||
textWrap="true"
|
colSpan="3"
|
||||||
verticalAlignment="bottom"
|
orientation="horizontal"
|
||||||
/>
|
scrollBarIndicatorVisible="false"
|
||||||
<Label
|
>
|
||||||
col="2"
|
<Label
|
||||||
class="bx"
|
class="title orkm"
|
||||||
:text="icon.share"
|
:text="recipe.title"
|
||||||
@tap=""
|
verticalAlignment="bottom"
|
||||||
verticalAlignment="top"
|
/>
|
||||||
/>
|
</ScrollView>
|
||||||
|
<Label row="0" col="2" class="bx" :text="icon.share" @tap="" />
|
||||||
<Label
|
<Label
|
||||||
|
row="0"
|
||||||
col="3"
|
col="3"
|
||||||
class="bx"
|
class="bx"
|
||||||
:class="{ 'view-favorited': recipe.isFavorite }"
|
:class="{ 'view-favorited': recipe.isFavorite }"
|
||||||
:text="recipe.isFavorite ? icon.heart : icon.heartOutline"
|
:text="recipe.isFavorite ? icon.heart : icon.heartOutline"
|
||||||
@tap="toggleFavorite"
|
@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>
|
</GridLayout>
|
||||||
</ActionBar>
|
</ActionBar>
|
||||||
|
@ -43,7 +50,7 @@
|
||||||
<TabView androidElevation="0" width="100%" height="100%">
|
<TabView androidElevation="0" width="100%" height="100%">
|
||||||
<TabViewItem title="Overview">
|
<TabViewItem title="Overview">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<StackLayout class="">
|
<StackLayout>
|
||||||
<StackLayout
|
<StackLayout
|
||||||
width="100%"
|
width="100%"
|
||||||
:height="screenWidth"
|
:height="screenWidth"
|
||||||
|
@ -62,13 +69,13 @@
|
||||||
horizontalAlignment="center"
|
horizontalAlignment="center"
|
||||||
class="bx"
|
class="bx"
|
||||||
fontSize="160"
|
fontSize="160"
|
||||||
:text="icon.dish"
|
:text="icon.image"
|
||||||
/>
|
/>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
<StackLayout margin="16 16 128">
|
<StackLayout margin="16 16 144">
|
||||||
<Label class="view-cat orkm" :text="recipe.category" />
|
<Label class="view-cat orkm" :text="recipe.category" />
|
||||||
<Label
|
<Label
|
||||||
class="view-title p-b-8 orkm"
|
class="view-title orkm"
|
||||||
:text="recipe.title"
|
:text="recipe.title"
|
||||||
textWrap="true"
|
textWrap="true"
|
||||||
/>
|
/>
|
||||||
|
@ -88,9 +95,9 @@
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
<TabViewItem title="Ingredients" v-if="recipe.ingredients[0].item">
|
<TabViewItem title="Ingredients" v-if="recipe.ingredients.length">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<StackLayout padding="16 16 128">
|
<StackLayout padding="16 16 124">
|
||||||
<AbsoluteLayout class="inputField">
|
<AbsoluteLayout class="inputField">
|
||||||
<TextField
|
<TextField
|
||||||
width="50%"
|
width="50%"
|
||||||
|
@ -101,7 +108,7 @@
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
<StackLayout margin="24 0 8 0">
|
<StackLayout margin="24 0 8 0">
|
||||||
<Label
|
<Label
|
||||||
class="view-title p-b-8 orkm"
|
class="view-title orkm"
|
||||||
:text="
|
:text="
|
||||||
`Ingredients for ${portionScale}${
|
`Ingredients for ${portionScale}${
|
||||||
portionScale > 1
|
portionScale > 1
|
||||||
|
@ -128,9 +135,9 @@
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
<TabViewItem title="Instructions" v-if="recipe.instructions[0].length">
|
<TabViewItem title="Instructions" v-if="recipe.instructions.length">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<StackLayout padding="16 16 128">
|
<StackLayout padding="32 16 132">
|
||||||
<GridLayout
|
<GridLayout
|
||||||
columns="auto ,*"
|
columns="auto ,*"
|
||||||
v-for="(instruction, index) in recipe.instructions"
|
v-for="(instruction, index) in recipe.instructions"
|
||||||
|
@ -158,9 +165,9 @@
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
<TabViewItem title="Notes" v-if="recipe.notes[0].length">
|
<TabViewItem title="Notes" v-if="recipe.notes.length">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<StackLayout padding="16 16 128">
|
<StackLayout padding="32 16 132">
|
||||||
<GridLayout
|
<GridLayout
|
||||||
columns="auto ,*"
|
columns="auto ,*"
|
||||||
v-for="(note, index) in recipe.notes"
|
v-for="(note, index) in recipe.notes"
|
||||||
|
@ -184,9 +191,9 @@
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
</TabViewItem>
|
</TabViewItem>
|
||||||
<TabViewItem title="References" v-if="recipe.references[0].length">
|
<TabViewItem title="References" v-if="recipe.references.length">
|
||||||
<ScrollView scrollBarIndicatorVisible="false">
|
<ScrollView scrollBarIndicatorVisible="false">
|
||||||
<StackLayout padding="16 16 128">
|
<StackLayout padding="32 16 132">
|
||||||
<GridLayout
|
<GridLayout
|
||||||
columns="auto ,*"
|
columns="auto ,*"
|
||||||
v-for="(reference, index) in recipe.references"
|
v-for="(reference, index) in recipe.references"
|
||||||
|
@ -214,6 +221,7 @@
|
||||||
</TabView>
|
</TabView>
|
||||||
<GridLayout id="btnFabContainer" rows="*,88" columns="*,88">
|
<GridLayout id="btnFabContainer" rows="*,88" columns="*,88">
|
||||||
<Label
|
<Label
|
||||||
|
v-if="!busy"
|
||||||
row="1"
|
row="1"
|
||||||
col="1"
|
col="1"
|
||||||
class="bx btnFab"
|
class="bx btnFab"
|
||||||
|
@ -221,6 +229,7 @@
|
||||||
androidElevation="8"
|
androidElevation="8"
|
||||||
@tap="editRecipe"
|
@tap="editRecipe"
|
||||||
/>
|
/>
|
||||||
|
<ActivityIndicator v-else row="1" col="1" :busy="busy" />
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
</AbsoluteLayout>
|
</AbsoluteLayout>
|
||||||
</Page>
|
</Page>
|
||||||
|
@ -229,18 +238,26 @@
|
||||||
<script>
|
<script>
|
||||||
import { screen } from "tns-core-modules/platform"
|
import { screen } from "tns-core-modules/platform"
|
||||||
import * as utils from "tns-core-modules/utils/utils"
|
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"
|
import { mapState, mapActions } from "vuex"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ["recipe"],
|
props: ["recipeIndex", "hijackGlobalBackEvent", "releaseGlobalBackEvent"],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
busy: false,
|
||||||
portionScale: 1,
|
portionScale: 1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["icon", "recipes"]),
|
...mapState(["icon", "recipes"]),
|
||||||
|
recipe() {
|
||||||
|
return this.recipes[this.recipeIndex]
|
||||||
|
},
|
||||||
screenWidth() {
|
screenWidth() {
|
||||||
return screen.mainScreen.widthDIPs
|
return screen.mainScreen.widthDIPs
|
||||||
},
|
},
|
||||||
|
@ -254,18 +271,33 @@ export default {
|
||||||
roundedQuantity(quantity, unit) {
|
roundedQuantity(quantity, unit) {
|
||||||
return Math.round(quantity * this.isPortionScalePositive * 100) / 100
|
return Math.round(quantity * this.isPortionScalePositive * 100) / 100
|
||||||
},
|
},
|
||||||
// indexChange(args) {
|
|
||||||
// let newIndex = args.value
|
|
||||||
// console.log("Current tab index: " + newIndex)
|
|
||||||
// },
|
|
||||||
navigateBack() {
|
|
||||||
this.$navigateBack()
|
|
||||||
},
|
|
||||||
editRecipe() {
|
editRecipe() {
|
||||||
alert("edit recipe")
|
this.busy = true
|
||||||
|
this.$navigateTo(EditRecipe, {
|
||||||
|
transition: {
|
||||||
|
name: "slide",
|
||||||
|
duration: 250,
|
||||||
|
curve: "easeIn",
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
recipeIndex: this.recipeIndex,
|
||||||
|
},
|
||||||
|
// backstackVisible: false,
|
||||||
|
})
|
||||||
},
|
},
|
||||||
toggleFavorite() {
|
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) {
|
getTime(time) {
|
||||||
let t = time.split(":")
|
let t = time.split(":")
|
||||||
|
@ -276,14 +308,13 @@ export default {
|
||||||
openURL(args, url) {
|
openURL(args, url) {
|
||||||
utils.openUrl(url)
|
utils.openUrl(url)
|
||||||
},
|
},
|
||||||
|
setCurrentComponent() {
|
||||||
|
this.releaseGlobalBackEvent()
|
||||||
|
this.busy = false
|
||||||
|
setTimeout((e) => {
|
||||||
|
this.$store.dispatch("setCurrentComponent", "ViewRecipe")
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
|
||||||
ActionBar {
|
|
||||||
height: 128;
|
|
||||||
}
|
|
||||||
.actionBarContainer .bx {
|
|
||||||
margin-top: 4;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
64
app/components/modal/ActionDialog.vue
Normal 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>
|
45
app/components/modal/ConfirmDialog.vue
Normal 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>
|
49
app/components/modal/PromptDialog.vue
Normal 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>
|
54
app/main.js
|
@ -1,55 +1,25 @@
|
||||||
// import VueDevtools from "nativescript-vue-devtools"
|
|
||||||
import Vue from "nativescript-vue"
|
import Vue from "nativescript-vue"
|
||||||
import App from "./components/App"
|
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"
|
import store from "./store"
|
||||||
|
|
||||||
// Prints Vue logs when --env.production is *NOT* set while building
|
import RadListView from "nativescript-ui-listview/vue"
|
||||||
Vue.config.silent = TNS_ENV === "production"
|
Vue.use(RadListView)
|
||||||
|
|
||||||
|
import DateTimePicker from "nativescript-datetimepicker/vue"
|
||||||
|
Vue.use(DateTimePicker)
|
||||||
|
|
||||||
Vue.registerElement(
|
Vue.registerElement(
|
||||||
"RadSideDrawer",
|
"RadSideDrawer",
|
||||||
() => require("nativescript-ui-sidedrawer").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({
|
new Vue({
|
||||||
store,
|
store,
|
||||||
render: (h) => h("frame", [h(App)]),
|
render: (h) => h("frame", [h(App)]),
|
||||||
|
|
461
app/store.js
|
@ -6,188 +6,178 @@ Vue.use(Vuex)
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
recipes: [
|
recipes: [
|
||||||
{
|
// {
|
||||||
imageSrc: null,
|
// imageSrc: null,
|
||||||
title: "Mediterranean Salad",
|
// title: "Mediterranean Salad",
|
||||||
category: "Salads",
|
// category: "Salads",
|
||||||
prepTime: "00:10",
|
// prepTime: "12:25",
|
||||||
cookTime: "00:20",
|
// cookTime: "00:30",
|
||||||
portionSize: 1,
|
// portionSize: 1,
|
||||||
ingredients: [
|
// ingredients: [
|
||||||
{
|
// {
|
||||||
item: "Cucumbers, Seeded And Sliced",
|
// item: "Cucumbers, Seeded And Sliced",
|
||||||
quantity: 3,
|
// quantity: 3,
|
||||||
unit: null,
|
// unit: "unit",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Crumbled Feta Cheese",
|
// item: "Crumbled Feta Cheese",
|
||||||
quantity: 1.5,
|
// quantity: 1.5,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Black Olives, Pitted And Sliced",
|
// item: "Black Olives, Pitted And Sliced",
|
||||||
quantity: 1,
|
// quantity: 1,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Diced Roma Tomatoes",
|
// item: "Diced Roma Tomatoes",
|
||||||
quantity: 3,
|
// quantity: 3,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
|
// item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
|
||||||
quantity: 0.3,
|
// quantity: 0.3,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Onion, Sliced",
|
// item: "Onion, Sliced",
|
||||||
quantity: 1.5,
|
// quantity: 1.5,
|
||||||
unit: null,
|
// unit: "unit",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Cucumbers, Seeded And Sliced",
|
// item: "Cucumbers, Seeded And Sliced",
|
||||||
quantity: 3,
|
// quantity: 3,
|
||||||
unit: null,
|
// unit: "unit",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Crumbled Feta Cheese",
|
// item: "Crumbled Feta Cheese",
|
||||||
quantity: 1.5,
|
// quantity: 1.5,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Black Olives, Pitted And Sliced",
|
// item: "Black Olives, Pitted And Sliced",
|
||||||
quantity: 1,
|
// quantity: 1,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Diced Roma Tomatoes",
|
// item: "Diced Roma Tomatoes",
|
||||||
quantity: 3,
|
// quantity: 3,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
|
// item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
|
||||||
quantity: 0.3,
|
// quantity: 0.3,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Onion, Sliced",
|
// item: "Onion, Sliced",
|
||||||
quantity: 1.5,
|
// quantity: 1.5,
|
||||||
unit: null,
|
// unit: "unit",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Cucumbers, Seeded And Sliced",
|
// item: "Cucumbers, Seeded And Sliced",
|
||||||
quantity: 3,
|
// quantity: 3,
|
||||||
unit: null,
|
// unit: "unit",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Crumbled Feta Cheese",
|
// item: "Crumbled Feta Cheese",
|
||||||
quantity: 1.5,
|
// quantity: 1.5,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Black Olives, Pitted And Sliced",
|
// item: "Black Olives, Pitted And Sliced",
|
||||||
quantity: 1,
|
// quantity: 1,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Diced Roma Tomatoes",
|
// item: "Diced Roma Tomatoes",
|
||||||
quantity: 3,
|
// quantity: 3,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
|
// item: "Diced Oil Packed Sun Dried Tomatoes, Drained, Oil Reserved",
|
||||||
quantity: 0.3,
|
// quantity: 0.3,
|
||||||
unit: "cup",
|
// unit: "cup",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
item: "Onion, Sliced",
|
// item: "Onion, Sliced",
|
||||||
quantity: 1.5,
|
// quantity: 1.5,
|
||||||
unit: null,
|
// unit: "unit",
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
instructions: [
|
// 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.",
|
// "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. 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. 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.",
|
||||||
"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.",
|
||||||
"Chill until serving.",
|
// "Chill until serving.",
|
||||||
"Chill until serving.",
|
// "Chill until serving.",
|
||||||
"Chill until serving.",
|
// "Chill until serving.",
|
||||||
"Chill until serving.",
|
// "Chill until serving.",
|
||||||
],
|
// ],
|
||||||
notes: [
|
// 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.",
|
// "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: [
|
// 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/",
|
||||||
"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,
|
// isFavorite: true,
|
||||||
},
|
// tried: false,
|
||||||
{
|
// lastModified: "2020-10-18T17:37:51.798Z",
|
||||||
imageSrc: null,
|
// },
|
||||||
title: "Fresh Tomato Sauce",
|
// {
|
||||||
category: "Sauces",
|
// imageSrc: null,
|
||||||
prepTime: "00:20",
|
// title: "Fresh Tomato Sauce",
|
||||||
cookTime: "00:25",
|
// category: "Sauces",
|
||||||
portionSize: 1,
|
// prepTime: "00:45",
|
||||||
ingredients: [
|
// cookTime: "00:35",
|
||||||
{
|
// portionSize: 1,
|
||||||
item: null,
|
// ingredients: [],
|
||||||
quantity: null,
|
// instructions: [],
|
||||||
unit: null,
|
// notes: [],
|
||||||
},
|
// references: [],
|
||||||
],
|
// isFavorite: true,
|
||||||
instructions: [""],
|
// tried: true,
|
||||||
notes: [""],
|
// lastModified: "2020-10-15T17:37:51.798Z",
|
||||||
references: [""],
|
// },
|
||||||
isFavorite: true,
|
// {
|
||||||
},
|
// imageSrc: null,
|
||||||
{
|
// title: "Creamy Mushroom Herb Pasta",
|
||||||
imageSrc: null,
|
// category: "Lunch",
|
||||||
title: "Creamy Mushroom Herb Pasta",
|
// prepTime: "00:10",
|
||||||
category: "Lunch",
|
// cookTime: "00:15",
|
||||||
prepTime: "00:45",
|
// portionSize: 1,
|
||||||
cookTime: "00:25",
|
// ingredients: [],
|
||||||
portionSize: 1,
|
// instructions: [],
|
||||||
ingredients: [
|
// notes: [],
|
||||||
{
|
// references: [],
|
||||||
item: null,
|
// isFavorite: false,
|
||||||
quantity: null,
|
// tried: false,
|
||||||
unit: null,
|
// lastModified: "2020-10-12T17:37:51.798Z",
|
||||||
},
|
// },
|
||||||
],
|
// {
|
||||||
instructions: [""],
|
// imageSrc: null,
|
||||||
notes: [""],
|
// title: "Grilled Cheese Sandwich",
|
||||||
references: [""],
|
// category: "Lunch",
|
||||||
isFavorite: false,
|
// prepTime: "00:50",
|
||||||
},
|
// cookTime: "00:12",
|
||||||
{
|
// portionSize: 1,
|
||||||
imageSrc: null,
|
// ingredients: [],
|
||||||
title: "Grilled Cheese Sandwich",
|
// instructions: [],
|
||||||
category: "Lunch",
|
// notes: [],
|
||||||
prepTime: "00:20",
|
// references: [],
|
||||||
cookTime: "00:10",
|
// isFavorite: false,
|
||||||
portionSize: 1,
|
// tried: true,
|
||||||
ingredients: [
|
// lastModified: "2020-10-03T17:37:51.798Z",
|
||||||
{
|
// },
|
||||||
item: null,
|
|
||||||
quantity: null,
|
|
||||||
unit: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
instructions: [""],
|
|
||||||
notes: [""],
|
|
||||||
references: [""],
|
|
||||||
isFavorite: false,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
viewIsScrolled: false,
|
viewIsScrolled: false,
|
||||||
icon: {
|
icon: {
|
||||||
|
@ -202,7 +192,7 @@ export default new Vuex.Store({
|
||||||
sort: "\ueb2b",
|
sort: "\ueb2b",
|
||||||
plus: "\ueb89",
|
plus: "\ueb89",
|
||||||
close: "\uec4e",
|
close: "\uec4e",
|
||||||
dish: "\uea71",
|
image: "\ueae9",
|
||||||
back: "\ue988",
|
back: "\ue988",
|
||||||
save: "\uee48",
|
save: "\uee48",
|
||||||
camera: "\uecc2",
|
camera: "\uecc2",
|
||||||
|
@ -216,22 +206,127 @@ export default new Vuex.Store({
|
||||||
file: "\ued60",
|
file: "\ued60",
|
||||||
user: "\uee8e",
|
user: "\uee8e",
|
||||||
trash: "\uee83",
|
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: {
|
mutations: {
|
||||||
addRecipe(state, recipe) {
|
addRecipe(state, recipe) {
|
||||||
state.recipes.push(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) {
|
toggleFavorite(state, index) {
|
||||||
state.recipes[index].isFavorite = !state.recipes[index].isFavorite
|
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: {
|
actions: {
|
||||||
addRecipe({ commit }, recipe) {
|
addRecipe({ commit }, recipe) {
|
||||||
commit("addRecipe", 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) {
|
toggleFavorite({ commit }, index) {
|
||||||
commit("toggleFavorite", 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
|
@ -19,20 +19,15 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nativescript/theme": "^2.2.1",
|
"@nativescript/theme": "^2.2.1",
|
||||||
"@nstudio/nativescript-checkbox": "^1.0.0",
|
|
||||||
"@vue/devtools": "^5.3.3",
|
|
||||||
"nativescript-camera": "^4.5.0",
|
"nativescript-camera": "^4.5.0",
|
||||||
|
"nativescript-couchbase-plugin": "^0.9.6",
|
||||||
"nativescript-datetimepicker": "^1.2.3",
|
"nativescript-datetimepicker": "^1.2.3",
|
||||||
"nativescript-fonticon": "^2.0.2",
|
|
||||||
"nativescript-mediafilepicker": "^4.0.0",
|
"nativescript-mediafilepicker": "^4.0.0",
|
||||||
"nativescript-menu": "^1.1.6",
|
|
||||||
"nativescript-permissions": "^1.3.9",
|
"nativescript-permissions": "^1.3.9",
|
||||||
"nativescript-socketio": "^3.3.1",
|
"nativescript-toast": "^2.0.0",
|
||||||
"nativescript-toasty": "^3.0.0-alpha.2",
|
|
||||||
"nativescript-ui-listview": "^8.2.0",
|
"nativescript-ui-listview": "^8.2.0",
|
||||||
"nativescript-ui-sidedrawer": "^8.0.1",
|
"nativescript-ui-sidedrawer": "^8.0.1",
|
||||||
"nativescript-vue": "^2.6.1",
|
"nativescript-vue": "^2.6.1",
|
||||||
"nativescript-vue-devtools": "^1.4.0",
|
|
||||||
"tns-core-modules": "^6.5.1",
|
"tns-core-modules": "^6.5.1",
|
||||||
"vuex": "^3.3.0"
|
"vuex": "^3.3.0"
|
||||||
},
|
},
|
||||||
|
|