aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.css38
-rw-r--r--src/App.js48
-rw-r--r--src/App.scss41
-rw-r--r--src/App.test.js8
-rw-r--r--src/classes/brand.js44
-rw-r--r--src/classes/item.js67
-rw-r--r--src/components/editors/item-editor.js177
-rw-r--r--src/components/editors/scss/item-editor.scss88
-rw-r--r--src/components/tables/item-table.js78
-rw-r--r--src/components/tables/scss/table.scss49
-rw-r--r--src/index.css13
-rw-r--r--src/index.js7
-rw-r--r--src/logo.svg1
-rw-r--r--src/reportWebVitals.js13
-rw-r--r--src/setupTests.js5
-rw-r--r--src/views/manage/items.js46
-rw-r--r--src/views/new-invoice.js33
17 files changed, 652 insertions, 104 deletions
diff --git a/src/App.css b/src/App.css
deleted file mode 100644
index 74b5e05..0000000
--- a/src/App.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.App {
- text-align: center;
-}
-
-.App-logo {
- height: 40vmin;
- pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
- .App-logo {
- animation: App-logo-spin infinite 20s linear;
- }
-}
-
-.App-header {
- background-color: #282c34;
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- font-size: calc(10px + 2vmin);
- color: white;
-}
-
-.App-link {
- color: #61dafb;
-}
-
-@keyframes App-logo-spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
-}
diff --git a/src/App.js b/src/App.js
index 3784575..d75d8e5 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,24 +1,34 @@
-import logo from './logo.svg';
-import './App.css';
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
-function App() {
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import './App.scss';
+import { BrowserRouter, Route, Routes } from "react-router-dom";
+import ManageItemsPage from './views/manage/items';
+
+const App = () => {
return (
- <div className="App">
- <header className="App-header">
- <img src={logo} className="App-logo" alt="logo" />
- <p>
- Edit <code>src/App.js</code> and save to reload.
- </p>
- <a
- className="App-link"
- href="https://reactjs.org"
- target="_blank"
- rel="noopener noreferrer"
- >
- Learn React
- </a>
- </header>
- </div>
+ <BrowserRouter>
+ <main>
+ <Routes>
+ <Route exact path="/manage/items" element={<ManageItemsPage/>}/>
+ <Route path="*" element={<h1>404</h1>}/>
+ </Routes>
+ </main>
+ </BrowserRouter>
);
}
diff --git a/src/App.scss b/src/App.scss
new file mode 100644
index 0000000..81bde15
--- /dev/null
+++ b/src/App.scss
@@ -0,0 +1,41 @@
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500&display=swap');
+
+* {
+ font-family: 'Open Sans', sans-serif;
+}
+
+body {
+ margin: 0;
+ padding: 0;
+ //background-color: #dfe0e8;
+ background-color: #282a36;
+ color: #f8f8f2;
+}
+
+main {
+ //background-color: #FDFDFD;
+ background-color: #282a36;
+ width: 100%;
+ max-width: 1500px;
+ margin: 0 auto;
+ min-height: 100vh;
+ padding: 0.7rem 0.5rem;
+ box-sizing: border-box;
+}
diff --git a/src/App.test.js b/src/App.test.js
deleted file mode 100644
index 1f03afe..0000000
--- a/src/App.test.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { render, screen } from '@testing-library/react';
-import App from './App';
-
-test('renders learn react link', () => {
- render(<App />);
- const linkElement = screen.getByText(/learn react/i);
- expect(linkElement).toBeInTheDocument();
-});
diff --git a/src/classes/brand.js b/src/classes/brand.js
new file mode 100644
index 0000000..48bc974
--- /dev/null
+++ b/src/classes/brand.js
@@ -0,0 +1,44 @@
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import axios from "axios";
+
+/* TODO: implement a better way to handle
+ * API responses/errors
+ *
+ * maybe I can send a notification when a brand
+ * is successfully added, or when some error occours
+ */
+
+export class Brand {
+ constructor() {
+ this.Id = null;
+ this.Name = "";
+ }
+}
+
+export const deleteBrand = (id, ok, fail) => {
+ axios.delete(`/brand/${id}`)
+ .then(res => ok())
+ .catch(err => fail())
+}
+
+export const getAllBrands = (ok, fail) => {
+ axios.get("/brand/all")
+ .then(res => ok(res.data))
+ .catch(err => fail())
+}
diff --git a/src/classes/item.js b/src/classes/item.js
new file mode 100644
index 0000000..3985e9d
--- /dev/null
+++ b/src/classes/item.js
@@ -0,0 +1,67 @@
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import axios from "axios";
+import { Brand } from "./brand"
+
+/* TODO: implement a better way to handle
+ * API responses/errors
+ *
+ * maybe I can send a notification when an item
+ * is successfully added, or when some error occours
+ */
+
+export class Item {
+ constructor() {
+ this.Id = null;
+ this.Brand = new Brand();
+ this.UnitOfMeasure = "";
+ this.Name = "";
+ this.Description = "";
+ this.HSN = "";
+ this.UnitPrice = 0.00;
+ this.GSTPercentage = 0.00;
+ this.MinQuantity = 0.00;
+ this.MaxQuantity = 0.00;
+ }
+}
+
+export class InvoiceItem extends Item {
+ constructor() {
+ super();
+ this.Quantity = 0.00;
+ this.DiscountPercentage = 0.00;
+ }
+}
+
+export const saveItem = (item, ok, fail) => {
+ axios.post("/item/new", item)
+ .then(res => { console.log(res);ok()})
+ .catch((err) => fail())
+}
+
+export const deleteItem = (id, ok, fail) => {
+ axios.delete(`/item/${id}`)
+ .then(res => ok())
+ .catch((err) => fail())
+}
+
+export const getAllItems = (ok, fail) => {
+ axios.get("/item/all")
+ .then(res => ok(res.data))
+ .catch(err => fail())
+}
diff --git a/src/components/editors/item-editor.js b/src/components/editors/item-editor.js
new file mode 100644
index 0000000..af505ac
--- /dev/null
+++ b/src/components/editors/item-editor.js
@@ -0,0 +1,177 @@
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import { Item, saveItem } from './../../classes/item'
+import { Brand, getAllBrands } from './../../classes/brand'
+import './scss/item-editor.scss'
+
+import { useState, useEffect } from 'react';
+
+const ItemEditor = (props) => {
+ const [name, setName] = useState("");
+ const [desc, setDesc] = useState("");
+ const [HSN, setHSN] = useState("");
+ const [unit, setUnit] = useState("");
+ const [unitPrice, setUnitPrice] = useState(0.00);
+ const [gstP, setGSTP] = useState(0.00);
+ const [minQty, setMinQty] = useState(0.00);
+ const [maxQty, setMaxQty] = useState(0.00);
+ const [brand, setBrand] = useState(new Brand());
+ const [savedBrands, setSavedBrands] = useState([]);
+
+ // get saved brands from API
+ // needed by the brands dropdown menu
+ useEffect(() => {
+ // TODO: handle error
+ getAllBrands(setSavedBrands, () => {});
+ }, [])
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+
+ const item = new Item();
+ item.Name = name;
+ item.Description = desc;
+ item.HSN = HSN;
+ item.UnitOfMeasure = unit;
+ item.UnitPrice = unitPrice;
+ item.GSTPercentage = gstP;
+ item.MinQuantity = minQty;
+ item.MaxQuantity = maxQty;
+ item.Brand = brand;
+
+ // TODO: Save is for new items. implement modification too
+ saveItem(item, handleSuccess, handleFail);
+ }
+
+ const handleSuccess = () => {
+ clearAll();
+ props.callback();
+ }
+
+ const handleFail = () => {
+ alert("fail");
+ }
+
+ const handleBrandSelect = (e) => {
+ const b = savedBrands.filter(i => i.Id === e.target.value )[0];
+ setBrand(b ? b : new Brand());
+ }
+
+ const clearAll = () => {
+ setName("");
+ setDesc("");
+ setHSN("");
+ setUnit("");
+ setUnitPrice(0.00);
+ setGSTP(0.00);
+ setMinQty(0.00);
+ setMaxQty(0.00);
+ setBrand(new Brand())
+ }
+
+ const handleCancel = () => {
+ // TODO: hide this component or something
+ clearAll();
+ }
+
+ const validateFloatInput = (e, callback) => {
+ const f = parseFloat(e.target.value);
+ f && callback(f)
+ }
+
+ return (
+ <div className={"editor-wrapper"}>
+ <p>Add New Item</p>
+ <form onSubmit={handleSubmit} className={"editor"}>
+ <label>
+ Product/Service:
+ <input
+ type="text" name="name"
+ value={name} onChange={(e) => setName(e.target.value)} />
+ </label>
+
+ <label>
+ Description:
+ <input
+ type="text" name="desc"
+ value={desc} onChange={(e) => setDesc(e.target.value)} />
+ </label>
+
+ <label>
+ HSN:
+ <input
+ type="text" name="hsn"
+ value={HSN} onChange={(e) => setHSN(e.target.value)} />
+ </label>
+
+ <label>
+ Unit of Measurement:
+ <input
+ type="text" name="unit"
+ value={unit} onChange={(e) => setUnit(e.target.value)} />
+ </label>
+
+ <label>
+ Unit Price:
+ <input
+ type="number" name="unitprice"
+ value={unitPrice} onChange={(e) => validateFloatInput(e, setUnitPrice)} />
+ </label>
+
+ <label>
+ GST %:
+ <input
+ type="number" name="gstp"
+ value={gstP} onChange={(e) => validateFloatInput(e, setGSTP)} />
+ </label>
+
+ <label>
+ Minimum Quantity:
+ <input
+ type="number" name="minqty"
+ value={minQty} onChange={(e) => validateFloatInput(e, setMinQty)} />
+ </label>
+
+ <label>
+ Maximum Quantity:
+ <input
+ type="number" name="maxqty"
+ value={maxQty} onChange={(e) => validateFloatInput(e, setMaxQty)} />
+ </label>
+
+ <label>
+ Brand:
+ <select value={brand.Id ? brand.Id : ""} onChange={handleBrandSelect}>
+ <option key="placeholder" value={""}>
+ {brand.Id == null ? "Select a Brand (optional)" : "None"}
+ </option>
+ {savedBrands.map(i => <option key={i.Id} value={i.Id}>{i.Name}</option>)}
+ </select>
+ </label>
+
+ <span className={"buttons"}>
+ <input type="button" value="Clear" onClick={clearAll}/>
+ <input type="button" value="Cancel" onClick={handleCancel}/>
+ <input type="submit" value="Save" />
+ </span>
+ </form>
+ </div>
+ );
+}
+
+export default ItemEditor;
diff --git a/src/components/editors/scss/item-editor.scss b/src/components/editors/scss/item-editor.scss
new file mode 100644
index 0000000..968795a
--- /dev/null
+++ b/src/components/editors/scss/item-editor.scss
@@ -0,0 +1,88 @@
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+.editor-wrapper {
+ width: 100%;
+ margin: auto;
+ padding: 0;
+ margin: 0;
+ position: relative;
+ p {
+ text-align: center;
+ font-weight: bold;
+ font-size: 1.7rem;
+ color: #bd93f9;
+ }
+}
+
+.editor {
+ padding-bottom: 2.5rem;
+ margin: auto;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: space-evenly;
+ align-items: center;
+ min-width: 90%;
+
+ label {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: center;
+ max-width: 24rem;
+ width: 90%;
+ padding: 0.3rem 0.1rem;
+ border-bottom: 1px dotted #d0afff;
+
+ select,input {
+ padding: 0.2rem;
+ max-width: 13rem;
+ width: 90%;
+ box-sizing: border-box;
+ background-color: #00000000;
+ border: 1px solid #bd93f9;
+ color: white;
+ border-radius: 4px;
+ outline: 0;
+ }
+ }
+
+ .buttons {
+ position: absolute;
+ display: flex;
+ justify-content: space-between;
+ width: 13.5rem;
+ input {
+ padding: 0.2rem 0;
+ width: 4rem;
+ background-color: #00000000;
+ border: 1px solid #bd93f9;
+ color: white;
+ border-radius: 4px;
+ transition: background-color 0.4s, color 0.4s;
+ }
+ input:hover {
+ background-color: #bd93f9;
+ color: black;
+ }
+ bottom: 0;
+ left: 0;
+ right: 0;
+ margin: auto;
+ }
+}
diff --git a/src/components/tables/item-table.js b/src/components/tables/item-table.js
new file mode 100644
index 0000000..c1115c1
--- /dev/null
+++ b/src/components/tables/item-table.js
@@ -0,0 +1,78 @@
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import './scss/table.scss';
+import { deleteItem } from './../../classes/item';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { faPencil, faTrashCan } from '@fortawesome/free-solid-svg-icons'
+
+const ItemTable = (props) => {
+ const handleDelete = (i) => {
+ // TODO: add confirmation prompt
+ deleteItem(i.Id, handleDelSuccess, handleDelFail);
+ }
+
+ const handleDelSuccess = () => {
+ props.refresh();
+ }
+
+ const handleDelFail = () => {
+ alert("fail")
+ }
+
+ return (
+ <table>
+ <thead>
+ <tr>
+ <th>S. No</th>
+ <th>Name</th>
+ <th>Description</th>
+ <th>Brand Name</th>
+ <th>UOM</th>
+ <th>HSN</th>
+ <th>Unit Price</th>
+ <th>GST %</th>
+ <th>Min Qty</th>
+ <th>Max Qty</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {props.items && props.items.map((i, id=id+1) => (
+ <tr key={id}>
+ <td>{id+1}</td>
+ <td className={i.Name === "" ? "empty" : ""}>{i.Name}</td>
+ <td className={i.Description === "" ? "empty" : ""}>{i.Description}</td>
+ <td className={i.Brand.Name === "" ? "empty" : ""}>{i.Brand.Name}</td>
+ <td className={i.UnitOfMeasure === "" ? "empty" : ""}>{i.UnitOfMeasure}</td>
+ <td className={i.HSN === "" ? "empty" : ""}>{i.HSN}</td>
+ <td className={i.UnitPrice === 0.0 ? "empty" : ""}>{i.UnitPrice}</td>
+ <td className={i.GSTPercentage === 0.0 ? "empty" : ""}>{i.GSTPercentage}</td>
+ <td className={i.MinQuantity === 0.0 ? "empty" : ""}>{i.MinQuantity}</td>
+ <td className={i.MaxQuantity === 0.0 ? "empty" : ""}>{i.MaxQuantity}</td>
+ <td className={"buttons"}>
+ <FontAwesomeIcon icon={faPencil} onClick={() => alert("editing coming soon")}/>
+ <FontAwesomeIcon icon={faTrashCan} onClick={() => handleDelete(i)}/>
+ </td>
+ </tr>
+ ))}
+ </tbody>
+ </table>
+ );
+}
+
+export default ItemTable;
diff --git a/src/components/tables/scss/table.scss b/src/components/tables/scss/table.scss
new file mode 100644
index 0000000..44d7f57
--- /dev/null
+++ b/src/components/tables/scss/table.scss
@@ -0,0 +1,49 @@
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+table {
+ width: 90%;
+ margin: auto;
+
+ th {
+ box-sizing: border-box;
+ background-color: #383a59;
+ font-weight: normal;
+ text-align: left;
+ padding-left: 0.3rem;
+ }
+
+ tr:hover {
+ background-color: rgba(#383a59, 0.4);
+ }
+
+ td {
+ border-bottom: 1px solid white;
+ }
+
+ td.empty {
+ border-bottom: 1px solid gray;
+ }
+
+ td.buttons {
+ display: flex;
+ justify-content: space-evenly;
+ align-items: center;
+ border: none;
+ height: 1.4rem;
+ }
+}
diff --git a/src/index.css b/src/index.css
deleted file mode 100644
index ec2585e..0000000
--- a/src/index.css
+++ /dev/null
@@ -1,13 +0,0 @@
-body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-
-code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
-}
diff --git a/src/index.js b/src/index.js
index d563c0f..593edf1 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,8 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
-import './index.css';
import App from './App';
-import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
@@ -10,8 +8,3 @@ root.render(
<App />
</React.StrictMode>
);
-
-// If you want to start measuring performance in your app, pass a function
-// to log results (for example: reportWebVitals(console.log))
-// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
-reportWebVitals();
diff --git a/src/logo.svg b/src/logo.svg
deleted file mode 100644
index 9dfc1c0..0000000
--- a/src/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg> \ No newline at end of file
diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js
deleted file mode 100644
index 5253d3a..0000000
--- a/src/reportWebVitals.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const reportWebVitals = onPerfEntry => {
- if (onPerfEntry && onPerfEntry instanceof Function) {
- import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
- getCLS(onPerfEntry);
- getFID(onPerfEntry);
- getFCP(onPerfEntry);
- getLCP(onPerfEntry);
- getTTFB(onPerfEntry);
- });
- }
-};
-
-export default reportWebVitals;
diff --git a/src/setupTests.js b/src/setupTests.js
deleted file mode 100644
index 8f2609b..0000000
--- a/src/setupTests.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// jest-dom adds custom jest matchers for asserting on DOM nodes.
-// allows you to do things like:
-// expect(element).toHaveTextContent(/react/i)
-// learn more: https://github.com/testing-library/jest-dom
-import '@testing-library/jest-dom';
diff --git a/src/views/manage/items.js b/src/views/manage/items.js
new file mode 100644
index 0000000..3190504
--- /dev/null
+++ b/src/views/manage/items.js
@@ -0,0 +1,46 @@
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/* This page shows a list of all the items
+ * with options to add/modify/delete items
+ */
+
+import { useState, useEffect } from 'react';
+
+import { getAllItems } from '../../classes/item';
+import ItemEditor from './../../components/editors/item-editor';
+import ItemTable from './../../components/tables/item-table';
+
+const ManageItemsPage = () => {
+ const [allItems, setAllItems] = useState([]);
+ // TODO: handle error
+ const updateList = () =>
+ getAllItems(setAllItems, () => {});
+
+ useEffect(() => {
+ updateList();
+ }, []);
+
+ return (
+ <>
+ <ItemEditor callback={updateList}/>
+ <ItemTable refresh={updateList} items={allItems}/>
+ </>
+ );
+}
+
+export default ManageItemsPage;
diff --git a/src/views/new-invoice.js b/src/views/new-invoice.js
new file mode 100644
index 0000000..bba149a
--- /dev/null
+++ b/src/views/new-invoice.js
@@ -0,0 +1,33 @@
+/* OpenBills-web - Web based libre billing software
+ * Copyright (C) 2022 Vidhu Kant Sharma <vidhukant@vidhukant.xyz>
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import NewBrand from './../components/doc-editors/new-brand';
+import ItemEditor from './../components/doc-editors/item-editor';
+
+const NewInvoicePage = () => {
+ return (
+ <>
+ <h1>Billing Page</h1>
+ <h2>Add new brand:</h2>
+ <NewBrand/>
+ <h2>Add new item:</h2>
+ <ItemEditor/>
+ </>
+ );
+}
+
+export default NewInvoicePage;