ostroner 1.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/bin/create-project.js +57 -0
- package/package.json +23 -0
- package/templates/stock-chain/backend/.env +9 -0
- package/templates/stock-chain/backend/.eslintrc.js +6 -0
- package/templates/stock-chain/backend/.prettierrc +14 -0
- package/templates/stock-chain/backend/README.md +1 -0
- package/templates/stock-chain/backend/package-lock.json +1666 -0
- package/templates/stock-chain/backend/package.json +21 -0
- package/templates/stock-chain/backend/src/app.js +59 -0
- package/templates/stock-chain/backend/src/config/db.js +29 -0
- package/templates/stock-chain/backend/src/controllers/auth.js +31 -0
- package/templates/stock-chain/backend/src/controllers/bookingcontroller.js +65 -0
- package/templates/stock-chain/backend/src/controllers/buscontroller.js +59 -0
- package/templates/stock-chain/backend/src/controllers/deliverycontroller.js +35 -0
- package/templates/stock-chain/backend/src/controllers/schedulecontroller.js +85 -0
- package/templates/stock-chain/backend/src/controllers/shipmentcontroller.js +35 -0
- package/templates/stock-chain/backend/src/controllers/suppliercontroller.js +35 -0
- package/templates/stock-chain/backend/src/controllers/usercontroller.js +59 -0
- package/templates/stock-chain/backend/src/middleware/auth.js +11 -0
- package/templates/stock-chain/backend/src/middleware/errorHandler.js +7 -0
- package/templates/stock-chain/backend/src/models/delivery.js +20 -0
- package/templates/stock-chain/backend/src/models/index.js +6 -0
- package/templates/stock-chain/backend/src/models/shipment.js +20 -0
- package/templates/stock-chain/backend/src/models/supplier.js +17 -0
- package/templates/stock-chain/backend/src/models/user.js +15 -0
- package/templates/stock-chain/backend/src/routes/authroute.js +11 -0
- package/templates/stock-chain/backend/src/routes/bookingroute.js +18 -0
- package/templates/stock-chain/backend/src/routes/busroute.js +18 -0
- package/templates/stock-chain/backend/src/routes/deliveriesroute.js +18 -0
- package/templates/stock-chain/backend/src/routes/scheduleroute.js +18 -0
- package/templates/stock-chain/backend/src/routes/shipmentsroute.js +18 -0
- package/templates/stock-chain/backend/src/routes/suppliersroute.js +18 -0
- package/templates/stock-chain/backend/src/routes/userroute.js +18 -0
- package/templates/stock-chain/frontend/.env +1 -0
- package/templates/stock-chain/frontend/README.md +16 -0
- package/templates/stock-chain/frontend/eslint.config.js +21 -0
- package/templates/stock-chain/frontend/index.html +13 -0
- package/templates/stock-chain/frontend/package-lock.json +3131 -0
- package/templates/stock-chain/frontend/package.json +33 -0
- package/templates/stock-chain/frontend/public/favicon.svg +1 -0
- package/templates/stock-chain/frontend/public/icons.svg +24 -0
- package/templates/stock-chain/frontend/src/App.jsx +55 -0
- package/templates/stock-chain/frontend/src/assets/hero.png +0 -0
- package/templates/stock-chain/frontend/src/assets/react.svg +1 -0
- package/templates/stock-chain/frontend/src/assets/vite.svg +1 -0
- package/templates/stock-chain/frontend/src/components/Button.jsx +15 -0
- package/templates/stock-chain/frontend/src/components/Input.jsx +25 -0
- package/templates/stock-chain/frontend/src/context/AuthContext.jsx +59 -0
- package/templates/stock-chain/frontend/src/index.css +7 -0
- package/templates/stock-chain/frontend/src/main.jsx +18 -0
- package/templates/stock-chain/frontend/src/pages/AppLayout.jsx +125 -0
- package/templates/stock-chain/frontend/src/pages/Login.jsx +78 -0
- package/templates/stock-chain/frontend/src/pages/ManagerDeliveries.jsx +113 -0
- package/templates/stock-chain/frontend/src/pages/ManagerShipments.jsx +113 -0
- package/templates/stock-chain/frontend/src/pages/ManagerSuppliers.jsx +122 -0
- package/templates/stock-chain/frontend/src/pages/Register.jsx +60 -0
- package/templates/stock-chain/frontend/src/services/api.js +8 -0
- package/templates/stock-chain/frontend/src/services/authService.js +11 -0
- package/templates/stock-chain/frontend/vite.config.js +8 -0
- package/templates/y-bus/backend/.env +9 -0
- package/templates/y-bus/backend/.eslintrc.js +6 -0
- package/templates/y-bus/backend/.prettierrc +14 -0
- package/templates/y-bus/backend/README.md +1 -0
- package/templates/y-bus/backend/package-lock.json +1666 -0
- package/templates/y-bus/backend/package.json +21 -0
- package/templates/y-bus/backend/src/app.js +44 -0
- package/templates/y-bus/backend/src/config/db.js +29 -0
- package/templates/y-bus/backend/src/controllers/auth.js +23 -0
- package/templates/y-bus/backend/src/controllers/bookingcontroller.js +65 -0
- package/templates/y-bus/backend/src/controllers/buscontroller.js +59 -0
- package/templates/y-bus/backend/src/controllers/schedulecontroller.js +85 -0
- package/templates/y-bus/backend/src/controllers/usercontroller.js +59 -0
- package/templates/y-bus/backend/src/middleware/auth.js +11 -0
- package/templates/y-bus/backend/src/middleware/errorHandler.js +7 -0
- package/templates/y-bus/backend/src/models/booking.js +27 -0
- package/templates/y-bus/backend/src/models/bus.js +16 -0
- package/templates/y-bus/backend/src/models/index.js +15 -0
- package/templates/y-bus/backend/src/models/schedule.js +25 -0
- package/templates/y-bus/backend/src/models/user.js +20 -0
- package/templates/y-bus/backend/src/routes/bookingroute.js +18 -0
- package/templates/y-bus/backend/src/routes/busroute.js +18 -0
- package/templates/y-bus/backend/src/routes/scheduleroute.js +18 -0
- package/templates/y-bus/backend/src/routes/userroute.js +18 -0
- package/templates/y-bus/frontend/.env +1 -0
- package/templates/y-bus/frontend/README.md +16 -0
- package/templates/y-bus/frontend/eslint.config.js +21 -0
- package/templates/y-bus/frontend/index.html +13 -0
- package/templates/y-bus/frontend/package-lock.json +3131 -0
- package/templates/y-bus/frontend/package.json +33 -0
- package/templates/y-bus/frontend/public/favicon.svg +1 -0
- package/templates/y-bus/frontend/public/icons.svg +24 -0
- package/templates/y-bus/frontend/src/App.jsx +108 -0
- package/templates/y-bus/frontend/src/assets/hero.png +0 -0
- package/templates/y-bus/frontend/src/assets/react.svg +1 -0
- package/templates/y-bus/frontend/src/assets/vite.svg +1 -0
- package/templates/y-bus/frontend/src/components/Button.jsx +15 -0
- package/templates/y-bus/frontend/src/components/Input.jsx +25 -0
- package/templates/y-bus/frontend/src/context/AuthContext.jsx +59 -0
- package/templates/y-bus/frontend/src/index.css +7 -0
- package/templates/y-bus/frontend/src/main.jsx +18 -0
- package/templates/y-bus/frontend/src/pages/AppLayout.jsx +135 -0
- package/templates/y-bus/frontend/src/pages/CustomerTrips.jsx +101 -0
- package/templates/y-bus/frontend/src/pages/Login.jsx +81 -0
- package/templates/y-bus/frontend/src/pages/ManagerBuses.jsx +140 -0
- package/templates/y-bus/frontend/src/pages/ManagerDashboard.jsx +108 -0
- package/templates/y-bus/frontend/src/pages/ManagerReport.jsx +89 -0
- package/templates/y-bus/frontend/src/pages/ManagerSchedules.jsx +233 -0
- package/templates/y-bus/frontend/src/pages/MyBookings.jsx +78 -0
- package/templates/y-bus/frontend/src/pages/Register.jsx +67 -0
- package/templates/y-bus/frontend/src/services/api.js +8 -0
- package/templates/y-bus/frontend/src/services/authService.js +33 -0
- package/templates/y-bus/frontend/vite.config.js +8 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { Link } from "react-router-dom";
|
|
3
|
+
import toast from "react-hot-toast";
|
|
4
|
+
import { useAuth } from "../context/AuthContext";
|
|
5
|
+
import api from "../services/api";
|
|
6
|
+
|
|
7
|
+
export function MyBookings() {
|
|
8
|
+
const [bookings, setBookings] = useState([]);
|
|
9
|
+
const { user } = useAuth();
|
|
10
|
+
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
async function loadMyBookings() {
|
|
13
|
+
if (!user?.userid) return;
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const response = await api.get("/bookings");
|
|
17
|
+
const allBookings = response.data?.data || [];
|
|
18
|
+
setBookings(allBookings.filter((booking) => booking.userid === user.userid));
|
|
19
|
+
} catch (error) {
|
|
20
|
+
toast.error(error.response?.data?.message || "Failed to load bookings");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
loadMyBookings();
|
|
25
|
+
}, [user]);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="space-y-6">
|
|
29
|
+
<section className="rounded-2xl border border-gray-200 bg-white p-5 shadow-sm">
|
|
30
|
+
<h1 className="text-2xl font-bold text-gray-950">My bookings</h1>
|
|
31
|
+
<p className="mt-2 text-sm text-gray-500">Your reserved seats and trip information.</p>
|
|
32
|
+
<Link to="/" className="mt-4 inline-block text-sm font-semibold text-gray-900 underline">
|
|
33
|
+
Browse trips
|
|
34
|
+
</Link>
|
|
35
|
+
</section>
|
|
36
|
+
|
|
37
|
+
{bookings.length === 0 ? (
|
|
38
|
+
<div className="rounded-2xl border border-gray-200 bg-white p-5 text-sm text-gray-500 shadow-sm">You have no bookings yet.</div>
|
|
39
|
+
) : (
|
|
40
|
+
<div className="grid gap-4">
|
|
41
|
+
{bookings.map((booking) => (
|
|
42
|
+
<article key={booking.bookingid} className="rounded-2xl border border-gray-200 bg-white p-5 shadow-sm">
|
|
43
|
+
<div className="flex flex-wrap justify-between gap-4">
|
|
44
|
+
<div>
|
|
45
|
+
<h2 className="text-lg font-bold text-gray-950">{booking.Schedule?.routename || "Trip"}</h2>
|
|
46
|
+
<p className="mt-1 text-sm text-gray-500">
|
|
47
|
+
{booking.Schedule?.departurepoint || "-"} - {booking.Schedule?.destination || "-"}
|
|
48
|
+
</p>
|
|
49
|
+
</div>
|
|
50
|
+
<span className="rounded-full border border-gray-300 px-3 py-1 text-xs font-semibold capitalize text-gray-600">
|
|
51
|
+
{booking.paymentstatus}
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
<dl className="mt-5 grid gap-3 text-sm sm:grid-cols-3">
|
|
55
|
+
<div>
|
|
56
|
+
<dt className="text-gray-500">Passenger</dt>
|
|
57
|
+
<dd className="font-semibold text-gray-950">{booking.passengername}</dd>
|
|
58
|
+
</div>
|
|
59
|
+
<div>
|
|
60
|
+
<dt className="text-gray-500">Seat</dt>
|
|
61
|
+
<dd className="font-semibold text-gray-950">{booking.seatnumber}</dd>
|
|
62
|
+
</div>
|
|
63
|
+
<div>
|
|
64
|
+
<dt className="text-gray-500">Departure</dt>
|
|
65
|
+
<dd className="font-semibold text-gray-950">
|
|
66
|
+
{booking.Schedule?.departuretime
|
|
67
|
+
? new Date(booking.Schedule.departuretime).toLocaleString()
|
|
68
|
+
: "N/A"}
|
|
69
|
+
</dd>
|
|
70
|
+
</div>
|
|
71
|
+
</dl>
|
|
72
|
+
</article>
|
|
73
|
+
))}
|
|
74
|
+
</div>
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { Link, useNavigate } from "react-router-dom";
|
|
3
|
+
import toast from "react-hot-toast";
|
|
4
|
+
import { useAuth } from "../context/AuthContext";
|
|
5
|
+
import { Button } from "../components/Button";
|
|
6
|
+
import { Input, Select } from "../components/Input";
|
|
7
|
+
|
|
8
|
+
export function Register() {
|
|
9
|
+
const [form, setForm] = useState({ username: "", password: "", userrole: "customer" });
|
|
10
|
+
const { register } = useAuth();
|
|
11
|
+
const navigate = useNavigate();
|
|
12
|
+
|
|
13
|
+
async function handleSubmit(event) {
|
|
14
|
+
event.preventDefault();
|
|
15
|
+
try {
|
|
16
|
+
await register(form);
|
|
17
|
+
toast.success("Account created. Please login.");
|
|
18
|
+
navigate("/login");
|
|
19
|
+
} catch (error) {
|
|
20
|
+
toast.error(error.response?.data?.message || "Registration failed");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<main className="grid min-h-screen place-items-center bg-gray-100 p-4">
|
|
26
|
+
<form
|
|
27
|
+
onSubmit={handleSubmit}
|
|
28
|
+
className="w-full max-w-md rounded-2xl border border-gray-200 bg-white p-6 shadow-sm"
|
|
29
|
+
>
|
|
30
|
+
<h1 className="text-2xl font-bold text-gray-950">Create account</h1>
|
|
31
|
+
<p className="mt-1 text-sm text-gray-500">Choose a role for testing the system.</p>
|
|
32
|
+
|
|
33
|
+
<div className="mt-6 grid gap-4">
|
|
34
|
+
<Input
|
|
35
|
+
label="Username"
|
|
36
|
+
value={form.username}
|
|
37
|
+
onChange={(event) => setForm({ ...form, username: event.target.value })}
|
|
38
|
+
required
|
|
39
|
+
/>
|
|
40
|
+
<Input
|
|
41
|
+
label="Password"
|
|
42
|
+
type="password"
|
|
43
|
+
value={form.password}
|
|
44
|
+
onChange={(event) => setForm({ ...form, password: event.target.value })}
|
|
45
|
+
required
|
|
46
|
+
/>
|
|
47
|
+
<Select
|
|
48
|
+
label="Role"
|
|
49
|
+
value={form.userrole}
|
|
50
|
+
onChange={(event) => setForm({ ...form, userrole: event.target.value })}
|
|
51
|
+
>
|
|
52
|
+
<option value="customer">Customer</option>
|
|
53
|
+
<option value="manager">Manager</option>
|
|
54
|
+
</Select>
|
|
55
|
+
<Button type="submit" className="w-full">Create account</Button>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<p className="mt-6 text-center text-sm text-gray-500">
|
|
59
|
+
Already have an account?{" "}
|
|
60
|
+
<Link className="font-semibold text-gray-950 underline" to="/login">
|
|
61
|
+
Login
|
|
62
|
+
</Link>
|
|
63
|
+
</p>
|
|
64
|
+
</form>
|
|
65
|
+
</main>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import api from "./api";
|
|
2
|
+
|
|
3
|
+
export const registerUser = async (payload) => {
|
|
4
|
+
const response = await api.post("/users", payload);
|
|
5
|
+
return response.data;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const loginUser = async (payload) => {
|
|
9
|
+
try {
|
|
10
|
+
const response = await api.post("/auth/login", payload);
|
|
11
|
+
return response.data;
|
|
12
|
+
} catch (error) {
|
|
13
|
+
if (error.response?.status === 404 || error.response?.status === 405) {
|
|
14
|
+
const usersResponse = await api.get("/users");
|
|
15
|
+
const users = usersResponse.data?.data || [];
|
|
16
|
+
const matchedUser = users.find(
|
|
17
|
+
(user) =>
|
|
18
|
+
user.username === payload.username &&
|
|
19
|
+
user.password === payload.password
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
if (!matchedUser) {
|
|
23
|
+
const fallbackError = new Error("Invalid credentials");
|
|
24
|
+
fallbackError.response = { data: { message: "Invalid credentials" } };
|
|
25
|
+
throw fallbackError;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return { data: matchedUser };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
};
|