create-jinmankn-app 1.0.12 → 1.0.13

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.
Files changed (54) hide show
  1. package/package.json +1 -1
  2. package/templates/EPMS(Employee Payroll Managment System)/package-lock.json +13 -0
  3. package/templates/SMS(Stock Managment System)/backend-project/server.js +1 -1
  4. package/templates/SMS(Stock Managment System)/frontend-project/src/components/AppLayout.jsx +1 -1
  5. package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Login.jsx +1 -1
  6. package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Product.jsx +211 -78
  7. package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Profile.jsx +1 -1
  8. package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Register.jsx +1 -1
  9. package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Reports.jsx +1 -1
  10. package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Sales.jsx +6 -6
  11. package/templates/SMS(Stock Managment System)/frontend-project/src/pages/Warehouse.jsx +150 -44
  12. package/templates/SMS(Stock Managment System)/package-lock.json +13 -0
  13. package/templates/index/README.md +34 -0
  14. package/templates/index/backend/config/db.js +12 -0
  15. package/templates/index/backend/controllers/authController.js +88 -0
  16. package/templates/index/backend/controllers/departmentController.js +74 -0
  17. package/templates/index/backend/controllers/employeeController.js +204 -0
  18. package/templates/index/backend/controllers/positionController.js +78 -0
  19. package/templates/index/backend/controllers/reportController.js +45 -0
  20. package/templates/index/backend/middleware/auth.js +27 -0
  21. package/templates/index/backend/models/Department.js +15 -0
  22. package/templates/index/backend/models/Employee.js +73 -0
  23. package/templates/index/backend/models/Position.js +20 -0
  24. package/templates/index/backend/models/User.js +32 -0
  25. package/templates/index/backend/package-lock.json +2190 -0
  26. package/templates/index/backend/package.json +22 -0
  27. package/templates/index/backend/routes/authRoutes.js +11 -0
  28. package/templates/index/backend/routes/departmentRoutes.js +17 -0
  29. package/templates/index/backend/routes/employeeRoutes.js +19 -0
  30. package/templates/index/backend/routes/positionRoutes.js +17 -0
  31. package/templates/index/backend/routes/protectedRoutes.js +10 -0
  32. package/templates/index/backend/routes/reportRoutes.js +9 -0
  33. package/templates/index/backend/server.js +30 -0
  34. package/templates/index/frontend/README.md +16 -0
  35. package/templates/index/frontend/eslint.config.js +21 -0
  36. package/templates/index/frontend/index.html +13 -0
  37. package/templates/index/frontend/package-lock.json +3095 -0
  38. package/templates/index/frontend/package.json +31 -0
  39. package/templates/index/frontend/public/favicon.svg +1 -0
  40. package/templates/index/frontend/src/App.css +0 -0
  41. package/templates/index/frontend/src/App.jsx +35 -0
  42. package/templates/index/frontend/src/assets/hero.png +0 -0
  43. package/templates/index/frontend/src/components/DashboardLayout.jsx +90 -0
  44. package/templates/index/frontend/src/components/ProtectedRoute.jsx +9 -0
  45. package/templates/index/frontend/src/index.css +59 -0
  46. package/templates/index/frontend/src/main.jsx +11 -0
  47. package/templates/index/frontend/src/pages/DashboardHome.jsx +58 -0
  48. package/templates/index/frontend/src/pages/Department.jsx +150 -0
  49. package/templates/index/frontend/src/pages/Employee.jsx +366 -0
  50. package/templates/index/frontend/src/pages/Login.jsx +81 -0
  51. package/templates/index/frontend/src/pages/Position.jsx +169 -0
  52. package/templates/index/frontend/src/pages/Register.jsx +102 -0
  53. package/templates/index/frontend/src/pages/Reports.jsx +94 -0
  54. package/templates/index/frontend/vite.config.js +7 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-jinmankn-app",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "create-jinmankn-app": "./bin/index.js"
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "jinman-blueprint",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "jinman-blueprint",
9
+ "version": "1.0.0",
10
+ "license": "ISC"
11
+ }
12
+ }
13
+ }
@@ -25,7 +25,7 @@ app.use('/api/sales', salesRoutes);
25
25
  app.use('/api/warehouse', warehouseRoutes);
26
26
  app.use('/api/reports', reportRoutes);
27
27
 
28
- const PORT = 5001;
28
+ const PORT = 1000;
29
29
  app.listen(PORT, () => {
30
30
  console.log(`Server running on http://localhost:${PORT}`);
31
31
  });
@@ -23,7 +23,7 @@ function AppLayout({ title, subtitle, children }) {
23
23
  }
24
24
 
25
25
  axios
26
- .get('http://localhost:5001/api/auth/me', {
26
+ .get('http://localhost:1000/api/auth/me', {
27
27
  headers: { Authorization: `Bearer ${localStorage.getItem('token')}` },
28
28
  })
29
29
  .then((response) => {
@@ -17,7 +17,7 @@ function Login() {
17
17
  setLoading(true);
18
18
 
19
19
  try {
20
- const response = await axios.post('http://localhost:5001/api/auth/login', { email, password });
20
+ const response = await axios.post('http://localhost:1000/api/auth/login', { email, password });
21
21
  localStorage.setItem('token', response.data.token);
22
22
  localStorage.setItem('user', JSON.stringify(response.data.user));
23
23
  setMessage('Login successful');
@@ -1,8 +1,11 @@
1
- import { useState } from 'react';
1
+ import { useEffect, useState } from 'react';
2
2
  import axios from 'axios';
3
3
  import AppLayout from '../components/AppLayout';
4
4
 
5
+ const API_BASE = 'http://localhost:1000/api/product';
6
+
5
7
  function Product() {
8
+ const [products, setProducts] = useState([]);
6
9
  const [productCode, setProductCode] = useState('');
7
10
  const [productName, setProductName] = useState('');
8
11
  const [category, setCategory] = useState('');
@@ -11,6 +14,8 @@ function Product() {
11
14
  const [supplierName, setSupplierName] = useState('');
12
15
  const [dateReceived, setDateReceived] = useState('');
13
16
  const [message, setMessage] = useState('');
17
+ const [error, setError] = useState('');
18
+ const [editingId, setEditingId] = useState(null);
14
19
 
15
20
  const headers = {
16
21
  Authorization: `Bearer ${localStorage.getItem('token')}`,
@@ -24,96 +29,224 @@ function Product() {
24
29
  setQuantityInStock('');
25
30
  setSupplierName('');
26
31
  setDateReceived('');
32
+ setEditingId(null);
33
+ };
34
+
35
+ const fetchProducts = async () => {
36
+ try {
37
+ const response = await axios.get(`${API_BASE}/getproduct`, { headers });
38
+ setProducts(response.data);
39
+ } catch (err) {
40
+ setError('Failed to load products');
41
+ console.error(err);
42
+ }
27
43
  };
28
44
 
29
45
  const handleSubmit = async (e) => {
30
46
  e.preventDefault();
47
+ setError('');
48
+ setMessage('');
49
+
31
50
  try {
32
- await axios.post(
33
- 'http://localhost:5001/api/product/addproduct',
34
- {
35
- productCode,
36
- productName,
37
- category,
38
- unitPrice,
39
- quantityInStock,
40
- supplierName,
41
- dateReceived,
42
- },
43
- { headers }
44
- );
45
- setMessage('Product added');
51
+ if (editingId) {
52
+ await axios.put(
53
+ `${API_BASE}/updateproduct/${editingId}`,
54
+ {
55
+ productCode,
56
+ productName,
57
+ category,
58
+ unitPrice,
59
+ quantityInStock,
60
+ supplierName,
61
+ dateReceived,
62
+ },
63
+ { headers }
64
+ );
65
+ setMessage('Product updated successfully');
66
+ } else {
67
+ await axios.post(
68
+ `${API_BASE}/addproduct`,
69
+ {
70
+ productCode,
71
+ productName,
72
+ category,
73
+ unitPrice,
74
+ quantityInStock,
75
+ supplierName,
76
+ dateReceived,
77
+ },
78
+ { headers }
79
+ );
80
+ setMessage('Product added successfully');
81
+ }
46
82
  clearForm();
83
+ fetchProducts();
84
+ } catch (err) {
85
+ setError(err.response?.data?.message || 'Failed to save product');
86
+ console.error(err);
87
+ }
88
+ };
89
+
90
+ const handleEdit = (product) => {
91
+ setEditingId(product._id);
92
+ setProductCode(product.productCode || '');
93
+ setProductName(product.productName || '');
94
+ setCategory(product.category || '');
95
+ setUnitPrice(product.unitPrice || '');
96
+ setQuantityInStock(product.quantityInStock || '');
97
+ setSupplierName(product.supplierName || '');
98
+ setDateReceived(product.dateReceived ? product.dateReceived.split('T')[0] : '');
99
+ window.scrollTo({ top: 0, behavior: 'smooth' });
100
+ };
101
+
102
+ const handleDelete = async (id) => {
103
+ try {
104
+ await axios.delete(`${API_BASE}/deleteproduct/${id}`, { headers });
105
+ setMessage('Product deleted successfully');
106
+ fetchProducts();
47
107
  } catch (err) {
48
- console.log(err);
108
+ setError('Failed to delete product');
109
+ console.error(err);
49
110
  }
50
111
  };
51
112
 
113
+ useEffect(() => {
114
+ fetchProducts();
115
+ }, []);
116
+
52
117
  return (
53
118
  <AppLayout title="Product management" subtitle="Inventory">
54
- <div className="mx-auto max-w-xl">
55
- {message && <p className="alert-success mb-4">{message}</p>}
119
+ <div className="mx-auto max-w-6xl space-y-6">
120
+ <div className="card space-y-4 p-5">
121
+ {message && <p className="alert-success">{message}</p>}
122
+ {error && <p className="alert-error">{error}</p>}
123
+
124
+ <form onSubmit={handleSubmit} className="space-y-3">
125
+ <h2 className="text-lg font-semibold text-slate-800">
126
+ {editingId ? 'Edit product' : 'Add new product'}
127
+ </h2>
128
+ <div className="grid gap-4 sm:grid-cols-2">
129
+ <input
130
+ type="text"
131
+ placeholder="Product code"
132
+ value={productCode}
133
+ onChange={(e) => setProductCode(e.target.value)}
134
+ className="input-field"
135
+ required
136
+ />
137
+ <input
138
+ type="text"
139
+ placeholder="Product name"
140
+ value={productName}
141
+ onChange={(e) => setProductName(e.target.value)}
142
+ className="input-field"
143
+ required
144
+ />
145
+ <input
146
+ type="text"
147
+ placeholder="Category"
148
+ value={category}
149
+ onChange={(e) => setCategory(e.target.value)}
150
+ className="input-field"
151
+ required
152
+ />
153
+ <input
154
+ type="number"
155
+ placeholder="Unit price"
156
+ value={unitPrice}
157
+ onChange={(e) => setUnitPrice(e.target.value)}
158
+ className="input-field"
159
+ required
160
+ />
161
+ <input
162
+ type="number"
163
+ placeholder="Quantity in stock"
164
+ value={quantityInStock}
165
+ onChange={(e) => setQuantityInStock(e.target.value)}
166
+ className="input-field"
167
+ required
168
+ />
169
+ <input
170
+ type="text"
171
+ placeholder="Supplier name"
172
+ value={supplierName}
173
+ onChange={(e) => setSupplierName(e.target.value)}
174
+ className="input-field"
175
+ required
176
+ />
177
+ <input
178
+ type="date"
179
+ value={dateReceived}
180
+ onChange={(e) => setDateReceived(e.target.value)}
181
+ className="input-field"
182
+ required
183
+ />
184
+ </div>
185
+ <div className="flex flex-wrap gap-3">
186
+ <button type="submit" className="btn-primary">
187
+ {editingId ? 'Save changes' : 'Add product'}
188
+ </button>
189
+ {editingId && (
190
+ <button type="button" onClick={clearForm} className="btn-secondary">
191
+ Cancel
192
+ </button>
193
+ )}
194
+ </div>
195
+ </form>
196
+ </div>
56
197
 
57
- <form onSubmit={handleSubmit} className="card space-y-3 p-5">
58
- <input
59
- type="text"
60
- placeholder="Product code"
61
- value={productCode}
62
- onChange={(e) => setProductCode(e.target.value)}
63
- className="input-field"
64
- required
65
- />
66
- <input
67
- type="text"
68
- placeholder="Product name"
69
- value={productName}
70
- onChange={(e) => setProductName(e.target.value)}
71
- className="input-field"
72
- required
73
- />
74
- <input
75
- type="text"
76
- placeholder="Category"
77
- value={category}
78
- onChange={(e) => setCategory(e.target.value)}
79
- className="input-field"
80
- required
81
- />
82
- <input
83
- type="number"
84
- placeholder="Unit price"
85
- value={unitPrice}
86
- onChange={(e) => setUnitPrice(e.target.value)}
87
- className="input-field"
88
- required
89
- />
90
- <input
91
- type="number"
92
- placeholder="Quantity in stock"
93
- value={quantityInStock}
94
- onChange={(e) => setQuantityInStock(e.target.value)}
95
- className="input-field"
96
- required
97
- />
98
- <input
99
- type="text"
100
- placeholder="Supplier name"
101
- value={supplierName}
102
- onChange={(e) => setSupplierName(e.target.value)}
103
- className="input-field"
104
- required
105
- />
106
- <input
107
- type="date"
108
- value={dateReceived}
109
- onChange={(e) => setDateReceived(e.target.value)}
110
- className="input-field"
111
- required
112
- />
113
- <button type="submit" className="btn-primary">
114
- Add product
115
- </button>
116
- </form>
198
+ <div className="card p-5">
199
+ <h2 className="text-lg font-semibold text-slate-800">Products</h2>
200
+ {products.length === 0 ? (
201
+ <p className="mt-4 text-sm text-slate-500">No products available yet.</p>
202
+ ) : (
203
+ <div className="mt-4 overflow-x-auto">
204
+ <table className="min-w-full divide-y divide-slate-200 text-sm">
205
+ <thead>
206
+ <tr className="bg-slate-50 text-left text-slate-600">
207
+ <th className="px-4 py-3">Code</th>
208
+ <th className="px-4 py-3">Name</th>
209
+ <th className="px-4 py-3">Category</th>
210
+ <th className="px-4 py-3">Price</th>
211
+ <th className="px-4 py-3">Stock</th>
212
+ <th className="px-4 py-3">Supplier</th>
213
+ <th className="px-4 py-3">Received</th>
214
+ <th className="px-4 py-3">Actions</th>
215
+ </tr>
216
+ </thead>
217
+ <tbody className="divide-y divide-slate-200">
218
+ {products.map((product) => (
219
+ <tr key={product._id} className="hover:bg-slate-50">
220
+ <td className="px-4 py-3">{product.productCode}</td>
221
+ <td className="px-4 py-3">{product.productName}</td>
222
+ <td className="px-4 py-3">{product.category}</td>
223
+ <td className="px-4 py-3">{product.unitPrice}</td>
224
+ <td className="px-4 py-3">{product.quantityInStock}</td>
225
+ <td className="px-4 py-3">{product.supplierName}</td>
226
+ <td className="px-4 py-3">{product.dateReceived?.split('T')[0] || '-'}</td>
227
+ <td className="px-4 py-3 space-x-2">
228
+ <button
229
+ type="button"
230
+ onClick={() => handleEdit(product)}
231
+ className="btn-secondary"
232
+ >
233
+ Edit
234
+ </button>
235
+ <button
236
+ type="button"
237
+ onClick={() => handleDelete(product._id)}
238
+ className="btn-danger"
239
+ >
240
+ Delete
241
+ </button>
242
+ </td>
243
+ </tr>
244
+ ))}
245
+ </tbody>
246
+ </table>
247
+ </div>
248
+ )}
249
+ </div>
117
250
  </div>
118
251
  </AppLayout>
119
252
  );
@@ -8,7 +8,7 @@ function Profile() {
8
8
 
9
9
  const handleRetrieve = async () => {
10
10
  try {
11
- const response = await axios.get('http://localhost:5001/api/auth/me', {
11
+ const response = await axios.get('http://localhost:1000/api/auth/me', {
12
12
  headers: {
13
13
  Authorization: `Bearer ${localStorage.getItem('token')}`,
14
14
  },
@@ -18,7 +18,7 @@ function Register() {
18
18
  setLoading(true);
19
19
 
20
20
  try {
21
- const response = await axios.post('http://localhost:5001/api/auth/register', {
21
+ const response = await axios.post('http://localhost:1000/api/auth/register', {
22
22
  name,
23
23
  email,
24
24
  password,
@@ -12,7 +12,7 @@ function Reports() {
12
12
 
13
13
  const fetchReports = async () => {
14
14
  try {
15
- const res = await axios.get('http://localhost:5001/api/reports/summary', { headers });
15
+ const res = await axios.get('http://localhost:1000/api/reports/summary', { headers });
16
16
  setReports(res.data);
17
17
  } catch (err) {
18
18
  setError('Could not load reports');
@@ -29,7 +29,7 @@ function Sales() {
29
29
 
30
30
  const fetchProducts = async () => {
31
31
  try {
32
- const res = await axios.get('http://localhost:5001/api/product/getproduct', { headers });
32
+ const res = await axios.get('http://localhost:1000/api/product/getproduct', { headers });
33
33
  setProducts(res.data);
34
34
  } catch (error) {
35
35
  console.log(error);
@@ -38,7 +38,7 @@ function Sales() {
38
38
 
39
39
  const fetchWarehouses = async () => {
40
40
  try {
41
- const res = await axios.get('http://localhost:5001/api/warehouse/getwarehouse', { headers });
41
+ const res = await axios.get('http://localhost:1000/api/warehouse/getwarehouse', { headers });
42
42
  setWarehouses(res.data);
43
43
  } catch (error) {
44
44
  console.log(error);
@@ -47,7 +47,7 @@ function Sales() {
47
47
 
48
48
  const handleGet = async () => {
49
49
  try {
50
- const res = await axios.get('http://localhost:5001/api/sales/getsales', { headers });
50
+ const res = await axios.get('http://localhost:1000/api/sales/getsales', { headers });
51
51
  setTransactions(res.data);
52
52
  } catch (error) {
53
53
  console.log(error);
@@ -65,14 +65,14 @@ function Sales() {
65
65
  try {
66
66
  if (editId) {
67
67
  await axios.put(
68
- `http://localhost:5001/api/sales/updatesales/${editId}`,
68
+ `http://localhost:1000/api/sales/updatesales/${editId}`,
69
69
  { transactionDate, quantityMoved, transactionType, productId, warehouseId },
70
70
  { headers }
71
71
  );
72
72
  setMessage('Transaction updated successfully');
73
73
  } else {
74
74
  await axios.post(
75
- 'http://localhost:5001/api/sales/addsales',
75
+ 'http://localhost:1000/api/sales/addsales',
76
76
  { transactionDate, quantityMoved, transactionType, productId, warehouseId },
77
77
  { headers }
78
78
  );
@@ -87,7 +87,7 @@ function Sales() {
87
87
 
88
88
  const handledelete = async (id) => {
89
89
  try {
90
- await axios.delete(`http://localhost:5001/api/sales/deletesales/${id}`, { headers });
90
+ await axios.delete(`http://localhost:1000/api/sales/deletesales/${id}`, { headers });
91
91
  handleGet();
92
92
  } catch (error) {
93
93
  console.log(error);