sms-tps 1.0.0 → 1.0.1

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.
@@ -0,0 +1,388 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import {
3
+ FaClosedCaptioning,
4
+ FaPlus,
5
+ FaTimes,
6
+ FaTimesCircle,
7
+ } from "react-icons/fa";
8
+ import axios from "axios";
9
+ import toast from "react-hot-toast";
10
+
11
+ const Product = () => {
12
+ const port = 3400;
13
+ const API_URL = `http://localhost:${port}/api/product`;
14
+ const API_URL_W = `http://localhost:${port}/api/warehouse`;
15
+ const [data, setData] = useState([]);
16
+ const [dataW, setDataW] = useState([]);
17
+ const [model, setModel] = useState(false);
18
+ // About Form
19
+ const [formData, setFormData] = useState({
20
+ productCode: "",
21
+ productName: "",
22
+ category: "",
23
+ quantityInStock: "",
24
+ unitPrice: "",
25
+ supplierName: "",
26
+ dateReceived: "",
27
+ warehouse_id: "",
28
+ });
29
+ // About Form
30
+
31
+ // About Table
32
+
33
+ useEffect(() => {
34
+ const fecthData = async () => {
35
+ try {
36
+ const res = await axios.get(`${API_URL}/get`);
37
+ if (!res.data.success) {
38
+ return toast.error(res.data.message);
39
+ }
40
+ setData(res.data.product);
41
+ } catch (error) {
42
+ alert(error.message);
43
+ }
44
+ };
45
+ fecthData();
46
+ }, [formData]);
47
+
48
+ // About Table
49
+
50
+ useEffect(() => {
51
+ const fecthData = async () => {
52
+ try {
53
+ const res = await axios.get(`${API_URL_W}/get`);
54
+ if (!res.data.success) {
55
+ return toast.error(res.data.message);
56
+ }
57
+ setDataW(res.data.warehouse);
58
+ } catch (error) {
59
+ alert(error.message);
60
+ }
61
+ };
62
+ fecthData();
63
+ }, [formData]);
64
+
65
+ // About Form
66
+
67
+ const handleFormData = async (e) => {
68
+ const { name, value } = e.target;
69
+ setFormData({ ...formData, [name]: value });
70
+ };
71
+
72
+ const handleSubmit = async (e) => {
73
+ e.preventDefault();
74
+ try {
75
+ if (
76
+ !formData.productCode ||
77
+ !formData.productName ||
78
+ !formData.quantityInStock ||
79
+ !formData.supplierName ||
80
+ !formData.unitPrice ||
81
+ !formData.category ||
82
+ !formData.dateReceived ||
83
+ !formData.warehouse_id
84
+ ) {
85
+ return toast.error("You Must Fill all Field");
86
+ }
87
+
88
+ const res = await axios.post(`${API_URL}/add`, formData);
89
+ if (!res.data.success) {
90
+ return toast.error(res.data.message);
91
+ }
92
+ toast.success(res.data.message);
93
+ setFormData({
94
+ productCode: "",
95
+ productName: "",
96
+ category: "",
97
+ quantityInStock: "",
98
+ unitPrice: "",
99
+ supplierName: "",
100
+ dateReceived: "",
101
+ warehouse_id: "",
102
+ });
103
+ } catch (error) {
104
+ toast.error(error.message);
105
+ }
106
+ // About Form
107
+ };
108
+ return (
109
+ <div className="p-1 flex flex-col gap-2 w-full ">
110
+ <div className="bg-white/50 rounded-md px-4 py-2 flex justify-between items-center">
111
+ <h1 className="md:text-xl font-bold text-indigo-500 text-md">
112
+ Product
113
+ </h1>
114
+ <div
115
+ className="p-2 text-white/90 rounded-lg bg-green-500 flex items-center gap-2"
116
+ onClick={() => {
117
+ setModel(true);
118
+ }}
119
+ >
120
+ <FaPlus /> <p className="md:block hidden">Add Product</p>
121
+ </div>
122
+ </div>
123
+
124
+ <div className="bg-white/50 p-4 rounded-lg block md:hidden">
125
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-2">
126
+ {data.map((o, i) => (
127
+ <div className="w-full bg-white p-2 rounded-lg" key={i}>
128
+ <h1 className="text-gray-500">{i + 1}</h1>
129
+ <div className="flex justify-between">
130
+ <h1 className="font-semibold text-indigo-500">Product Code:</h1>
131
+ <p className="text-gray-800">{o.productCode}</p>
132
+ </div>
133
+ <div className="flex justify-between">
134
+ <h1 className="font-semibold text-indigo-500">Product Name:</h1>
135
+ <p className="text-gray-800">{o.productName}</p>
136
+ </div>
137
+ <div className="flex justify-between">
138
+ <h1 className="font-semibold text-indigo-500">Category:</h1>
139
+ <p className="text-gray-800">{o.category}</p>
140
+ </div>
141
+ <div className="flex justify-between">
142
+ <h1 className="font-semibold text-indigo-500">
143
+ Quantity In Stock:
144
+ </h1>
145
+ <p className="text-gray-800">{o.quantityInStock}</p>
146
+ </div>
147
+ <div className="flex justify-between">
148
+ <h1 className="font-semibold text-indigo-500">Unit Price:</h1>
149
+ <p className="text-gray-800">{o.unitPrice}</p>
150
+ </div>
151
+ <div className="flex justify-between gap-2">
152
+ <h1 className="font-semibold text-indigo-500">
153
+ Supplier Name:
154
+ </h1>
155
+ <p className="text-gray-800">{o.supplierName}</p>
156
+ </div>
157
+ <div className="flex justify-between gap-2">
158
+ <h1 className="font-semibold text-indigo-500">
159
+ Date Received:
160
+ </h1>
161
+ <p className="text-gray-800">{o.dateReceived}</p>
162
+ </div>
163
+ <div className="flex justify-between gap-2">
164
+ <h1 className="font-semibold text-indigo-500">
165
+ Warehouse Name:
166
+ </h1>
167
+ <p className="text-gray-800">{o.warehouse_id?.warehouseName}</p>
168
+ </div>
169
+ </div>
170
+ ))}
171
+ </div>
172
+ </div>
173
+ <div className="bg-white/50 p-4 md:flex flex-col gap-2 rounded-lg hidden ">
174
+ <div className="bg-white p-2 rounded-lg">
175
+ <table className="w-full">
176
+ <thead>
177
+ <tr className="text-sm text-indigo-500">
178
+ <th>No</th>
179
+ <th>Product Code</th>
180
+ <th>Product Name</th>
181
+ <th>Category</th>
182
+ <th>Quantity In Stock</th>
183
+ <th>Unit Price</th>
184
+ <th>Supplier Name</th>
185
+ <th>Date Received</th>
186
+ <th>Warehouse Name</th>
187
+ </tr>
188
+ </thead>
189
+ <tbody>
190
+ {data.map((o, i) => (
191
+ <tr key={i} className="text-sm text-center">
192
+ <td className="px-2 p-2">{i + 1}</td>
193
+ <td className="px-2">{o.productCode} </td>
194
+ <td className="px-2">{o.productName}</td>
195
+ <td className="px-2">{o.category}</td>
196
+ <td className="px-2">{o.quantityInStock}</td>
197
+ <td className="px-2">{o.unitPrice}</td>
198
+ <td className="px-2">{o.supplierName}</td>
199
+ <td className="px-2">{o.dateReceived}</td>
200
+ <td className="px-2">{o.warehouse_id?.warehouseName}</td>
201
+ </tr>
202
+ ))}
203
+ </tbody>
204
+ </table>
205
+ </div>
206
+ </div>
207
+ {model && (
208
+ <div
209
+ className="fixed flex items-center justify-center bg-indigo-500/35 w-full inset-0"
210
+ onClick={() => {
211
+ setModel(false);
212
+ }}
213
+ >
214
+ <div
215
+ className="bg-white/95 w-120 p-4 rounded-2xl"
216
+ onClick={(e) => {
217
+ e.stopPropagation();
218
+ }}
219
+ >
220
+ <form
221
+ onSubmit={handleSubmit}
222
+ className="flex
223
+ flex-col gap-4 w-full"
224
+ >
225
+ <div className="flex items-center justify-between p-4">
226
+ <h1 className="text-xl font-semibold text-green-500">
227
+ Add Product
228
+ </h1>
229
+ <div
230
+ className=""
231
+ onClick={() => {
232
+ setModel(false);
233
+ }}
234
+ >
235
+ <FaTimesCircle className="text-3xl text-indigo-500" />
236
+ </div>
237
+ </div>
238
+ <div className="grid grid-cols-1 gap-2 md:grid-cols-2">
239
+ <div className="flex flex-col gap-1">
240
+ <label
241
+ htmlFor="nationalId"
242
+ className="font-semibold text-md text-blue-400"
243
+ >
244
+ Product Code
245
+ </label>
246
+ <input
247
+ value={formData.productCode}
248
+ name="productCode"
249
+ onChange={handleFormData}
250
+ type="text"
251
+ placeholder="productCode"
252
+ className="px-3 py-1 rounded-md border border-blue-500 focus:outline-blue-300"
253
+ />
254
+ </div>
255
+ <div className="flex flex-col gap-1">
256
+ <label
257
+ htmlFor="first_name"
258
+ className="font-semibold text-md text-blue-400"
259
+ >
260
+ Product Name
261
+ </label>
262
+ <input
263
+ value={formData.productName}
264
+ onChange={handleFormData}
265
+ type="text"
266
+ name="productName"
267
+ placeholder="productName"
268
+ className="px-3 py-1 rounded-md border border- focus:outline-blue-300"
269
+ />
270
+ </div>
271
+ <div className="flex flex-col gap-1">
272
+ <label
273
+ htmlFor="last_name"
274
+ className="font-semibold text-md text-blue-400"
275
+ >
276
+ Category
277
+ </label>
278
+ <input
279
+ value={formData.category}
280
+ onChange={handleFormData}
281
+ type="text"
282
+ name="category"
283
+ placeholder="category"
284
+ className="px-3 py-1 rounded-md border border-blue-500 focus:outline-blue-300"
285
+ />
286
+ </div>
287
+ <div className="flex flex-col gap-1">
288
+ <label
289
+ htmlFor="email"
290
+ className="font-semibold text-md text-blue-400"
291
+ >
292
+ {" "}
293
+ Quantity In Stock
294
+ </label>
295
+ <input
296
+ value={formData.quantityInStock}
297
+ onChange={handleFormData}
298
+ type="number"
299
+ name="quantityInStock"
300
+ placeholder="quantityInStock"
301
+ className="px-3 py-1 rounded-md border border-blue-500 focus:outline-blue-300"
302
+ />
303
+ </div>
304
+ <div className="flex flex-col gap-1">
305
+ <label
306
+ htmlFor="telephone"
307
+ className="font-semibold text-md text-blue-400"
308
+ >
309
+ Unit Price
310
+ </label>
311
+ <input
312
+ value={formData.unitPrice}
313
+ type="number"
314
+ onChange={handleFormData}
315
+ name="unitPrice"
316
+ placeholder="unitPrice"
317
+ className="px-3 py-1 rounded-md border border-blue-500 focus:outline-blue-300"
318
+ />
319
+ </div>
320
+ <div className="flex flex-col gap-1">
321
+ <label
322
+ htmlFor="address"
323
+ className="font-semibold text-md text-blue-400"
324
+ >
325
+ Supplier Name
326
+ </label>
327
+ <input
328
+ value={formData.supplierName}
329
+ onChange={handleFormData}
330
+ type="text"
331
+ name="supplierName"
332
+ placeholder="Kigali / Rwanda - Kicukiro"
333
+ className="px-3 py-1 rounded-md border border-blue-500 focus:outline-blue-300"
334
+ />
335
+ </div>
336
+ <div className="flex flex-col gap-1">
337
+ <label
338
+ htmlFor="address"
339
+ className="font-semibold text-md text-blue-400"
340
+ >
341
+ Date Received
342
+ </label>
343
+ <input
344
+ value={formData.dateReceived}
345
+ onChange={handleFormData}
346
+ type="datetime-local"
347
+ name="dateReceived"
348
+ placeholder="dateReceived"
349
+ className="px-3 py-1 rounded-md border border-blue-500 focus:outline-blue-300"
350
+ />
351
+ </div>
352
+ <div className="flex flex-col gap-1">
353
+ <label
354
+ htmlFor="address"
355
+ className="font-semibold text-md text-blue-400"
356
+ >
357
+ Date Received
358
+ </label>
359
+ <select
360
+ name="warehouse_id"
361
+ value={formData.warehouse_id}
362
+ onChange={handleFormData}
363
+ className="px-3 py-1 rounded-md border border-blue-500 focus:outline-blue-300"
364
+ >
365
+ <option value="">Select Warehouse</option>
366
+ {dataW.map((w, i) => (
367
+ <option key={i} value={w._id}>
368
+ {w.warehouseName}
369
+ </option>
370
+ ))}
371
+ </select>
372
+ </div>
373
+ </div>
374
+ <button
375
+ type="submit"
376
+ className="bg-green-500 p-2 text-white/90 font-semibold rounded-md hover:rounded-2xl"
377
+ >
378
+ Register Product
379
+ </button>
380
+ </form>
381
+ </div>
382
+ </div>
383
+ )}
384
+ </div>
385
+ );
386
+ };
387
+
388
+ export default Product;
@@ -0,0 +1,162 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import {
3
+ FaClosedCaptioning,
4
+ FaPlus,
5
+ FaTimes,
6
+ FaTimesCircle,
7
+ } from "react-icons/fa";
8
+ import axios from "axios";
9
+ import toast from "react-hot-toast";
10
+
11
+ const Report = () => {
12
+ const port = 3400;
13
+ const API_URL = `http://localhost:${port}/api/warehouse`;
14
+ const API_URL_L = `http://localhost:${port}/api/product`;
15
+ const API_URL_T = `http://localhost:${port}/api/transfer`;
16
+ // End
17
+ // set Data in State From backend
18
+ const [data, setData] = useState([]);
19
+ const [transferData, setTransferData] = useState([]);
20
+ const [landData, setLandData] = useState([]);
21
+ // End
22
+ // About Form
23
+
24
+ const fecthData = async () => {
25
+ try {
26
+ const res = await axios.get(`${API_URL}/get`);
27
+ if (!res.data.success) {
28
+ return toast.error(res.data.message);
29
+ }
30
+ setData(res.data.warehouse);
31
+ } catch (error) {
32
+ alert(error.message);
33
+ }
34
+ };
35
+
36
+ const fecthDataL = async () => {
37
+ try {
38
+ const res = await axios.get(`${API_URL_L}/get`);
39
+ if (!res.data.success) {
40
+ return toast.error(res.data.message);
41
+ }
42
+ setLandData(res.data.product);
43
+ } catch (error) {
44
+ alert(error.message);
45
+ }
46
+ };
47
+
48
+ const fecthDataT = async () => {
49
+ try {
50
+ const res = await axios.get(`${API_URL_T}/get`);
51
+ if (!res.data.success) {
52
+ return toast.error(res.data.message);
53
+ }
54
+ setTransferData(res.data.transfer);
55
+ } catch (error) {
56
+ toast.error(error.message);
57
+ }
58
+ };
59
+
60
+ useEffect(() => {
61
+ fecthDataT();
62
+ fecthData();
63
+ fecthDataL();
64
+ }, []);
65
+
66
+
67
+ const dataReport = data.map((w)=>{
68
+ const warehouse = w.warehouseName;
69
+ const totalProduct = landData.filter((p)=>p.warehouse_id?._id === w._id).length
70
+ const totalInStock = landData.filter(
71
+ (pr) => pr.warehouse_id?._id === w._id,
72
+ )[0];
73
+ const totalOutStock = transferData.filter((t) => t.warehouse_id?._id === w._id)[0];
74
+ const warehouseLocation = w.warehouseLocation;
75
+
76
+ return ({
77
+ warehouse,
78
+ totalProduct,
79
+ InStock: totalInStock?.quantityInStock,
80
+ OutStock: totalOutStock?.quantityMoved,
81
+ warehouseLocation
82
+ });
83
+ })
84
+
85
+ console.log(dataReport)
86
+
87
+ // About Table
88
+ return (
89
+ <div className="p-1 flex flex-col gap-2 w-full ">
90
+ <div className="bg-white/50 rounded-md px-4 py-2 flex justify-between items-center">
91
+ <h1 className="md:text-xl font-bold text-indigo-500 text-md">
92
+ Project
93
+ </h1>
94
+ </div>
95
+ <div className="bg-white/50 p-4 rounded-lg block md:hidden">
96
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-2">
97
+ {dataReport.map((o, i) => (
98
+ <div className="w-full bg-white p-2 rounded-lg" key={i}>
99
+ <h1 className="text-gray-500">{i + 1}</h1>
100
+ <div className="flex justify-between">
101
+ <h1 className="font-semibold text-indigo-500">Warehouse:</h1>
102
+ <p className="text-gray-800">{o.warehouse}</p>
103
+ </div>
104
+ <div className="flex justify-between">
105
+ <h1 className="font-semibold text-indigo-500">
106
+ Total Product:
107
+ </h1>
108
+ <p className="text-gray-800">{o.totalProduct}</p>
109
+ </div>
110
+ <div className="flex justify-between">
111
+ <h1 className="font-semibold text-indigo-500">In Stock:</h1>
112
+ <p className="text-gray-800">{o.InStock}</p>
113
+ </div>
114
+ <div className="flex justify-between">
115
+ <h1 className="font-semibold text-indigo-500">Out Stock:</h1>
116
+ <p className="text-gray-800">{o.OutStock}</p>
117
+ </div>
118
+ <div className="flex justify-between">
119
+ <h1 className="font-semibold text-indigo-500">
120
+ Warehouse Location:
121
+ </h1>
122
+ <p className="text-gray-800">{o.warehouseLocation}</p>
123
+ </div>
124
+ </div>
125
+ ))}
126
+ </div>
127
+ </div>
128
+ <div className="bg-white/50 p-4 md:flex flex-col gap-2 rounded-lg hidden ">
129
+ <div className="bg-white p-2 rounded-lg">
130
+ <table className="w-full">
131
+ <thead>
132
+ <tr className="text-sm text-indigo-500">
133
+ <th>No</th>
134
+ <th>Warehouse</th>
135
+ <th>Total Product</th>
136
+ <th>In Stock</th>
137
+ <th>Out Stock</th>
138
+ <th>Warehouse Location</th>
139
+ </tr>
140
+ </thead>
141
+ <tbody>
142
+ {dataReport.map((o, i) => (
143
+ <tr key={i} className="text-sm text-center">
144
+ <td className="px-2 p-2">{i + 1}</td>
145
+ <td className="px-2">{o.warehouse} </td>
146
+ <td className="px-2">
147
+ {o.totalProduct}
148
+ </td>
149
+ <td className="px-2">{o.InStock}</td>
150
+ <td className="px-2">{o.OutStock}</td>
151
+ <td className="px-2">{o.warehouseLocation}</td>
152
+ </tr>
153
+ ))}
154
+ </tbody>
155
+ </table>
156
+ </div>
157
+ </div>
158
+ </div>
159
+ );
160
+ };
161
+
162
+ export default Report;