feat(scheduling): add frontend types and API client

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kkfluous
2026-04-16 20:20:23 +08:00
parent ebe46c6f73
commit 569b5ea349
2 changed files with 81 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
import { fetchJson } from '../../auth/api-client';
import type { SchedulingResponse } from './types';
const BASE = '/api/scheduling';
export async function fetchSuggestions(targetId?: number): Promise<SchedulingResponse> {
const params = new URLSearchParams();
if (targetId !== undefined) params.set('targetId', String(targetId));
const qs = params.toString();
return fetchJson<SchedulingResponse>(`${BASE}/suggestions${qs ? `?${qs}` : ''}`);
}
export async function sendNotify(body: {
suggestionId: string;
currentPlate: string;
candidatePlate: string;
}): Promise<{ success: boolean; message: string }> {
return fetchJson<{ success: boolean; message: string }>(`${BASE}/notify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
}

View File

@@ -0,0 +1,58 @@
export interface SchedulingVehicleInfo {
plateNumber: string;
targetId: number;
targetName: string;
vehicleType: string;
totalMileage: number;
completionRate: number;
yearTarget: number;
region: string;
province: string;
customer: string | null;
customerAvgDaily: number;
predictedYearEnd: number;
daysLeft: number;
}
export interface CandidateVehicle {
plateNumber: string;
targetId: number | null;
targetName: string | null;
vehicleType: string;
totalMileage: number;
completionRate: number;
yearTarget: number | null;
region: string;
province: string;
mileageGap: number;
predictedAfterSwap: number;
canQualifyAfterSwap: boolean;
}
export interface SchedulingSuggestion {
id: string;
priority: 'high' | 'medium';
type: 'replace_qualified' | 'rescue_hopeless';
currentVehicle: SchedulingVehicleInfo;
candidates: CandidateVehicle[];
reason: string;
}
export interface SchedulingSummary {
qualifiedCount: number;
hopelessCount: number;
suggestionCount: number;
estimatedGain: number;
}
export interface SchedulingTargetOption {
id: number;
name: string;
vehicleCount: number;
}
export interface SchedulingResponse {
summary: SchedulingSummary;
suggestions: SchedulingSuggestion[];
targets: SchedulingTargetOption[];
}