feat: basic crud complete

This commit is contained in:
Mike 2025-01-20 19:24:37 -05:00
parent 6fb88b315a
commit 77a93ae9b1
10 changed files with 105 additions and 27 deletions

View file

@ -68,6 +68,21 @@ h6 {
isolation: isolate;
}
/*
* remove dumb stuff
*/
/* 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;
}
li {
list-style-type: none;
}
@ -106,6 +121,10 @@ nav {
font-size: 1.5rem;
}
a {
text-decoration: none;
}
.container {
width: 100%;
max-width: 800px;
@ -118,7 +137,7 @@ nav {
.btn {
padding: 0.5em 1em;
margin: 1em;
width: 100%;
}
.container.flex {
@ -137,10 +156,12 @@ nav {
.items-table {
width: 80%;
border-collapse: collapse;
table-layout: fixed;
}
.form-item {
display: flex;
flex-direction: column;
}
.form-item.btn-row {

View file

@ -1,14 +1,17 @@
function addForm() {
let buttonClicked = true;
const addForm = document.querySelector(".add-form");
const button = document.querySelector(".add-btn");
const addFormClass = document.querySelector(".add-form");
button.addEventListener("click", () => {
buttonClicked
? (addForm.style.display = " block")
: (addForm.style.display = "none");
buttonClicked = !buttonClicked;
});
if (addFormClass != null) {
const button = document.querySelector(".add-btn");
button.addEventListener("click", () => {
buttonClicked
? (addFormClass.style.display = " block")
: (addFormClass.style.display = "none");
buttonClicked = !buttonClicked;
});
}
}
export { addForm };

View file

@ -5,6 +5,9 @@ function formInput(props) {
formItemDiv.classList.add("form-item");
const input = document.createElement("input");
input.name = props.name;
input.required = true;
input.type = props.type;
if (props.type === "number") input.step = "0.01";
const label = document.createElement("label");
label.textContent = props.labelText;
formItemDiv.append(label, input);
@ -17,23 +20,30 @@ async function modal() {
div.classList.add("modal");
div.style = `
display: none;
positino: fixed;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 50vh;
height: 100vh;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.4);
justify-content: center;
align-items: center;
backdrop-filter: blur(15px);
`;
const form = document.createElement("form");
form.method = "POST";
form.action = "/item";
const name = formInput({ labelText: "Name", name: "name" });
const price = formInput({ labelText: "Price", name: "price" });
const qty = formInput({ labelText: "QTY", name: "qty" });
const name = formInput({ labelText: "name", name: "name", type: "text" });
const price = formInput({
labelText: "price",
name: "price",
type: "number",
});
const qty = formInput({ labelText: "qty", name: "qty", type: "number" });
const categories = await categoryPicker();
const stores = await storePicker();
@ -44,12 +54,19 @@ async function modal() {
submitButton.textContent = "Add Item";
const closeButton = document.createElement("button");
closeButton.classList.add("btn");
closeButton.textContent = "Close";
closeButton.type = "button";
closeButton.addEventListener("click", () => {
div.style.display = "none";
});
form.append(name, price, qty, categories, stores, submitButton, closeButton);
const btns = document.createElement("div");
btns.classList.add("form-item");
btns.style.flexDirection = "row";
btns.append(submitButton, closeButton);
form.append(name, price, qty, categories, stores, btns);
div.append(form);
return div;

View file

@ -22,7 +22,7 @@ async function categoryPicker() {
formItemDiv.classList.add("form-item");
const formLabel = document.createElement("label");
formLabel.textContent = "Categories";
formLabel.textContent = "categories";
const select = document.createElement("select");
select.classList.add("categories-list-modal");

View file

@ -4,6 +4,7 @@ import { addForm } from "./components/addForm.js";
const newItemLink = document.querySelector("a[href='/add']");
const modalElement = await modal();
let modalToggle = false;
async function handleDelete(e) {
console.log(e.target);
}
@ -55,7 +56,13 @@ newItemLink.addEventListener("click", (e) => {
e.preventDefault();
modalToggle
? (modalElement.style.display = "none")
: (modalElement.style.display = "block");
: (modalElement.style.display = "flex");
modalToggle = !modalToggle;
});
modalElement.addEventListener("click", (e) => {
e.stopPropagation();
if (e.target === e.currentTarget) modalElement.style.display = "none";
modalToggle = !modalToggle;
});

View file

@ -122,13 +122,25 @@ async function itemEditGet(req, res, next) {
}
async function itemEditPost(req, res, next) {
const itemId = req.params.id;
console.log(itemId);
const { id, name, qty, price, category, store } = req.body;
const category_id = await db.getCategoryId({ name: category });
const store_id = await db.getStoreId({ name: store });
const update = {
id: id,
name: name,
qty: qty,
price: utils.convertToInteger(price),
category_id: category_id.category_id,
store_id: store_id.store_id,
};
const dbRes = await db.updateItem(update);
res.redirect("/");
}
async function itemDelete(req, res) {
console.log(req.body.name);
const itemId = await db.getItemByName(req.body.name);
if (itemId) db.deleteItem(itemId);
console.log(`Delted item: ${itemId}`);

View file

@ -33,6 +33,22 @@ async function insertItem(data) {
}
}
async function updateItem(item) {
const { id, name, price, qty, category_id, store_id } = item;
try {
await pool.query(
`UPDATE items
SET name=$1, price=$2, qty=$3, category_id=$4, store_id=$5
WHERE id=$6`,
[name, price, qty, category_id, store_id, id],
);
return null;
} catch (e) {
return e;
}
}
async function deleteItem(item) {
try {
const res = await pool.query("DELETE FROM items WHERE id = $1", [item.id]);
@ -46,7 +62,7 @@ async function getAllItemsWithRelationships() {
const { rows } = await pool.query(
`SELECT items.id, items.name, items.price, items.qty, category.name AS category_name, store.name AS store_name FROM items
LEFT JOIN category ON items.category_id = category.category_id
LEFT JOIN store ON items.store_id = store.store_id;`,
LEFT JOIN store ON items.store_id = store.store_id ORDER BY items.id;`,
);
return rows;
@ -117,6 +133,7 @@ module.exports = {
getAllItems,
getItemByName,
deleteItem,
updateItem,
getCategories,
getCategoryId,
getStores,

View file

@ -1,7 +1,9 @@
<h1 class="heading"><%= type %></h1>
<div class="container">
<%- include("card", {items: data}) %>
<button class="btn add-btn">New <%= type %></button>
</div>
<form method="POST" action="/<%= type %>" class="add-form">
<div class="container">
<div class="form-item">

View file

@ -1,4 +1,3 @@
<div class="container">
<% items.forEach(item => { %>
<div class="container flex">
<p class="title">
@ -11,4 +10,3 @@
</div>
<% }); %>
</div>

View file

@ -1,8 +1,9 @@
<form method="POST" action="/item/id">
<div class="form-item"><label>Name</label><input name="name" value="<%= item.name %>" /></div>
<div class="form-item"><label>Price</label><input name="price" value=<%= item.price %> /></div>
<div class="form-item"><label>QTY</label><input name="qty" value=<%= item.qty %> /></div>
<input type="hidden" value=<%= item.id %> name="id">
<div class="form-item"><label>Name</label><input name="name" value="<%= item.name %>" required /></div>
<div class="form-item"><label>Price</label><input name="price" value=<%= (item.price/100).toFixed(2) %> type="number" step="0.01" required /></div>
<div class="form-item"><label>QTY</label><input name="qty" value=<%= item.qty %> type="number" required /></div>
<div class="form-item">
<label>Categories</label>
<select class="categories-list" name="category">
@ -29,6 +30,6 @@
<% }); %>
</select>
</div>
<button type="submit" class="btn">Add Item</button><button>Close</button>
<button type="submit" class="btn">UPDATE ITEM</button><button class="btn">RETURN</button>
</form>