inventrack 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/api/index.js +13 -0
- package/backend/README.md +35 -0
- package/backend/data/db.json +1239 -0
- package/backend/package-lock.json +532 -0
- package/backend/package.json +8 -0
- package/frontend/README.md +22 -0
- package/frontend/assets/Icon.png +0 -0
- package/frontend/assets/IconSort.png +0 -0
- package/frontend/assets/activity-1.png +0 -0
- package/frontend/assets/activity-2.png +0 -0
- package/frontend/assets/activity-3.png +0 -0
- package/frontend/assets/activity-4.png +0 -0
- package/frontend/assets/card-icon-1.png +0 -0
- package/frontend/assets/card-icon-2.png +0 -0
- package/frontend/assets/card-icon-3.png +0 -0
- package/frontend/assets/card-icon-4.png +0 -0
- package/frontend/assets/login.png +0 -0
- package/frontend/assets/logo.png +0 -0
- package/frontend/categories.html +143 -0
- package/frontend/css/all.min.css +9 -0
- package/frontend/css/bootstrap.min.css +6 -0
- package/frontend/css/categories.css +359 -0
- package/frontend/css/dashboard.css +373 -0
- package/frontend/css/inventoryInsights.css +308 -0
- package/frontend/css/inventoryOverview.css +353 -0
- package/frontend/css/orders.css +632 -0
- package/frontend/css/products.css +364 -0
- package/frontend/css/signin.css +120 -0
- package/frontend/css/style.css +282 -0
- package/frontend/css/suppliers.css +136 -0
- package/frontend/dashboard.html +160 -0
- package/frontend/index.html +124 -0
- package/frontend/inventoryInsights.html +182 -0
- package/frontend/inventoryOverview.html +187 -0
- package/frontend/js/api.js +55 -0
- package/frontend/js/auth.js +70 -0
- package/frontend/js/bootstrap.bundle.min.js +7 -0
- package/frontend/js/categories.js +356 -0
- package/frontend/js/dashboard.js +341 -0
- package/frontend/js/inventoryInsights.js +396 -0
- package/frontend/js/inventoryOverview.js +503 -0
- package/frontend/js/orders.js +662 -0
- package/frontend/js/products.js +650 -0
- package/frontend/js/suppliers.js +535 -0
- package/frontend/js/utils.js +234 -0
- package/frontend/orders.html +216 -0
- package/frontend/products.html +152 -0
- package/frontend/suppliers.html +175 -0
- package/frontend/webfonts/fa-brands-400.woff2 +0 -0
- package/frontend/webfonts/fa-regular-400.woff2 +0 -0
- package/frontend/webfonts/fa-solid-900.woff2 +0 -0
- package/frontend/webfonts/fa-v4compatibility.woff2 +0 -0
- package/package.json +38 -0
- package/vercel.json +18 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
// * json-server --watch db.json --port 3000
|
|
2
|
+
|
|
3
|
+
// Fun for NavBar
|
|
4
|
+
function renderNavbar(activePage) {
|
|
5
|
+
// Top NavBar
|
|
6
|
+
const topNavbar = `
|
|
7
|
+
<nav class="navbar navbar-expand-lg px-4" style="background-color: var(--primary); height: var(--topbar-height);">
|
|
8
|
+
|
|
9
|
+
<a class="navbar-brand d-flex align-items-center gap-2 fw-bold text-white" href="dashboard.html">
|
|
10
|
+
<img src="assets/logo.png" alt="InvenTrack" width="32" height="32" class="rounded-circle" />
|
|
11
|
+
InvenTrack
|
|
12
|
+
</a>
|
|
13
|
+
|
|
14
|
+
<div class="ms-auto d-flex align-items-center gap-3">
|
|
15
|
+
<i class="fas fa-bell fs-5 text-white"></i>
|
|
16
|
+
<div>
|
|
17
|
+
<img src="https://cdn-icons-png.flaticon.com/512/149/149071.png" width="34" height="34" class="rounded-circle border border-white" role="button" data-bs-toggle="dropdown" alt="profile" />
|
|
18
|
+
<ul class="dropdown-menu dropdown-menu-end">
|
|
19
|
+
<li><a class="dropdown-item" href="#">Profile</a></li>
|
|
20
|
+
<li><hr class="dropdown-divider" /></li>
|
|
21
|
+
<li><a class="dropdown-item text-danger" href="index.html">Logout</a></li>
|
|
22
|
+
</ul>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
</nav>
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
// Second NavBar
|
|
30
|
+
const pages = [
|
|
31
|
+
{ label: "Dashboard", icon: "fa-gauge", href: "dashboard.html" },
|
|
32
|
+
{ label: "Products", icon: "fa-box", href: "products.html" },
|
|
33
|
+
{ label: "Categories", icon: "fa-tags", href: "categories.html" },
|
|
34
|
+
{ label: "Suppliers", icon: "fa-truck", href: "suppliers.html" },
|
|
35
|
+
{ label: "Orders", icon: "fa-cart-shopping", href: "orders.html" },
|
|
36
|
+
{ label: "InventoryInsights", icon: "fa-chart-bar", href: "inventoryInsights.html" },
|
|
37
|
+
{ label: "InventoryOverview", icon: "fa-chart-bar", href: "inventoryOverview.html" },
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
const navItems = pages
|
|
41
|
+
.map(
|
|
42
|
+
(page) => `
|
|
43
|
+
<li class="nav-item">
|
|
44
|
+
<a class="nav-link ${activePage === page.label ? "active" : ""}" href="${page.href}">
|
|
45
|
+
<i class="fas ${page.icon} me-1"></i>${((page.label).split('y')).join('y ')}
|
|
46
|
+
</a>
|
|
47
|
+
</li>
|
|
48
|
+
`,
|
|
49
|
+
)
|
|
50
|
+
.join("");
|
|
51
|
+
|
|
52
|
+
const secondNavbar = `
|
|
53
|
+
<nav class="navbar navbar-expand-lg px-4" style="background-color: #fff; border-bottom: 2px solid #e5e0f5;">
|
|
54
|
+
|
|
55
|
+
<a class="nav-link active d-flex d-lg-none align-items-center gap-2 fw-semibold" style="color: var(--primary);" href="#">
|
|
56
|
+
<i class="fas ${pages.find((p) => p.label === activePage)?.icon} me-1"></i>${activePage}
|
|
57
|
+
</a>
|
|
58
|
+
|
|
59
|
+
<button class="navbar-toggler ms-auto" type="button" data-bs-toggle="collapse" data-bs-target="#secondNavMenu">
|
|
60
|
+
<span class="navbar-toggler-icon"></span>
|
|
61
|
+
</button>
|
|
62
|
+
|
|
63
|
+
<div class="collapse navbar-collapse" id="secondNavMenu">
|
|
64
|
+
<ul class="navbar-nav flex-row flex-wrap gap-1 me-auto">
|
|
65
|
+
${navItems}
|
|
66
|
+
</ul>
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
</nav>
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
document.getElementById("top-navbar").innerHTML = topNavbar;
|
|
73
|
+
document.getElementById("second-navbar").innerHTML = secondNavbar;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function renderFooter() {
|
|
77
|
+
const footer = `
|
|
78
|
+
<div class="container">
|
|
79
|
+
<p>copyright@invenTrack.com</p>
|
|
80
|
+
</div>
|
|
81
|
+
`
|
|
82
|
+
document.getElementById('footer').innerHTML = footer;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// * Modal Helpers
|
|
86
|
+
|
|
87
|
+
const closeModal = function () {
|
|
88
|
+
modal.classList.add('hidden')
|
|
89
|
+
modalOverlay.classList.add('hidden')
|
|
90
|
+
}
|
|
91
|
+
const showModal = function () {
|
|
92
|
+
modal.classList.remove('hidden')
|
|
93
|
+
modalOverlay.classList.remove('hidden')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// * Search functionality (Should be suitable for all pages)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
// ^ search By Name
|
|
100
|
+
async function searchByName(endpoint, searchInputValue) {
|
|
101
|
+
let pageData = (await getData(`${endpoint}`)).data
|
|
102
|
+
let dataAfterFilteration = pageData.filter((data) => {
|
|
103
|
+
return data.name.toLowerCase().includes(searchInputValue.toLowerCase());
|
|
104
|
+
});
|
|
105
|
+
return dataAfterFilteration;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// ^ filter By Status
|
|
109
|
+
async function filterByStatus(selectValue, endpoint) {
|
|
110
|
+
let pageData = (await getData(`${endpoint}`)).data
|
|
111
|
+
if (!selectValue.value || selectValue.value !== 'all') {
|
|
112
|
+
return pageData.filter((data) => {
|
|
113
|
+
return data.status.toLowerCase() === selectValue.value.toLowerCase()
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
return pageData
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
// * Sort Functionality (Should be suitable for all pages)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
// * Pagination
|
|
129
|
+
|
|
130
|
+
// ~ notes for pagination in Yur HTML you should only add this html tag at the same level of your table of data
|
|
131
|
+
// * <div id="pagination" class="container w-50 d-flex align-items-center justify-content-between"> </div >
|
|
132
|
+
|
|
133
|
+
// & Calculate total pages number
|
|
134
|
+
function getTotalPages(totalCount, limit) {
|
|
135
|
+
return Math.ceil(totalCount / limit);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// & Rendering Pagination
|
|
139
|
+
// ^ Container > is the pagination container you want buttons inside
|
|
140
|
+
// ^ state > I added it in each js page so you can control pagination state using one VARIABLE (Object) istead ot multiple Variables
|
|
141
|
+
// ^ onPageChange > is a parameter representing the renderTable function which is used to render data in the table from the json file
|
|
142
|
+
|
|
143
|
+
// ! Don't forget to call it every time (After rendering data and if no products found also but not in < network error > (Getting data from json file))
|
|
144
|
+
|
|
145
|
+
function renderPagination(container, state, onPageChange) {
|
|
146
|
+
if (!container) {
|
|
147
|
+
console.error("Pagination container not found");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
container.innerHTML = "";
|
|
152
|
+
|
|
153
|
+
const totalPages = Math.ceil(state.totalCount / state.limit);
|
|
154
|
+
|
|
155
|
+
if (totalPages <= 1) return;
|
|
156
|
+
|
|
157
|
+
const prevBtn = document.createElement("button");
|
|
158
|
+
prevBtn.textContent = "Prev";
|
|
159
|
+
prevBtn.classList.add('prevBtn')
|
|
160
|
+
prevBtn.disabled = state.page === 1;
|
|
161
|
+
prevBtn.addEventListener("click", function () {
|
|
162
|
+
if (state.page > 1) {
|
|
163
|
+
state.page--;
|
|
164
|
+
onPageChange();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
container.appendChild(prevBtn);
|
|
168
|
+
|
|
169
|
+
for (let i = 1; i <= totalPages; i++) {
|
|
170
|
+
const btn = document.createElement("button");
|
|
171
|
+
btn.classList.add('pagePaginateBtn')
|
|
172
|
+
btn.textContent = i;
|
|
173
|
+
|
|
174
|
+
if (i === state.page) {
|
|
175
|
+
btn.classList.add("active");
|
|
176
|
+
btn.classList.add('colored')
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
btn.addEventListener("click", function () {
|
|
180
|
+
state.page = i;
|
|
181
|
+
onPageChange();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
container.appendChild(btn);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const nextBtn = document.createElement("button");
|
|
188
|
+
nextBtn.textContent = "Next";
|
|
189
|
+
nextBtn.classList.add('nextBtn')
|
|
190
|
+
nextBtn.disabled = state.page === totalPages;
|
|
191
|
+
nextBtn.addEventListener("click", function () {
|
|
192
|
+
if (state.page < totalPages) {
|
|
193
|
+
state.page++;
|
|
194
|
+
onPageChange();
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
container.appendChild(nextBtn);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
// * Validation
|
|
202
|
+
|
|
203
|
+
function validateInputs(regexForValidInput, inputElement, messageShowForUser) {
|
|
204
|
+
const value = inputElement.value.trim();
|
|
205
|
+
|
|
206
|
+
if (regexForValidInput.test(value)) {
|
|
207
|
+
inputElement.setCustomValidity("");
|
|
208
|
+
inputElement.style.border = "2px solid rgb(0, 208, 59)";
|
|
209
|
+
} else {
|
|
210
|
+
inputElement.setCustomValidity(messageShowForUser);
|
|
211
|
+
inputElement.reportValidity();
|
|
212
|
+
inputElement.style.border = "2px solid rgba(255, 89, 89, 0.89)";
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function validateSelect(selectValidate) {
|
|
217
|
+
if (selectValidate.value === "") {
|
|
218
|
+
selectValidate.setCustomValidity("Please select a value");
|
|
219
|
+
selectValidate.reportValidity();
|
|
220
|
+
selectValidate.style.border = "2px solid rgba(255, 89, 89, 0.89)";
|
|
221
|
+
} else {
|
|
222
|
+
selectValidate.setCustomValidity("");
|
|
223
|
+
selectValidate.style.border = "2px solid rgb(0, 208, 59)";
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
// * Get Stock Class
|
|
229
|
+
|
|
230
|
+
function getStockClass(quantity, minStock) {
|
|
231
|
+
if (quantity === 0) return "stock-critical";
|
|
232
|
+
if (quantity <= minStock) return "stock-critical";
|
|
233
|
+
return "stock-normal";
|
|
234
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Orders Page</title>
|
|
8
|
+
|
|
9
|
+
<link rel="stylesheet" href="css/bootstrap.min.css" />
|
|
10
|
+
<link rel="stylesheet" href="css/all.min.css" />
|
|
11
|
+
<link rel="stylesheet" href="css/style.css" />
|
|
12
|
+
<link rel="stylesheet" href="css/orders.css" />
|
|
13
|
+
</head>
|
|
14
|
+
|
|
15
|
+
<body class="orders-page">
|
|
16
|
+
<div id="top-navbar"></div>
|
|
17
|
+
<div id="second-navbar"></div>
|
|
18
|
+
|
|
19
|
+
<main class="orders-content">
|
|
20
|
+
<div class="container px-3 px-md-4 px-lg-5">
|
|
21
|
+
<!-- Header -->
|
|
22
|
+
<div
|
|
23
|
+
class="orders-header d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center gap-3">
|
|
24
|
+
<div>
|
|
25
|
+
<h1 class="orders-title">Purchase Orders</h1>
|
|
26
|
+
<p class="orders-subtitle mb-0">Manage orders from suppliers</p>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<button class="btn create-order-btn" data-bs-toggle="modal" data-bs-target="#createOrderModal">
|
|
30
|
+
<i class="fa-solid fa-plus"></i>
|
|
31
|
+
<span>Create Order</span>
|
|
32
|
+
</button>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<!-- Search -->
|
|
36
|
+
<div class="search-wrapper">
|
|
37
|
+
<i class="fa-solid fa-magnifying-glass search-icon"></i>
|
|
38
|
+
<input type="text" class="form-control order-search-input" placeholder="Search by Order ID or Supplier..." />
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<!-- Desktop / Tablet Table -->
|
|
42
|
+
<div class="orders-table-card d-none d-md-block">
|
|
43
|
+
<div class="table-responsive">
|
|
44
|
+
<table class="table orders-table align-middle mb-0">
|
|
45
|
+
<thead>
|
|
46
|
+
<tr>
|
|
47
|
+
<th>ORDER ID</th>
|
|
48
|
+
<th>SUPPLIER</th>
|
|
49
|
+
<th>ORDER DATE</th>
|
|
50
|
+
<th>ITEMS COUNT</th>
|
|
51
|
+
<th>TOTAL COST</th>
|
|
52
|
+
<th>STATUS</th>
|
|
53
|
+
<th class="text-center">ACTIONS</th>
|
|
54
|
+
</tr>
|
|
55
|
+
</thead>
|
|
56
|
+
|
|
57
|
+
<tbody id="ordersTableBody">
|
|
58
|
+
</tbody>
|
|
59
|
+
</table>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<div
|
|
63
|
+
class="table-footer d-flex flex-column flex-sm-row justify-content-between align-items-start align-items-sm-center gap-3">
|
|
64
|
+
<p class="results-text mb-0">Showing 1 to 4 of 28 orders</p>
|
|
65
|
+
|
|
66
|
+
<div class="pagination-custom d-flex align-items-center gap-2">
|
|
67
|
+
<button class="page-btn">
|
|
68
|
+
<i class="fa-solid fa-angle-left"></i>
|
|
69
|
+
</button>
|
|
70
|
+
<button class="page-btn active">1</button>
|
|
71
|
+
<button class="page-btn">2</button>
|
|
72
|
+
<button class="page-btn">3</button>
|
|
73
|
+
<button class="page-btn">
|
|
74
|
+
<i class="fa-solid fa-angle-right"></i>
|
|
75
|
+
</button>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<!-- Mobile Cards -->
|
|
81
|
+
<div class="orders-mobile d-block d-md-none" id="ordersMobile"></div>
|
|
82
|
+
</div>
|
|
83
|
+
</main>
|
|
84
|
+
|
|
85
|
+
<!-- Modal -->
|
|
86
|
+
<div class="modal fade create-order-modal" id="createOrderModal" tabindex="-1" aria-labelledby="createOrderModalLabel"
|
|
87
|
+
aria-hidden="true">
|
|
88
|
+
<div class="modal-dialog modal-dialog-centered modal-lg">
|
|
89
|
+
<div class="modal-content create-order-modal-content">
|
|
90
|
+
|
|
91
|
+
<!-- Header -->
|
|
92
|
+
<div class="modal-header create-order-modal-header">
|
|
93
|
+
<div class="d-flex align-items-center gap-3">
|
|
94
|
+
<div class="modal-icon-box">
|
|
95
|
+
<i class="fa-solid fa-cart-plus"></i>
|
|
96
|
+
</div>
|
|
97
|
+
<h5 class="modal-title create-order-modal-title" id="createOrderModalLabel">Create New Order</h5>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<button type="button" class="btn-close custom-close-btn" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<!-- Body -->
|
|
104
|
+
<div class="modal-body create-order-modal-body">
|
|
105
|
+
<form id="createOrderForm">
|
|
106
|
+
<div class="row g-3 mb-4">
|
|
107
|
+
<div class="col-12 col-md-6">
|
|
108
|
+
<label for="supplierSelect" class="form-label modal-label">Supplier</label>
|
|
109
|
+
<select id="supplierSelect" class="form-select modal-input">
|
|
110
|
+
<option selected>Select a supplier</option>
|
|
111
|
+
<option>Global Tech Solutions</option>
|
|
112
|
+
<option>Acme Corp</option>
|
|
113
|
+
<option>Logistics Hub</option>
|
|
114
|
+
<option>Office Supplies Co</option>
|
|
115
|
+
</select>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div class="col-12 col-md-6">
|
|
119
|
+
<label for="orderDate" class="form-label modal-label">Order Date</label>
|
|
120
|
+
<input type="date" id="orderDate" class="form-control modal-input" value="2023-10-24">
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<div class="order-items-header d-flex justify-content-between align-items-center flex-wrap gap-2 mb-3">
|
|
125
|
+
<h6 class="order-items-title mb-0">ORDER ITEMS</h6>
|
|
126
|
+
<button type="button" class="btn add-row-btn" id="addProductRowBtn">
|
|
127
|
+
<i class="fa-regular fa-circle-plus"></i>
|
|
128
|
+
Add Product Row
|
|
129
|
+
</button>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div class="items-table-wrapper mb-4">
|
|
133
|
+
<div class="table-responsive">
|
|
134
|
+
<table class="table modal-items-table align-middle mb-0">
|
|
135
|
+
<thead>
|
|
136
|
+
<tr>
|
|
137
|
+
<th>PRODUCT</th>
|
|
138
|
+
<th>QTY</th>
|
|
139
|
+
<th>COST</th>
|
|
140
|
+
<th></th>
|
|
141
|
+
</tr>
|
|
142
|
+
</thead>
|
|
143
|
+
<tbody id="orderItemsBody">
|
|
144
|
+
<tr>
|
|
145
|
+
<td>
|
|
146
|
+
<input type="text" class="form-control item-input" value="Wireless Mouse MX">
|
|
147
|
+
</td>
|
|
148
|
+
<td>
|
|
149
|
+
<input type="number" class="form-control item-input qty-input" value="12" min="1">
|
|
150
|
+
</td>
|
|
151
|
+
<td>
|
|
152
|
+
<input type="number" class="form-control item-input cost-input" value="24.99" min="0"
|
|
153
|
+
step="0.01">
|
|
154
|
+
</td>
|
|
155
|
+
<td class="text-end">
|
|
156
|
+
<button type="button" class="remove-row-btn" aria-label="Remove row">
|
|
157
|
+
<i class="fa-regular fa-trash-can"></i>
|
|
158
|
+
</button>
|
|
159
|
+
</td>
|
|
160
|
+
</tr>
|
|
161
|
+
|
|
162
|
+
<tr>
|
|
163
|
+
<td>
|
|
164
|
+
<input type="text" class="form-control item-input" value="Mechanical Keyboard K2">
|
|
165
|
+
</td>
|
|
166
|
+
<td>
|
|
167
|
+
<input type="number" class="form-control item-input qty-input" value="5" min="1">
|
|
168
|
+
</td>
|
|
169
|
+
<td>
|
|
170
|
+
<input type="number" class="form-control item-input cost-input" value="89.00" min="0"
|
|
171
|
+
step="0.01">
|
|
172
|
+
</td>
|
|
173
|
+
<td class="text-end">
|
|
174
|
+
<button type="button" class="remove-row-btn" aria-label="Remove row">
|
|
175
|
+
<i class="fa-regular fa-trash-can"></i>
|
|
176
|
+
</button>
|
|
177
|
+
</td>
|
|
178
|
+
</tr>
|
|
179
|
+
</tbody>
|
|
180
|
+
</table>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
<div class="d-flex justify-content-end">
|
|
185
|
+
<div class="total-card">
|
|
186
|
+
<div class="total-row small-row">
|
|
187
|
+
<span>Subtotal</span>
|
|
188
|
+
<span id="subtotalValue">$744.88</span>
|
|
189
|
+
</div>
|
|
190
|
+
<div class="total-row grand-total-row">
|
|
191
|
+
<span>Total Cost</span>
|
|
192
|
+
<span id="totalValue">$744.88</span>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
</form>
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
<!-- Footer -->
|
|
200
|
+
<div class="modal-footer create-order-modal-footer">
|
|
201
|
+
<button type="button" class="btn modal-cancel-btn" data-bs-dismiss="modal">Cancel</button>
|
|
202
|
+
<button type="button" class="btn modal-save-btn">Save Order</button>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
<footer id="footer"></footer>
|
|
209
|
+
|
|
210
|
+
<script src="js/bootstrap.bundle.min.js"></script>
|
|
211
|
+
<script src="js/utils.js"></script>
|
|
212
|
+
<script src="js/api.js"></script>
|
|
213
|
+
<script src="js/orders.js"></script>
|
|
214
|
+
</body>
|
|
215
|
+
|
|
216
|
+
</html>
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Products Page</title>
|
|
8
|
+
<!-- CSS -->
|
|
9
|
+
<link rel="stylesheet" href="css/bootstrap.min.css" />
|
|
10
|
+
<link rel="stylesheet" href="css/all.min.css" />
|
|
11
|
+
<link rel="stylesheet" href="css/style.css" />
|
|
12
|
+
<link rel="stylesheet" href="css/products.css">
|
|
13
|
+
</head>
|
|
14
|
+
|
|
15
|
+
<body>
|
|
16
|
+
<div id="top-navbar"></div>
|
|
17
|
+
<div id="second-navbar"></div>
|
|
18
|
+
|
|
19
|
+
<main>
|
|
20
|
+
<div class="container">
|
|
21
|
+
<div class="main-content w-100 mt-4 position-relative">
|
|
22
|
+
<div class="modal-wrapper hidden position-absolute justify-content-center align-items-start" id="modal">
|
|
23
|
+
<div class="modal-data">
|
|
24
|
+
<div class="modal-header d-flex flex-column">
|
|
25
|
+
<h2><span id="modalType"></span> Product</h2>
|
|
26
|
+
<p>Fill in the information belwo to update your inventory</p>
|
|
27
|
+
</div>
|
|
28
|
+
<form action="" id="productData" class="d-flex flex-column gap-3">
|
|
29
|
+
<div class="form-group d-flex flex-column">
|
|
30
|
+
<label for="product-name">Product Name</label>
|
|
31
|
+
<input type="text" required id="productName" placeholder="Enter Your Product Name" class="product-name"
|
|
32
|
+
name="productName">
|
|
33
|
+
</div>
|
|
34
|
+
<div class="form-row d-flex justify-content-between">
|
|
35
|
+
<div class="form-group d-flex flex-column">
|
|
36
|
+
<label for="productSKU">SKU</label>
|
|
37
|
+
<input type="text" class="product-sku" id="productSKU" name="sku" placeholder="WH-1000-PRO" required>
|
|
38
|
+
</div>
|
|
39
|
+
<div class="form-group d-flex flex-column">
|
|
40
|
+
<label for="productPrice">Price</label>
|
|
41
|
+
<input type="text" id="productPrice" placeholder="$ 100" class="product-price" name="price" required>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div class="form-row d-flex justify-content-between">
|
|
46
|
+
<div class="form-group d-flex flex-column">
|
|
47
|
+
<label for="category">Category</label>
|
|
48
|
+
<select name="category" id="category">
|
|
49
|
+
<option value="" selected>Select</option>
|
|
50
|
+
</select>
|
|
51
|
+
</div>
|
|
52
|
+
<div class="form-group d-flex flex-column">
|
|
53
|
+
<label for="supplier">Supplier</label>
|
|
54
|
+
<select name="supplier" id="supplier">
|
|
55
|
+
<option value="" selected>Select</option>
|
|
56
|
+
</select>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div class="form-row d-flex justify-content-between">
|
|
61
|
+
<div class="form-group d-flex flex-column">
|
|
62
|
+
<label for="initialQty">Initial Quantity</label>
|
|
63
|
+
<input type="text" class="product-qty" id="initialQty" name="Quantity" placeholder="100" required>
|
|
64
|
+
</div>
|
|
65
|
+
<div class="form-group d-flex flex-column">
|
|
66
|
+
<label for="reorderLevel">Reorder Level</label>
|
|
67
|
+
<input type="text" id="reorderLevel" placeholder="10" class="reorder-level" name="reoder-level"
|
|
68
|
+
required>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</form>
|
|
72
|
+
<div class="modal-btns mt-4 d-flex justify-content-between align-items-center">
|
|
73
|
+
<button class="cancel-btn" id="cancelBtn">Cancel</button>
|
|
74
|
+
<button class="save-product-btn" id="saveProduct"><i class="fa-solid fa-file-circle-check"></i> Save
|
|
75
|
+
Product</button>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
|
|
80
|
+
<div class="modal-overlay hidden position-absolute" id="modalOverlay"></div>
|
|
81
|
+
<div class="page-header d-flex align-items-center justify-content-between my-5">
|
|
82
|
+
<div class="page-title">
|
|
83
|
+
<h1 class="mb-1 fw-bold">Products</h1>
|
|
84
|
+
<p class="m-0">Manage all products and stock level</p>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="header-btns">
|
|
87
|
+
<button class="export-btn" id="exportBtn"><i class="fa-solid fa-download"></i> Export</button>
|
|
88
|
+
<button class="add-product" data-type="Add" id="addProductBtn"><i class="fa-solid fa-plus"></i> Add
|
|
89
|
+
Product</button>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<!-- section search -->
|
|
94
|
+
<section class="card p-4 border-0 mb-3">
|
|
95
|
+
<form class="row g-2">
|
|
96
|
+
<div class="col-9">
|
|
97
|
+
<input type="search" class="form-control rounded-4" placeholder="Search by Product name"
|
|
98
|
+
id="searchByProductName">
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div class="col-2">
|
|
102
|
+
<select class="form-select" id="formSelect">
|
|
103
|
+
<option value="" selected>Status: All</option>
|
|
104
|
+
<option value="in_stock">In Stock</option>
|
|
105
|
+
<option value="low_stock">Low Stock</option>
|
|
106
|
+
<option value="out_of_stock">Out of Stock</option>
|
|
107
|
+
</select>
|
|
108
|
+
</div> <!--form-select-->
|
|
109
|
+
|
|
110
|
+
<div class="col-1">
|
|
111
|
+
<div class="sorting border text-center py-2 px-2 rounded-3">
|
|
112
|
+
<img src="./assets/IconSort.png" class="m-auto mt-2">
|
|
113
|
+
</div> <!--sorting-->
|
|
114
|
+
</div>
|
|
115
|
+
</form>
|
|
116
|
+
</section> <!--cardSearch-->
|
|
117
|
+
|
|
118
|
+
<div class="products-card card">
|
|
119
|
+
<table class="table">
|
|
120
|
+
<thead>
|
|
121
|
+
<tr>
|
|
122
|
+
<th>Product Name</th>
|
|
123
|
+
<th>Category</th>
|
|
124
|
+
<th>Price</th>
|
|
125
|
+
<th>Stock</th>
|
|
126
|
+
<th>Status</th>
|
|
127
|
+
<th colspan="2">Actions</th>
|
|
128
|
+
</tr>
|
|
129
|
+
</thead>
|
|
130
|
+
<tbody class="table-body" id="tableBody">
|
|
131
|
+
|
|
132
|
+
</tbody>
|
|
133
|
+
</table>
|
|
134
|
+
<div class="table-footer">
|
|
135
|
+
<span id="inventoryTableInfo"></span>
|
|
136
|
+
<div class="pagination" id="pagination"></div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
</main>
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
<footer id="footer"></footer>
|
|
145
|
+
<!-- Scripts -->
|
|
146
|
+
<script src="js/bootstrap.bundle.min.js"></script>
|
|
147
|
+
<script src="js/api.js"></script>
|
|
148
|
+
<script src="js/utils.js"></script>
|
|
149
|
+
<script src="js/products.js"></script>
|
|
150
|
+
</body>
|
|
151
|
+
|
|
152
|
+
</html>
|