diff --git a/.erb/configs/webpack.config.renderer.web.ts b/.erb/configs/webpack.config.renderer.web.ts index 0253921..9dca212 100644 --- a/.erb/configs/webpack.config.renderer.web.ts +++ b/.erb/configs/webpack.config.renderer.web.ts @@ -10,7 +10,7 @@ import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; import { merge } from 'webpack-merge'; import TerserPlugin from 'terser-webpack-plugin'; -import CopyPlugin from 'copy-webpack-plugin' +import CopyPlugin from 'copy-webpack-plugin'; import baseConfig from './webpack.config.base'; import webpackPaths from './webpack.paths'; import checkNodeEnv from '../scripts/check-node-env'; diff --git a/.eslintrc.js b/.eslintrc.js index 9f98c6d..f216b3a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,6 +14,10 @@ module.exports = { 'no-unused-vars': 'off', '@typescript-eslint/no-unused-vars': 'error', 'import/prefer-default-export': 'off', + 'react/require-default-props': 'off', + 'react-hooks/exhaustive-deps': 'warn', + 'react/jsx-props-no-spreading': 'warn', + 'import/no-cycle': 'warn', }, parserOptions: { ecmaVersion: 2022, diff --git a/capacitor.config.ts b/capacitor.config.ts index 2d58635..7bc435e 100644 --- a/capacitor.config.ts +++ b/capacitor.config.ts @@ -5,8 +5,8 @@ const config: CapacitorConfig = { appName: 'Nutrition Planner', webDir: 'release/app/dist/renderer', server: { - androidScheme: 'https' - } + androidScheme: 'https', + }, }; export default config; diff --git a/package.json b/package.json index 3a845c6..1483691 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "description": "An offline first nutrition planner", + "version": "1.0.1", "keywords": [ "nutrition" ], @@ -26,6 +27,7 @@ "build:web": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.web.ts", "postinstall": "ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && npm run build:dll", "lint": "cross-env NODE_ENV=development eslint . --ext .js,.jsx,.ts,.tsx", + "lint:fix": "cross-env NODE_ENV=development eslint . --fix --ext .js,.jsx,.ts,.tsx", "package": "ts-node ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never && npm run build:dll", "rebuild": "electron-rebuild --parallel --types prod,dev,optional --module-dir release/app", "start": "ts-node ./.erb/scripts/check-port-in-use.js && npm run start:renderer", diff --git a/release/app/package.json b/release/app/package.json index 5ed1846..0f61a7b 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "nutrition-planner", - "version": "1.0.0", + "version": "1.0.1", "description": "A simple calculator for nutrition", "license": "MIT", "main": "./dist/main/main.js", diff --git a/src/main/menu.ts b/src/main/menu.ts index ed5eb59..1ed47a7 100644 --- a/src/main/menu.ts +++ b/src/main/menu.ts @@ -1,10 +1,4 @@ -import { - app, - Menu, - shell, - BrowserWindow, - MenuItemConstructorOptions, -} from 'electron'; +import { app, Menu, BrowserWindow, MenuItemConstructorOptions } from 'electron'; interface DarwinMenuItemConstructorOptions extends MenuItemConstructorOptions { selector?: string; @@ -27,9 +21,7 @@ export default class MenuBuilder { } const template = - process.platform === 'darwin' - ? this.buildDarwinTemplate() - : []; + process.platform === 'darwin' ? this.buildDarwinTemplate() : []; const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index e8acc9c..ceb978c 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -24,6 +24,7 @@ import { MenuHStack } from './components/MenuHStack'; import { LocalStorageKeysEnum } from './constants'; import { initRxNPDatabase } from './data/rxnp/RxNPDatabaseHelpers'; import { RxNPDatabaseType } from './data/rxnp/RxNPDatabaseType'; +import { RxNPItemDocument } from './data/rxnp/RxNPItemSchema'; import LogPage from './pages'; import GroupsPage from './pages/groups'; import ItemsPage from './pages/items'; @@ -52,7 +53,7 @@ export default function App() { 'en', ); const [replicationState, setReplicationState] = - useState(null); + useState | null>(null); useEffect(() => { i18n.changeLanguage(languageLocalStorage); @@ -76,6 +77,7 @@ export default function App() { } else if (replicationState !== null) { replicationState.cancel(); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [couchDbUrlLocalStorage, database]); useEffect(() => { @@ -84,6 +86,7 @@ export default function App() { addRxPlugin(RxDBQueryBuilderPlugin); addRxPlugin(RxDBJsonDumpPlugin); addRxPlugin(RxDBLeaderElectionPlugin); + // eslint-disable-next-line promise/catch-or-return initRxNPDatabase('nutrition-planner-db', getRxStorageDexie()).then( setDatabase, ); diff --git a/src/renderer/components/BigCalendarChakraToolbar.tsx b/src/renderer/components/BigCalendarChakraToolbar.tsx index 4382331..b6a43f2 100644 --- a/src/renderer/components/BigCalendarChakraToolbar.tsx +++ b/src/renderer/components/BigCalendarChakraToolbar.tsx @@ -14,6 +14,7 @@ import { useTranslation } from 'react-i18next'; import { dateIsToday } from '../utilities/dateIsToday'; export function BigCalendarChakraToolbar(props: ToolbarProps) { + const { onNavigate, date, label, view, onView } = props; const { t } = useTranslation(); return ( @@ -24,24 +25,24 @@ export function BigCalendarChakraToolbar(props: ToolbarProps) { width={{ base: 'full', sm: 'initial' }} > props.onNavigate('PREV')} + onClick={() => onNavigate('PREV')} icon={} aria-label={t('previous')} variant="outline" flexGrow={{ base: 1, sm: 'initial' }} /> props.onNavigate('NEXT')} + onClick={() => onNavigate('NEXT')} icon={} aria-label={t('next')} variant="outline" @@ -52,31 +53,31 @@ export function BigCalendarChakraToolbar(props: ToolbarProps) {
- {props.label} + {label}
diff --git a/src/renderer/components/ItemTableRow.tsx b/src/renderer/components/ItemTableRow.tsx index 410ed0a..3ab9472 100644 --- a/src/renderer/components/ItemTableRow.tsx +++ b/src/renderer/components/ItemTableRow.tsx @@ -8,7 +8,7 @@ import { Text, Tr, useColorModeValue, - useToast + useToast, } from '@chakra-ui/react'; import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -24,8 +24,6 @@ import { RxNPItemDocument } from '../data/rxnp/RxNPItemSchema'; import { ServingOrTotalEnum } from '../data/interfaces/ServingOrTotalEnum'; import { LocalStorageKeysEnum } from '../constants'; - - export function ItemTableRow(props: { document: RxNPItemDocument; priceType: ServingOrTotalEnum; @@ -98,8 +96,10 @@ export function ItemTableRow(props: { icon={} aria-label={t('copy')} onClick={async () => { - const baseItems = getBaseItems(await document.recursivelyPopulateSubitems()); - navigator.clipboard.writeText(baseItems.join("\n")); + const baseItems = getBaseItems( + await document.recursivelyPopulateSubitems(), + ); + navigator.clipboard.writeText(baseItems.join('\n')); toast({ title: t('copied'), status: 'success', @@ -108,7 +108,7 @@ export function ItemTableRow(props: { /> } - aria-label={t("delete")} + aria-label={t('delete')} onClick={onDelete} /> diff --git a/src/renderer/components/form-controls/ItemFormControls.tsx b/src/renderer/components/form-controls/ItemFormControls.tsx index 353e65b..5ede1cc 100644 --- a/src/renderer/components/form-controls/ItemFormControls.tsx +++ b/src/renderer/components/form-controls/ItemFormControls.tsx @@ -1,5 +1,4 @@ import { FormikProps } from 'formik'; -import { t } from 'i18next'; import { RefObject } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocalStorage } from 'usehooks-ts'; diff --git a/src/renderer/components/form-controls/LogSubitemFormControls.tsx b/src/renderer/components/form-controls/LogSubitemFormControls.tsx index d226444..7adb3ee 100644 --- a/src/renderer/components/form-controls/LogSubitemFormControls.tsx +++ b/src/renderer/components/form-controls/LogSubitemFormControls.tsx @@ -1,5 +1,4 @@ import { FormikProps } from 'formik'; -import { t } from 'i18next'; import { RefObject } from 'react'; import { useTranslation } from 'react-i18next'; import { useLocalStorage } from 'usehooks-ts'; @@ -13,25 +12,15 @@ export function LogSubitemFormControls(props: { onPaste: (text: string) => Promise; firstInputFieldRef: RefObject | undefined; }) { - const { formikProps, onPaste } = props; + const { formikProps, onPaste, firstInputFieldRef } = props; const { t } = useTranslation(); - const [languageLocalStorage] = useLocalStorage( - LocalStorageKeysEnum.language, - 'en', - ); - const [currencyLocalStorage] = useLocalStorage( LocalStorageKeysEnum.currency, 'USD', ); - const currencyFormatter = new Intl.NumberFormat(languageLocalStorage, { - style: 'currency', - currency: currencyLocalStorage, - }); - const currencyDenominator = currencyLocalStorage === 'JPY' ? 1 : 100; return ( @@ -44,7 +33,7 @@ export function LogSubitemFormControls(props: { placeholder={t('name')} formikProps={formikProps} spaceProps={{ pb: 2 }} - inputFieldRef={props.firstInputFieldRef} + inputFieldRef={firstInputFieldRef} /> - {result.map((value) => { + {result.map((aValue) => { return ( { return item.name; }} > - {value.name} + {aValue.name} ); })} diff --git a/src/renderer/components/form-controls/SubitemField.tsx b/src/renderer/components/form-controls/SubitemField.tsx index a06b83c..559e26e 100644 --- a/src/renderer/components/form-controls/SubitemField.tsx +++ b/src/renderer/components/form-controls/SubitemField.tsx @@ -13,14 +13,14 @@ interface SubitemFieldProps { } export function SubitemField(props: SubitemFieldProps) { - const {formikProps, fieldArrayHelpers, itemTypesIn, label} = props; + const { formikProps, fieldArrayHelpers, itemTypesIn, label } = props; return ( {label} {formikProps.values.subitems?.map((value, index) => { return ( ( }, }} closeOnSelect - onChange={(value: string | moment.Moment) => { - let formattedValue = value; - if (moment.isMoment(value)) { - formattedValue = value.toISOString(); + onChange={(aValue: string | moment.Moment) => { + let formattedValue = aValue; + if (moment.isMoment(aValue)) { + formattedValue = aValue.toISOString(); } formikProps.setFieldValue(name, formattedValue); }} - // value={value ?? ''} /> {error && {error}} diff --git a/src/renderer/components/form/LogForm.tsx b/src/renderer/components/form/LogForm.tsx index 35ff95a..3302572 100644 --- a/src/renderer/components/form/LogForm.tsx +++ b/src/renderer/components/form/LogForm.tsx @@ -9,7 +9,7 @@ import { TabPanel, } from '@chakra-ui/react'; import { Form, FormikProps } from 'formik'; -import { FormEvent, Fragment, RefObject, useState } from 'react'; +import { FormEvent, Fragment, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { ItemInterface } from '../../data/interfaces/ItemInterface'; import { ItemTypeEnum } from '../../data/interfaces/ItemTypeEnum'; @@ -20,7 +20,6 @@ import { LogSubitemFormControls } from '../form-controls/LogSubitemFormControls' type LogFormProps = { formikProps: FormikProps; - firstInputFieldRef: RefObject | undefined; onDelete?: (item: ItemInterface | null) => void; onPaste: (text: string) => Promise; onChangeType: (isLog: boolean) => void; diff --git a/src/renderer/components/formik/GroupFormik.tsx b/src/renderer/components/formik/GroupFormik.tsx index 5ce1e49..2aafe42 100644 --- a/src/renderer/components/formik/GroupFormik.tsx +++ b/src/renderer/components/formik/GroupFormik.tsx @@ -48,6 +48,7 @@ export function GroupFormik(props: GroupFormikProps) { }} validateOnChange={false} validateOnBlur={false} + // eslint-disable-next-line react/no-unstable-nested-components component={(formikProps) => { return ( { async function onPaste(text: string) { const parsedNutritionDictionary: { [key: string]: number } = @@ -72,6 +73,7 @@ export function ItemFormik(props: ItemFormProps) { return ( (initialLogValue); + const [initialValuesState, setInitialValuesState] = + useState(initialLogValue); return ( @@ -53,18 +55,20 @@ export function LogFormik(props: LogFormProps) { validationSchema={yupItemSchema} onSubmit={(values, helpers) => { const dateString = values.date.toString(); + console.log(dateString); if (moment(dateString, [moment.ISO_8601], true).isValid()) { onSubmit({ ...values, }); helpers.resetForm(); } else { - helpers.setErrors({date: 'Invalid date'}); + helpers.setErrors({ date: 'Invalid date' }); helpers.setSubmitting(false); } }} validateOnChange={false} validateOnBlur={false} + // eslint-disable-next-line react/no-unstable-nested-components component={(formikProps) => { async function onPaste(text: string) { const parsedNutritionDictionary: { [key: string]: number } = @@ -87,6 +91,7 @@ export function LogFormik(props: LogFormProps) { return ( { return ( 31 || !item) { // Prevent going beyond 32 levels +export function itemSumNutrition(info: Array): ItemInterface { + return info.reduce( + (previousValue, currentValue) => + itemAddNutrition(previousValue, currentValue), + itemZeroNutrition, + ); +} + +export function itemDivideNutrition( + lhs: ItemInterface, + rhs: number, +): ItemInterface { + return { + massGrams: Math.round((lhs.massGrams ?? 0) / rhs), + energyKilocalories: Math.round((lhs.energyKilocalories ?? 0) / rhs), + fatGrams: Math.round((lhs.fatGrams ?? 0) / rhs), + saturatedFatGrams: Math.round((lhs.saturatedFatGrams ?? 0) / rhs), + transFatGrams: Math.round((lhs.transFatGrams ?? 0) / rhs), + cholesterolMilligrams: Math.round((lhs.cholesterolMilligrams ?? 0) / rhs), + sodiumMilligrams: Math.round((lhs.sodiumMilligrams ?? 0) / rhs), + carbohydrateGrams: Math.round((lhs.carbohydrateGrams ?? 0) / rhs), + fiberGrams: Math.round((lhs.fiberGrams ?? 0) / rhs), + sugarGrams: Math.round((lhs.sugarGrams ?? 0) / rhs), + proteinGrams: Math.round((lhs.proteinGrams ?? 0) / rhs), + }; +} + +export function itemMultiplyNutrition( + lhs: ItemInterface, + rhs: number, +): ItemInterface { + return { + massGrams: Math.round((lhs?.massGrams ?? 0) * rhs), + energyKilocalories: Math.round((lhs?.energyKilocalories ?? 0) * rhs), + fatGrams: Math.round((lhs?.fatGrams ?? 0) * rhs), + saturatedFatGrams: Math.round((lhs?.saturatedFatGrams ?? 0) * rhs), + transFatGrams: Math.round((lhs?.transFatGrams ?? 0) * rhs), + cholesterolMilligrams: Math.round((lhs?.cholesterolMilligrams ?? 0) * rhs), + sodiumMilligrams: Math.round((lhs?.sodiumMilligrams ?? 0) * rhs), + carbohydrateGrams: Math.round((lhs?.carbohydrateGrams ?? 0) * rhs), + fiberGrams: Math.round((lhs?.fiberGrams ?? 0) * rhs), + sugarGrams: Math.round((lhs?.sugarGrams ?? 0) * rhs), + proteinGrams: Math.round((lhs?.proteinGrams ?? 0) * rhs), + }; +} + +export function getBaseItems( + item: ItemInterface, + depth: number = 0, + parentCount: number = 1, +): string[] { + if (depth > 31 || !item) { + // Prevent going beyond 32 levels return []; } if (item.subitems && item.subitems.length > 0) { let baseItems: string[] = []; + // eslint-disable-next-line no-restricted-syntax for (const subitem of item.subitems) { if (subitem.item) { - const effectiveCount = subitem.count ? subitem.count * parentCount : parentCount; - baseItems = baseItems.concat(getBaseItems(subitem.item, depth + 1, effectiveCount)); + const effectiveCount = subitem.count + ? subitem.count * parentCount + : parentCount; + baseItems = baseItems.concat( + getBaseItems(subitem.item, depth + 1, effectiveCount), + ); } } return baseItems; - } else if (item.name) { - return [`${item.name} (${parentCount} x ${(item.massGrams ?? 0)}g)`]; // Include the parent count in the output + } + if (item.name) { + return [`${item.name} (${parentCount} x ${item.massGrams ?? 0}g)`]; // Include the parent count in the output } return []; @@ -51,14 +144,13 @@ export function itemServingNutrition( if (item.subitems && item.subitems.length > 0) { const toSum = item.subitems.map((value) => { if (value.item) { - const item = itemMultiplyNutrition( + const anItem = itemMultiplyNutrition( itemServingNutrition(value.item!, theDepth + 1), value.count!, ); - return item; - } else { - return itemZeroNutrition; + return anItem; } + return itemZeroNutrition; }); return itemDivideNutrition(itemSumNutrition(toSum), item.count ?? 1); @@ -80,14 +172,13 @@ export function logServingNutrition( if (item.subitems && item.subitems.length > 0) { const toSum = item.subitems.map((value) => { if (value.item) { - const item = itemDivideNutrition( + const anItem = itemDivideNutrition( itemServingNutrition(value.item!, theDepth + 1), value.count!, ); - return item; - } else { - return itemZeroNutrition; + return anItem; } + return itemZeroNutrition; }); return itemDivideNutrition(itemSumNutrition(toSum), item.count ?? 1); @@ -115,9 +206,8 @@ export function itemServingPriceCents( itemServingPriceCents(value.item, theDepth + 1) * (value.count ?? 1) ); - } else { - return 0; } + return 0; }) .reduce((previous, current) => previous + current, 0) / (item.count ?? 1) @@ -128,102 +218,3 @@ export function itemServingPriceCents( return priceCents; } - -export const itemZeroNutrition: ItemInterface = { - massGrams: 0, - energyKilocalories: 0, - fatGrams: 0, - saturatedFatGrams: 0, - transFatGrams: 0, - cholesterolMilligrams: 0, - sodiumMilligrams: 0, - carbohydrateGrams: 0, - fiberGrams: 0, - sugarGrams: 0, - proteinGrams: 0, -} - -export function itemAddNutrition( - lhs: ItemInterface, - rhs: ItemInterface, -): ItemInterface { - return { - massGrams: (lhs.massGrams ?? 0) + (rhs.massGrams ?? 0), - energyKilocalories: - (lhs.energyKilocalories ?? 0) + (rhs.energyKilocalories ?? 0), - fatGrams: (lhs.fatGrams ?? 0) + (rhs.fatGrams ?? 0), - saturatedFatGrams: - (lhs.saturatedFatGrams ?? 0) + (rhs.saturatedFatGrams ?? 0), - transFatGrams: (lhs.transFatGrams ?? 0) + (rhs.transFatGrams ?? 0), - cholesterolMilligrams: - (lhs.cholesterolMilligrams ?? 0) + (rhs.cholesterolMilligrams ?? 0), - sodiumMilligrams: (lhs.sodiumMilligrams ?? 0) + (rhs.sodiumMilligrams ?? 0), - carbohydrateGrams: - (lhs.carbohydrateGrams ?? 0) + (rhs.carbohydrateGrams ?? 0), - fiberGrams: (lhs.fiberGrams ?? 0) + (rhs.fiberGrams ?? 0), - sugarGrams: (lhs.sugarGrams ?? 0) + (rhs.sugarGrams ?? 0), - proteinGrams: (lhs.proteinGrams ?? 0) + (rhs.proteinGrams ?? 0), - }; -} - -export function itemEquals(rhs: ItemInterface, lhs: ItemInterface): boolean { - return ( - rhs.massGrams === lhs.massGrams && - rhs.energyKilocalories === lhs.energyKilocalories && - rhs.fatGrams === lhs.fatGrams && - rhs.saturatedFatGrams === lhs.saturatedFatGrams && - rhs.transFatGrams === lhs.transFatGrams && - rhs.cholesterolMilligrams === lhs.cholesterolMilligrams && - rhs.sodiumMilligrams === lhs.sodiumMilligrams && - rhs.carbohydrateGrams === lhs.carbohydrateGrams && - rhs.fiberGrams === lhs.fiberGrams && - rhs.sugarGrams === lhs.sugarGrams && - rhs.proteinGrams === lhs.proteinGrams - ); -} - -export function itemSumNutrition(info: Array): ItemInterface { - return info.reduce( - (previousValue, currentValue) => - itemAddNutrition(previousValue, currentValue), - itemZeroNutrition, - ); -} - -export function itemDivideNutrition( - lhs: ItemInterface, - rhs: number, -): ItemInterface { - return { - massGrams: Math.round((lhs.massGrams ?? 0) / rhs), - energyKilocalories: Math.round((lhs.energyKilocalories ?? 0) / rhs), - fatGrams: Math.round((lhs.fatGrams ?? 0) / rhs), - saturatedFatGrams: Math.round((lhs.saturatedFatGrams ?? 0) / rhs), - transFatGrams: Math.round((lhs.transFatGrams ?? 0) / rhs), - cholesterolMilligrams: Math.round((lhs.cholesterolMilligrams ?? 0) / rhs), - sodiumMilligrams: Math.round((lhs.sodiumMilligrams ?? 0) / rhs), - carbohydrateGrams: Math.round((lhs.carbohydrateGrams ?? 0) / rhs), - fiberGrams: Math.round((lhs.fiberGrams ?? 0) / rhs), - sugarGrams: Math.round((lhs.sugarGrams ?? 0) / rhs), - proteinGrams: Math.round((lhs.proteinGrams ?? 0) / rhs), - }; -} - -export function itemMultiplyNutrition( - lhs: ItemInterface, - rhs: number, -): ItemInterface { - return { - massGrams: Math.round((lhs?.massGrams ?? 0) * rhs), - energyKilocalories: Math.round((lhs?.energyKilocalories ?? 0) * rhs), - fatGrams: Math.round((lhs?.fatGrams ?? 0) * rhs), - saturatedFatGrams: Math.round((lhs?.saturatedFatGrams ?? 0) * rhs), - transFatGrams: Math.round((lhs?.transFatGrams ?? 0) * rhs), - cholesterolMilligrams: Math.round((lhs?.cholesterolMilligrams ?? 0) * rhs), - sodiumMilligrams: Math.round((lhs?.sodiumMilligrams ?? 0) * rhs), - carbohydrateGrams: Math.round((lhs?.carbohydrateGrams ?? 0) * rhs), - fiberGrams: Math.round((lhs?.fiberGrams ?? 0) * rhs), - sugarGrams: Math.round((lhs?.sugarGrams ?? 0) * rhs), - proteinGrams: Math.round((lhs?.proteinGrams ?? 0) * rhs), - }; -} diff --git a/src/renderer/data/interfaces/ItemInterface.ts b/src/renderer/data/interfaces/ItemInterface.ts index 464842e..4ea87a6 100644 --- a/src/renderer/data/interfaces/ItemInterface.ts +++ b/src/renderer/data/interfaces/ItemInterface.ts @@ -1,5 +1,5 @@ -import { ItemTypeEnum } from "./ItemTypeEnum"; -import { SubitemInterface } from "./SubitemInterface"; +import { ItemTypeEnum } from './ItemTypeEnum'; +import { SubitemInterface } from './SubitemInterface'; export interface ItemInterface { id?: string; diff --git a/src/renderer/data/rxnp/RxNPDatabaseHelpers.ts b/src/renderer/data/rxnp/RxNPDatabaseHelpers.ts index 04c3c20..bb994a5 100644 --- a/src/renderer/data/rxnp/RxNPDatabaseHelpers.ts +++ b/src/renderer/data/rxnp/RxNPDatabaseHelpers.ts @@ -69,12 +69,14 @@ export async function upsertLogInterface( const findByOriginalIdsMap = await collection ?.findByIds(originalIds) .exec(); + // eslint-disable-next-line no-restricted-syntax for (const [originalSubitemId, originalSubitem] of Array.from( findByOriginalIdsMap ?? [], )) { + // eslint-disable-next-line no-await-in-loop const newSubitem = await originalSubitem.recursivelyUpsertNewSubitems(); - item.subitems.forEach(function (value, index) { - if (value.itemId == originalSubitemId) { + item.subitems.forEach((value, index) => { + if (value.itemId === originalSubitemId) { item.subitems![index].itemId = newSubitem.id; item.subitems![index].item = undefined; } @@ -82,9 +84,8 @@ export async function upsertLogInterface( } } - if (item.subitems?.length == 1 && item.subitems![0].itemId == null) { + if (item.subitems?.length === 1 && item.subitems![0].itemId == null) { item.subitems![0].itemId = newItem?.id; - } else { } const log: any = { @@ -120,10 +121,12 @@ export async function recursivelyPopulateSubitems( if (mutableThis.subitems && mutableThis.subitems.length > 0) { const ids = mutableThis.subitems.map((value) => value.itemId!) ?? []; const findByIdsMap = await collection?.findByIds(ids).exec(); + // eslint-disable-next-line no-restricted-syntax for (const [subitemId, subitem] of Array.from(findByIdsMap ?? [])) { + // eslint-disable-next-line no-await-in-loop const populatedSubitem = await subitem.recursivelyPopulateSubitems(); - mutableThis.subitems.forEach(function (value, index) { - if (value.itemId == subitemId) { + mutableThis.subitems.forEach((value, index) => { + if (value.itemId === subitemId) { mutableThis.subitems![index].item = populatedSubitem; } }); diff --git a/src/renderer/data/rxnp/RxNPItemSchema.ts b/src/renderer/data/rxnp/RxNPItemSchema.ts index c354c99..a6924bc 100644 --- a/src/renderer/data/rxnp/RxNPItemSchema.ts +++ b/src/renderer/data/rxnp/RxNPItemSchema.ts @@ -1,3 +1,4 @@ +/* eslint-disable */ import { RxCollection, RxDocument, RxJsonSchema } from 'rxdb'; import { dataid } from '../../utilities/dataid'; import { itemZeroNutrition } from '../interfaces/ItemHelpers'; @@ -178,7 +179,7 @@ export const rxnpItemDocumentMethods: RxNPItemDocumentMethods = { } } - return this.remove() != undefined; + return this.remove() !== undefined; }, }; @@ -190,7 +191,7 @@ export async function recursivelyPopulateSubitemsOfItems( if (items.length > 0) { const populatedSubitems = await Promise.all( items.map(async (value) => { - return await value.recursivelyPopulateSubitems(); + return value.recursivelyPopulateSubitems(); }), ); diff --git a/src/renderer/data/yup/YupItemSchema.ts b/src/renderer/data/yup/YupItemSchema.ts index acc12bc..ab7820d 100644 --- a/src/renderer/data/yup/YupItemSchema.ts +++ b/src/renderer/data/yup/YupItemSchema.ts @@ -1,18 +1,8 @@ -import { - array, - date, - InferType, - mixed, - number, - object, - Schema, - string, -} from 'yup'; +import { array, InferType, mixed, number, object, Schema, string } from 'yup'; import { ItemInterface } from '../interfaces/ItemInterface'; import { ItemTypeEnum } from '../interfaces/ItemTypeEnum'; import { yupSubitemSchema } from './YupSubitemSchema'; -export type YupItemType = InferType; export const yupItemSchema: Schema = object({ id: string().label('ID'), date: string().label('Date').meta({ @@ -36,3 +26,4 @@ export const yupItemSchema: Schema = object({ proteinGrams: number(), subitems: array().of(yupSubitemSchema).default([]), }); +export type YupItemType = InferType; diff --git a/src/renderer/data/yup/YupSubitemSchema.ts b/src/renderer/data/yup/YupSubitemSchema.ts index d71dff1..4d46fd1 100644 --- a/src/renderer/data/yup/YupSubitemSchema.ts +++ b/src/renderer/data/yup/YupSubitemSchema.ts @@ -2,9 +2,9 @@ import { InferType, lazy, number, object, Schema, string } from 'yup'; import { SubitemInterface } from '../interfaces/SubitemInterface'; import { yupItemSchema } from './YupItemSchema'; -export type YupSubitemType = InferType; export const yupSubitemSchema: Schema = object({ itemId: string(), item: lazy(() => yupItemSchema), count: number(), }); +export type YupSubitemType = InferType; diff --git a/src/renderer/i18n/dictionaries/ar.json b/src/renderer/i18n/dictionaries/ar.json index 530ce17..c4ac995 100644 --- a/src/renderer/i18n/dictionaries/ar.json +++ b/src/renderer/i18n/dictionaries/ar.json @@ -1,23 +1,20 @@ { - "AUD": "دولار أسترالي", - "CAD": "دولار كندي", - "CHF": "فرنك سويسري", - "CNY": "يوان صيني", - "EUR": "يورو", - "GBP": "جنيه بريطاني", - "JPY": "ين ياباني", - "USD": "دولار أمريكي", "actions": "الإجراءات", "add": "إضافة", "areYouSure": "هل أنت متأكد؟", + "AUD": "دولار أسترالي", "basalMetabolicRate": "معدل الأيض الأساسي", "birthday": "تاريخ الميلاد", + "CAD": "دولار كندي", "cancel": "إلغاء", "carb": "كرب", "carbohydrate": "كربوهيدرات", "carbohydrateTarget": "هدف الكربوهيدرات", + "carbs": "كربوهيدرات", + "CHF": "فرنك سويسري", "cholesterol": "كوليسترول", "cmCentimeters": "سم", + "CNY": "يوان صيني", "copied": "تم النسخ", "copy": "نسخ", "couchDbUrl": "رابط CouchDB", @@ -32,11 +29,13 @@ "edit": "تحرير", "energy": "طاقة", "energyTarget": "هدف الطاقة", + "EUR": "يورو", "exportJson": "تصدير JSON", "fat": "دهون", "fatTarget": "هدف الدهون", "female": "أنثى", "fiber": "ألياف", + "GBP": "جنيه بريطاني", "goalDate": "تاريخ الهدف", "goalWeight": "الوزن المستهدف", "grams": "غرامات", @@ -49,6 +48,7 @@ "item": "عنصر", "items": "عناصر", "itemsEmpty": "لم يتم العثور على عناصر", + "JPY": "ين ياباني", "kcal": "سعرات حرارية", "kgKilograms": "كغ", "language": "اللغة", @@ -86,6 +86,7 @@ "toggleColorMode": "تبديل وضع اللون", "totalPrice": "السعر الإجمالي", "transFat": "دهون عبرية", + "USD": "دولار أمريكي", "week": "أسبوع", "weight": "الوزن" } diff --git a/src/renderer/i18n/dictionaries/cmn.json b/src/renderer/i18n/dictionaries/cmn.json index 7107bae..e9e69a6 100644 --- a/src/renderer/i18n/dictionaries/cmn.json +++ b/src/renderer/i18n/dictionaries/cmn.json @@ -1,23 +1,20 @@ { - "AUD": "澳大利亚元", - "CAD": "加拿大元", - "CHF": "瑞士法郎", - "CNY": "人民币", - "EUR": "欧元", - "GBP": "英镑", - "JPY": "日元", - "USD": "美元", "actions": "操作", "add": "添加", "areYouSure": "你确定吗?", + "AUD": "澳大利亚元", "basalMetabolicRate": "基础代谢率", "birthday": "生日", + "CAD": "加拿大元", "cancel": "取消", "carb": "碳水", "carbohydrate": "碳水化合物", "carbohydrateTarget": "碳水化合物目标", + "carbs": "碳水", + "CHF": "瑞士法郎", "cholesterol": "胆固醇", "cmCentimeters": "厘米", + "CNY": "人民币", "copied": "已复制", "copy": "复制", "couchDbUrl": "CouchDB URL", @@ -32,11 +29,13 @@ "edit": "编辑", "energy": "能量", "energyTarget": "能量目标", + "EUR": "欧元", "exportJson": "导出 JSON", "fat": "脂肪", "fatTarget": "脂肪目标", "female": "女", "fiber": "纤维", + "GBP": "英镑", "goalDate": "目标日期", "goalWeight": "目标体重", "grams": "克", @@ -49,6 +48,7 @@ "item": "项目", "items": "项目", "itemsEmpty": "未找到项目", + "JPY": "日元", "kcal": "千卡", "kgKilograms": "千克", "language": "语言", @@ -86,6 +86,7 @@ "toggleColorMode": "切换界面", "totalPrice": "总价", "transFat": "反式脂肪", + "USD": "美元", "week": "周", "weight": "体重" } diff --git a/src/renderer/i18n/dictionaries/en.json b/src/renderer/i18n/dictionaries/en.json index 9704887..661dadb 100644 --- a/src/renderer/i18n/dictionaries/en.json +++ b/src/renderer/i18n/dictionaries/en.json @@ -1,23 +1,20 @@ { - "AUD": "Australian Dollar", - "CAD": "Canadian Dollar", - "CHF": "Swiss Franc", - "CNY": "Chinese Yuan", - "EUR": "Euro", - "GBP": "British Pound", - "JPY": "Japanese Yen", - "USD": "United States Dollar", "actions": "Actions", "add": "Add", "areYouSure": "Are you sure?", + "AUD": "Australian Dollar", "basalMetabolicRate": "Basal metabolic rate", "birthday": "Birthday", + "CAD": "Canadian Dollar", "cancel": "Cancel", "carb": "Carb", "carbohydrate": "Carbohydrate", "carbohydrateTarget": "Carb target", + "carbs": "Carbs", + "CHF": "Swiss Franc", "cholesterol": "Cholesterol", "cmCentimeters": "cm", + "CNY": "Chinese Yuan", "copied": "Copied", "copy": "Copy", "couchDbUrl": "CouchDB URL", @@ -32,11 +29,13 @@ "edit": "Edit", "energy": "Energy", "energyTarget": "Energy target", + "EUR": "Euro", "exportJson": "Export JSON", "fat": "Fat", "fatTarget": "Fat target", "female": "Female", "fiber": "Fiber", + "GBP": "British Pound", "goalDate": "Goal date", "goalWeight": "Goal weight", "group": "Group", @@ -48,6 +47,7 @@ "item": "Item", "items": "Items", "itemsEmpty": "No items found", + "JPY": "Japanese Yen", "kcal": "kcal", "kgKilograms": "kg", "language": "Language", @@ -86,6 +86,7 @@ "toggleColorMode": "Toggle dark UI", "totalPrice": "Total price", "transFat": "Trans fat", + "USD": "United States Dollar", "week": "Week", "weight": "Weight" } diff --git a/src/renderer/i18n/dictionaries/es.json b/src/renderer/i18n/dictionaries/es.json index 2899608..f27bd23 100644 --- a/src/renderer/i18n/dictionaries/es.json +++ b/src/renderer/i18n/dictionaries/es.json @@ -1,23 +1,20 @@ { - "AUD": "Dólar australiano", - "CAD": "Dólar canadiense", - "CHF": "Franco suizo", - "CNY": "Yuan chino", - "EUR": "Euro", - "GBP": "Libra esterlina", - "JPY": "Yen japonés", - "USD": "Dólar estadounidense", "actions": "Acciones", "add": "Añadir", "areYouSure": "¿Estás seguro?", + "AUD": "Dólar australiano", "basalMetabolicRate": "Tasa metabólica basal", "birthday": "Cumpleaños", + "CAD": "Dólar canadiense", "cancel": "Cancelar", "carb": "Carbo", "carbohydrate": "Carbohidrato", "carbohydrateTarget": "Objetivo de carbohidratos", + "carbs": "Carbos", + "CHF": "Franco suizo", "cholesterol": "Colesterol", "cmCentimeters": "cm", + "CNY": "Yuan chino", "copied": "已复制", "copy": "复制", "couchDbUrl": "URL de CouchDB", @@ -32,11 +29,13 @@ "edit": "编辑", "energy": "Energía", "energyTarget": "Objetivo de energía", + "EUR": "Euro", "exportJson": "Exportar JSON", "fat": "Grasa", "fatTarget": "Objetivo de grasa", "female": "Femenino", "fiber": "Fibra", + "GBP": "Libra esterlina", "goalDate": "Fecha objetivo", "goalWeight": "Peso objetivo", "grams": "gramos", @@ -49,6 +48,7 @@ "item": "Ítem", "items": "Ítems", "itemsEmpty": "No se encontraron ítems", + "JPY": "Yen japonés", "kcal": "kcal", "kgKilograms": "kg", "language": "Idioma", @@ -86,6 +86,7 @@ "toggleColorMode": "Cambiar modo de color", "totalPrice": "Precio total", "transFat": "Grasa trans", + "USD": "Dólar estadounidense", "week": "Semana", "weight": "Peso" } diff --git a/src/renderer/i18n/dictionaries/fr.json b/src/renderer/i18n/dictionaries/fr.json index c83f3df..22bde56 100644 --- a/src/renderer/i18n/dictionaries/fr.json +++ b/src/renderer/i18n/dictionaries/fr.json @@ -1,23 +1,20 @@ { - "AUD": "Dollar australien", - "CAD": "Dollar canadien", - "CHF": "Franc suisse", - "CNY": "Yuan chinois", - "EUR": "Euro", - "GBP": "Livre sterling", - "JPY": "Yen japonais", - "USD": "Dollar américain", "actions": "Actions", "add": "Ajouter", "areYouSure": "Êtes-vous sûr ?", + "AUD": "Dollar australien", "basalMetabolicRate": "Taux métabolique basal", "birthday": "Anniversaire", + "CAD": "Dollar canadien", "cancel": "Annuler", "carb": "Gluc", "carbohydrate": "Glucide", "carbohydrateTarget": "Objectif de glucides", + "carbs": "Glucides", + "CHF": "Franc suisse", "cholesterol": "Cholestérol", "cmCentimeters": "cm", + "CNY": "Yuan chinois", "copied": "Copié", "copy": "Copier", "couchDbUrl": "URL de CouchDB", @@ -32,11 +29,13 @@ "edit": "Modifier", "energy": "Énergie", "energyTarget": "Objectif énergétique", + "EUR": "Euro", "exportJson": "Exporter en JSON", "fat": "Graisse", "fatTarget": "Objectif de graisse", "female": "Femme", "fiber": "Fibre", + "GBP": "Livre sterling", "goalDate": "Date cible", "goalWeight": "Poids cible", "grams": "grammes", @@ -49,6 +48,7 @@ "item": "Article", "items": "Articles", "itemsEmpty": "Aucun article trouvé", + "JPY": "Yen japonais", "kcal": "kcal", "kgKilograms": "kg", "language": "Langue", @@ -86,6 +86,7 @@ "toggleColorMode": "Basculer le mode couleur", "totalPrice": "Prix total", "transFat": "Graisse trans", + "USD": "Dollar américain", "week": "Semaine", "weight": "Poids" } diff --git a/src/renderer/i18n/dictionaries/hi.json b/src/renderer/i18n/dictionaries/hi.json index 8bc2b13..c84beae 100644 --- a/src/renderer/i18n/dictionaries/hi.json +++ b/src/renderer/i18n/dictionaries/hi.json @@ -1,23 +1,20 @@ { - "AUD": "ऑस्ट्रेलियाई डॉलर", - "CAD": "कनाडाई डॉलर", - "CHF": "स्विस फ्रैंक", - "CNY": "चीनी युआन", - "EUR": "यूरो", - "GBP": "ब्रिटिश पाउंड", - "JPY": "जापानी येन", - "USD": "अमेरिकी डॉलर", "actions": "क्रियाएँ", "add": "जोड़ें", "areYouSure": "क्या आपको यकीन है?", + "AUD": "ऑस्ट्रेलियाई डॉलर", "basalMetabolicRate": "मूल चयापचय दर", "birthday": "जन्मदिन", + "CAD": "कनाडाई डॉलर", "cancel": "रद्द करें", "carb": "कार्ब", "carbohydrate": "कार्बोहाइड्रेट", "carbohydrateTarget": "कार्बोहाइड्रेट लक्ष्य", + "carbs": "कार्ब्स", + "CHF": "स्विस फ्रैंक", "cholesterol": "कोलेस्ट्रॉल", "cmCentimeters": "सेंटीमीटर", + "CNY": "चीनी युआन", "copied": "कॉपी किया गया", "copy": "कॉपी", "couchDbUrl": "CouchDB URL", @@ -32,11 +29,13 @@ "edit": "संपादित करें", "energy": "ऊर्जा", "energyTarget": "ऊर्जा लक्ष्य", + "EUR": "यूरो", "exportJson": "JSON निर्यात करें", "fat": "वसा", "fatTarget": "वसा लक्ष्य", "female": "महिला", "fiber": "फाइबर", + "GBP": "ब्रिटिश पाउंड", "goalDate": "लक्ष्य तिथि", "goalWeight": "लक्ष्य वज़न", "grams": "ग्राम", @@ -49,6 +48,7 @@ "item": "वस्तु", "items": "वस्तुएँ", "itemsEmpty": "कोई वस्तुएँ नहीं मिलीं", + "JPY": "जापानी येन", "kcal": "किलोकैलोरी", "kgKilograms": "किलोग्राम", "language": "भाषा", @@ -86,6 +86,7 @@ "toggleColorMode": "यूआई टॉगल करें", "totalPrice": "कुल मूल्य", "transFat": "ट्रांस वसा", + "USD": "अमेरिकी डॉलर", "week": "सप्ताह", "weight": "वज़न" } diff --git a/src/renderer/pages/index.tsx b/src/renderer/pages/index.tsx index d7682c9..2e79bc2 100644 --- a/src/renderer/pages/index.tsx +++ b/src/renderer/pages/index.tsx @@ -47,6 +47,7 @@ import { recursivelyPopulateSubitemsOfItems, } from '../data/rxnp/RxNPItemSchema'; import { LocalStorageKeysEnum } from '../constants'; +import { upsertLogInterface } from '../data/rxnp/RxNPDatabaseHelpers'; export interface RangeType { start: Date; @@ -62,6 +63,9 @@ export default function LogPage() { start: moment().startOf(viewState).toDate(), end: moment().endOf(viewState).toDate(), }); + const [logDrawerItem, setLogDrawerItem] = useState( + null, + ); const [eventsState, setEventsState] = useState([]); const [selectedEvent, setModalEvent] = useState(null); const [editItemState, setEditItemState] = useState( @@ -97,13 +101,12 @@ export default function LogPage() { ); function formatTitle(priceCents: number, nutrition: ItemInterface) { - return `${currencyFormatter.format( - (priceCents ?? 0) / currencyDenominator, - )} | ${nutrition.energyKilocalories}kcal | ${nutrition.massGrams}g mass | ${ - nutrition.fatGrams - }g fat | ${nutrition.carbohydrateGrams}g carbs | ${ - nutrition.proteinGrams - }g protein`; + const formattableCurrencyAmount = (priceCents ?? 0) / currencyDenominator; + const currencyString = + formattableCurrencyAmount !== 0 + ? `${currencyFormatter.format(formattableCurrencyAmount)} | ` + : ``; + return `${currencyString}${nutrition.energyKilocalories}kcal | ${nutrition.massGrams}g mass | ${nutrition.fatGrams}g fat | ${nutrition.carbohydrateGrams}g carbs | ${nutrition.proteinGrams}g protein`; } function titleForItemInterface(item: ItemInterface) { @@ -114,7 +117,7 @@ export default function LogPage() { useEffect(() => { async function calculate() { - const datesInRange = new Array(); + const datesInRange: Date[] = []; let currentDate = dateRangeState.start; while (currentDate <= dateRangeState.end) { datesInRange.push(currentDate); @@ -135,6 +138,7 @@ export default function LogPage() { }; }); + // eslint-disable-next-line no-restricted-syntax for (const dateInRange of datesInRange) { const populatedLogsOnDate = populatedResults.filter((value) => moment(dateInRange).isSame(moment(value.date), 'day'), @@ -172,7 +176,7 @@ export default function LogPage() { setViewState('week'); } - const [languageLocaleStorage, setLanguageLocalStorage] = useLocalStorage( + const [languageLocaleStorage] = useLocalStorage( LocalStorageKeysEnum.language, 'en', ); @@ -233,13 +237,13 @@ export default function LogPage() { dayRangeHeaderFormat: ( range: DateRange, culture?: Culture, - localizer?: DateLocalizer, + aLocalizer?: DateLocalizer, ) => { - return `${localizer?.format( + return `${aLocalizer?.format( range.start, 'LLL d', culture, - )}-${localizer?.format(range.end, 'LLL d', culture)}`; + )}-${aLocalizer?.format(range.end, 'LLL d', culture)}`; }, }} onDoubleClickEvent={async (event) => { @@ -259,6 +263,12 @@ export default function LogPage() { } } }} + onSelectSlot={(slotInfo: { start: Date }) => { + setLogDrawerItem({ + type: ItemTypeEnum.log, + date: slotInfo.start.toISOString(), + }); + }} events={eventsState} views={{ day: true, month: true, week: true }} startAccessor="start" @@ -306,6 +316,15 @@ export default function LogPage() { + { + setLogDrawerItem(null); + if (item) { + await upsertLogInterface(item, collection ?? undefined); + } + }} + /> ); } diff --git a/src/renderer/pages/privacy.tsx b/src/renderer/pages/privacy.tsx index 4986830..dc0c183 100644 --- a/src/renderer/pages/privacy.tsx +++ b/src/renderer/pages/privacy.tsx @@ -1,7 +1,8 @@ +/* eslint-disable react/no-unescaped-entities */ import React from 'react'; import { Box, Heading, Text } from '@chakra-ui/react'; -const PrivacyPage = () => { +function PrivacyPage() { return ( Privacy Policy @@ -61,10 +62,11 @@ const PrivacyPage = () => { Contact Us - If you have any questions about this Privacy Policy, please contact paul.jones@adeptry.com + If you have any questions about this Privacy Policy, please contact + paul.jones@adeptry.com ); -}; +} export default PrivacyPage; diff --git a/src/renderer/pages/support.tsx b/src/renderer/pages/support.tsx index ef58637..c0e1a93 100644 --- a/src/renderer/pages/support.tsx +++ b/src/renderer/pages/support.tsx @@ -1,15 +1,13 @@ import React from 'react'; import { Box, Heading, Text } from '@chakra-ui/react'; -const SupportPage = () => { +function SupportPage() { return ( Support - - For support, contact paul.jones@adeptry.com - + For support, contact paul.jones@adeptry.com ); -}; +} export default SupportPage; diff --git a/src/renderer/pages/terms.tsx b/src/renderer/pages/terms.tsx index f460340..d35adb2 100644 --- a/src/renderer/pages/terms.tsx +++ b/src/renderer/pages/terms.tsx @@ -1,7 +1,8 @@ +/* eslint-disable react/no-unescaped-entities */ import React from 'react'; import { Box, Heading, Text } from '@chakra-ui/react'; -const TermsPage = () => { +function TermsPage() { return ( Terms of Service @@ -56,10 +57,11 @@ const TermsPage = () => { Contact Us - If you have any questions about these Terms, please contact me: paul.jones@adeptry.com + If you have any questions about these Terms, please contact me: + paul.jones@adeptry.com ); -}; +} export default TermsPage; diff --git a/src/renderer/utilities/calculateEnergyTargetKcal.ts b/src/renderer/utilities/calculateEnergyTargetKcal.ts index 8513cff..fdc545d 100644 --- a/src/renderer/utilities/calculateEnergyTargetKcal.ts +++ b/src/renderer/utilities/calculateEnergyTargetKcal.ts @@ -18,12 +18,18 @@ export function calculateEnergyTargetKcal(params: { } = params; if ( - weightKilograms == undefined || - sexIsMale == undefined || - ageYears == undefined || - heightCentimeters == undefined || - goalWeightKilograms == undefined || - goalDays == undefined + weightKilograms === null || + weightKilograms === undefined || + sexIsMale === null || + sexIsMale === undefined || + ageYears === null || + ageYears === undefined || + heightCentimeters === null || + heightCentimeters === undefined || + goalWeightKilograms === null || + goalWeightKilograms === undefined || + goalDays === null || + goalDays === undefined ) { return undefined; } diff --git a/src/renderer/utilities/isValidUrl.ts b/src/renderer/utilities/isValidUrl.ts index b8b27d9..0af133b 100644 --- a/src/renderer/utilities/isValidUrl.ts +++ b/src/renderer/utilities/isValidUrl.ts @@ -1,14 +1,13 @@ export function isValidUrl(value?: string) { - if (value === undefined) { - return false; - } + if (value === undefined) { + return false; + } - const expression = - /[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)?/gi; - const regex = new RegExp(expression); - if (value.match(regex)) { - return true; - } else { - return false; - } + const expression = + /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)?/gi; + const regex = new RegExp(expression); + if (value.match(regex)) { + return true; } + return false; +} diff --git a/src/renderer/utilities/parseNutritionDictionary.ts b/src/renderer/utilities/parseNutritionDictionary.ts index 283dc0f..32e8563 100644 --- a/src/renderer/utilities/parseNutritionDictionary.ts +++ b/src/renderer/utilities/parseNutritionDictionary.ts @@ -16,10 +16,11 @@ export function parseNutritionDictionary(text: string) { ]; const numberedGroups: { [key: string]: number } = {}; + // eslint-disable-next-line no-restricted-syntax for (const regExp of regExps) { const regExpMatchArray = regExp.exec(text); const matchedGroup = regExpMatchArray?.groups ?? {}; - Object.keys(matchedGroup).forEach(function (key) { + Object.keys(matchedGroup).forEach((key) => { numberedGroups[key] = +matchedGroup[key]; }); }