Compare commits
2 Commits
master
...
11-create-
| Author | SHA1 | Date | |
|---|---|---|---|
| b939752d96 | |||
| 0d82d5c3ef |
196
client/package-lock.json
generated
196
client/package-lock.json
generated
@ -18,7 +18,10 @@
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^17.0.2",
|
||||
"react-bootstrap": "^2.1.2",
|
||||
"react-datepicker": "^4.14.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-hook-form": "^7.44.3",
|
||||
"react-modal": "^3.16.1",
|
||||
"react-scripts": "5.0.0",
|
||||
"sass": "^1.49.7",
|
||||
"web-vitals": "^2.1.4"
|
||||
@ -1772,11 +1775,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
|
||||
"integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==",
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
|
||||
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
@ -5886,6 +5889,21 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/date-fns"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||
@ -7187,6 +7205,11 @@
|
||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/exenv": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
|
||||
"integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
|
||||
},
|
||||
"node_modules/exit": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
|
||||
@ -13142,6 +13165,23 @@
|
||||
"react-dom": ">=16.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-datepicker": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.14.0.tgz",
|
||||
"integrity": "sha512-MLky2SF8hVTPgFRseauoOprjz6/rUMWq8MHadWYwExJvojUyCZOWDMWq9bRqoliQqqPhcViYjyxAxvFQpD9aDA==",
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.9.2",
|
||||
"classnames": "^2.2.6",
|
||||
"date-fns": "^2.24.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-onclickoutside": "^6.12.2",
|
||||
"react-popper": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.9.0 || ^17 || ^18",
|
||||
"react-dom": "^16.9.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dev-utils": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
|
||||
@ -13277,6 +13317,26 @@
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
|
||||
"integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA=="
|
||||
},
|
||||
"node_modules/react-fast-compare": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
|
||||
},
|
||||
"node_modules/react-hook-form": {
|
||||
"version": "7.44.3",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.44.3.tgz",
|
||||
"integrity": "sha512-/tHId6p2ViAka1wECMw8FEPn/oz/w226zehHrJyQ1oIzCBNMIJCaj6ZkQcv+MjDxYh9MWR7RQic7Qqwe4a5nkw==",
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/react-hook-form"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
@ -13287,6 +13347,51 @@
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"node_modules/react-modal": {
|
||||
"version": "3.16.1",
|
||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz",
|
||||
"integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==",
|
||||
"dependencies": {
|
||||
"exenv": "^1.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-lifecycles-compat": "^3.0.0",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18",
|
||||
"react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-onclickoutside": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz",
|
||||
"integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==",
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://github.com/Pomax/react-onclickoutside/blob/master/FUNDING.md"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^15.5.x || ^16.x || ^17.x || ^18.x",
|
||||
"react-dom": "^15.5.x || ^16.x || ^17.x || ^18.x"
|
||||
}
|
||||
},
|
||||
"node_modules/react-popper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
|
||||
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
|
||||
"dependencies": {
|
||||
"react-fast-compare": "^3.0.1",
|
||||
"warning": "^4.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@popperjs/core": "^2.0.0",
|
||||
"react": "^16.8.0 || ^17 || ^18",
|
||||
"react-dom": "^16.8.0 || ^17 || ^18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-refresh": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
|
||||
@ -13446,9 +13551,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||
},
|
||||
"node_modules/regenerator-transform": {
|
||||
"version": "0.14.5",
|
||||
@ -17368,11 +17473,11 @@
|
||||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.16.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
|
||||
"integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==",
|
||||
"version": "7.22.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
|
||||
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
"regenerator-runtime": "^0.13.11"
|
||||
}
|
||||
},
|
||||
"@babel/runtime-corejs3": {
|
||||
@ -20403,6 +20508,14 @@
|
||||
"whatwg-url": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.30.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.21.0"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||
@ -21357,6 +21470,11 @@
|
||||
"strip-final-newline": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"exenv": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
|
||||
"integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
|
||||
},
|
||||
"exit": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
|
||||
@ -25532,6 +25650,19 @@
|
||||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"react-datepicker": {
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.14.0.tgz",
|
||||
"integrity": "sha512-MLky2SF8hVTPgFRseauoOprjz6/rUMWq8MHadWYwExJvojUyCZOWDMWq9bRqoliQqqPhcViYjyxAxvFQpD9aDA==",
|
||||
"requires": {
|
||||
"@popperjs/core": "^2.9.2",
|
||||
"classnames": "^2.2.6",
|
||||
"date-fns": "^2.24.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-onclickoutside": "^6.12.2",
|
||||
"react-popper": "^2.3.0"
|
||||
}
|
||||
},
|
||||
"react-dev-utils": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
|
||||
@ -25633,6 +25764,17 @@
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz",
|
||||
"integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA=="
|
||||
},
|
||||
"react-fast-compare": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
|
||||
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
|
||||
},
|
||||
"react-hook-form": {
|
||||
"version": "7.44.3",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.44.3.tgz",
|
||||
"integrity": "sha512-/tHId6p2ViAka1wECMw8FEPn/oz/w226zehHrJyQ1oIzCBNMIJCaj6ZkQcv+MjDxYh9MWR7RQic7Qqwe4a5nkw==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "17.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
|
||||
@ -25643,6 +25785,32 @@
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-modal": {
|
||||
"version": "3.16.1",
|
||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz",
|
||||
"integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==",
|
||||
"requires": {
|
||||
"exenv": "^1.2.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-lifecycles-compat": "^3.0.0",
|
||||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"react-onclickoutside": {
|
||||
"version": "6.13.0",
|
||||
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.13.0.tgz",
|
||||
"integrity": "sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==",
|
||||
"requires": {}
|
||||
},
|
||||
"react-popper": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
|
||||
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
|
||||
"requires": {
|
||||
"react-fast-compare": "^3.0.1",
|
||||
"warning": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"react-refresh": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
|
||||
@ -25763,9 +25931,9 @@
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
"version": "0.13.11",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
|
||||
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
|
||||
},
|
||||
"regenerator-transform": {
|
||||
"version": "0.14.5",
|
||||
|
||||
@ -13,7 +13,10 @@
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^17.0.2",
|
||||
"react-bootstrap": "^2.1.2",
|
||||
"react-datepicker": "^4.14.0",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-hook-form": "^7.44.3",
|
||||
"react-modal": "^3.16.1",
|
||||
"react-scripts": "5.0.0",
|
||||
"sass": "^1.49.7",
|
||||
"web-vitals": "^2.1.4"
|
||||
|
||||
12
client/src/components/buttons/AddBudgetPeriodButton.jsx
Normal file
12
client/src/components/buttons/AddBudgetPeriodButton.jsx
Normal file
@ -0,0 +1,12 @@
|
||||
import { ReactComponent as Plus } from '../../resources/Plus.svg';
|
||||
import './AddBudgetPeriodButton.scss';
|
||||
|
||||
const AddBudgetPeriodButton = ({ onClick }) => {
|
||||
return (<div className='add-budget-period-button-container'>
|
||||
<div className='add-budget-period-button-icon-container' onClick={onClick}>
|
||||
<Plus />
|
||||
</div>
|
||||
</div>);
|
||||
};
|
||||
|
||||
export default AddBudgetPeriodButton;
|
||||
10
client/src/components/buttons/AddBudgetPeriodButton.scss
Normal file
10
client/src/components/buttons/AddBudgetPeriodButton.scss
Normal file
@ -0,0 +1,10 @@
|
||||
.add-budget-period-button-container {
|
||||
vertical-align: top;
|
||||
.add-budget-period-button-icon-container {
|
||||
border: 4px solid #ccc;
|
||||
border-radius: 5px;
|
||||
svg {
|
||||
fill: #ccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
client/src/data/validation/CommonRegex.js
Normal file
3
client/src/data/validation/CommonRegex.js
Normal file
@ -0,0 +1,3 @@
|
||||
const usDateFormatRegex = /^(0[1-9]|1[0-2])\/(0[1-9]|[12][0-9]|3[01])\/\d{4}$/;
|
||||
|
||||
export { usDateFormatRegex };
|
||||
28
client/src/forms/AddBudgetPeriodForm.jsx
Normal file
28
client/src/forms/AddBudgetPeriodForm.jsx
Normal file
@ -0,0 +1,28 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import _ from 'lodash';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import DateInput from './components/DateInput';
|
||||
|
||||
const AddBudgetPeriodForm = ({ requestClose }) => {
|
||||
const [tmp, setTmp] = useState(0),
|
||||
{ handleSubmit, register, formState: { errors }, trigger } = useForm({ mode: 'onChange' }),
|
||||
onSubmit = (data) => { console.log(data); requestClose() };
|
||||
|
||||
useEffect(() => {
|
||||
trigger();
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="budget-period-form">
|
||||
<h1>Choose Budget Period</h1>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<DateInput label='Start Date' fieldName='startDate' required={true} form={{ register, errors }} />
|
||||
<DateInput label='End Date' fieldName='endDate' required={true} form={{ register, errors }} />
|
||||
<button type='submit' disabled={!_.isEmpty(errors)}>Create</button>
|
||||
</form>
|
||||
<button onClick={requestClose}>Cancel</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AddBudgetPeriodForm;
|
||||
@ -1,20 +0,0 @@
|
||||
import { useState } from "react";
|
||||
import { DropdownButton, Dropdown } from "react-bootstrap";
|
||||
|
||||
const BudgetPeriodForm = () => {
|
||||
const [tmp, setTmp] = useState(0);
|
||||
|
||||
return (
|
||||
<div className="budget-period-form">
|
||||
<h1>Choose Budget Period</h1>
|
||||
<DropdownButton id="dropdown-basic-button" title="Select budget period">
|
||||
<Dropdown.Item href="#/action-1">Weekly</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-2">Bi-Weekly</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-3">Bi-Monthly</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-4">Monthly</Dropdown.Item>
|
||||
</DropdownButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default BudgetPeriodForm;
|
||||
25
client/src/forms/components/DateInput.jsx
Normal file
25
client/src/forms/components/DateInput.jsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { usDateFormatRegex } from '../../data/validation/CommonRegex';
|
||||
import { useState } from 'react';
|
||||
import DatePicker from 'react-datepicker';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
|
||||
const DateInput = ({ label, fieldName, required, form }) => {
|
||||
const [selectedDate, setSelectedDate] = useState(null),
|
||||
options = required === true ? {
|
||||
required: `${label} is required`,
|
||||
pattern: {
|
||||
value: usDateFormatRegex,
|
||||
message: 'Invalid date format (MM/DD/YYYY)',
|
||||
}
|
||||
} : {};
|
||||
|
||||
return (
|
||||
<div className='date-input-box'>
|
||||
<label>{label}</label>
|
||||
<DatePicker selected={selectedDate} {...form.register(fieldName, options)} onChange={(date) => { setSelectedDate(date) }} />
|
||||
{form.errors[fieldName] && <span>{form.errors[fieldName].message}</span>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DateInput;
|
||||
@ -1 +1,6 @@
|
||||
<?xml version="1.0"?><svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px" height="24px"> <path d="M 12 1 C 8.6761905 1 6 3.6761905 6 7 L 6 8 C 4.9069372 8 4 8.9069372 4 10 L 4 20 C 4 21.093063 4.9069372 22 6 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 10 C 20 8.9069372 19.093063 8 18 8 L 18 7 C 18 3.6761905 15.32381 1 12 1 z M 12 3 C 14.27619 3 16 4.7238095 16 7 L 16 8 L 8 8 L 8 7 C 8 4.7238095 9.7238095 3 12 3 z M 6 10 L 18 10 L 18 20 L 6 20 L 6 10 z M 12 13 C 10.9 13 10 13.9 10 15 C 10 16.1 10.9 17 12 17 C 13.1 17 14 16.1 14 15 C 14 13.9 13.1 13 12 13 z"/></svg>
|
||||
<?xml version="1.0"?>
|
||||
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24px"
|
||||
height="24px">
|
||||
<path
|
||||
d="M 12 1 C 8.6761905 1 6 3.6761905 6 7 L 6 8 C 4.9069372 8 4 8.9069372 4 10 L 4 20 C 4 21.093063 4.9069372 22 6 22 L 18 22 C 19.093063 22 20 21.093063 20 20 L 20 10 C 20 8.9069372 19.093063 8 18 8 L 18 7 C 18 3.6761905 15.32381 1 12 1 z M 12 3 C 14.27619 3 16 4.7238095 16 7 L 16 8 L 8 8 L 8 7 C 8 4.7238095 9.7238095 3 12 3 z M 6 10 L 18 10 L 18 20 L 6 20 L 6 10 z M 12 13 C 10.9 13 10 13.9 10 15 C 10 16.1 10.9 17 12 17 C 13.1 17 14 16.1 14 15 C 14 13.9 13.1 13 12 13 z" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 615 B After Width: | Height: | Size: 630 B |
8
client/src/resources/Plus.svg
Normal file
8
client/src/resources/Plus.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<rect width="20" height="90" x="40" y="5" rx="5" ry="5" />
|
||||
<rect width="90" height="20" x="5" y="40" rx="5" ry="5" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 237 B |
@ -1,20 +1,27 @@
|
||||
import _ from 'lodash';
|
||||
import BudgetPeriodCard from './BudgetPeriodCard';
|
||||
import { BudgetContext } from '../data/context/BudgetContext'
|
||||
import { useContext } from 'react';
|
||||
import { useContext, useState } from 'react';
|
||||
import Modal from 'react-modal';
|
||||
import AddBudgetPeriodButton from '../components/buttons/AddBudgetPeriodButton';
|
||||
import AddBudgetPeriodForm from '../forms/AddBudgetPeriodForm';
|
||||
import './BudgetCardView.scss';
|
||||
|
||||
const BudgetCardView = () => {
|
||||
const context = useContext(BudgetContext),
|
||||
[showAddBudgetPeriodMenu, setShowAddBudgetPeriodMenu] = useState(false),
|
||||
activePeriod = context?.budgetPeriods?.find?.(p => !p.locked);
|
||||
|
||||
return (
|
||||
<div className="budget-card-view-tray">
|
||||
<div className='budget-card-view-tray'>
|
||||
{context?.budgetPeriods?.map?.(p => {
|
||||
return (
|
||||
<BudgetPeriodCard key={p.id} periodData={p} isActive={p === activePeriod} />
|
||||
);
|
||||
})}
|
||||
<AddBudgetPeriodButton onClick={() => setShowAddBudgetPeriodMenu(true)} />
|
||||
<Modal isOpen={showAddBudgetPeriodMenu} onRequestClose={() => setShowAddBudgetPeriodMenu(false)}>
|
||||
<AddBudgetPeriodForm requestClose={() => setShowAddBudgetPeriodMenu(false)} />
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
background-color: #efefef;
|
||||
border-bottom: 2px solid #ccc;
|
||||
border-top: 2px solid #ccc;
|
||||
height: 750px;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
overflow-x: auto;
|
||||
@ -9,4 +10,15 @@
|
||||
.budget-period-card {
|
||||
display: inline-block;
|
||||
}
|
||||
.add-budget-period-button-container {
|
||||
display: inline-block;
|
||||
margin: 1em;
|
||||
width: 400px;
|
||||
.add-budget-period-button-icon-container {
|
||||
height: 100px;
|
||||
margin-left: 80px;
|
||||
margin-top: 296px;
|
||||
width: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,8 +2,8 @@ import { useState, useEffect, useRef, useContext } from 'react';
|
||||
import BudgetPeriodTransTable from './BudgetPeriodTransTable';
|
||||
import Lock from '../resources/Lock.svg';
|
||||
import OpenLock from '../resources/OpenLock.svg';
|
||||
import './BudgetPeriodCard.scss';
|
||||
import { BudgetContext } from '../data/context/BudgetContext';
|
||||
import './BudgetPeriodCard.scss';
|
||||
|
||||
const BudgetPeriodCard = ({periodData, isActive}) => {
|
||||
const cardRef = useRef(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user