diff --git a/admin_ui/src/components/BusLinesManager.jsx b/admin_ui/src/components/BusLinesManager.jsx
index 07642ec..557f128 100644
--- a/admin_ui/src/components/BusLinesManager.jsx
+++ b/admin_ui/src/components/BusLinesManager.jsx
@@ -13,6 +13,7 @@ export default function BusLinesManager({ token, user }) {
const [message, setMessage] = useState(null)
const [isAdmin] = useState(Boolean(user?.userCode))
const [deleteConfirm, setDeleteConfirm] = useState(null)
+ const [editingLine, setEditingLine] = useState(null)
const loadBusLines = async () => {
try {
@@ -41,10 +42,14 @@ export default function BusLinesManager({ token, user }) {
e.preventDefault()
setMessage(null)
try {
+ // Map selected stop ids to names (server currently stores names)
+ const startStopName = stops.find(s => String(s.id) === String(startStop))?.name || startStop
+ const endStopName = stops.find(s => String(s.id) === String(endStop))?.name || endStop
+
const res = await client.post('/admin/bus-lines', {
lineNumber: Number(lineNumber),
- startStop,
- endStop,
+ startStop: startStopName,
+ endStop: endStopName,
estimatedDurationMinutes: Number(estimatedDurationMinutes),
description,
})
@@ -91,13 +96,29 @@ export default function BusLinesManager({ token, user }) {
diff --git a/admin_ui/src/components/FleetManager.jsx b/admin_ui/src/components/FleetManager.jsx
index ced9c68..da88cfe 100644
--- a/admin_ui/src/components/FleetManager.jsx
+++ b/admin_ui/src/components/FleetManager.jsx
@@ -10,6 +10,8 @@ export default function FleetManager({ token, user }) {
const [message, setMessage] = useState(null)
const [canCreateBus, setCanCreateBus] = useState(true)
const [isAdmin] = useState(Boolean(user?.userCode))
+ const [editingBus, setEditingBus] = useState(null)
+ const [deleteConfirm, setDeleteConfirm] = useState(null)
const loadBuses = async () => {
try {
@@ -65,6 +67,12 @@ export default function FleetManager({ token, user }) {
#{bus.id} {bus.name}
Seats: {bus.seatCapacity}
Plate: {bus.licensePlate}
+ {isAdmin && (
+ <>
+
+
+ >
+ )}
))}
@@ -83,6 +91,62 @@ export default function FleetManager({ token, user }) {
)}
{message &&
{message}
}
+
+ {editingBus && (
+
+ )}
+
+ {deleteConfirm && (
+
+
+
Delete Bus?
+
{deleteConfirm.name}
+
+
+
+
+
+
+ )}
)
}
diff --git a/admin_ui/src/components/ScheduleMaker.jsx b/admin_ui/src/components/ScheduleMaker.jsx
index 42c2c0f..6e4b5de 100644
--- a/admin_ui/src/components/ScheduleMaker.jsx
+++ b/admin_ui/src/components/ScheduleMaker.jsx
@@ -15,6 +15,7 @@ export default function ScheduleMaker({ token, user }) {
const [isAdmin] = useState(Boolean(user?.userCode))
const [deleteConfirm, setDeleteConfirm] = useState(null)
const [expandedSchedule, setExpandedSchedule] = useState(null)
+ const [routeStopsByLine, setRouteStopsByLine] = useState({})
// Form state
const [selectedLine, setSelectedLine] = useState('')
@@ -138,6 +139,18 @@ export default function ScheduleMaker({ token, user }) {
return date.toLocaleTimeString('nl-NL', { hour: '2-digit', minute: '2-digit' })
}
+ // Fetch route stops for a given line and cache them in state
+ const loadRouteStops = async (busLineId) => {
+ if (!busLineId) return
+ try {
+ const res = await client.get(`/admin/bus-lines/${busLineId}/stops`)
+ const routeStops = res.data.routeStops || []
+ setRouteStopsByLine(prev => ({ ...prev, [busLineId]: routeStops }))
+ } catch (err) {
+ // ignore silently, message already used elsewhere
+ }
+ }
+
const getCandidateWindow = () => {
const line = busLines.find(l => String(l.id) === String(selectedLine))
if (!line || !selectedDate || !startTime) return null
@@ -385,25 +398,67 @@ export default function ScheduleMaker({ token, user }) {
{expandedSchedule === schedule.id && (
- {schedule.departureTimes && schedule.departureTimes.length > 0 ? (
-
-
- {schedule.departureTimes.map(stop => (
-
- |
- {stop.order}.
- |
- {stop.stopName} |
-
- {formatTime(stop.departureTime)}
- |
-
- ))}
-
-
- ) : (
-
Geen haltes gekoppeld
- )}
+ {(() => {
+ const lineId = schedule.busLineId
+ const cached = routeStopsByLine[lineId]
+ if (!cached) {
+ // Load and show loading text
+ loadRouteStops(lineId)
+ return
Laden haltes...
+ }
+
+ if (cached.length === 0) {
+ return
Geen haltes gekoppeld
+ }
+
+ // Render editable list of stops with ETA inputs
+ return (
+
+ )
+ })()}
)}
diff --git a/admin_ui/src/components/StopsManager.jsx b/admin_ui/src/components/StopsManager.jsx
index aec54d3..692be04 100644
--- a/admin_ui/src/components/StopsManager.jsx
+++ b/admin_ui/src/components/StopsManager.jsx
@@ -10,6 +10,8 @@ export default function StopsManager({ token, user }) {
const [message, setMessage] = useState(null)
const [isAdmin] = useState(Boolean(user?.userCode))
const [deleteConfirm, setDeleteConfirm] = useState(null)
+ const [editingStop, setEditingStop] = useState(null)
+
const loadStops = async () => {
try {
@@ -84,6 +86,15 @@ export default function StopsManager({ token, user }) {
Delete
)}
+ {isAdmin && (
+
+ )}
))}
@@ -117,6 +128,40 @@ export default function StopsManager({ token, user }) {
)}
+
+ {editingStop && (
+