Skip to content

Commit 5c92eae

Browse files
authored
Merge pull request #39 from Callisto13/item-notes
Add Notes field to Inventory Items
2 parents b80a187 + 3b1d4fc commit 5c92eae

10 files changed

Lines changed: 89 additions & 19 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
'use strict';
2+
3+
module.exports = {
4+
up: (queryInterface, Sequelize) => {
5+
return queryInterface.addColumn('items', 'notes', {
6+
type: Sequelize.STRING(500),
7+
defaultValue: ''
8+
}
9+
})
10+
},
11+
12+
down: (queryInterface, Sequelize) => {
13+
return queryInterface.removeColumn('items', 'notes'),
14+
}
15+
};

api/models/item.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ const item = (sequelize, DataTypes) => {
6666
allowNull: false,
6767
defaultValue: false
6868
},
69+
notes: {
70+
type: DataTypes.STRING(500)
71+
},
6972
});
7073

7174
Item.associate = models => {
@@ -88,4 +91,4 @@ const item = (sequelize, DataTypes) => {
8891
return Item;
8992
};
9093

91-
export default item;
94+
export default item;

frontend/src/app/Inventory/Item.tsx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from 'react';
22
import { isEqual } from 'lodash';
3+
import { Icon, Tooltip } from 'antd';
34

45
import { Item as ItemType } from "types/item";
56
import { Update } from "types/api/item";
@@ -8,11 +9,12 @@ import { AppContext } from "AppContext";
89
import { Input, Option, SelectCreatable, Select } from "app/components/FormFields";
910
import { alertSuccess, alertWarn } from "app/components/Notifications";
1011
import EditItem from "app/components/EditItem";
12+
import { DotIcon } from "app/components/Icons";
1113

1214
import { categoryOptions, weightUnitOptions } from "lib/utils/form";
1315
import { categorySelectValue } from "lib/utils/categories";
1416

15-
import { Grid, PairGrid, inlineStyles } from "styles/grid";
17+
import { Grid, PairGrid, NotesIndicator, inlineStyles } from "styles/grid";
1618

1719
interface ItemProps {
1820
item: ItemType;
@@ -55,24 +57,32 @@ const Item: React.FC<ItemProps> = ({item, updateItem, fetchItems}) => {
5557
.catch(() => alertWarn({message: 'Error updating item.'}));
5658
}
5759

60+
5861
const categoryValue = categorySelectValue(app.categories, copy.categoryId);
59-
const {product_name, name, weight_unit, weight, price} = copy;
62+
const {product_name, name, weight_unit, weight, price, notes} = copy;
63+
const hasNotes = notes !== "";
6064
return (
6165
<>
6266
<Grid>
67+
<div className="align-center">
68+
<NotesIndicator className={hasNotes ? 'active' : ''}>
69+
<Tooltip title={hasNotes ? notes : "No notes on this item"}
70+
mouseEnterDelay={.1} placement="right">
71+
<Icon component={DotIcon}/>
72+
</Tooltip>
73+
</NotesIndicator>
74+
</div>
6375
<div>
6476
<Input value={name || ''}
6577
onChange={v => update('name', v)}
6678
onBlur={handleSave}
6779
style={inlineStyles}/>
6880
</div>
69-
<div>
7081
<Input value={product_name || ''}
7182
placeholder="product name"
7283
onChange={v => update('product_name', v)}
7384
onBlur={handleSave}
7485
style={inlineStyles}/>
75-
</div>
7686
<div>
7787
<SelectCreatable
7888
options={categoryOptions(app.categories)}
@@ -130,4 +140,4 @@ const Item: React.FC<ItemProps> = ({item, updateItem, fetchItems}) => {
130140
)
131141
};
132142

133-
export default React.memo(Item);
143+
export default React.memo(Item);

frontend/src/app/PackForm/PackForm.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ const PackForm: React.FC<PackFormSpecs.Props> = ({ history, packId, getPack, exp
6262
}
6363

6464
const addItem = (item: Item) => {
65-
const items = Object.assign([], [...packItems, { ...item, packItem: { notes: '', quantity: 1, worn: false } }]);
65+
const items = Object.assign([], [...packItems, { ...item, packItem: { notes: item.notes, quantity: 1, worn: false } }]);
6666
setPackItems(items);
6767
};
6868

@@ -259,4 +259,4 @@ const PackForm: React.FC<PackFormSpecs.Props> = ({ history, packId, getPack, exp
259259
);
260260
};
261261

262-
export default PackForm;
262+
export default PackForm;

frontend/src/app/components/EditItem/index.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const EditForm: React.FC<FormSpecs.Props> = (
5353
</ButtonGroup>
5454
);
5555

56-
const { product_name, name, weight_unit, weight, price, product_url } = record;
56+
const { product_name, name, weight_unit, weight, price, product_url, notes } = record;
5757
return (
5858
<Modal
5959
title={<ModalTitle>Edit Item</ModalTitle>}
@@ -109,6 +109,12 @@ const EditForm: React.FC<FormSpecs.Props> = (
109109
type="url"
110110
value={product_url || ''}
111111
onChange={v => updateItem('product_url', v)}
112+
/>
113+
114+
<Input label="Notes"
115+
value={notes || ''}
116+
placeholder="Care instructions, further details, etc..."
117+
onChange={v => updateItem('notes', v)}
112118
last={true}/>
113119
</Modal>
114120
)
@@ -118,4 +124,4 @@ const EditWithApi = withApi<FormSpecs.ApiProps>(api => ({
118124
deleteItem: api.ItemService.delete
119125
}))(EditForm);
120126

121-
export default EditWithApi;
127+
export default EditWithApi;

frontend/src/app/components/Icons/index.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
import * as React from 'react';
22

3+
export const DotIcon = () => (
4+
<svg x="0px" y="0px" width="32px" height="30px" viewBox="0 0 20 20" xmlSpace="preserve">
5+
<g>
6+
<g>
7+
<path d="M7.8 10c0 1.215 0.986 2.2 2.201 2.2s2.199-0.986 2.199-2.2c0-1.215-0.984-2.199-2.199-2.199s-2.201 0.984-2.201 2.199z"></path>
8+
</g>
9+
</g>
10+
</svg>
11+
);
12+
313
export const ShirtIcon = () => (
414
<svg x="0px" y="0px" width="42px" height="40px" viewBox="0 0 40.143 40.143" xmlSpace="preserve">
515
<g>
@@ -69,4 +79,4 @@ export const TempIcon = () => (
6979
<ellipse cx="4.33332" cy="17.5" rx="1" ry="0.5" transform="rotate(-28.5335 4.33332 17.5)" fill="#FF8C8C"/>
7080
</svg>
7181

72-
);
82+
);

frontend/src/app/components/ItemForm/ItemForm.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ const ItemForm: React.FC<FormSpecs.Props> = ({ createItem, exportCsv, onSubmit }
4141
weight_unit: default_weight_unit,
4242
price: undefined,
4343
product_url: '',
44-
newCategory: false
44+
newCategory: false,
45+
notes: ''
4546
}}
4647
validationSchema={Yup.object().shape({
4748
name: Yup.string().required('Item name is required'),
@@ -138,6 +139,12 @@ const ItemForm: React.FC<FormSpecs.Props> = ({ createItem, exportCsv, onSubmit }
138139
onChange={v => setFieldValue('product_url', v)}
139140
allowedLength={ItemConstants.product_url}
140141
/>
142+
<Input
143+
label="Notes"
144+
value={values.notes || ''}
145+
placeholder="Care instructions, further details, etc..."
146+
onChange={v => setFieldValue('notes', v)}
147+
/>
141148
<Button onClick={submitForm}
142149
disabled={isSubmitting}
143150
block={true}
@@ -172,4 +179,4 @@ const ItemFormWithProps = withApi<FormSpecs.ApiProps>(api => ({
172179
exportCsv: api.ItemService.exportCSV
173180
}))(ItemForm);
174181

175-
export default ItemFormWithProps;
182+
export default ItemFormWithProps;

frontend/src/styles/grid.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import styled from "styled-components";
33

44
export const Grid = styled.div`
55
display: grid;
6-
grid-template-columns: 160px minmax(200px, auto) 160px 140px 60px 30px;
6+
grid-template-columns: 2px 160px minmax(200px, auto) 160px 140px 60px 30px;
77
grid-template-rows: auto;
88
grid-column-gap: 16px;
99
align-items: center;
10-
10+
11+
.align-center {
12+
justify-self: center;
13+
}
1114
.align-right {
1215
justify-self: end;
1316
}
@@ -32,12 +35,27 @@ export const PackItemGrid = styled.div`
3235
grid-column-gap: 16px;
3336
align-items: center;
3437
line-height: 1.25em;
35-
38+
3639
.align-right {
3740
justify-self: end;
3841
}
39-
42+
4043
.align-center {
4144
justify-self: center;
4245
}
4346
`;
47+
48+
export const NotesIndicator = styled.div`
49+
display: flex;
50+
justify-content: space-between;
51+
52+
svg {
53+
fill: #CCC;
54+
width: 20px;
55+
}
56+
57+
&.active svg {
58+
fill: #34ACD4;
59+
width: 20px;
60+
}
61+
`;

frontend/src/styles/style.less

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ body {
5252
padding: 8px;
5353
text-align: center;
5454
line-height: 1.25rem;
55-
max-width: 180px;
55+
width: fit-content;
5656
}
5757

5858
.ant-spin-dot {

frontend/src/types/item.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface BaseItem {
99
weight_unit?: WeightUnit;
1010
price?: number;
1111
product_url?: string;
12+
notes?: string;
1213
}
1314

1415
export interface Item extends BaseItem {
@@ -57,4 +58,4 @@ export enum ItemConstants {
5758
name = 200,
5859
product_name = 500,
5960
product_url = 500
60-
}
61+
}

0 commit comments

Comments
 (0)