create-steve-rogers 1.0.0 → 1.0.2

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 (94) hide show
  1. package/apps/SFMS/.env +9 -0
  2. package/apps/SFMS/README.md +0 -0
  3. package/apps/SFMS/backend/.env +9 -0
  4. package/apps/SFMS/backend/.env.example +9 -0
  5. package/apps/SFMS/backend/package-lock.json +1580 -0
  6. package/apps/SFMS/backend/package.json +23 -0
  7. package/apps/SFMS/backend/src/config/database.js +7 -0
  8. package/apps/SFMS/backend/src/config/env.js +35 -0
  9. package/apps/SFMS/backend/src/middleware/authMiddleware.js +32 -0
  10. package/apps/SFMS/backend/src/models/Payment.js +12 -0
  11. package/apps/SFMS/backend/src/models/Student.js +12 -0
  12. package/apps/SFMS/backend/src/models/User.js +13 -0
  13. package/apps/SFMS/backend/src/routes/authRoutes.js +93 -0
  14. package/apps/SFMS/backend/src/routes/paymentRoutes.js +117 -0
  15. package/apps/SFMS/backend/src/routes/reportRoutes.js +59 -0
  16. package/apps/SFMS/backend/src/routes/studentRoutes.js +79 -0
  17. package/apps/SFMS/backend/src/server.js +34 -0
  18. package/apps/SFMS/frontend/.env.example +8 -0
  19. package/apps/SFMS/frontend/dist/assets/index-B08X8imN.css +1 -0
  20. package/apps/SFMS/frontend/dist/assets/index-DVO0_wcb.js +67 -0
  21. package/apps/SFMS/frontend/dist/favicon.svg +4 -0
  22. package/apps/SFMS/frontend/dist/index.html +20 -0
  23. package/apps/SFMS/frontend/index.html +19 -0
  24. package/apps/SFMS/frontend/package-lock.json +2667 -0
  25. package/apps/SFMS/frontend/package.json +23 -0
  26. package/apps/SFMS/frontend/postcss.config.js +6 -0
  27. package/apps/SFMS/frontend/public/favicon.svg +4 -0
  28. package/apps/SFMS/frontend/src/App.jsx +41 -0
  29. package/apps/SFMS/frontend/src/api/apiClient.js +41 -0
  30. package/apps/SFMS/frontend/src/components/AppLayout.jsx +60 -0
  31. package/apps/SFMS/frontend/src/context/AuthContext.jsx +79 -0
  32. package/apps/SFMS/frontend/src/index.css +229 -0
  33. package/apps/SFMS/frontend/src/main.jsx +16 -0
  34. package/apps/SFMS/frontend/src/pages/DashboardPage.jsx +82 -0
  35. package/apps/SFMS/frontend/src/pages/LoginPage.jsx +142 -0
  36. package/apps/SFMS/frontend/src/pages/PaymentsPage.jsx +269 -0
  37. package/apps/SFMS/frontend/src/pages/ReportsPage.jsx +114 -0
  38. package/apps/SFMS/frontend/src/pages/StudentsPage.jsx +257 -0
  39. package/apps/SFMS/frontend/tailwind.config.js +21 -0
  40. package/apps/SFMS/frontend/vite.config.js +35 -0
  41. package/apps/SIMS/.env +4 -0
  42. package/apps/SIMS/README.md +138 -0
  43. package/apps/SIMS/backend/.env +4 -0
  44. package/apps/SIMS/backend/.env.example +4 -0
  45. package/apps/SIMS/backend/package-lock.json +1600 -0
  46. package/apps/SIMS/backend/package.json +22 -0
  47. package/apps/SIMS/backend/src/config/db.js +9 -0
  48. package/apps/SIMS/backend/src/controllers/authController.js +93 -0
  49. package/apps/SIMS/backend/src/controllers/simsReportController.js +94 -0
  50. package/apps/SIMS/backend/src/controllers/sparePartController.js +41 -0
  51. package/apps/SIMS/backend/src/controllers/stockInController.js +45 -0
  52. package/apps/SIMS/backend/src/controllers/stockOutController.js +123 -0
  53. package/apps/SIMS/backend/src/middleware/auth.js +8 -0
  54. package/apps/SIMS/backend/src/models/SparePart.js +17 -0
  55. package/apps/SIMS/backend/src/models/StockIn.js +16 -0
  56. package/apps/SIMS/backend/src/models/StockOut.js +18 -0
  57. package/apps/SIMS/backend/src/models/User.js +11 -0
  58. package/apps/SIMS/backend/src/routes/authRoutes.js +12 -0
  59. package/apps/SIMS/backend/src/routes/simsReportRoutes.js +8 -0
  60. package/apps/SIMS/backend/src/routes/sparePartRoutes.js +8 -0
  61. package/apps/SIMS/backend/src/routes/stockInRoutes.js +8 -0
  62. package/apps/SIMS/backend/src/routes/stockOutRoutes.js +10 -0
  63. package/apps/SIMS/backend/src/server.js +62 -0
  64. package/apps/SIMS/backend/src/utils/passwordPolicy.js +10 -0
  65. package/apps/SIMS/backend/src/utils/sparePartHelpers.js +5 -0
  66. package/apps/SIMS/frontend/dist/assets/index-3hv-vGL2.css +2 -0
  67. package/apps/SIMS/frontend/dist/assets/index-T8XT7M6y.js +19 -0
  68. package/apps/SIMS/frontend/dist/index.html +14 -0
  69. package/apps/SIMS/frontend/index.html +13 -0
  70. package/apps/SIMS/frontend/package-lock.json +3053 -0
  71. package/apps/SIMS/frontend/package.json +31 -0
  72. package/apps/SIMS/frontend/src/App.jsx +112 -0
  73. package/apps/SIMS/frontend/src/api/authApi.js +7 -0
  74. package/apps/SIMS/frontend/src/api/client.js +8 -0
  75. package/apps/SIMS/frontend/src/api/simsReportApi.js +5 -0
  76. package/apps/SIMS/frontend/src/api/sparePartsApi.js +4 -0
  77. package/apps/SIMS/frontend/src/api/stockInApi.js +4 -0
  78. package/apps/SIMS/frontend/src/api/stockOutApi.js +6 -0
  79. package/apps/SIMS/frontend/src/api/usersApi.js +3 -0
  80. package/apps/SIMS/frontend/src/components/AppLayout.jsx +60 -0
  81. package/apps/SIMS/frontend/src/index.css +737 -0
  82. package/apps/SIMS/frontend/src/main.jsx +13 -0
  83. package/apps/SIMS/frontend/src/pages/DashboardPage.jsx +179 -0
  84. package/apps/SIMS/frontend/src/pages/LoginPage.jsx +75 -0
  85. package/apps/SIMS/frontend/src/pages/RegisterPage.jsx +78 -0
  86. package/apps/SIMS/frontend/src/pages/ReportsPage.jsx +108 -0
  87. package/apps/SIMS/frontend/src/pages/ResetPasswordPage.jsx +75 -0
  88. package/apps/SIMS/frontend/src/pages/SparePartPage.jsx +128 -0
  89. package/apps/SIMS/frontend/src/pages/StockInPage.jsx +100 -0
  90. package/apps/SIMS/frontend/src/pages/StockOutPage.jsx +206 -0
  91. package/apps/SIMS/frontend/src/utils/passwordPolicy.js +8 -0
  92. package/apps/SIMS/frontend/vite.config.js +8 -0
  93. package/apps/config.js +13 -0
  94. package/package.json +1 -1
@@ -0,0 +1,100 @@
1
+ import { useEffect, useState } from "react";
2
+ import { getSpareParts } from "../api/sparePartsApi";
3
+ import { getStockIn, createStockIn } from "../api/stockInApi";
4
+
5
+ function StockInPage() {
6
+ const [parts, setParts] = useState([]);
7
+ const [rows, setRows] = useState([]);
8
+ const [form, setForm] = useState({ sparePartId: "", stockInQuantity: "", stockInDate: "" });
9
+ const [message, setMessage] = useState("");
10
+
11
+ const load = async () => {
12
+ const [pr, inRows] = await Promise.all([getSpareParts(), getStockIn()]);
13
+ setParts(pr.data);
14
+ setRows(inRows.data);
15
+ };
16
+
17
+ useEffect(() => {
18
+ load().catch(() => setMessage("Load failed"));
19
+ }, []);
20
+
21
+ const onSubmit = async (e) => {
22
+ e.preventDefault();
23
+ setMessage("");
24
+ const q = Number(form.stockInQuantity);
25
+ if (!form.sparePartId || !form.stockInDate) {
26
+ setMessage("Select part and date");
27
+ return;
28
+ }
29
+ try {
30
+ await createStockIn({
31
+ sparePartId: form.sparePartId,
32
+ stockInQuantity: q,
33
+ stockInDate: new Date(form.stockInDate).toISOString(),
34
+ });
35
+ setForm({ sparePartId: "", stockInQuantity: "", stockInDate: "" });
36
+ setMessage("Stock in saved");
37
+ load();
38
+ } catch (err) {
39
+ setMessage(err.response?.data?.message || "Save failed");
40
+ }
41
+ };
42
+
43
+ return (
44
+ <div className="grid gap-4 md:grid-cols-2">
45
+ <section className="rounded-lg border border-blue-200 bg-white p-4 shadow">
46
+ <h2 className="mb-3 text-lg font-semibold text-blue-900">Stock In (insert only)</h2>
47
+ <form onSubmit={onSubmit} className="space-y-2">
48
+ <select
49
+ className="w-full rounded border px-3 py-2"
50
+ value={form.sparePartId}
51
+ onChange={(e) => setForm((f) => ({ ...f, sparePartId: e.target.value }))}
52
+ required
53
+ >
54
+ <option value="">Spare part</option>
55
+ {parts.map((p) => (
56
+ <option key={p._id} value={p._id}>
57
+ {p.name} — {p.category}
58
+ </option>
59
+ ))}
60
+ </select>
61
+ <input
62
+ type="number"
63
+ className="w-full rounded border px-3 py-2"
64
+ placeholder="Quantity in"
65
+ min="1"
66
+ value={form.stockInQuantity}
67
+ onChange={(e) => setForm((f) => ({ ...f, stockInQuantity: e.target.value }))}
68
+ required
69
+ />
70
+ <input
71
+ type="date"
72
+ className="w-full rounded border px-3 py-2"
73
+ value={form.stockInDate}
74
+ onChange={(e) => setForm((f) => ({ ...f, stockInDate: e.target.value }))}
75
+ required
76
+ />
77
+ <button
78
+ type="submit"
79
+ className="w-full rounded bg-blue-700 py-2 text-white hover:bg-blue-800"
80
+ >
81
+ Save
82
+ </button>
83
+ </form>
84
+ {message && <p className="mt-2 text-sm text-slate-600">{message}</p>}
85
+ </section>
86
+ <section className="rounded-lg border border-slate-200 bg-white p-4 shadow">
87
+ <h2 className="mb-3 text-lg font-semibold">History (read)</h2>
88
+ <div className="max-h-96 overflow-auto text-sm">
89
+ {rows.map((r) => (
90
+ <div key={r._id} className="border-b border-slate-100 py-2">
91
+ {r.sparePart?.name} +{r.stockInQuantity} @ {new Date(r.stockInDate).toLocaleDateString()}
92
+ </div>
93
+ ))}
94
+ </div>
95
+ </section>
96
+ </div>
97
+ );
98
+ }
99
+
100
+ export default StockInPage;
@@ -0,0 +1,206 @@
1
+ import { useEffect, useState } from "react";
2
+ import { getSpareParts } from "../api/sparePartsApi";
3
+ import { getStockOut, createStockOut, updateStockOut, deleteStockOut } from "../api/stockOutApi";
4
+
5
+ const empty = { sparePartId: "", stockOutQuantity: "", stockOutUnitPrice: "", stockOutDate: "" };
6
+
7
+ function StockOutPage() {
8
+ const [parts, setParts] = useState([]);
9
+ const [rows, setRows] = useState([]);
10
+ const [form, setForm] = useState(empty);
11
+ const [editing, setEditing] = useState(null);
12
+ const [message, setMessage] = useState("");
13
+
14
+ const load = async () => {
15
+ const [pr, out] = await Promise.all([getSpareParts(), getStockOut()]);
16
+ setParts(pr.data);
17
+ setRows(out.data);
18
+ };
19
+
20
+ useEffect(() => {
21
+ load().catch(() => setMessage("Load failed"));
22
+ }, []);
23
+
24
+ const onSubmit = async (e) => {
25
+ e.preventDefault();
26
+ setMessage("");
27
+ const q = Number(form.stockOutQuantity);
28
+ const u = Number(form.stockOutUnitPrice);
29
+ if (!editing) {
30
+ try {
31
+ await createStockOut({
32
+ sparePartId: form.sparePartId,
33
+ stockOutQuantity: q,
34
+ stockOutUnitPrice: u,
35
+ stockOutDate: new Date(form.stockOutDate).toISOString(),
36
+ });
37
+ setForm(empty);
38
+ setMessage("Saved");
39
+ load();
40
+ } catch (err) {
41
+ setMessage(err.response?.data?.message || "Failed");
42
+ }
43
+ } else {
44
+ try {
45
+ await updateStockOut(editing, {
46
+ stockOutQuantity: q,
47
+ stockOutUnitPrice: u,
48
+ stockOutDate: new Date(form.stockOutDate).toISOString(),
49
+ });
50
+ setEditing(null);
51
+ setForm(empty);
52
+ setMessage("Updated");
53
+ load();
54
+ } catch (err) {
55
+ setMessage(err.response?.data?.message || "Update failed");
56
+ }
57
+ }
58
+ };
59
+
60
+ const startEdit = (r) => {
61
+ setEditing(r._id);
62
+ setForm({
63
+ sparePartId: r.sparePart?._id || r.sparePart,
64
+ stockOutQuantity: r.stockOutQuantity,
65
+ stockOutUnitPrice: r.stockOutUnitPrice,
66
+ stockOutDate: r.stockOutDate
67
+ ? new Date(r.stockOutDate).toISOString().slice(0, 10)
68
+ : "",
69
+ });
70
+ };
71
+
72
+ const onDelete = async (id) => {
73
+ if (!window.confirm("Delete this stock out?")) return;
74
+ setMessage("");
75
+ try {
76
+ await deleteStockOut(id);
77
+ if (editing === id) {
78
+ setEditing(null);
79
+ setForm(empty);
80
+ }
81
+ setMessage("Deleted");
82
+ load();
83
+ } catch (err) {
84
+ setMessage(err.response?.data?.message || "Delete failed");
85
+ }
86
+ };
87
+
88
+ return (
89
+ <div className="space-y-4">
90
+ <section className="rounded-lg border border-amber-200 bg-white p-4 shadow">
91
+ <h2 className="mb-3 text-lg font-semibold text-amber-900">Stock Out (create / list / update / delete)</h2>
92
+ <form onSubmit={onSubmit} className="grid gap-2 md:grid-cols-2 lg:grid-cols-5">
93
+ <select
94
+ className="rounded border px-2 py-2"
95
+ value={form.sparePartId}
96
+ disabled={Boolean(editing)}
97
+ onChange={(e) => setForm((f) => ({ ...f, sparePartId: e.target.value }))}
98
+ required={!editing}
99
+ >
100
+ <option value="">Spare part</option>
101
+ {parts.map((p) => (
102
+ <option key={p._id} value={p._id}>
103
+ {p.name}
104
+ </option>
105
+ ))}
106
+ </select>
107
+ <input
108
+ type="number"
109
+ className="rounded border px-2 py-2"
110
+ min="1"
111
+ placeholder="Quantity"
112
+ value={form.stockOutQuantity}
113
+ onChange={(e) => setForm((f) => ({ ...f, stockOutQuantity: e.target.value }))}
114
+ required
115
+ />
116
+ <input
117
+ type="number"
118
+ className="rounded border px-2 py-2"
119
+ min="0"
120
+ step="0.01"
121
+ placeholder="Unit price"
122
+ value={form.stockOutUnitPrice}
123
+ onChange={(e) => setForm((f) => ({ ...f, stockOutUnitPrice: e.target.value }))}
124
+ required
125
+ />
126
+ <input
127
+ type="date"
128
+ className="rounded border px-2 py-2"
129
+ value={form.stockOutDate}
130
+ onChange={(e) => setForm((f) => ({ ...f, stockOutDate: e.target.value }))}
131
+ required
132
+ />
133
+ <div className="flex gap-2">
134
+ <button
135
+ type="submit"
136
+ className="flex-1 rounded bg-amber-600 px-2 py-2 text-white hover:bg-amber-700"
137
+ >
138
+ {editing ? "Update" : "Save"}
139
+ </button>
140
+ {editing && (
141
+ <button
142
+ type="button"
143
+ className="rounded bg-slate-500 px-2 py-2 text-white"
144
+ onClick={() => {
145
+ setEditing(null);
146
+ setForm(empty);
147
+ }}
148
+ >
149
+ Cancel
150
+ </button>
151
+ )}
152
+ </div>
153
+ </form>
154
+ {message && <p className="mt-2 text-sm text-slate-600">{message}</p>}
155
+ </section>
156
+ <section className="rounded-lg border border-slate-200 bg-white p-4 shadow">
157
+ <h2 className="mb-3 font-semibold">All stock out records</h2>
158
+ <div className="overflow-x-auto">
159
+ <table className="w-full min-w-[640px] text-left text-sm">
160
+ <thead>
161
+ <tr className="bg-slate-100">
162
+ <th className="p-2">Part</th>
163
+ <th className="p-2">Qty</th>
164
+ <th className="p-2">Unit $</th>
165
+ <th className="p-2">Total</th>
166
+ <th className="p-2">Date</th>
167
+ <th className="p-2" />
168
+ </tr>
169
+ </thead>
170
+ <tbody>
171
+ {rows.map((r) => (
172
+ <tr key={r._id} className="border-b">
173
+ <td className="p-2">{r.sparePart?.name || ""}</td>
174
+ <td className="p-2">{r.stockOutQuantity}</td>
175
+ <td className="p-2">{r.stockOutUnitPrice}</td>
176
+ <td className="p-2">{r.stockOutTotalPrice}</td>
177
+ <td className="p-2">
178
+ {r.stockOutDate ? new Date(r.stockOutDate).toLocaleDateString() : ""}
179
+ </td>
180
+ <td className="p-2">
181
+ <button
182
+ type="button"
183
+ className="mr-1 rounded bg-amber-100 px-2 py-0.5 text-amber-900"
184
+ onClick={() => startEdit(r)}
185
+ >
186
+ Edit
187
+ </button>
188
+ <button
189
+ type="button"
190
+ className="rounded bg-red-100 px-2 py-0.5 text-red-800"
191
+ onClick={() => onDelete(r._id)}
192
+ >
193
+ Del
194
+ </button>
195
+ </td>
196
+ </tr>
197
+ ))}
198
+ </tbody>
199
+ </table>
200
+ </div>
201
+ </section>
202
+ </div>
203
+ );
204
+ }
205
+
206
+ export default StockOutPage;
@@ -0,0 +1,8 @@
1
+ export function strongPasswordError(password) {
2
+ const p = String(password || "");
3
+ if (p.length < 8) return "Use at least 8 characters";
4
+ if (!/[A-Z]/.test(p)) return "Include an uppercase letter";
5
+ if (!/[a-z]/.test(p)) return "Include a lowercase letter";
6
+ if (!/[0-9]/.test(p)) return "Include a number";
7
+ return null;
8
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+ import tailwindcss from "@tailwindcss/vite";
4
+
5
+ export default defineConfig({
6
+ plugins: [react(), tailwindcss()],
7
+ server: { port: 5174 },
8
+ });
package/apps/config.js CHANGED
@@ -5,4 +5,17 @@ export const apps = [
5
5
  description: "Hospital management system by Steve Rogers",
6
6
  folder: "HMSR",
7
7
  },
8
+ {
9
+ title: "SIMS - Stock Inventory Management",
10
+ value: "sims",
11
+ description: "Stock inventory management by Steve Rogers",
12
+ folder: "SIMS",
13
+ },
14
+ {
15
+ title: "SFMS - Student Fee Management System",
16
+ value: "sfms",
17
+ description: "Student Fee Management System by steve rogers",
18
+ folder: "SFMS"
19
+
20
+ }
8
21
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-steve-rogers",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Steve Rogers personal app installer",
5
5
  "bin": {
6
6
  "create-steve-rogers": "index.js"