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', more: '\ue946', less: '\ue947', }, 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 = [...(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, combs }) { state.recipes.forEach((e, i) => { if (combs.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, r }) { let i = state.recipes.findIndex((e) => e.id == id) state.recipes[i].rating = r db.execute(`UPDATE recipes SET rating = ${r} 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) }, }, })