Full Code of vangelov/calories-in for AI

master 2dd62babb5e8 cached
340 files
591.2 KB
207.8k tokens
559 symbols
1 requests
Download .txt
Showing preview only (672K chars total). Download the full file or copy to clipboard to get everything.
Repository: vangelov/calories-in
Branch: master
Commit: 2dd62babb5e8
Files: 340
Total size: 591.2 KB

Directory structure:
gitextract_ov6rt79l/

├── .gitignore
├── .husky/
│   ├── .gitignore
│   └── pre-commit
├── .prettierignore
├── .prettierrc
├── .vscode/
│   └── settings.json
├── LICENSE
├── README.md
├── package.json
├── public/
│   ├── browserconfig.xml
│   ├── index.html
│   ├── robots.txt
│   └── site.webmanifest
├── src/
│   ├── App.tsx
│   ├── diets/
│   │   ├── DietEditor/
│   │   │   ├── DndContextProvider.tsx
│   │   │   ├── Form/
│   │   │   │   ├── About.tsx
│   │   │   │   ├── Controls/
│   │   │   │   │   ├── ExportButton.tsx
│   │   │   │   │   ├── MenuOrDrawer.tsx
│   │   │   │   │   ├── Name.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Footer.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── useDietFormEvents.ts
│   │   │   │   └── useVariantFormActions.ts
│   │   │   └── index.tsx
│   │   ├── PdfDietEditor.tsx
│   │   ├── dietForm.ts
│   │   ├── index.ts
│   │   ├── persistence/
│   │   │   ├── ExportModal/
│   │   │   │   ├── Content/
│   │   │   │   │   ├── Exporter/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── usePdfExport.ts
│   │   │   │   │   │   └── worker/
│   │   │   │   │   │       ├── custom.d.ts
│   │   │   │   │   │       ├── index.ts
│   │   │   │   │   │       ├── types.ts
│   │   │   │   │   │       └── worker.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── canExportDietForm.ts
│   │   │   ├── hasMissingFoods.ts
│   │   │   ├── index.ts
│   │   │   ├── loadLastOrDefaultDietForm.ts
│   │   │   ├── parseDietForm.ts
│   │   │   ├── useDietImportErrors.tsx
│   │   │   └── useImportDietForm.ts
│   │   ├── types.ts
│   │   ├── useDietFormStore.ts
│   │   ├── useGetDietFormStatsTree.ts
│   │   └── useScrollManager.ts
│   ├── dom/
│   │   ├── animateScrollLeft.ts
│   │   ├── index.ts
│   │   ├── isElementInViewport.ts
│   │   ├── useGetRefForId.ts
│   │   └── useScrollTo.ts
│   ├── foods/
│   │   ├── FoodInfo.tsx
│   │   ├── FoodModal/
│   │   │   ├── Content/
│   │   │   │   ├── DeleteConfirmationModal.tsx
│   │   │   │   ├── FoodFormProvider.tsx
│   │   │   │   ├── Form/
│   │   │   │   │   ├── Footer.tsx
│   │   │   │   │   ├── Header.tsx
│   │   │   │   │   ├── Tabs/
│   │   │   │   │   │   ├── NutritionFactsFormFields.tsx
│   │   │   │   │   │   ├── UrlField.tsx
│   │   │   │   │   │   ├── VolumeFormFields.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── useSubmitFoodForm.ts
│   │   │   │   │   └── useTabs.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── useDeleteFood.ts
│   │   │   └── index.tsx
│   │   ├── FoodsDrawer/
│   │   │   ├── Content/
│   │   │   │   ├── Header.tsx
│   │   │   │   ├── MenuButtons.tsx
│   │   │   │   ├── SelectedFoodsList/
│   │   │   │   │   ├── SelectedFoodItem.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── useFoodEvents.ts
│   │   │   └── index.tsx
│   │   ├── FoodsList/
│   │   │   ├── VirtualizedList/
│   │   │   │   ├── FoodItem/
│   │   │   │   │   ├── AnimateAppear.tsx
│   │   │   │   │   ├── DisappearingBox.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── FoodItemRenderer.tsx
│   │   │   │   ├── Inner.tsx
│   │   │   │   └── index.tsx
│   │   │   └── index.tsx
│   │   ├── builtIn/
│   │   │   ├── bakedProducts.json
│   │   │   ├── beef.json
│   │   │   ├── beverages.json
│   │   │   ├── dairyAndEggs.json
│   │   │   ├── fatsAndOils.json
│   │   │   ├── finfishAndShellFish.json
│   │   │   ├── fruitsAndJuices.json
│   │   │   ├── grainsAndPasta.json
│   │   │   ├── index.ts
│   │   │   ├── legumesAndLegumeProducts.json
│   │   │   ├── nutAndSeedProducts.json
│   │   │   ├── pork.json
│   │   │   ├── poultry.json
│   │   │   ├── saucesAndSoups.json
│   │   │   ├── spicesAndHerbs.json
│   │   │   ├── sweetsAndSnacks.json
│   │   │   └── vegetables.json
│   │   ├── foodForm.ts
│   │   ├── foodVolumeForm.ts
│   │   ├── index.ts
│   │   ├── persistence/
│   │   │   ├── FoodsListModal/
│   │   │   │   ├── Content.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── MissingFoodsModal.tsx
│   │   │   ├── index.ts
│   │   │   ├── loadFoods.ts
│   │   │   └── useImportFoods.ts
│   │   ├── types.ts
│   │   └── useFoodsStore.ts
│   ├── foods-categories/
│   │   ├── FoodCategoriesSelect.tsx
│   │   ├── categories.json
│   │   ├── index.ts
│   │   └── types.ts
│   ├── foods-filters/
│   │   ├── FoodsFilterPopoverOrModal/
│   │   │   ├── Content.tsx
│   │   │   ├── Footer.tsx
│   │   │   ├── Modal.tsx
│   │   │   ├── Popover.tsx
│   │   │   ├── Trigger.tsx
│   │   │   └── index.tsx
│   │   ├── foodsFilter.ts
│   │   ├── index.ts
│   │   ├── persistence/
│   │   │   ├── index.ts
│   │   │   └── loadFoodsFilter.ts
│   │   ├── useFilterFoods.ts
│   │   └── useFoodsFilterStore.ts
│   ├── form/
│   │   ├── duplicate.ts
│   │   ├── index.ts
│   │   ├── names.ts
│   │   ├── types.ts
│   │   ├── useFormError.ts
│   │   └── useSelectInputText.ts
│   ├── general/
│   │   ├── Badge.tsx
│   │   ├── ContextMenuFlex.tsx
│   │   ├── HFadeScroll/
│   │   │   ├── FadeBox.tsx
│   │   │   ├── ScrollContainer.tsx
│   │   │   └── index.tsx
│   │   ├── Loader.tsx
│   │   ├── Menu.tsx
│   │   ├── MenuOrDrawer/
│   │   │   ├── Drawer/
│   │   │   │   ├── getDrawerButtons.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── Menu/
│   │   │   │   ├── getMenuItems.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── MenuOrDrawerItem.tsx
│   │   │   ├── MenuOrDrawerSeparator.tsx
│   │   │   ├── Trigger.tsx
│   │   │   └── index.tsx
│   │   ├── ResponsiveButton.tsx
│   │   ├── ResponsiveIconButton.tsx
│   │   ├── RightAligned.tsx
│   │   ├── ScreenSizeProvider/
│   │   │   ├── context.ts
│   │   │   └── index.tsx
│   │   ├── Tooltip.tsx
│   │   ├── TooltipCommandLabel.tsx
│   │   ├── deepCopy.ts
│   │   ├── getCtrlKeyName.ts
│   │   ├── index.ts
│   │   ├── minDelay.ts
│   │   ├── stores.tsx
│   │   ├── useElementHeight.ts
│   │   ├── useOneTimeCheckStore.ts
│   │   ├── useRunIfNotUnmounted.ts
│   │   ├── useSameOrPreviousValue.ts
│   │   └── useSelection.ts
│   ├── icons/
│   │   ├── CalendarPlus.tsx
│   │   └── index.ts
│   ├── index.tsx
│   ├── ingredients/
│   │   ├── IngredientsList/
│   │   │   ├── EmptyList.tsx
│   │   │   ├── IngredientItem/
│   │   │   │   ├── MenuOrDrawer.tsx
│   │   │   │   ├── MissingStatsLayout.tsx
│   │   │   │   ├── Notes.tsx
│   │   │   │   ├── PresenceAnimation.tsx
│   │   │   │   ├── StatsLayout.tsx
│   │   │   │   ├── getMenuOrDrawerItems.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── useIngredientsEvents.ts
│   │   │   │   └── useNotesEvents.tsx
│   │   │   └── index.tsx
│   │   ├── PdfIngredientsList/
│   │   │   ├── PdfIngredientItem/
│   │   │   │   ├── FoodName.tsx
│   │   │   │   └── index.tsx
│   │   │   └── index.tsx
│   │   ├── getIngredient.ts
│   │   ├── index.ts
│   │   ├── ingredientForm.ts
│   │   ├── types.ts
│   │   ├── useGetIngredientFormStatsTree.ts
│   │   └── useIngredientsFormsActions.ts
│   ├── layout/
│   │   ├── MainLayout.tsx
│   │   ├── Page/
│   │   │   ├── ElementContainer.tsx
│   │   │   ├── PageBody.tsx
│   │   │   ├── PageFooter.tsx
│   │   │   ├── PageHeader.tsx
│   │   │   └── index.tsx
│   │   ├── RightAligned.tsx
│   │   ├── index.tsx
│   │   └── useHasSideNavigation.ts
│   ├── meals/
│   │   ├── MealsList/
│   │   │   ├── EmptyList.tsx
│   │   │   ├── MealItem/
│   │   │   │   ├── Header/
│   │   │   │   │   ├── MenuOrDrawer.tsx
│   │   │   │   │   ├── Name.tsx
│   │   │   │   │   ├── getMenuOrDrawerItems.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Notes.tsx
│   │   │   │   ├── PresenceAnimation.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── useGetAndUpdateStats.ts
│   │   │   │   └── useMealFormEvents.ts
│   │   │   ├── MealsControls.tsx
│   │   │   ├── index.tsx
│   │   │   └── useScrollToAndFocusMeal.ts
│   │   ├── PdfMealsList/
│   │   │   ├── Notes.tsx
│   │   │   ├── PdfMealItem.tsx
│   │   │   └── index.tsx
│   │   ├── index.ts
│   │   ├── mealForm.ts
│   │   ├── types.ts
│   │   ├── useGetMealFormStatsTree.ts
│   │   └── useMealsFormsActions.ts
│   ├── notes/
│   │   ├── EditNotesModal/
│   │   │   ├── Content/
│   │   │   │   ├── Form/
│   │   │   │   │   ├── Header.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── NotesFormProvider.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── notesForm.ts
│   │   │   └── index.tsx
│   │   ├── index.ts
│   │   └── notesForm.ts
│   ├── persistence/
│   │   ├── DownloadButton.tsx
│   │   ├── file.ts
│   │   ├── fixWhiteSpace.tsx
│   │   ├── getUntitledFileName.ts
│   │   ├── index.ts
│   │   ├── useBlobUrl.ts
│   │   ├── useImportFileError.ts
│   │   └── useSaveValue.ts
│   ├── portions/
│   │   ├── PortionsMenuOrDrawer/
│   │   │   ├── Drawer/
│   │   │   │   ├── PortionItem.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── Menu.tsx
│   │   │   ├── Trigger.tsx
│   │   │   └── index.tsx
│   │   ├── PortionsSelect.tsx
│   │   ├── defaultPortions.ts
│   │   ├── formatAmount.ts
│   │   ├── getAmountFromPortionsToGrams.ts
│   │   ├── getIngredientPortionDescription.ts
│   │   ├── getPortionDescription.ts
│   │   ├── getToGramsConversionFactor.ts
│   │   ├── index.ts
│   │   ├── types.ts
│   │   ├── useGetAmount.ts
│   │   ├── useGetToGramsConversionFactor.ts
│   │   └── usePortionsStore.ts
│   ├── react-app-env.d.ts
│   ├── reportWebVitals.ts
│   ├── setupTests.ts
│   ├── stats/
│   │   ├── AmountInput.tsx
│   │   ├── EnergyStat.tsx
│   │   ├── PdfStat.tsx
│   │   ├── PdfStatsLayout.tsx
│   │   ├── Stat.tsx
│   │   ├── StatValueDetail.tsx
│   │   ├── StatsFormFields/
│   │   │   ├── MacrosFormFields.tsx
│   │   │   ├── ReavealButton.tsx
│   │   │   ├── StatFormField/
│   │   │   │   ├── ReadOnlyInput.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── types.ts
│   │   │   │   └── useGetInputElement.tsx
│   │   │   ├── VitaminsAndMineralsFormFields.tsx
│   │   │   ├── index.tsx
│   │   │   ├── useGetDailyValuePercent.ts
│   │   │   └── useGetValue.ts
│   │   ├── StatsLayout.tsx
│   │   ├── amountAsNumber.ts
│   │   ├── calculations/
│   │   │   ├── aggregateStats.ts
│   │   │   ├── getDailyValuePercent.ts
│   │   │   ├── getEnergiesEstimates.ts
│   │   │   ├── getMacrosPercents.ts
│   │   │   ├── getStatsTree.ts
│   │   │   ├── index.ts
│   │   │   └── roundMacrosPercents.ts
│   │   ├── getUnit.ts
│   │   ├── index.ts
│   │   ├── objectFromNutritionDataKeys.ts
│   │   ├── statsVariants.ts
│   │   ├── types.ts
│   │   ├── useMealsStatsStore.ts
│   │   ├── useUpdateMealStats.ts
│   │   └── useVariantStats.ts
│   ├── theme/
│   │   ├── colors.ts
│   │   ├── components/
│   │   │   ├── Alert.ts
│   │   │   ├── Button.ts
│   │   │   ├── Divider.ts
│   │   │   ├── Input.ts
│   │   │   ├── Textarea.ts
│   │   │   └── index.ts
│   │   ├── getComputedColorFromChakra.ts
│   │   ├── index.ts
│   │   └── styles.ts
│   ├── undoRedo/
│   │   ├── UndoRedoButtons/
│   │   │   ├── RedoButton.tsx
│   │   │   ├── UndoButton.tsx
│   │   │   └── index.tsx
│   │   ├── appLocation.ts
│   │   ├── deltasStack.ts
│   │   ├── index.ts
│   │   ├── useDietFormVersionsStore.ts
│   │   └── useKeyboard.ts
│   └── variants/
│       ├── PdfVariantsList/
│       │   ├── PdfVariantItem.tsx
│       │   └── index.tsx
│       ├── VariantStats/
│       │   ├── EnergyStat.tsx
│       │   ├── VariantStat.tsx
│       │   └── index.tsx
│       ├── VariantsDetailsModal/
│       │   ├── Content/
│       │   │   ├── FormFields.tsx
│       │   │   ├── VariantsDetailsFormProvider.tsx
│       │   │   ├── index.tsx
│       │   │   ├── useVariantFormEvents.ts
│       │   │   └── variantsDetailsForm.ts
│       │   └── index.tsx
│       ├── VariantsList/
│       │   ├── AddVariantButton.tsx
│       │   ├── ScrollButtons.tsx
│       │   ├── VariantItem/
│       │   │   ├── PresenceAnimation.tsx
│       │   │   ├── getMenuOrDrawerItems.tsx
│       │   │   ├── index.tsx
│       │   │   ├── useScrollIntoView.ts
│       │   │   └── useVariantFormEvents.ts
│       │   ├── VariantNameModal/
│       │   │   ├── Content.tsx
│       │   │   ├── VariantNameFormProvider.tsx
│       │   │   ├── index.tsx
│       │   │   ├── useSubmitVariantNameForm.ts
│       │   │   └── variantNameForm.ts
│       │   ├── VariantsMenuOrDrawer/
│       │   │   ├── Drawer/
│       │   │   │   ├── VariantItem.tsx
│       │   │   │   └── index.tsx
│       │   │   ├── Menu.tsx
│       │   │   ├── Trigger.tsx
│       │   │   └── index.tsx
│       │   ├── index.tsx
│       │   ├── useScrollState.ts
│       │   └── useVariantFormEvents.ts
│       ├── getVariantFormIndexAfterRemove.ts
│       ├── index.ts
│       ├── useGetVariantFormStatsTree.ts
│       ├── useVariantsFormsActions.ts
│       └── variantForm.ts
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*


================================================
FILE: .husky/.gitignore
================================================
_


================================================
FILE: .husky/pre-commit
================================================
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged


================================================
FILE: .prettierignore
================================================
**/node_modules
**/dist
**/package.json
**/yarn.lock
**/package-lock.json
**/.eslintrc.json
**/tsconfig.json

================================================
FILE: .prettierrc
================================================
{
  "arrowParens": "avoid",
  "singleQuote": true,
  "semi": false,
  "printWidth": 80
} 

================================================
FILE: .vscode/settings.json
================================================
{
  "editor.formatOnPaste": true,
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode"
} 

================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2021 Vladimir Angelov

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
<p align="center">
   <a href="https://calories-in.com" target="_blank">
    <img src="devices-preview.png" alt="Devices preview" />
  </a>
</p>
<h1 align="center">Calories-In</h1>

<div align="center">

  <h3>A web-based meal plan editor for people who prepare all of their food.</h3>
  
<br />

Live version: https://calories-in.com

Demo video: https://tella.video/calories-in-4onp

</div>

## Background

The idea was born out of my experience of trying to find a better alternative to Google Sheets for calculating the macros of my meal plans. I wanted to be able to do this on desktop as it's more convenient but nothing really felt fast and simple enough.

A huge inspiration for me has been [excalidraw.com](http://excalidraw.com).

## Notable libraries

- [Chakra UI](https://chakra-ui.com/)
- [React Beautiful Dnd](https://github.com/atlassian/react-beautiful-dnd)
- [React-pdf](https://react-pdf.org/)
- [Comlink-loader](https://github.com/GoogleChromeLabs/comlink-loader)
- [React window](https://github.com/bvaughn/react-window)
- [Fuse.js](https://fusejs.io/)
- [Framer Motion](https://www.framer.com/motion/)
- [Feather icons](https://feathericons.com/)

## Available Scripts

In the project directory, you can run:

### `yarn start`

Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.

### `yarn build`

Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.


================================================
FILE: package.json
================================================
{
  "name": "energytab",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@chakra-ui/react": "^1.3.4",
    "@emotion/css": "^11.1.3",
    "@emotion/react": "^11.1.5",
    "@emotion/styled": "^11.1.5",
    "@hookform/resolvers": "^2.6.0",
    "@react-hook/resize-observer": "^1.2.0",
    "@react-pdf/renderer": "^2.0.19",
    "@szhsin/react-menu": "1.11.0",
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "@types/jest": "^26.0.15",
    "@types/node": "^12.0.0",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.0",
    "@types/react-window": "^1.8.3",
    "@types/smoothscroll-polyfill": "^0.3.1",
    "@types/uuid": "^8.3.0",
    "comlink-loader": "^2.0.0",
    "focus-visible": "^5.2.0",
    "format-quantity": "^1.0.1",
    "framer-motion": "^3.10.0",
    "fuse.js": "^6.4.6",
    "immer": "^9.0.5",
    "jsondiffpatch": "^0.4.1",
    "numeric-quantity": "^1.0.2",
    "pretty-bytes": "^5.6.0",
    "react": "^17.0.1",
    "react-beautiful-dnd": "13.0.0",
    "react-device-detect": "^1.17.0",
    "react-dom": "^17.0.1",
    "react-feather": "^2.0.9",
    "react-hook-form": "7.8.5",
    "react-merge-refs": "^1.1.0",
    "react-scripts": "4.0.3",
    "react-window": "^1.8.6",
    "scroll-polyfill": "^1.0.1",
    "source-map-explorer": "^2.5.2",
    "typescript": "^4.1.2",
    "uuid": "^8.3.2",
    "web-vitals": "^1.0.1",
    "yup": "^0.32.9"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "format": "prettier --write src/**/*.{ts,tsx}",
    "lint": "tsc --noEmit && eslint src/**/*.{ts,tsx}",
    "prepare": "husky install",
    "analyze": "source-map-explorer 'build/static/js/*.js'"
  },
  "lint-staged": {
    "src/**/*.{ts,tsx}": [
      "yarn lint"
    ],
    "*.{ts,tsx}": "prettier --write"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@types/react-beautiful-dnd": "^13.0.0",
    "@types/react-custom-scroll": "^4.2.1",
    "@types/react-custom-scrollbars": "^4.0.7",
    "husky": "^6.0.0",
    "lint-staged": "^10.5.4",
    "prettier": "^2.2.1"
  }
}


================================================
FILE: public/browserconfig.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
    <msapplication>
        <tile>
            <square150x150logo src="/mstile-150x150.png"/>
            <TileColor>#da532c</TileColor>
        </tile>
    </msapplication>
</browserconfig>


================================================
FILE: public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    
    <meta
      name="description"
      content="Build custom meals plans faster"
    />

    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
    <link rel="manifest" href="/site.webmanifest">
    <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
    <meta name="msapplication-TileColor" content="#da532c">
    <meta name="theme-color" content="#319795"> 
    
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.usefathom.com/script.js" data-site="%REACT_APP_FATHOM_SITE%" defer></script>
    <title>Calories-In</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>


================================================
FILE: public/robots.txt
================================================
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:


================================================
FILE: public/site.webmanifest
================================================
{
    "name": "",
    "short_name": "",
    "icons": [
        {
            "src": "/android-chrome-192x192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
            "src": "/android-chrome-512x512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ],
    "theme_color": "#319795",
    "background_color": "#319795",
    "display": "standalone"
}


================================================
FILE: src/App.tsx
================================================
import { ChakraProvider } from '@chakra-ui/react'
import { MainLayout } from 'layout'
import 'focus-visible/dist/focus-visible'
import theme from 'theme'
import { FoodsStoreProvider } from 'foods'
import { loadFoods } from 'foods/persistence'
import { OneTimeCheckStoreProvider, ScreenSizeProvider } from 'general'
import { DietEditor } from 'diets'
import { useState } from 'react'
import { PortionsStoreProvider } from 'portions'

import 'scroll-polyfill/auto'

function App() {
  const [foods] = useState(loadFoods)

  return (
    <ChakraProvider theme={theme}>
      <ScreenSizeProvider>
        <OneTimeCheckStoreProvider>
          <PortionsStoreProvider>
            <FoodsStoreProvider initialFoods={foods}>
              <MainLayout>
                <DietEditor />
              </MainLayout>
            </FoodsStoreProvider>
          </PortionsStoreProvider>
        </OneTimeCheckStoreProvider>
      </ScreenSizeProvider>
    </ChakraProvider>
  )
}

export default App


================================================
FILE: src/diets/DietEditor/DndContextProvider.tsx
================================================
import { useDietFormActions } from 'diets'
import { ReactNode } from 'react'

import { DragDropContext, DropResult } from 'react-beautiful-dnd'

type Props = {
  children: ReactNode
}

function DndContextProvider({ children }: Props) {
  const dietFormActions = useDietFormActions()

  const onDragEnd = (dropResult: DropResult) => {
    const { source, destination, type } = dropResult

    if (!destination) {
      return
    }

    if (type === 'variantsList') {
      dietFormActions.moveVariantForm(source.index, destination.index)
    } else if (type === 'mealsList') {
      dietFormActions.moveMealForm(source.index, destination.index)
    } else if (type === 'ingredientsList') {
      dietFormActions.moveIngredientForm(
        source.droppableId,
        source.index,
        destination.droppableId,
        destination.index
      )
    }
  }

  return <DragDropContext onDragEnd={onDragEnd}>{children}</DragDropContext>
}

export default DndContextProvider


================================================
FILE: src/diets/DietEditor/Form/About.tsx
================================================
import {
  Modal,
  ModalOverlay,
  ModalContent,
  ModalHeader,
  ModalFooter,
  ModalBody,
  ModalCloseButton,
  Button,
  Text,
  ListItem,
  List,
  ListIcon,
} from '@chakra-ui/react'
import { CheckCircle } from 'react-feather'

type Props = {
  isOpen: boolean
  onClose: () => void
}

function About({ isOpen, onClose }: Props) {
  return (
    <Modal isOpen={isOpen} onClose={onClose} size="2xl" scrollBehavior="inside">
      <ModalOverlay />
      <ModalContent>
        <ModalHeader>About </ModalHeader>
        <ModalCloseButton />
        <ModalBody>
          <Text fontSize="lg">
            <Text>Hi, I'm Vladimir, the person behind this project.</Text>
            <br />
            <Text>
              <Text fontWeight="semibold" as="span" textColor="teal.600">
                Calories-In
              </Text>{' '}
              is made for people who follow meal plans that involve preparing
              everything by yourself and gives them full control to fine tune
              the nutritional values.
            </Text>
            <br />
            <Text>
              The idea was born out of my experience of trying to find a better
              alternative to Google Sheets for calculating the macros of my own
              meal plans. I wanted to be able to do this on desktop as it's more
              convenient but nothing really felt fast and simple enough.
            </Text>
            <br />
            <Text>The main differences to other apps in this space are:</Text>
            <br />
            <List ml={8}>
              <ListItem>
                <ListIcon as={CheckCircle} color="teal.600" />
                <Text fontWeight="semibold" as="span" textColor="teal.600">
                  Faster search
                </Text>
                <Text mt={1}>
                  There are actually not that many foods you need when you
                  prepare everything yourself. This means all of the food data
                  can be downloaded beforehand which makes the search super
                  fast. Of course you can add your own foods if you'd like.{' '}
                </Text>
              </ListItem>
              <br />
              <ListItem>
                <ListIcon as={CheckCircle} color="teal.600" />
                <Text fontWeight="semibold" as="span" textColor="teal.600">
                  Undo/Redo
                </Text>
                <Text mt={1}>
                  Building a plan from scratch or updating an existing one
                  involves some back and forth choosing the right foods and
                  adjusting their amounts. This is especially true if you want
                  to be as close as possible to a specific calorie limit and
                  have your macros be a certain percentages split.
                </Text>
              </ListItem>
              <br />
              <ListItem>
                <ListIcon as={CheckCircle} color="teal.600" />
                <Text fontWeight="semibold" as="span" textColor="teal.600">
                  Faster export
                </Text>
                <Text mt={1}>
                  Creating the PDF file for your meal plan is done entirely
                  inside the browser. It does not involve generating and
                  downloading it from a server. This means I can keep the cost
                  of running the website low and you get your file in just a few
                  seconds.
                </Text>
              </ListItem>
              <br />
              <ListItem>
                <ListIcon as={CheckCircle} color="teal.600" />
                <Text fontWeight="semibold" as="span" textColor="teal.600">
                  Simpler
                </Text>

                <Text mt={1}>
                  There are no other pages except the editor. Most of the other
                  tools are bloated with additional features for professionals,
                  such as managing clients, creating invoices, etc.
                </Text>
              </ListItem>
              <br />
              <ListItem>
                <ListIcon as={CheckCircle} color="teal.600" />
                <Text fontWeight="semibold" as="span" textColor="teal.600">
                  Fully mobile
                </Text>
                <Text mt={1}>
                  You can use your phone or tablet to build your meal plans
                  right from your browser. If you add the app to your home
                  screen it will look and feel almost like a native one.
                </Text>
              </ListItem>
            </List>
            <br />
          </Text>
        </ModalBody>

        <ModalFooter>
          <Button size="lg" onClick={onClose}>
            Close
          </Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  )
}

export default About


================================================
FILE: src/diets/DietEditor/Form/Controls/ExportButton.tsx
================================================
import { ScreenSize, useScreenSize } from 'general'
import { Button, ButtonProps, IconButton } from '@chakra-ui/react'
import { Share } from 'react-feather'
import { canExportDietForm } from 'diets/persistence'
import { useDietForm } from 'diets'

type Props = {} & ButtonProps

function ExportButton({ ...rest }: Props) {
  const screenSize = useScreenSize()
  const dietForm = useDietForm()
  const canExport = canExportDietForm(dietForm)

  const commonProps: ButtonProps = {
    isDisabled: !canExport,
    ...rest,
  }

  if (screenSize >= ScreenSize.Medium) {
    return (
      <Button
        leftIcon={<Share size={16} pointerEvents="none" />}
        variant="solid"
        colorScheme="teal"
        size="md"
        {...commonProps}
      >
        Export
      </Button>
    )
  }

  return (
    <IconButton
      isDisabled={!canExport}
      aria-label="Export"
      colorScheme="teal"
      size="md"
      icon={<Share size={20} pointerEvents="none" />}
      {...commonProps}
    />
  )
}

export default ExportButton


================================================
FILE: src/diets/DietEditor/Form/Controls/MenuOrDrawer.tsx
================================================
import { chakra } from '@chakra-ui/react'
import { Download, List, MoreHorizontal, Trash } from 'react-feather'
import {
  MenuOrDrawer as MenuOrDrawerBase,
  MenuOrDrawerItem,
  MenuOrDrawerSeparator,
  ScreenSize,
  useScreenSize,
} from 'general'

const DownloadStyled = chakra(Download)
const ListStyled = chakra(List)
const TrashStyled = chakra(Trash)

type Props = {
  onImport: () => void
  onClear: () => void
  onViewFoods: () => void
}

function MenuOrDrawer({ onImport, onClear, onViewFoods }: Props) {
  const screenSize = useScreenSize()

  const items = [
    <MenuOrDrawerSeparator key="separator" />,
    <MenuOrDrawerItem
      key="importMealPlan"
      icon={<DownloadStyled />}
      onClick={onImport}
    >
      Import meal plan
    </MenuOrDrawerItem>,
    <MenuOrDrawerItem
      key="manageFoods"
      icon={<ListStyled />}
      onClick={onViewFoods}
    >
      Manage foods
    </MenuOrDrawerItem>,
  ]

  if (screenSize <= ScreenSize.Small) {
    items.unshift(
      <MenuOrDrawerItem
        key="clearMealPlan"
        icon={<TrashStyled />}
        onClick={onClear}
      >
        Clear
      </MenuOrDrawerItem>
    )
  }

  return (
    <MenuOrDrawerBase
      size="md"
      title="More actions"
      variant="solid"
      mr={2}
      icon={<MoreHorizontal size={20} />}
      aria-label="More actions"
    >
      {items}
    </MenuOrDrawerBase>
  )
}

export default MenuOrDrawer


================================================
FILE: src/diets/DietEditor/Form/Controls/Name.tsx
================================================
import { useDietForm, useDietFormActions } from 'diets'
import { Editable, EditableInput, EditablePreview } from '@chakra-ui/react'
import { ChangeEvent, useEffect, useRef } from 'react'
import getComputedColorFromChakra from 'theme/getComputedColorFromChakra'
import { canExportDietForm } from 'diets/persistence'

function Name() {
  const dietForm = useDietForm()
  const dietFormActions = useDietFormActions()
  const editablePreviewRef = useRef<HTMLDivElement>(null)
  const focusedForDietFieldIdMap = useRef<Record<string, boolean | undefined>>(
    {}
  )

  useEffect(() => {
    if (
      !canExportDietForm(dietForm) &&
      editablePreviewRef.current &&
      !focusedForDietFieldIdMap.current[dietForm.fieldId]
    ) {
      editablePreviewRef.current.focus()
      focusedForDietFieldIdMap.current[dietForm.fieldId] = true
    }
  }, [dietForm])

  function onNameChange(event: ChangeEvent<HTMLInputElement>) {
    const { value } = event.target
    dietFormActions.updateDietForm({ name: value })
  }

  const boxShadowColor = getComputedColorFromChakra('teal.400')

  return (
    <Editable
      fontSize="lg"
      fontWeight="medium"
      textAlign="center"
      value={dietForm.name}
      width="85%"
      data-test-type="diet-name"
    >
      <EditablePreview ref={editablePreviewRef} width="100%" />
      <EditableInput
        _focus={{ boxShadow: `${boxShadowColor} 0px 0px 0px 3px` }}
        onChange={onNameChange}
      />
    </Editable>
  )
}

export default Name


================================================
FILE: src/diets/DietEditor/Form/Controls/index.tsx
================================================
import { Flex, useDisclosure, Button } from '@chakra-ui/react'
import { UndoRedoButtons, useKeyboard } from 'undoRedo'
import { getDietForm, useDietFormActions } from 'diets'
import { useImportDietForm, ExportModal } from 'diets/persistence'
import {
  FoodsListModal,
  MissingFoodsModal,
  useImportFoods,
} from 'foods/persistence'
import { FoodsDrawer } from 'foods'
import { Trash } from 'react-feather'
import MenuOrDrawer from './MenuOrDrawer'
import Name from './Name'
import { ScreenSize, useScreenSize } from 'general'
import ExportButton from './ExportButton'

function Controls() {
  const dietFormActions = useDietFormActions()
  const exportModalDisclosure = useDisclosure()
  const missingFoodsModalDisclosure = useDisclosure()
  const { onLoadFromFile } = useImportDietForm({ missingFoodsModalDisclosure })
  const foodsListModalDisclosure = useDisclosure()
  const importFoods = useImportFoods({ foodsListModalDisclosure })
  const foodsDrawerDisclosure = useDisclosure()
  const screenSize = useScreenSize()

  useKeyboard()

  function onClear() {
    dietFormActions.setDietForm(getDietForm())
  }

  return (
    <Flex width="100%" alignItems="center">
      <Flex flex={1} mr={2}>
        <UndoRedoButtons />
      </Flex>

      <Flex flexShrink={1} justifyContent="center" flex={4}>
        <Name />
      </Flex>

      <Flex ml={2} justifyContent="flex-end" spacing={3} flex={1}>
        <MenuOrDrawer
          onImport={onLoadFromFile}
          onClear={onClear}
          onViewFoods={foodsDrawerDisclosure.onOpen}
        />

        {screenSize >= ScreenSize.Medium && (
          <Button
            leftIcon={<Trash size={16} />}
            size="md"
            onClick={onClear}
            mr={2}
          >
            Clear
          </Button>
        )}

        <ExportButton onClick={exportModalDisclosure.onOpen} />
      </Flex>

      <MissingFoodsModal
        isOpen={missingFoodsModalDisclosure.isOpen}
        onClose={missingFoodsModalDisclosure.onClose}
        onImport={importFoods.onImport}
      />

      <FoodsListModal
        isOpen={foodsListModalDisclosure.isOpen}
        onClose={foodsListModalDisclosure.onClose}
        foodsToImport={importFoods.foodsToImport}
      />

      <FoodsDrawer
        isOpen={foodsDrawerDisclosure.isOpen}
        onClose={foodsDrawerDisclosure.onClose}
        canSelect={false}
      />

      <ExportModal
        isOpen={exportModalDisclosure.isOpen}
        onClose={exportModalDisclosure.onClose}
      />
    </Flex>
  )
}

export default Controls


================================================
FILE: src/diets/DietEditor/Form/Footer.tsx
================================================
import { Box, HStack, Button, Divider, Link, BoxProps } from '@chakra-ui/react'

type Props = {
  onAbout: () => void
} & BoxProps

function Footer({ onAbout, ...rest }: Props) {
  return (
    <Box {...rest}>
      <Divider />
      <HStack height="50px" spacing={3}>
        <Button
          variant="link"
          color="gray.500"
          fontWeight="thin"
          py={0.5}
          onClick={onAbout}
        >
          About
        </Button>

        <Link
          color="gray.500"
          target="_blank"
          href="https://www.termsfeed.com/live/7e9b9ec6-aca7-4c99-a987-feb8b535a8e9"
        >
          Terms
        </Link>

        <Link
          color="gray.500"
          target="_blank"
          href="https://www.termsfeed.com/live/ff5061b9-09e0-4fae-a8e9-010274f2085c"
        >
          Disclaimer
        </Link>
      </HStack>
    </Box>
  )
}

export default Footer


================================================
FILE: src/diets/DietEditor/Form/index.tsx
================================================
import { useDietForm, useScrollManager } from 'diets'
import { DietFormVersionsStoreProvider } from 'undoRedo'
import { useRef } from 'react'
import { Page, PageHeader, PageBody } from 'layout'
import { MealsList } from 'meals'
import useDietFormEvents from './useDietFormEvents'
import { Box, useDisclosure, Flex } from '@chakra-ui/react'
import { ScreenSize, useElementHeight, useScreenSize } from 'general'
import Controls from './Controls'
import { FoodsDrawer } from 'foods'
import { VariantsList, VariantStats } from 'variants'
import useVariantFormEvents from './useVariantFormActions'
import About from './About'
import Footer from './Footer'

function Form() {
  const horizontalScrollRef = useRef<HTMLDivElement>(null)
  const dietForm = useDietForm()
  const { variantsForms } = dietForm
  const selectedVariantForm = variantsForms[dietForm.selectedVariantFormIndex]

  const scrollManager = useScrollManager({
    selectedVariantForm,
    horizontalScrollRef,
  })

  const foodsDrawerDisclosure = useDisclosure()
  const dietFormEvents = useDietFormEvents({
    scrollManager,
    foodsDrawerDisclosure,
  })

  const {
    elementHeight: headerHeight,
    elementRef: headerRef,
  } = useElementHeight()
  const variantFormEvents = useVariantFormEvents({ scrollManager })

  const screenSize = useScreenSize()

  const aboutModalDisclosure = useDisclosure()

  return (
    <DietFormVersionsStoreProvider
      horizontalScrollRef={horizontalScrollRef}
      form={dietForm}
      onUndo={dietFormEvents.onUndoOrRedo}
      onRedo={dietFormEvents.onUndoOrRedo}
    >
      <Page>
        <PageHeader ref={headerRef}>
          <Box bg="white" py={3}>
            <Controls />
          </Box>
        </PageHeader>

        <PageBody>
          <VariantsList
            onVariantFormCopy={variantFormEvents.onVariantFormCopy}
            onVariantFormSelect={variantFormEvents.onVariantFormSelect}
            ref={horizontalScrollRef}
          />

          <Flex>
            <MealsList
              flex={1}
              headerHeight={headerHeight}
              selectedVariantFormFieldId={selectedVariantForm.fieldId}
              mealsForms={selectedVariantForm.mealsForms}
              selectedVariantFormIndex={dietForm.selectedVariantFormIndex}
              onAddMeal={foodsDrawerDisclosure.onOpen}
            />

            {screenSize >= ScreenSize.Large && (
              <VariantStats
                data-test-type="variant-stats"
                position="sticky"
                top={`${headerHeight + 24}px`}
                ml={6}
                width="300px"
                bg="white"
                borderRadius={6}
                boxShadow="base"
              />
            )}
          </Flex>

          <Footer mt={10} onAbout={aboutModalDisclosure.onOpen} />

          <FoodsDrawer
            isOpen={foodsDrawerDisclosure.isOpen}
            onClose={foodsDrawerDisclosure.onClose}
            mealName={`Meal ${selectedVariantForm.mealsForms.length + 1}`}
            onSelectedFoods={dietFormEvents.onMealAdded}
          />

          <About
            isOpen={aboutModalDisclosure.isOpen}
            onClose={aboutModalDisclosure.onClose}
          />
        </PageBody>
      </Page>
    </DietFormVersionsStoreProvider>
  )
}

export default Form


================================================
FILE: src/diets/DietEditor/Form/useDietFormEvents.ts
================================================
import { UseDisclosureReturn } from '@chakra-ui/hooks'
import { DietForm, useDietFormActions, ScrollManager } from 'diets'
import { Food } from 'foods'
import { getIngredient } from 'ingredients'
import { getMealForm } from 'meals'
import { AppLocation } from 'undoRedo'

type Params = {
  scrollManager: ScrollManager
  foodsDrawerDisclosure: UseDisclosureReturn
}

function useDietFormEvents({ scrollManager, foodsDrawerDisclosure }: Params) {
  const dietFormActions = useDietFormActions()
  const { setScrollState } = scrollManager

  function onMealAdded(foods: Food[], mealName?: string) {
    foodsDrawerDisclosure.onClose()
    const ingredients = foods.map(getIngredient)
    const mealForm = getMealForm({ name: mealName as string, ingredients })
    dietFormActions.appendMealForm(mealForm)
  }

  function onUndoOrRedo(
    form: DietForm,
    { scrollTop, scrollLeft, variantIndex }: AppLocation
  ) {
    const finalVariantIndex = form.variantsForms[variantIndex]
      ? variantIndex
      : form.selectedVariantFormIndex

    dietFormActions.updateDietForm({
      ...form,
      selectedVariantFormIndex: finalVariantIndex,
    })

    setScrollState({ top: scrollTop, left: scrollLeft })
  }

  return {
    onUndoOrRedo,
    onMealAdded,
  }
}

export default useDietFormEvents


================================================
FILE: src/diets/DietEditor/Form/useVariantFormActions.ts
================================================
import { VariantForm } from 'variants'
import { useCallback } from 'react'
import { ScrollManager } from 'diets/useScrollManager'

type Params = {
  scrollManager: ScrollManager
}

function useVariantFormEvents({ scrollManager }: Params) {
  const { setScrollState, getCachedScrollTop } = scrollManager

  const onVariantFormSelect = useCallback(
    (variantForm: VariantForm) => {
      setScrollState({ top: getCachedScrollTop(variantForm.fieldId) })
    },
    [setScrollState, getCachedScrollTop]
  )

  const onVariantFormCopy = useCallback(() => {
    setScrollState({ top: 0 })
  }, [setScrollState])

  return {
    onVariantFormCopy,
    onVariantFormSelect,
  }
}

export default useVariantFormEvents


================================================
FILE: src/diets/DietEditor/index.tsx
================================================
import { DietFormStoreProvider } from 'diets'
import Form from './Form'
import { useOneTimeCheckActions } from 'general'
import DndContextProvider from './DndContextProvider'
import { MealsStatsStoreProvider } from 'stats'
import { useState } from 'react'
import { loadLastOrDefaultDietForm } from 'diets/persistence'

function DietEditor() {
  const oneTimeCheckActions = useOneTimeCheckActions()
  const [dietForm] = useState(loadLastOrDefaultDietForm)

  return (
    <>
      <DietFormStoreProvider
        initialDietForm={dietForm}
        oneTimeCheckActions={oneTimeCheckActions}
      >
        <MealsStatsStoreProvider>
          <DndContextProvider>
            <Form />
          </DndContextProvider>
        </MealsStatsStoreProvider>
      </DietFormStoreProvider>
    </>
  )
}

export default DietEditor


================================================
FILE: src/diets/PdfDietEditor.tsx
================================================
import ReactPDF, {
  Document,
  Page,
  Font,
  StyleSheet,
  View,
} from '@react-pdf/renderer'
import { Food } from 'foods'
import { Portion } from 'portions'
import { ReactElement } from 'react'
import { StatsTree } from 'stats/calculations/getStatsTree'
import getComputedColorFromChakra from 'theme/getComputedColorFromChakra'
import PdfVariantItem from 'variants/PdfVariantsList/PdfVariantItem'
import { DietForm } from './dietForm'

type Props = {
  dietForm: DietForm
  foodsById: Record<number, Food>
  portionsById: Record<string, Portion>

  dietFormStatsTree: StatsTree
} & ReactPDF.DocumentProps

function PdfDietEditor({
  dietForm,
  foodsById,
  portionsById,
  dietFormStatsTree,
  ...rest
}: Props) {
  const { variantsForms } = dietForm

  const variantItemsElements: ReactElement[] = []

  variantsForms.forEach((variantForm, index) => {
    const { mealsForms } = variantForm
    const { stats, subtrees } = dietFormStatsTree.subtrees[index]

    if (mealsForms.length > 0) {
      variantItemsElements.push(
        <PdfVariantItem
          index={variantItemsElements.length}
          key={variantForm.fieldId}
          variantForm={variantForm}
          stats={stats}
          mealsFormsStatsTrees={subtrees}
          foodsById={foodsById}
          portionsById={portionsById}
        />
      )
    }
  })

  return (
    <Document {...rest}>
      <Page
        style={[
          styles.page,
          { backgroundColor: getComputedColorFromChakra('gray.50') },
        ]}
      >
        <View
          fixed
          style={{
            backgroundColor: getComputedColorFromChakra('teal.500'),
            height: 10,
            alignItems: 'center',
            padding: 4,
            marginBottom: 24,
          }}
        />

        {variantItemsElements}
      </Page>
    </Document>
  )
}

const styles = StyleSheet.create({
  page: {
    fontFamily: 'Roboto',
    paddingBottom: 12,
  },
})

Font.register({
  family: 'Roboto',
  fonts: [
    {
      src:
        'https://fontlibrary.org/assets/fonts/roboto/4f8c3c9bbdde908a86daabfe666d2f61/ac3f799d5bbaf5196fab15ab8de8431c/RobotoRegular.ttf',
      fontWeight: 'normal',
    },

    {
      src:
        'https://fontlibrary.org/assets/fonts/roboto/4f8c3c9bbdde908a86daabfe666d2f61/fe13e4170719c2fc586501e777bde143/RobotoMedium.ttf',
      fontWeight: 'medium',
    },

    {
      src:
        'https://fontlibrary.org/assets/fonts/roboto/4f8c3c9bbdde908a86daabfe666d2f61/d329cc8b34667f114a95422aaad1b063/RobotoBold.ttf',
      fontWeight: 'bold',
    },
  ],
})

export default PdfDietEditor


================================================
FILE: src/diets/dietForm.ts
================================================
import { Diet } from 'diets'
import { getVariantForm, VariantForm } from 'variants'
import { v4 as uuidv4 } from 'uuid'

type DietForm = {
  fieldId: string
  name: string
  selectedVariantFormIndex: number
  variantsForms: VariantForm[]
}

function getDietForm(diet?: Diet): DietForm {
  const variantsForms = [getVariantForm('Day 1')]
  const fieldId = uuidv4()

  if (diet) {
    return {
      fieldId,
      name: diet.name,
      variantsForms,
      selectedVariantFormIndex: 0,
    }
  }

  return {
    fieldId,
    name: 'Untitled',
    variantsForms,
    selectedVariantFormIndex: 0,
  }
}

export type { DietForm }

export { getDietForm }


================================================
FILE: src/diets/index.ts
================================================
export * from './dietForm'
export { default as useDietFormStore } from './useDietFormStore'
export * from './useDietFormStore'
export { default as DietEditor } from './DietEditor'
export * from './types'
export { default as useGetDietFormStatsTree } from './useGetDietFormStatsTree'
export { default as useScrollManager } from './useScrollManager'
export * from './useScrollManager'


================================================
FILE: src/diets/persistence/ExportModal/Content/Exporter/index.tsx
================================================
import { Loader } from 'general'
import {
  Alert,
  AlertIcon,
  AlertTitle,
  AlertDescription,
} from '@chakra-ui/react'
import usePdfExport from './usePdfExport'

type Props = {
  onUpdate: (blob: Blob, url: string) => void
}

function Exporter({ onUpdate }: Props) {
  const { isLoading, error } = usePdfExport({ onUpdate })

  if (isLoading) {
    return <Loader label="Exporting..." />
  }

  return (
    <Alert
      status={error ? 'error' : 'success'}
      variant="subtle"
      flexDirection="column"
      alignItems="center"
      justifyContent="center"
      textAlign="center"
      height="200px"
      bg="white"
    >
      <AlertIcon color={error ? 'red.400' : 'teal.400'} boxSize="40px" mr={0} />
      <AlertTitle mt={4} mb={1} fontSize="lg">
        {error
          ? 'Something went wrong while creating your pdf file'
          : 'Your PDF file is ready'}
      </AlertTitle>
      {!error && (
        <AlertDescription maxWidth="sm">
          Downloading this plan will allow you to import it later if you need to
          update it.
        </AlertDescription>
      )}
    </Alert>
  )
}

export default Exporter


================================================
FILE: src/diets/persistence/ExportModal/Content/Exporter/usePdfExport.ts
================================================
import { useDietForm, useGetDietFormStatsTree } from 'diets'
import { useFoods } from 'foods'
import { usePortions } from 'portions'
import { useEffect, useState } from 'react'
import Worker from './worker'
import { minDelay, useRunIfNotUnmounted } from 'general'

const worker = new Worker()

type Params = {
  onUpdate: (blob: Blob, url: string) => void
}

function usePdfExport({ onUpdate }: Params) {
  const dietForm = useDietForm()
  const { foodsById } = useFoods()
  const { portionsById } = usePortions()
  const getDietFormStatsTree = useGetDietFormStatsTree()
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState<unknown>()

  const runIfNotUnmounted = useRunIfNotUnmounted()

  useEffect(() => {
    async function run() {
      const dietFormStatsTree = getDietFormStatsTree(dietForm)
      const startDate = new Date()

      try {
        setIsLoading(true)
        const blob = await worker.getDietPdfBlob({
          dietForm,
          dietFormStatsTree,
          foodsById,
          portionsById,
        })

        await minDelay(startDate)

        runIfNotUnmounted(() => {
          setIsLoading(false)
          const url = URL.createObjectURL(blob)
          onUpdate(blob, url)
        })
      } catch (error) {
        await minDelay(startDate)

        runIfNotUnmounted(() => {
          setIsLoading(false)
          setError(error)
        })
      }
    }
    run()
  }, [
    dietForm,
    foodsById,
    portionsById,
    getDietFormStatsTree,
    onUpdate,
    runIfNotUnmounted,
  ])

  return {
    isLoading,
    error,
  }
}

export default usePdfExport


================================================
FILE: src/diets/persistence/ExportModal/Content/Exporter/worker/custom.d.ts
================================================
declare module 'comlink-loader!*' {
  import { Params } from './types'

  class WebpackWorker extends Worker {
    constructor()

    getDietPdfBlob(data: Params): Promise<Blob>
  }

  export = WebpackWorker
}


================================================
FILE: src/diets/persistence/ExportModal/Content/Exporter/worker/index.ts
================================================
// eslint-disable-next-line
import Worker from 'comlink-loader!./worker'

export default Worker


================================================
FILE: src/diets/persistence/ExportModal/Content/Exporter/worker/types.ts
================================================
import { DietForm } from 'diets/dietForm'
import { Food } from 'foods/types'
import { Portion } from 'portions/types'
import { StatsTree } from 'stats/calculations'

type Params = {
  dietForm: DietForm
  foodsById: Record<number, Food>
  portionsById: Record<string, Portion>
  dietFormStatsTree: StatsTree
}

export type { Params }


================================================
FILE: src/diets/persistence/ExportModal/Content/Exporter/worker/worker.tsx
================================================
import { pdf } from '@react-pdf/renderer'

if (process.env.NODE_ENV !== 'production') {
  const t: any = global
  t.$RefreshReg$ = () => {}
  t.$RefreshSig$ = () => () => {}
}

async function getDietPdfBlob(data: any) {
  const PdfDietEditor = require('diets/PdfDietEditor').default

  const document = (
    <PdfDietEditor
      dietForm={data.dietForm}
      foodsById={data.foodsById}
      portionsById={data.portionsById}
      subject={JSON.stringify(data.dietForm)}
      dietFormStatsTree={data.dietFormStatsTree}
    />
  )

  return pdf(document).toBlob()
}

export { getDietPdfBlob }


================================================
FILE: src/diets/persistence/ExportModal/Content/index.tsx
================================================
import {
  ModalContent,
  ModalHeader,
  ModalFooter,
  ModalBody,
  ModalCloseButton,
  Button,
  VStack,
  Text,
} from '@chakra-ui/react'
import { useState, useCallback } from 'react'
import { DownloadButton } from 'persistence'
import { useDietForm } from 'diets'
import Exporter from './Exporter'

type Props = {
  onClose: () => void
}

function Content({ onClose }: Props) {
  const [blob, setBlob] = useState<Blob>()
  const [url, setUrl] = useState<string>()
  const dietForm = useDietForm()

  const onUpdate = useCallback((blob: Blob, url: string) => {
    setBlob(blob)
    setUrl(url)
  }, [])

  function onViewInBrowser() {
    window.open(url, '_blank')
  }

  return (
    <ModalContent>
      <ModalHeader fontWeight="normal">
        Export{' '}
        <Text as="span" fontWeight="bold">
          {dietForm.name}
        </Text>
      </ModalHeader>
      <ModalCloseButton />
      <ModalBody px={0}>
        <Exporter onUpdate={onUpdate} />
      </ModalBody>

      <ModalFooter>
        <VStack spacing={3} width="100%">
          {blob && url && (
            <DownloadButton
              blob={blob}
              onClose={onClose}
              label="Download"
              isFullWidth={true}
              fileName={dietForm.name}
              isLoading={blob === undefined}
            />
          )}
          {blob && url && (
            <Button
              mr={3}
              variant="outline"
              colorScheme="teal"
              onClick={onViewInBrowser}
              isFullWidth={true}
            >
              View in browser
            </Button>
          )}

          <Button isFullWidth={true} variant="solid" onClick={onClose}>
            Close
          </Button>
        </VStack>
      </ModalFooter>
    </ModalContent>
  )
}

export default Content


================================================
FILE: src/diets/persistence/ExportModal/index.tsx
================================================
import { Modal, ModalOverlay } from '@chakra-ui/react'
import Content from './Content'

type Props = {
  isOpen: boolean
  onClose: () => void
}

function ExportModal({ isOpen, onClose }: Props) {
  return (
    <Modal size="sm" isOpen={isOpen} onClose={onClose}>
      <ModalOverlay />
      <Content onClose={onClose} />
    </Modal>
  )
}

export default ExportModal


================================================
FILE: src/diets/persistence/canExportDietForm.ts
================================================
import { DietForm } from 'diets'

function canExportDietForm(dietForm: DietForm) {
  const { variantsForms } = dietForm

  return variantsForms.some(({ mealsForms }) => {
    return mealsForms.length > 0
  })
}

export default canExportDietForm


================================================
FILE: src/diets/persistence/hasMissingFoods.ts
================================================
import { DietForm } from 'diets'
import { Food, FoodId } from 'foods'

function hasMissingFoods(dietForm: DietForm, foodsById: Record<FoodId, Food>) {
  const { variantsForms } = dietForm

  for (const variantForm of variantsForms) {
    const { mealsForms } = variantForm

    for (const mealForm of mealsForms) {
      const { ingredientsForms } = mealForm

      for (const ingredientForm of ingredientsForms) {
        const food = foodsById[ingredientForm.foodId]

        if (!food) {
          return true
        }
      }
    }
  }

  return false
}

export default hasMissingFoods


================================================
FILE: src/diets/persistence/index.ts
================================================
export { default as ExportModal } from './ExportModal'
export { default as useImportDietForm } from './useImportDietForm'
export { default as parseDietForm } from './parseDietForm'
export { default as hasMissingFoods } from './hasMissingFoods'
export { default as loadLastOrDefaultDietForm } from './loadLastOrDefaultDietForm'
export { default as canExportDietForm } from './canExportDietForm'


================================================
FILE: src/diets/persistence/loadLastOrDefaultDietForm.ts
================================================
import { getDietForm } from 'diets'

function loadLastOrDefaultDietForm() {
  const savedValue = localStorage.getItem('lastDietForm')

  if (savedValue) {
    try {
      return JSON.parse(savedValue)
    } catch (error) {
      return getDietForm()
    }
  }

  return getDietForm()
}

export default loadLastOrDefaultDietForm


================================================
FILE: src/diets/persistence/parseDietForm.ts
================================================
import { DietForm } from 'diets'
import { fixWhiteSpace } from 'persistence'

function getLocation(text: string) {
  const subject = '/Subject'
  const startIndex = text.indexOf('/Subject')
  const endIndex = text.indexOf('R', startIndex)

  if (startIndex < 0 || endIndex < 0) {
    throw new SyntaxError()
  }
  const locatioPrefix = text.slice(startIndex + subject.length, endIndex).trim()
  return `${locatioPrefix} obj`
}

function getData(location: string, text: string) {
  const startIndex = text.indexOf(location)
  const endIndex = text.indexOf('endobj', startIndex)

  if (startIndex < 0 || endIndex < 0) {
    throw new SyntaxError()
  }

  return text.slice(startIndex + location.length + 2, endIndex - 2)
}

function parseDietForm(text: string) {
  const location = getLocation(text)
  const data = getData(location, text)
  const dietForm = JSON.parse(data, (key: string, value) => {
    if (key === 'notes') {
      return fixWhiteSpace(value)
    }

    return value
  }) as DietForm

  return dietForm
}

export default parseDietForm


================================================
FILE: src/diets/persistence/useDietImportErrors.tsx
================================================
import { useToast } from '@chakra-ui/toast'
import { Text, Button, UseDisclosureReturn } from '@chakra-ui/react'

type Params = {
  missingFoodsModalDisclosure: UseDisclosureReturn
}

function useDietImportErrors({ missingFoodsModalDisclosure }: Params) {
  const toast = useToast()

  function onLearnAboutMissingFoods() {
    toast.closeAll()
    missingFoodsModalDisclosure.onOpen()
  }

  function onMissingFoods() {
    toast({
      isClosable: true,
      position: 'top',
      title: 'File imported',
      description: (
        <Text>
          Warning: Foods missing.{' '}
          <Button
            variant="link"
            colorScheme="white"
            onClick={onLearnAboutMissingFoods}
          >
            Learn more
          </Button>
        </Text>
      ),
      status: 'warning',
      duration: null,
    })
  }

  return {
    onMissingFoods,
    missingFoodsModalDisclosure,
  }
}

export default useDietImportErrors


================================================
FILE: src/diets/persistence/useImportDietForm.ts
================================================
import { selectFile, readFile } from 'persistence'
import { useFoods } from 'foods'
import { useDietFormActions } from 'diets'
import { hasMissingFoods, parseDietForm } from 'diets/persistence'
import useFileImportError from 'persistence/useImportFileError'
import { useToast } from '@chakra-ui/toast'
import useDietImportErrors from './useDietImportErrors'
import { UseDisclosureReturn } from '@chakra-ui/hooks'

type Params = {
  missingFoodsModalDisclosure: UseDisclosureReturn
}

function useImportDietForm({ missingFoodsModalDisclosure }: Params) {
  const { foodsById } = useFoods()
  const dietFormActions = useDietFormActions()
  const fileImportError = useFileImportError()
  const dietImportErrors = useDietImportErrors({ missingFoodsModalDisclosure })
  const toast = useToast()

  async function onLoadFromFile() {
    const file = await selectFile('application/pdf')

    try {
      const text = await readFile(file)
      const dietForm = parseDietForm(text)

      if (hasMissingFoods(dietForm, foodsById)) {
        dietImportErrors.onMissingFoods()
      } else {
        toast({
          status: 'success',
          position: 'top',
          title: 'Meal plan imported',
          duration: 2000,
          isClosable: true,
        })
      }
      dietFormActions.setDietForm(dietForm)
    } catch (error: any) {
      fileImportError.onError({ error, file })
    }
  }

  return {
    onLoadFromFile,
    missingFoodsModalDisclosure: dietImportErrors.missingFoodsModalDisclosure,
  }
}

export default useImportDietForm


================================================
FILE: src/diets/types.ts
================================================
import { Meal } from 'meals'

type Diet = {
  id: number
  name: string
  meals: Meal[]
}

export type { Diet }


================================================
FILE: src/diets/useDietFormStore.ts
================================================
import { useCallback, useState } from 'react'
import { DietForm } from './dietForm'
import { useVariantsFormsActions, VariantsFormsActions } from 'variants'
import { useMealsFormsActions, MealsFormsActions } from 'meals'
import { useCallbacksMemo, makeStoreProvider } from 'general'
import {
  useIngredientsFormsActions,
  IngredientsFormsActions,
} from 'ingredients'
import { OneTimeCheckActions } from 'general'
import { useSaveValue } from 'persistence'

export type Params = {
  initialDietForm: DietForm
  oneTimeCheckActions: OneTimeCheckActions
}

type Actions = VariantsFormsActions &
  MealsFormsActions &
  IngredientsFormsActions

function useDietFormStore({
  initialDietForm,

  oneTimeCheckActions,
}: Params) {
  const [dietForm, setDietForm] = useState(initialDietForm)

  useSaveValue({ value: dietForm, key: 'lastDietForm' })

  const variantsFormsActions = useVariantsFormsActions({
    setDietForm,
    oneTimeCheckActions,
  })

  const mealsFormsActions = useMealsFormsActions({
    setDietForm,
    oneTimeCheckActions,
  })

  const ingredientsFormsActions = useIngredientsFormsActions({
    setDietForm,
    oneTimeCheckActions,
  })

  const updateDietForm = useCallback(
    (partialDietForm: Partial<DietForm>) => {
      setDietForm(dietForm => {
        return {
          ...dietForm,
          ...partialDietForm,
        }
      })
    },
    [setDietForm]
  )

  const ownActions = {
    setDietForm,
    updateDietForm,
  }

  const actions: Actions & typeof ownActions = useCallbacksMemo({
    ...ownActions,
    ...mealsFormsActions,
    ...variantsFormsActions,
    ...ingredientsFormsActions,
  })

  return [dietForm, actions] as const
}

const [
  DietFormStoreProvider,
  useDietForm,
  useDietFormActions,
] = makeStoreProvider(useDietFormStore)

export { DietFormStoreProvider, useDietForm, useDietFormActions }

export default useDietFormStore


================================================
FILE: src/diets/useGetDietFormStatsTree.ts
================================================
import { StatsTree, getStatsTree } from 'stats'
import { DietForm } from './dietForm'
import { useGetVariantFormStatsTree } from 'variants'
import { useCallback } from 'react'

function useGetDietFormStatsTree() {
  const getVariantFormStatsTree = useGetVariantFormStatsTree()

  const getDietFormStatsTree2 = useCallback(
    (dietForm: DietForm): StatsTree => {
      const subtrees = dietForm.variantsForms.map(variantForm =>
        getVariantFormStatsTree(variantForm)
      )

      return getStatsTree({
        id: dietForm.fieldId,
        subtrees,
        calculateAvg: true,
      })
    },
    [getVariantFormStatsTree]
  )

  return getDietFormStatsTree2
}

export default useGetDietFormStatsTree


================================================
FILE: src/diets/useScrollManager.ts
================================================
import { VariantForm } from 'variants'
import { useState, useRef, useEffect, RefObject, useCallback } from 'react'

type ScrollState = {
  top?: number
  left?: number
}

type Params = {
  selectedVariantForm: VariantForm
  horizontalScrollRef: RefObject<HTMLDivElement>
}

function useScrollManager({
  selectedVariantForm,
  horizontalScrollRef,
}: Params) {
  const scrollTopCacheRef = useRef<Record<string, number | undefined>>({})
  const [scrollState, setScrollState] = useState<ScrollState>({
    top: 0,
    left: 0,
  })

  const getCachedScrollTop = useCallback((variantFormFieldId: string) => {
    return scrollTopCacheRef.current[variantFormFieldId] || 0
  }, [])

  useEffect(() => {
    function onScroll() {
      scrollTopCacheRef.current[selectedVariantForm.fieldId] = window.scrollY
    }
    window.addEventListener('scroll', onScroll)

    return () => {
      window.removeEventListener('scroll', onScroll)
    }
  }, [selectedVariantForm.fieldId])

  useEffect(() => {
    const { top, left } = scrollState

    if (top !== undefined) {
      window.scroll({ top })
    }

    if (left !== undefined && horizontalScrollRef.current) {
      horizontalScrollRef.current.scrollLeft = left
    }
  }, [scrollState, horizontalScrollRef])

  return {
    setScrollState,
    getCachedScrollTop,
  }
}

type ScrollManager = ReturnType<typeof useScrollManager>

export type { ScrollManager }

export default useScrollManager


================================================
FILE: src/dom/animateScrollLeft.ts
================================================
import { animate } from 'framer-motion'
import { RefObject } from 'react'

function animateScrollLeft(nodeRef: RefObject<HTMLDivElement>, delta: number) {
  if (!nodeRef.current) {
    return
  }

  const node = nodeRef.current

  animate(node.scrollLeft, node.scrollLeft + delta, {
    duration: 0.2,
    onUpdate: value => {
      node.scrollLeft = value
    },
  })
}

export default animateScrollLeft


================================================
FILE: src/dom/index.ts
================================================
export { default as animateScrollLeft } from './animateScrollLeft'
export { default as isElementInViewport } from './isElementInViewport'
export { default as useGetRefForId } from './useGetRefForId'
export { default as useScrollTo } from './useScrollTo'


================================================
FILE: src/dom/isElementInViewport.ts
================================================
function isElementInViewport(element: Element) {
  const { top, left, bottom, right } = element.getBoundingClientRect()

  return (
    top >= 0 &&
    left >= 0 &&
    bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
    right <= (window.innerWidth || document.documentElement.clientWidth)
  )
}

export default isElementInViewport


================================================
FILE: src/dom/useGetRefForId.ts
================================================
import { createRef, RefObject, useCallback, useRef } from 'react'

type RefsCache<T> = {
  [id: number]: RefObject<T>
  [id: string]: RefObject<T>
}

function useGetRefForId<T extends HTMLElement = HTMLElement>() {
  const cacheRef = useRef<RefsCache<T>>({})

  const getRef = useCallback((id: number | string) => {
    if (!cacheRef.current[id]) {
      cacheRef.current[id] = createRef()
    }

    return cacheRef.current[id]
  }, [])

  return getRef
}

export default useGetRefForId


================================================
FILE: src/dom/useScrollTo.ts
================================================
import { useEffect, useRef, useCallback } from 'react'

function useScrollTo() {
  const scrollTimeoutRef = useRef<number>()
  const didScrollCheckTimeoutRef = useRef<number>()

  useEffect(() => {
    return () => {
      window.clearTimeout(scrollTimeoutRef.current)
    }
  }, [])

  const scrollTo = useCallback((node: HTMLElement) => {
    return new Promise<void>(resolve => {
      const resolveWihoutScrollTimeout = window.setTimeout(() => {
        window.clearTimeout(didScrollCheckTimeoutRef.current)

        window.removeEventListener('scroll', listener)
        resolve()
      }, 100)

      function listener() {
        window.clearTimeout(scrollTimeoutRef.current)
        window.clearTimeout(resolveWihoutScrollTimeout)

        scrollTimeoutRef.current = window.setTimeout(() => {
          window.removeEventListener('scroll', listener)
          resolve()
        }, 50)
      }

      window.addEventListener('scroll', listener)

      node.scrollIntoView({
        behavior: 'smooth',
        block: 'center',
      })
    })
  }, [])

  return scrollTo
}

export default useScrollTo


================================================
FILE: src/foods/FoodInfo.tsx
================================================
import { Text, Box, Flex, BoxProps, Link } from '@chakra-ui/react'
import { Food } from 'foods'
import { ReactNode } from 'react'
import { DEFAULT_SERVING_SIZE_IN_GRAMS } from './foodForm'

type Props = {
  food: Food
  nameNoOfLines?: number
  canBeLink?: boolean
  notes?: string

  energy?: number
  children?: ReactNode
} & BoxProps

function FoodInfo({
  food,

  fontSize,
  nameNoOfLines,
  energy,
  notes,
  children,
  canBeLink = false,
  ...rest
}: Props) {
  return (
    <Flex height="100%" align="center" {...rest}>
      <Box>
        {food.url && canBeLink ? (
          <Link target="_blank" href={food.url} color="teal.500">
            {food.name}
          </Link>
        ) : (
          <Text noOfLines={nameNoOfLines} color="gray.800">
            {food.name}
          </Text>
        )}

        {energy !== undefined && (
          <Text fontSize="sm" textColor="gray.500">
            <Text as="span" fontWeight="medium">
              {`${Math.round(energy as number)}kcal`}
            </Text>{' '}
            / {food.servingSizeInGrams || DEFAULT_SERVING_SIZE_IN_GRAMS}g
          </Text>
        )}

        {children}
      </Box>
    </Flex>
  )
}

export default FoodInfo


================================================
FILE: src/foods/FoodModal/Content/DeleteConfirmationModal.tsx
================================================
import {
  Modal,
  ModalOverlay,
  ModalContent,
  ModalHeader,
  ModalFooter,
  ModalBody,
  ModalCloseButton,
  Button,
  Text,
} from '@chakra-ui/react'

type Props = {
  isOpen: boolean
  onCancel: () => void
  onConfirm: () => void
  text: string
  confirmButtonLabel: String
}

function DeleteConfirmationModal({
  isOpen,
  onCancel,
  onConfirm,
  text,
  confirmButtonLabel,
}: Props) {
  return (
    <Modal isOpen={isOpen} onClose={onCancel} size="xs" isCentered>
      <ModalOverlay />
      <ModalContent>
        <ModalHeader>Delete food</ModalHeader>
        <ModalCloseButton />
        <ModalBody>
          <Text>{text}</Text>
          <br />
          <Text fontWeight="medium">This action cannot be undone.</Text>
        </ModalBody>

        <ModalFooter>
          <Button variant="outline" onClick={onCancel}>
            Cancel
          </Button>
          <Button colorScheme="red" ml={3} onClick={onConfirm}>
            {confirmButtonLabel}
          </Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  )
}

export default DeleteConfirmationModal


================================================
FILE: src/foods/FoodModal/Content/FoodFormProvider.tsx
================================================
import { useForm } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'
import { ReactNode } from 'react'
import { FormProvider } from 'react-hook-form'
import {
  Food,
  FoodForm,
  foodFormSchema,
  FoodFormSchemaContext,
  getFoodForm,
  useFoods,
} from 'foods'

type Props = {
  food?: Food
  children: ReactNode
}

function FoodFormProvider({ food, children }: Props) {
  const defaultValues = getFoodForm(food)
  const { allFoods } = useFoods()

  const formMethods = useForm<FoodForm, FoodFormSchemaContext>({
    defaultValues,
    resolver: yupResolver(foodFormSchema),
    context: {
      allFoods,
      food,
    },
    mode: 'onChange',
  })

  return <FormProvider {...formMethods}>{children}</FormProvider>
}

export default FoodFormProvider


================================================
FILE: src/foods/FoodModal/Content/Form/Footer.tsx
================================================
import { ModalFooter, Button, HStack } from '@chakra-ui/react'

type Props = {
  onClose: () => void
  onSubmit: () => void
  isEditing: boolean
}

function Footer({ onClose, onSubmit, isEditing }: Props) {
  return (
    <ModalFooter>
      <HStack spacing={3}>
        <Button onClick={onClose}>Close</Button>
        {isEditing && (
          <Button
            colorScheme="teal"
            type="submit"
            variant="solid"
            onClick={onSubmit}
          >
            Save food
          </Button>
        )}
      </HStack>
    </ModalFooter>
  )
}

export default Footer


================================================
FILE: src/foods/FoodModal/Content/Form/Header.tsx
================================================
import { ModalHeader, Button } from '@chakra-ui/react'

type Props = {
  onClose: () => void
  title: string
  canEdit: boolean
  onToggleEdit: () => void
  isEditing: boolean
}

function Header({ title, canEdit, isEditing, onToggleEdit }: Props) {
  return (
    <ModalHeader>
      {title}
      {canEdit && (
        <Button
          ml={3}
          variant="link"
          size="md"
          colorScheme="teal"
          onClick={onToggleEdit}
        >
          {isEditing ? 'Back to preview' : 'Edit food'}
        </Button>
      )}
    </ModalHeader>
  )
}

export default Header


================================================
FILE: src/foods/FoodModal/Content/Form/Tabs/NutritionFactsFormFields.tsx
================================================
import { Box, FlexProps, VStack } from '@chakra-ui/react'
import { RefObject } from 'react'
import { StatsFormFields, StatFormField } from 'stats'

type Props = {
  nameInputRef: RefObject<HTMLInputElement>
  canEdit: boolean
} & FlexProps

function NutritionFactsFormFields({ nameInputRef, canEdit, ...rest }: Props) {
  return (
    <Box {...rest}>
      <VStack spacing={2} alignItems="stretch">
        <VStack spacing={2}>
          <StatFormField
            hasDivider={false}
            isEmphasized={true}
            name="servingSizeInGrams"
            label="Serving size"
            isRequired={true}
            inputType="nutritionValue"
            isReadOnly={!canEdit}
          />

          <StatFormField
            name="energy"
            isCaption={true}
            isValueBold={true}
            isEmphasized={true}
            label="Calories"
            inputType="nutritionValue"
            nutritionValueUnit="kcal"
            isRequired={true}
            isReadOnly={!canEdit}
          />
        </VStack>

        <StatsFormFields canEdit={canEdit} />
      </VStack>
    </Box>
  )
}

export default NutritionFactsFormFields


================================================
FILE: src/foods/FoodModal/Content/Form/Tabs/UrlField.tsx
================================================
import {
  Flex,
  FormControl,
  FormLabel,
  Link,
  Alert,
  AlertIcon,
} from '@chakra-ui/react'
import { Input } from '@chakra-ui/react'
import { Food, FoodForm } from 'foods'
import { useFormContext } from 'react-hook-form'

type Props = {
  canEdit: boolean
  food?: Food
}

function UrlField({ canEdit, food }: Props) {
  const { register } = useFormContext<FoodForm>()

  return (
    <Flex minHeight={canEdit ? '200px' : undefined} flexDirection="column">
      {canEdit && (
        <Alert status="info" mb={3}>
          <AlertIcon color="teal.400" />
          Add a link will open a web page when the food is clicked. This is
          useful if you want to show a specific product.
        </Alert>
      )}

      <FormControl id="email">
        <Flex alignItems="center">
          <FormLabel mb={0} flexShrink={0}>
            Link:
          </FormLabel>
          {canEdit ? (
            <Input
              {...register('url')}
              placeholder="http://example.com"
              type="email"
            />
          ) : (
            <Link
              href={food?.url}
              target="_blank"
              noOfLines={1}
              color="teal.500"
            >
              {food?.url}
            </Link>
          )}
        </Flex>
      </FormControl>
    </Flex>
  )
}

export default UrlField


================================================
FILE: src/foods/FoodModal/Content/Form/Tabs/VolumeFormFields.tsx
================================================
import { Flex, Text, HStack, Alert, AlertIcon } from '@chakra-ui/react'
import { Food, FoodForm } from 'foods'
import { PortionsSelect, usePortions } from 'portions'
import { Controller, useFormContext } from 'react-hook-form'
import { AmountInput } from 'stats'

type Props = {
  canEdit: boolean
  food?: Food
}

function VolumeFields({ canEdit, food }: Props) {
  const { register } = useFormContext<FoodForm>()
  const { portionsById, volumeBasedPortions } = usePortions()
  const portion = food?.volume ? portionsById[food.volume.portionId] : undefined

  return (
    <Flex minHeight={canEdit ? '200px' : undefined} flexDirection="column">
      {canEdit && (
        <Alert status="info" mb={3}>
          <AlertIcon color="teal.400" />
          Enter the food weight in grams per some volume measurement if you want
          to convert between weight and volume (for example: between grams and
          cups).
        </Alert>
      )}

      <HStack spacing={2}>
        {canEdit && <Text fontWeight="medium">1 x</Text>}
        {canEdit ? (
          <PortionsSelect
            width="200px"
            portions={volumeBasedPortions}
            {...register('volumeForm.portionId')}
          />
        ) : (
          <Text fontWeight="medium">
            1 x {`${portion?.singular} (${portion?.millilitersPerAmount} ml)`}
          </Text>
        )}

        <Text fontWeight="medium">=</Text>
        <HStack spacing={1} alignItems="center">
          {canEdit ? (
            <Controller
              name="volumeForm.weightInGrams"
              render={({ field }) => (
                <AmountInput value={field.value} onChange={field.onChange} />
              )}
            />
          ) : (
            <Text>{food?.volume?.weightInGrams}g</Text>
          )}
          {canEdit && <Text textColor="gray.500">g</Text>}
        </HStack>
      </HStack>
    </Flex>
  )
}

export default VolumeFields


================================================
FILE: src/foods/FoodModal/Content/Form/Tabs/index.tsx
================================================
import { Food } from 'foods'
import NutritionFactsFormFields from './NutritionFactsFormFields'
import { RefObject } from 'react'
import {
  Tabs as TabsBase,
  TabList,
  TabPanels,
  Tab,
  TabPanel,
} from '@chakra-ui/react'
import VolumeFormFields from './VolumeFormFields'
import UrlField from './UrlField'
import { useFormContext } from 'react-hook-form'

type TabName = 'nutrition' | 'volume' | 'link'

type Props = {
  nameInputRef: RefObject<HTMLInputElement>
  food?: Food
  isEditing: boolean
  selectedTabName: TabName
  tabNames: TabName[]
  onTabNameChange: (name: TabName) => void
}

function Tabs({
  nameInputRef,
  food,
  isEditing,
  selectedTabName,
  tabNames,
  onTabNameChange,
}: Props) {
  const { formState } = useFormContext()
  const tabIndex = tabNames.indexOf(selectedTabName)

  function onTabIndexChange(index: number) {
    onTabNameChange(tabNames[index])
  }

  return (
    <TabsBase
      variant="enclosed"
      colorScheme="teal"
      index={tabIndex}
      onChange={onTabIndexChange}
    >
      <TabList>
        <Tab color={formState.errors?.energy ? 'red.500' : undefined}>
          Nutrition Facts
        </Tab>

        {tabNames.includes('volume') && <Tab>Volume</Tab>}
        {tabNames.includes('link') && <Tab>Link</Tab>}
      </TabList>

      <TabPanels>
        <TabPanel px={0}>
          <NutritionFactsFormFields
            nameInputRef={nameInputRef}
            canEdit={isEditing}
          />
        </TabPanel>
        {tabNames.includes('volume') && (
          <TabPanel px={0}>
            <VolumeFormFields food={food} canEdit={isEditing} />
          </TabPanel>
        )}

        {tabNames.includes('link') && (
          <TabPanel px={0}>
            <UrlField canEdit={isEditing} food={food} />
          </TabPanel>
        )}
      </TabPanels>
    </TabsBase>
  )
}

export type { TabName }

export default Tabs


================================================
FILE: src/foods/FoodModal/Content/Form/index.tsx
================================================
import {
  ModalContent,
  ModalCloseButton,
  ModalBody,
  Button,
  Divider,
  Box,
  VStack,
  Text,
} from '@chakra-ui/react'
import { Food } from 'foods'
import { RefObject } from 'react'
import useSubmitFoodForm from './useSubmitFoodForm'
import { StatFormField } from 'stats'
import Footer from './Footer'
import Header from './Header'
import Tabs from './Tabs'
import useTabs from './useTabs'

type Props = {
  onClose: () => void
  title: string
  nameInputRef: RefObject<HTMLInputElement>
  food?: Food
  canEdit: boolean
  isEditing: boolean
  onToggleEdit: () => void
  onDelete: () => void
  onFoodCreatedOrUpdated?: (newFood: Food, oldFood?: Food) => void
}

function Form({
  onClose,
  nameInputRef,
  title,
  food,
  canEdit,
  onFoodCreatedOrUpdated,
  isEditing,
  onToggleEdit,
  onDelete,
}: Props) {
  const { onSubmit } = useSubmitFoodForm({
    onComplete: (newOrUpdatedFood: Food) => {
      onFoodCreatedOrUpdated && onFoodCreatedOrUpdated(newOrUpdatedFood, food)
      onClose()
    },
  })

  const { tabNames, onTabNameChange, selectedTabName } = useTabs({
    isEditing,
    food,
  })

  return (
    <form onSubmit={onSubmit}>
      <ModalContent>
        <Header
          title={title}
          canEdit={canEdit}
          isEditing={isEditing}
          onClose={onClose}
          onToggleEdit={onToggleEdit}
        />
        <ModalCloseButton />

        <ModalBody>
          <VStack spacing={6} align="stretch\">
            <VStack spacing={2} align="stretch">
              {isEditing ? (
                <StatFormField
                  textInputRef={nameInputRef}
                  name="name"
                  label="Name"
                  inputType="text"
                  isRequired={true}
                  isReadOnly={!isEditing}
                  hasDivider={false}
                />
              ) : (
                <Text fontSize="xl" fontWeight="bold">
                  {food?.name}
                </Text>
              )}
              <StatFormField
                name="categoryId"
                label="Category"
                inputType="foodCategory"
                isRequired={true}
                isReadOnly={!isEditing}
              />
            </VStack>

            <Tabs
              nameInputRef={nameInputRef}
              isEditing={isEditing}
              food={food}
              tabNames={tabNames}
              onTabNameChange={onTabNameChange}
              selectedTabName={selectedTabName}
            />
          </VStack>

          {isEditing && food && (
            <Box>
              <Divider />
              <Button width="100%" my={6} colorScheme="red" onClick={onDelete}>
                Delete food
              </Button>
            </Box>
          )}
        </ModalBody>

        <Footer onClose={onClose} onSubmit={onSubmit} isEditing={isEditing} />
      </ModalContent>
    </form>
  )
}

export type { Props }

export default Form


================================================
FILE: src/foods/FoodModal/Content/Form/useSubmitFoodForm.ts
================================================
import { objectFromNutritionDataKeys } from 'stats'
import { Food, FoodForm } from 'foods'
import { useOneTimeCheckActions } from 'general'
import { useFormContext } from 'react-hook-form'
import { useFoodsActions } from 'foods'
import { v4 as uuidv4 } from 'uuid'

type Params = {
  onComplete: (food: Food) => void
}

function withProtocol(url: string) {
  return !/^https?:\/\//i.test(url) ? `http://${url}` : url
}

function useSubmitFoodForm({ onComplete }: Params) {
  const { handleSubmit } = useFormContext()
  const foodsActions = useFoodsActions()
  const oneTimeCheckActions = useOneTimeCheckActions()

  const onSubmit = handleSubmit((foodForm: FoodForm) => {
    const food: Food = {
      id: foodForm.id !== undefined ? foodForm.id : uuidv4(),
      name: foodForm.name,
      categoryId: foodForm.categoryId,
      addedByUser: true,
      servingSizeInGrams: Number(foodForm.servingSizeInGrams),
      url: foodForm.url ? withProtocol(foodForm.url) : undefined,
      ...objectFromNutritionDataKeys(key => Number(foodForm[key])),
    }

    const { volumeForm } = foodForm
    const volumeWeightInGrams = Number(volumeForm.weightInGrams)

    if (volumeWeightInGrams > 0) {
      food.volume = {
        portionId: volumeForm.portionId,
        weightInGrams: volumeWeightInGrams,
      }
    }

    if (foodForm.id === undefined) {
      oneTimeCheckActions.set(`food-appear-${food.id}`)
    }
    oneTimeCheckActions.set(`food-flash-${food.id}`)

    foodsActions.setFoods([food])
    onComplete(food)
  })

  return {
    onSubmit,
  }
}

export default useSubmitFoodForm


================================================
FILE: src/foods/FoodModal/Content/Form/useTabs.tsx
================================================
import { Food } from 'foods'
import { useEffect, useState } from 'react'
import { TabName } from './Tabs'

type Params = {
  food?: Food
  isEditing: boolean
}

function getTabNames(isEditing: boolean, food?: Food): TabName[] {
  if (isEditing) {
    return ['nutrition', 'volume', 'link']
  }

  const result: TabName[] = ['nutrition']

  if (food?.volume) {
    result.push('volume')
  }

  if (food?.url) {
    result.push('link')
  }

  return result
}

function useTabs({ food, isEditing }: Params) {
  const [selectedTabName, setSelectedTabName] = useState<TabName>('nutrition')

  function onTabNameChange(newTabName: TabName) {
    setSelectedTabName(newTabName)
  }

  const tabNames = getTabNames(isEditing, food)

  useEffect(() => {
    if (!tabNames.includes(selectedTabName)) {
      setSelectedTabName('nutrition')
    }
  }, [food, isEditing, selectedTabName, tabNames])

  return {
    onTabNameChange,
    selectedTabName,
    tabNames,
  }
}

export default useTabs


================================================
FILE: src/foods/FoodModal/Content/index.tsx
================================================
import { Food } from 'foods'
import { RefObject, useState } from 'react'
import DeleteConfirmationModal from './DeleteConfirmationModal'
import useDeleteFood from './useDeleteFood'
import Form from './Form'
import FoodFormProvider from './FoodFormProvider'

type Props = {
  onClose: () => void
  title: string
  nameInputRef: RefObject<HTMLInputElement>
  food?: Food
  onFoodCreatedOrUpdated?: (newFood: Food, oldFood?: Food) => void
  onFoodDeleted?: (food: Food) => void
}

function Content({
  onClose,
  nameInputRef,
  title,
  food,
  onFoodCreatedOrUpdated,
  onFoodDeleted,
}: Props) {
  const canEdit = Boolean(food && food.addedByUser)
  const deleteFood = useDeleteFood({ food, onClose, onFoodDeleted })
  const [isEditing, setIsEditing] = useState(!food)

  function onToggleEdit() {
    setIsEditing(!isEditing)
  }

  return (
    <FoodFormProvider food={food}>
      <Form
        nameInputRef={nameInputRef}
        title={title}
        canEdit={canEdit}
        onToggleEdit={onToggleEdit}
        food={food}
        onDelete={deleteFood.onDelete}
        onFoodCreatedOrUpdated={onFoodCreatedOrUpdated}
        onClose={onClose}
        isEditing={isEditing}
      />

      <DeleteConfirmationModal
        text="Deleting this food will remove it from all meal plans where it's being used."
        confirmButtonLabel="Delete food"
        isOpen={deleteFood.deleteConfirmationDisclosure.isOpen}
        onCancel={deleteFood.deleteConfirmationDisclosure.onClose}
        onConfirm={deleteFood.onConfirmDelete}
      />
    </FoodFormProvider>
  )
}

export type { Props }

export default Content


================================================
FILE: src/foods/FoodModal/Content/useDeleteFood.ts
================================================
import { useDisclosure } from '@chakra-ui/hooks'
import { useFoodsActions } from 'foods'
import { Food } from 'foods'
import { useToast } from '@chakra-ui/react'

type Params = {
  food?: Food
  onClose: () => void
  onFoodDeleted?: (food: Food) => void
}

function useDeleteFood({ food, onClose, onFoodDeleted }: Params) {
  const deleteConfirmationDisclosure = useDisclosure()
  const foodsActions = useFoodsActions()
  const toast = useToast()

  function onDelete() {
    deleteConfirmationDisclosure.onOpen()
  }

  function onConfirmDelete() {
    if (food) {
      foodsActions.removeFood(food.id)
      toast({
        position: 'top',
        title: 'Food deleted',
        status: 'success',
        duration: 2000,
        isClosable: true,
      })
      deleteConfirmationDisclosure.onClose()
      onFoodDeleted && onFoodDeleted(food)
      onClose()
    }
  }

  return {
    deleteConfirmationDisclosure,
    onDelete,
    onConfirmDelete,
  }
}

export default useDeleteFood


================================================
FILE: src/foods/FoodModal/index.tsx
================================================
import { Modal, ModalOverlay } from '@chakra-ui/react'
import { Food } from 'foods'
import { useRef } from 'react'
import Content from './Content'

type Props = {
  onClose: () => void
  isOpen: boolean
  food?: Food
  onFoodCreatedOrUpdated?: (newFood: Food, oldFood?: Food) => void
  onFoodDeleted?: (food: Food) => void
}

function FoodModal({
  onClose,
  isOpen,
  food,
  onFoodCreatedOrUpdated,
  onFoodDeleted,
}: Props) {
  const nameInputRef = useRef<HTMLInputElement>(null)
  const title = food ? 'Food Details' : 'Create Food'

  return (
    <Modal
      isOpen={isOpen}
      preserveScrollBarGap={true}
      initialFocusRef={!food ? nameInputRef : undefined}
      onClose={onClose}
      scrollBehavior="inside"
      size={food ? 'md' : 'lg'}
    >
      <ModalOverlay />

      <Content
        nameInputRef={nameInputRef}
        onClose={onClose}
        title={title}
        food={food}
        onFoodCreatedOrUpdated={onFoodCreatedOrUpdated}
        onFoodDeleted={onFoodDeleted}
      />
    </Modal>
  )
}

export type { Props }

export default FoodModal


================================================
FILE: src/foods/FoodsDrawer/Content/Header.tsx
================================================
import { DrawerHeader, Text } from '@chakra-ui/react'
import { MealForm } from 'meals'

type Props = {
  mealName?: string
  canSelect: boolean
  mealForm?: MealForm
}

function getTitlePrefix(props: Props) {
  const { mealName, canSelect, mealForm } = props

  if (!mealForm && mealName) {
    return 'Select Foods for '
  }

  if (canSelect) {
    return mealName ? 'Add Foods to ' : 'Add Foods'
  }

  return 'Foods'
}

function Header(props: Props) {
  const { mealName } = props
  const fontWeight = mealName ? 'normal' : 'bold'
  let titlePrefix = getTitlePrefix(props)

  return (
    <DrawerHeader fontWeight={fontWeight} mr={3}>
      {titlePrefix}

      {mealName && (
        <Text as="span" fontSize="xl" fontWeight="bold">
          {mealName}
        </Text>
      )}
    </DrawerHeader>
  )
}

export default Header


================================================
FILE: src/foods/FoodsDrawer/Content/MenuButtons.tsx
================================================
import { chakra, IconButton } from '@chakra-ui/react'
import { MoreHorizontal, Download, Share } from 'react-feather'
import { Menu, MenuItem } from 'general'

const DownloadStyled = chakra(Download)
const ShareStyled = chakra(Share)
const MoreHorizontalStyled = chakra(MoreHorizontal)

type Props = {
  onImport: () => void
  onExport: () => void
}

function MenuButtons({ onImport, onExport }: Props) {
  return (
    <Menu
      arrow
      align="end"
      viewScroll="close"
      menuButton={
        <IconButton
          aria-label="Foods actions"
          icon={<MoreHorizontalStyled size={20} pointerEvents="none" />}
          variant="outline"
        />
      }
    >
      <MenuItem onClick={onImport}>
        <DownloadStyled pointerEvents="none" mr={3} />
        Import custom foods
      </MenuItem>
      <MenuItem onClick={onExport}>
        <ShareStyled pointerEvents="none" mr={3} />
        Export custom foods
      </MenuItem>
    </Menu>
  )
}

export default MenuButtons


================================================
FILE: src/foods/FoodsDrawer/Content/SelectedFoodsList/SelectedFoodItem.tsx
================================================
import { Tag, TagLabel, TagCloseButton, Fade } from '@chakra-ui/react'
import { Food } from 'foods'

type Props = {
  food: Food
  onUnselect: (food: Food) => void
}

function SelectedFoodItem({ food, onUnselect }: Props) {
  return (
    <Fade in={true}>
      <Tag
        size="md"
        borderRadius="full"
        variant="outline"
        colorScheme="teal"
        maxWidth="250px"
      >
        <TagLabel>{food.name}</TagLabel>
        <TagCloseButton onClick={() => onUnselect(food)} />
      </Tag>
    </Fade>
  )
}

export default SelectedFoodItem


================================================
FILE: src/foods/FoodsDrawer/Content/SelectedFoodsList/index.tsx
================================================
import { Flex, Text, Wrap } from '@chakra-ui/react'
import { Selection } from 'general'
import SelectedFoodItem from './SelectedFoodItem'
import { Food, useFoods } from 'foods'

type Props = {
  selection: Selection<Food>
}

function SelectedFoods({ selection }: Props) {
  const { selectedItems: selectedFoods } = selection
  const { foodsById } = useFoods()

  return (
    <Flex alignItems="center" minHeight="56px">
      {selectedFoods.length > 0 ? (
        <Wrap spacing={2}>
          {selectedFoods.map(({ id }) => (
            <SelectedFoodItem
              key={id}
              food={foodsById[id]}
              onUnselect={selection.toggleItem}
            />
          ))}
        </Wrap>
      ) : (
        <Text textColor="gray.500">Select one or more foods</Text>
      )}
    </Flex>
  )
}

export default SelectedFoods


================================================
FILE: src/foods/FoodsDrawer/Content/index.tsx
================================================
import {
  DrawerContent,
  DrawerCloseButton,
  DrawerBody,
  DrawerFooter,
  Flex,
  Button,
  VStack,
  Text,
  HStack,
  useDisclosure,
} from '@chakra-ui/react'
import { RefObject, useRef, useState } from 'react'
import { FoodsList, FoodsListMethods, FoodModal, Food } from 'foods'
import { useSelection, Tooltip } from 'general'
import SelectedFoodsList from './SelectedFoodsList'
import Header from './Header'
import MenuButtons from './MenuButtons'
import { useImportFoods, FoodsListModal } from 'foods/persistence'
import { FoodsFilterStoreProvider } from 'foods-filters'
import { loadFoodsFilter } from 'foods-filters/persistence'
import useFoodEvents from './useFoodEvents'
import { MealForm } from 'meals'

type Props = {
  onClose: () => void
  mealName?: string
  mealForm?: MealForm
  searchInputRef: RefObject<HTMLInputElement>
  onSelectedFoods?: (foods: Food[], mealName?: string) => void

  canSelect: boolean
}

function Content({
  onClose,
  mealName,
  mealForm,
  searchInputRef,
  onSelectedFoods,
  canSelect,
}: Props) {
  const selection = useSelection<Food>()
  const listRef = useRef<FoodsListMethods>(null)
  const foodEvents = useFoodEvents({ listRef, selection })

  const foodsListModalDisclosure = useDisclosure()
  const importFoods = useImportFoods({ foodsListModalDisclosure })
  const [foodsFilter] = useState(loadFoodsFilter)

  function onAdd() {
    onSelectedFoods && onSelectedFoods(selection.selectedItems, mealName)
  }

  return (
    <DrawerContent>
      <DrawerCloseButton />
      <Header mealForm={mealForm} mealName={mealName} canSelect={canSelect} />

      <DrawerBody overflow="hidden">
        <VStack
          width="100%"
          height="100%"
          spacing={canSelect ? 3 : 6}
          alignItems="stretch"
        >
          <Flex>
            <Text textColor="gray.500" size="lg" mr={1}>
              Need more foods?
            </Text>
            <Button
              variant="link"
              colorScheme="teal"
              onClick={foodEvents.onCreateFood}
            >
              Create a new food
            </Button>
          </Flex>

          {canSelect && <SelectedFoodsList selection={selection} />}

          <FoodsFilterStoreProvider initialFilter={foodsFilter}>
            <FoodsList
              ref={listRef}
              searchInputRef={searchInputRef}
              selection={selection}
              flex={1}
              onFoodPreview={foodEvents.onPreviewFood}
              itemUsageType={canSelect ? 'selectOrPreview' : 'previewOnly'}
            />
          </FoodsFilterStoreProvider>
        </VStack>
      </DrawerBody>

      <DrawerFooter justifyContent={canSelect ? 'flex-end' : 'space-between'}>
        {!canSelect && (
          <MenuButtons
            onImport={importFoods.onImport}
            onExport={foodsListModalDisclosure.onOpen}
          />
        )}

        <HStack spacing={3}>
          <Button variant="solid" size="md" onClick={onClose}>
            Close
          </Button>
          {canSelect && (
            <Tooltip
              isActive={!mealForm}
              delay={300}
              label="You can add more later"
            >
              <Button
                isDisabled={selection.selectedItems.length === 0}
                colorScheme="teal"
                onClick={onAdd}
              >
                {mealForm ? 'Add selected foods' : 'Select foods'}
              </Button>
            </Tooltip>
          )}
        </HStack>
      </DrawerFooter>

      <FoodModal
        isOpen={foodEvents.foodModalDisclosure.isOpen}
        onClose={foodEvents.foodModalDisclosure.onClose}
        onFoodCreatedOrUpdated={foodEvents.onFoodCreatedOrUpdated}
        onFoodDeleted={foodEvents.onFoodDeleted}
        food={foodEvents.food}
      />

      <FoodsListModal
        isOpen={foodsListModalDisclosure.isOpen}
        onClose={foodsListModalDisclosure.onClose}
        foodsToImport={importFoods.foodsToImport}
      />
    </DrawerContent>
  )
}

export default Content


================================================
FILE: src/foods/FoodsDrawer/Content/useFoodEvents.ts
================================================
import { useDisclosure } from '@chakra-ui/react'
import { Food } from 'foods'
import { useState, RefObject } from 'react'
import { FoodsListMethods } from 'foods'
import { Selection } from 'general'

type Params = {
  listRef: RefObject<FoodsListMethods>
  selection: Selection<Food>
}

function useFoodEvents({ listRef, selection }: Params) {
  const foodModalDisclosure = useDisclosure()
  const [food, setFood] = useState<Food>()

  function onCreateFood() {
    setFood(undefined)
    foodModalDisclosure.onOpen()
  }

  function onPreviewFood(food: Food) {
    setFood(food)
    foodModalDisclosure.onOpen()
  }

  function onFoodDeleted(food: Food) {
    selection.removeItem(food)
  }

  function onFoodCreatedOrUpdated(newFood: Food, oldFood?: Food) {
    if (!listRef.current) {
      return
    }

    if (!oldFood || (oldFood && newFood.categoryId !== oldFood.categoryId)) {
      listRef.current.scrollToFood(newFood)
    }
  }

  return {
    onCreateFood,
    onPreviewFood,
    onFoodCreatedOrUpdated,
    food,
    foodModalDisclosure,
    onFoodDeleted,
  }
}

export default useFoodEvents


================================================
FILE: src/foods/FoodsDrawer/index.tsx
================================================
import { Drawer, DrawerOverlay } from '@chakra-ui/react'
import { Food } from 'foods'
import { MealForm } from 'meals'
import { useRef } from 'react'
import { isMobile } from 'react-device-detect'
import Content from './Content'

type Props = {
  onClose: () => void
  isOpen: boolean
  mealName?: string
  mealForm?: MealForm
  canSelect?: boolean
  onSelectedFoods?: (foods: Food[], mealName?: string) => void
}

function FoodsDrawer({
  onClose,
  isOpen,
  mealName,
  mealForm,
  canSelect = true,
  onSelectedFoods,
}: Props) {
  const searchInputRef = useRef<HTMLInputElement>(null)

  return (
    <Drawer
      initialFocusRef={isMobile ? undefined : searchInputRef}
      isOpen={isOpen}
      size="md"
      placement="right"
      onClose={onClose}
    >
      <DrawerOverlay />
      <Content
        onClose={onClose}
        mealName={mealName}
        mealForm={mealForm}
        onSelectedFoods={onSelectedFoods}
        searchInputRef={searchInputRef}
        canSelect={canSelect}
      />
    </Drawer>
  )
}

export default FoodsDrawer


================================================
FILE: src/foods/FoodsList/VirtualizedList/FoodItem/AnimateAppear.tsx
================================================
import { motion } from 'framer-motion'
import { ReactNode } from 'react'

type Props = {
  shouldAnimate: boolean
  children: ReactNode
}

const variants = {
  open: {
    opacity: 1,
    scale: 1,
  },
  hidden: { opacity: 0, scale: 0.9 },
}

function AnimateAppear({ shouldAnimate, children }: Props) {
  return (
    <motion.div
      transition={{
        ease: 'easeInOut',
        duration: shouldAnimate ? 0.35 : undefined,
        delay: 0.5,
      }}
      initial={shouldAnimate ? 'hidden' : false}
      animate="open"
      variants={variants}
    >
      {children}
    </motion.div>
  )
}

export default AnimateAppear


================================================
FILE: src/foods/FoodsList/VirtualizedList/FoodItem/DisappearingBox.tsx
================================================
import { Box } from '@chakra-ui/react'
import { useEffect, useState } from 'react'

type Props = {
  shouldAnimate: boolean
}

function DisappearingBox({ shouldAnimate }: Props) {
  const [opacity, setOpacity] = useState(shouldAnimate ? 1 : 0)

  useEffect(() => {
    if (shouldAnimate) {
      setOpacity(0)
    }
  }, [shouldAnimate])

  return (
    <Box
      position="absolute"
      left="0"
      bg="gray.100"
      right="0"
      top="0"
      bottom="0"
      opacity={opacity}
      transition="opacity 2s ease-in-out"
    />
  )
}

export default DisappearingBox


================================================
FILE: src/foods/FoodsList/VirtualizedList/FoodItem/index.tsx
================================================
import { FoodInfo, Food } from 'foods'
import { Flex, FlexProps, Box, chakra, IconButton } from '@chakra-ui/react'
import { Info } from 'react-feather'
import { MouseEvent } from 'react'
import { useOneTimeCheckActions, Tooltip } from 'general'
import DisappearingBox from './DisappearingBox'
import AnimateAppear from './AnimateAppear'

const InfoStyled = chakra(Info)

type UsageType = 'selectOrPreview' | 'previewOnly' | 'nonInteractive'

type Props = {
  food: Food
  isSelected?: boolean
  onPreview: (food: Food) => void
  onChoose: (food: Food) => void
  usageType?: UsageType
} & FlexProps

function FoodItem({
  food,
  isSelected = false,
  onPreview,
  onChoose,
  usageType = 'selectOrPreview',
  ...rest
}: Props) {
  function onInfoButtonClick(event: MouseEvent<HTMLButtonElement>) {
    event.stopPropagation()
    onPreview(food)
  }

  const oneTimeCheckActions = useOneTimeCheckActions()
  const shouldAnimateAppear = oneTimeCheckActions.checkAndReset(
    `food-appear-${food.id}`
  )
  const shouldAnimateFlash = oneTimeCheckActions.checkAndReset(
    `food-flash-${food.id}`
  )

  return (
    <Box
      pb={2}
      onClick={() => {
        if (usageType === 'previewOnly') {
          onPreview(food)
        } else if (usageType === 'selectOrPreview') {
          onChoose(food)
        }
      }}
      {...rest}
    >
      <AnimateAppear shouldAnimate={shouldAnimateAppear}>
        <Flex
          cursor={usageType !== 'nonInteractive' ? 'pointer' : undefined}
          _hover={
            usageType !== 'nonInteractive'
              ? {
                  backgroundColor: !isSelected ? 'gray.50' : undefined,
                }
              : undefined
          }
          position="relative"
          transition="border 150ms ease-out"
          borderColor={isSelected ? 'teal.500' : 'gray.200'}
          backgroundColor={isSelected ? 'gray.50' : 'white'}
          borderWidth="1px"
          borderRadius={6}
          overflow="hidden"
          justifyContent="space-between"
          alignItems="center"
          p={3}
          height="64px"
        >
          {shouldAnimateFlash && (
            <DisappearingBox shouldAnimate={shouldAnimateFlash} />
          )}

          <FoodInfo
            nameNoOfLines={1}
            food={food}
            energy={food.energy}
            position="relative"
            zIndex={1}
          />
          {usageType === 'selectOrPreview' && (
            <Tooltip label="Food details">
              <IconButton
                aria-label="Food details"
                icon={<InfoStyled size={20} pointerEvents="none" />}
                variant="ghost"
                onClick={onInfoButtonClick}
                position="relative"
                zIndex={1}
              />
            </Tooltip>
          )}
        </Flex>
      </AnimateAppear>
    </Box>
  )
}

export type { UsageType }

export default FoodItem


================================================
FILE: src/foods/FoodsList/VirtualizedList/FoodItemRenderer.tsx
================================================
import { Food } from 'foods'
import FoodItem, { UsageType } from './FoodItem'
import { TOP_PADDING } from './Inner'

type Data = {
  getFood: (index: number) => Food
  isFoodSelected: (food: Food) => boolean
  onFoodSelect: (food: Food) => void
  onFoodPreview: (food: Food) => void
  usageType: UsageType
}

type Props = {
  style: any
  index: number
  data: Data
}

function FoodItemRenderer({ style, index, data }: Props) {
  const {
    getFood,
    onFoodSelect,
    onFoodPreview,
    isFoodSelected,
    usageType,
  } = data
  const food = getFood(index)

  return (
    <FoodItem
      key={food.id}
      style={{
        ...style,
        top: `${parseFloat(style['top'] as string) + TOP_PADDING}px`,
      }}
      onChoose={onFoodSelect}
      isSelected={isFoodSelected(food)}
      onPreview={onFoodPreview}
      food={food}
      usageType={usageType}
    />
  )
}

export default FoodItemRenderer


================================================
FILE: src/foods/FoodsList/VirtualizedList/Inner.tsx
================================================
import { forwardRef } from 'react'

const TOP_PADDING = 12

const Inner = forwardRef<any, any>(({ style, ...rest }, ref) => (
  <div
    ref={ref}
    style={{
      ...style,
      height: `${parseFloat(style.height) + TOP_PADDING}px`,
    }}
    {...rest}
  />
))

export { TOP_PADDING }

export default Inner


================================================
FILE: src/foods/FoodsList/VirtualizedList/index.tsx
================================================
import { Box } from '@chakra-ui/react'
import { FixedSizeList } from 'react-window'
import { forwardRef, ForwardedRef } from 'react'
import { Food } from 'foods'
import Inner from './Inner'
import FoodItemRenderer from './FoodItemRenderer'
import { UsageType } from './FoodItem'
import { useElementHeight } from 'general'

type Props = {
  foodsCount: number
  getFood: (index: number) => Food
  isFoodSelected: (food: Food) => boolean
  onFoodSelect: (food: Food) => void
  onFoodPreview: (food: Food) => void
  forwardRef?: ForwardedRef<FixedSizeList>
  itemUsageType: UsageType
}

function VirtualizedList({
  getFood,
  isFoodSelected,
  onFoodSelect,
  onFoodPreview,
  foodsCount,
  forwardRef,
  itemUsageType,
}: Props) {
  const { elementHeight, elementRef } = useElementHeight()

  return (
    <Box position="relative" ref={elementRef} flex={1}>
      <FixedSizeList
        style={{ position: 'absolute', top: 0 }}
        innerElementType={Inner}
        height={elementHeight}
        itemCount={foodsCount}
        itemData={{
          getFood,
          onFoodSelect,
          onFoodPreview,
          isFoodSelected,
          usageType: itemUsageType,
        }}
        itemSize={72}
        width="100%"
        ref={forwardRef}
      >
        {FoodItemRenderer}
      </FixedSizeList>
    </Box>
  )
}

export default forwardRef<FixedSizeList, Props>((props, ref) => (
  <VirtualizedList {...props} forwardRef={ref} />
))


================================================
FILE: src/foods/FoodsList/index.tsx
================================================
import {
  Input,
  InputGroup,
  InputLeftElement,
  chakra,
  Flex,
  Text,
  FlexProps,
  HStack,
  Box,
} from '@chakra-ui/react'
import { Divider } from '@chakra-ui/react'
import { Search } from 'react-feather'
import VirtualizedList from './VirtualizedList'
import { Selection } from 'general'
import {
  ForwardedRef,
  RefObject,
  useRef,
  useImperativeHandle,
  forwardRef,
  ChangeEvent,
  useEffect,
} from 'react'
import { useFoods } from 'foods'
import {
  useFilterFoods,
  useFoodsFilter,
  useFoodsFilterActions,
} from 'foods-filters'
import { Food } from 'foods'
import { FixedSizeList } from 'react-window'
import { FoodsFilterPopoverOrModal } from 'foods-filters'
import { UsageType } from './VirtualizedList/FoodItem'
import { isMobile } from 'react-device-detect'

const SearchStyled = chakra(Search)

type FoodsListMethods = {
  scrollToFood: (food: Food) => void
}

type Props = {
  searchInputRef?: RefObject<HTMLInputElement>
  selection?: Selection<Food>
  onFoodPreview?: (food: Food) => void
  forwardedRef?: ForwardedRef<FoodsListMethods>
  allowsFiltering?: boolean
  itemUsageType?: UsageType
} & FlexProps

function FoodsList({
  selection,
  searchInputRef,
  onFoodPreview,
  forwardedRef,
  allowsFiltering = true,
  itemUsageType = 'selectOrPreview',
  ...rest
}: Props) {
  const { allFoods, userFoods } = useFoods()
  const listRef = useRef<FixedSizeList>(null)

  const filter = useFoodsFilter()
  const foodsFilterActions = useFoodsFilterActions()
  const filteredFoods = useFilterFoods(allFoods, userFoods, filter)

  useEffect(() => {
    if (filter.categoryId) {
      listRef.current?.scrollToItem(0, 'start')
    }
  }, [filter.categoryId])

  useImperativeHandle(forwardedRef, () => ({
    scrollToFood: (food: Food) => {
      foodsFilterActions.resetCategoryIdAndQuery()

      if (listRef.current) {
        const foods = filter.onlyFoodsAddedByUser ? userFoods : allFoods
        const index = foods.map(({ id }) => id).indexOf(food.id)
        listRef.current.scrollToItem(index, 'center')
      }
    },
  }))

  function onFoodSelect(food: Food) {
    if (selection) {
      selection.toggleItem(food)
      const input = searchInputRef?.current

      if (input && !isMobile) {
        input.focus()
        input.setSelectionRange(0, input.value.length)
      }
    }
  }

  return (
    <Flex flexDirection="column" {...rest}>
      <HStack spacing={3}>
        {allowsFiltering && (
          <Box>
            <FoodsFilterPopoverOrModal />
          </Box>
        )}

        <InputGroup size="md" flex={4}>
          <InputLeftElement
            pointerEvents="none"
            children={
              <SearchStyled pointerEvents="none" size={20} color="gray.400" />
            }
          />
          <Input
            ref={searchInputRef}
            value={filter.query}
            onChange={(event: ChangeEvent<HTMLInputElement>) =>
              foodsFilterActions.updateFilter({ query: event.target.value })
            }
            placeholder="Search"
          />
        </InputGroup>
      </HStack>

      <Divider mt={3} width="100%" />

      {filteredFoods.length > 0 ? (
        <VirtualizedList
          ref={listRef}
          foodsCount={filteredFoods.length}
          isFoodSelected={food =>
            selection ? selection.isIdSelected(food.id) : false
          }
          getFood={index => filteredFoods[index]}
          onFoodSelect={onFoodSelect}
          onFoodPreview={onFoodPreview || (() => {})}
          itemUsageType={itemUsageType}
        />
      ) : (
        <Flex flex={1} alignItems="center" justifyContent="center">
          <Text textColor="gray.500">No foods found</Text>
        </Flex>
      )}
    </Flex>
  )
}

export type { FoodsListMethods }

export default forwardRef<any, Props>((props, ref) => (
  <FoodsList {...props} forwardedRef={ref} />
))


================================================
FILE: src/foods/builtIn/bakedProducts.json
================================================

  [
    {
      "id": 3001,
      "name": "Taco shells",
      "categoryId": 3000,
      "energy": 476,
      "fat": 21.79,
      "saturatedFat": 7.105,
      "monounsaturatedFat": 6.935,
      "polyunsaturatedFat": 5.495,
      "carbs": 63.49,
      "sugar": 1.5,
      "fiber": 6.7,
      "protein": 6.41,
      "sodium": 324,
      "cholesterol": 0,
      "vitaminA": 1,
      "vitaminB1": 0.216,
      "vitaminB2": 0.08,
      "vitaminB3": 1.867,
      "vitaminB5": 0,
      "vitaminB6": 0.203,
      "vitaminB9": 69,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0.69,
      "vitaminK": 8.6,
      "magnesium": 83,
      "calcium": 100,
      "phosphorus": 233,
      "potassium": 231,
      "iron": 1.64,
      "selenium": 4.8,
      "zinc": 1.61,
      "manganese": 0.56,
      "copper": 0.113,
      "choline": 29.9
    },
    {
      "id": 3002,
      "name": "Flour tortilla",
      "categoryId": 3000,
      "energy": 306,
      "fat": 7.99,
      "saturatedFat": 2.924,
      "monounsaturatedFat": 1.751,
      "polyunsaturatedFat": 2.29,
      "carbs": 49.38,
      "sugar": 3.71,
      "fiber": 3.5,
      "protein": 8.2,
      "sodium": 736,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.503,
      "vitaminB2": 0.282,
      "vitaminB3": 4.415,
      "vitaminB5": 0,
      "vitaminB6": 0.059,
      "vitaminB9": 94,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 7.2,
      "magnesium": 22,
      "calcium": 146,
      "phosphorus": 206,
      "potassium": 125,
      "iron": 3.63,
      "selenium": 22.3,
      "zinc": 0.53,
      "manganese": 0,
      "copper": 0.104,
      "choline": 7.9
    },
    {
      "id": 3003,
      "name": "Corn tortilla",
      "categoryId": 3000,
      "energy": 218,
      "fat": 2.85,
      "saturatedFat": 0.453,
      "monounsaturatedFat": 0.692,
      "polyunsaturatedFat": 1.419,
      "carbs": 44.64,
      "sugar": 0.88,
      "fiber": 6.3,
      "protein": 5.7,
      "sodium": 45,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.094,
      "vitaminB2": 0.065,
      "vitaminB3": 1.498,
      "vitaminB5": 0,
      "vitaminB6": 0.219,
      "vitaminB9": 5,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0.28,
      "vitaminK": 0,
      "magnesium": 72,
      "calcium": 81,
      "phosphorus": 314,
      "potassium": 186,
      "iron": 1.23,
      "selenium": 6.1,
      "zinc": 1.31,
      "manganese": 0,
      "copper": 0.154,
      "choline": 13.3
    },
    {
      "id": 3004,
      "name": "Bagel",
      "categoryId": 3000,
      "energy": 264,
      "fat": 1.32,
      "saturatedFat": 0.36,
      "monounsaturatedFat": 0.39,
      "polyunsaturatedFat": 0.526,
      "carbs": 52.38,
      "sugar": 8.43,
      "fiber": 1.6,
      "protein": 10.56,
      "sodium": 422,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.568,
      "vitaminB2": 0.344,
      "vitaminB3": 4.515,
      "vitaminB5": 0,
      "vitaminB6": 0.07,
      "vitaminB9": 106,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0.1,
      "vitaminK": 0.2,
      "magnesium": 29,
      "calcium": 105,
      "phosphorus": 99,
      "potassium": 107,
      "iron": 3.57,
      "selenium": 21.5,
      "zinc": 0.83,
      "manganese": 0,
      "copper": 0.128,
      "choline": 14.6
    },
    {
      "id": 3005,
      "name": "Whole-grain bread",
      "categoryId": 3000,
      "energy": 265,
      "fat": 4.23,
      "saturatedFat": 0.872,
      "monounsaturatedFat": 0.76,
      "polyunsaturatedFat": 1.872,
      "carbs": 43.34,
      "sugar": 6.39,
      "fiber": 7.4,
      "protein": 13.36,
      "sodium": 381,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.279,
      "vitaminB2": 0.131,
      "vitaminB3": 4.042,
      "vitaminB5": 0.336,
      "vitaminB6": 0.263,
      "vitaminB9": 75,
      "vitaminB12": 0,
      "vitaminC": 0.1,
      "vitaminD": 0,
      "vitaminE": 0.37,
      "vitaminK": 1.4,
      "magnesium": 78,
      "calcium": 103,
      "phosphorus": 228,
      "potassium": 230,
      "iron": 2.5,
      "selenium": 32.9,
      "zinc": 1.7,
      "manganese": 2.025,
      "copper": 0.282,
      "choline": 22
    },
    {
      "id": 3006,
      "name": "White bread",
      "categoryId": 3000,
      "energy": 270,
      "fat": 3.59,
      "saturatedFat": 0.821,
      "monounsaturatedFat": 0.717,
      "polyunsaturatedFat": 1.87,
      "carbs": 49.2,
      "sugar": 5.34,
      "fiber": 2.3,
      "protein": 9.43,
      "sodium": 477,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.507,
      "vitaminB2": 0.24,
      "vitaminB3": 4.76,
      "vitaminB5": 0,
      "vitaminB6": 0.092,
      "vitaminB9": 111,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0.22,
      "vitaminK": 0.2,
      "magnesium": 27,
      "calcium": 211,
      "phosphorus": 113,
      "potassium": 117,
      "iron": 3.36,
      "selenium": 23.2,
      "zinc": 0.88,
      "manganese": 0,
      "copper": 0.124,
      "choline": 14.6
    },
    {
      "id": 3007,
      "name": "Jumbo Seeded Hamburger Buns",
      "categoryId": 3000,
      "energy": 277,
      "fat": 4.62,
      "saturatedFat": 0.77,
      "monounsaturatedFat": 0.77,
      "polyunsaturatedFat": 1.54,
      "carbs": 50.77,
      "sugar": 4.62,
      "fiber": 1.5,
      "protein": 9.23,
      "sodium": 446,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0.308,
      "vitaminB3": 4.154,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 0,
      "calcium": 92,
      "phosphorus": 0,
      "potassium": 92,
      "iron": 3.08,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0,
      "url": "https://www.instacart.com/products/18368481-holsum-cotton-s-jumbo-seeded-hamburger-buns-18-2-oz"
    },
    {
      "id": 3008,
      "name": "While-wheat pita",
      "categoryId": 3000,
      "energy": 262,
      "fat": 1.71,
      "saturatedFat": 0.208,
      "monounsaturatedFat": 0.349,
      "polyunsaturatedFat": 1.055,
      "carbs": 55.89,
      "sugar": 2.87,
      "fiber": 6.1,
      "protein": 9.8,
      "sodium": 421,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.339,
      "vitaminB2": 0.08,
      "vitaminB3": 2.84,
      "vitaminB5": 0.831,
      "vitaminB6": 0.265,
      "vitaminB9": 35,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0.61,
      "vitaminK": 1.4,
      "magnesium": 69,
      "calcium": 15,
      "phosphorus": 180,
      "potassium": 170,
      "iron": 3.06,
      "selenium": 44,
      "zinc": 1.52,
      "manganese": 1.74,
      "copper": 0.29,
      "choline": 26.5
    },
    {
      "id": 3009,
      "name": "Saltine crakers",
      "categoryId": 3000,
      "energy": 418,
      "fat": 8.64,
      "saturatedFat": 1.653,
      "monounsaturatedFat": 1.986,
      "polyunsaturatedFat": 4.835,
      "carbs": 74.05,
      "sugar": 1.29,
      "fiber": 2.8,
      "protein": 9.46,
      "sodium": 941,
      "cholesterol": 0,
      "vitaminA": 1,
      "vitaminB1": 0.702,
      "vitaminB2": 0.487,
      "vitaminB3": 6.442,
      "vitaminB5": 0.536,
      "vitaminB6": 0.086,
      "vitaminB9": 134,
      "vitaminB12": 0.09,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 1.15,
      "vitaminK": 25.4,
      "magnesium": 23,
      "calcium": 19,
      "phosphorus": 102,
      "potassium": 152,
      "iron": 5.57,
      "selenium": 10.3,
      "zinc": 0.69,
      "manganese": 0.686,
      "copper": 0.139,
      "choline": 16.7,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 45
      }
    },
    {
      "id": 3010,
      "name": "Snyders' Olde Tyme Pretzels",
      "categoryId": 3000,
      "energy": 400,
      "fat": 3.33,
      "saturatedFat": 0,
      "monounsaturatedFat": 3.33,
      "polyunsaturatedFat": 0,
      "carbs": 80,
      "sugar": 3.33,
      "fiber": 3.3,
      "protein": 10,
      "sodium": 400,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0.453,
      "vitaminB3": 5.333,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 0,
      "calcium": 0,
      "phosphorus": 0,
      "potassium": 0,
      "iron": 3.6,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0,
      "url": "https://www.snydersofhanover.com/olde-tyme"

    },
    {
      "id": 3011,
      "name": "Seasoned breadcrumbs",
      "categoryId": 3000,
      "energy": 383,
      "fat": 5.48,
      "saturatedFat": 1.391,
      "monounsaturatedFat": 1.168,
      "polyunsaturatedFat": 2.3,
      "carbs": 68.49,
      "sugar": 5.74,
      "fiber": 4.9,
      "protein": 14.13,
      "sodium": 2100,
      "cholesterol": 1,
      "vitaminA": 10,
      "vitaminB1": 0.961,
      "vitaminB2": 0.415,
      "vitaminB3": 6.161,
      "vitaminB5": 0.623,
      "vitaminB6": 0.171,
      "vitaminB9": 119,
      "vitaminB12": 0.35,
      "vitaminC": 2.7,
      "vitaminD": 0,
      "vitaminE": 0.26,
      "vitaminK": 46,
      "magnesium": 46,
      "calcium": 182,
      "phosphorus": 177,
      "potassium": 231,
      "iron": 4.92,
      "selenium": 24.7,
      "zinc": 1.43,
      "manganese": 0.984,
      "copper": 0.244,
      "choline": 14.6,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 120
      }
    },
    {
      "id": 3012,
      "name": "English muffins",
      "categoryId": 3000,
      "energy": 245,
      "fat": 1.75,
      "saturatedFat": 0,
      "monounsaturatedFat": 0,
      "polyunsaturatedFat": 0,
      "carbs": 50.17,
      "sugar": 1.75,
      "fiber": 3.5,
      "protein": 7.02,
      "sodium": 386,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.263,
      "vitaminB2": 0.179,
      "vitaminB3": 2.105,
      "vitaminB5": 0,
      "vitaminB6": 0.056,
      "vitaminB9": 70,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0.25,
      "vitaminK": 2.3,
      "magnesium": 33,
      "calcium": 140,
      "phosphorus": 127,
      "potassium": 130,
      "iron": 2.53,
      "selenium": 17.3,
      "zinc": 0.97,
      "manganese": 0,
      "copper": 0.164,
      "choline": 6.5
    },
    {
      "id": 3013,
      "name": "High fiber tortilla",
      "categoryId": 3000,
      "energy": 111,
      "fat": 3.33,
      "saturatedFat": 0,
      "monounsaturatedFat": 0,
      "polyunsaturatedFat": 0,
      "carbs": 35.56,
      "sugar": 0,
      "fiber": 24.4,
      "protein": 8.89,
      "sodium": 689,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 0,
      "calcium": 222,
      "phosphorus": 0,
      "potassium": 0,
      "iron": 1.6,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0
    },
    {
      "id": 3014,
      "name": "La Tortilla Low carb tortillas",
      "categoryId": 3000,
      "energy": 167,
      "fat": 5.95,
      "saturatedFat": 2.38,
      "monounsaturatedFat": 0,
      "polyunsaturatedFat": 0,
      "carbs": 35.71,
      "sugar": 2.38,
      "fiber": 21.4,
      "protein": 11.9,
      "sodium": 595,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 0,
      "calcium": 102,
      "phosphorus": 0,
      "potassium": 43,
      "iron": 2.38,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0,
      "url": "https://www.latortillafactory.com/product/non-gmo-low-carb-flour-soft-taco-size/"

    },
    {
      "id": 3015,
      "name": "Wheat crackers",
      "categoryId": 3000,
      "energy": 455,
      "fat": 16.4,
      "saturatedFat": 3.21,
      "monounsaturatedFat": 3.47,
      "polyunsaturatedFat": 8.474,
      "carbs": 70.73,
      "sugar": 15.48,
      "fiber": 6.9,
      "protein": 7.3,
      "sodium": 699,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.284,
      "vitaminB2": 0.146,
      "vitaminB3": 4.022,
      "vitaminB5": 0.577,
      "vitaminB6": 0.244,
      "vitaminB9": 38,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 1.55,
      "vitaminK": 14.2,
      "magnesium": 72,
      "calcium": 92,
      "phosphorus": 302,
      "potassium": 283,
      "iron": 2.64,
      "selenium": 9.9,
      "zinc": 1.64,
      "manganese": 1.549,
      "copper": 0.274,
      "choline": 27.2
    },
    {
      "id": 3016, 
      "name": "Graham crackers",
      "categoryId": 3000,
      "energy": 430,
      "fat": 10.6,
      "saturatedFat": 1.633,
      "monounsaturatedFat": 2.509,
      "polyunsaturatedFat": 5.388,
      "carbs": 77.66,
      "sugar": 24.85,
      "fiber": 3.4,
      "protein": 6.69,
      "sodium": 516,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.265,
      "vitaminB2": 0.317,
      "vitaminB3": 4.439,
      "vitaminB5": 0,
      "vitaminB6": 0.156,
      "vitaminB9": 91,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 1.51,
      "vitaminK": 14.3,
      "magnesium": 40,
      "calcium": 77,
      "phosphorus": 185,
      "potassium": 170,
      "iron": 3.78,
      "selenium": 6.3,
      "zinc": 0.96,
      "manganese": 0,
      "copper": 0.17,
      "choline": 5.9
    }
  ]

================================================
FILE: src/foods/builtIn/beef.json
================================================
[
  {
    "id": 201,
    "name": "70% Lean Ground Beef",
    "categoryId": 200,
    "energy": 332,
    "fat": 30,
    "saturatedFat": 11.754,
    "monounsaturatedFat": 14.171,
    "polyunsaturatedFat": 0.697,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 14.35,
    "sodium": 66,
    "cholesterol": 78,
    "vitaminA": 4,
    "vitaminB1": 0.044,
    "vitaminB2": 0.151,
    "vitaminB3": 3.382,
    "vitaminB5": 0.395,
    "vitaminB6": 0.278,
    "vitaminB9": 9,
    "vitaminB12": 2.07,
    "vitaminC": 0,
    "vitaminD": 0.1,
    "vitaminE": 0.17,
    "vitaminK": 2.9,
    "magnesium": 14,
    "calcium": 24,
    "phosphorus": 132,
    "potassium": 218,
    "iron": 1.64,
    "selenium": 13.5,
    "zinc": 3.57,
    "manganese": 0.009,
    "copper": 0.05,
    "choline": 46.8
  },
  {
    "id": 202,
    "name": "75% Lean Ground Beef",
    "categoryId": 200,
    "energy": 293,
    "fat": 25,
    "saturatedFat": 9.568,
    "monounsaturatedFat": 11.383,
    "polyunsaturatedFat": 0.609,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 15.76,
    "sodium": 66,
    "cholesterol": 75,
    "vitaminA": 4,
    "vitaminB1": 0.044,
    "vitaminB2": 0.151,
    "vitaminB3": 3.804,
    "vitaminB5": 0.446,
    "vitaminB6": 0.301,
    "vitaminB9": 8,
    "vitaminB12": 2.11,
    "vitaminC": 0,
    "vitaminD": 0.1,
    "vitaminE": 0.17,
    "vitaminK": 2.4,
    "magnesium": 15,
    "calcium": 21,
    "phosphorus": 145,
    "potassium": 244,
    "iron": 1.79,
    "selenium": 14.3,
    "zinc": 3.87,
    "manganese": 0.009,
    "copper": 0.056,
    "choline": 51.6
  },
  {
    "id": 203,
    "name": "80% Lean Ground Beef",
    "categoryId": 200,
    "energy": 254,
    "fat": 20,
    "saturatedFat": 7.581,
    "monounsaturatedFat": 8.848,
    "polyunsaturatedFat": 0.521,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 17.17,
    "sodium": 66,
    "cholesterol": 71,
    "vitaminA": 4,
    "vitaminB1": 0.043,
    "vitaminB2": 0.151,
    "vitaminB3": 4.227,
    "vitaminB5": 0.498,
    "vitaminB6": 0.323,
    "vitaminB9": 7,
    "vitaminB12": 2.14,
    "vitaminC": 0,
    "vitaminD": 0.1,
    "vitaminE": 0.17,
    "vitaminK": 1.8,
    "magnesium": 17,
    "calcium": 18,
    "phosphorus": 158,
    "potassium": 270,
    "iron": 1.94,
    "selenium": 15,
    "zinc": 4.18,
    "manganese": 0.01,
    "copper": 0.061,
    "choline": 56.4
  },
  {
    "id": 204,
    "name": "90% Lean Ground Beef",
    "categoryId": 200,
    "energy": 176,
    "fat": 10,
    "saturatedFat": 3.927,
    "monounsaturatedFat": 4.194,
    "polyunsaturatedFat": 0.345,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 20,
    "sodium": 66,
    "cholesterol": 65,
    "vitaminA": 4,
    "vitaminB1": 0.042,
    "vitaminB2": 0.151,
    "vitaminB3": 5.072,
    "vitaminB5": 0.601,
    "vitaminB6": 0.369,
    "vitaminB9": 6,
    "vitaminB12": 2.21,
    "vitaminC": 0,
    "vitaminD": 0.1,
    "vitaminE": 0.17,
    "vitaminK": 0.8,
    "magnesium": 20,
    "calcium": 12,
    "phosphorus": 184,
    "potassium": 321,
    "iron": 2.24,
    "selenium": 16.6,
    "zinc": 4.79,
    "manganese": 0.01,
    "copper": 0.072,
    "choline": 66.1
  },
  {
    "id": 205,
    "name": "95% Lean Ground Beef",
    "categoryId": 200,
    "energy": 137,
    "fat": 5,
    "saturatedFat": 2.182,
    "monounsaturatedFat": 1.994,
    "polyunsaturatedFat": 0.257,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 21.41,
    "sodium": 66,
    "cholesterol": 62,
    "vitaminA": 4,
    "vitaminB1": 0.041,
    "vitaminB2": 0.151,
    "vitaminB3": 5.494,
    "vitaminB5": 0.652,
    "vitaminB6": 0.392,
    "vitaminB9": 5,
    "vitaminB12": 2.24,
    "vitaminC": 0,
    "vitaminD": 0.1,
    "vitaminE": 0.17,
    "vitaminK": 0.3,
    "magnesium": 22,
    "calcium": 9,
    "phosphorus": 198,
    "potassium": 346,
    "iron": 2.38,
    "selenium": 17.4,
    "zinc": 5.09,
    "manganese": 0.01,
    "copper": 0.078,
    "choline": 70.9
  },
  {
    "id": 206,
    "name": "Jack Link's Original Beef Jerky",
    "categoryId": 200,
    "energy": 278,
    "fat": 2.78,
    "saturatedFat": 0,
    "monounsaturatedFat": 0,
    "polyunsaturatedFat": 0,
    "carbs": 16.67,
    "sugar": 11.11,
    "fiber": 0,
    "protein": 44.44,
    "sodium": 2056,
    "cholesterol": 111,
    "vitaminA": 0,
    "vitaminB1": 0,
    "vitaminB2": 0,
    "vitaminB3": 0,
    "vitaminB5": 0,
    "vitaminB6": 0,
    "vitaminB9": 0,
    "vitaminB12": 0,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0,
    "vitaminK": 0,
    "magnesium": 0,
    "calcium": 0,
    "phosphorus": 0,
    "potassium": 0,
    "iron": 4,
    "selenium": 0,
    "zinc": 0,
    "manganese": 0,
    "copper": 0,
    "choline": 0,
    "url": "https://www.jacklinks.com/shop/original-beef-jerky"
  }
]

================================================
FILE: src/foods/builtIn/beverages.json
================================================
[
    {
      "id": 7001,
      "name": "Unsweetened Almond Milk",
      "categoryId": 7000,
      "energy": 15,
      "fat": 0.96,
      "saturatedFat": 0.08,
      "monounsaturatedFat": 0.59,
      "polyunsaturatedFat": 0.24,
      "carbs": 1.31,
      "sugar": 0.81,
      "fiber": 0.2,
      "protein": 0.4,
      "sodium": 72,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0.01,
      "vitaminB3": 0.07,
      "vitaminB5": 0.01,
      "vitaminB6": 0,
      "vitaminB9": 1,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 1,
      "vitaminE": 6.33,
      "vitaminK": 0,
      "magnesium": 6,
      "calcium": 184,
      "phosphorus": 9,
      "potassium": 67,
      "iron": 0.28,
      "selenium": 0.1,
      "zinc": 0.06,
      "manganese": 0.04,
      "copper": 0.02,
      "choline": 3.1,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 262
      }
    },
    {
      "id": 7002,
      "name": "Unsweetened Rice Milk",
      "categoryId": 7000,
      "energy": 47,
      "fat": 0.97,
      "saturatedFat": 0,
      "monounsaturatedFat": 0.625,
      "polyunsaturatedFat": 0.313,
      "carbs": 9.17,
      "sugar": 5.28,
      "fiber": 0.3,
      "protein": 0.28,
      "sodium": 39,
      "cholesterol": 0,
      "vitaminA": 63,
      "vitaminB1": 0.027,
      "vitaminB2": 0.142,
      "vitaminB3": 0.39,
      "vitaminB5": 0.146,
      "vitaminB6": 0.039,
      "vitaminB9": 2,
      "vitaminB12": 0.63,
      "vitaminC": 0,
      "vitaminD": 1,
      "vitaminE": 0.47,
      "vitaminK": 0.2,
      "magnesium": 11,
      "calcium": 118,
      "phosphorus": 56,
      "potassium": 27,
      "iron": 0.2,
      "selenium": 2.2,
      "zinc": 0.13,
      "manganese": 0.282,
      "copper": 0.037,
      "choline": 2.1
    },
    {
      "id": 7003,
      "name": "Whey Protein Powder",
      "categoryId": 7000,
      "energy": 352,
      "fat": 1.56,
      "saturatedFat": 0.781,
      "monounsaturatedFat": 0.158,
      "polyunsaturatedFat": 0.299,
      "carbs": 6.25,
      "sugar": 0,
      "fiber": 3.1,
      "protein": 78.13,
      "sodium": 156,
      "cholesterol": 16,
      "vitaminA": 0,
      "vitaminB1": 0.609,
      "vitaminB2": 2.017,
      "vitaminB3": 1.136,
      "vitaminB5": 5.516,
      "vitaminB6": 0.607,
      "vitaminB9": 33,
      "vitaminB12": 2.45,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 195,
      "calcium": 469,
      "phosphorus": 1321,
      "potassium": 500,
      "iron": 1.13,
      "selenium": 26.7,
      "zinc": 6.18,
      "manganese": 0,
      "copper": 0.049,
      "choline": 224,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 32
      }
    },
    {
      "id": 7004,
      "name": "Coconut Milk",
      "categoryId": 7000,
      "energy": 31,
      "fat": 2.08,
      "saturatedFat": 2.083,
      "monounsaturatedFat": 0,
      "polyunsaturatedFat": 0,
      "carbs": 2.92,
      "sugar": 2.5,
      "fiber": 0,
      "protein": 0.21,
      "sodium": 19,
      "cholesterol": 0,
      "vitaminA": 63,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 1.25,
      "vitaminC": 0,
      "vitaminD": 1,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 0,
      "calcium": 188,
      "phosphorus": 0,
      "potassium": 19,
      "iron": 0.3,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 240
      }
    },
    {
      "id": 7005,
      "name": "Red Wine",
      "categoryId": 7000,
      "energy": 85,
      "fat": 0,
      "saturatedFat": 0,
      "monounsaturatedFat": 0,
      "polyunsaturatedFat": 0,
      "carbs": 2.61,
      "sugar": 0.62,
      "fiber": 0,
      "protein": 0.07,
      "sodium": 4,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.005,
      "vitaminB2": 0.031,
      "vitaminB3": 0.224,
      "vitaminB5": 0.03,
      "vitaminB6": 0.057,
      "vitaminB9": 1,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0.4,
      "magnesium": 12,
      "calcium": 8,
      "phosphorus": 23,
      "potassium": 127,
      "iron": 0.46,
      "selenium": 0.2,
      "zinc": 0.14,
      "manganese": 0.132,
      "copper": 0.011,
      "choline": 5.7
    },
    {
      "id": 7006,
      "name": "Beer",
      "categoryId": 7000,
      "energy": 43,
      "fat": 0,
      "saturatedFat": 0,
      "monounsaturatedFat": 0,
      "polyunsaturatedFat": 0,
      "carbs": 3.55,
      "sugar": 0,
      "fiber": 0,
      "protein": 0.46,
      "sodium": 4,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.005,
      "vitaminB2": 0.025,
      "vitaminB3": 0.513,
      "vitaminB5": 0.041,
      "vitaminB6": 0.046,
      "vitaminB9": 6,
      "vitaminB12": 0.02,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 6,
      "calcium": 4,
      "phosphorus": 14,
      "potassium": 27,
      "iron": 0.02,
      "selenium": 0.6,
      "zinc": 0.01,
      "manganese": 0.008,
      "copper": 0.005,
      "choline": 10.1
    }
  ]

================================================
FILE: src/foods/builtIn/dairyAndEggs.json
================================================
[
  {
    "id": 501,
    "name": "Skim Milk",
    "categoryId": 500,
    "energy": 34,
    "fat": 0.08,
    "saturatedFat": 0.049,
    "monounsaturatedFat": 0.017,
    "polyunsaturatedFat": 0.006,
    "carbs": 4.89,
    "sugar": 5.05,
    "fiber": 0,
    "protein": 3.43,
    "sodium": 41,
    "cholesterol": 3,
    "vitaminA": 64,
    "vitaminB1": 0.056,
    "vitaminB2": 0.131,
    "vitaminB3": 0.118,
    "vitaminB5": 0,
    "vitaminB6": 0.058,
    "vitaminB9": 2,
    "vitaminB12": 0.58,
    "vitaminC": 0,
    "vitaminD": 1.1,
    "vitaminE": 0,
    "vitaminK": 0,
    "magnesium": 12,
    "calcium": 132,
    "phosphorus": 107,
    "potassium": 167,
    "iron": 0,
    "selenium": 2,
    "zinc": 0.45,
    "manganese": 0,
    "copper": 0.002,
    "choline": 18.2
  },
  {
    "id": 502,
    "name": "Whole Eggs",
    "categoryId": 500,
    "energy": 143,
    "fat": 9.51,
    "saturatedFat": 3.126,
    "monounsaturatedFat": 3.658,
    "polyunsaturatedFat": 1.911,
    "carbs": 0.72,
    "sugar": 0.37,
    "fiber": 0,
    "protein": 12.56,
    "sodium": 142,
    "cholesterol": 372,
    "vitaminA": 160,
    "vitaminB1": 0.04,
    "vitaminB2": 0.457,
    "vitaminB3": 0.075,
    "vitaminB5": 1.533,
    "vitaminB6": 0.17,
    "vitaminB9": 47,
    "vitaminB12": 0.89,
    "vitaminC": 0,
    "vitaminD": 2,
    "vitaminE": 1.05,
    "vitaminK": 0.3,
    "magnesium": 12,
    "calcium": 56,
    "phosphorus": 198,
    "potassium": 138,
    "iron": 1.75,
    "selenium": 30.7,
    "zinc": 1.29,
    "manganese": 0.028,
    "copper": 0.072,
    "choline": 293.8,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 243
    }
  },
  {
    "id": 503,
    "name": "Egg Whites",
    "categoryId": 500,
    "energy": 52,
    "fat": 0.17,
    "saturatedFat": 0,
    "monounsaturatedFat": 0,
    "polyunsaturatedFat": 0,
    "carbs": 0.73,
    "sugar": 0.71,
    "fiber": 0,
    "protein": 10.9,
    "sodium": 166,
    "cholesterol": 0,
    "vitaminA": 0,
    "vitaminB1": 0.004,
    "vitaminB2": 0.439,
    "vitaminB3": 0.105,
    "vitaminB5": 0.19,
    "vitaminB6": 0.005,
    "vitaminB9": 4,
    "vitaminB12": 0.09,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0,
    "vitaminK": 0,
    "magnesium": 11,
    "calcium": 7,
    "phosphorus": 15,
    "potassium": 163,
    "iron": 0.08,
    "selenium": 20,
    "zinc": 0.03,
    "manganese": 0.011,
    "copper": 0.023,
    "choline": 1.1,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 243
    }
  },
  {
    "id": 504,
    "name": "Half and Half",
    "categoryId": 500,
    "energy": 131,
    "fat": 11.5,
    "saturatedFat": 7.032,
    "monounsaturatedFat": 3.32,
    "polyunsaturatedFat": 0.554,
    "carbs": 4.3,
    "sugar": 4.13,
    "fiber": 0,
    "protein": 3.13,
    "sodium": 61,
    "cholesterol": 35,
    "vitaminA": 97,
    "vitaminB1": 0.03,
    "vitaminB2": 0.194,
    "vitaminB3": 0.109,
    "vitaminB5": 0.539,
    "vitaminB6": 0.05,
    "vitaminB9": 3,
    "vitaminB12": 0.19,
    "vitaminC": 0.9,
    "vitaminD": 0,
    "vitaminE": 0.25,
    "vitaminK": 1.3,
    "magnesium": 10,
    "calcium": 107,
    "phosphorus": 95,
    "potassium": 132,
    "iron": 0.05,
    "selenium": 3.2,
    "zinc": 0.39,
    "manganese": 0.005,
    "copper": 0.009,
    "choline": 18.7,
    "volume": {
      "portionId": "tablespoons",
      "weightInGrams": 15
    }
  },
  {
    "id": 505,
    "name": "Reduced Fat Cheddar Cheese",
    "categoryId": 500,
    "energy": 316,
    "fat": 20.41,
    "saturatedFat": 12.602,
    "monounsaturatedFat": 5.304,
    "polyunsaturatedFat": 0.893,
    "carbs": 2.67,
    "sugar": 0.26,
    "fiber": 0,
    "protein": 27.35,
    "sodium": 628,
    "cholesterol": 76,
    "vitaminA": 145,
    "vitaminB1": 0.021,
    "vitaminB2": 0.397,
    "vitaminB3": 0.145,
    "vitaminB5": 0.389,
    "vitaminB6": 0.084,
    "vitaminB9": 20,
    "vitaminB12": 1.41,
    "vitaminC": 0,
    "vitaminD": 0.3,
    "vitaminE": 0.48,
    "vitaminK": 1.5,
    "magnesium": 27,
    "calcium": 761,
    "phosphorus": 520,
    "potassium": 63,
    "iron": 0.12,
    "selenium": 35.8,
    "zinc": 4.44,
    "manganese": 0.031,
    "copper": 0.043,
    "choline": 15.4
  },
  {
    "id": 506,
    "name": "Sour Cream",
    "categoryId": 500,
    "energy": 198,
    "fat": 19.35,
    "saturatedFat": 10.14,
    "monounsaturatedFat": 4.594,
    "polyunsaturatedFat": 0.8,
    "carbs": 4.63,
    "sugar": 3.41,
    "fiber": 0,
    "protein": 2.44,
    "sodium": 31,
    "cholesterol": 59,
    "vitaminA": 124,
    "vitaminB1": 0.02,
    "vitaminB2": 0.168,
    "vitaminB3": 0.093,
    "vitaminB5": 0.472,
    "vitaminB6": 0.041,
    "vitaminB9": 6,
    "vitaminB12": 0.21,
    "vitaminC": 0.9,
    "vitaminD": 0,
    "vitaminE": 0.38,
    "vitaminK": 1.5,
    "magnesium": 10,
    "calcium": 101,
    "phosphorus": 76,
    "potassium": 125,
    "iron": 0.07,
    "selenium": 3.7,
    "zinc": 0.33,
    "manganese": 0.015,
    "copper": 0.018,
    "choline": 19.2,
    "volume": {
      "portionId": "tablespoons",
      "weightInGrams": 12
    }
  },
  {
    "id": 507,
    "name": "Fat Free Sour Cream",
    "categoryId": 500,
    "energy": 74,
    "fat": 0,
    "saturatedFat": 0,
    "monounsaturatedFat": 0,
    "polyunsaturatedFat": 0,
    "carbs": 15.6,
    "sugar": 0.39,
    "fiber": 0,
    "protein": 3.1,
    "sodium": 141,
    "cholesterol": 9,
    "vitaminA": 73,
    "vitaminB1": 0.04,
    "vitaminB2": 0.15,
    "vitaminB3": 0.07,
    "vitaminB5": 0,
    "vitaminB6": 0.02,
    "vitaminB9": 11,
    "vitaminB12": 0.3,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0,
    "vitaminK": 0,
    "magnesium": 10,
    "calcium": 125,
    "phosphorus": 95,
    "potassium": 129,
    "iron": 0,
    "selenium": 5.3,
    "zinc": 0.5,
    "manganese": 0,
    "copper": 0.016,
    "choline": 19.2,
    "volume": {
      "portionId": "tablespoons",
      "weightInGrams": 12
    }
  },
  {
    "id": 508,
    "name": "2% Milk",
    "categoryId": 500,
    "energy": 50,
    "fat": 1.98,
    "saturatedFat": 1.257,
    "monounsaturatedFat": 0.56,
    "polyunsaturatedFat": 0.073,
    "carbs": 4.8,
    "sugar": 5.06,
    "fiber": 0,
    "protein": 3.3,
    "sodium": 47,
    "cholesterol": 8,
    "vitaminA": 55,
    "vitaminB1": 0.039,
    "vitaminB2": 0.185,
    "vitaminB3": 0.092,
    "vitaminB5": 0.356,
    "vitaminB6": 0.038,
    "vitaminB9": 5,
    "vitaminB12": 0.53,
    "vitaminC": 0.2,
    "vitaminD": 1.2,
    "vitaminE": 0.03,
    "vitaminK": 0.2,
    "magnesium": 11,
    "calcium": 120,
    "phosphorus": 92,
    "potassium": 140,
    "iron": 0.02,
    "selenium": 2.5,
    "zinc": 0.48,
    "manganese": 0.014,
    "copper": 0.006,
    "choline": 16.4,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 244
    }
  },
  {
    "id": 509,
    "name": "Nonfat Mozzarella Cheese",
    "categoryId": 500,
    "energy": 141,
    "fat": 0,
    "saturatedFat": 0,
    "monounsaturatedFat": 0,
    "polyunsaturatedFat": 0,
    "carbs": 3.5,
    "sugar": 1.48,
    "fiber": 1.8,
    "protein": 31.7,
    "sodium": 743,
    "cholesterol": 18,
    "vitaminA": 127,
    "vitaminB1": 0.02,
    "vitaminB2": 0.3,
    "vitaminB3": 0.12,
    "vitaminB5": 0,
    "vitaminB6": 0.08,
    "vitaminB9": 10,
    "vitaminB12": 0.92,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0.14,
    "vitaminK": 1.6,
    "magnesium": 33,
    "calcium": 961,
    "phosphorus": 656,
    "potassium": 106,
    "iron": 0.31,
    "selenium": 18.9,
    "zinc": 3.92,
    "manganese": 0,
    "copper": 0.034,
    "choline": 15.4,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 113
    }
  },
  {
    "id": 510,
    "name": "Feta Cheese",
    "categoryId": 500,
    "energy": 265,
    "fat": 21.49,
    "saturatedFat": 13.3,
    "monounsaturatedFat": 4.623,
    "polyunsaturatedFat": 0.591,
    "carbs": 3.88,
    "sugar": 0,
    "fiber": 0,
    "protein": 14.21,
    "sodium": 1139,
    "cholesterol": 89,
    "vitaminA": 125,
    "vitaminB1": 0.154,
    "vitaminB2": 0.844,
    "vitaminB3": 0.991,
    "vitaminB5": 0.967,
    "vitaminB6": 0.424,
    "vitaminB9": 32,
    "vitaminB12": 1.69,
    "vitaminC": 0,
    "vitaminD": 0.4,
    "vitaminE": 0.18,
    "vitaminK": 1.8,
    "magnesium": 19,
    "calcium": 493,
    "phosphorus": 337,
    "potassium": 62,
    "iron": 0.65,
    "selenium": 15,
    "zinc": 2.88,
    "manganese": 0.028,
    "copper": 0.032,
    "choline": 15.4,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 150
    }
  },
  {
    "id": 511,
    "name": "0% Greek Yogurt",
    "categoryId": 500,
    "energy": 53,
    "fat": 0,
    "saturatedFat": 0,
    "monounsaturatedFat": 0,
    "polyunsaturatedFat": 0,
    "carbs": 2.94,
    "sugar": 2.94,
    "fiber": 0,
    "protein": 10.59,
    "sodium": 38,
    "cholesterol": 0,
    "vitaminA": 0,
    "vitaminB1": 0,
    "vitaminB2": 0,
    "vitaminB3": 0,
    "vitaminB5": 0,
    "vitaminB6": 0,
    "vitaminB9": 0,
    "vitaminB12": 0,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0,
    "vitaminK": 0,
    "magnesium": 0,
    "calcium": 118,
    "phosphorus": 0,
    "potassium": 0,
    "iron": 0,
    "selenium": 0,
    "zinc": 0,
    "manganese": 0,
    "copper": 0,
    "choline": 0
  },
  {
    "id": 512,
    "name": "1% Cottage Cheese",
    "categoryId": 500,
    "energy": 72,
    "fat": 1.02,
    "saturatedFat": 0.645,
    "monounsaturatedFat": 0.291,
    "polyunsaturatedFat": 0.031,
    "carbs": 2.72,
    "sugar": 2.72,
    "fiber": 0,
    "protein": 12.39,
    "sodium": 406,
    "cholesterol": 4,
    "vitaminA": 11,
    "vitaminB1": 0.021,
    "vitaminB2": 0.165,
    "vitaminB3": 0.128,
    "vitaminB5": 0.215,
    "vitaminB6": 0.068,
    "vitaminB9": 12,
    "vitaminB12": 0.63,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0.01,
    "vitaminK": 0.1,
    "magnesium": 5,
    "calcium": 61,
    "phosphorus": 134,
    "potassium": 86,
    "iron": 0.14,
    "selenium": 9,
    "zinc": 0.38,
    "manganese": 0.003,
    "copper": 0.028,
    "choline": 17.5,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 226
    }
  },
  {
    "id": 513,
    "name": "2% Cottage Cheese",
    "categoryId": 500,
    "energy": 81,
    "fat": 2.27,
    "saturatedFat": 1.235,
    "monounsaturatedFat": 0.516,
    "polyunsaturatedFat": 0.083,
    "carbs": 4.76,
    "sugar": 4,
    "fiber": 0,
    "protein": 10.45,
    "sodium": 308,
    "cholesterol": 12,
    "vitaminA": 68,
    "vitaminB1": 0.02,
    "vitaminB2": 0.251,
    "vitaminB3": 0.103,
    "vitaminB5": 0.524,
    "vitaminB6": 0.057,
    "vitaminB9": 8,
    "vitaminB12": 0.47,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0.08,
    "vitaminK": 0,
    "magnesium": 9,
    "calcium": 111,
    "phosphorus": 150,
    "potassium": 125,
    "iron": 0.13,
    "selenium": 11.9,
    "zinc": 0.51,
    "manganese": 0.015,
    "copper": 0.033,
    "choline": 16.3,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 226
    }
  },
  {
    "id": 514,
    "name": "Grated Parmesan Cheese",
    "categoryId": 500,
    "energy": 420,
    "fat": 27.84,
    "saturatedFat": 15.371,
    "monounsaturatedFat": 7.13,
    "polyunsaturatedFat": 1.386,
    "carbs": 13.91,
    "sugar": 0.07,
    "fiber": 0,
    "protein": 28.42,
    "sodium": 1804,
    "cholesterol": 86,
    "vitaminA": 262,
    "vitaminB1": 0.026,
    "vitaminB2": 0.358,
    "vitaminB3": 0.08,
    "vitaminB5": 0.45,
    "vitaminB6": 0.081,
    "vitaminB9": 6,
    "vitaminB12": 1.4,
    "vitaminC": 0,
    "vitaminD": 0.5,
    "vitaminE": 0.53,
    "vitaminK": 1.7,
    "magnesium": 34,
    "calcium": 853,
    "phosphorus": 627,
    "potassium": 180,
    "iron": 0.49,
    "selenium": 34.4,
    "zinc": 4.2,
    "manganese": 0.071,
    "copper": 0.04,
    "choline": 14.1,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 100
    }
  },
  {
    "id": 515,
    "name": "Light Whipping Cream",
    "categoryId": 500,
    "energy": 292,
    "fat": 30.91,
    "saturatedFat": 19.337,
    "monounsaturatedFat": 9.093,
    "polyunsaturatedFat": 0.884,
    "carbs": 2.96,
    "sugar": 2.96,
    "fiber": 0,
    "protein": 2.17,
    "sodium": 34,
    "cholesterol": 111,
    "vitaminA": 279,
    "vitaminB1": 0.024,
    "vitaminB2": 0.125,
    "vitaminB3": 0.042,
    "vitaminB5": 0.259,
    "vitaminB6": 0.028,
    "vitaminB9": 4,
    "vitaminB12": 0.2,
    "vitaminC": 0.6,
    "vitaminD": 0.6,
    "vitaminE": 0.88,
    "vitaminK": 2.7,
    "magnesium": 7,
    "calcium": 69,
    "phosphorus": 61,
    "potassium": 97,
    "iron": 0.03,
    "selenium": 0.5,
    "zinc": 0.25,
    "manganese": 0.001,
    "copper": 0.007,
    "choline": 16.8,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 239
    }
  },
  {
    "id": 516,
    "name": "Reduced Fat Grated Parmesan Cheese",
    "categoryId": 500,
    "energy": 265,
    "fat": 20,
    "saturatedFat": 13.317,
    "monounsaturatedFat": 6.098,
    "polyunsaturatedFat": 0.462,
    "carbs": 1.37,
    "sugar": 0,
    "fiber": 0,
    "protein": 20,
    "sodium": 1529,
    "cholesterol": 88,
    "vitaminA": 160,
    "vitaminB1": 0.029,
    "vitaminB2": 0.486,
    "vitaminB3": 0.114,
    "vitaminB5": 0.325,
    "vitaminB6": 0.049,
    "vitaminB9": 10,
    "vitaminB12": 2.26,
    "vitaminC": 0,
    "vitaminD": 0.4,
    "vitaminE": 0.17,
    "vitaminK": 1.7,
    "magnesium": 38,
    "calcium": 1109,
    "phosphorus": 729,
    "potassium": 125,
    "iron": 0.9,
    "selenium": 17.7,
    "zinc": 3.87,
    "manganese": 0.085,
    "copper": 0.238,
    "choline": 20.7,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 100
    }
  },
  {
    "id": 517,
    "name": "Neufchatel Cheese",
    "categoryId": 500,
    "energy": 253,
    "fat": 22.78,
    "saturatedFat": 12.79,
    "monounsaturatedFat": 5.784,
    "polyunsaturatedFat": 0.97,
    "carbs": 3.59,
    "sugar": 3.19,
    "fiber": 0,
    "protein": 9.15,
    "sodium": 334,
    "cholesterol": 74,
    "vitaminA": 241,
    "vitaminB1": 0.022,
    "vitaminB2": 0.155,
    "vitaminB3": 0.21,
    "vitaminB5": 0.575,
    "vitaminB6": 0.041,
    "vitaminB9": 14,
    "vitaminB12": 0.3,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0.4,
    "vitaminK": 1.7,
    "magnesium": 10,
    "calcium": 117,
    "phosphorus": 138,
    "potassium": 152,
    "iron": 0.13,
    "selenium": 3,
    "zinc": 0.82,
    "manganese": 0.011,
    "copper": 0.027,
    "choline": 0
  },
  {
    "id": 518,
    "name": "Low Fat Cream Cheese",
    "categoryId": 500,
    "energy": 208,
    "fat": 16.67,
    "saturatedFat": 10,
    "monounsaturatedFat": 3.996,
    "polyunsaturatedFat": 0.575,
    "carbs": 6.73,
    "sugar": 3.3,
    "fiber": 0,
    "protein": 7.85,
    "sodium": 317,
    "cholesterol": 54,
    "vitaminA": 161,
    "vitaminB1": 0.04,
    "vitaminB2": 0.185,
    "vitaminB3": 0.125,
    "vitaminB5": 0.845,
    "vitaminB6": 0.045,
    "vitaminB9": 19,
    "vitaminB12": 0.92,
    "vitaminC": 0,
    "vitaminD": 0.3,
    "vitaminE": 0.27,
    "vitaminK": 1.1,
    "magnesium": 8,
    "calcium": 148,
    "phosphorus": 152,
    "potassium": 247,
    "iron": 0.17,
    "selenium": 4,
    "zinc": 0.57,
    "manganese": 0.011,
    "copper": 0.032,
    "choline": 12.1,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 240
    }
  },
  {
    "id": 519,
    "name": "Fat Free American Cheese",
    "categoryId": 500,
    "energy": 126,
    "fat": 0,
    "saturatedFat": 0,
    "monounsaturatedFat": 0,
    "polyunsaturatedFat": 0,
    "carbs": 10.53,
    "sugar": 5.26,
    "fiber": 0,
    "protein": 21.05,
    "sodium": 1316,
    "cholesterol": 26,
    "vitaminA": 56,
    "vitaminB1": 0.412,
    "vitaminB2": 0.545,
    "vitaminB3": 5.56,
    "vitaminB5": 0,
    "vitaminB6": 0.567,
    "vitaminB9": 9,
    "vitaminB12": 1.85,
    "vitaminC": 0,
    "vitaminD": 0.1,
    "vitaminE": 0.27,
    "vitaminK": 0.2,
    "magnesium": 115,
    "calcium": 789,
    "phosphorus": 316,
    "potassium": 393,
    "iron": 0,
    "selenium": 14.6,
    "zinc": 4.11,
    "manganese": 0,
    "copper": 0.559,
    "choline": 38.4
  },
  {
    "id": 520,
    "name": "Cream Cheese",
    "categoryId": 500,
    "energy": 350,
    "fat": 34.44,
    "saturatedFat": 20.213,
    "monounsaturatedFat": 8.907,
    "polyunsaturatedFat": 1.483,
    "carbs": 5.52,
    "sugar": 3.76,
    "fiber": 0,
    "protein": 6.15,
    "sodium": 314,
    "cholesterol": 101,
    "vitaminA": 308,
    "vitaminB1": 0.023,
    "vitaminB2": 0.23,
    "vitaminB3": 0.091,
    "vitaminB5": 0.517,
    "vitaminB6": 0.056,
    "vitaminB9": 9,
    "vitaminB12": 0.22,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0.86,
    "vitaminK": 2.1,
    "magnesium": 9,
    "calcium": 97,
    "phosphorus": 107,
    "potassium": 132,
    "iron": 0.11,
    "selenium": 8.6,
    "zinc": 0.5,
    "manganese": 0.011,
    "copper": 0.018,
    "choline": 26.8,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 232
    }
  },
  {
    "id": 521,
    "name": "Gouda Cheese",
    "categoryId": 500,
    "energy": 356,
    "fat": 27.44,
    "saturatedFat": 17.614,
    "monounsaturatedFat": 7.747,
    "polyunsaturatedFat": 0.657,
    "carbs": 2.22,
    "sugar": 2.22,
    "fiber": 0,
    "protein": 24.94,
    "sodium": 819,
    "cholesterol": 114,
    "vitaminA": 165,
    "vitaminB1": 0.03,
    "vitaminB2": 0.334,
    "vitaminB3": 0.063,
    "vitaminB5": 0.34,
    "vitaminB6": 0.08,
    "vitaminB9": 21,
    "vitaminB12": 1.54,
    "vitaminC": 0,
    "vitaminD": 0.5,
    "vitaminE": 0.24,
    "vitaminK": 2.3,
    "magnesium": 29,
    "calcium": 700,
    "phosphorus": 546,
    "potassium": 121,
    "iron": 0.24,
    "selenium": 14.5,
    "zinc": 3.9,
    "manganese": 0.011,
    "copper": 0.036,
    "choline": 15.4
  },
  {
    "id": 522,
    "name": "Brie Cheese",
    "categoryId": 500,
    "energy": 334,
    "fat": 27.68,
    "saturatedFat": 17.41,
    "monounsaturatedFat": 8.013,
    "polyunsaturatedFat": 0.826,
    "carbs": 0.45,
    "sugar": 0.45,
    "fiber": 0,
    "protein": 20.75,
    "sodium": 629,
    "cholesterol": 100,
    "vitaminA": 174,
    "vitaminB1": 0.07,
    "vitaminB2": 0.52,
    "vitaminB3": 0.38,
    "vitaminB5": 0.69,
    "vitaminB6": 0.235,
    "vitaminB9": 65,
    "vitaminB12": 1.65,
    "vitaminC": 0,
    "vitaminD": 0.5,
    "vitaminE": 0.24,
    "vitaminK": 2.3,
    "magnesium": 20,
    "calcium": 184,
    "phosphorus": 188,
    "potassium": 152,
    "iron": 0.5,
    "selenium": 14.5,
    "zinc": 2.38,
    "manganese": 0.034,
    "copper": 0.019,
    "choline": 15.4,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 240
    }
  },
  {
    "id": 523,
    "name": "Cheddar Cheese",
    "categoryId": 500,
    "energy": 410,
    "fat": 33.82,
    "saturatedFat": 19.368,
    "monounsaturatedFat": 8.428,
    "polyunsaturatedFat": 1.433,
    "carbs": 2.13,
    "sugar": 0.27,
    "fiber": 0,
    "protein": 24.25,
    "sodium": 644,
    "cholesterol": 99,
    "vitaminA": 263,
    "vitaminB1": 0.027,
    "vitaminB2": 0.434,
    "vitaminB3": 0.039,
    "vitaminB5": 0.481,
    "vitaminB6": 0.075,
    "vitaminB9": 27,
    "vitaminB12": 0.88,
    "vitaminC": 0,
    "vitaminD": 1,
    "vitaminE": 0.78,
    "vitaminK": 2.4,
    "magnesium": 27,
    "calcium": 711,
    "phosphorus": 460,
    "potassium": 76,
    "iron": 0.16,
    "selenium": 28.3,
    "zinc": 3.74,
    "manganese": 0.024,
    "copper": 0.035,
    "choline": 16.5
  },
  {
    "id": 524,
    "name": "Blue Cheese",
    "categoryId": 500,
    "energy": 353,
    "fat": 28.74,
    "saturatedFat": 18.669,
    "monounsaturatedFat": 7.778,
    "polyunsaturatedFat": 0.8,
    "carbs": 2.34,
    "sugar": 0.5,
    "fiber": 0,
    "protein": 21.4,
    "sodium": 1146,
    "cholesterol": 75,
    "vitaminA": 198,
    "vitaminB1": 0.029,
    "vitaminB2": 0.382,
    "vitaminB3": 1.016,
    "vitaminB5": 1.729,
    "vitaminB6": 0.166,
    "vitaminB9": 36,
    "vitaminB12": 1.22,
    "vitaminC": 0,
    "vitaminD": 0.5,
    "vitaminE": 0.25,
    "vitaminK": 2.4,
    "magnesium": 23,
    "calcium": 528,
    "phosphorus": 387,
    "potassium": 256,
    "iron": 0.31,
    "selenium": 14.5,
    "zinc": 2.66,
    "manganese": 0.009,
    "copper": 0.04,
    "choline": 15.4,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 135
    }
  },
  {
    "id": 525,
    "name": "Egg Yolk",
    "categoryId": 500,
    "energy": 322,
    "fat": 26.54,
    "saturatedFat": 9.551,
    "monounsaturatedFat": 11.738,
    "polyunsaturatedFat": 4.204,
    "carbs": 3.59,
    "sugar": 0.56,
    "fiber": 0,
    "protein": 15.86,
    "sodium": 48,
    "cholesterol": 1085,
    "vitaminA": 381,
    "vitaminB1": 0.176,
    "vitaminB2": 0.528,
    "vitaminB3": 0.024,
    "vitaminB5": 2.99,
    "vitaminB6": 0.35,
    "vitaminB9": 146,
    "vitaminB12": 1.95,
    "vitaminC": 0,
    "vitaminD": 5.4,
    "vitaminE": 2.58,
    "vitaminK": 0.7,
    "magnesium": 5,
    "calcium": 129,
    "phosphorus": 390,
    "potassium": 109,
    "iron": 2.73,
    "selenium": 56,
    "zinc": 2.3,
    "manganese": 0.055,
    "copper": 0.077,
    "choline": 820.2,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 243
    }
  },
  {
    "id": 526,
    "name": "Provolone Cheese",
    "categoryId": 500,
    "energy": 351,
    "fat": 26.62,
    "saturatedFat": 17.078,
    "monounsaturatedFat": 7.393,
    "polyunsaturatedFat": 0.769,
    "carbs": 2.14,
    "sugar": 0.56,
    "fiber": 0,
    "protein": 25.58,
    "sodium": 727,
    "cholesterol": 69,
    "vitaminA": 236,
    "vitaminB1": 0.019,
    "vitaminB2": 0.321,
    "vitaminB3": 0.156,
    "vitaminB5": 0.476,
    "vitaminB6": 0.073,
    "vitaminB9": 10,
    "vitaminB12": 1.46,
    "vitaminC": 0,
    "vitaminD": 0.5,
    "vitaminE": 0.23,
    "vitaminK": 2.2,
    "magnesium": 28,
    "calcium": 756,
    "phosphorus": 496,
    "potassium": 138,
    "iron": 0.52,
    "selenium": 14.5,
    "zinc": 3.23,
    "manganese": 0.01,
    "copper": 0.026,
    "choline": 15.4,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 132
    }
  },
  {
    "id": 527,
    "name": "Reduced Fat Provolone Chesse",
    "categoryId": 500,
    "energy": 274,
    "fat": 17.6,
    "saturatedFat": 11.3,
    "monounsaturatedFat": 4.89,
    "polyunsaturatedFat": 0.51,
    "carbs": 3.5,
    "sugar": 0.55,
    "fiber": 0,
    "protein": 24.7,
    "sodium": 615,
    "cholesterol": 55,
    "vitaminA": 141,
    "vitaminB1": 0.019,
    "vitaminB2": 0.321,
    "vitaminB3": 0.156,
    "vitaminB5": 0.476,
    "vitaminB6": 0.073,
    "vitaminB9": 10,
    "vitaminB12": 1.46,
    "vitaminC": 0,
    "vitaminD": 0.3,
    "vitaminE": 0.15,
    "vitaminK": 1.5,
    "magnesium": 28,
    "calcium": 756,
    "phosphorus": 496,
    "potassium": 138,
    "iron": 0.52,
    "selenium": 14.5,
    "zinc": 3.23,
    "manganese": 0.01,
    "copper": 0.026,
    "choline": 12.9,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 113
    }
  },
  {
    "id": 528,
    "name": "Swiss Cheese",
    "categoryId": 500,
    "energy": 393,
    "fat": 30.99,
    "saturatedFat": 18.227,
    "monounsaturatedFat": 8.046,
    "polyunsaturatedFat": 1.341,
    "carbs": 1.44,
    "sugar": 0,
    "fiber": 0,
    "protein": 26.96,
    "sodium": 187,
    "cholesterol": 93,
    "vitaminA": 288,
    "vitaminB1": 0.011,
    "vitaminB2": 0.302,
    "vitaminB3": 0.064,
    "vitaminB5": 0.353,
    "vitaminB6": 0.071,
    "vitaminB9": 10,
    "vitaminB12": 3.06,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0.6,
    "vitaminK": 1.4,
    "magnesium": 33,
    "calcium": 890,
    "phosphorus": 574,
    "potassium": 72,
    "iron": 0.13,
    "selenium": 30,
    "zinc": 4.37,
    "manganese": 0.026,
    "copper": 0.047,
    "choline": 13.8,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 244
    }
  },
  {
    "id": 529,
    "name": "Low Fat Swiss Cheese",
    "categoryId": 500,
    "energy": 179,
    "fat": 5.1,
    "saturatedFat": 3.304,
    "monounsaturatedFat": 1.351,
    "polyunsaturatedFat": 0.18,
    "carbs": 3.4,
    "sugar": 1.33,
    "fiber": 0,
    "protein": 28.4,
    "sodium": 199,
    "cholesterol": 35,
    "vitaminA": 40,
    "vitaminB1": 0.02,
    "vitaminB2": 0.36,
    "vitaminB3": 0.09,
    "vitaminB5": 0,
    "vitaminB6": 0.08,
    "vitaminB9": 6,
    "vitaminB12": 1.68,
    "vitaminC": 0,
    "vitaminD": 0.1,
    "vitaminE": 0.07,
    "vitaminK": 0.5,
    "magnesium": 36,
    "calcium": 961,
    "phosphorus": 605,
    "potassium": 111,
    "iron": 0.17,
    "selenium": 12.7,
    "zinc": 3.9,
    "manganese": 0,
    "copper": 0.027,
    "choline": 15.4,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 132
    }
  },
  {
    "id": 530,
    "name": "White Queso Cheese",
    "categoryId": 500,
    "energy": 310,
    "fat": 24.31,
    "saturatedFat": 13.661,
    "monounsaturatedFat": 6.459,
    "polyunsaturatedFat": 1.149,
    "carbs": 2.53,
    "sugar": 1.76,
    "fiber": 0,
    "protein": 20.38,
    "sodium": 704,
    "cholesterol": 70,
    "vitaminA": 157,
    "vitaminB1": 0.048,
    "vitaminB2": 0.23,
    "vitaminB3": 0.035,
    "vitaminB5": 0.397,
    "vitaminB6": 0.086,
    "vitaminB9": 0,
    "vitaminB12": 1.75,
    "vitaminC": 0,
    "vitaminD": 0.7,
    "vitaminE": 0.47,
    "vitaminK": 1.6,
    "magnesium": 29,
    "calcium": 690,
    "phosphorus": 467,
    "potassium": 126,
    "iron": 0.18,
    "selenium": 13.8,
    "zinc": 3.06,
    "manganese": 0.021,
    "copper": 0.025,
    "choline": 15.4,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 118
    }
  },
  {
    "id": 531,
    "name": "Part Skim Ricotta Cheese",
    "categoryId": 500,
    "energy": 138,
    "fat": 7.91,
    "saturatedFat": 4.927,
    "monounsaturatedFat": 2.314,
    "polyunsaturatedFat": 0.26,
    "carbs": 5.14,
    "sugar": 0.31,
    "fiber": 0,
    "protein": 11.39,
    "sodium": 99,
    "cholesterol": 31,
    "vitaminA": 107,
    "vitaminB1": 0.021,
    "vitaminB2": 0.185,
    "vitaminB3": 0.078,
    "vitaminB5": 0.242,
    "vitaminB6": 0.02,
    "vitaminB9": 13,
    "vitaminB12": 0.29,
    "vitaminC": 0,
    "vitaminD": 0.1,
    "vitaminE": 0.07,
    "vitaminK": 0.7,
    "magnesium": 15,
    "calcium": 272,
    "phosphorus": 183,
    "potassium": 125,
    "iron": 0.44,
    "selenium": 16.7,
    "zinc": 1.34,
    "manganese": 0.01,
    "copper": 0.034,
    "choline": 16.3,
    "volume": {
      "portionId": "cups",
      "weightInGrams": 124
    }
  },
  {
    "id": 532,
    "name": "Egg White Wraps",
    "categoryId": 500,
    "energy": 89,
    "fat": 0,
    "saturatedFat": 0,
    "monounsaturatedFat": 0,
    "polyunsaturatedFat": 0,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 17.86,
    "sodium": 429,
    "cholesterol": 0,
    "vitaminA": 0,
    "vitaminB1": 0,
    "vitaminB2": 0,
    "vitaminB3": 0,
    "vitaminB5": 0,
    "vitaminB6": 0,
    "vitaminB9": 0,
    "vitaminB12": 0,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0,
    "vitaminK": 0,
    "magnesium": 0,
    "calcium": 36,
    "phosphorus": 0,
    "potassium": 250,
    "iron": 0,
    "selenium": 0,
    "zinc": 0,
    "manganese": 0,
    "copper": 0,
    "choline": 0
  }
]

================================================
FILE: src/foods/builtIn/fatsAndOils.json
================================================
[
    {
      "id": 2001,
      "name": "PAM cooking spray",
      "categoryId": 2000,
      "energy": 792,
      "fat": 78.69,
      "saturatedFat": 5.025,
      "monounsaturatedFat": 49.792,
      "polyunsaturatedFat": 22.145,
      "carbs": 20.69,
      "sugar": 0,
      "fiber": 0,
      "protein": 0.26,
      "sodium": 59,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 0,
      "calcium": 0,
      "phosphorus": 0,
      "potassium": 0,
      "iron": 0,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0
    },
    {
      "id": 2002,
      "name": "Butter",
      "categoryId": 2000,
      "energy": 717,
      "fat": 81.11,
      "saturatedFat": 51.368,
      "monounsaturatedFat": 21.021,
      "polyunsaturatedFat": 3.043,
      "carbs": 0.06,
      "sugar": 0.06,
      "fiber": 0,
      "protein": 0.85,
      "sodium": 643,
      "cholesterol": 215,
      "vitaminA": 684,
      "vitaminB1": 0.005,
      "vitaminB2": 0.034,
      "vitaminB3": 0.042,
      "vitaminB5": 0.11,
      "vitaminB6": 0.003,
      "vitaminB9": 3,
      "vitaminB12": 0.17,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 2.32,
      "vitaminK": 7,
      "magnesium": 2,
      "calcium": 24,
      "phosphorus": 24,
      "potassium": 24,
      "iron": 0.02,
      "selenium": 1,
      "zinc": 0.09,
      "manganese": 0,
      "copper": 0,
      "choline": 18.8,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 227
      }
    },
    {
      "id": 2003,
      "name": "Olive Oil",
      "categoryId": 2000,
      "energy": 884,
      "fat": 100,
      "saturatedFat": 13.808,
      "monounsaturatedFat": 72.961,
      "polyunsaturatedFat": 10.523,
      "carbs": 0,
      "sugar": 0,
      "fiber": 0,
      "protein": 0,
      "sodium": 2,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 14.35,
      "vitaminK": 60.2,
      "magnesium": 0,
      "calcium": 1,
      "phosphorus": 0,
      "potassium": 1,
      "iron": 0.56,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0.3,
      "volume": {
        "portionId": "tablespoons",
        "weightInGrams": 13.5
      }
    },
    {
      "id": 2004,
      "name": "Coconut oil",
      "categoryId": 2000,
      "energy": 892,
      "fat": 99.06,
      "saturatedFat": 82.475,
      "monounsaturatedFat": 6.332,
      "polyunsaturatedFat": 1.702,
      "carbs": 0,
      "sugar": 0,
      "fiber": 0,
      "protein": 0,
      "sodium": 0,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0.11,
      "vitaminK": 0.6,
      "magnesium": 0,
      "calcium": 1,
      "phosphorus": 0,
      "potassium": 0,
      "iron": 0.05,
      "selenium": 0,
      "zinc": 0.02,
      "manganese": 0,
      "copper": 0,
      "choline": 0.3,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 218
      }
    },
    {
      "id": 2005,
      "name": "Avocado Oil",
      "categoryId": 2000,
      "energy": 884,
      "fat": 100,
      "saturatedFat": 11.56,
      "monounsaturatedFat": 70.554,
      "polyunsaturatedFat": 13.486,
      "carbs": 0,
      "sugar": 0,
      "fiber": 0,
      "protein": 0,
      "sodium": 0,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 0,
      "calcium": 0,
      "phosphorus": 0,
      "potassium": 0,
      "iron": 0,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0,
      "volume": {
        "portionId": "teaspoons",
        "weightInGrams": 4.5
      }
    },
    {
      "id": 2006,
      "name": "Flaxseed Oil",
      "categoryId": 2000,
      "energy": 884,
      "fat": 99.98,
      "saturatedFat": 8.976,
      "monounsaturatedFat": 18.438,
      "polyunsaturatedFat": 67.849,
      "carbs": 0,
      "sugar": 0,
      "fiber": 0,
      "protein": 0.11,
      "sodium": 0,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0.47,
      "vitaminK": 9.3,
      "magnesium": 0,
      "calcium": 1,
      "phosphorus": 1,
      "potassium": 0,
      "iron": 0,
      "selenium": 0,
      "zinc": 0.07,
      "manganese": 0,
      "copper": 0,
      "choline": 0.2,
      "volume": {
        "portionId": "tablespoons",
        "weightInGrams": 13.6
      }
    },
    {
      "id": 2007,
      "name": "Canola Oil",
      "categoryId": 2000,
      "energy": 884,
      "fat": 100,
      "saturatedFat": 7.365,
      "monounsaturatedFat": 63.276,
      "polyunsaturatedFat": 28.142,
      "carbs": 0,
      "sugar": 0,
      "fiber": 0,
      "protein": 0,
      "sodium": 0,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 17.46,
      "vitaminK": 71.3,
      "magnesium": 0,
      "calcium": 0,
      "phosphorus": 0,
      "potassium": 0,
      "iron": 0,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0.2,
      "volume": {
        "portionId": "teaspoons",
        "weightInGrams": 4.5
      }
    },
    {
      "id": 2008,
      "name": "Salmon Oil",
      "categoryId": 2000,
      "energy": 902,
      "fat": 100,
      "saturatedFat": 19.872,
      "monounsaturatedFat": 29.037,
      "polyunsaturatedFat": 40.324,
      "carbs": 0,
      "sugar": 0,
      "fiber": 0,
      "protein": 0,
      "sodium": 0,
      "cholesterol": 485,
      "vitaminA": 0,
      "vitaminB1": 0,
      "vitaminB2": 0,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 0,
      "calcium": 0,
      "phosphorus": 0,
      "potassium": 0,
      "iron": 0,
      "selenium": 0,
      "zinc": 0,
      "manganese": 0,
      "copper": 0,
      "choline": 0,
      "volume": {
        "portionId": "teaspoons",
        "weightInGrams": 4.5
      }
    },
    {
      "id": 2009,
      "name": "Italian Salad Dressing",
      "categoryId": 2000,
      "energy": 240,
      "fat": 21.12,
      "saturatedFat": 2.948,
      "monounsaturatedFat": 5.638,
      "polyunsaturatedFat": 10.748,
      "carbs": 12.12,
      "sugar": 10.77,
      "fiber": 0,
      "protein": 0.41,
      "sodium": 993,
      "cholesterol": 0,
      "vitaminA": 2,
      "vitaminB1": 0.02,
      "vitaminB2": 0,
      "vitaminB3": 0.131,
      "vitaminB5": 0,
      "vitaminB6": 0.064,
      "vitaminB9": 0,
      "vitaminB12": 0,
      "vitaminC": 0.4,
      "vitaminD": 0,
      "vitaminE": 2.19,
      "vitaminK": 56,
      "magnesium": 5,
      "calcium": 13,
      "phosphorus": 15,
      "potassium": 84,
      "iron": 0.26,
      "selenium": 2,
      "zinc": 0.07,
      "manganese": 0.031,
      "copper": 0.019,
      "choline": 2.6,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 235
      }
    },
    {
      "id": 2010,
      "name": "Fat Free Italian Salad Dressing",
      "categoryId": 2000,
      "energy": 47,
      "fat": 0.87,
      "saturatedFat": 0.295,
      "monounsaturatedFat": 0.235,
      "polyunsaturatedFat": 0.192,
      "carbs": 8.75,
      "sugar": 8.85,
      "fiber": 0.6,
      "protein": 0.97,
      "sodium": 1129,
      "cholesterol": 2,
      "vitaminA": 4,
      "vitaminB1": 0.031,
      "vitaminB2": 0.053,
      "vitaminB3": 0.135,
      "vitaminB5": 0,
      "vitaminB6": 0,
      "vitaminB9": 12,
      "vitaminB12": 0.31,
      "vitaminC": 0.4,
      "vitaminD": 0,
      "vitaminE": 0.76,
      "vitaminK": 1.6,
      "magnesium": 5,
      "calcium": 30,
      "phosphorus": 109,
      "potassium": 102,
      "iron": 0.4,
      "selenium": 2,
      "zinc": 0.36,
      "manganese": 0.032,
      "copper": 0.116,
      "choline": 4,
      "volume": {
        "portionId": "tablespoons",
        "weightInGrams": 14
      }
    },
    {
      "id": 2011,
      "name": "Light Italian Salad Dressing",
      "categoryId": 2000,
      "energy": 102,
      "fat": 6.68,
      "saturatedFat": 0.833,
      "monounsaturatedFat": 1.725,
      "polyunsaturatedFat": 3.236,
      "carbs": 9.99,
      "sugar": 9.16,
      "fiber": 0,
      "protein": 0.39,
      "sodium": 891,
      "cholesterol": 0,
      "vitaminA": 1,
      "vitaminB1": 0.012,
      "vitaminB2": 0.008,
      "vitaminB3": 0.094,
      "vitaminB5": 0,
      "vitaminB6": 0.055,
      "vitaminB9": 3,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 4.28,
      "vitaminK": 12.5,
      "magnesium": 4,
      "calcium": 15,
      "phosphorus": 12,
      "potassium": 90,
      "iron": 0.25,
      "selenium": 1.6,
      "zinc": 0.06,
      "manganese": 0,
      "copper": 0.019,
      "choline": 3.3
    },
    {
      "id": 2012,
      "name": "Light Mayonnaise",
      "categoryId": 2000,
      "energy": 238,
      "fat": 22.22,
      "saturatedFat": 3.446,
      "monounsaturatedFat": 5.01,
      "polyunsaturatedFat": 12.993,
      "carbs": 9.23,
      "sugar": 3.56,
      "fiber": 0,
      "protein": 0.37,
      "sodium": 827,
      "cholesterol": 16,
      "vitaminA": 8,
      "vitaminB1": 0.008,
      "vitaminB2": 0,
      "vitaminB3": 0.01,
      "vitaminB5": 0.058,
      "vitaminB6": 0.002,
      "vitaminB9": 4,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 2.19,
      "vitaminK": 53.7,
      "magnesium": 2,
      "calcium": 6,
      "phosphorus": 15,
      "potassium": 31,
      "iron": 0.14,
      "selenium": 2.6,
      "zinc": 0.07,
      "manganese": 0.007,
      "copper": 0.019,
      "choline": 9,
      "volume": {
        "portionId": "tablespoons",
        "weightInGrams": 15
      }
    },
    {
      "id": 2013,
      "name": "Mayonnaise",
      "categoryId": 2000,
      "energy": 680,
      "fat": 74.85,
      "saturatedFat": 11.703,
      "monounsaturatedFat": 16.843,
      "polyunsaturatedFat": 44.69,
      "carbs": 0.57,
      "sugar": 0.57,
      "fiber": 0,
      "protein": 0.96,
      "sodium": 635,
      "cholesterol": 42,
      "vitaminA": 16,
      "vitaminB1": 0.01,
      "vitaminB2": 0.019,
      "vitaminB3": 0,
      "vitaminB5": 0,
      "vitaminB6": 0.008,
      "vitaminB9": 5,
      "vitaminB12": 0.12,
      "vitaminC": 0,
      "vitaminD": 0.2,
      "vitaminE": 3.28,
      "vitaminK": 163,
      "magnesium": 1,
      "calcium": 8,
      "phosphorus": 21,
      "potassium": 20,
      "iron": 0.21,
      "selenium": 2.3,
      "zinc": 0.15,
      "manganese": 0,
      "copper": 0.019,
      "choline": 34.2
    }
  ]

================================================
FILE: src/foods/builtIn/finfishAndShellFish.json
================================================
[
  {
    "id": 401,
    "name": "Wild Atlantic Salmon",
    "categoryId": 400,
    "energy": 142,
    "fat": 6.34,
    "saturatedFat": 0.981,
    "monounsaturatedFat": 2.103,
    "polyunsaturatedFat": 2.539,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 19.84,
    "sodium": 44,
    "cholesterol": 55,
    "vitaminA": 12,
    "vitaminB1": 0.226,
    "vitaminB2": 0.38,
    "vitaminB3": 7.86,
    "vitaminB5": 1.664,
    "vitaminB6": 0.818,
    "vitaminB9": 25,
    "vitaminB12": 3.18,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0,
    "vitaminK": 0,
    "magnesium": 29,
    "calcium": 12,
    "phosphorus": 200,
    "potassium": 490,
    "iron": 0.8,
    "selenium": 36.5,
    "zinc": 0.64,
    "manganese": 0.016,
    "copper": 0.25,
    "choline": 0
  },
  {
    "id": 402,
    "name": "Canned Tuna (in water)",
    "categoryId": 400,
    "energy": 128,
    "fat": 2.97,
    "saturatedFat": 0.792,
    "monounsaturatedFat": 0.784,
    "polyunsaturatedFat": 1.109,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 23.62,
    "sodium": 377,
    "cholesterol": 42,
    "vitaminA": 6,
    "vitaminB1": 0.008,
    "vitaminB2": 0.044,
    "vitaminB3": 5.799,
    "vitaminB5": 0.124,
    "vitaminB6": 0.217,
    "vitaminB9": 2,
    "vitaminB12": 1.17,
    "vitaminC": 0,
    "vitaminD": 2,
    "vitaminE": 0.85,
    "vitaminK": 2.5,
    "magnesium": 33,
    "calcium": 14,
    "phosphorus": 217,
    "potassium": 237,
    "iron": 0.97,
    "selenium": 65.7,
    "zinc": 0.48,
    "manganese": 0.019,
    "copper": 0.039,
    "choline": 29.3
  },
  {
    "id": 403,
    "name": "Shrimp",
    "categoryId": 400,
    "energy": 85,
    "fat": 0.51,
    "saturatedFat": 0.101,
    "monounsaturatedFat": 0.086,
    "polyunsaturatedFat": 0.152,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 20.1,
    "sodium": 119,
    "cholesterol": 161,
    "vitaminA": 0,
    "vitaminB1": 0,
    "vitaminB2": 0,
    "vitaminB3": 0,
    "vitaminB5": 0,
    "vitaminB6": 0,
    "vitaminB9": 0,
    "vitaminB12": 0,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0,
    "vitaminK": 0,
    "magnesium": 35,
    "calcium": 64,
    "phosphorus": 214,
    "potassium": 264,
    "iron": 0.52,
    "selenium": 0,
    "zinc": 1.34,
    "manganese": 0.033,
    "copper": 0.391,
    "choline": 0
  },
  {
    "id": 404,
    "name": "Canned Salmon",
    "categoryId": 400,
    "energy": 137,
    "fat": 5.48,
    "saturatedFat": 1.009,
    "monounsaturatedFat": 1.499,
    "polyunsaturatedFat": 1.497,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 20.55,
    "sodium": 403,
    "cholesterol": 59,
    "vitaminA": 25,
    "vitaminB1": 0.025,
    "vitaminB2": 0.19,
    "vitaminB3": 6.776,
    "vitaminB5": 0,
    "vitaminB6": 0.268,
    "vitaminB9": 13,
    "vitaminB12": 4.62,
    "vitaminC": 0,
    "vitaminD": 15,
    "vitaminE": 0.97,
    "vitaminK": 0.4,
    "magnesium": 30,
    "calcium": 220,
    "phosphorus": 338,
    "potassium": 336,
    "iron": 0.64,
    "selenium": 33.9,
    "zinc": 0.79,
    "manganese": 0,
    "copper": 0.071,
    "choline": 86.6
  },
  {
    "id": 405,
    "name": "Atlantic Cod",
    "categoryId": 400,
    "energy": 82,
    "fat": 0.67,
    "saturatedFat": 0.131,
    "monounsaturatedFat": 0.094,
    "polyunsaturatedFat": 0.231,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 17.81,
    "sodium": 54,
    "cholesterol": 43,
    "vitaminA": 12,
    "vitaminB1": 0.076,
    "vitaminB2": 0.065,
    "vitaminB3": 2.063,
    "vitaminB5": 0.153,
    "vitaminB6": 0.245,
    "vitaminB9": 7,
    "vitaminB12": 0.91,
    "vitaminC": 1,
    "vitaminD": 0.9,
    "vitaminE": 0.64,
    "vitaminK": 0.1,
    "magnesium": 32,
    "calcium": 16,
    "phosphorus": 203,
    "potassium": 413,
    "iron": 0.38,
    "selenium": 33.1,
    "zinc": 0.45,
    "manganese": 0.015,
    "copper": 0.028,
    "choline": 65.2
  },
  {
    "id": 406,
    "name": "Tilapia",
    "categoryId": 400,
    "energy": 96,
    "fat": 1.7,
    "saturatedFat": 0.585,
    "monounsaturatedFat": 0.498,
    "polyunsaturatedFat": 0.363,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 20.08,
    "sodium": 52,
    "cholesterol": 50,
    "vitaminA": 0,
    "vitaminB1": 0.041,
    "vitaminB2": 0.063,
    "vitaminB3": 3.903,
    "vitaminB5": 0.487,
    "vitaminB6": 0.162,
    "vitaminB9": 24,
    "vitaminB12": 1.58,
    "vitaminC": 0,
    "vitaminD": 3.1,
    "vitaminE": 0.4,
    "vitaminK": 1.4,
    "magnesium": 27,
    "calcium": 10,
    "phosphorus": 170,
    "potassium": 302,
    "iron": 0.56,
    "selenium": 41.8,
    "zinc": 0.33,
    "manganese": 0.037,
    "copper": 0.075,
    "choline": 42.5
  },
  {
    "id": 407,
    "name": "Smoked Salmon",
    "categoryId": 400,
    "energy": 117,
    "fat": 4.32,
    "saturatedFat": 0.929,
    "monounsaturatedFat": 2.023,
    "polyunsaturatedFat": 0.995,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 18.28,
    "sodium": 672,
    "cholesterol": 23,
    "vitaminA": 26,
    "vitaminB1": 0.023,
    "vitaminB2": 0.101,
    "vitaminB3": 4.72,
    "vitaminB5": 0,
    "vitaminB6": 0.278,
    "vitaminB9": 2,
    "vitaminB12": 3.26,
    "vitaminC": 0,
    "vitaminD": 17.1,
    "vitaminE": 1.35,
    "vitaminK": 0.1,
    "magnesium": 18,
    "calcium": 11,
    "phosphorus": 164,
    "potassium": 175,
    "iron": 0.85,
    "selenium": 32.4,
    "zinc": 0.31,
    "manganese": 0,
    "copper": 0.23,
    "choline": 89
  },
  {
    "id": 408,
    "name": "Cod",
    "categoryId": 400,
    "energy": 82,
    "fat": 0.67,
    "saturatedFat": 0.131,
    "monounsaturatedFat": 0.094,
    "polyunsaturatedFat": 0.231,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 17.81,
    "sodium": 54,
    "cholesterol": 43,
    "vitaminA": 12,
    "vitaminB1": 0.076,
    "vitaminB2": 0.065,
    "vitaminB3": 2.063,
    "vitaminB5": 0.153,
    "vitaminB6": 0.245,
    "vitaminB9": 7,
    "vitaminB12": 0.91,
    "vitaminC": 1,
    "vitaminD": 0.9,
    "vitaminE": 0.64,
    "vitaminK": 0.1,
    "magnesium": 32,
    "calcium": 16,
    "phosphorus": 203,
    "potassium": 413,
    "iron": 0.38,
    "selenium": 33.1,
    "zinc": 0.45,
    "manganese": 0.015,
    "copper": 0.028,
    "choline": 65.2
  },
  {
    "id": 409,
    "name": "Halibut",
    "categoryId": 400,
    "energy": 91,
    "fat": 1.33,
    "saturatedFat": 0.292,
    "monounsaturatedFat": 0.471,
    "polyunsaturatedFat": 0.29,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 18.56,
    "sodium": 68,
    "cholesterol": 49,
    "vitaminA": 20,
    "vitaminB1": 0.05,
    "vitaminB2": 0.03,
    "vitaminB3": 6.513,
    "vitaminB5": 0.343,
    "vitaminB6": 0.548,
    "vitaminB9": 12,
    "vitaminB12": 1.1,
    "vitaminC": 0,
    "vitaminD": 4.7,
    "vitaminE": 0.61,
    "vitaminK": 0,
    "magnesium": 23,
    "calcium": 7,
    "phosphorus": 236,
    "potassium": 435,
    "iron": 0.16,
    "selenium": 45.6,
    "zinc": 0.36,
    "manganese": 0.011,
    "copper": 0.023,
    "choline": 61.8
  },
  {
    "id": 410,
    "name": "Haddock",
    "categoryId": 400,
    "energy": 74,
    "fat": 0.45,
    "saturatedFat": 0.091,
    "monounsaturatedFat": 0.061,
    "polyunsaturatedFat": 0.166,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 16.32,
    "sodium": 213,
    "cholesterol": 54,
    "vitaminA": 17,
    "vitaminB1": 0.02,
    "vitaminB2": 0.057,
    "vitaminB3": 3.363,
    "vitaminB5": 0.403,
    "vitaminB6": 0.281,
    "vitaminB9": 12,
    "vitaminB12": 1.83,
    "vitaminC": 0,
    "vitaminD": 0.5,
    "vitaminE": 0.45,
    "vitaminK": 0.1,
    "magnesium": 21,
    "calcium": 11,
    "phosphorus": 227,
    "potassium": 286,
    "iron": 0.17,
    "selenium": 25.9,
    "zinc": 0.32,
    "manganese": 0.011,
    "copper": 0.021,
    "choline": 65
  },
  {
    "id": 411,
    "name": "Trout",
    "categoryId": 400,
    "energy": 148,
    "fat": 6.61,
    "saturatedFat": 1.149,
    "monounsaturatedFat": 3.254,
    "polyunsaturatedFat": 1.499,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 20.77,
    "sodium": 52,
    "cholesterol": 58,
    "vitaminA": 17,
    "vitaminB1": 0.35,
    "vitaminB2": 0.33,
    "vitaminB3": 4.5,
    "vitaminB5": 1.94,
    "vitaminB6": 0.2,
    "vitaminB9": 13,
    "vitaminB12": 7.79,
    "vitaminC": 0.5,
    "vitaminD": 3.9,
    "vitaminE": 0.2,
    "vitaminK": 0.1,
    "magnesium": 22,
    "calcium": 43,
    "phosphorus": 245,
    "potassium": 361,
    "iron": 1.5,
    "selenium": 12.6,
    "zinc": 0.66,
    "manganese": 0.851,
    "copper": 0.188,
    "choline": 65
  },
  {
    "id": 412,
    "name": "Lobster",
    "categoryId": 400,
    "energy": 77,
    "fat": 0.75,
    "saturatedFat": 0.181,
    "monounsaturatedFat": 0.22,
    "polyunsaturatedFat": 0.296,
    "carbs": 0,
    "sugar": 0,
    "fiber": 0,
    "protein": 16.52,
    "sodium": 423,
    "cholesterol": 127,
    "vitaminA": 1,
    "vitaminB1": 0.02,
    "vitaminB2": 0.014,
    "vitaminB3": 1.591,
    "vitaminB5": 1.449,
    "vitaminB6": 0.104,
    "vitaminB9": 10,
    "vitaminB12": 1.25,
    "vitaminC": 0,
    "vitaminD": 0,
    "vitaminE": 0.87,
    "vitaminK": 0,
    "magnesium": 38,
    "calcium": 84,
    "phosphorus": 161,
    "potassium": 200,
    "iron": 0.26,
    "selenium": 63.6,
    "zinc": 3.53,
    "manganese": 0.056,
    "copper": 1.349,
    "choline": 70.3
  },
  {
    "id": 413,
    "name": "Pacific Oyster",
    "categoryId": 400,
    "energy": 81,
    "fat": 2.3,
    "saturatedFat": 0.51,
    "monounsaturatedFat": 0.358,
    "polyunsaturatedFat": 0.894,
    "carbs": 4.95,
    "sugar": 0,
    "fiber": 0,
    "protein": 9.45,
    "sodium": 106,
    "cholesterol": 50,
    "vitaminA": 81,
    "vitaminB1": 0.067,
    "vitaminB2": 0.233,
    "vitaminB3": 2.01,
    "vitaminB5": 0.5,
    "vitaminB6": 0.05,
    "vitaminB9": 10,
    "vitaminB12": 16,
    "vitaminC": 8,
    "vitaminD": 0,
    "vitaminE": 0,
    "vitaminK": 0,
    "magnesium": 22,
    "calcium": 8,
    "phosphorus": 162,
    "potassium": 168,
    "iron": 5.11,
    "selenium": 77,
    "zinc": 16.62,
    "manganese": 0.643,
    "copper": 1.576,
    "choline": 0
  },
  {
    "id": 414,
    "name": "Squid",
    "categoryId": 400,
    "energy": 92,
    "fat": 1.38,
    "saturatedFat": 0.358,
    "monounsaturatedFat": 0.107,
    "polyunsaturatedFat": 0.524,
    "carbs": 3.08,
    "sugar": 0,
    "fiber": 0,
    "protein": 15.58,
    "sodium": 44,
    "cholesterol": 233,
    "vitaminA": 10,
    "vitaminB1": 0.02,
    "vitaminB2": 0.412,
    "vitaminB3": 2.175,
    "vitaminB5": 0.5,
    "vitaminB6": 0.056,
    "vitaminB9": 5,
    "vitaminB12": 1.3,
    "vitaminC": 4.7,
    "vitaminD": 0,
    "vitaminE": 1.2,
    "vitaminK": 0,
    "magnesium": 33,
    "calcium": 32,
    "phosphorus": 221,
    "potassium": 246,
    "iron": 0.68,
    "selenium": 44.8,
    "zinc": 1.53,
    "manganese": 0.035,
    "copper": 1.891,
    "choline": 65
  }
]

================================================
FILE: src/foods/builtIn/fruitsAndJuices.json
================================================
[
    {
      "id": 901,
      "name": "Tomatoes",
      "categoryId": 900,
      "energy": 18,
      "fat": 0.2,
      "saturatedFat": 0.028,
      "monounsaturatedFat": 0.031,
      "polyunsaturatedFat": 0.083,
      "carbs": 3.89,
      "sugar": 2.63,
      "fiber": 1.2,
      "protein": 0.88,
      "sodium": 5,
      "cholesterol": 0,
      "vitaminA": 42,
      "vitaminB1": 0.037,
      "vitaminB2": 0.019,
      "vitaminB3": 0.594,
      "vitaminB5": 0,
      "vitaminB6": 0.08,
      "vitaminB9": 15,
      "vitaminB12": 0,
      "vitaminC": 13.7,
      "vitaminD": 0,
      "vitaminE": 0.54,
      "vitaminK": 7.9,
      "magnesium": 11,
      "calcium": 10,
      "phosphorus": 24,
      "potassium": 237,
      "iron": 0.27,
      "selenium": 0,
      "zinc": 0.17,
      "manganese": 0,
      "copper": 0.059,
      "choline": 6.7
    },
    { 
      "id": 902,
      "name": "Lemon Juice",
      "categoryId": 900,
      "energy": 22,
      "fat": 0.24,
      "saturatedFat": 0.04,
      "monounsaturatedFat": 0.006,
      "polyunsaturatedFat": 0.021,
      "carbs": 6.9,
      "sugar": 2.52,
      "fiber": 0.3,
      "protein": 0.35,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.024,
      "vitaminB2": 0.015,
      "vitaminB3": 0.091,
      "vitaminB5": 0.131,
      "vitaminB6": 0.046,
      "vitaminB9": 20,
      "vitaminB12": 0,
      "vitaminC": 38.7,
      "vitaminD": 0,
      "vitaminE": 0.15,
      "vitaminK": 0,
      "magnesium": 6,
      "calcium": 6,
      "phosphorus": 8,
      "potassium": 103,
      "iron": 0.08,
      "selenium": 0.1,
      "zinc": 0.05,
      "manganese": 0.012,
      "copper": 0.016,
      "choline": 5.1,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 244
      }
    },
    {
      "id": 903,
      "name": "Raisins",
      "categoryId": 900,
      "energy": 299,
      "fat": 0.25,
      "saturatedFat": 0.094,
      "monounsaturatedFat": 0.024,
      "polyunsaturatedFat": 0.053,
      "carbs": 79.32,
      "sugar": 65.18,
      "fiber": 4.5,
      "protein": 3.3,
      "sodium": 26,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.106,
      "vitaminB2": 0.125,
      "vitaminB3": 0.766,
      "vitaminB5": 0,
      "vitaminB6": 0.174,
      "vitaminB9": 5,
      "vitaminB12": 0,
      "vitaminC": 2.3,
      "vitaminD": 0,
      "vitaminE": 0.12,
      "vitaminK": 3.5,
      "magnesium": 36,
      "calcium": 62,
      "phosphorus": 98,
      "potassium": 744,
      "iron": 1.79,
      "selenium": 0.6,
      "zinc": 0.36,
      "manganese": 0,
      "copper": 0.272,
      "choline": 11.1
    },
    {
      "id": 904,
      "name": "Orange Juice",
      "categoryId": 900,
      "energy": 47,
      "fat": 0.15,
      "saturatedFat": 0.018,
      "monounsaturatedFat": 0.025,
      "polyunsaturatedFat": 0.034,
      "carbs": 11.01,
      "sugar": 8.76,
      "fiber": 0.3,
      "protein": 0.68,
      "sodium": 4,
      "cholesterol": 0,
      "vitaminA": 9,
      "vitaminB1": 0.039,
      "vitaminB2": 0.021,
      "vitaminB3": 0.201,
      "vitaminB5": 0.18,
      "vitaminB6": 0.031,
      "vitaminB9": 24,
      "vitaminB12": 0,
      "vitaminC": 30.1,
      "vitaminD": 0,
      "vitaminE": 0.2,
      "vitaminK": 0.1,
      "magnesium": 10,
      "calcium": 10,
      "phosphorus": 17,
      "potassium": 184,
      "iron": 0.1,
      "selenium": 0.1,
      "zinc": 0.04,
      "manganese": 0.021,
      "copper": 0.022,
      "choline": 6.2,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 249
      }
    },
    {
      "id": 905,
      "name": "Raspberries",
      "categoryId": 900,
      "energy": 52,
      "fat": 0.65,
      "saturatedFat": 0.019,
      "monounsaturatedFat": 0.064,
      "polyunsaturatedFat": 0.375,
      "carbs": 11.94,
      "sugar": 4.42,
      "fiber": 6.5,
      "protein": 1.2,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 2,
      "vitaminB1": 0.032,
      "vitaminB2": 0.038,
      "vitaminB3": 0.598,
      "vitaminB5": 0.329,
      "vitaminB6": 0.055,
      "vitaminB9": 21,
      "vitaminB12": 0,
      "vitaminC": 26.2,
      "vitaminD": 0,
      "vitaminE": 0.87,
      "vitaminK": 7.8,
      "magnesium": 22,
      "calcium": 25,
      "phosphorus": 29,
      "potassium": 151,
      "iron": 0.69,
      "selenium": 0.2,
      "zinc": 0.42,
      "manganese": 0.67,
      "copper": 0.09,
      "choline": 12.3,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 123
      }
    },
    {
      "id": 906,
      "name": "Strawberries",
      "categoryId": 900,
      "energy": 32,
      "fat": 0.3,
      "saturatedFat": 0.015,
      "monounsaturatedFat": 0.043,
      "polyunsaturatedFat": 0.155,
      "carbs": 7.68,
      "sugar": 4.89,
      "fiber": 2,
      "protein": 0.67,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 1,
      "vitaminB1": 0.024,
      "vitaminB2": 0.022,
      "vitaminB3": 0.386,
      "vitaminB5": 0.125,
      "vitaminB6": 0.047,
      "vitaminB9": 24,
      "vitaminB12": 0,
      "vitaminC": 58.8,
      "vitaminD": 0,
      "vitaminE": 0.29,
      "vitaminK": 2.2,
      "magnesium": 13,
      "calcium": 16,
      "phosphorus": 24,
      "potassium": 153,
      "iron": 0.41,
      "selenium": 0.4,
      "zinc": 0.14,
      "manganese": 0.386,
      "copper": 0.048,
      "choline": 5.7,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 232
      }
    },
    {
      "id": 907,
      "name": "Blackberries",
      "categoryId": 900,
      "energy": 43,
      "fat": 0.49,
      "saturatedFat": 0.014,
      "monounsaturatedFat": 0.047,
      "polyunsaturatedFat": 0.28,
      "carbs": 9.61,
      "sugar": 4.88,
      "fiber": 5.3,
      "protein": 1.39,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 11,
      "vitaminB1": 0.02,
      "vitaminB2": 0.026,
      "vitaminB3": 0.646,
      "vitaminB5": 0.276,
      "vitaminB6": 0.03,
      "vitaminB9": 25,
      "vitaminB12": 0,
      "vitaminC": 21,
      "vitaminD": 0,
      "vitaminE": 1.17,
      "vitaminK": 19.8,
      "magnesium": 20,
      "calcium": 29,
      "phosphorus": 22,
      "potassium": 162,
      "iron": 0.62,
      "selenium": 0.4,
      "zinc": 0.53,
      "manganese": 0.646,
      "copper": 0.165,
      "choline": 8.5,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 144
      }
    },
    {
      "id": 908,
      "name": "Bananas",
      "categoryId": 900,
      "energy": 89,
      "fat": 0.33,
      "saturatedFat": 0.112,
      "monounsaturatedFat": 0.032,
      "polyunsaturatedFat": 0.073,
      "carbs": 22.84,
      "sugar": 12.23,
      "fiber": 2.6,
      "protein": 1.09,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 3,
      "vitaminB1": 0.031,
      "vitaminB2": 0.073,
      "vitaminB3": 0.665,
      "vitaminB5": 0.334,
      "vitaminB6": 0.367,
      "vitaminB9": 20,
      "vitaminB12": 0,
      "vitaminC": 8.7,
      "vitaminD": 0,
      "vitaminE": 0.1,
      "vitaminK": 0.5,
      "magnesium": 27,
      "calcium": 5,
      "phosphorus": 22,
      "potassium": 358,
      "iron": 0.26,
      "selenium": 1,
      "zinc": 0.15,
      "manganese": 0.27,
      "copper": 0.078,
      "choline": 9.8,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 150
      }
    },
    {
      "id": 909,
      "name": "Blueberries",
      "categoryId": 900,
      "energy": 57,
      "fat": 0.33,
      "saturatedFat": 0.028,
      "monounsaturatedFat": 0.047,
      "polyunsaturatedFat": 0.146,
      "carbs": 14.49,
      "sugar": 9.96,
      "fiber": 2.4,
      "protein": 0.74,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 3,
      "vitaminB1": 0.037,
      "vitaminB2": 0.041,
      "vitaminB3": 0.418,
      "vitaminB5": 0.124,
      "vitaminB6": 0.052,
      "vitaminB9": 6,
      "vitaminB12": 0,
      "vitaminC": 9.7,
      "vitaminD": 0,
      "vitaminE": 0.57,
      "vitaminK": 19.3,
      "magnesium": 6,
      "calcium": 6,
      "phosphorus": 12,
      "potassium": 77,
      "iron": 0.28,
      "selenium": 0.1,
      "zinc": 0.16,
      "manganese": 0.336,
      "copper": 0.057,
      "choline": 6,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 148
      }
    },
    {
      "id": 910,
      "name": "Cherries",
      "categoryId": 900,
      "energy": 63,
      "fat": 0.2,
      "saturatedFat": 0.038,
      "monounsaturatedFat": 0.047,
      "polyunsaturatedFat": 0.052,
      "carbs": 16.01,
      "sugar": 12.82,
      "fiber": 2.1,
      "protein": 1.06,
      "sodium": 0,
      "cholesterol": 0,
      "vitaminA": 3,
      "vitaminB1": 0.027,
      "vitaminB2": 0.033,
      "vitaminB3": 0.154,
      "vitaminB5": 0.199,
      "vitaminB6": 0.049,
      "vitaminB9": 4,
      "vitaminB12": 0,
      "vitaminC": 7,
      "vitaminD": 0,
      "vitaminE": 0.07,
      "vitaminK": 2.1,
      "magnesium": 11,
      "calcium": 13,
      "phosphorus": 21,
      "potassium": 222,
      "iron": 0.36,
      "selenium": 0,
      "zinc": 0.07,
      "manganese": 0.07,
      "copper": 0.06,
      "choline": 6.1,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 154
      }
    },
    {
      "id": 911,
      "name": "Peaches",
      "categoryId": 900,
      "energy": 39,
      "fat": 0.25,
      "saturatedFat": 0.019,
      "monounsaturatedFat": 0.067,
      "polyunsaturatedFat": 0.086,
      "carbs": 9.54,
      "sugar": 8.39,
      "fiber": 1.5,
      "protein": 0.91,
      "sodium": 0,
      "cholesterol": 0,
      "vitaminA": 16,
      "vitaminB1": 0.024,
      "vitaminB2": 0.031,
      "vitaminB3": 0.806,
      "vitaminB5": 0.153,
      "vitaminB6": 0.025,
      "vitaminB9": 4,
      "vitaminB12": 0,
      "vitaminC": 6.6,
      "vitaminD": 0,
      "vitaminE": 0.73,
      "vitaminK": 2.6,
      "magnesium": 9,
      "calcium": 6,
      "phosphorus": 20,
      "potassium": 190,
      "iron": 0.25,
      "selenium": 0.1,
      "zinc": 0.17,
      "manganese": 0.061,
      "copper": 0.068,
      "choline": 6.1,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 154
      }
    },
    {
      "id": 912,
      "name": "Crushed Tomatoes (canned)",
      "categoryId": 900,
      "energy": 32,
      "fat": 0.28,
      "saturatedFat": 0.04,
      "monounsaturatedFat": 0.043,
      "polyunsaturatedFat": 0.113,
      "carbs": 7.29,
      "sugar": 4.4,
      "fiber": 1.9,
      "protein": 1.64,
      "sodium": 186,
      "cholesterol": 0,
      "vitaminA": 11,
      "vitaminB1": 0.075,
      "vitaminB2": 0.052,
      "vitaminB3": 1.222,
      "vitaminB5": 0.278,
      "vitaminB6": 0.15,
      "vitaminB9": 13,
      "vitaminB12": 0,
      "vitaminC": 9.2,
      "vitaminD": 0,
      "vitaminE": 1.25,
      "vitaminK": 5.3,
      "magnesium": 20,
      "calcium": 34,
      "phosphorus": 32,
      "potassium": 293,
      "iron": 1.3,
      "selenium": 0.6,
      "zinc": 0.27,
      "manganese": 0.183,
      "copper": 0.183,
      "choline": 12.9,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 121
      }
    },
    {
      "id": 913,
      "name": "Pears",
      "categoryId": 900,
      "energy": 57,
      "fat": 0.14,
      "saturatedFat": 0.022,
      "monounsaturatedFat": 0.084,
      "polyunsaturatedFat": 0.094,
      "carbs": 15.23,
      "sugar": 9.75,
      "fiber": 3.1,
      "protein": 0.36,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 1,
      "vitaminB1": 0.012,
      "vitaminB2": 0.026,
      "vitaminB3": 0.161,
      "vitaminB5": 0.049,
      "vitaminB6": 0.029,
      "vitaminB9": 7,
      "vitaminB12": 0,
      "vitaminC": 4.3,
      "vitaminD": 0,
      "vitaminE": 0.12,
      "vitaminK": 4.4,
      "magnesium": 7,
      "calcium": 9,
      "phosphorus": 12,
      "potassium": 116,
      "iron": 0.18,
      "selenium": 0.1,
      "zinc": 0.1,
      "manganese": 0.048,
      "copper": 0.082,
      "choline": 5.1,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 161
      }
    },
    {
      "id": 914,
      "name": "Apples",
      "categoryId": 900,
      "energy": 52,
      "fat": 0.17,
      "saturatedFat": 0.028,
      "monounsaturatedFat": 0.007,
      "polyunsaturatedFat": 0.051,
      "carbs": 13.81,
      "sugar": 10.39,
      "fiber": 2.4,
      "protein": 0.26,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 3,
      "vitaminB1": 0.017,
      "vitaminB2": 0.026,
      "vitaminB3": 0.091,
      "vitaminB5": 0,
      "vitaminB6": 0.041,
      "vitaminB9": 3,
      "vitaminB12": 0,
      "vitaminC": 4.6,
      "vitaminD": 0,
      "vitaminE": 0.18,
      "vitaminK": 2.2,
      "magnesium": 5,
      "calcium": 6,
      "phosphorus": 11,
      "potassium": 107,
      "iron": 0.12,
      "selenium": 0,
      "zinc": 0.04,
      "manganese": 0,
      "copper": 0.027,
      "choline": 3.4
    },
    {
      "id": 915,
      "name": "Grapes",
      "categoryId": 900,
      "energy": 69,
      "fat": 0.16,
      "saturatedFat": 0.054,
      "monounsaturatedFat": 0.007,
      "polyunsaturatedFat": 0.048,
      "carbs": 18.1,
      "sugar": 15.48,
      "fiber": 0.9,
      "protein": 0.72,
      "sodium": 2,
      "cholesterol": 0,
      "vitaminA": 3,
      "vitaminB1": 0.069,
      "vitaminB2": 0.07,
      "vitaminB3": 0.188,
      "vitaminB5": 0,
      "vitaminB6": 0.086,
      "vitaminB9": 2,
      "vitaminB12": 0,
      "vitaminC": 3.2,
      "vitaminD": 0,
      "vitaminE": 0.19,
      "vitaminK": 14.6,
      "magnesium": 7,
      "calcium": 10,
      "phosphorus": 20,
      "potassium": 191,
      "iron": 0.36,
      "selenium": 0.1,
      "zinc": 0.07,
      "manganese": 0,
      "copper": 0.127,
      "choline": 5.6
    },
    {
      "id": 916,
      "name": "Avocado",
      "categoryId": 900,
      "energy": 160,
      "fat": 14.66,
      "saturatedFat": 2.126,
      "monounsaturatedFat": 9.799,
      "polyunsaturatedFat": 1.816,
      "carbs": 8.53,
      "sugar": 0.66,
      "fiber": 6.7,
      "protein": 2,
      "sodium": 7,
      "cholesterol": 0,
      "vitaminA": 7,
      "vitaminB1": 0.067,
      "vitaminB2": 0.13,
      "vitaminB3": 1.738,
      "vitaminB5": 1.389,
      "vitaminB6": 0.257,
      "vitaminB9": 81,
      "vitaminB12": 0,
      "vitaminC": 10,
      "vitaminD": 0,
      "vitaminE": 2.07,
      "vitaminK": 21,
      "magnesium": 29,
      "calcium": 12,
      "phosphorus": 52,
      "potassium": 485,
      "iron": 0.55,
      "selenium": 0.4,
      "zinc": 0.64,
      "manganese": 0.142,
      "copper": 0.19,
      "choline": 14.2,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 230
      }
    },
    {
      "id": 917,
      "name": "Plums",
      "categoryId": 900,
      "energy": 46,
      "fat": 0.28,
      "saturatedFat": 0.017,
      "monounsaturatedFat": 0.134,
      "polyunsaturatedFat": 0.044,
      "carbs": 11.42,
      "sugar": 9.92,
      "fiber": 1.4,
      "protein": 0.7,
      "sodium": 0,
      "cholesterol": 0,
      "vitaminA": 17,
      "vitaminB1": 0.028,
      "vitaminB2": 0.026,
      "vitaminB3": 0.417,
      "vitaminB5": 0.135,
      "vitaminB6": 0.029,
      "vitaminB9": 5,
      "vitaminB12": 0,
      "vitaminC": 9.5,
      "vitaminD": 0,
      "vitaminE": 0.26,
      "vitaminK": 6.4,
      "magnesium": 7,
      "calcium": 6,
      "phosphorus": 16,
      "potassium": 157,
      "iron": 0.17,
      "selenium": 0,
      "zinc": 0.1,
      "manganese": 0.052,
      "copper": 0.057,
      "choline": 1.9,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 165
      }
    },
    {
      "id": 918,
      "name": "Mangos",
      "categoryId": 900,
      "energy": 60,
      "fat": 0.38,
      "saturatedFat": 0.092,
      "monounsaturatedFat": 0.14,
      "polyunsaturatedFat": 0.071,
      "carbs": 14.98,
      "sugar": 13.66,
      "fiber": 1.6,
      "protein": 0.82,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 54,
      "vitaminB1": 0.028,
      "vitaminB2": 0.038,
      "vitaminB3": 0.669,
      "vitaminB5": 0.197,
      "vitaminB6": 0.119,
      "vitaminB9": 43,
      "vitaminB12": 0,
      "vitaminC": 36.4,
      "vitaminD": 0,
      "vitaminE": 0.9,
      "vitaminK": 4.2,
      "magnesium": 10,
      "calcium": 11,
      "phosphorus": 14,
      "potassium": 168,
      "iron": 0.16,
      "selenium": 0.6,
      "zinc": 0.09,
      "manganese": 0.063,
      "copper": 0.111,
      "choline": 7.6,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 165
      }
    },
    {
      "id": 919,
      "name": "Pineapple",
      "categoryId": 900,
      "energy": 50,
      "fat": 0.12,
      "saturatedFat": 0.009,
      "monounsaturatedFat": 0.013,
      "polyunsaturatedFat": 0.04,
      "carbs": 13.12,
      "sugar": 9.85,
      "fiber": 1.4,
      "protein": 0.54,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 3,
      "vitaminB1": 0.079,
      "vitaminB2": 0.032,
      "vitaminB3": 0.5,
      "vitaminB5": 0.213,
      "vitaminB6": 0.112,
      "vitaminB9": 18,
      "vitaminB12": 0,
      "vitaminC": 47.8,
      "vitaminD": 0,
      "vitaminE": 0.02,
      "vitaminK": 0.7,
      "magnesium": 12,
      "calcium": 13,
      "phosphorus": 8,
      "potassium": 109,
      "iron": 0.29,
      "selenium": 0.1,
      "zinc": 0.12,
      "manganese": 0.927,
      "copper": 0.11,
      "choline": 5.5,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 165
      }
    },
    {
      "id": 920,
      "name": "Kiwi",
      "categoryId": 900,
      "energy": 58,
      "fat": 0.44,
      "saturatedFat": 0.029,
      "monounsaturatedFat": 0.047,
      "polyunsaturatedFat": 0.287,
      "carbs": 14,
      "sugar": 8.99,
      "fiber": 3,
      "protein": 1.06,
      "sodium": 5,
      "cholesterol": 0,
      "vitaminA": 4,
      "vitaminB1": 0.027,
      "vitaminB2": 0.025,
      "vitaminB3": 0.37,
      "vitaminB5": 0,
      "vitaminB6": 0.061,
      "vitaminB9": 26,
      "vitaminB12": 0,
      "vitaminC": 74.7,
      "vitaminD": 0,
      "vitaminE": 1.3,
      "vitaminK": 40.3,
      "magnesium": 16,
      "calcium": 35,
      "phosphorus": 34,
      "potassium": 198,
      "iron": 0.24,
      "selenium": 0.2,
      "zinc": 0.14,
      "manganese": 0,
      "copper": 0.134,
      "choline": 7.8
    },
    {
      "id": 921,
      "name": "Pickled Olives",
      "categoryId": 900,
      "energy": 145,
      "fat": 15.32,
      "saturatedFat": 2.029,
      "monounsaturatedFat": 11.314,
      "polyunsaturatedFat": 1.307,
      "carbs": 3.84,
      "sugar": 0.54,
      "fiber": 3.3,
      "protein": 1.03,
      "sodium": 1556,
      "cholesterol": 0,
      "vitaminA": 20,
      "vitaminB1": 0.021,
      "vitaminB2": 0.007,
      "vitaminB3": 0.237,
      "vitaminB5": 0.023,
      "vitaminB6": 0.031,
      "vitaminB9": 3,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 3.81,
      "vitaminK": 1.4,
      "magnesium": 11,
      "calcium": 52,
      "phosphorus": 4,
      "potassium": 42,
      "iron": 0.49,
      "selenium": 0.9,
      "zinc": 0.04,
      "manganese": 0,
      "copper": 0.12,
      "choline": 14.2
    },
    {
      "id": 922,
      "name": "Grapefruit",
      "categoryId": 900,
      "energy": 32,
      "fat": 0.1,
      "saturatedFat": 0.014,
      "monounsaturatedFat": 0.013,
      "polyunsaturatedFat": 0.024,
      "carbs": 8.08,
      "sugar": 6.98,
      "fiber": 1.1,
      "protein": 0.63,
      "sodium": 0,
      "cholesterol": 0,
      "vitaminA": 46,
      "vitaminB1": 0.036,
      "vitaminB2": 0.02,
      "vitaminB3": 0.25,
      "vitaminB5": 0.283,
      "vitaminB6": 0.042,
      "vitaminB9": 10,
      "vitaminB12": 0,
      "vitaminC": 34.4,
      "vitaminD": 0,
      "vitaminE": 0.13,
      "vitaminK": 0,
      "magnesium": 8,
      "calcium": 12,
      "phosphorus": 8,
      "potassium": 139,
      "iron": 0.09,
      "selenium": 0.3,
      "zinc": 0.07,
      "manganese": 0.012,
      "copper": 0.047,
      "choline": 7.7,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 230
      }
    },
    {
      "id": 923,
      "name": "Sugar-apples",
      "categoryId": 900,
      "energy": 94,
      "fat": 0.29,
      "saturatedFat": 0.048,
      "monounsaturatedFat": 0.114,
      "polyunsaturatedFat": 0.04,
      "carbs": 23.64,
      "sugar": 0,
      "fiber": 4.4,
      "protein": 2.06,
      "sodium": 9,
      "cholesterol": 0,
      "vitaminA": 0,
      "vitaminB1": 0.11,
      "vitaminB2": 0.113,
      "vitaminB3": 0.883,
      "vitaminB5": 0.226,
      "vitaminB6": 0.2,
      "vitaminB9": 14,
      "vitaminB12": 0,
      "vitaminC": 36.3,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 0,
      "magnesium": 21,
      "calcium": 24,
      "phosphorus": 32,
      "potassium": 247,
      "iron": 0.6,
      "selenium": 0.6,
      "zinc": 0.1,
      "manganese": 0,
      "copper": 0.086,
      "choline": 0,
      "volume": {
        "portionId": "cups",
        "weightInGrams": 250
      }
    },
    {
      "id": 924,
      "name": "Figs",
      "categoryId": 900,
      "energy": 74,
      "fat": 0.3,
      "saturatedFat": 0.06,
      "monounsaturatedFat": 0.066,
      "polyunsaturatedFat": 0.144,
      "carbs": 19.18,
      "sugar": 16.26,
      "fiber": 2.9,
      "protein": 0.75,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 7,
      "vitaminB1": 0.06,
      "vitaminB2": 0.05,
      "vitaminB3": 0.4,
      "vitaminB5": 0.3,
      "vitaminB6": 0.113,
      "vitaminB9": 6,
      "vitaminB12": 0,
      "vitaminC": 2,
      "vitaminD": 0,
      "vitaminE": 0.11,
      "vitaminK": 4.7,
      "magnesium": 17,
      "calcium": 35,
      "phosphorus": 14,
      "potassium": 232,
      "iron": 0.37,
      "selenium": 0.2,
      "zinc": 0.15,
      "manganese": 0.128,
      "copper": 0.07,
      "choline": 4.7
    },
    {
      "id": 925,
      "name": "Medjool Dates",
      "categoryId": 900,
      "energy": 277,
      "fat": 0.15,
      "saturatedFat": 0,
      "monounsaturatedFat": 0,
      "polyunsaturatedFat": 0,
      "carbs": 74.97,
      "sugar": 66.47,
      "fiber": 6.7,
      "protein": 1.81,
      "sodium": 1,
      "cholesterol": 0,
      "vitaminA": 7,
      "vitaminB1": 0.05,
      "vitaminB2": 0.06,
      "vitaminB3": 1.61,
      "vitaminB5": 0.805,
      "vitaminB6": 0.249,
      "vitaminB9": 15,
      "vitaminB12": 0,
      "vitaminC": 0,
      "vitaminD": 0,
      "vitaminE": 0,
      "vitaminK": 2.7,
      "magnesium": 54,
      "calcium": 64,
      "phosphorus": 62,
      "potassium": 696,
      "iron": 0.9,
      "selenium": 0,
      "zinc": 0.44,
      "manganese": 0.2
Download .txt
gitextract_ov6rt79l/

├── .gitignore
├── .husky/
│   ├── .gitignore
│   └── pre-commit
├── .prettierignore
├── .prettierrc
├── .vscode/
│   └── settings.json
├── LICENSE
├── README.md
├── package.json
├── public/
│   ├── browserconfig.xml
│   ├── index.html
│   ├── robots.txt
│   └── site.webmanifest
├── src/
│   ├── App.tsx
│   ├── diets/
│   │   ├── DietEditor/
│   │   │   ├── DndContextProvider.tsx
│   │   │   ├── Form/
│   │   │   │   ├── About.tsx
│   │   │   │   ├── Controls/
│   │   │   │   │   ├── ExportButton.tsx
│   │   │   │   │   ├── MenuOrDrawer.tsx
│   │   │   │   │   ├── Name.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Footer.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── useDietFormEvents.ts
│   │   │   │   └── useVariantFormActions.ts
│   │   │   └── index.tsx
│   │   ├── PdfDietEditor.tsx
│   │   ├── dietForm.ts
│   │   ├── index.ts
│   │   ├── persistence/
│   │   │   ├── ExportModal/
│   │   │   │   ├── Content/
│   │   │   │   │   ├── Exporter/
│   │   │   │   │   │   ├── index.tsx
│   │   │   │   │   │   ├── usePdfExport.ts
│   │   │   │   │   │   └── worker/
│   │   │   │   │   │       ├── custom.d.ts
│   │   │   │   │   │       ├── index.ts
│   │   │   │   │   │       ├── types.ts
│   │   │   │   │   │       └── worker.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── canExportDietForm.ts
│   │   │   ├── hasMissingFoods.ts
│   │   │   ├── index.ts
│   │   │   ├── loadLastOrDefaultDietForm.ts
│   │   │   ├── parseDietForm.ts
│   │   │   ├── useDietImportErrors.tsx
│   │   │   └── useImportDietForm.ts
│   │   ├── types.ts
│   │   ├── useDietFormStore.ts
│   │   ├── useGetDietFormStatsTree.ts
│   │   └── useScrollManager.ts
│   ├── dom/
│   │   ├── animateScrollLeft.ts
│   │   ├── index.ts
│   │   ├── isElementInViewport.ts
│   │   ├── useGetRefForId.ts
│   │   └── useScrollTo.ts
│   ├── foods/
│   │   ├── FoodInfo.tsx
│   │   ├── FoodModal/
│   │   │   ├── Content/
│   │   │   │   ├── DeleteConfirmationModal.tsx
│   │   │   │   ├── FoodFormProvider.tsx
│   │   │   │   ├── Form/
│   │   │   │   │   ├── Footer.tsx
│   │   │   │   │   ├── Header.tsx
│   │   │   │   │   ├── Tabs/
│   │   │   │   │   │   ├── NutritionFactsFormFields.tsx
│   │   │   │   │   │   ├── UrlField.tsx
│   │   │   │   │   │   ├── VolumeFormFields.tsx
│   │   │   │   │   │   └── index.tsx
│   │   │   │   │   ├── index.tsx
│   │   │   │   │   ├── useSubmitFoodForm.ts
│   │   │   │   │   └── useTabs.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── useDeleteFood.ts
│   │   │   └── index.tsx
│   │   ├── FoodsDrawer/
│   │   │   ├── Content/
│   │   │   │   ├── Header.tsx
│   │   │   │   ├── MenuButtons.tsx
│   │   │   │   ├── SelectedFoodsList/
│   │   │   │   │   ├── SelectedFoodItem.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── useFoodEvents.ts
│   │   │   └── index.tsx
│   │   ├── FoodsList/
│   │   │   ├── VirtualizedList/
│   │   │   │   ├── FoodItem/
│   │   │   │   │   ├── AnimateAppear.tsx
│   │   │   │   │   ├── DisappearingBox.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── FoodItemRenderer.tsx
│   │   │   │   ├── Inner.tsx
│   │   │   │   └── index.tsx
│   │   │   └── index.tsx
│   │   ├── builtIn/
│   │   │   ├── bakedProducts.json
│   │   │   ├── beef.json
│   │   │   ├── beverages.json
│   │   │   ├── dairyAndEggs.json
│   │   │   ├── fatsAndOils.json
│   │   │   ├── finfishAndShellFish.json
│   │   │   ├── fruitsAndJuices.json
│   │   │   ├── grainsAndPasta.json
│   │   │   ├── index.ts
│   │   │   ├── legumesAndLegumeProducts.json
│   │   │   ├── nutAndSeedProducts.json
│   │   │   ├── pork.json
│   │   │   ├── poultry.json
│   │   │   ├── saucesAndSoups.json
│   │   │   ├── spicesAndHerbs.json
│   │   │   ├── sweetsAndSnacks.json
│   │   │   └── vegetables.json
│   │   ├── foodForm.ts
│   │   ├── foodVolumeForm.ts
│   │   ├── index.ts
│   │   ├── persistence/
│   │   │   ├── FoodsListModal/
│   │   │   │   ├── Content.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── MissingFoodsModal.tsx
│   │   │   ├── index.ts
│   │   │   ├── loadFoods.ts
│   │   │   └── useImportFoods.ts
│   │   ├── types.ts
│   │   └── useFoodsStore.ts
│   ├── foods-categories/
│   │   ├── FoodCategoriesSelect.tsx
│   │   ├── categories.json
│   │   ├── index.ts
│   │   └── types.ts
│   ├── foods-filters/
│   │   ├── FoodsFilterPopoverOrModal/
│   │   │   ├── Content.tsx
│   │   │   ├── Footer.tsx
│   │   │   ├── Modal.tsx
│   │   │   ├── Popover.tsx
│   │   │   ├── Trigger.tsx
│   │   │   └── index.tsx
│   │   ├── foodsFilter.ts
│   │   ├── index.ts
│   │   ├── persistence/
│   │   │   ├── index.ts
│   │   │   └── loadFoodsFilter.ts
│   │   ├── useFilterFoods.ts
│   │   └── useFoodsFilterStore.ts
│   ├── form/
│   │   ├── duplicate.ts
│   │   ├── index.ts
│   │   ├── names.ts
│   │   ├── types.ts
│   │   ├── useFormError.ts
│   │   └── useSelectInputText.ts
│   ├── general/
│   │   ├── Badge.tsx
│   │   ├── ContextMenuFlex.tsx
│   │   ├── HFadeScroll/
│   │   │   ├── FadeBox.tsx
│   │   │   ├── ScrollContainer.tsx
│   │   │   └── index.tsx
│   │   ├── Loader.tsx
│   │   ├── Menu.tsx
│   │   ├── MenuOrDrawer/
│   │   │   ├── Drawer/
│   │   │   │   ├── getDrawerButtons.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── Menu/
│   │   │   │   ├── getMenuItems.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── MenuOrDrawerItem.tsx
│   │   │   ├── MenuOrDrawerSeparator.tsx
│   │   │   ├── Trigger.tsx
│   │   │   └── index.tsx
│   │   ├── ResponsiveButton.tsx
│   │   ├── ResponsiveIconButton.tsx
│   │   ├── RightAligned.tsx
│   │   ├── ScreenSizeProvider/
│   │   │   ├── context.ts
│   │   │   └── index.tsx
│   │   ├── Tooltip.tsx
│   │   ├── TooltipCommandLabel.tsx
│   │   ├── deepCopy.ts
│   │   ├── getCtrlKeyName.ts
│   │   ├── index.ts
│   │   ├── minDelay.ts
│   │   ├── stores.tsx
│   │   ├── useElementHeight.ts
│   │   ├── useOneTimeCheckStore.ts
│   │   ├── useRunIfNotUnmounted.ts
│   │   ├── useSameOrPreviousValue.ts
│   │   └── useSelection.ts
│   ├── icons/
│   │   ├── CalendarPlus.tsx
│   │   └── index.ts
│   ├── index.tsx
│   ├── ingredients/
│   │   ├── IngredientsList/
│   │   │   ├── EmptyList.tsx
│   │   │   ├── IngredientItem/
│   │   │   │   ├── MenuOrDrawer.tsx
│   │   │   │   ├── MissingStatsLayout.tsx
│   │   │   │   ├── Notes.tsx
│   │   │   │   ├── PresenceAnimation.tsx
│   │   │   │   ├── StatsLayout.tsx
│   │   │   │   ├── getMenuOrDrawerItems.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── useIngredientsEvents.ts
│   │   │   │   └── useNotesEvents.tsx
│   │   │   └── index.tsx
│   │   ├── PdfIngredientsList/
│   │   │   ├── PdfIngredientItem/
│   │   │   │   ├── FoodName.tsx
│   │   │   │   └── index.tsx
│   │   │   └── index.tsx
│   │   ├── getIngredient.ts
│   │   ├── index.ts
│   │   ├── ingredientForm.ts
│   │   ├── types.ts
│   │   ├── useGetIngredientFormStatsTree.ts
│   │   └── useIngredientsFormsActions.ts
│   ├── layout/
│   │   ├── MainLayout.tsx
│   │   ├── Page/
│   │   │   ├── ElementContainer.tsx
│   │   │   ├── PageBody.tsx
│   │   │   ├── PageFooter.tsx
│   │   │   ├── PageHeader.tsx
│   │   │   └── index.tsx
│   │   ├── RightAligned.tsx
│   │   ├── index.tsx
│   │   └── useHasSideNavigation.ts
│   ├── meals/
│   │   ├── MealsList/
│   │   │   ├── EmptyList.tsx
│   │   │   ├── MealItem/
│   │   │   │   ├── Header/
│   │   │   │   │   ├── MenuOrDrawer.tsx
│   │   │   │   │   ├── Name.tsx
│   │   │   │   │   ├── getMenuOrDrawerItems.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── Notes.tsx
│   │   │   │   ├── PresenceAnimation.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── useGetAndUpdateStats.ts
│   │   │   │   └── useMealFormEvents.ts
│   │   │   ├── MealsControls.tsx
│   │   │   ├── index.tsx
│   │   │   └── useScrollToAndFocusMeal.ts
│   │   ├── PdfMealsList/
│   │   │   ├── Notes.tsx
│   │   │   ├── PdfMealItem.tsx
│   │   │   └── index.tsx
│   │   ├── index.ts
│   │   ├── mealForm.ts
│   │   ├── types.ts
│   │   ├── useGetMealFormStatsTree.ts
│   │   └── useMealsFormsActions.ts
│   ├── notes/
│   │   ├── EditNotesModal/
│   │   │   ├── Content/
│   │   │   │   ├── Form/
│   │   │   │   │   ├── Header.tsx
│   │   │   │   │   └── index.tsx
│   │   │   │   ├── NotesFormProvider.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── notesForm.ts
│   │   │   └── index.tsx
│   │   ├── index.ts
│   │   └── notesForm.ts
│   ├── persistence/
│   │   ├── DownloadButton.tsx
│   │   ├── file.ts
│   │   ├── fixWhiteSpace.tsx
│   │   ├── getUntitledFileName.ts
│   │   ├── index.ts
│   │   ├── useBlobUrl.ts
│   │   ├── useImportFileError.ts
│   │   └── useSaveValue.ts
│   ├── portions/
│   │   ├── PortionsMenuOrDrawer/
│   │   │   ├── Drawer/
│   │   │   │   ├── PortionItem.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── Menu.tsx
│   │   │   ├── Trigger.tsx
│   │   │   └── index.tsx
│   │   ├── PortionsSelect.tsx
│   │   ├── defaultPortions.ts
│   │   ├── formatAmount.ts
│   │   ├── getAmountFromPortionsToGrams.ts
│   │   ├── getIngredientPortionDescription.ts
│   │   ├── getPortionDescription.ts
│   │   ├── getToGramsConversionFactor.ts
│   │   ├── index.ts
│   │   ├── types.ts
│   │   ├── useGetAmount.ts
│   │   ├── useGetToGramsConversionFactor.ts
│   │   └── usePortionsStore.ts
│   ├── react-app-env.d.ts
│   ├── reportWebVitals.ts
│   ├── setupTests.ts
│   ├── stats/
│   │   ├── AmountInput.tsx
│   │   ├── EnergyStat.tsx
│   │   ├── PdfStat.tsx
│   │   ├── PdfStatsLayout.tsx
│   │   ├── Stat.tsx
│   │   ├── StatValueDetail.tsx
│   │   ├── StatsFormFields/
│   │   │   ├── MacrosFormFields.tsx
│   │   │   ├── ReavealButton.tsx
│   │   │   ├── StatFormField/
│   │   │   │   ├── ReadOnlyInput.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── types.ts
│   │   │   │   └── useGetInputElement.tsx
│   │   │   ├── VitaminsAndMineralsFormFields.tsx
│   │   │   ├── index.tsx
│   │   │   ├── useGetDailyValuePercent.ts
│   │   │   └── useGetValue.ts
│   │   ├── StatsLayout.tsx
│   │   ├── amountAsNumber.ts
│   │   ├── calculations/
│   │   │   ├── aggregateStats.ts
│   │   │   ├── getDailyValuePercent.ts
│   │   │   ├── getEnergiesEstimates.ts
│   │   │   ├── getMacrosPercents.ts
│   │   │   ├── getStatsTree.ts
│   │   │   ├── index.ts
│   │   │   └── roundMacrosPercents.ts
│   │   ├── getUnit.ts
│   │   ├── index.ts
│   │   ├── objectFromNutritionDataKeys.ts
│   │   ├── statsVariants.ts
│   │   ├── types.ts
│   │   ├── useMealsStatsStore.ts
│   │   ├── useUpdateMealStats.ts
│   │   └── useVariantStats.ts
│   ├── theme/
│   │   ├── colors.ts
│   │   ├── components/
│   │   │   ├── Alert.ts
│   │   │   ├── Button.ts
│   │   │   ├── Divider.ts
│   │   │   ├── Input.ts
│   │   │   ├── Textarea.ts
│   │   │   └── index.ts
│   │   ├── getComputedColorFromChakra.ts
│   │   ├── index.ts
│   │   └── styles.ts
│   ├── undoRedo/
│   │   ├── UndoRedoButtons/
│   │   │   ├── RedoButton.tsx
│   │   │   ├── UndoButton.tsx
│   │   │   └── index.tsx
│   │   ├── appLocation.ts
│   │   ├── deltasStack.ts
│   │   ├── index.ts
│   │   ├── useDietFormVersionsStore.ts
│   │   └── useKeyboard.ts
│   └── variants/
│       ├── PdfVariantsList/
│       │   ├── PdfVariantItem.tsx
│       │   └── index.tsx
│       ├── VariantStats/
│       │   ├── EnergyStat.tsx
│       │   ├── VariantStat.tsx
│       │   └── index.tsx
│       ├── VariantsDetailsModal/
│       │   ├── Content/
│       │   │   ├── FormFields.tsx
│       │   │   ├── VariantsDetailsFormProvider.tsx
│       │   │   ├── index.tsx
│       │   │   ├── useVariantFormEvents.ts
│       │   │   └── variantsDetailsForm.ts
│       │   └── index.tsx
│       ├── VariantsList/
│       │   ├── AddVariantButton.tsx
│       │   ├── ScrollButtons.tsx
│       │   ├── VariantItem/
│       │   │   ├── PresenceAnimation.tsx
│       │   │   ├── getMenuOrDrawerItems.tsx
│       │   │   ├── index.tsx
│       │   │   ├── useScrollIntoView.ts
│       │   │   └── useVariantFormEvents.ts
│       │   ├── VariantNameModal/
│       │   │   ├── Content.tsx
│       │   │   ├── VariantNameFormProvider.tsx
│       │   │   ├── index.tsx
│       │   │   ├── useSubmitVariantNameForm.ts
│       │   │   └── variantNameForm.ts
│       │   ├── VariantsMenuOrDrawer/
│       │   │   ├── Drawer/
│       │   │   │   ├── VariantItem.tsx
│       │   │   │   └── index.tsx
│       │   │   ├── Menu.tsx
│       │   │   ├── Trigger.tsx
│       │   │   └── index.tsx
│       │   ├── index.tsx
│       │   ├── useScrollState.ts
│       │   └── useVariantFormEvents.ts
│       ├── getVariantFormIndexAfterRemove.ts
│       ├── index.ts
│       ├── useGetVariantFormStatsTree.ts
│       ├── useVariantsFormsActions.ts
│       └── variantForm.ts
└── tsconfig.json
Download .txt
SYMBOL INDEX (559 symbols across 269 files)

FILE: src/App.tsx
  function App (line 14) | function App() {

FILE: src/diets/DietEditor/DndContextProvider.tsx
  type Props (line 6) | type Props = {
  function DndContextProvider (line 10) | function DndContextProvider({ children }: Props) {

FILE: src/diets/DietEditor/Form/About.tsx
  type Props (line 17) | type Props = {
  function About (line 22) | function About({ isOpen, onClose }: Props) {

FILE: src/diets/DietEditor/Form/Controls/ExportButton.tsx
  type Props (line 7) | type Props = {} & ButtonProps
  function ExportButton (line 9) | function ExportButton({ ...rest }: Props) {

FILE: src/diets/DietEditor/Form/Controls/MenuOrDrawer.tsx
  type Props (line 15) | type Props = {
  function MenuOrDrawer (line 21) | function MenuOrDrawer({ onImport, onClear, onViewFoods }: Props) {

FILE: src/diets/DietEditor/Form/Controls/Name.tsx
  function Name (line 7) | function Name() {

FILE: src/diets/DietEditor/Form/Controls/index.tsx
  function Controls (line 17) | function Controls() {

FILE: src/diets/DietEditor/Form/Footer.tsx
  type Props (line 3) | type Props = {
  function Footer (line 7) | function Footer({ onAbout, ...rest }: Props) {

FILE: src/diets/DietEditor/Form/index.tsx
  function Form (line 16) | function Form() {

FILE: src/diets/DietEditor/Form/useDietFormEvents.ts
  type Params (line 8) | type Params = {
  function useDietFormEvents (line 13) | function useDietFormEvents({ scrollManager, foodsDrawerDisclosure }: Par...

FILE: src/diets/DietEditor/Form/useVariantFormActions.ts
  type Params (line 5) | type Params = {
  function useVariantFormEvents (line 9) | function useVariantFormEvents({ scrollManager }: Params) {

FILE: src/diets/DietEditor/index.tsx
  function DietEditor (line 9) | function DietEditor() {

FILE: src/diets/PdfDietEditor.tsx
  type Props (line 16) | type Props = {
  function PdfDietEditor (line 24) | function PdfDietEditor({

FILE: src/diets/dietForm.ts
  type DietForm (line 5) | type DietForm = {
  function getDietForm (line 12) | function getDietForm(diet?: Diet): DietForm {

FILE: src/diets/persistence/ExportModal/Content/Exporter/index.tsx
  type Props (line 10) | type Props = {
  function Exporter (line 14) | function Exporter({ onUpdate }: Props) {

FILE: src/diets/persistence/ExportModal/Content/Exporter/usePdfExport.ts
  type Params (line 10) | type Params = {
  function usePdfExport (line 14) | function usePdfExport({ onUpdate }: Params) {

FILE: src/diets/persistence/ExportModal/Content/Exporter/worker/custom.d.ts
  class WebpackWorker (line 4) | class WebpackWorker extends Worker {

FILE: src/diets/persistence/ExportModal/Content/Exporter/worker/types.ts
  type Params (line 6) | type Params = {

FILE: src/diets/persistence/ExportModal/Content/Exporter/worker/worker.tsx
  function getDietPdfBlob (line 9) | async function getDietPdfBlob(data: any) {

FILE: src/diets/persistence/ExportModal/Content/index.tsx
  type Props (line 16) | type Props = {
  function Content (line 20) | function Content({ onClose }: Props) {

FILE: src/diets/persistence/ExportModal/index.tsx
  type Props (line 4) | type Props = {
  function ExportModal (line 9) | function ExportModal({ isOpen, onClose }: Props) {

FILE: src/diets/persistence/canExportDietForm.ts
  function canExportDietForm (line 3) | function canExportDietForm(dietForm: DietForm) {

FILE: src/diets/persistence/hasMissingFoods.ts
  function hasMissingFoods (line 4) | function hasMissingFoods(dietForm: DietForm, foodsById: Record<FoodId, F...

FILE: src/diets/persistence/loadLastOrDefaultDietForm.ts
  function loadLastOrDefaultDietForm (line 3) | function loadLastOrDefaultDietForm() {

FILE: src/diets/persistence/parseDietForm.ts
  function getLocation (line 4) | function getLocation(text: string) {
  function getData (line 16) | function getData(location: string, text: string) {
  function parseDietForm (line 27) | function parseDietForm(text: string) {

FILE: src/diets/persistence/useDietImportErrors.tsx
  type Params (line 4) | type Params = {
  function useDietImportErrors (line 8) | function useDietImportErrors({ missingFoodsModalDisclosure }: Params) {

FILE: src/diets/persistence/useImportDietForm.ts
  type Params (line 10) | type Params = {
  function useImportDietForm (line 14) | function useImportDietForm({ missingFoodsModalDisclosure }: Params) {

FILE: src/diets/types.ts
  type Diet (line 3) | type Diet = {

FILE: src/diets/useDietFormStore.ts
  type Params (line 13) | type Params = {
  type Actions (line 18) | type Actions = VariantsFormsActions &
  function useDietFormStore (line 22) | function useDietFormStore({

FILE: src/diets/useGetDietFormStatsTree.ts
  function useGetDietFormStatsTree (line 6) | function useGetDietFormStatsTree() {

FILE: src/diets/useScrollManager.ts
  type ScrollState (line 4) | type ScrollState = {
  type Params (line 9) | type Params = {
  function useScrollManager (line 14) | function useScrollManager({
  type ScrollManager (line 57) | type ScrollManager = ReturnType<typeof useScrollManager>

FILE: src/dom/animateScrollLeft.ts
  function animateScrollLeft (line 4) | function animateScrollLeft(nodeRef: RefObject<HTMLDivElement>, delta: nu...

FILE: src/dom/isElementInViewport.ts
  function isElementInViewport (line 1) | function isElementInViewport(element: Element) {

FILE: src/dom/useGetRefForId.ts
  type RefsCache (line 3) | type RefsCache<T> = {
  function useGetRefForId (line 8) | function useGetRefForId<T extends HTMLElement = HTMLElement>() {

FILE: src/dom/useScrollTo.ts
  function useScrollTo (line 3) | function useScrollTo() {

FILE: src/foods-categories/FoodCategoriesSelect.tsx
  type Props (line 5) | type Props = { forwardedRef?: ForwardedRef<HTMLSelectElement> } & Select...
  function FoodCategoriesSelect (line 7) | function FoodCategoriesSelect({ children, forwardedRef, ...rest }: Props) {

FILE: src/foods-categories/types.ts
  type FoodCategory (line 1) | type FoodCategory = {

FILE: src/foods-filters/FoodsFilterPopoverOrModal/Content.tsx
  type Props (line 6) | type Props = {
  function Content (line 10) | function Content({ selectRef }: Props) {

FILE: src/foods-filters/FoodsFilterPopoverOrModal/Footer.tsx
  type Props (line 8) | type Props = {
  function Footer (line 12) | function Footer({ onClose }: Props) {

FILE: src/foods-filters/FoodsFilterPopoverOrModal/Modal.tsx
  type Props (line 14) | type Props = {
  function Modal (line 19) | function Modal({ isOpen, onClose }: Props) {

FILE: src/foods-filters/FoodsFilterPopoverOrModal/Popover.tsx
  function Popover (line 16) | function Popover() {

FILE: src/foods-filters/FoodsFilterPopoverOrModal/Trigger.tsx
  type Props (line 7) | type Props = {
  function Trigger (line 12) | function Trigger({ onClick, forwardedRef }: Props) {

FILE: src/foods-filters/FoodsFilterPopoverOrModal/index.tsx
  function FoodsFilterPopoverOrModal (line 7) | function FoodsFilterPopoverOrModal() {

FILE: src/foods-filters/foodsFilter.ts
  constant DEFAULT_FILTER (line 1) | const DEFAULT_FILTER: FoodsFilter = {
  type FoodsFilter (line 7) | type FoodsFilter = {
  function nonQueryChangesCount (line 13) | function nonQueryChangesCount(filter: FoodsFilter) {

FILE: src/foods-filters/persistence/loadFoodsFilter.ts
  function loadFoodsFilter (line 3) | function loadFoodsFilter() {

FILE: src/foods-filters/useFilterFoods.ts
  constant OPTIONS (line 6) | const OPTIONS = { keys: ['name'] }
  function groupFoodsByCategoryId (line 8) | function groupFoodsByCategoryId(foods: Food[]) {
  function useFilterFoods (line 24) | function useFilterFoods(

FILE: src/foods-filters/useFoodsFilterStore.ts
  type Params (line 6) | type Params = {
  function filterWithoutQuery (line 11) | function filterWithoutQuery(filter: FoodsFilter) {
  function useFoodsFilterStore (line 15) | function useFoodsFilterStore({

FILE: src/foods/FoodInfo.tsx
  type Props (line 6) | type Props = {
  function FoodInfo (line 16) | function FoodInfo({

FILE: src/foods/FoodModal/Content/DeleteConfirmationModal.tsx
  type Props (line 13) | type Props = {
  function DeleteConfirmationModal (line 21) | function DeleteConfirmationModal({

FILE: src/foods/FoodModal/Content/FoodFormProvider.tsx
  type Props (line 14) | type Props = {
  function FoodFormProvider (line 19) | function FoodFormProvider({ food, children }: Props) {

FILE: src/foods/FoodModal/Content/Form/Footer.tsx
  type Props (line 3) | type Props = {
  function Footer (line 9) | function Footer({ onClose, onSubmit, isEditing }: Props) {

FILE: src/foods/FoodModal/Content/Form/Header.tsx
  type Props (line 3) | type Props = {
  function Header (line 11) | function Header({ title, canEdit, isEditing, onToggleEdit }: Props) {

FILE: src/foods/FoodModal/Content/Form/Tabs/NutritionFactsFormFields.tsx
  type Props (line 5) | type Props = {
  function NutritionFactsFormFields (line 10) | function NutritionFactsFormFields({ nameInputRef, canEdit, ...rest }: Pr...

FILE: src/foods/FoodModal/Content/Form/Tabs/UrlField.tsx
  type Props (line 13) | type Props = {
  function UrlField (line 18) | function UrlField({ canEdit, food }: Props) {

FILE: src/foods/FoodModal/Content/Form/Tabs/VolumeFormFields.tsx
  type Props (line 7) | type Props = {
  function VolumeFields (line 12) | function VolumeFields({ canEdit, food }: Props) {

FILE: src/foods/FoodModal/Content/Form/Tabs/index.tsx
  type TabName (line 15) | type TabName = 'nutrition' | 'volume' | 'link'
  type Props (line 17) | type Props = {
  function Tabs (line 26) | function Tabs({

FILE: src/foods/FoodModal/Content/Form/index.tsx
  type Props (line 20) | type Props = {
  function Form (line 32) | function Form({

FILE: src/foods/FoodModal/Content/Form/useSubmitFoodForm.ts
  type Params (line 8) | type Params = {
  function withProtocol (line 12) | function withProtocol(url: string) {
  function useSubmitFoodForm (line 16) | function useSubmitFoodForm({ onComplete }: Params) {

FILE: src/foods/FoodModal/Content/Form/useTabs.tsx
  type Params (line 5) | type Params = {
  function getTabNames (line 10) | function getTabNames(isEditing: boolean, food?: Food): TabName[] {
  function useTabs (line 28) | function useTabs({ food, isEditing }: Params) {

FILE: src/foods/FoodModal/Content/index.tsx
  type Props (line 8) | type Props = {
  function Content (line 17) | function Content({

FILE: src/foods/FoodModal/Content/useDeleteFood.ts
  type Params (line 6) | type Params = {
  function useDeleteFood (line 12) | function useDeleteFood({ food, onClose, onFoodDeleted }: Params) {

FILE: src/foods/FoodModal/index.tsx
  type Props (line 6) | type Props = {
  function FoodModal (line 14) | function FoodModal({

FILE: src/foods/FoodsDrawer/Content/Header.tsx
  type Props (line 4) | type Props = {
  function getTitlePrefix (line 10) | function getTitlePrefix(props: Props) {
  function Header (line 24) | function Header(props: Props) {

FILE: src/foods/FoodsDrawer/Content/MenuButtons.tsx
  type Props (line 9) | type Props = {
  function MenuButtons (line 14) | function MenuButtons({ onImport, onExport }: Props) {

FILE: src/foods/FoodsDrawer/Content/SelectedFoodsList/SelectedFoodItem.tsx
  type Props (line 4) | type Props = {
  function SelectedFoodItem (line 9) | function SelectedFoodItem({ food, onUnselect }: Props) {

FILE: src/foods/FoodsDrawer/Content/SelectedFoodsList/index.tsx
  type Props (line 6) | type Props = {
  function SelectedFoods (line 10) | function SelectedFoods({ selection }: Props) {

FILE: src/foods/FoodsDrawer/Content/index.tsx
  type Props (line 25) | type Props = {
  function Content (line 35) | function Content({

FILE: src/foods/FoodsDrawer/Content/useFoodEvents.ts
  type Params (line 7) | type Params = {
  function useFoodEvents (line 12) | function useFoodEvents({ listRef, selection }: Params) {

FILE: src/foods/FoodsDrawer/index.tsx
  type Props (line 8) | type Props = {
  function FoodsDrawer (line 17) | function FoodsDrawer({

FILE: src/foods/FoodsList/VirtualizedList/FoodItem/AnimateAppear.tsx
  type Props (line 4) | type Props = {
  function AnimateAppear (line 17) | function AnimateAppear({ shouldAnimate, children }: Props) {

FILE: src/foods/FoodsList/VirtualizedList/FoodItem/DisappearingBox.tsx
  type Props (line 4) | type Props = {
  function DisappearingBox (line 8) | function DisappearingBox({ shouldAnimate }: Props) {

FILE: src/foods/FoodsList/VirtualizedList/FoodItem/index.tsx
  type UsageType (line 11) | type UsageType = 'selectOrPreview' | 'previewOnly' | 'nonInteractive'
  type Props (line 13) | type Props = {
  function FoodItem (line 21) | function FoodItem({

FILE: src/foods/FoodsList/VirtualizedList/FoodItemRenderer.tsx
  type Data (line 5) | type Data = {
  type Props (line 13) | type Props = {
  function FoodItemRenderer (line 19) | function FoodItemRenderer({ style, index, data }: Props) {

FILE: src/foods/FoodsList/VirtualizedList/Inner.tsx
  constant TOP_PADDING (line 3) | const TOP_PADDING = 12

FILE: src/foods/FoodsList/VirtualizedList/index.tsx
  type Props (line 10) | type Props = {
  function VirtualizedList (line 20) | function VirtualizedList({

FILE: src/foods/FoodsList/index.tsx
  type FoodsListMethods (line 39) | type FoodsListMethods = {
  type Props (line 43) | type Props = {
  function FoodsList (line 52) | function FoodsList({

FILE: src/foods/foodForm.ts
  type FoodForm (line 7) | type FoodForm = {
  constant DEFAULT_SERVING_SIZE_IN_GRAMS (line 16) | const DEFAULT_SERVING_SIZE_IN_GRAMS = 100
  function getFoodForm (line 18) | function getFoodForm(food?: Food) {
  type FoodFormSchemaContext (line 46) | type FoodFormSchemaContext = {
  function useFoodForm (line 79) | function useFoodForm(foodForm: FoodForm) {

FILE: src/foods/foodVolumeForm.ts
  type FoodVolumeForm (line 3) | type FoodVolumeForm = {
  function getFoodVolumeForm (line 8) | function getFoodVolumeForm(foodVolume?: FoodVolume): FoodVolumeForm {

FILE: src/foods/persistence/FoodsListModal/Content.tsx
  type Action (line 14) | type Action = 'import' | 'export'
  type Props (line 16) | type Props = {
  function Content (line 23) | function Content({ onClose, title, onImport, action }: Props) {

FILE: src/foods/persistence/FoodsListModal/index.tsx
  type Props (line 6) | type Props = {
  function FoodsListModal (line 12) | function FoodsListModal({ onClose, isOpen, foodsToImport }: Props) {

FILE: src/foods/persistence/MissingFoodsModal.tsx
  type Props (line 13) | type Props = {
  function MissingFoodsModal (line 19) | function MissingFoodsModal({ isOpen, onClose, onImport }: Props) {

FILE: src/foods/persistence/loadFoods.ts
  function loadFoods (line 3) | function loadFoods() {

FILE: src/foods/persistence/useImportFoods.ts
  type Params (line 6) | type Params = {
  function useImportFoods (line 10) | function useImportFoods({ foodsListModalDisclosure }: Params) {

FILE: src/foods/types.ts
  type FoodId (line 3) | type FoodId = string | number
  type FoodVolume (line 5) | type FoodVolume = {
  type Food (line 10) | type Food = {

FILE: src/foods/useFoodsStore.ts
  type Params (line 7) | type Params = {
  function sortedFoods (line 11) | function sortedFoods(foods: Food[]) {
  function useFoodsStore (line 21) | function useFoodsStore({ initialFoods }: Params) {

FILE: src/form/duplicate.ts
  function duplicate (line 5) | function duplicate<T extends Form>(originalForm: T) {

FILE: src/form/names.ts
  function getDuplicatedName (line 3) | function getDuplicatedName(index: number, forms: Form[]) {
  function getEnumeratedName (line 9) | function getEnumeratedName(currentName: string, forms: Form[]) {

FILE: src/form/types.ts
  type Form (line 1) | type Form = {

FILE: src/form/useFormError.ts
  function useFormError (line 3) | function useFormError(name: string) {

FILE: src/form/useSelectInputText.ts
  function useSelectInputText (line 3) | function useSelectInputText(inputRef: RefObject<HTMLInputElement>) {

FILE: src/general/Badge.tsx
  type Props (line 6) | type Props = {
  function Badge (line 12) | function Badge({ children, count, forwardedRef, ...rest }: Props) {

FILE: src/general/ContextMenuFlex.tsx
  type Props (line 8) | type Props = {
  function ContextMenuFlex (line 14) | function ContextMenuFlex({

FILE: src/general/HFadeScroll/FadeBox.tsx
  type ShadowProps (line 4) | type ShadowProps = {
  function getLinearGradient (line 10) | function getLinearGradient(direction: 'left' | 'right') {
  function FadeBox (line 23) | function FadeBox({ hasStartFade, hasEndFade, children }: ShadowProps) {

FILE: src/general/HFadeScroll/index.tsx
  type Props (line 13) | type Props = {
  function onMousewheel (line 33) | function onMousewheel(event: WheelEvent) {
  function onScroll (line 41) | function onScroll() {

FILE: src/general/Loader.tsx
  type Props (line 3) | type Props = {
  function Loader (line 7) | function Loader({ label }: Props) {

FILE: src/general/MenuOrDrawer/Drawer/getDrawerButtons.tsx
  function getDrawerButtons (line 6) | function getDrawerButtons(

FILE: src/general/MenuOrDrawer/Drawer/index.tsx
  type Props (line 13) | type Props = {
  function Drawer (line 20) | function Drawer({ title, isOpen, onClose, children }: Props) {

FILE: src/general/MenuOrDrawer/Menu/getMenuItems.tsx
  function getMenuItems (line 9) | function getMenuItems(children: ReactElement | ReactElement[]) {

FILE: src/general/MenuOrDrawer/Menu/index.tsx
  type Props (line 7) | type Props = {
  function Menu (line 12) | function Menu({ children, title, ...rest }: Props) {

FILE: src/general/MenuOrDrawer/MenuOrDrawerItem.tsx
  type Props (line 3) | type Props = {
  function MenuItem (line 10) | function MenuItem(props: Props) {

FILE: src/general/MenuOrDrawer/MenuOrDrawerSeparator.tsx
  function MenuOrDrawerSeparator (line 1) | function MenuOrDrawerSeparator() {

FILE: src/general/MenuOrDrawer/Trigger.tsx
  type Props (line 5) | type Props = {
  function Trigger (line 9) | function Trigger({ forwardedRef, ...rest }: Props) {

FILE: src/general/MenuOrDrawer/index.tsx
  type Props (line 8) | type Props = {
  function MenuOrDrawer (line 13) | function MenuOrDrawer({ children, title, ...rest }: Props) {

FILE: src/general/ResponsiveButton.tsx
  type Props (line 5) | type Props = {
  function ResponsiveButton (line 9) | function ResponsiveButton({ forwardedRef, ...rest }: Props) {

FILE: src/general/ResponsiveIconButton.tsx
  type Props (line 5) | type Props = {
  function ResponsiveIconButton (line 10) | function ResponsiveIconButton({

FILE: src/general/RightAligned.tsx
  type Props (line 4) | type Props = {
  function RightAligned (line 8) | function RightAligned({ children, ...rest }: Props) {

FILE: src/general/ScreenSizeProvider/context.ts
  type ScreenSize (line 3) | enum ScreenSize {
  function useScreenSize (line 13) | function useScreenSize() {

FILE: src/general/ScreenSizeProvider/index.tsx
  type Props (line 5) | type Props = {
  function ScreenSizeProvider (line 9) | function ScreenSizeProvider({ children }: Props) {

FILE: src/general/Tooltip.tsx
  type Props (line 4) | type Props = {
  function Tooltip (line 11) | function Tooltip({ children, label, isActive = true, delay = 500 }: Prop...

FILE: src/general/TooltipCommandLabel.tsx
  type Props (line 3) | type Props = {
  function TooltipCommandLabel (line 8) | function TooltipCommandLabel({ command, kbdCombo }: Props) {

FILE: src/general/getCtrlKeyName.ts
  function isMac (line 1) | function isMac() {
  function getCtrlKeyName (line 5) | function getCtrlKeyName() {

FILE: src/general/minDelay.ts
  function minDelay (line 1) | function minDelay(startDate: Date, minDelayInMs = 500) {

FILE: src/general/stores.tsx
  function guard (line 10) | function guard(value: unknown): value is object {
  function makeUseContext (line 14) | function makeUseContext<T>(context: Context<T>) {
  function makeProvider (line 28) | function makeProvider<T>() {
  function makeStoreProvider (line 35) | function makeStoreProvider<State, Actions, StoreParams extends object>(
  function useCallbacksMemo (line 75) | function useCallbacksMemo<T extends object>(methods: T) {

FILE: src/general/useElementHeight.ts
  function useElementHeight (line 4) | function useElementHeight() {

FILE: src/general/useOneTimeCheckStore.ts
  type KeysMap (line 4) | type KeysMap = {
  function useOneTimeCheckStore (line 8) | function useOneTimeCheckStore() {
  type OneTimeCheckActions (line 41) | type OneTimeCheckActions = ReturnType<typeof useOneTimeCheckActions>

FILE: src/general/useRunIfNotUnmounted.ts
  function useRunIfNotUnmounted (line 3) | function useRunIfNotUnmounted() {

FILE: src/general/useSameOrPreviousValue.ts
  function useSameOrPreviousValue (line 3) | function useSameOrPreviousValue<T>(value: T) {

FILE: src/general/useSelection.ts
  type Id (line 3) | type Id = number | string
  type Item (line 4) | type Item = { id: Id }
  type SelectionMap (line 5) | type SelectionMap = { [id in Id]: boolean | undefined }
  type Selection (line 7) | type Selection<T extends Item> = {
  function useSelection (line 16) | function useSelection<T extends Item>(): Selection<T> {

FILE: src/icons/CalendarPlus.tsx
  function CalendarPlus (line 3) | function CalendarPlus({ size = 24, ...rest }) {

FILE: src/ingredients/IngredientsList/EmptyList.tsx
  type Props (line 3) | type Props = {
  function EmptyList (line 7) | function EmptyList({ onAddIngredients }: Props) {

FILE: src/ingredients/IngredientsList/IngredientItem/MenuOrDrawer.tsx
  type Props (line 5) | type Props = {
  function MenuOrDrawer (line 9) | function MenuOrDrawer({ children }: Props) {

FILE: src/ingredients/IngredientsList/IngredientItem/MissingStatsLayout.tsx
  type Props (line 4) | type Props = {
  function MissingStatsLayout (line 8) | function MissingStatsLayout({ onRemoveRequest }: Props) {

FILE: src/ingredients/IngredientsList/IngredientItem/Notes.tsx
  type Props (line 6) | type Props = {
  function Notes (line 11) | function Notes({ notesEvents, ingredientForm }: Props) {

FILE: src/ingredients/IngredientsList/IngredientItem/PresenceAnimation.tsx
  type Props (line 4) | type Props = {
  function PresenceAnimation (line 20) | function PresenceAnimation({

FILE: src/ingredients/IngredientsList/IngredientItem/StatsLayout.tsx
  type Props (line 8) | type Props = {
  function StatsLayout (line 22) | function StatsLayout({

FILE: src/ingredients/IngredientsList/IngredientItem/getMenuOrDrawerItems.tsx
  type Props (line 10) | type Props = {
  function getMenuOrDrawerItems (line 17) | function getMenuOrDrawerItems({

FILE: src/ingredients/IngredientsList/IngredientItem/index.tsx
  type Props (line 17) | type Props = {
  function IngredientItem (line 32) | function IngredientItem({

FILE: src/ingredients/IngredientsList/IngredientItem/useIngredientsEvents.ts
  type Params (line 13) | type Params = {
  function useIngredientsEvents (line 22) | function useIngredientsEvents({

FILE: src/ingredients/IngredientsList/IngredientItem/useNotesEvents.tsx
  type Params (line 6) | type Params = {
  function useNotesEvents (line 13) | function useNotesEvents({
  type NotesEvents (line 61) | type NotesEvents = ReturnType<typeof useNotesEvents>

FILE: src/ingredients/IngredientsList/index.tsx
  type Props (line 10) | type Props = {
  function IngredientsList (line 20) | function IngredientsList({

FILE: src/ingredients/PdfIngredientsList/PdfIngredientItem/FoodName.tsx
  type Props (line 7) | type Props = {
  function Name (line 13) | function Name({ ingredientForm, foodsById, portionsById }: Props) {

FILE: src/ingredients/PdfIngredientsList/PdfIngredientItem/index.tsx
  type Props (line 10) | type Props = {
  function PdfIngredientItem (line 18) | function PdfIngredientItem({

FILE: src/ingredients/PdfIngredientsList/index.tsx
  type Props (line 9) | type Props = {
  function PdfIngredientsList (line 16) | function PdfIngredientsList({

FILE: src/ingredients/getIngredient.ts
  function getIngredient (line 4) | function getIngredient(food: Food): Ingredient {

FILE: src/ingredients/ingredientForm.ts
  type IngredientForm (line 6) | type IngredientForm = {
  function getIngredientForm (line 14) | function getIngredientForm(ingredient: Ingredient): IngredientForm {
  function getInsertIngredientFormAnimationKey (line 25) | function getInsertIngredientFormAnimationKey(fieldId: string) {

FILE: src/ingredients/types.ts
  type Ingredient (line 3) | type Ingredient = {

FILE: src/ingredients/useGetIngredientFormStatsTree.ts
  function useGetIngredientFormStatsTree (line 9) | function useGetIngredientFormStatsTree() {

FILE: src/ingredients/useIngredientsFormsActions.ts
  type Params (line 13) | type Params = {
  function useIngredientsFormsActions (line 18) | function useIngredientsFormsActions({
  type IngredientsFormsActions (line 138) | type IngredientsFormsActions = ReturnType<typeof useIngredientsFormsActi...

FILE: src/layout/MainLayout.tsx
  type MainLayoutProps (line 11) | type MainLayoutProps = {
  function MainLayout (line 20) | function MainLayout({ children }: MainLayoutProps) {

FILE: src/layout/Page/ElementContainer.tsx
  type Props (line 4) | type Props = {
  function ElementContainer (line 9) | function ElementContainer({ children, forwardedRef, ...rest }: Props) {

FILE: src/layout/Page/PageBody.tsx
  type Props (line 5) | type Props = {
  function PageBody (line 9) | function PageBody({ children }: Props) {

FILE: src/layout/Page/PageFooter.tsx
  type Props (line 5) | type Props = {
  function PageFooter (line 10) | function PageFooter({ children, footerContainerRef }: Props) {

FILE: src/layout/Page/PageHeader.tsx
  type Props (line 5) | type Props = {
  function PageHeader (line 10) | function PageHeader({ children, forwardedRef }: Props) {

FILE: src/layout/Page/index.tsx
  type Props (line 4) | type Props = {
  function Page (line 8) | function Page({ children }: Props) {

FILE: src/layout/RightAligned.tsx
  type Props (line 4) | type Props = {
  function RightAligned (line 8) | function RightAligned({ children, ...rest }: Props) {

FILE: src/layout/useHasSideNavigation.ts
  function useHasSideNavigation (line 3) | function useHasSideNavigation() {

FILE: src/meals/MealsList/EmptyList.tsx
  type Props (line 6) | type Props = {
  function EmptyList (line 10) | function EmptyList({ onAddMeal }: Props) {

FILE: src/meals/MealsList/MealItem/Header/MenuOrDrawer.tsx
  type Props (line 5) | type Props = {
  function MenuOrDrawer (line 9) | function MenuOrDrawer({ children }: Props) {

FILE: src/meals/MealsList/MealItem/Header/Name.tsx
  type Props (line 6) | type Props = {
  function Name (line 13) | function Name({

FILE: src/meals/MealsList/MealItem/Header/getMenuOrDrawerItems.tsx
  type Params (line 11) | type Params = {
  function getMenuOrDrawerItems (line 19) | function getMenuOrDrawerItems({

FILE: src/meals/MealsList/MealItem/Header/index.tsx
  type Props (line 11) | type Props = {
  function Header (line 23) | function Header({

FILE: src/meals/MealsList/MealItem/Notes.tsx
  type Props (line 3) | type Props = {
  function Notes (line 7) | function Notes({ notes }: Props) {

FILE: src/meals/MealsList/MealItem/PresenceAnimation.tsx
  type Props (line 4) | type Props = {
  function PresenceAnimation (line 21) | function PresenceAnimation({

FILE: src/meals/MealsList/MealItem/index.tsx
  type Props (line 14) | type Props = {
  function MealItem (line 25) | function MealItem({

FILE: src/meals/MealsList/MealItem/useGetAndUpdateStats.ts
  type Params (line 6) | type Params = {
  function useGetAndUpdateStats (line 12) | function useGetAndUpdateStats({

FILE: src/meals/MealsList/MealItem/useMealFormEvents.ts
  type Params (line 9) | type Params = {
  function useMealFormEvents (line 18) | function useMealFormEvents({

FILE: src/meals/MealsList/MealsControls.tsx
  type Props (line 7) | type Props = {
  function MealsControls (line 12) | function MealsControls({ mealsForms, onAddMeal }: Props) {

FILE: src/meals/MealsList/index.tsx
  type Props (line 12) | type Props = {
  function MealsList (line 20) | function MealsList({

FILE: src/meals/MealsList/useScrollToAndFocusMeal.ts
  type Params (line 6) | type Params = {
  function useScrollToAndFocusMeal (line 11) | function useScrollToAndFocusMeal({ getMealNameInputRefById }: Params) {

FILE: src/meals/PdfMealsList/Notes.tsx
  type Props (line 4) | type Props = {
  function Notes (line 8) | function Notes({ notes }: Props) {

FILE: src/meals/PdfMealsList/PdfMealItem.tsx
  type Props (line 13) | type Props = {
  function PdfMealItem (line 22) | function PdfMealItem({

FILE: src/meals/PdfMealsList/index.tsx
  type Props (line 8) | type Props = {
  function PdfMealsList (line 15) | function PdfMealsList({

FILE: src/meals/mealForm.ts
  type MealForm (line 5) | type MealForm = {
  function getMealForm (line 12) | function getMealForm(meal?: Meal): MealForm {
  function getInsertMealFormAnimationKey (line 32) | function getInsertMealFormAnimationKey(fieldId: string) {

FILE: src/meals/types.ts
  type Meal (line 3) | type Meal = {

FILE: src/meals/useGetMealFormStatsTree.ts
  function useGetMealFormStatsTree (line 6) | function useGetMealFormStatsTree() {

FILE: src/meals/useMealsFormsActions.ts
  type Params (line 13) | type Params = {
  function useMealsFormsActions (line 18) | function useMealsFormsActions({ setDietForm, oneTimeCheckActions }: Para...
  type MealsFormsActions (line 111) | type MealsFormsActions = ReturnType<typeof useMealsFormsActions>

FILE: src/notes/EditNotesModal/Content/Form/Header.tsx
  type Props (line 3) | type Props = {
  function Header (line 8) | function Header({ ownerName, notes }: Props) {

FILE: src/notes/EditNotesModal/Content/Form/index.tsx
  type Props (line 22) | type Props = {
  function Form (line 32) | function Form({

FILE: src/notes/EditNotesModal/Content/NotesFormProvider.tsx
  type Props (line 6) | type Props = {
  function NotesFormProvider (line 11) | function NotesFormProvider({ children, notes }: Props) {

FILE: src/notes/EditNotesModal/Content/index.tsx
  type Props (line 5) | type Props = {
  function Content (line 15) | function Content({

FILE: src/notes/EditNotesModal/Content/notesForm.ts
  type NotesForm (line 3) | type NotesForm = {
  function getNotesForm (line 7) | function getNotesForm(notes?: string): NotesForm {

FILE: src/notes/EditNotesModal/index.tsx
  type Props (line 5) | type Props = {
  function EditNotesModal (line 15) | function EditNotesModal({

FILE: src/notes/notesForm.ts
  type NotesForm (line 3) | type NotesForm = {
  function getNotesForm (line 7) | function getNotesForm(notes?: string): NotesForm {

FILE: src/persistence/DownloadButton.tsx
  type Props (line 5) | type Props = {
  function DownloadButton (line 12) | function DownloadButton({ blob, onClose, fileName, label, ...rest }: Pro...

FILE: src/persistence/file.ts
  function createFileInput (line 1) | function createFileInput(accept: string) {
  function selectFile (line 10) | function selectFile(accept: string) {
  function readFile (line 25) | function readFile(file: File) {

FILE: src/persistence/fixWhiteSpace.tsx
  function fixWhiteSpace (line 1) | function fixWhiteSpace(text: string) {

FILE: src/persistence/getUntitledFileName.ts
  type Params (line 1) | type Params = {
  function getUntitledFileName (line 5) | function getUntitledFileName({ prefix = 'Untitled' }: Params = {}) {

FILE: src/persistence/useBlobUrl.ts
  type Params (line 3) | type Params = {
  function useBlobUrl (line 7) | function useBlobUrl({ blob }: Params) {

FILE: src/persistence/useImportFileError.ts
  constant COMMON_TOAST_OPTIONS (line 3) | const COMMON_TOAST_OPTIONS: UseToastOptions = {
  type OnErrorParams (line 10) | type OnErrorParams = {
  function useFileImportError (line 15) | function useFileImportError() {

FILE: src/persistence/useSaveValue.ts
  constant TIMEOUT (line 3) | const TIMEOUT = 150
  type Params (line 5) | type Params = {
  function useSaveValue (line 11) | function useSaveValue({ value, key, isEnabled = true }: Params) {

FILE: src/portions/PortionsMenuOrDrawer/Drawer/PortionItem.tsx
  type Props (line 5) | type Props = {
  function PortionItem (line 10) | function PortionItem({ portion, isSelected, ...rest }: Props) {

FILE: src/portions/PortionsMenuOrDrawer/Drawer/index.tsx
  type Props (line 12) | type Props = {
  function Drawer (line 20) | function Drawer({

FILE: src/portions/PortionsMenuOrDrawer/Menu.tsx
  type Props (line 9) | type Props = {
  function Menu (line 15) | function Menu({ portions, onChange, selectedPortionId }: Props) {

FILE: src/portions/PortionsMenuOrDrawer/Trigger.tsx
  type Props (line 5) | type Props = {
  function Trigger (line 11) | function Trigger({ forwardedRef, selectedPortionId, ...rest }: Props) {

FILE: src/portions/PortionsMenuOrDrawer/index.tsx
  type Props (line 9) | type Props = {
  function PortionsMenuOrDrawer (line 15) | function PortionsMenuOrDrawer({

FILE: src/portions/PortionsSelect.tsx
  type Props (line 5) | type Props = {
  function PortionsSelect (line 10) | function PortionsSelect({ children, forwardedRef, portions, ...rest }: P...

FILE: src/portions/formatAmount.ts
  function formatAsNumber (line 3) | function formatAsNumber(amount: number) {
  function formatAmount (line 12) | function formatAmount(amount: number, portionId: string): string {

FILE: src/portions/getAmountFromPortionsToGrams.ts
  function getAmountFromPortionToGrams (line 5) | function getAmountFromPortionToGrams(

FILE: src/portions/getIngredientPortionDescription.ts
  constant UNITS_WITH_DISTANCE (line 7) | const UNITS_WITH_DISTANCE = ['oz', 'tsp', 'tbsp', 'fl oz', 'cup']
  function getIngredientPortionDescription (line 9) | function getIngredientPortionDescription(

FILE: src/portions/getPortionDescription.ts
  function getPortionDescription (line 3) | function getPortionDescription(portion: Portion) {

FILE: src/portions/getToGramsConversionFactor.ts
  function getToGramsConversionFactor (line 4) | function getToGramsConversionFactor(

FILE: src/portions/types.ts
  type Portion (line 1) | type Portion = {

FILE: src/portions/useGetAmount.ts
  function useGetAmount (line 8) | function useGetAmount() {

FILE: src/portions/useGetToGramsConversionFactor.ts
  function useGetToGramsConversionFactor (line 6) | function useGetToGramsConversionFactor() {

FILE: src/portions/usePortionsStore.ts
  type PortionsMap (line 6) | type PortionsMap = Record<string, Portion>
  function usePortionsStore (line 8) | function usePortionsStore() {

FILE: src/stats/AmountInput.tsx
  type Props (line 5) | type Props = {
  constant MAX_AMOUNT_EXCLUDING (line 10) | const MAX_AMOUNT_EXCLUDING = 10000
  function AmountInput (line 12) | function AmountInput({

FILE: src/stats/EnergyStat.tsx
  type Props (line 6) | type Props = {
  function EnergyStat (line 11) | function EnergyStat({ energy, energyDiff, ...rest }: Props) {

FILE: src/stats/PdfStat.tsx
  type Props (line 14) | type Props = {
  function PdfStat (line 23) | function PdfStat({

FILE: src/stats/PdfStatsLayout.tsx
  type Props (line 4) | type Props = {
  function PdfStatsLayout (line 13) | function PdfStatsLayout({
  constant NAME_WIDTH (line 32) | const NAME_WIDTH = '50%'
  constant MACROS_COUNT (line 33) | const MACROS_COUNT = 4
  constant MACRO_WIDTH (line 34) | const MACRO_WIDTH = `${(100 - parseInt(NAME_WIDTH, 10)) / MACROS_COUNT}%`

FILE: src/stats/Stat.tsx
  type Props (line 13) | type Props = {
  function Stat (line 23) | function Stat({

FILE: src/stats/StatValueDetail.tsx
  type Props (line 5) | type Props = {
  function StatValueDetail (line 12) | function StatValueDetail({

FILE: src/stats/StatsFormFields/MacrosFormFields.tsx
  type Props (line 5) | type Props = {
  function MacrosFormFields (line 10) | function MacrosFormFields({

FILE: src/stats/StatsFormFields/ReavealButton.tsx
  type Props (line 7) | type Props = {
  function RevealButton (line 13) | function RevealButton({

FILE: src/stats/StatsFormFields/StatFormField/ReadOnlyInput.tsx
  type Props (line 6) | type Props = {
  function formatNutritionValue (line 13) | function formatNutritionValue(value: string) {
  function ReadOnlyInput (line 23) | function ReadOnlyInput({

FILE: src/stats/StatsFormFields/StatFormField/index.tsx
  type Props (line 19) | type Props = {
  function StatFormField (line 39) | function StatFormField(props: Props) {

FILE: src/stats/StatsFormFields/StatFormField/types.ts
  type InputType (line 1) | type InputType = 'text' | 'nutritionValue' | 'foodCategory'

FILE: src/stats/StatsFormFields/StatFormField/useGetInputElement.tsx
  type Params (line 9) | type Params = {
  function useGetInputElement (line 19) | function useGetInputElement({

FILE: src/stats/StatsFormFields/VitaminsAndMineralsFormFields.tsx
  type Props (line 7) | type Props = {
  type FieldData (line 11) | type FieldData = {
  function VitaminsAndMinerals (line 41) | function VitaminsAndMinerals({ canEdit, ...rest }: Props) {

FILE: src/stats/StatsFormFields/index.tsx
  type Props (line 5) | type Props = {
  function StatsFormFields (line 10) | function StatsFormFields({

FILE: src/stats/StatsFormFields/useGetDailyValuePercent.ts
  function useGetDailyValuePercent (line 4) | function useGetDailyValuePercent() {

FILE: src/stats/StatsFormFields/useGetValue.ts
  function useGetValue (line 5) | function useGetValue() {

FILE: src/stats/StatsLayout.tsx
  type Props (line 5) | type Props = {
  function StatsLayout (line 17) | function StatsLayout({

FILE: src/stats/amountAsNumber.ts
  function amountAsNumber (line 3) | function amountAsNumber(amount: string) {

FILE: src/stats/calculations/aggregateStats.ts
  function sumStats (line 4) | function sumStats(stats: Stats[]): Stats {
  function avgStats (line 21) | function avgStats(

FILE: src/stats/calculations/getDailyValuePercent.ts
  type DailyValuesRecord (line 3) | type DailyValuesRecord = Partial<Record<keyof NutritionData, number>>
  constant DAILY_VALUES_RECORD (line 6) | const DAILY_VALUES_RECORD: DailyValuesRecord = {
  function getDailyValuePercent (line 32) | function getDailyValuePercent(name: keyof NutritionData, value: number) {

FILE: src/stats/calculations/getEnergiesEstimates.ts
  constant CALORIES_PER_GRAM_PROTEIN (line 3) | const CALORIES_PER_GRAM_PROTEIN = 4
  constant CALORIES_PER_GRAM_CARBS (line 4) | const CALORIES_PER_GRAM_CARBS = 4
  constant CALORIES_PER_GRAM_FAT (line 5) | const CALORIES_PER_GRAM_FAT = 9
  function getProteinEnergyEstimate (line 7) | function getProteinEnergyEstimate(gramsProtein: number) {
  function getCarbsEnergyEstimate (line 11) | function getCarbsEnergyEstimate(gramsCarbs: number) {
  function getFatEnergyEstimate (line 15) | function getFatEnergyEstimate(gramsFat: number) {
  function getStatsEnergiesEstimates (line 19) | function getStatsEnergiesEstimates(stats: Stats) {

FILE: src/stats/calculations/getMacrosPercents.ts
  type MacrosPercents (line 4) | type MacrosPercents = {
  function getMacroEnergyPercent (line 10) | function getMacroEnergyPercent(energyFromMacro: number, energyTotal: num...
  function getMacrosPercents (line 14) | function getMacrosPercents(stats: Stats): MacrosPercents {

FILE: src/stats/calculations/getStatsTree.ts
  type StatsTree (line 4) | type StatsTree = {
  type Params (line 11) | type Params = {
  function getStatsTree (line 17) | function getStatsTree({ id, subtrees, calculateAvg = false }: Params) {

FILE: src/stats/calculations/roundMacrosPercents.ts
  type RoundedMacroPercent (line 3) | type RoundedMacroPercent = {
  function getDiff (line 8) | function getDiff(macroPercents: MacrosPercents) {
  function getRoundedMacroPercents (line 17) | function getRoundedMacroPercents(
  function getMacrosPercents (line 44) | function getMacrosPercents(
  function roundMacrosPercents (line 68) | function roundMacrosPercents(macroPercents: MacrosPercents): MacrosPerce...

FILE: src/stats/getUnit.ts
  type Unit (line 3) | type Unit = 'mcg' | 'mg' | 'g'
  type UnitsRecord (line 4) | type UnitsRecord = Record<keyof NutritionData, Unit>
  function getUnit (line 48) | function getUnit(name: keyof NutritionData) {

FILE: src/stats/objectFromNutritionDataKeys.ts
  type MappedNutritionData (line 3) | type MappedNutritionData<T> = { [k in keyof NutritionData]: T }
  constant NUTRITION_STATS_KEYS (line 5) | const NUTRITION_STATS_KEYS: (keyof NutritionData)[] = [
  function objectFromNutritionDataKeys (line 46) | function objectFromNutritionDataKeys<T>(

FILE: src/stats/statsVariants.ts
  type StatVariant (line 1) | type StatVariant =
  function isForDiet (line 10) | function isForDiet(statVariant: StatVariant) {
  function isForEnergy (line 14) | function isForEnergy(statVariant: StatVariant) {
  function isForIngredient (line 18) | function isForIngredient(statVaraint: StatVariant) {
  function isForMeal (line 22) | function isForMeal(statVaraint: StatVariant) {
  function getValueTextColor (line 26) | function getValueTextColor(statVariant: StatVariant) {
  function getValueFontWeight (line 34) | function getValueFontWeight(statVariant: StatVariant) {
  function getLabelColor (line 46) | function getLabelColor(statVariant: StatVariant) {

FILE: src/stats/types.ts
  type NutritionData (line 1) | type NutritionData = {
  type Stats (line 43) | type Stats = {

FILE: src/stats/useMealsStatsStore.ts
  type MealsStats (line 6) | type MealsStats = Record<string, Record<number, Stats> | undefined>
  function useMealsStatsStore (line 8) | function useMealsStatsStore() {

FILE: src/stats/useUpdateMealStats.ts
  type Params (line 5) | type Params = {
  function useUpdateMealStats (line 11) | function useUpdateMealStats({

FILE: src/stats/useVariantStats.ts
  type Params (line 7) | type Params = {
  function useVariantStats (line 11) | function useVariantStats({ variantFormFieldId }: Params) {

FILE: src/theme/getComputedColorFromChakra.ts
  function getComputedColorFromChakra (line 16) | function getComputedColorFromChakra(chakraColor: string) {

FILE: src/undoRedo/UndoRedoButtons/RedoButton.tsx
  function RedoButton (line 15) | function RedoButton() {

FILE: src/undoRedo/UndoRedoButtons/UndoButton.tsx
  function UndoButton (line 15) | function UndoButton() {

FILE: src/undoRedo/UndoRedoButtons/index.tsx
  function UndoRedoButtons (line 5) | function UndoRedoButtons() {

FILE: src/undoRedo/appLocation.ts
  type AppLocation (line 4) | type AppLocation = {
  type Params (line 10) | type Params = {
  function getAppLocation (line 15) | function getAppLocation({

FILE: src/undoRedo/deltasStack.ts
  type DeltaNode (line 4) | type DeltaNode = {
  constant MAX_SIZE (line 11) | const MAX_SIZE = 100
  class DeltasStack (line 12) | class DeltasStack {
    method getNextNodeToUnpatch (line 19) | getNextNodeToUnpatch(): DeltaNode | null {
    method getNextNodeToPatch (line 43) | getNextNodeToPatch(): DeltaNode | null {
    method keepOnlyLast (line 57) | keepOnlyLast(n: number) {
    method push (line 73) | push(delta: Delta, appLocation: AppLocation) {

FILE: src/undoRedo/useDietFormVersionsStore.ts
  type Params (line 9) | type Params = {
  constant TIMEOUT_IN_MS (line 20) | const TIMEOUT_IN_MS = 200
  type UndoRedoState (line 22) | type UndoRedoState = {
  function shouldSaveDelta (line 27) | function shouldSaveDelta(delta: Delta) {
  function useDietFormVersionsStore (line 35) | function useDietFormVersionsStore({

FILE: src/undoRedo/useKeyboard.ts
  function useKeyboard (line 5) | function useKeyboard() {

FILE: src/variants/PdfVariantsList/PdfVariantItem.tsx
  type Props (line 14) | type Props = {
  function PdfVariantItem (line 23) | function PdfVariantItem({

FILE: src/variants/PdfVariantsList/index.tsx
  type Props (line 8) | type Props = {
  function PdfVariantsList (line 15) | function PdfVariantsList({

FILE: src/variants/VariantStats/EnergyStat.tsx
  type Props (line 4) | type Props = {
  function getEnergyDiffDetail (line 10) | function getEnergyDiffDetail(energyDiff: number) {
  function EnergyStat (line 15) | function EnergyStat({ energy, energyDiff, hasAtLeastOneMeal, ...rest }: ...

FILE: src/variants/VariantStats/VariantStat.tsx
  type VariantStatType (line 4) | type VariantStatType = 'energy' | 'primaryMacro' | 'secondaryMacro'
  type Props (line 6) | type Props = {
  function getLabelFontWeight (line 15) | function getLabelFontWeight(type: VariantStatType) {
  function getValueFontWeight (line 26) | function getValueFontWeight(type: VariantStatType) {
  function VariantStat (line 36) | function VariantStat({

FILE: src/variants/VariantStats/index.tsx
  type Props (line 21) | type Props = {} & BoxProps
  function VariantStats (line 23) | function VariantStats({ ...rest }: Props) {

FILE: src/variants/VariantsDetailsModal/Content/FormFields.tsx
  type Props (line 16) | type Props = {
  function FormFields (line 24) | function FormFields({

FILE: src/variants/VariantsDetailsModal/Content/VariantsDetailsFormProvider.tsx
  type Props (line 10) | type Props = {
  function VariantsDetailsFormProvider (line 16) | function VariantsDetailsFormProvider({

FILE: src/variants/VariantsDetailsModal/Content/index.tsx
  type Props (line 15) | type Props = {
  function Content (line 21) | function Content({ onClose, initialVariantForm }: Props) {

FILE: src/variants/VariantsDetailsModal/Content/useVariantFormEvents.ts
  type Params (line 5) | type Params = {
  function useVariantFormEvents (line 9) | function useVariantFormEvents({ dietFormStatsTree }: Params) {

FILE: src/variants/VariantsDetailsModal/Content/variantsDetailsForm.ts
  type VariantsDetailsForm (line 10) | type VariantsDetailsForm = {
  function getVariantsDetailsForm (line 15) | function getVariantsDetailsForm(

FILE: src/variants/VariantsDetailsModal/index.tsx
  type Props (line 5) | type Props = {
  function VariantsDetailsModal (line 11) | function VariantsDetailsModal({ onClose, isOpen, initialVariantForm }: P...

FILE: src/variants/VariantsList/AddVariantButton.tsx
  type Props (line 5) | type Props = {} & ButtonProps
  function AddVariantButton (line 7) | function AddVariantButton({ ...rest }: Props) {

FILE: src/variants/VariantsList/ScrollButtons.tsx
  type Props (line 6) | type Props = {
  constant SCROLL_DELTA (line 13) | const SCROLL_DELTA = 100
  function ScrollButtons (line 15) | function ScrollButtons({

FILE: src/variants/VariantsList/VariantItem/PresenceAnimation.tsx
  type Props (line 4) | type Props = {
  function PresenceAnimation (line 20) | function PresenceAnimation({

FILE: src/variants/VariantsList/VariantItem/getMenuOrDrawerItems.tsx
  type Props (line 10) | type Props = {
  function getMenuOrDrawerItems (line 18) | function getMenuOrDrawerItems({

FILE: src/variants/VariantsList/VariantItem/index.tsx
  type Props (line 13) | type Props = {
  function VariantItem (line 28) | function VariantItem({

FILE: src/variants/VariantsList/VariantItem/useScrollIntoView.ts
  type Params (line 3) | type Params = {
  function useScrollIntoView (line 8) | function useScrollIntoView({ ref, isSelected }: Params) {

FILE: src/variants/VariantsList/VariantItem/useVariantFormEvents.ts
  type Params (line 6) | type Params = {
  function useVariantFormEvents (line 14) | function useVariantFormEvents({

FILE: src/variants/VariantsList/VariantNameModal/Content.tsx
  type Props (line 21) | type Props = {
  function Content (line 28) | function Content({ title, onClose, initialRef, variantFormIndex }: Props) {

FILE: src/variants/VariantsList/VariantNameModal/VariantNameFormProvider.tsx
  type Props (line 12) | type Props = {
  function VariantNameFormProvider (line 17) | function VariantNameFormProvider({ children, variantFormIndex }: Props) {

FILE: src/variants/VariantsList/VariantNameModal/index.tsx
  type Props (line 6) | type Props = {
  function VariantNameModal (line 12) | function VariantNameModal({ onClose, isOpen, variantFormIndex }: Props) {

FILE: src/variants/VariantsList/VariantNameModal/useSubmitVariantNameForm.ts
  type Params (line 5) | type Params = {
  function useSubmitVariantNameForm (line 10) | function useSubmitVariantNameForm({ onComplete, variantFormIndex }: Para...

FILE: src/variants/VariantsList/VariantNameModal/variantNameForm.ts
  type VariantNameForm (line 4) | type VariantNameForm = {
  function getVariantNameForm (line 8) | function getVariantNameForm(name: string): VariantNameForm {
  type VariantNameFormSchemaContext (line 14) | type VariantNameFormSchemaContext = {

FILE: src/variants/VariantsList/VariantsMenuOrDrawer/Drawer/VariantItem.tsx
  type Props (line 4) | type Props = {
  function VariantItem (line 9) | function VariantItem({ name, isSelected, ...rest }: Props) {

FILE: src/variants/VariantsList/VariantsMenuOrDrawer/Drawer/index.tsx
  type Props (line 13) | type Props = {
  function Drawer (line 19) | function Drawer({ isOpen, onClose, onSelect }: Props) {

FILE: src/variants/VariantsList/VariantsMenuOrDrawer/Menu.tsx
  type Props (line 10) | type Props = {
  function Menu (line 14) | function Menu({ onSelect }: Props) {

FILE: src/variants/VariantsList/VariantsMenuOrDrawer/Trigger.tsx
  type Props (line 6) | type Props = {
  function Trigger (line 11) | function Trigger({ forwardedRef, onClick, ...rest }: Props) {

FILE: src/variants/VariantsList/VariantsMenuOrDrawer/index.tsx
  type Props (line 9) | type Props = {
  function VariantsMenuOrDrawer (line 13) | function VariantsMenuOrDrawer({ onVariantFormSelect }: Props) {

FILE: src/variants/VariantsList/index.tsx
  type Props (line 17) | type Props = {
  function VariantsList (line 22) | function VariantsList({

FILE: src/variants/VariantsList/useScrollState.ts
  function useScrollState (line 3) | function useScrollState() {

FILE: src/variants/VariantsList/useVariantFormEvents.ts
  type Params (line 6) | type Params = {
  function useVariantFormEvents (line 13) | function useVariantFormEvents({

FILE: src/variants/getVariantFormIndexAfterRemove.ts
  function getVariantFormIndexAfterRemove (line 1) | function getVariantFormIndexAfterRemove(

FILE: src/variants/useGetVariantFormStatsTree.ts
  function useGetVariantFormStatsTree (line 6) | function useGetVariantFormStatsTree() {

FILE: src/variants/useVariantsFormsActions.ts
  type Params (line 13) | type Params = {
  function getAppendedVariantFormName (line 18) | function getAppendedVariantFormName(variantForms: VariantForm[]) {
  function useVariantsFormsActions (line 22) | function useVariantsFormsActions({ setDietForm, oneTimeCheckActions }: P...
  type VariantsFormsActions (line 145) | type VariantsFormsActions = ReturnType<typeof useVariantsFormsActions>

FILE: src/variants/variantForm.ts
  type VariantForm (line 4) | type VariantForm = {
  function getVariantForm (line 10) | function getVariantForm(name: string): VariantForm {
  function getInsertVariantFormAnimationKey (line 20) | function getInsertVariantFormAnimationKey(fieldId: string) {
Condensed preview — 340 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (680K chars).
[
  {
    "path": ".gitignore",
    "chars": 310,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
  },
  {
    "path": ".husky/.gitignore",
    "chars": 2,
    "preview": "_\n"
  },
  {
    "path": ".husky/pre-commit",
    "chars": 58,
    "preview": "#!/bin/sh\n. \"$(dirname \"$0\")/_/husky.sh\"\n\nnpx lint-staged\n"
  },
  {
    "path": ".prettierignore",
    "chars": 108,
    "preview": "**/node_modules\n**/dist\n**/package.json\n**/yarn.lock\n**/package-lock.json\n**/.eslintrc.json\n**/tsconfig.json"
  },
  {
    "path": ".prettierrc",
    "chars": 89,
    "preview": "{\n  \"arrowParens\": \"avoid\",\n  \"singleQuote\": true,\n  \"semi\": false,\n  \"printWidth\": 80\n} "
  },
  {
    "path": ".vscode/settings.json",
    "chars": 121,
    "preview": "{\n  \"editor.formatOnPaste\": true,\n  \"editor.formatOnSave\": true,\n  \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n}"
  },
  {
    "path": "LICENSE",
    "chars": 1072,
    "preview": "MIT License\n\nCopyright (c) 2021 Vladimir Angelov\n\nPermission is hereby granted, free of charge, to any person obtaining "
  },
  {
    "path": "README.md",
    "chars": 1537,
    "preview": "<p align=\"center\">\n   <a href=\"https://calories-in.com\" target=\"_blank\">\n    <img src=\"devices-preview.png\" alt=\"Devices"
  },
  {
    "path": "package.json",
    "chars": 2512,
    "preview": "{\n  \"name\": \"energytab\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@chakra-ui/react\": \"^1.3.4\",\n"
  },
  {
    "path": "public/browserconfig.xml",
    "chars": 246,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n    <msapplication>\n        <tile>\n            <square150x150logo"
  },
  {
    "path": "public/index.html",
    "chars": 1646,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-w"
  },
  {
    "path": "public/robots.txt",
    "chars": 67,
    "preview": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "public/site.webmanifest",
    "chars": 426,
    "preview": "{\n    \"name\": \"\",\n    \"short_name\": \"\",\n    \"icons\": [\n        {\n            \"src\": \"/android-chrome-192x192.png\",\n     "
  },
  {
    "path": "src/App.tsx",
    "chars": 985,
    "preview": "import { ChakraProvider } from '@chakra-ui/react'\nimport { MainLayout } from 'layout'\nimport 'focus-visible/dist/focus-v"
  },
  {
    "path": "src/diets/DietEditor/DndContextProvider.tsx",
    "chars": 974,
    "preview": "import { useDietFormActions } from 'diets'\nimport { ReactNode } from 'react'\n\nimport { DragDropContext, DropResult } fro"
  },
  {
    "path": "src/diets/DietEditor/Form/About.tsx",
    "chars": 4885,
    "preview": "import {\n  Modal,\n  ModalOverlay,\n  ModalContent,\n  ModalHeader,\n  ModalFooter,\n  ModalBody,\n  ModalCloseButton,\n  Butto"
  },
  {
    "path": "src/diets/DietEditor/Form/Controls/ExportButton.tsx",
    "chars": 1040,
    "preview": "import { ScreenSize, useScreenSize } from 'general'\nimport { Button, ButtonProps, IconButton } from '@chakra-ui/react'\ni"
  },
  {
    "path": "src/diets/DietEditor/Form/Controls/MenuOrDrawer.tsx",
    "chars": 1425,
    "preview": "import { chakra } from '@chakra-ui/react'\nimport { Download, List, MoreHorizontal, Trash } from 'react-feather'\nimport {"
  },
  {
    "path": "src/diets/DietEditor/Form/Controls/Name.tsx",
    "chars": 1501,
    "preview": "import { useDietForm, useDietFormActions } from 'diets'\nimport { Editable, EditableInput, EditablePreview } from '@chakr"
  },
  {
    "path": "src/diets/DietEditor/Form/Controls/index.tsx",
    "chars": 2553,
    "preview": "import { Flex, useDisclosure, Button } from '@chakra-ui/react'\nimport { UndoRedoButtons, useKeyboard } from 'undoRedo'\ni"
  },
  {
    "path": "src/diets/DietEditor/Form/Footer.tsx",
    "chars": 907,
    "preview": "import { Box, HStack, Button, Divider, Link, BoxProps } from '@chakra-ui/react'\n\ntype Props = {\n  onAbout: () => void\n} "
  },
  {
    "path": "src/diets/DietEditor/Form/index.tsx",
    "chars": 3314,
    "preview": "import { useDietForm, useScrollManager } from 'diets'\nimport { DietFormVersionsStoreProvider } from 'undoRedo'\nimport { "
  },
  {
    "path": "src/diets/DietEditor/Form/useDietFormEvents.ts",
    "chars": 1297,
    "preview": "import { UseDisclosureReturn } from '@chakra-ui/hooks'\nimport { DietForm, useDietFormActions, ScrollManager } from 'diet"
  },
  {
    "path": "src/diets/DietEditor/Form/useVariantFormActions.ts",
    "chars": 712,
    "preview": "import { VariantForm } from 'variants'\nimport { useCallback } from 'react'\nimport { ScrollManager } from 'diets/useScrol"
  },
  {
    "path": "src/diets/DietEditor/index.tsx",
    "chars": 821,
    "preview": "import { DietFormStoreProvider } from 'diets'\nimport Form from './Form'\nimport { useOneTimeCheckActions } from 'general'"
  },
  {
    "path": "src/diets/PdfDietEditor.tsx",
    "chars": 2597,
    "preview": "import ReactPDF, {\n  Document,\n  Page,\n  Font,\n  StyleSheet,\n  View,\n} from '@react-pdf/renderer'\nimport { Food } from '"
  },
  {
    "path": "src/diets/dietForm.ts",
    "chars": 651,
    "preview": "import { Diet } from 'diets'\nimport { getVariantForm, VariantForm } from 'variants'\nimport { v4 as uuidv4 } from 'uuid'\n"
  },
  {
    "path": "src/diets/index.ts",
    "chars": 383,
    "preview": "export * from './dietForm'\nexport { default as useDietFormStore } from './useDietFormStore'\nexport * from './useDietForm"
  },
  {
    "path": "src/diets/persistence/ExportModal/Content/Exporter/index.tsx",
    "chars": 1148,
    "preview": "import { Loader } from 'general'\nimport {\n  Alert,\n  AlertIcon,\n  AlertTitle,\n  AlertDescription,\n} from '@chakra-ui/rea"
  },
  {
    "path": "src/diets/persistence/ExportModal/Content/Exporter/usePdfExport.ts",
    "chars": 1633,
    "preview": "import { useDietForm, useGetDietFormStatsTree } from 'diets'\nimport { useFoods } from 'foods'\nimport { usePortions } fro"
  },
  {
    "path": "src/diets/persistence/ExportModal/Content/Exporter/worker/custom.d.ts",
    "chars": 210,
    "preview": "declare module 'comlink-loader!*' {\n  import { Params } from './types'\n\n  class WebpackWorker extends Worker {\n    const"
  },
  {
    "path": "src/diets/persistence/ExportModal/Content/Exporter/worker/index.ts",
    "chars": 96,
    "preview": "// eslint-disable-next-line\nimport Worker from 'comlink-loader!./worker'\n\nexport default Worker\n"
  },
  {
    "path": "src/diets/persistence/ExportModal/Content/Exporter/worker/types.ts",
    "chars": 334,
    "preview": "import { DietForm } from 'diets/dietForm'\nimport { Food } from 'foods/types'\nimport { Portion } from 'portions/types'\nim"
  },
  {
    "path": "src/diets/persistence/ExportModal/Content/Exporter/worker/worker.tsx",
    "chars": 595,
    "preview": "import { pdf } from '@react-pdf/renderer'\n\nif (process.env.NODE_ENV !== 'production') {\n  const t: any = global\n  t.$Ref"
  },
  {
    "path": "src/diets/persistence/ExportModal/Content/index.tsx",
    "chars": 1823,
    "preview": "import {\n  ModalContent,\n  ModalHeader,\n  ModalFooter,\n  ModalBody,\n  ModalCloseButton,\n  Button,\n  VStack,\n  Text,\n} fr"
  },
  {
    "path": "src/diets/persistence/ExportModal/index.tsx",
    "chars": 370,
    "preview": "import { Modal, ModalOverlay } from '@chakra-ui/react'\nimport Content from './Content'\n\ntype Props = {\n  isOpen: boolean"
  },
  {
    "path": "src/diets/persistence/canExportDietForm.ts",
    "chars": 245,
    "preview": "import { DietForm } from 'diets'\n\nfunction canExportDietForm(dietForm: DietForm) {\n  const { variantsForms } = dietForm\n"
  },
  {
    "path": "src/diets/persistence/hasMissingFoods.ts",
    "chars": 591,
    "preview": "import { DietForm } from 'diets'\nimport { Food, FoodId } from 'foods'\n\nfunction hasMissingFoods(dietForm: DietForm, food"
  },
  {
    "path": "src/diets/persistence/index.ts",
    "chars": 394,
    "preview": "export { default as ExportModal } from './ExportModal'\nexport { default as useImportDietForm } from './useImportDietForm"
  },
  {
    "path": "src/diets/persistence/loadLastOrDefaultDietForm.ts",
    "chars": 328,
    "preview": "import { getDietForm } from 'diets'\n\nfunction loadLastOrDefaultDietForm() {\n  const savedValue = localStorage.getItem('l"
  },
  {
    "path": "src/diets/persistence/parseDietForm.ts",
    "chars": 1052,
    "preview": "import { DietForm } from 'diets'\nimport { fixWhiteSpace } from 'persistence'\n\nfunction getLocation(text: string) {\n  con"
  },
  {
    "path": "src/diets/persistence/useDietImportErrors.tsx",
    "chars": 954,
    "preview": "import { useToast } from '@chakra-ui/toast'\nimport { Text, Button, UseDisclosureReturn } from '@chakra-ui/react'\n\ntype P"
  },
  {
    "path": "src/diets/persistence/useImportDietForm.ts",
    "chars": 1545,
    "preview": "import { selectFile, readFile } from 'persistence'\nimport { useFoods } from 'foods'\nimport { useDietFormActions } from '"
  },
  {
    "path": "src/diets/types.ts",
    "chars": 112,
    "preview": "import { Meal } from 'meals'\n\ntype Diet = {\n  id: number\n  name: string\n  meals: Meal[]\n}\n\nexport type { Diet }\n"
  },
  {
    "path": "src/diets/useDietFormStore.ts",
    "chars": 1891,
    "preview": "import { useCallback, useState } from 'react'\nimport { DietForm } from './dietForm'\nimport { useVariantsFormsActions, Va"
  },
  {
    "path": "src/diets/useGetDietFormStatsTree.ts",
    "chars": 711,
    "preview": "import { StatsTree, getStatsTree } from 'stats'\nimport { DietForm } from './dietForm'\nimport { useGetVariantFormStatsTre"
  },
  {
    "path": "src/diets/useScrollManager.ts",
    "chars": 1440,
    "preview": "import { VariantForm } from 'variants'\nimport { useState, useRef, useEffect, RefObject, useCallback } from 'react'\n\ntype"
  },
  {
    "path": "src/dom/animateScrollLeft.ts",
    "chars": 405,
    "preview": "import { animate } from 'framer-motion'\nimport { RefObject } from 'react'\n\nfunction animateScrollLeft(nodeRef: RefObject"
  },
  {
    "path": "src/dom/index.ts",
    "chars": 254,
    "preview": "export { default as animateScrollLeft } from './animateScrollLeft'\nexport { default as isElementInViewport } from './isE"
  },
  {
    "path": "src/dom/isElementInViewport.ts",
    "chars": 359,
    "preview": "function isElementInViewport(element: Element) {\n  const { top, left, bottom, right } = element.getBoundingClientRect()\n"
  },
  {
    "path": "src/dom/useGetRefForId.ts",
    "chars": 488,
    "preview": "import { createRef, RefObject, useCallback, useRef } from 'react'\n\ntype RefsCache<T> = {\n  [id: number]: RefObject<T>\n  "
  },
  {
    "path": "src/dom/useScrollTo.ts",
    "chars": 1108,
    "preview": "import { useEffect, useRef, useCallback } from 'react'\n\nfunction useScrollTo() {\n  const scrollTimeoutRef = useRef<numbe"
  },
  {
    "path": "src/foods/FoodInfo.tsx",
    "chars": 1208,
    "preview": "import { Text, Box, Flex, BoxProps, Link } from '@chakra-ui/react'\nimport { Food } from 'foods'\nimport { ReactNode } fro"
  },
  {
    "path": "src/foods/FoodModal/Content/DeleteConfirmationModal.tsx",
    "chars": 1096,
    "preview": "import {\n  Modal,\n  ModalOverlay,\n  ModalContent,\n  ModalHeader,\n  ModalFooter,\n  ModalBody,\n  ModalCloseButton,\n  Butto"
  },
  {
    "path": "src/foods/FoodModal/Content/FoodFormProvider.tsx",
    "chars": 784,
    "preview": "import { useForm } from 'react-hook-form'\nimport { yupResolver } from '@hookform/resolvers/yup'\nimport { ReactNode } fro"
  },
  {
    "path": "src/foods/FoodModal/Content/Form/Footer.tsx",
    "chars": 599,
    "preview": "import { ModalFooter, Button, HStack } from '@chakra-ui/react'\n\ntype Props = {\n  onClose: () => void\n  onSubmit: () => v"
  },
  {
    "path": "src/foods/FoodModal/Content/Form/Header.tsx",
    "chars": 593,
    "preview": "import { ModalHeader, Button } from '@chakra-ui/react'\n\ntype Props = {\n  onClose: () => void\n  title: string\n  canEdit: "
  },
  {
    "path": "src/foods/FoodModal/Content/Form/Tabs/NutritionFactsFormFields.tsx",
    "chars": 1169,
    "preview": "import { Box, FlexProps, VStack } from '@chakra-ui/react'\nimport { RefObject } from 'react'\nimport { StatsFormFields, St"
  },
  {
    "path": "src/foods/FoodModal/Content/Form/Tabs/UrlField.tsx",
    "chars": 1348,
    "preview": "import {\n  Flex,\n  FormControl,\n  FormLabel,\n  Link,\n  Alert,\n  AlertIcon,\n} from '@chakra-ui/react'\nimport { Input } fr"
  },
  {
    "path": "src/foods/FoodModal/Content/Form/Tabs/VolumeFormFields.tsx",
    "chars": 1931,
    "preview": "import { Flex, Text, HStack, Alert, AlertIcon } from '@chakra-ui/react'\nimport { Food, FoodForm } from 'foods'\nimport { "
  },
  {
    "path": "src/foods/FoodModal/Content/Form/Tabs/index.tsx",
    "chars": 1893,
    "preview": "import { Food } from 'foods'\nimport NutritionFactsFormFields from './NutritionFactsFormFields'\nimport { RefObject } from"
  },
  {
    "path": "src/foods/FoodModal/Content/Form/index.tsx",
    "chars": 2954,
    "preview": "import {\n  ModalContent,\n  ModalCloseButton,\n  ModalBody,\n  Button,\n  Divider,\n  Box,\n  VStack,\n  Text,\n} from '@chakra-"
  },
  {
    "path": "src/foods/FoodModal/Content/Form/useSubmitFoodForm.ts",
    "chars": 1592,
    "preview": "import { objectFromNutritionDataKeys } from 'stats'\nimport { Food, FoodForm } from 'foods'\nimport { useOneTimeCheckActio"
  },
  {
    "path": "src/foods/FoodModal/Content/Form/useTabs.tsx",
    "chars": 985,
    "preview": "import { Food } from 'foods'\nimport { useEffect, useState } from 'react'\nimport { TabName } from './Tabs'\n\ntype Params ="
  },
  {
    "path": "src/foods/FoodModal/Content/index.tsx",
    "chars": 1619,
    "preview": "import { Food } from 'foods'\nimport { RefObject, useState } from 'react'\nimport DeleteConfirmationModal from './DeleteCo"
  },
  {
    "path": "src/foods/FoodModal/Content/useDeleteFood.ts",
    "chars": 992,
    "preview": "import { useDisclosure } from '@chakra-ui/hooks'\nimport { useFoodsActions } from 'foods'\nimport { Food } from 'foods'\nim"
  },
  {
    "path": "src/foods/FoodModal/index.tsx",
    "chars": 1081,
    "preview": "import { Modal, ModalOverlay } from '@chakra-ui/react'\nimport { Food } from 'foods'\nimport { useRef } from 'react'\nimpor"
  },
  {
    "path": "src/foods/FoodsDrawer/Content/Header.tsx",
    "chars": 832,
    "preview": "import { DrawerHeader, Text } from '@chakra-ui/react'\nimport { MealForm } from 'meals'\n\ntype Props = {\n  mealName?: stri"
  },
  {
    "path": "src/foods/FoodsDrawer/Content/MenuButtons.tsx",
    "chars": 1000,
    "preview": "import { chakra, IconButton } from '@chakra-ui/react'\nimport { MoreHorizontal, Download, Share } from 'react-feather'\nim"
  },
  {
    "path": "src/foods/FoodsDrawer/Content/SelectedFoodsList/SelectedFoodItem.tsx",
    "chars": 564,
    "preview": "import { Tag, TagLabel, TagCloseButton, Fade } from '@chakra-ui/react'\nimport { Food } from 'foods'\n\ntype Props = {\n  fo"
  },
  {
    "path": "src/foods/FoodsDrawer/Content/SelectedFoodsList/index.tsx",
    "chars": 843,
    "preview": "import { Flex, Text, Wrap } from '@chakra-ui/react'\nimport { Selection } from 'general'\nimport SelectedFoodItem from './"
  },
  {
    "path": "src/foods/FoodsDrawer/Content/index.tsx",
    "chars": 4046,
    "preview": "import {\n  DrawerContent,\n  DrawerCloseButton,\n  DrawerBody,\n  DrawerFooter,\n  Flex,\n  Button,\n  VStack,\n  Text,\n  HStac"
  },
  {
    "path": "src/foods/FoodsDrawer/Content/useFoodEvents.ts",
    "chars": 1107,
    "preview": "import { useDisclosure } from '@chakra-ui/react'\nimport { Food } from 'foods'\nimport { useState, RefObject } from 'react"
  },
  {
    "path": "src/foods/FoodsDrawer/index.tsx",
    "chars": 1058,
    "preview": "import { Drawer, DrawerOverlay } from '@chakra-ui/react'\nimport { Food } from 'foods'\nimport { MealForm } from 'meals'\ni"
  },
  {
    "path": "src/foods/FoodsList/VirtualizedList/FoodItem/AnimateAppear.tsx",
    "chars": 633,
    "preview": "import { motion } from 'framer-motion'\nimport { ReactNode } from 'react'\n\ntype Props = {\n  shouldAnimate: boolean\n  chil"
  },
  {
    "path": "src/foods/FoodsList/VirtualizedList/FoodItem/DisappearingBox.tsx",
    "chars": 578,
    "preview": "import { Box } from '@chakra-ui/react'\nimport { useEffect, useState } from 'react'\n\ntype Props = {\n  shouldAnimate: bool"
  },
  {
    "path": "src/foods/FoodsList/VirtualizedList/FoodItem/index.tsx",
    "chars": 2920,
    "preview": "import { FoodInfo, Food } from 'foods'\nimport { Flex, FlexProps, Box, chakra, IconButton } from '@chakra-ui/react'\nimpor"
  },
  {
    "path": "src/foods/FoodsList/VirtualizedList/FoodItemRenderer.tsx",
    "chars": 916,
    "preview": "import { Food } from 'foods'\nimport FoodItem, { UsageType } from './FoodItem'\nimport { TOP_PADDING } from './Inner'\n\ntyp"
  },
  {
    "path": "src/foods/FoodsList/VirtualizedList/Inner.tsx",
    "chars": 312,
    "preview": "import { forwardRef } from 'react'\n\nconst TOP_PADDING = 12\n\nconst Inner = forwardRef<any, any>(({ style, ...rest }, ref)"
  },
  {
    "path": "src/foods/FoodsList/VirtualizedList/index.tsx",
    "chars": 1446,
    "preview": "import { Box } from '@chakra-ui/react'\nimport { FixedSizeList } from 'react-window'\nimport { forwardRef, ForwardedRef } "
  },
  {
    "path": "src/foods/FoodsList/index.tsx",
    "chars": 3876,
    "preview": "import {\n  Input,\n  InputGroup,\n  InputLeftElement,\n  chakra,\n  Flex,\n  Text,\n  FlexProps,\n  HStack,\n  Box,\n} from '@cha"
  },
  {
    "path": "src/foods/builtIn/bakedProducts.json",
    "chars": 14166,
    "preview": "\n  [\n    {\n      \"id\": 3001,\n      \"name\": \"Taco shells\",\n      \"categoryId\": 3000,\n      \"energy\": 476,\n      \"fat\": 21"
  },
  {
    "path": "src/foods/builtIn/beef.json",
    "chars": 4785,
    "preview": "[\n  {\n    \"id\": 201,\n    \"name\": \"70% Lean Ground Beef\",\n    \"categoryId\": 200,\n    \"energy\": 332,\n    \"fat\": 30,\n    \"s"
  },
  {
    "path": "src/foods/builtIn/beverages.json",
    "chars": 5337,
    "preview": "[\n    {\n      \"id\": 7001,\n      \"name\": \"Unsweetened Almond Milk\",\n      \"categoryId\": 7000,\n      \"energy\": 15,\n      \""
  },
  {
    "path": "src/foods/builtIn/dairyAndEggs.json",
    "chars": 27156,
    "preview": "[\n  {\n    \"id\": 501,\n    \"name\": \"Skim Milk\",\n    \"categoryId\": 500,\n    \"energy\": 34,\n    \"fat\": 0.08,\n    \"saturatedFa"
  },
  {
    "path": "src/foods/builtIn/fatsAndOils.json",
    "chars": 11786,
    "preview": "[\n    {\n      \"id\": 2001,\n      \"name\": \"PAM cooking spray\",\n      \"categoryId\": 2000,\n      \"energy\": 792,\n      \"fat\":"
  },
  {
    "path": "src/foods/builtIn/finfishAndShellFish.json",
    "chars": 10916,
    "preview": "[\n  {\n    \"id\": 401,\n    \"name\": \"Wild Atlantic Salmon\",\n    \"categoryId\": 400,\n    \"energy\": 142,\n    \"fat\": 6.34,\n    "
  },
  {
    "path": "src/foods/builtIn/fruitsAndJuices.json",
    "chars": 30289,
    "preview": "[\n    {\n      \"id\": 901,\n      \"name\": \"Tomatoes\",\n      \"categoryId\": 900,\n      \"energy\": 18,\n      \"fat\": 0.2,\n      "
  },
  {
    "path": "src/foods/builtIn/grainsAndPasta.json",
    "chars": 16958,
    "preview": "[\n  {\n    \"id\": 601,\n    \"name\": \"Brown Rice\",\n    \"categoryId\": 600,\n    \"energy\": 367,\n    \"fat\": 3.2,\n    \"saturatedF"
  },
  {
    "path": "src/foods/builtIn/index.ts",
    "chars": 1130,
    "preview": "import poultry from './poultry.json'\nimport beef from './beef.json'\nimport pork from './pork.json'\nimport finfishAndShel"
  },
  {
    "path": "src/foods/builtIn/legumesAndLegumeProducts.json",
    "chars": 16899,
    "preview": "[\n    {\n      \"id\": 801,\n      \"name\": \"Traditional Refried Beans (canned)\",\n      \"categoryId\": 800,\n      \"energy\": 90"
  },
  {
    "path": "src/foods/builtIn/nutAndSeedProducts.json",
    "chars": 19753,
    "preview": "[\n    {\n      \"id\": 1001,\n      \"name\": \"Sunflower Seeds\",\n      \"categoryId\": 1000,\n      \"energy\": 584,\n      \"fat\": 5"
  },
  {
    "path": "src/foods/builtIn/pork.json",
    "chars": 4740,
    "preview": "[\n  {\n    \"id\": 301,\n    \"name\": \"84% Lean Ground Pork\",\n    \"categoryId\": 300,\n    \"energy\": 218,\n    \"fat\": 16,\n    \"s"
  },
  {
    "path": "src/foods/builtIn/poultry.json",
    "chars": 7830,
    "preview": "[\n  {\n    \"id\": 101,\n    \"name\": \"Skinless Chicken Breast\",\n    \"categoryId\": 100,\n    \"energy\": 108,\n    \"fat\": 3,\n    "
  },
  {
    "path": "src/foods/builtIn/saucesAndSoups.json",
    "chars": 15982,
    "preview": "[\n    {\n      \"id\": 4001,\n      \"name\": \"Sriracha\",\n      \"categoryId\": 4000,\n      \"energy\": 93,\n      \"fat\": 0.93,\n   "
  },
  {
    "path": "src/foods/builtIn/spicesAndHerbs.json",
    "chars": 22421,
    "preview": "[\n  {\n    \"id\": 5001,\n    \"name\": \"Salt\",\n    \"categoryId\": 5000,\n    \"energy\": 0,\n    \"fat\": 0,\n    \"saturatedFat\": 0,\n"
  },
  {
    "path": "src/foods/builtIn/sweetsAndSnacks.json",
    "chars": 21656,
    "preview": "[\n    {\n      \"id\": 6001,\n      \"name\": \"Maple syrup\",\n      \"categoryId\": 6000,\n      \"energy\": 260,\n      \"fat\": 0.06,"
  },
  {
    "path": "src/foods/builtIn/vegetables.json",
    "chars": 35543,
    "preview": "[\n  {\n    \"id\": 701,\n    \"name\": \"Sweet Corn Kernels (frozen)\",\n    \"categoryId\": 700,\n    \"energy\": 88,\n    \"fat\": 0.78"
  },
  {
    "path": "src/foods/foodForm.ts",
    "chars": 2355,
    "preview": "import { Food, FoodId } from 'foods'\nimport { useForm } from 'react-hook-form'\nimport { object, string, number } from 'y"
  },
  {
    "path": "src/foods/foodVolumeForm.ts",
    "chars": 450,
    "preview": "import { FoodVolume } from 'foods'\n\ntype FoodVolumeForm = {\n  portionId: string\n  weightInGrams: string\n}\n\nfunction getF"
  },
  {
    "path": "src/foods/index.ts",
    "chars": 397,
    "preview": "export * from './foodForm'\nexport * from './useFoodsStore'\nexport { default as FoodInfo } from './FoodInfo'\nexport { def"
  },
  {
    "path": "src/foods/persistence/FoodsListModal/Content.tsx",
    "chars": 1821,
    "preview": "import {\n  ModalContent,\n  ModalHeader,\n  ModalCloseButton,\n  ModalFooter,\n  ModalBody,\n  Button,\n  HStack,\n} from '@cha"
  },
  {
    "path": "src/foods/persistence/FoodsListModal/index.tsx",
    "chars": 1536,
    "preview": "import { Modal, ModalOverlay, useToast } from '@chakra-ui/react'\nimport { Food, FoodsStoreProvider, useFoods, useFoodsAc"
  },
  {
    "path": "src/foods/persistence/MissingFoodsModal.tsx",
    "chars": 1243,
    "preview": "import {\n  Modal,\n  ModalOverlay,\n  ModalContent,\n  ModalHeader,\n  ModalFooter,\n  ModalBody,\n  ModalCloseButton,\n  Butto"
  },
  {
    "path": "src/foods/persistence/index.ts",
    "chars": 273,
    "preview": "export { default as MissingFoodsModal } from './MissingFoodsModal'\nexport { default as useImportFoods } from './useImpor"
  },
  {
    "path": "src/foods/persistence/loadFoods.ts",
    "chars": 295,
    "preview": "import { builtInFoods } from 'foods'\n\nfunction loadFoods() {\n  const userFoodsString = localStorage.getItem('userFoods')"
  },
  {
    "path": "src/foods/persistence/useImportFoods.ts",
    "chars": 858,
    "preview": "import { UseDisclosureReturn } from '@chakra-ui/hooks'\nimport { Food } from 'foods'\nimport { selectFile, readFile, useFi"
  },
  {
    "path": "src/foods/types.ts",
    "chars": 351,
    "preview": "import { NutritionData } from 'stats'\n\ntype FoodId = string | number\n\ntype FoodVolume = {\n  portionId: string\n  weightIn"
  },
  {
    "path": "src/foods/useFoodsStore.ts",
    "chars": 1848,
    "preview": "import { Food, FoodId } from 'foods'\nimport { useState, useCallback, useMemo } from 'react'\nimport produce from 'immer'\n"
  },
  {
    "path": "src/foods-categories/FoodCategoriesSelect.tsx",
    "chars": 716,
    "preview": "import { SelectProps, Select } from '@chakra-ui/select'\nimport foodCategories from './categories.json'\nimport { Forwarde"
  },
  {
    "path": "src/foods-categories/categories.json",
    "chars": 765,
    "preview": "[\n    { \"name\": \"Poultry\", \"id\": 100 },\n    { \"name\": \"Beef\", \"id\": 200 },\n    { \"name\": \"Pork\", \"id\": 300 },\n    { \"nam"
  },
  {
    "path": "src/foods-categories/index.ts",
    "chars": 159,
    "preview": "export { default as FoodCategoriesSelect } from './FoodCategoriesSelect'\nexport * from './types'\nexport { default as foo"
  },
  {
    "path": "src/foods-categories/types.ts",
    "chars": 98,
    "preview": "type FoodCategory = {\n  id: number\n  name: string\n  color: string\n}\n\nexport type { FoodCategory }\n"
  },
  {
    "path": "src/foods-filters/FoodsFilterPopoverOrModal/Content.tsx",
    "chars": 1299,
    "preview": "import { VStack, Checkbox } from '@chakra-ui/react'\nimport { FoodCategoriesSelect } from 'foods-categories'\nimport { use"
  },
  {
    "path": "src/foods-filters/FoodsFilterPopoverOrModal/Footer.tsx",
    "chars": 744,
    "preview": "import { HStack, Button } from '@chakra-ui/react'\nimport {\n  nonQueryChangesCount,\n  useFoodsFilter,\n  useFoodsFilterAct"
  },
  {
    "path": "src/foods-filters/FoodsFilterPopoverOrModal/Modal.tsx",
    "chars": 817,
    "preview": "import {\n  Modal as ModalBase,\n  ModalOverlay,\n  ModalContent,\n  ModalHeader,\n  ModalFooter,\n  ModalBody,\n  ModalCloseBu"
  },
  {
    "path": "src/foods-filters/FoodsFilterPopoverOrModal/Popover.tsx",
    "chars": 1103,
    "preview": "import {\n  Popover as PopoverBase,\n  PopoverTrigger,\n  PopoverContent,\n  PopoverHeader,\n  PopoverBody,\n  PopoverFooter,\n"
  },
  {
    "path": "src/foods-filters/FoodsFilterPopoverOrModal/Trigger.tsx",
    "chars": 847,
    "preview": "import { Badge } from 'general'\nimport { IconButton } from '@chakra-ui/react'\nimport { Filter } from 'react-feather'\nimp"
  },
  {
    "path": "src/foods-filters/FoodsFilterPopoverOrModal/index.tsx",
    "chars": 626,
    "preview": "import { useScreenSize, ScreenSize } from 'general'\nimport Modal from './Modal'\nimport Trigger from './Trigger'\nimport P"
  },
  {
    "path": "src/foods-filters/foodsFilter.ts",
    "chars": 570,
    "preview": "const DEFAULT_FILTER: FoodsFilter = {\n  query: '',\n  onlyFoodsAddedByUser: false,\n  categoryId: 0,\n}\n\ntype FoodsFilter ="
  },
  {
    "path": "src/foods-filters/index.ts",
    "chars": 283,
    "preview": "export { default as useFilterFoods } from './useFilterFoods'\nexport * from './foodsFilter'\nexport { default as useFoodsF"
  },
  {
    "path": "src/foods-filters/persistence/index.ts",
    "chars": 63,
    "preview": "export { default as loadFoodsFilter } from './loadFoodsFilter'\n"
  },
  {
    "path": "src/foods-filters/persistence/loadFoodsFilter.ts",
    "chars": 337,
    "preview": "import { DEFAULT_FILTER, FoodsFilter } from 'foods-filters'\n\nfunction loadFoodsFilter() {\n  const foodsFilterString = lo"
  },
  {
    "path": "src/foods-filters/useFilterFoods.ts",
    "chars": 1281,
    "preview": "import Fuse from 'fuse.js'\nimport { useMemo } from 'react'\nimport { Food } from 'foods'\nimport { FoodsFilter } from './f"
  },
  {
    "path": "src/foods-filters/useFoodsFilterStore.ts",
    "chars": 1480,
    "preview": "import { useCallback, useState } from 'react'\nimport { FoodsFilter, DEFAULT_FILTER } from './foodsFilter'\nimport { makeS"
  },
  {
    "path": "src/form/duplicate.ts",
    "chars": 366,
    "preview": "import { deepCopy } from 'general'\nimport { v4 as uuidv4 } from 'uuid'\nimport { Form } from './types'\n\nfunction duplicat"
  },
  {
    "path": "src/form/index.ts",
    "chars": 201,
    "preview": "export { default as duplicate } from './duplicate'\nexport * from './names'\nexport { default as useFormError } from './us"
  },
  {
    "path": "src/form/names.ts",
    "chars": 544,
    "preview": "import { Form } from './types'\n\nfunction getDuplicatedName(index: number, forms: Form[]) {\n  const form = forms[index]\n "
  },
  {
    "path": "src/form/types.ts",
    "chars": 71,
    "preview": "type Form = {\n  fieldId: string\n  name: string\n}\n\nexport type { Form }\n"
  },
  {
    "path": "src/form/useFormError.ts",
    "chars": 413,
    "preview": "import { useFormContext } from 'react-hook-form'\n\nfunction useFormError(name: string) {\n  const { formState } = useFormC"
  },
  {
    "path": "src/form/useSelectInputText.ts",
    "chars": 301,
    "preview": "import { RefObject, useEffect } from 'react'\n\nfunction useSelectInputText(inputRef: RefObject<HTMLInputElement>) {\n  use"
  },
  {
    "path": "src/general/Badge.tsx",
    "chars": 1102,
    "preview": "import { ForwardedRef, ReactNode } from 'react'\nimport { Box, BoxProps, Center, Fade, Text } from '@chakra-ui/react'\nimp"
  },
  {
    "path": "src/general/ContextMenuFlex.tsx",
    "chars": 1538,
    "preview": "import { Flex, FlexProps } from '@chakra-ui/react'\nimport { ForwardedRef, ReactElement, forwardRef } from 'react'\nimport"
  },
  {
    "path": "src/general/HFadeScroll/FadeBox.tsx",
    "chars": 958,
    "preview": "import { ReactNode } from 'react'\nimport { Box } from '@chakra-ui/react'\n\ntype ShadowProps = {\n  hasStartFade: boolean\n "
  },
  {
    "path": "src/general/HFadeScroll/ScrollContainer.tsx",
    "chars": 251,
    "preview": "import { Flex } from '@chakra-ui/react'\nimport styled from '@emotion/styled'\n\nconst ScrollContainer = styled(Flex)`\n  -m"
  },
  {
    "path": "src/general/HFadeScroll/index.tsx",
    "chars": 2489,
    "preview": "import {\n  ForwardedRef,\n  ReactNode,\n  forwardRef,\n  useRef,\n  useEffect,\n  useState,\n} from 'react'\nimport ScrollConta"
  },
  {
    "path": "src/general/Loader.tsx",
    "chars": 431,
    "preview": "import { Spinner, Text, Center, Flex } from '@chakra-ui/react'\n\ntype Props = {\n  label: string\n}\n\nfunction Loader({ labe"
  },
  {
    "path": "src/general/Menu.tsx",
    "chars": 548,
    "preview": "import styled from '@emotion/styled'\nimport {\n  Menu as MenuBase,\n  MenuButton,\n  MenuItem,\n  ControlledMenu as Controll"
  },
  {
    "path": "src/general/MenuOrDrawer/Drawer/getDrawerButtons.tsx",
    "chars": 993,
    "preview": "import { cloneElement, ReactElement, Children } from 'react'\nimport { Button, Divider } from '@chakra-ui/react'\nimport M"
  },
  {
    "path": "src/general/MenuOrDrawer/Drawer/index.tsx",
    "chars": 919,
    "preview": "import {\n  Drawer as DrawerBase,\n  DrawerBody,\n  DrawerHeader,\n  DrawerOverlay,\n  DrawerContent,\n  DrawerCloseButton,\n  "
  },
  {
    "path": "src/general/MenuOrDrawer/Menu/getMenuItems.tsx",
    "chars": 747,
    "preview": "import {\n  MenuItem,\n  MenuOrDrawerItem,\n  MenuOrDrawerSeparator,\n  MenuDivider,\n} from 'general'\nimport { cloneElement,"
  },
  {
    "path": "src/general/MenuOrDrawer/Menu/index.tsx",
    "chars": 650,
    "preview": "import { ButtonProps } from '@chakra-ui/react'\nimport { Menu as MenuBase, MenuHeader } from 'general'\nimport Trigger fro"
  },
  {
    "path": "src/general/MenuOrDrawer/MenuOrDrawerItem.tsx",
    "chars": 231,
    "preview": "import { ReactElement, ReactNode } from 'react'\n\ntype Props = {\n  onClick?: () => void\n  children: ReactNode\n  icon: Rea"
  },
  {
    "path": "src/general/MenuOrDrawer/MenuOrDrawerSeparator.tsx",
    "chars": 89,
    "preview": "function MenuOrDrawerSeparator() {\n  return null\n}\n\nexport default MenuOrDrawerSeparator\n"
  },
  {
    "path": "src/general/MenuOrDrawer/Trigger.tsx",
    "chars": 616,
    "preview": "import { IconButton, ButtonProps } from '@chakra-ui/react'\nimport { MoreHorizontal } from 'react-feather'\nimport { Forwa"
  },
  {
    "path": "src/general/MenuOrDrawer/index.tsx",
    "chars": 1099,
    "preview": "import { useScreenSize, ScreenSize } from 'general'\nimport Drawer from './Drawer'\nimport Trigger from './Trigger'\nimport"
  },
  {
    "path": "src/general/ResponsiveButton.tsx",
    "chars": 589,
    "preview": "import { Button, ButtonProps } from '@chakra-ui/react'\nimport { useScreenSize, ScreenSize } from 'general'\nimport { Forw"
  },
  {
    "path": "src/general/ResponsiveIconButton.tsx",
    "chars": 637,
    "preview": "import { IconButtonProps, IconButton } from '@chakra-ui/react'\nimport { useScreenSize, ScreenSize } from 'general'\nimpor"
  },
  {
    "path": "src/general/RightAligned.tsx",
    "chars": 425,
    "preview": "import { Flex, FlexProps } from '@chakra-ui/react'\nimport { ReactNode } from 'react'\n\ntype Props = {\n  children: ReactNo"
  },
  {
    "path": "src/general/ScreenSizeProvider/context.ts",
    "chars": 439,
    "preview": "import { createContext, useContext } from 'react'\n\nenum ScreenSize {\n  Base = 0,\n  Small,\n  Medium,\n  Large,\n  ExtraLarg"
  },
  {
    "path": "src/general/ScreenSizeProvider/index.tsx",
    "chars": 666,
    "preview": "import { useBreakpointValue } from '@chakra-ui/media-query'\nimport { ReactNode } from 'react'\nimport { ScreenSizeContext"
  },
  {
    "path": "src/general/Tooltip.tsx",
    "chars": 1114,
    "preview": "import { ReactElement, useState, cloneElement, useRef, ReactNode } from 'react'\nimport { Tooltip as TooltipBase } from '"
  },
  {
    "path": "src/general/TooltipCommandLabel.tsx",
    "chars": 354,
    "preview": "import { Text } from '@chakra-ui/react'\n\ntype Props = {\n  command: string\n  kbdCombo: string\n}\n\nfunction TooltipCommandL"
  },
  {
    "path": "src/general/deepCopy.ts",
    "chars": 149,
    "preview": "const deepCopy = (value: any, replacer?: (key: string, value: any) => any) =>\n  JSON.parse(JSON.stringify(value, replace"
  },
  {
    "path": "src/general/getCtrlKeyName.ts",
    "chars": 186,
    "preview": "function isMac() {\n  return navigator.platform.indexOf('Mac') > -1\n}\n\nfunction getCtrlKeyName() {\n  if (isMac()) {\n    r"
  },
  {
    "path": "src/general/index.ts",
    "chars": 1333,
    "preview": "export { default as HFadeScroll } from './HFadeScroll'\nexport * from './HFadeScroll'\nexport { default as Badge } from '."
  },
  {
    "path": "src/general/minDelay.ts",
    "chars": 366,
    "preview": "function minDelay(startDate: Date, minDelayInMs = 500) {\n  return new Promise(resolve => {\n    const endDate = new Date("
  },
  {
    "path": "src/general/stores.tsx",
    "chars": 2129,
    "preview": "import {\n  Context,\n  useContext,\n  createContext,\n  ReactNode,\n  useMemo,\n  Provider,\n} from 'react'\n\nfunction guard(va"
  },
  {
    "path": "src/general/useElementHeight.ts",
    "chars": 417,
    "preview": "import { useRef, useState } from 'react'\nimport useResizeObserver from '@react-hook/resize-observer'\n\nfunction useElemen"
  },
  {
    "path": "src/general/useOneTimeCheckStore.ts",
    "chars": 1026,
    "preview": "import { makeStoreProvider, useCallbacksMemo } from 'general'\nimport { useRef, useCallback } from 'react'\n\ntype KeysMap "
  },
  {
    "path": "src/general/useRunIfNotUnmounted.ts",
    "chars": 423,
    "preview": "import { useCallback, useEffect, useRef } from 'react'\n\nfunction useRunIfNotUnmounted() {\n  const isUnmountedRef = useRe"
  },
  {
    "path": "src/general/useSameOrPreviousValue.ts",
    "chars": 255,
    "preview": "import { useEffect, useRef } from 'react'\n\nfunction useSameOrPreviousValue<T>(value: T) {\n  const previous = useRef(valu"
  },
  {
    "path": "src/general/useSelection.ts",
    "chars": 1282,
    "preview": "import { useState } from 'react'\n\ntype Id = number | string\ntype Item = { id: Id }\ntype SelectionMap = { [id in Id]: boo"
  },
  {
    "path": "src/icons/CalendarPlus.tsx",
    "chars": 1259,
    "preview": "import { chakra } from '@chakra-ui/react'\n\nfunction CalendarPlus({ size = 24, ...rest }) {\n  return (\n    <svg width={si"
  },
  {
    "path": "src/icons/index.ts",
    "chars": 57,
    "preview": "export { default as CalendarPlus } from './CalendarPlus'\n"
  },
  {
    "path": "src/index.tsx",
    "chars": 472,
    "preview": "import React from 'react'\nimport ReactDOM from 'react-dom'\nimport App from './App'\nimport reportWebVitals from './report"
  },
  {
    "path": "src/ingredients/IngredientsList/EmptyList.tsx",
    "chars": 536,
    "preview": "import { Flex, Text, Button } from '@chakra-ui/react'\n\ntype Props = {\n  onAddIngredients: () => void\n}\n\nfunction EmptyLi"
  },
  {
    "path": "src/ingredients/IngredientsList/IngredientItem/MenuOrDrawer.tsx",
    "chars": 426,
    "preview": "import { RightAligned } from 'layout'\nimport { MenuOrDrawer as MenuOrDrawerBase } from 'general'\nimport { ReactElement }"
  },
  {
    "path": "src/ingredients/IngredientsList/IngredientItem/MissingStatsLayout.tsx",
    "chars": 665,
    "preview": "import { Flex, Text, Button } from '@chakra-ui/react'\nimport { Trash2 } from 'react-feather'\n\ntype Props = {\n  onRemoveR"
  },
  {
    "path": "src/ingredients/IngredientsList/IngredientItem/Notes.tsx",
    "chars": 741,
    "preview": "import PresenceAnimation from './PresenceAnimation'\nimport { Box, Text } from '@chakra-ui/react'\nimport { NotesEvents } "
  },
  {
    "path": "src/ingredients/IngredientsList/IngredientItem/PresenceAnimation.tsx",
    "chars": 856,
    "preview": "import { ReactNode } from 'react'\nimport { motion } from 'framer-motion'\n\ntype Props = {\n  children: ReactNode\n  shouldA"
  },
  {
    "path": "src/ingredients/IngredientsList/IngredientItem/StatsLayout.tsx",
    "chars": 2164,
    "preview": "import { IngredientForm } from 'ingredients'\nimport { Food, FoodInfo } from 'foods'\nimport { StatsLayout as StatsLayoutB"
  },
  {
    "path": "src/ingredients/IngredientsList/IngredientItem/getMenuOrDrawerItems.tsx",
    "chars": 1113,
    "preview": "import { chakra } from '@chakra-ui/react'\nimport { IngredientForm } from 'ingredients'\nimport { Trash2, Info, Edit } fro"
  },
  {
    "path": "src/ingredients/IngredientsList/IngredientItem/index.tsx",
    "chars": 4898,
    "preview": "import { IngredientForm } from 'ingredients'\nimport { Draggable } from 'react-beautiful-dnd'\nimport { memo } from 'react"
  },
  {
    "path": "src/ingredients/IngredientsList/IngredientItem/useIngredientsEvents.ts",
    "chars": 2249,
    "preview": "import { useDietFormActions } from 'diets'\nimport { useOneTimeCheckActions } from 'general'\nimport { ChangeEvent, useSta"
  },
  {
    "path": "src/ingredients/IngredientsList/IngredientItem/useNotesEvents.tsx",
    "chars": 1497,
    "preview": "import { useDietFormActions } from 'diets'\nimport { useOneTimeCheckActions } from 'general'\nimport { IngredientForm } fr"
  },
  {
    "path": "src/ingredients/IngredientsList/index.tsx",
    "chars": 2370,
    "preview": "import { Box, Fade } from '@chakra-ui/react'\nimport IngredientItem from './IngredientItem'\nimport { Droppable } from 're"
  },
  {
    "path": "src/ingredients/PdfIngredientsList/PdfIngredientItem/FoodName.tsx",
    "chars": 1845,
    "preview": "import { Text, StyleSheet, View, Link } from '@react-pdf/renderer'\nimport { Food, FoodId } from 'foods'\nimport { Ingredi"
  },
  {
    "path": "src/ingredients/PdfIngredientsList/PdfIngredientItem/index.tsx",
    "chars": 1484,
    "preview": "import { StyleSheet, View } from '@react-pdf/renderer'\nimport { Food, FoodId } from 'foods'\nimport { IngredientForm } fr"
  },
  {
    "path": "src/ingredients/PdfIngredientsList/index.tsx",
    "chars": 1715,
    "preview": "import { View, Text, StyleSheet } from '@react-pdf/renderer'\nimport { Food, FoodId } from 'foods'\nimport { IngredientFor"
  },
  {
    "path": "src/ingredients/getIngredient.ts",
    "chars": 546,
    "preview": "import { DEFAULT_SERVING_SIZE_IN_GRAMS, Food } from 'foods'\nimport { Ingredient } from './types'\n\nfunction getIngredient"
  },
  {
    "path": "src/ingredients/index.ts",
    "chars": 400,
    "preview": "export { default as IngredientsList } from './IngredientsList'\nexport * from './ingredientForm'\nexport { default as useI"
  },
  {
    "path": "src/ingredients/ingredientForm.ts",
    "chars": 739,
    "preview": "import { Ingredient } from './types'\nimport { v4 as uuidv4 } from 'uuid'\nimport { FoodId } from 'foods'\nimport { formatA"
  },
  {
    "path": "src/ingredients/types.ts",
    "chars": 136,
    "preview": "import { FoodId } from 'foods'\n\ntype Ingredient = {\n  foodId: FoodId\n  amount: number\n  portionId: string\n}\n\nexport type"
  },
  {
    "path": "src/ingredients/useGetIngredientFormStatsTree.ts",
    "chars": 1497,
    "preview": "import { useFoods } from 'foods'\nimport { IngredientForm } from './ingredientForm'\nimport { StatsTree, objectFromNutriti"
  },
  {
    "path": "src/ingredients/useIngredientsFormsActions.ts",
    "chars": 4120,
    "preview": "import { useCallback, SetStateAction } from 'react'\nimport { DietForm } from 'diets'\nimport produce from 'immer'\nimport "
  },
  {
    "path": "src/layout/MainLayout.tsx",
    "chars": 1101,
    "preview": "import {\n  createContext,\n  ReactElement,\n  ReactNode,\n  RefObject,\n  useRef,\n} from 'react'\nimport { Box } from '@chakr"
  },
  {
    "path": "src/layout/Page/ElementContainer.tsx",
    "chars": 527,
    "preview": "import { Box, BoxProps } from '@chakra-ui/react'\nimport { ForwardedRef, ReactNode, forwardRef } from 'react'\n\ntype Props"
  },
  {
    "path": "src/layout/Page/PageBody.tsx",
    "chars": 395,
    "preview": "import { Flex } from '@chakra-ui/react'\nimport { ReactNode } from 'react'\nimport ElementContainer from './ElementContain"
  },
  {
    "path": "src/layout/Page/PageFooter.tsx",
    "chars": 637,
    "preview": "import { Box } from '@chakra-ui/react'\nimport { ReactNode, RefObject } from 'react'\nimport ElementContainer from './Elem"
  },
  {
    "path": "src/layout/Page/PageHeader.tsx",
    "chars": 704,
    "preview": "import { Box, Flex } from '@chakra-ui/react'\nimport { ForwardedRef, forwardRef, ReactNode } from 'react'\nimport ElementC"
  },
  {
    "path": "src/layout/Page/index.tsx",
    "chars": 441,
    "preview": "import { Box } from '@chakra-ui/react'\nimport { ReactNode } from 'react'\n\ntype Props = {\n  children: ReactNode\n}\n\nfuncti"
  },
  {
    "path": "src/layout/RightAligned.tsx",
    "chars": 425,
    "preview": "import { Flex, FlexProps } from '@chakra-ui/react'\nimport { ReactNode } from 'react'\n\ntype Props = {\n  children: ReactNo"
  },
  {
    "path": "src/layout/index.tsx",
    "chars": 203,
    "preview": "export { default as Page } from './Page'\nexport * from './Page'\nexport { default as MainLayout } from './MainLayout'\nexp"
  },
  {
    "path": "src/layout/useHasSideNavigation.ts",
    "chars": 214,
    "preview": "// import { useScreenSize } from 'general'\n\nfunction useHasSideNavigation() {\n  /*const screenSize = useScreenSize()\n  r"
  },
  {
    "path": "src/meals/MealsList/EmptyList.tsx",
    "chars": 1086,
    "preview": "import { Text, Center, chakra, Button, VStack } from '@chakra-ui/react'\nimport { Plus } from 'react-feather'\n\nconst Plus"
  },
  {
    "path": "src/meals/MealsList/MealItem/Header/MenuOrDrawer.tsx",
    "chars": 530,
    "preview": "import { RightAligned } from 'layout'\nimport { MenuOrDrawer as MenuOrDrawerBase } from 'general'\nimport { ReactElement }"
  },
  {
    "path": "src/meals/MealsList/MealItem/Header/Name.tsx",
    "chars": 1106,
    "preview": "import { BoxProps, Input, Flex } from '@chakra-ui/react'\nimport { useDietFormActions } from 'diets'\nimport { MealForm } "
  },
  {
    "path": "src/meals/MealsList/MealItem/Header/getMenuOrDrawerItems.tsx",
    "chars": 1423,
    "preview": "import { chakra } from '@chakra-ui/react'\nimport { Plus, Trash2, Copy, Edit } from 'react-feather'\nimport { MealForm } f"
  },
  {
    "path": "src/meals/MealsList/MealItem/Header/index.tsx",
    "chars": 2143,
    "preview": "import { BoxProps } from '@chakra-ui/react'\nimport { MealForm } from 'meals'\nimport { Stat, StatsLayout } from 'stats'\ni"
  }
]

// ... and 140 more files (download for full content)

About this extraction

This page contains the full source code of the vangelov/calories-in GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 340 files (591.2 KB), approximately 207.8k tokens, and a symbol index with 559 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!