Add Docker configuration and initial server setup for bus_running_record app
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import { fail, handleOptions, json } from "../_shared/http.ts";
|
||||
import { requireUser } from "../_shared/supabase.ts";
|
||||
|
||||
const PAGE_SIZE = 20;
|
||||
|
||||
Deno.serve(async (req) => {
|
||||
const preflight = handleOptions(req);
|
||||
if (preflight) return preflight;
|
||||
|
||||
if (req.method !== "POST") return fail("Method not allowed", 405);
|
||||
|
||||
const { client, user, error: userError } = await requireUser(req);
|
||||
if (!user) return fail(userError ?? "Unauthorized", 401);
|
||||
|
||||
let body: {
|
||||
channel_id?: string;
|
||||
schedule_id?: string;
|
||||
stop_name?: string;
|
||||
offset?: number;
|
||||
limit?: number;
|
||||
};
|
||||
try {
|
||||
body = await req.json();
|
||||
} catch {
|
||||
return fail("Invalid JSON body");
|
||||
}
|
||||
|
||||
const channelId = (body.channel_id ?? "").trim();
|
||||
const scheduleId = (body.schedule_id ?? "").trim();
|
||||
const stopName = (body.stop_name ?? "").trim();
|
||||
const offset = Math.max(0, typeof body.offset === "number" ? body.offset : 0);
|
||||
const limit = Math.min(100, Math.max(1, typeof body.limit === "number" ? body.limit : PAGE_SIZE));
|
||||
|
||||
if (!channelId) return fail("channel_id is required");
|
||||
if (!scheduleId) return fail("schedule_id is required");
|
||||
if (!stopName) return fail("stop_name is required");
|
||||
|
||||
const { data: schedule, error: scheduleError } = await client
|
||||
.from("operations_schedules")
|
||||
.select("id, channel_id")
|
||||
.eq("id", scheduleId)
|
||||
.eq("channel_id", channelId)
|
||||
.maybeSingle();
|
||||
|
||||
if (scheduleError) return fail(scheduleError.message, 400);
|
||||
if (!schedule) return fail("forbidden", 403);
|
||||
|
||||
const { data: tripRows, error: tripError } = await client
|
||||
.from("operations_trips")
|
||||
.select("id, trip_number, duty_number, bus_work_number, direction")
|
||||
.eq("schedule_id", scheduleId);
|
||||
|
||||
if (tripError) return fail(tripError.message, 500);
|
||||
|
||||
const trips = (tripRows ?? []) as {
|
||||
id: string;
|
||||
trip_number: string;
|
||||
duty_number: string;
|
||||
bus_work_number: string;
|
||||
direction: string;
|
||||
}[];
|
||||
|
||||
if (trips.length === 0) return json({ schedule: [], has_more: false });
|
||||
|
||||
const tripIds = trips.map((t) => t.id);
|
||||
const tripById = Object.fromEntries(trips.map((t) => [t.id, t]));
|
||||
|
||||
const { data: stopRows, error: stopError } = await client
|
||||
.from("operations_trip_stops")
|
||||
.select("trip_id, scheduled_time")
|
||||
.in("trip_id", tripIds)
|
||||
.eq("stop_name", stopName);
|
||||
|
||||
if (stopError) return fail(stopError.message, 500);
|
||||
|
||||
const rows = (stopRows ?? []) as { trip_id: string; scheduled_time: string | null }[];
|
||||
|
||||
const result = rows
|
||||
.map((row) => {
|
||||
const trip = tripById[row.trip_id];
|
||||
if (!trip) return null;
|
||||
return { trip, scheduled_time: row.scheduled_time ?? null };
|
||||
})
|
||||
.filter(Boolean) as { trip: typeof trips[0]; scheduled_time: string | null }[];
|
||||
|
||||
result.sort((a, b) => {
|
||||
const aNum = parseInt(a.trip.trip_number, 10);
|
||||
const bNum = parseInt(b.trip.trip_number, 10);
|
||||
if (!isNaN(aNum) && !isNaN(bNum)) return aNum - bNum;
|
||||
return a.trip.trip_number.localeCompare(b.trip.trip_number);
|
||||
});
|
||||
|
||||
const page = result.slice(offset, offset + limit);
|
||||
const hasMore = offset + limit < result.length;
|
||||
|
||||
return json({ schedule: page, has_more: hasMore });
|
||||
});
|
||||
Reference in New Issue
Block a user