diff --git a/api/controllers/item.js b/api/controllers/item.js index 8933258..221acc3 100644 --- a/api/controllers/item.js +++ b/api/controllers/item.js @@ -89,9 +89,9 @@ router.get('', async (req, res) => { }); // create or retrieve category -async function fetchCategory(categoryId) { +async function fetchCategory(categoryId, excludeWeight) { let newCat = null; - const category = { name: categoryId, level: 'USER' }; + const category = { name: categoryId, level: 'USER', exclude_weight: excludeWeight }; try { newCat = await models.Category.create(category); } catch (err) { @@ -106,12 +106,12 @@ async function fetchCategory(categoryId) { // Create router.post('', authenticate, async (req, res) => { - const { newCategory } = req.body; + const { newCategory, excludeWeight } = req.body; const { payload } = itemPayload(req.body); let newCat = null; if (newCategory) { - const { category, err } = await fetchCategory(payload.categoryId); + const { category, err } = await fetchCategory(payload.categoryId, excludeWeight); if (err) { return res.status(400).json(err); } @@ -132,7 +132,8 @@ router.put('', authenticate, async (req, res) => { let newCat = null; if (newCategory) { - const { category, err } = await fetchCategory(payload.categoryId); + // hardcoding false here while I figure out how to do update + const { category, err } = await fetchCategory(payload.categoryId, false); if (err) { return res.status(400).json(err); } @@ -162,4 +163,4 @@ router.post('/delete', authenticate, (req, res) => { }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/frontend/src/app/Inventory/Table.tsx b/frontend/src/app/Inventory/Table.tsx index 51bded9..a9095cc 100644 --- a/frontend/src/app/Inventory/Table.tsx +++ b/frontend/src/app/Inventory/Table.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { Icon, Tooltip } from 'antd'; import { Category } from "types/category"; import { Item as ItemType } from 'types/item'; @@ -6,6 +7,7 @@ import { Update } from "types/api/item"; import Item from './Item'; import ExpandablePanel from "../components/ExpandablePanel"; +import { helpIconStyles } from "styles/common"; interface TableProps { category: Category; @@ -22,15 +24,25 @@ const Table: React.FC = ({ category, items, updateItem, fetchItems } fetchItems={fetchItems}/> ); - const Header =

{category.name}

; + function setHeader(category: Category): JSX.Element { + if (category.exclude_weight) { + return

{category.name} + + + +

; + } + return

{category.name}

+ } return (
- + {itemList}
) }; -export default Table; \ No newline at end of file +export default Table; diff --git a/frontend/src/app/Pack/Items.tsx b/frontend/src/app/Pack/Items.tsx index 0ab7618..3cd9e7c 100644 --- a/frontend/src/app/Pack/Items.tsx +++ b/frontend/src/app/Pack/Items.tsx @@ -10,6 +10,7 @@ import { getItemWeight, getWeightByCategory } from "lib/utils/weight"; import { getCategories } from "lib/utils/categories"; import { ItemList, ItemName, ItemNotes, ItemDescription, ItemQuantity, ItemWeight, CategorySection } from "./styles"; +import { helpIconStyles } from "styles/common"; import ExpandablePanel from 'app/components/ExpandablePanel'; interface ItemsProps { @@ -42,7 +43,14 @@ const Items: React.FC = ({ items, unit }) => { const Header = ( <> -

{cat.name}

+

+ {cat.name} + {cat.exclude_weight && + + + } +

{catWeight!.total.label} {unit} ) @@ -99,4 +107,4 @@ const Items: React.FC = ({ items, unit }) => { }; -export default Items; \ No newline at end of file +export default Items; diff --git a/frontend/src/app/components/CategoryTable/index.tsx b/frontend/src/app/components/CategoryTable/index.tsx index 6ee1b44..b8ec323 100644 --- a/frontend/src/app/components/CategoryTable/index.tsx +++ b/frontend/src/app/components/CategoryTable/index.tsx @@ -25,8 +25,10 @@ const CategoryChart: React.FC = ({ data, unit }) => { const totalWeight = data.reduce((acc: number, cur: CategoryItemSpecs) => acc + cur.total.value, 0); const excludedWeight = data.reduce((acc: number, cur: CategoryItemSpecs) => acc + cur.excluded.value, 0); const consumables = data.find(c => c.name === 'Consumables'); + const customExcludedCategories = data.find(c => c.level === 'USER' && c.exclude_weight === true); + const customExcludedWeight = customExcludedCategories ? customExcludedCategories.total.value : 0; const consumablesWeight = consumables ? consumables.total.value : 0; - const wornWeight = excludedWeight - consumablesWeight; + const wornWeight = excludedWeight - consumablesWeight - customExcludedWeight; const baseWeight = totalWeight - excludedWeight; return ( @@ -47,6 +49,12 @@ const CategoryChart: React.FC = ({ data, unit }) => {
Worn
{wornWeight.toFixed(2)} {unit}
+ {customExcludedCategories && + +
Other Excluded
+
{customExcludedWeight.toFixed(2)} {unit}
+
+ }
Base Weight
{baseWeight.toFixed(2)} {unit}
@@ -55,4 +63,4 @@ const CategoryChart: React.FC = ({ data, unit }) => { ) }; -export default React.memo(CategoryChart); \ No newline at end of file +export default React.memo(CategoryChart); diff --git a/frontend/src/app/components/FormFields/SwitchInput.tsx b/frontend/src/app/components/FormFields/SwitchInput.tsx index bb04b1a..cb1909b 100644 --- a/frontend/src/app/components/FormFields/SwitchInput.tsx +++ b/frontend/src/app/components/FormFields/SwitchInput.tsx @@ -15,13 +15,13 @@ const SwitchInput: React.FC = ({ checked, checkedText, uncheckedTex return ( ); }; -export default SwitchInput; \ No newline at end of file +export default SwitchInput; diff --git a/frontend/src/app/components/FormFields/index.js b/frontend/src/app/components/FormFields/index.js index 0b03d77..087591d 100644 --- a/frontend/src/app/components/FormFields/index.js +++ b/frontend/src/app/components/FormFields/index.js @@ -2,5 +2,6 @@ export { default as Input } from './Input'; export { default as Textarea } from './Textarea'; export { default as Select } from './Select' export { default as SelectCreatable } from './SelectCreatable' +export { default as SwitchInput } from './SwitchInput' export { Option } from './types'; -export { Label } from './styles'; \ No newline at end of file +export { Label } from './styles'; diff --git a/frontend/src/app/components/ItemForm/ItemForm.tsx b/frontend/src/app/components/ItemForm/ItemForm.tsx index 8b5cbf4..12363b7 100644 --- a/frontend/src/app/components/ItemForm/ItemForm.tsx +++ b/frontend/src/app/components/ItemForm/ItemForm.tsx @@ -3,7 +3,7 @@ import * as Yup from 'yup'; import FileDownload from 'js-file-download'; import { Formik, FormikProps } from "formik"; import { Row, Col, Button } from "antd"; -import { Input, Select, SelectCreatable, Option } from '../FormFields'; +import { Input, Select, SelectCreatable, Option, SwitchInput } from "../FormFields"; import { AppContext } from 'AppContext'; import { CreateItem, ItemConstants } from "types/item"; @@ -11,7 +11,7 @@ import { FormSpecs } from "./types"; import withApi from 'app/components/higher-order/with-api'; import { categoryOptions, weightUnitOptions } from "lib/utils/form"; -import { categorySelectValue } from "lib/utils/categories"; +import { categorySelectValue, categoryCheckIfNew } from "lib/utils/categories"; import UploadModal from 'app/Inventory/UploadModal'; import { alertError, alertSuccess } from "../Notifications"; @@ -42,6 +42,7 @@ const ItemForm: React.FC = ({ createItem, exportCsv, onSubmit } price: undefined, product_url: '', newCategory: false, + excludeWeight: false, notes: '' }} validationSchema={Yup.object().shape({ @@ -70,6 +71,7 @@ const ItemForm: React.FC = ({ createItem, exportCsv, onSubmit } const wasSubmitted = submitCount > 0; const weightUnit = values.weight_unit; const categoryValue = categorySelectValue(app.categories, values.categoryId); + let isNewCategory = categoryCheckIfNew(app.categories, values.categoryId); return ( @@ -88,7 +90,7 @@ const ItemForm: React.FC = ({ createItem, exportCsv, onSubmit } value={categoryValue || null} onChange={(option: Option) => { const value = option ? option.value : undefined; - const isNewCategory = Boolean(option && option.__isNew__); + isNewCategory = Boolean(option && option.__isNew__); setFieldValue('categoryId', value); setFieldValue('newCategory', isNewCategory); }} @@ -96,6 +98,15 @@ const ItemForm: React.FC = ({ createItem, exportCsv, onSubmit } errorMsg={errors.categoryId} clearable={true} /> + {isNewCategory && + setFieldValue('excludeWeight', v)}/> + } = ({ items, removeItem, updateItem, wei const catWeight = weightByCategory.find(c => c.id === cat.id); const Header = ( <> -

{cat.name}

+

+ {cat.name} + {cat.exclude_weight && + + + } +

{catWeight!.total.label} {weightUnit} ); @@ -71,4 +80,4 @@ const PackItems: React.FC = ({ items, removeItem, updateItem, wei ) }; -export default PackItems; \ No newline at end of file +export default PackItems; diff --git a/frontend/src/lib/utils/categories.ts b/frontend/src/lib/utils/categories.ts index a65bdeb..f47014f 100644 --- a/frontend/src/lib/utils/categories.ts +++ b/frontend/src/lib/utils/categories.ts @@ -29,4 +29,9 @@ export const categorySelectValue = (categories: Category[], value: number | stri value: currentCategory ? currentCategory.id : value, label: currentCategory ? currentCategory.name : value.toString() }; -}; \ No newline at end of file +}; + +export const categoryCheckIfNew = (categories: Category[], value: number | string | undefined): boolean => { + if (!value) return false; + return categories.find(cat => cat.id === value) ? false : true; +}; diff --git a/frontend/src/types/item.ts b/frontend/src/types/item.ts index c9076e6..9fd861a 100644 --- a/frontend/src/types/item.ts +++ b/frontend/src/types/item.ts @@ -22,6 +22,7 @@ export interface Item extends BaseItem { export type CreateItem = Omit & { categoryId?: number; newCategory: boolean; + excludeWeight: boolean; } export type UpdateItem = Omit & {