Skip to content

Commit 1cee3ad

Browse files
committed
first commit
0 parents  commit 1cee3ad

3 files changed

Lines changed: 368 additions & 0 deletions

File tree

index.html

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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>Document</title>
8+
<link rel="stylesheet" href="style.css">
9+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"
10+
integrity="sha512-Evv84Mr4kqVGRNSgIGL/F/aIDqQb7xQ2vcrdIwxfjThSH8CSR7PBEakCr51Ck+w+/U6swU2Im1vVX0SVk9ABhg=="
11+
crossorigin="anonymous" referrerpolicy="no-referrer" />
12+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"
13+
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
14+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"
15+
integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz"
16+
crossorigin="anonymous"></script>
17+
</head>
18+
19+
<body>
20+
<div class="container" style="width: 1000px;">
21+
<h1 class="text-center bg-primary text-light p-2 rounded mt-5">PRODUCTS MANAGEMENT</h1>
22+
23+
<div class="inputs mt-5">
24+
<div class="form-floating mb-3">
25+
<input type="text" id="products" name="products" class="form-control form-control-sm" placeholder="">
26+
<label for="products" class="mx-1 for-label">Product</label>
27+
<div id="productValidation" class=""></div>
28+
</div>
29+
<div class="row">
30+
<div class="col form-floating mb-3">
31+
<input onkeyup="CalculTotal()" type="number" id="price" name="price"
32+
class="form-control form-control-sm" placeholder="">
33+
<label for="price" class="mx-3 for-label">Price</label>
34+
<div id="priceValidation" class=""></div>
35+
</div>
36+
<div class="col form-floating mb-3">
37+
<input onkeyup="CalculTotal()" type="number" id="taxes" name="taxes"
38+
class="form-control form-control-sm" placeholder="">
39+
<label for="taxes" class="mx-3 for-label">Taxes</label>
40+
</div>
41+
<div class="col form-floating mb-3">
42+
<input onkeyup="CalculTotal()" type="number" id="ads" name="ads"
43+
class=" form-control form-control-sm" placeholder="">
44+
<label for="ads" class="mx-3 for-label">Ads</label>
45+
</div>
46+
<div class="col form-floating mb-3">
47+
<input onkeyup="CalculTotal()" type="number" id="discount" name="discount"
48+
class="form-control form-control-sm" placeholder="">
49+
<label for="discount" class="mx-3 for-label">Discount</label>
50+
</div>
51+
<div class="col mb-3">
52+
<small class="form-control align-content-center bg-primary text-light" style="height: 58px;"
53+
id="total">0</small>
54+
</div>
55+
</div>
56+
<div class="form-floating mb-3">
57+
<input type="number" id="count" name="count" class="form-control form-control-sm" placeholder="">
58+
<label for="count" class="for-label">Count</label>
59+
</div>
60+
<div class="form-floating mb-3">
61+
<input type="text" id="category" name="category" class="form-control form-control-sm" placeholder="">
62+
<label for="category" class="for-label">Category</label>
63+
<div id="categoryValidation" class=""></div>
64+
</div>
65+
<div class="mb-3">
66+
<input type="submit" id="create" class="btn btn-primary" style="width: 100%;" value="Create">
67+
</div>
68+
</div>
69+
<div class="outputs mb-3">
70+
<div class="form-floating mb-3">
71+
<input type="search" id="search" name="search" class="form-control form-control-sm" placeholder="">
72+
<label for="search" id="labelSearch" class="for-label">Search</label>
73+
</div>
74+
<div class="row mb-2">
75+
<div class="col form-floating mb-3">
76+
<input onclick="getSearchMood(this.id)" type="button" class="btn btn-primary" style="width: 100%;"
77+
id="searchProduct" value="Search By Product">
78+
</div>
79+
<div class="col form-floating mb-3">
80+
<input onclick="getSearchMood(this.id)" type="button" class="btn btn-primary" style="width: 100%;"
81+
id="searchCategory" value="Search By Category">
82+
</div>
83+
</div>
84+
<input id="deleteAll" type="button" class="btn btn-primary deletehide mb-3 " style="width: 100%;"
85+
value="Delete All">
86+
<div class="rad bg-light ">
87+
<table class="table table-hover table-light radius rad text-center ">
88+
<thead>
89+
<tr>
90+
<th>ID</th>
91+
<th>Product</th>
92+
<th>Price</th>
93+
<th>Taxes</th>
94+
<th>Ads</th>
95+
<th>Discount</th>
96+
<th>Category</th>
97+
<th>Total</th>
98+
<th></th>
99+
<th></th>
100+
</tr>
101+
</thead>
102+
<tbody id="tbody" class="table-hover">
103+
104+
</tbody>
105+
</table>
106+
</div>
107+
</div>
108+
</div>
109+
<script src="/main.js"></script>
110+
</body>
111+
112+
</html>

main.js

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
let products = document.getElementById('products');
2+
let price = document.getElementById('price');
3+
let taxes = document.getElementById('taxes');
4+
let ads = document.getElementById('ads');
5+
let discount = document.getElementById('discount');
6+
let total = document.getElementById('total');
7+
let count = document.getElementById('count');
8+
let category = document.getElementById('category');
9+
let create = document.getElementById('create');
10+
let deleteAll = document.getElementById('deleteAll');
11+
let search = document.getElementById('search');
12+
let labelSearch = document.getElementById('labelSearch');
13+
let SearchMood = 'products';
14+
let productValidation = document.getElementById('productValidation');
15+
let priceValidation = document.getElementById('priceValidation');
16+
let categoryValidation = document.getElementById('categoryValidation');
17+
18+
let productData = localStorage.productStorage ? JSON.parse(localStorage.productStorage) : [];
19+
20+
// function-total
21+
function CalculTotal() {
22+
if (price.value !== '') {
23+
let result = (+price.value + +taxes.value + +ads.value) - +discount.value;
24+
total.innerHTML = result;
25+
total.classList.remove("bg-primary");
26+
total.classList.add("bg-success");
27+
} else {
28+
total.innerHTML = " ";
29+
total.classList.remove("bg-success");
30+
total.classList.add("bg-primary");
31+
}
32+
}
33+
34+
35+
36+
37+
38+
// function-create-validation
39+
function createProduct() {
40+
let productObject = {
41+
products: products.value.trim().replace(/^[^a-zA-Z]+/, ''),
42+
price: price.value,
43+
taxes: taxes.value || '0',
44+
ads: ads.value || '0',
45+
discount: discount.value || '0',
46+
total: total.innerHTML,
47+
count: count.value,
48+
category: category.value.trim().replace(/^[^a-zA-Z]+/, ''),
49+
}
50+
if (productObject.products && price.value && productObject.category && +price.value >= 0) {
51+
for (let i = 0; i < (productObject.count > 1 ? productObject.count : 1); i++) {
52+
productData.push(productObject);
53+
}
54+
localStorage.setItem('productStorage', JSON.stringify(productData));
55+
clearInputs();
56+
readData();
57+
} else {
58+
validateInputs(productObject);
59+
}
60+
}
61+
62+
function validateInputs(productObject) {
63+
if (!productObject.products) {
64+
products.classList.add('is-invalid');
65+
productValidation.classList.add('invalid-feedback');
66+
productValidation.innerHTML = '* It must contain letters';
67+
} else {
68+
products.classList.remove('is-invalid');
69+
products.classList.add('is-valid');
70+
productValidation.classList.remove('invalid-feedback');
71+
productValidation.innerHTML = '';
72+
}
73+
if (!price.value || +price.value < 0) {
74+
price.classList.add('is-invalid');
75+
priceValidation.classList.add('invalid-feedback');
76+
priceValidation.innerHTML = '* Price is required';
77+
78+
} else {
79+
price.classList.remove('is-invalid');
80+
price.classList.add('is-valid');
81+
priceValidation.classList.remove('invalid-feedback');
82+
priceValidation.innerHTML = '';
83+
price.classList.remove('bg-danger');
84+
}
85+
if (!productObject.category) {
86+
category.classList.add('is-invalid');
87+
categoryValidation.classList.add('invalid-feedback');
88+
categoryValidation.innerHTML = '* It must contain letters';
89+
} else {
90+
category.classList.remove('is-invalid');
91+
category.classList.add('is-valid');
92+
categoryValidation.classList.remove('invalid-feedback');
93+
categoryValidation.innerHTML = '';
94+
}
95+
}
96+
97+
create.onclick = createProduct;
98+
99+
// function-clear-inputs-validation
100+
function clearInputs() {
101+
products.value = '';
102+
price.value = '';
103+
taxes.value = '';
104+
ads.value = '';
105+
discount.value = '';
106+
total.innerHTML = '0';
107+
count.value = '';
108+
category.value = '';
109+
total.classList.remove("bg-success");
110+
total.classList.add("bg-primary");
111+
products.classList.remove('is-invalid', 'is-valid');
112+
productValidation.classList.remove('invalid-feedback');
113+
productValidation.innerHTML = '';
114+
price.classList.remove('is-invalid', 'is-valid', 'bg-danger');
115+
priceValidation.classList.remove('invalid-feedback');
116+
priceValidation.innerHTML = '';
117+
category.classList.remove('is-invalid', 'is-valid');
118+
categoryValidation.classList.remove('invalid-feedback');
119+
categoryValidation.innerHTML = '';
120+
}
121+
122+
// function-read
123+
function readData() {
124+
let table = '';
125+
for (let i = 0; i < productData.length; i++) {
126+
table += `
127+
<tr>
128+
<td>${i}</td>
129+
<td>${productData[i].products}</td>
130+
<td>${productData[i].price}</td>
131+
<td>${productData[i].taxes}</td>
132+
<td>${productData[i].ads}</td>
133+
<td>${productData[i].discount}</td>
134+
<td>${productData[i].category}</td>
135+
<td>${productData[i].total}</td>
136+
<td><button class="btn btn-primary" onclick="updateProduct(${i})"><i class="fa-solid fa-pen-to-square"></i></button></td>
137+
<td><button class="btn btn-danger" onclick="deleteProduct(${i})"><i class="fa-solid fa-trash"></i></button></td>
138+
</tr>`;
139+
}
140+
document.getElementById('tbody').innerHTML = table;
141+
if (productData.length > 0) {
142+
deleteAll.classList.remove('deletehide');
143+
deleteAll.classList.add('deleteshow');
144+
deleteAll.value = `Delete All (${productData.length})`;
145+
} else {
146+
deleteAll.classList.remove('deleteshow');
147+
deleteAll.classList.add('deletehide');
148+
deleteAll.value = `Delete All`;
149+
}
150+
}
151+
readData();
152+
153+
// function-delete
154+
function deleteProduct(i) {
155+
productData.splice(i, 1);
156+
localStorage.setItem('productStorage', JSON.stringify(productData));
157+
readData();
158+
}
159+
160+
// delete-all
161+
deleteAll.onclick = function () {
162+
productData = [];
163+
localStorage.setItem('productStorage', JSON.stringify(productData));
164+
readData();
165+
}
166+
167+
// function-update
168+
function updateProduct(i) {
169+
products.value = productData[i].products;
170+
price.value = productData[i].price;
171+
taxes.value = productData[i].taxes || '0';
172+
ads.value = productData[i].ads || '0';
173+
discount.value = productData[i].discount || '0';
174+
total.innerHTML = productData[i].total;
175+
count.value = productData[i].count;
176+
category.value = productData[i].category;
177+
productData.splice(i, 1);
178+
localStorage.setItem('productStorage', JSON.stringify(productData));
179+
readData();
180+
}
181+
182+
// function-search
183+
function getSearchMood(id) {
184+
if (id === 'searchProduct') {
185+
SearchMood = 'products';
186+
labelSearch.innerHTML = 'Search By Products';
187+
} else {
188+
SearchMood = 'category';
189+
labelSearch.innerHTML = 'Search By Category';
190+
}
191+
search.focus();
192+
}
193+
194+
search.oninput = function () {
195+
let searchValue = search.value.trimStart().toLowerCase();
196+
let table = '';
197+
for (let i = 0; i < productData.length; i++) {
198+
if (SearchMood === 'products' && productData[i].products.toLowerCase().includes(searchValue)) {
199+
table += `
200+
<tr>
201+
<td>${i}</td>
202+
<td>${productData[i].products}</td>
203+
<td>${productData[i].price}</td>
204+
<td>${productData[i].taxes}</td>
205+
<td>${productData[i].ads}</td>
206+
<td>${productData[i].discount}</td>
207+
<td>${productData[i].category}</td>
208+
<td>${productData[i].total}</td>
209+
<td><button class="btn btn-primary" onclick="updateProduct(${i})">Update</button></td>
210+
<td><button class="btn btn-primary" onclick="deleteProduct(${i})">Delete</button></td>
211+
</tr>`;
212+
} else if (SearchMood === 'category' && productData[i].category.toLowerCase().includes(searchValue)) {
213+
table += `
214+
<tr>
215+
<td>${i}</td>
216+
<td>${productData[i].products}</td>
217+
<td>${productData[i].price}</td>
218+
<td>${productData[i].taxes}</td>
219+
<td>${productData[i].ads}</td>
220+
<td>${productData[i].discount}</td>
221+
<td>${productData[i].category}</td>
222+
<td>${productData[i].total}</td>
223+
<td><button class="btn btn-primary" onclick="updateProduct(${i})">Update</button></td>
224+
<td><button class="btn btn-primary" onclick="deleteProduct(${i})">Delete</button></td>
225+
</tr>`;
226+
}
227+
}
228+
document.getElementById('tbody').innerHTML = table;
229+
}
230+
231+
// function-clean-data
232+
function cleanData() {
233+
productData = productData.filter(product => product.products && product.price && product.category);
234+
localStorage.setItem('productStorage', JSON.stringify(productData));
235+
readData();
236+
}
237+
238+

style.css

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#total::before {
2+
content: 'Total: ';
3+
}
4+
5+
#total {
6+
transition: 0.5s;
7+
}
8+
9+
.rad {
10+
border-radius: 5px;
11+
border: 1px solid #d5d5d5;
12+
;
13+
overflow: hidden;
14+
}
15+
16+
.radius:hover {
17+
cursor: pointer;
18+
}

0 commit comments

Comments
 (0)