aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--server/database/database.go58
-rw-r--r--server/main.go23
-rw-r--r--server/openbills.dbbin8192 -> 12288 bytes
-rw-r--r--src/components/BillingPage.js14
-rw-r--r--src/components/Form/AddNewItemForm.js10
-rw-r--r--src/components/Form/Form.css28
-rw-r--r--src/components/Form/Form.scss53
-rw-r--r--src/components/Form/RegisterItemForm.js103
9 files changed, 252 insertions, 39 deletions
diff --git a/.gitignore b/.gitignore
index 24de31f..b7e0105 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,8 @@ yarn-error.log*
/server/openbills
/server/build
/server/app
+/server/openbills.db
+/server/database/openbills.db
/build
/app
diff --git a/server/database/database.go b/server/database/database.go
index 16b6f65..8b7c7f6 100644
--- a/server/database/database.go
+++ b/server/database/database.go
@@ -12,43 +12,67 @@
package database
import (
- _ "github.com/mattn/go-sqlite3"
"database/sql"
+ _ "github.com/mattn/go-sqlite3"
)
type Item struct {
Model string
Desc string `json:"Description"`
- Price int // *float32
+ Price float64
HSN int
}
-
var myDatabase *sql.DB
+var registered_items *sql.Stmt
+var register_item *sql.Stmt
func init() {
myDatabase, _ = sql.Open("sqlite3", "./openbills.db")
-}
-var myItems *sql.Stmt
-var addToMyItems *sql.Stmt
-func init() {
- myItems, _ = myDatabase.Prepare("CREATE TABLE IF NOT EXISTS RegisteredItems (id INTEGER PRIMARY KEY, model TEXT, desc TEXT, price INTEGER, HSN INTEGER)")
- myItems.Exec()
+ registered_items, _ = myDatabase.Prepare(
+ `CREATE TABLE IF NOT EXISTS registered_items
+ (id INTEGER PRIMARY KEY AUTOINCREMENT,
+ model TEXT NOT NULL,
+ desc TEXT,
+ price REAL,
+ hsn BLOB)`,
+ )
+ registered_items.Exec()
- addToMyItems, _ = myDatabase.Prepare("INSERT INTO RegisteredItems (id, model, desc, price, hsn) VALUES (?, ?, ?, ?, ?)")
+ register_item, _ = myDatabase.Prepare(
+ `INSERT INTO registered_items
+ (model, desc, price, hsn)
+ VALUES (?, ?, ?, ?)`,
+ )
}
func GetAllItems() []Item {
var allItems []Item
- rows, _ := myDatabase.Query("SELECT model, desc, price, hsn FROM RegisteredItems")
+ rows, _ := myDatabase.Query(
+ `SELECT model, desc, price, hsn FROM registered_items`,
+ )
+
+ var (
+ model, desc string
+ price float64
+ HSN int
+ )
- var model string
- var desc string
- var price int
- var hsn int
for rows.Next() {
- rows.Scan(&model, &desc, &price, &hsn)
- allItems = append(allItems, Item{model, desc, price, hsn})
+ rows.Scan(&model, &desc, &price, &HSN)
+ allItems = append(allItems, Item{model, desc, price, HSN})
}
+
return allItems
}
+
+func RegisterItem(model string, desc string, price float64, HSN int) {
+ /*
+ var item Item = Item{
+ model, desc, price, HSN,
+ }
+
+ register_item.Exec(item.Model, item.Desc, item.Price, item.HSN)
+ */
+ register_item.Exec(model, desc, price, HSN)
+}
diff --git a/server/main.go b/server/main.go
index b514a31..1aa34c3 100644
--- a/server/main.go
+++ b/server/main.go
@@ -16,7 +16,7 @@ import (
"github.com/gin-gonic/contrib/static"
"net/http"
- // this handles all the database functions
+ "strconv"
db "github.com/MikunoNaka/openbills/database"
)
@@ -33,6 +33,9 @@ func main() {
items := api.Group("/items")
items.GET("/", getAllItems)
+ items.POST("/", registerItem)
+
+ // items.POST("/", registerItem)
myRouter.Run(":8080")
}
@@ -41,3 +44,21 @@ func getAllItems(ctx *gin.Context) {
ctx.Header("Content-Type", "application/json")
ctx.JSON(http.StatusOK, db.GetAllItems())
}
+
+func registerItem(ctx *gin.Context) {
+ // extract data
+ model := ctx.Query("model")
+ desc := ctx.Query("desc")
+ price, _ := strconv.ParseFloat(ctx.Query("price"), 64)
+ hsn, _ := strconv.Atoi(ctx.Query("hsn"))
+
+ // why does it show warnings
+ item := db.Item {
+ model,
+ desc,
+ price,
+ hsn,
+ }
+
+ db.RegisterItem(item.Model, item.Desc, item.Price, item.HSN)
+}
diff --git a/server/openbills.db b/server/openbills.db
index 1f2afd2..4f15f57 100644
--- a/server/openbills.db
+++ b/server/openbills.db
Binary files differ
diff --git a/src/components/BillingPage.js b/src/components/BillingPage.js
index 7f97b32..fc09694 100644
--- a/src/components/BillingPage.js
+++ b/src/components/BillingPage.js
@@ -10,15 +10,15 @@ import React, { useState, useEffect } from "react";
import axios from "axios";
import AddNewItemForm from "./Form/AddNewItemForm";
+import RegisterItemForm from "./Form/RegisterItemForm";
+import MetaInfoForm from "./Form/MetaInfoForm";
import ItemsDisplay from "./Display/ItemsDisplay";
import SummaryDisplay from "./Display/SummaryDisplay";
-import MetaInfoForm from "./Form/MetaInfoForm";
const BillingPage = () => {
const [savedItems, getSavedItems] = useState([])
- // get data from server on startup
- useEffect(() => {
+ const getRegisteredItems = () => {
axios.get(`/api/items`)
.then((res) => {
getSavedItems(res.data);
@@ -27,8 +27,13 @@ const BillingPage = () => {
alert("The promise returned an error idk what to do");
console.log(res);
})
+ }
+
+ // get data from server on startup
+ useEffect(() => {
+ getRegisteredItems();
}, []);
- // to be handled by backend
+ // TODO: to be handled by backend
const defGSTValue = 18;
// update the items from AddNewItemForm
@@ -42,6 +47,7 @@ const BillingPage = () => {
return (
<>
<AddNewItemForm savedItems={savedItems} addItem={getItems} defGSTValue={defGSTValue}/>
+ <RegisterItemForm/>
<ItemsDisplay items={items} defGSTValue={defGSTValue}/>
<div className={"BillingPageFlex"}>
<MetaInfoForm/>
diff --git a/src/components/Form/AddNewItemForm.js b/src/components/Form/AddNewItemForm.js
index afd5259..5028af2 100644
--- a/src/components/Form/AddNewItemForm.js
+++ b/src/components/Form/AddNewItemForm.js
@@ -80,7 +80,7 @@ const AddNewItemForm = (props) => {
}>
<div className={"textInputs"}>
<label>
- Item:
+ Item/Service:
<select
value={itemNameValue}
onChange={
@@ -110,7 +110,7 @@ const AddNewItemForm = (props) => {
<div className={"numericInputs"}>
<label>
- Quantity: <input type="number" min="1" value={itemQtyValue} onInput={
+ Quantity:<input type="number" min="1" value={itemQtyValue} onInput={
(event) => {
const value = event.target.value;
setItemQtyValue(value);
@@ -156,10 +156,12 @@ const AddNewItemForm = (props) => {
</div>
<div className={"menuButtons"}>
+ <input type="button" value="Register New Item" onClick={() => {
+ alert("Coming Soon")
+ }} />
<input type="button" value="Placeholder1" />
<input type="button" value="Placeholder2" />
- <input type="button" value="Placeholder3" />
- <input type="submit" value="Panic" />
+ <input type="submit" value="Force Add" />
<input
type="submit"
value="add"
diff --git a/src/components/Form/Form.css b/src/components/Form/Form.css
index def42e5..ce94de4 100644
--- a/src/components/Form/Form.css
+++ b/src/components/Form/Form.css
@@ -1,3 +1,10 @@
+/*
+ * OpenBills - Self hosted browser app to generate and keep track of simple invoices
+ * Version - 0
+ * Licensed under the MIT license - https://opensource.org/licenses/MIT
+ *
+ * Copyright (c) 2021 Vidhu Kant Sharma
+*/
@import url("https://fonts.googleapis.com/css2?family=Quicksand:wght@500&display=swap");
/* Experimental color scheme */
/* light theme */
@@ -82,6 +89,27 @@ input[type=number] {
padding: 0.8rem 0;
border-bottom: 1px dotted lightblue; }
+.RegisterItemFormContainer {
+ /*display: none;*/
+ position: fixed;
+ width: 95%;
+ height: 70vh;
+ left: 0;
+ right: 0;
+ margin: auto;
+ top: 15vh;
+ background-color: #383A59; }
+
+.RegisterItemForm .textInputs,
+.RegisterItemForm .numericInputs {
+ width: 40%; }
+
+.RegisterItemForm {
+ width: 95%;
+ height: 60vh;
+ margin: 1rem auto;
+ justify-content: space-around; }
+
.MetaInfoForm {
width: 60%; }
diff --git a/src/components/Form/Form.scss b/src/components/Form/Form.scss
index 92f227a..f7a2d2e 100644
--- a/src/components/Form/Form.scss
+++ b/src/components/Form/Form.scss
@@ -10,6 +10,20 @@
$inputBorders: 1px solid $altBorderColor;
+/* hide arrows in numericInputs */
+/* Chrome, Safari, Edge, Opera */
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+/* Firefox */
+input[type=number] {
+ -moz-appearance: textfield;
+}
+
+
.formContainer {
/*border: 1px solid pink;*/
/*padding: 2rem;*/
@@ -72,19 +86,6 @@ label {
scrollbar-width: none; /* Firefox */
}
-/* hide arrows in numericInputs */
-/* Chrome, Safari, Edge, Opera */
-input::-webkit-outer-spin-button,
-input::-webkit-inner-spin-button {
- -webkit-appearance: none;
- margin: 0;
-}
-
-/* Firefox */
-input[type=number] {
- -moz-appearance: textfield;
-}
-
.addNewItemForm label {
display: flex;
justify-content: space-between;
@@ -92,6 +93,32 @@ input[type=number] {
border-bottom: 1px dotted $labelUnderlineColor;
}
+.RegisterItemFormContainer {
+ /*display: none;*/
+ position: fixed;
+
+ width: 95%;
+ height: 70vh;
+
+ left: 0;right: 0;
+ margin: auto;
+ top: 15vh;
+
+ background-color: $altBG;
+}
+
+.RegisterItemForm .textInputs,
+.RegisterItemForm .numericInputs {
+ width: 40%;
+}
+
+.RegisterItemForm {
+ width: 95%;
+ height: 60vh;
+ margin: 1rem auto;
+ justify-content: space-around;
+}
+
.MetaInfoForm {
width: 60%;
}
diff --git a/src/components/Form/RegisterItemForm.js b/src/components/Form/RegisterItemForm.js
new file mode 100644
index 0000000..1b38c8d
--- /dev/null
+++ b/src/components/Form/RegisterItemForm.js
@@ -0,0 +1,103 @@
+/*
+ * OpenBills - Self hosted browser app to generate and keep track of simple invoices
+ * Version - 0
+ * Licensed under the MIT license - https://opensource.org/licenses/MIT
+ *
+ * Copyright (c) 2021 Vidhu Kant Sharma
+*/
+
+// TODO: Code isn't tested properly
+// I'd be surprised if it has no bugs
+
+import React, { useState } from "react";
+import axios from "axios";
+import "./Form.css";
+
+
+const RegisterItemForm = () => {
+ // show/hide this component
+ const [visibility, setVisibility] = useState(true)// useState(props.visibility);
+
+ const [newItemNameValue, setNewItemNameValue] = useState("");
+ const [newItemDescValue, setNewItemDescValue] = useState("");
+ // const [newItemBrandValue, setNewItemBrandValue] = useState("");
+ // const [newItemTypeValue, setNewItemTypeValue] = useState("");
+ const [newItemPriceValue, setNewItemPriceValue] = useState("");
+ const [newItemHSNValue, setNewItemHSNValue] = useState("");
+ const [newItemGSTValue, setNewItemGSTValue] = useState("");
+
+
+ return (
+ <div className={"formContainer RegisterItemFormContainer"} style={{display: visibility ? "fixed" : "none"}}>
+ <form className={"addNewItemForm RegisterItemForm"} onSubmit={
+ (event) => {
+ event.preventDefault();
+ setVisibility(false);
+
+ axios.post(`/api/items/?model=${newItemNameValue}&desc=${newItemDescValue}&price=${newItemPriceValue}&hsn=${newItemHSNValue}&gst=${newItemGSTValue}`)
+ .then((res) => {
+ console.log(res);
+ })
+ .catch((err) => {
+ console.log(err);
+ });
+ }
+ }>
+ <div className={"textInputs"}>
+ <label>
+ Item/Service: <input type="text" value={newItemNameValue} onChange={
+ (event) => {
+ setNewItemNameValue(event.target.value);
+ }
+ } required />
+ </label>
+
+ <label>
+ Description: <input type="text" value={newItemDescValue} onChange={
+ (event) => {
+ setNewItemDescValue(event.target.value);
+ }
+ } />
+ </label>
+ </div>
+
+ <div className={"numericInputs"}>
+ <label>
+ Price: <input type="number" min="1.00" step="0.001" value={newItemPriceValue} onChange={
+ (event) => {
+ const value = event.target.value;
+ setNewItemPriceValue(value);
+ }
+ } />
+ </label>
+
+ <label>
+ HSN: <input type="number" min="0" value={newItemHSNValue} onChange={
+ (event) => {
+ const value = event.target.value;
+ setNewItemHSNValue(value);
+ }
+ } />
+ </label>
+
+ <label>
+ GST: <input type="number" min="0" value={newItemGSTValue} onChange={
+ (event) => {
+ const value = event.target.value;
+ setNewItemGSTValue(value);
+ }
+ } />
+ </label>
+ </div>
+
+ <input
+ type="submit"
+ value="Register/Add"
+ disabled={newItemNameValue !== "" ? "" : "disabled"}
+ />
+ </form>
+ </div>
+ );
+}
+
+export default RegisterItemForm;