enrecipes/app/store.ts
2021-06-18 21:52:03 +05:30

1263 lines
32 KiB
TypeScript

import Vue from 'nativescript-vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import {
getFileAccess,
File,
Application,
knownFolders,
path,
} from '@nativescript/core'
import {
getNumber,
setNumber,
getString,
setString,
} from '@nativescript/core/application-settings'
import { openOrCreate } from '@akylas/nativescript-sqlite'
import * as utils from '~/shared/utils'
// OpenDatabaseFile
const db = openOrCreate(
path.join(knownFolders.documents().path, 'EnRecipes.db')
)
// Create"recipes"Table
db.execute(
'CREATE TABLE IF NOT EXISTS recipes (id TEXT PRIMARY KEY, image TEXT, title TEXT, cuisine TEXT, category TEXT, tags TEXT, prepTime TEXT, cookTime TEXT, yieldQuantity TEXT, yieldUnit TEXT, difficulty TEXT, rating INT, ingredients TEXT, instructions TEXT, combinations TEXT, notes TEXT, favorite INT, tried INT, lastTried INT, lastModified INT, created INT)'
)
// Create"lists"Table
db.execute(
'CREATE TABLE IF NOT EXISTS lists (cuisines TEXT, categories TEXT, yieldUnits TEXT, units TEXT)'
)
// Create"mealPlans"Table
db.execute(
'CREATE TABLE IF NOT EXISTS mealPlans (id TEXT PRIMARY KEY, date INT, mealType TEXT, recipeID TEXT, quantity INT, note TEXT)'
)
// Create"timerPresets"Table
db.execute(
'CREATE TABLE IF NOT EXISTS timerPresets (id INT PRIMARY KEY, label TEXT, time TEXT)'
)
const defCuisines = [
'American',
'Brazilian',
'British',
'Chinese',
'Danish',
'Egyptian',
'Filipino',
'French',
'German',
'Greek',
'Indian',
'Irish',
'Italian',
'Jamaican',
'Japanese',
'Jewish',
'Kenyan',
'Korean',
'Mexican',
'Nigerian',
'Portuguese',
'Russian',
'Scottish',
'Spanish',
'Sri Lankan',
'Swedish',
'Thai',
'Turkish',
'Vietnamese',
]
const defCategories = [
'Appetizers',
'Barbecue',
'Beverages',
'Breads',
'breakfast',
'Desserts',
'dinner',
'Healthy',
'lunch',
'Main dishes',
'Meat',
'Noodles',
'Pasta',
'Poultry',
'Rice',
'Salads',
'Sauces',
'Seafood',
'Side dishes',
'snacks',
'Soups',
'Undefined',
'Vegan',
'Vegetarian',
]
const defYieldUnits = [
'Serving',
'Piece',
'Teaspoon',
'Tablespoon',
'Fluid Ounce',
'Ounce',
'Pound',
'Gram',
'Kilogram',
'Cup',
'Gallon',
'Millilitre',
'Litre',
'Roll',
'Patty',
'Loaf',
]
const defUnits = [
'unit',
'tsp',
'dsp',
'tbsp',
'fl oz',
'cup',
'pt',
'qt',
'gal',
'ml',
'l',
'oz',
'lb',
'mg',
'g',
'kg',
'cm',
'in',
'leaf',
'clove',
'piece',
'pinch',
'drop',
'dozen',
'stick',
'small',
'medium',
'large',
]
const listItems = {
cuisines: {
sort: 1,
defs: defCuisines,
},
categories: {
sort: 1,
defs: defCategories,
},
yieldUnits: {
sort: 0,
defs: defYieldUnits,
},
units: {
sort: 0,
defs: defUnits,
},
}
interface IRecipe {
id: string
image: string
title: string
cuisine: string
category: string
tags: string[]
prepTime: string
cookTime: string
yieldQuantity: number
yieldUnit: string
difficulty: string
rating: number
ingredients: string[]
instructions: string[]
combinations: string[]
notes: string[]
favorite: 0 | 1
tried: 0 | 1
lastTried: number | null
lastModified: number | null
created: number | null
}
interface IMealPlan {
id: string
date: number
mealType: string
recipeID: string
quantity: number
note: string
}
interface IMealPlanOld {
title: string
startDate: number
type: string
eventColor: string
}
export default new Vuex.Store({
state: {
recipes: [],
cuisines: [],
categories: [],
yieldUnits: [],
units: [],
mealPlans: [],
icon: {
cog: '\ue900',
home: '\ue901',
try: '\ue902',
tried: '\ue903',
fav: '\ue904',
faved: '\ue905',
menu: '\ue906',
cuisine: '\ue907',
category: '\ue908',
tag: '\ue909',
star: '\ue90a',
starred: '\ue90b',
time: '\ue90c',
diff: '\ue90d',
bag: '\ue90e',
bagged: '\ue90f',
price: '\ue910',
sear: '\ue911',
sort: '\ue912',
filter: '\ue913',
plus: '\ue914',
done: '\ue915',
back: '\ue916',
x: '\ue917',
del: '\ue918',
save: '\ue919',
undo: '\ue91a',
edit: '\ue91b',
cal: '\ue91c',
tod: '\ue91d',
left: '\ue91e',
right: '\ue91f',
img: '\ue920',
uncheck: '\ue921',
check: '\ue922',
share: '\ue923',
timer: '\ue924',
start: '\ue925',
pause: '\ue926',
addTo: '\ue927',
sound: '\ue928',
vibrate: '\ue929',
interface: '\ue92a',
opts: '\ue92b',
db: '\ue92c',
reset: '\ue92d',
info: '\ue92e',
lang: '\ue92f',
theme: '\ue930',
layout: '\ue931',
shuf: '\ue932',
week: '\ue933',
folder: '\ue934',
exp: '\ue935',
imp: '\ue936',
gh: '\ue937',
tg: '\ue938',
help: '\ue939',
priv: '\ue93a',
don: '\ue93b',
trans: '\ue93c',
delay: '\ue93d',
ring: '\ue93e',
print: '\ue93f',
dup: '\ue940',
calv: '\ue941',
mpd: '\ue942',
madd: '\ue943',
awake: '\ue944',
edge: '\ue945',
},
sortT: 'random', // SortType
langs: [
{
locale: 'ar',
title: 'العربية',
rtl: 1,
},
{
locale: 'da',
title: 'Dansk',
},
{
locale: 'de',
title: 'Deutsch',
},
{
locale: 'en-IN',
title: 'English (India)',
},
{
locale: 'en-GB',
title: 'English (United Kingdom)',
},
{
locale: 'en-US',
title: 'English (United States)',
},
{
locale: 'es',
title: 'Español',
},
{
locale: 'fr',
title: 'Français',
},
{
locale: 'fr-BE',
title: 'Français (Belgium)',
},
{
locale: 'fr-CA',
title: 'Français (Canada)',
},
{
locale: 'fr-CH',
title: 'Français (Switzerland)',
},
{
locale: 'hi',
title: 'हिंदी',
},
{
locale: 'id',
title: 'Indonesia',
},
{
locale: 'it',
title: 'Italiano',
},
{
locale: 'ja',
title: '日本語',
},
{
locale: 'ml',
title: 'മലയാളം',
},
{
locale: 'nb-NO',
title: 'Norsk bokmål',
},
{
locale: 'nl',
title: 'Nederlands',
},
{
locale: 'pt',
title: 'Português',
},
{
locale: 'pt-BR',
title: 'Português (Brazil)',
},
{
locale: 'ru',
title: 'Русский',
},
{
locale: 'ta',
title: 'தமிழ்',
},
{
locale: 'te',
title: 'తెలుగు',
},
],
shake: getNumber('shake', 1), // ShakeViewRandomRecipe
impSum: {
// ImportSummary
found: 0,
imported: 0,
updated: 0,
},
layout: getString('layout', 'detailed'),
selCuisine: null, // SelectedCuisine
selCategory: null, // SelectedCategory
selTag: null, // SelectedTag
theme: 'sysDef',
startMon: getNumber('startMon', 0), // StartWithMonday
timerD: getNumber('timerD', 1), // TimerDelay
timerS: {}, // TimerSound
timerV: getNumber('timerV', 0), // TimerVibrate
timerPs: [], // TimerPresets
activeTs: [], // ActiveTimers
FGS: 0, // ForeGroundService
RTL: getNumber('RTL', 0),
plannerV: getString('plannerV', 'wk'), // PlannerViewMode
planDel: getString('planDel', 'nvr'), // PlanDeletionCriteria
edgeS: getNumber('edgeS', 1), // EdgeSwipe
awakeV: getNumber('awakeV', 1), // AwakeViewer
},
mutations: {
// ToggleKeepAwakeOnRecipeViewer
toggleAwakeV(state) {
state.awakeV = +!state.awakeV
setNumber('awakeV', state.awakeV)
},
// ToggleEdgeSwipe
toggleEdgeS(state) {
state.edgeS = +!state.edgeS
setNumber('edgeS', state.edgeS)
},
// SetPlanDeletionCriteria
setPlanDel(state, s: string) {
state.planDel = s
setString('planDel', s)
},
// SetPlannerViewMode
setPlannerV(state, s: string) {
state.plannerV = s
setString('plannerV', s)
},
// SetRTLLayout
setRTL(state) {
state.RTL = getNumber('RTL', 0)
},
// SetForegroundService
setFgS(state, n: number) {
state.FGS = n
},
// AddTimerPreset
addTP(state, o) {
let i = state.timerPs.findIndex((e) => e.id == o.id)
if (state.timerPs.some((e) => e.id == o.id)) {
state.timerPs.splice(i, 1, o)
} else state.timerPs.push(o)
db.execute(
`REPLACE INTO timerPresets (id, label, time) VALUES (?, ?, ?)`,
[o.id, o.label, o.time]
)
},
// DeleteTimerPreset
deleteTP(state, n: number) {
let id = state.timerPs[n]
state.timerPs.splice(n, 1)
db.execute(`DELETE FROM timerPresets WHERE id = ${id}`)
},
// InitialiseTimerPreset
initTPs(state) {
if (!state.timerPs.length)
db.select(`SELECT * FROM timerPresets`).then((res) => {
res.forEach((t) => {
t.recipeID = 0
t.timerInt = 0
t.isPaused = 0
t.preset = 1
t.done = 0
state.timerPs.push(t)
})
})
},
// ImportTimerPresets
importTPs(state, ao) {
let newPresets = ao.filter(
(e) => !state.timerPs.some((f) => f.id === e.id)
)
newPresets.forEach((t) => {
db.execute(
`INSERT INTO timerPresets (id, label, time) VALUES (?, ?, ?)`,
[t.id, t.label, t.time]
)
state.timerPs.push(t)
})
},
// ClearActiveTimerInterval
clearATIs(state) {
state.activeTs.forEach((e) => {
clearInterval(e.timerInt)
e.timerInt = 0
})
},
// AddActiveTimer
addAT(state, { timer, i }) {
state.activeTs.splice(i, 0, timer)
},
// SortActiveTimers
sortATs(state) {
let a = state.activeTs.reduce((acc, e) => {
;(acc[e.recipeID] = acc[e.recipeID] || []).push(e)
return acc
}, {})
state.activeTs = [...(<any>Object).values(a).flat(2)]
},
// UpdateActiveTimer
updateAT(state, o) {
let i = state.activeTs.findIndex((e) => e.id == o.id)
state.activeTs.splice(i, 1, o)
},
// RemoveActiveTimer
removeAT(state, n: number) {
state.activeTs.splice(n, 1)
},
// SetTimerDelay
setTD(state, n: number) {
state.timerD = n
setNumber('timerD', n)
},
// SetTimerSound
setTS(state, s: string) {
state.timerS = s
setString('timerS', JSON.stringify(s))
},
// SetTimerVibrate
setTV(state, n: number) {
state.timerV = n
setNumber('timerV', n)
},
// ClearImportSummary
clearIS(state) {
for (const key in state.impSum) state.impSum[key] = 0
},
// SetFirstDayMonday
setFD(state, n: number) {
state.startMon = n
setNumber('startMon', n)
},
// SetTheme
setT(state, s: string) {
switch (s) {
case 'sysDef':
state.theme =
Application.systemAppearance() == 'dark' ? 'Dark' : 'Light'
break
case 'sysDefB':
state.theme =
Application.systemAppearance() == 'dark' ? 'Black' : 'Light'
break
default:
state.theme = s
break
}
setString('theme', s)
},
// ClearFilter
clearF(state) {
state.selCuisine = state.selCategory = state.selTag = null
},
// SetLayout
setL(state, s: string) {
state.layout = s
setString('layout', s)
},
// SetSortType
setST(state, s: string) {
state.sortT = s
},
// InitialiseRecipes
initRs(state) {
if (!state.recipes.length) {
db.select('SELECT * FROM recipes').then((res) => {
res.forEach((e) => {
Object.keys(e).forEach(
(f) =>
f.match(/tags|ingredients|instructions|combinations|notes/) &&
(e[f] = JSON.parse(e[f]))
)
state.recipes.push(e)
})
})
}
state.shake = getNumber('shake', 1)
state.sortT = getString('sortT', 'random')
},
// ImportRecipesFromJSON
importRsJSON(state, ao) {
let localRecipesIDs, partition
let imported = 0
let updated = 0
function getUpdatedData(data) {
return data.map((recipe) => {
let r = Object.assign({}, recipe)
if (r.timeRequired) {
r.prepTime = '00:00'
r.cookTime = r.timeRequired
delete r.timeRequired
}
if (r.imageSrc) {
r.image = r.imageSrc.replace('enrecipes', 'EnRecipes')
delete r.imageSrc
}
if (!r.hasOwnProperty('cuisine')) r.cuisine = 'Undefined'
if (!r.hasOwnProperty('tags')) r.tags = []
if (!r.hasOwnProperty('difficulty')) r.difficulty = 'Easy'
if (!r.hasOwnProperty('rating')) r.rating = 0
if (!r.hasOwnProperty('created')) r.created = r.lastModified
r.yieldQuantity = r.yield.quantity
r.yieldUnit = r.yield.unit
delete r.yield
function getTime(d) {
return new Date(d).getTime()
}
r.lastTried = getTime(r.lastTried)
r.lastModified = getTime(r.lastModified)
r.created = getTime(r.created)
r.favorite = r.favorite | 0
r.tried = r.tried | 0
return r
})
}
function createDocuments(data) {
data = getUpdatedData(data)
state.recipes = [...state.recipes, ...data]
data.forEach((r) => {
imported++
db.execute(
`INSERT INTO recipes (id, image, title, cuisine, category, tags, prepTime, cookTime, yieldQuantity, yieldUnit, difficulty, rating, ingredients, instructions, combinations, notes, favorite, tried, lastTried, lastModified, created) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
r.id,
r.image,
r.title,
r.cuisine,
r.category,
JSON.stringify(r.tags),
r.prepTime,
r.cookTime,
r.yieldQuantity,
r.yieldUnit,
r.difficulty,
r.rating,
JSON.stringify(r.ingredients),
JSON.stringify(r.instructions),
JSON.stringify(r.combinations),
JSON.stringify(r.notes),
r.favorite,
r.tried,
r.lastTried,
r.lastModified,
r.created,
]
)
})
}
function updateDocuments(data) {
data = getUpdatedData(data)
data.forEach((r) => {
let recipeIndex = state.recipes
.map((e, i) => {
let d1 = new Date(e.lastModified).getTime()
let d2 = new Date(r.lastModified).getTime()
return e.id === r.id && d1 < d2 ? i : -1
})
.filter((e) => e >= 0)[0]
if (recipeIndex >= 0) {
updated++
Object.assign(state.recipes[recipeIndex], r)
db.execute(
`REPLACE INTO recipes (id, image, title, cuisine, category, tags, prepTime, cookTime, yieldQuantity, yieldUnit, difficulty, rating, ingredients, instructions, combinations, notes, favorite, tried, lastTried, lastModified, created) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
r.id,
r.image,
r.title,
r.cuisine,
r.category,
JSON.stringify(r.tags),
r.prepTime,
r.cookTime,
r.yieldQuantity,
r.yieldUnit,
r.difficulty,
r.rating,
JSON.stringify(r.ingredients),
JSON.stringify(r.instructions),
JSON.stringify(r.combinations),
JSON.stringify(r.notes),
r.favorite,
r.tried,
r.lastTried,
r.lastModified,
r.created,
]
)
}
})
}
if (state.recipes.length) {
localRecipesIDs = state.recipes.map((e) => e.id)
partition = ao.reduce(
(result, recipe) => {
localRecipesIDs.indexOf(recipe.id) < 0
? result[0].push(recipe) // create candidates
: result[1].push(recipe) // update candidates
return result
},
[[], []]
)
if (partition[0].length) createDocuments(partition[0])
if (partition[1].length) updateDocuments(partition[1])
} else {
createDocuments(ao)
}
state.impSum.found = ao.length
state.impSum.imported = imported
state.impSum.updated = updated
},
// ImportRecipesFromDB
importRsDB(state, ao) {
let localRecipesIDs: string[], partition: any[]
let imported = 0
let updated = 0
function createDocuments(data: any[]) {
data.forEach((r) => {
const cols = Object.keys(r).join(', ')
const placeholder = Object.keys(r)
.fill('?')
.join(', ')
imported++
db.execute(
`REPLACE INTO recipes (${cols}) VALUES (${placeholder})`,
Object.values(r)
)
Object.keys(r).forEach(
(f) =>
f.match(/tags|ingredients|instructions|combinations|notes/) &&
(r[f] = JSON.parse(r[f]))
)
state.recipes.push(r)
})
}
function updateDocuments(data: any[]) {
data.forEach((r) => {
let recipeIndex = state.recipes
.map((e, i) => {
let d1 = new Date(e.lastModified).getTime()
let d2 = new Date(r.lastModified).getTime()
return e.id === r.id && d1 < d2 ? i : -1
})
.filter((e) => e >= 0)[0]
if (recipeIndex >= 0) {
updated++
const cols = Object.keys(r).join(', ')
const placeholder = Object.keys(r)
.fill('?')
.join(', ')
db.execute(
`REPLACE INTO recipes (${cols}) VALUES (${placeholder})`,
Object.values(r)
)
Object.keys(r).forEach(
(f) =>
f.match(/tags|ingredients|instructions|combinations|notes/) &&
(r[f] = JSON.parse(r[f]))
)
Object.assign(state.recipes[recipeIndex], r)
}
})
}
if (state.recipes.length) {
localRecipesIDs = state.recipes.map((e) => e.id)
partition = ao.reduce(
(result, recipe) => {
localRecipesIDs.indexOf(recipe.id) < 0
? result[0].push(recipe) // create candidates
: result[1].push(recipe) // update candidates
return result
},
[[], []]
)
if (partition[0].length) createDocuments(partition[0])
if (partition[1].length) updateDocuments(partition[1])
} else createDocuments(ao)
state.impSum.found = ao.length
state.impSum.imported = imported
state.impSum.updated = updated
},
// AddRecipe
addR(state, o: IRecipe) {
let r = JSON.parse(JSON.stringify(o))
Object.keys(o).forEach((e) => {
if (e.match(/tags|ingredients|instructions|combinations|notes/))
r[e] = JSON.stringify(r[e])
if (e.match(/favorite|tried/)) r[e] = r[e] ? 1 : 0
})
const cols = Object.keys(o).join(', ')
const placeholder = Object.keys(o)
.fill('?')
.join(', ')
db.execute(
`REPLACE INTO recipes (${cols}) VALUES (${placeholder})`,
Object.values(r)
)
let i: number
function exist({ id }, index: number) {
if (id === o.id) {
i = index
return 1
}
return 0
}
state.recipes.some(exist)
? Object.assign(state.recipes[i], o)
: state.recipes.push(o)
},
// DeleteRecipes
deleteRs(state, a) {
a.forEach((id: string) => {
let i = state.recipes.findIndex((e) => e.id === id)
getFileAccess().deleteFile(state.recipes[i].image)
state.recipes.splice(i, 1)
db.execute(`DELETE FROM recipes WHERE id = '${id}'`)
state.recipes.forEach((e, i) => {
if (e.combinations.includes(id)) {
state.recipes[i].combinations.splice(e.combinations.indexOf(id), 1)
db.execute(
`UPDATE recipes SET combinations = '${JSON.stringify(
state.recipes[i].combinations
)}' WHERE id = '${id}'`
)
}
})
})
},
// InitialiseListItems
initLIs(state) {
if (!state.cuisines.length) {
db.select(`SELECT * FROM lists`).then((res) => {
if (!res.length) {
db.execute(
`INSERT INTO lists (cuisines, categories, yieldUnits, units) VALUES (?, ?, ?, ?)`,
[null, null, null, null]
)
}
db.select(`SELECT * FROM lists`).then((res) => {
Object.keys(res[0]).forEach((list) => {
let userItems: string[]
let defs = listItems[list].defs
if (res[0][list]) {
userItems = JSON.parse(res[0][list])
state[list] = userItems.some((e: string) => defs.includes(e))
? userItems
: [...defs, ...userItems]
} else {
state[list] = defs
listItems[list].sort && state[list].sort()
}
})
})
})
}
},
// ImportListItems
importLIs(state, { data, listName }) {
state[listName] = [...new Set([...state[listName], ...data])]
if (listItems[listName].sort) state[listName].sort()
db.execute(
`UPDATE lists SET ${listName} = '${JSON.stringify(state[listName])}'`
)
},
// AddListItem
addLI(state, { item, listName }) {
let lowercase = state[listName].map((e: string) => e.toLowerCase())
if (lowercase.indexOf(item.toLowerCase()) == -1) {
state[listName].push(item)
if (listItems[listName].sort)
state[listName].sort((a: string, b: string) =>
a.toLowerCase().localeCompare(b.toLowerCase())
)
db.execute(
`UPDATE lists SET ${listName} = '${JSON.stringify(state[listName])}'`
)
}
},
// RemoveListItem
removeLI(state, { item, listName }) {
state[listName].splice(state[listName].indexOf(item), 1)
db.execute(
`UPDATE lists SET ${listName} = '${JSON.stringify(state[listName])}'`
)
},
// ResetListItems
resetLIs(state, listName) {
let defs = listItems[listName].defs
state[listName] = [...defs]
if (listItems[listName].sort)
state[listName].sort((a: string, b: string) =>
a.toLowerCase().localeCompare(b.toLowerCase())
)
db.execute(
`UPDATE lists SET ${listName} = '${JSON.stringify(state[listName])}'`
)
},
// InitialiseMealPlans
initMPs(state) {
if (!state.mealPlans.length) {
let c = state.planDel
let date = new Date()
let d = new Date()
d.setHours(0, 0, 0, 0)
let ld =
c == 'otay'
? 365
: c == 'otam'
? new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate()
: 7
d.setDate(d.getDate() - ld)
db.select(`SELECT * FROM mealPlans`).then((res) =>
res.forEach((p: any) =>
c !== 'nvr' && p.date < d.getTime()
? db.execute(`DELETE FROM mealPlans WHERE id = '${p.id}'`)
: state.mealPlans.push(p)
)
)
}
},
// ImportMealPlansFromJSON
importMPsJSON(state, ao) {
let updatedMealPlans = []
let newMealPlans = ao.filter((e) => {
if (e.hasOwnProperty('eventColor')) {
return !state.mealPlans.some((f) => {
let d = new Date(e.startDate)
let date = new Date(
d.getFullYear(),
d.getMonth(),
d.getDate(),
0
).getTime()
let type
switch (d.getHours()) {
case 0:
type = 'breakfast'
break
case 5:
type = 'lunch'
break
case 10:
type = 'dinner'
break
case 15:
type = 'snacks'
break
}
return f.recipeID == e.title && f.date == date && f.mealType == type
})
} else {
return !state.mealPlans.some(
(f) =>
f.recipeID == e.title && f.date == e.date && f.mealType == e.type
)
}
})
newMealPlans.forEach((p) => {
p.id = utils.getRandomID()
p.recipeID = p.title
p.quantity = 1
p.note = null
if (p.hasOwnProperty('eventColor')) {
let d = new Date(p.startDate)
p.date = new Date(
d.getFullYear(),
d.getMonth(),
d.getDate(),
0
).getTime()
switch (d.getHours()) {
case 0:
p.mealType = 'breakfast'
break
case 5:
p.mealType = 'lunch'
break
case 10:
p.mealType = 'dinner'
break
case 15:
p.mealType = 'snacks'
break
}
delete p.title
delete p.startDate
delete p.endDate
delete p.eventColor
} else {
p.mealType = p.type
delete p.type
delete p.title
}
updatedMealPlans.push(p)
})
state.mealPlans = [...state.mealPlans, ...updatedMealPlans]
updatedMealPlans.forEach((p) => {
db.execute(
`INSERT INTO mealPlans (id, date, mealType, recipeID, quantity, note) VALUES (?, ?, ?, ?, ?, ?)`,
[p.id, p.date, p.mealType, p.recipeID, p.quantity, p.note]
)
})
},
// ImportMealPlansFromDB
importMPsDB(state, ao: IMealPlan[]) {
let newMealPlans = ao.filter(
(e) =>
!state.mealPlans.some((f) =>
Object.keys(f).every((key) => f[key] == e[key])
)
)
state.mealPlans = [...state.mealPlans, ...newMealPlans]
newMealPlans.forEach((p) => {
db.execute(
`INSERT INTO mealPlans (id, date, mealType, recipeID, quantity, note) VALUES (?, ?, ?, ?, ?, ?)`,
[p.id, p.date, p.mealType, p.recipeID, p.quantity, p.note]
)
})
},
// AddMealPlan
addMP(
state,
{ plan, index, inDB }: { plan: IMealPlan; index: number; inDB: number }
) {
let mealPlan = {
id: plan.id,
date: plan.date,
mealType: plan.mealType,
recipeID: plan.recipeID,
quantity: plan.quantity,
note: plan.note,
}
if (inDB) {
const cols = Object.keys(mealPlan).join(', ')
const placeholder = Object.keys(mealPlan)
.fill('?')
.join(', ')
db.execute(
`REPLACE INTO mealPlans (${cols}) VALUES (${placeholder})`,
Object.values(mealPlan)
)
if (index === null) state.mealPlans.push(mealPlan)
} else {
state.mealPlans.splice(index, 0, mealPlan)
}
},
// DeleteMealPlan
deleteMP(
state,
{ id, index, inDB }: { id: string; index: number; inDB: number }
) {
if (inDB) {
db.execute(`DELETE FROM mealPlans WHERE id = '${id}'`)
} else {
state.mealPlans.splice(index, 1)
state.mealPlans = [...state.mealPlans]
}
},
toggleState(state, { id, key, setDate }) {
let i = state.recipes.findIndex((e) => e.id == id)
state.recipes[i][key] = state.recipes[i][key] ? 0 : 1
db.execute(
`UPDATE recipes SET ${key} = ${state.recipes[i][key]} WHERE id = '${id}'`
)
if (setDate) {
state.recipes[i].lastTried = new Date().getTime()
db.execute(
`UPDATE recipes SET lastTried = ${state.recipes[i].lastTried} WHERE id = '${id}'`
)
}
},
// UnLinkCombinations
unLinkCs(state, { id, a }) {
state.recipes.forEach((e, i) => {
if (a.includes(e.id)) {
state.recipes[i].combinations.splice(e.combinations.indexOf(id), 1)
db.execute(
`UPDATE recipes SET combinations = '${JSON.stringify(
state.recipes[i].combinations
)}' WHERE id = '${id}'`
)
}
})
},
// SetShake
setS(state, n: number) {
state.shake = n
setNumber('shake', n)
},
// SetRating
setR(state, { id, rating }) {
let i = state.recipes.findIndex((e) => e.id == id)
state.recipes[i].rating = rating
db.execute(`UPDATE recipes SET rating = ${rating} WHERE id = '${id}'`)
},
// UnLinkBrokenImages
unLinkBIs(state) {
state.recipes.forEach((r, i) => {
if (r.image && !File.exists(r.image)) {
r.image = null
Object.assign(state.recipes[i], r)
db.execute(`UPDATE recipes SET image = null WHERE id = '${r.id}'`)
}
})
},
setCuisine(state, s: string) {
state.selCuisine = s
},
setCategory(state, s: string) {
state.selCategory = s
},
setTag(state, s: string) {
state.selTag = s
},
},
actions: {
toggleAwakeV({ commit }) {
commit('toggleAwakeV')
},
toggleEdgeS({ commit }) {
commit('toggleEdgeS')
},
setPlanDel({ commit }, s: string) {
commit('setPlanDel', s)
},
setPlannerV({ commit }, s: string) {
commit('setPlannerV', s)
},
setRTL({ commit }) {
commit('setRTL')
},
sortATs({ commit }) {
commit('sortATs')
},
setFgS({ commit }, n: number) {
commit('setFgS', n)
},
addTP({ commit }, o) {
commit('addTP', o)
},
deleteTP({ commit }, o) {
commit('deleteTP', o)
},
initTPs({ commit }) {
commit('initTPs')
},
importTPs({ commit }, ao) {
commit('importTPs', ao)
},
clearATIs({ commit }) {
commit('clearATIs')
},
addAT({ commit }, o) {
commit('addAT', o)
},
updateAT({ commit }, o) {
commit('updateAT', o)
},
removeAT({ commit }, n: number) {
commit('removeAT', n)
},
setTD({ commit }, n: number) {
commit('setTD', n)
},
setTS({ commit }, s: string) {
commit('setTS', s)
},
setTV({ commit }, n: number) {
commit('setTV', n)
},
clearIS({ commit }) {
commit('clearIS')
},
setFD({ commit }, n: number) {
commit('setFD', n)
},
setT({ commit }, s: string) {
commit('setT', s)
},
clearF({ commit }) {
commit('clearF')
},
setL({ commit }, s: string) {
commit('setL', s)
},
setST({ commit }, s: string) {
commit('setST', s)
},
initRs({ commit }) {
commit('initRs')
},
importRsJSON({ commit }, ao) {
commit('importRsJSON', ao)
},
importRsDB({ commit }, ao) {
commit('importRsDB', ao)
},
addR({ commit }, o) {
commit('addR', o)
},
deleteRs({ commit }, a) {
commit('deleteRs', a)
},
initLIs({ commit }) {
commit('initLIs')
},
importLIs({ commit }, ao) {
commit('importLIs', ao)
},
addLI({ commit }, s: string) {
commit('addLI', s)
},
removeLI({ commit }, s: string) {
commit('removeLI', s)
},
resetLIs({ commit }, s: string) {
commit('resetLIs', s)
},
initMPs({ commit }) {
commit('initMPs')
},
importMPsJSON({ commit }, ao) {
commit('importMPsJSON', ao)
},
importMPsDB({ commit }, ao) {
commit('importMPsDB', ao)
},
addMP({ commit }, o) {
commit('addMP', o)
},
deleteMP({ commit }, o) {
commit('deleteMP', o)
},
toggleState({ commit }, o) {
commit('toggleState', o)
},
unLinkCs({ commit }, a) {
commit('unLinkCs', a)
},
setS({ commit }, n: number) {
commit('setS', n)
},
setR({ commit }, n: number) {
commit('setR', n)
},
unLinkBIs({ commit }) {
commit('unLinkBIs')
},
setCuisine({ commit }, s: string) {
commit('setCuisine', s)
},
setCategory({ commit }, s: string) {
commit('setCategory', s)
},
setTag({ commit }, s: string) {
commit('setTag', s)
},
},
})