feat: 공차중계 운전자 차량/프로필 관리 기능 구현

This commit is contained in:
dohyeons 2025-12-01 19:03:43 +09:00
parent 9c3f1d26ad
commit cd47f569e2
6 changed files with 540 additions and 89 deletions

View File

@ -23,7 +23,7 @@ export class DriverController {
// 사용자 정보 조회
const userResult = await query<any>(
`SELECT
user_id, user_name, cell_phone, license_number, vehicle_number, signup_type
user_id, user_name, cell_phone, license_number, vehicle_number, signup_type, branch_name
FROM user_info
WHERE user_id = $1`,
[userId]
@ -69,6 +69,7 @@ export class DriverController {
vehicleNumber: user.vehicle_number,
vehicleType: vehicle?.vehicle_type || null,
vehicleStatus: vehicle?.status || null,
branchName: user.branch_name || null,
},
});
} catch (error) {
@ -96,7 +97,7 @@ export class DriverController {
return;
}
const { userName, phoneNumber, licenseNumber, vehicleNumber, vehicleType } = req.body;
const { userName, phoneNumber, licenseNumber, vehicleNumber, vehicleType, branchName } = req.body;
// 공차중계 사용자 확인
const userCheck = await query<any>(
@ -144,9 +145,10 @@ export class DriverController {
user_name = COALESCE($1, user_name),
cell_phone = COALESCE($2, cell_phone),
license_number = COALESCE($3, license_number),
vehicle_number = COALESCE($4, vehicle_number)
WHERE user_id = $5`,
[userName || null, phoneNumber || null, licenseNumber || null, vehicleNumber || null, userId]
vehicle_number = COALESCE($4, vehicle_number),
branch_name = COALESCE($5, branch_name)
WHERE user_id = $6`,
[userName || null, phoneNumber || null, licenseNumber || null, vehicleNumber || null, branchName || null, userId]
);
// vehicles 테이블 업데이트
@ -156,9 +158,10 @@ export class DriverController {
vehicle_type = COALESCE($2, vehicle_type),
driver_name = COALESCE($3, driver_name),
driver_phone = COALESCE($4, driver_phone),
branch_name = COALESCE($5, branch_name),
updated_at = NOW()
WHERE user_id = $5`,
[vehicleNumber || null, vehicleType || null, userName || null, phoneNumber || null, userId]
WHERE user_id = $6`,
[vehicleNumber || null, vehicleType || null, userName || null, phoneNumber || null, branchName || null, userId]
);
logger.info(`운전자 프로필 수정 완료: ${userId}`);
@ -239,6 +242,160 @@ export class DriverController {
}
}
/**
* DELETE /api/driver/vehicle
* (user_id = NULL , )
*/
static async deleteVehicle(req: Request, res: Response): Promise<void> {
try {
const userId = req.user?.userId;
if (!userId) {
res.status(401).json({
success: false,
message: "인증이 필요합니다.",
});
return;
}
// 공차중계 사용자 확인
const userCheck = await query<any>(
`SELECT signup_type, vehicle_number FROM user_info WHERE user_id = $1`,
[userId]
);
if (userCheck.length === 0 || userCheck[0].signup_type !== "DRIVER") {
res.status(403).json({
success: false,
message: "공차중계 사용자만 접근할 수 있습니다.",
});
return;
}
// vehicles 테이블에서 user_id를 NULL로 변경하고 status를 disabled로 (기록 보존)
await query(
`UPDATE vehicles SET user_id = NULL, status = 'disabled', updated_at = NOW() WHERE user_id = $1`,
[userId]
);
// user_info에서 vehicle_number를 NULL로 변경
await query(
`UPDATE user_info SET vehicle_number = NULL WHERE user_id = $1`,
[userId]
);
logger.info(`차량 삭제 완료 (기록 보존): ${userId}`);
res.status(200).json({
success: true,
message: "차량이 삭제되었습니다.",
});
} catch (error) {
logger.error("차량 삭제 오류:", error);
res.status(500).json({
success: false,
message: "차량 삭제 중 오류가 발생했습니다.",
});
}
}
/**
* POST /api/driver/vehicle
*
*/
static async registerVehicle(req: Request, res: Response): Promise<void> {
try {
const userId = req.user?.userId;
const companyCode = req.user?.companyCode;
if (!userId) {
res.status(401).json({
success: false,
message: "인증이 필요합니다.",
});
return;
}
const { vehicleNumber, vehicleType, branchName } = req.body;
if (!vehicleNumber) {
res.status(400).json({
success: false,
message: "차량번호는 필수입니다.",
});
return;
}
// 공차중계 사용자 확인
const userCheck = await query<any>(
`SELECT signup_type, user_name, cell_phone, vehicle_number, company_code FROM user_info WHERE user_id = $1`,
[userId]
);
if (userCheck.length === 0 || userCheck[0].signup_type !== "DRIVER") {
res.status(403).json({
success: false,
message: "공차중계 사용자만 접근할 수 있습니다.",
});
return;
}
// 이미 차량이 있는지 확인
if (userCheck[0].vehicle_number) {
res.status(400).json({
success: false,
message: "이미 등록된 차량이 있습니다. 먼저 기존 차량을 삭제해주세요.",
});
return;
}
// 차량번호 중복 확인
const duplicateCheck = await query<any>(
`SELECT vehicle_number FROM vehicles WHERE vehicle_number = $1 AND user_id IS NOT NULL`,
[vehicleNumber]
);
if (duplicateCheck.length > 0) {
res.status(400).json({
success: false,
message: "이미 등록된 차량번호입니다.",
});
return;
}
const userName = userCheck[0].user_name;
const userPhone = userCheck[0].cell_phone;
// 사용자의 company_code 사용 (req.user에서 가져오거나 DB에서 조회한 값 사용)
const userCompanyCode = companyCode || userCheck[0].company_code;
// vehicles 테이블에 새 차량 등록 (company_code 포함, status는 'off')
await query(
`INSERT INTO vehicles (vehicle_number, vehicle_type, user_id, driver_name, driver_phone, branch_name, status, company_code, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, 'off', $7, NOW(), NOW())`,
[vehicleNumber, vehicleType || null, userId, userName, userPhone, branchName || null, userCompanyCode]
);
// user_info에 vehicle_number 업데이트
await query(
`UPDATE user_info SET vehicle_number = $1 WHERE user_id = $2`,
[vehicleNumber, userId]
);
logger.info(`새 차량 등록 완료: ${userId} -> ${vehicleNumber} (company_code: ${userCompanyCode})`);
res.status(200).json({
success: true,
message: "차량이 등록되었습니다.",
});
} catch (error) {
logger.error("차량 등록 오류:", error);
res.status(500).json({
success: false,
message: "차량 등록 중 오류가 발생했습니다.",
});
}
}
/**
* DELETE /api/driver/account
* ( )

View File

@ -26,6 +26,18 @@ router.put("/profile", DriverController.updateProfile);
*/
router.put("/status", DriverController.updateStatus);
/**
* DELETE /api/driver/vehicle
* ( )
*/
router.delete("/vehicle", DriverController.deleteVehicle);
/**
* POST /api/driver/vehicle
*
*/
router.post("/vehicle", DriverController.registerVehicle);
/**
* DELETE /api/driver/account
*

View File

@ -236,11 +236,19 @@ function AppLayoutInner({ children }: AppLayoutProps) {
saveProfile,
// 운전자 관련
isDriver,
hasVehicle,
driverInfo,
driverFormData,
updateDriverFormData,
handleDriverStatusChange,
handleDriverAccountDelete,
handleDeleteVehicle,
openVehicleRegisterModal,
closeVehicleRegisterModal,
isVehicleRegisterModalOpen,
newVehicleData,
updateNewVehicleData,
handleRegisterVehicle,
} = useProfile(user, refreshUserData, refreshMenus);
// 현재 경로에 따라 어드민 모드인지 판단 (쿼리 파라미터도 고려)
@ -491,11 +499,19 @@ function AppLayoutInner({ children }: AppLayoutProps) {
departments={departments}
alertModal={alertModal}
isDriver={isDriver}
hasVehicle={hasVehicle}
driverInfo={driverInfo}
driverFormData={driverFormData}
onDriverFormChange={updateDriverFormData}
onDriverStatusChange={handleDriverStatusChange}
onDriverAccountDelete={handleDriverAccountDelete}
onDeleteVehicle={handleDeleteVehicle}
onOpenVehicleRegisterModal={openVehicleRegisterModal}
isVehicleRegisterModalOpen={isVehicleRegisterModalOpen}
newVehicleData={newVehicleData}
onCloseVehicleRegisterModal={closeVehicleRegisterModal}
onNewVehicleDataChange={updateNewVehicleData}
onRegisterVehicle={handleRegisterVehicle}
onClose={closeProfileModal}
onFormChange={updateFormData}
onImageSelect={selectImage}

View File

@ -11,9 +11,10 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Camera, X, Car, Wrench, Clock } from "lucide-react";
import { Camera, X, Car, Wrench, Clock, Plus, Trash2 } from "lucide-react";
import { ProfileFormData } from "@/types/profile";
import { Separator } from "@/components/ui/separator";
import { VehicleRegisterData } from "@/lib/api/driver";
// 운전자 정보 타입
export interface DriverInfo {
@ -22,6 +23,7 @@ export interface DriverInfo {
licenseNumber: string;
phoneNumber: string;
vehicleStatus: string | null;
branchName: string | null;
}
// 알림 모달 컴포넌트
@ -70,6 +72,7 @@ export interface DriverFormData {
vehicleType: string;
licenseNumber: string;
phoneNumber: string;
branchName: string;
}
interface ProfileModalProps {
@ -90,11 +93,21 @@ interface ProfileModalProps {
};
// 운전자 관련 props (선택적)
isDriver?: boolean;
hasVehicle?: boolean;
driverInfo?: DriverInfo | null;
driverFormData?: DriverFormData;
onDriverFormChange?: (field: keyof DriverFormData, value: string) => void;
onDriverStatusChange?: (status: "off" | "maintenance") => void;
onDriverAccountDelete?: () => void;
// 차량 삭제/등록 관련 props
onDeleteVehicle?: () => void;
onOpenVehicleRegisterModal?: () => void;
// 새 차량 등록 모달 관련 props
isVehicleRegisterModalOpen?: boolean;
newVehicleData?: VehicleRegisterData;
onCloseVehicleRegisterModal?: () => void;
onNewVehicleDataChange?: (field: keyof VehicleRegisterData, value: string) => void;
onRegisterVehicle?: () => void;
onClose: () => void;
onFormChange: (field: keyof ProfileFormData, value: string) => void;
onImageSelect: (event: React.ChangeEvent<HTMLInputElement>) => void;
@ -115,11 +128,19 @@ export function ProfileModal({
departments,
alertModal,
isDriver = false,
hasVehicle = false,
driverInfo,
driverFormData,
onDriverFormChange,
onDriverStatusChange,
onDriverAccountDelete,
onDeleteVehicle,
onOpenVehicleRegisterModal,
isVehicleRegisterModalOpen = false,
newVehicleData,
onCloseVehicleRegisterModal,
onNewVehicleDataChange,
onRegisterVehicle,
onClose,
onFormChange,
onImageSelect,
@ -282,96 +303,147 @@ export function ProfileModal({
</div>
{/* 운전자 정보 섹션 (공차중계 사용자만) */}
{isDriver && driverFormData && onDriverFormChange && (
{isDriver && (
<>
<Separator className="my-4" />
<div className="space-y-4">
<div className="flex items-center gap-2">
<Car className="h-5 w-5 text-primary" />
<h3 className="text-sm font-semibold">/ </h3>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Car className="h-5 w-5 text-primary" />
<h3 className="text-sm font-semibold">/ </h3>
</div>
{/* 차량 유무에 따른 버튼 표시 */}
{hasVehicle ? (
<Button
type="button"
variant="destructive"
size="sm"
onClick={onDeleteVehicle}
className="flex items-center gap-1"
>
<Trash2 className="h-3 w-3" />
</Button>
) : (
<Button
type="button"
variant="default"
size="sm"
onClick={onOpenVehicleRegisterModal}
className="flex items-center gap-1"
>
<Plus className="h-3 w-3" />
</Button>
)}
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="vehicleNumber"></Label>
<Input
id="vehicleNumber"
value={driverFormData.vehicleNumber}
onChange={(e) => onDriverFormChange("vehicleNumber", e.target.value)}
placeholder="12가1234"
/>
</div>
<div className="space-y-2">
<Label htmlFor="vehicleType"></Label>
<Input
id="vehicleType"
value={driverFormData.vehicleType}
onChange={(e) => onDriverFormChange("vehicleType", e.target.value)}
placeholder="1톤 카고"
/>
</div>
</div>
{/* 운전자 정보 (항상 수정 가능) */}
{driverFormData && onDriverFormChange && (
<>
{/* 차량 정보 - 차량이 있을 때만 수정 가능 */}
{hasVehicle ? (
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="vehicleNumber"></Label>
<Input
id="vehicleNumber"
value={driverFormData.vehicleNumber}
onChange={(e) => onDriverFormChange("vehicleNumber", e.target.value)}
placeholder="12가1234"
/>
</div>
<div className="space-y-2">
<Label htmlFor="vehicleType"></Label>
<Input
id="vehicleType"
value={driverFormData.vehicleType}
onChange={(e) => onDriverFormChange("vehicleType", e.target.value)}
placeholder="1톤 카고"
/>
</div>
</div>
) : (
/* 차량이 없는 경우: 안내 메시지 */
<div className="text-center py-4 text-muted-foreground border rounded-md bg-muted/30">
<Car className="h-8 w-8 mx-auto mb-2 opacity-30" />
<p className="text-sm"> .</p>
<p className="text-xs mt-1"> .</p>
</div>
)}
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="driverPhone"></Label>
<Input
id="driverPhone"
value={driverFormData.phoneNumber}
onChange={(e) => onDriverFormChange("phoneNumber", e.target.value)}
placeholder="010-1234-5678"
/>
</div>
<div className="space-y-2">
<Label htmlFor="licenseNumber"></Label>
<Input
id="licenseNumber"
value={driverFormData.licenseNumber}
onChange={(e) => onDriverFormChange("licenseNumber", e.target.value)}
placeholder="12-34-567890-12"
/>
</div>
</div>
{/* 차량 상태 */}
{driverInfo && onDriverStatusChange && (
<div className="space-y-2">
<Label> </Label>
<div className="flex items-center gap-4">
<span className="text-sm font-medium px-3 py-1 rounded-full bg-muted">
{getStatusLabel(driverInfo.vehicleStatus)}
</span>
<div className="flex gap-2">
<Button
type="button"
variant="outline"
size="sm"
onClick={() => onDriverStatusChange("off")}
disabled={driverInfo.vehicleStatus === "off"}
className="flex items-center gap-1"
>
<Clock className="h-3 w-3" />
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => onDriverStatusChange("maintenance")}
disabled={driverInfo.vehicleStatus === "maintenance"}
className="flex items-center gap-1"
>
<Wrench className="h-3 w-3" />
</Button>
{/* 운전자 개인 정보 - 항상 수정 가능 */}
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="driverPhone"></Label>
<Input
id="driverPhone"
value={driverFormData.phoneNumber}
onChange={(e) => onDriverFormChange("phoneNumber", e.target.value)}
placeholder="010-1234-5678"
/>
</div>
<div className="space-y-2">
<Label htmlFor="licenseNumber"></Label>
<Input
id="licenseNumber"
value={driverFormData.licenseNumber}
onChange={(e) => onDriverFormChange("licenseNumber", e.target.value)}
placeholder="12-34-567890-12"
/>
</div>
</div>
<p className="text-xs text-muted-foreground">
* /
</p>
</div>
)}
<div className="space-y-2">
<Label htmlFor="branchName"> </Label>
<Input
id="branchName"
value={driverFormData.branchName}
onChange={(e) => onDriverFormChange("branchName", e.target.value)}
placeholder="서울 본점"
/>
</div>
{/* 차량 상태 - 차량이 있을 때만 표시 */}
{hasVehicle && driverInfo && onDriverStatusChange && (
<div className="space-y-2">
<Label> </Label>
<div className="flex items-center gap-4">
<span className="text-sm font-medium px-3 py-1 rounded-full bg-muted">
{getStatusLabel(driverInfo.vehicleStatus)}
</span>
<div className="flex gap-2">
<Button
type="button"
variant="outline"
size="sm"
onClick={() => onDriverStatusChange("off")}
disabled={driverInfo.vehicleStatus === "off"}
className="flex items-center gap-1"
>
<Clock className="h-3 w-3" />
</Button>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => onDriverStatusChange("maintenance")}
disabled={driverInfo.vehicleStatus === "maintenance"}
className="flex items-center gap-1"
>
<Wrench className="h-3 w-3" />
</Button>
</div>
</div>
<p className="text-xs text-muted-foreground">
* /
</p>
</div>
)}
</>
)}
</div>
</>
)}
@ -396,6 +468,50 @@ export function ProfileModal({
message={alertModal.message}
type={alertModal.type}
/>
{/* 새 차량 등록 모달 */}
{isVehicleRegisterModalOpen && newVehicleData && onNewVehicleDataChange && onRegisterVehicle && onCloseVehicleRegisterModal && (
<ResizableDialog open={isVehicleRegisterModalOpen} onOpenChange={onCloseVehicleRegisterModal}>
<ResizableDialogContent className="sm:max-w-[400px]">
<ResizableDialogHeader>
<ResizableDialogTitle> </ResizableDialogTitle>
<ResizableDialogDescription>
.
</ResizableDialogDescription>
</ResizableDialogHeader>
<div className="grid gap-4 py-4">
<div className="space-y-2">
<Label htmlFor="newVehicleNumber"> *</Label>
<Input
id="newVehicleNumber"
value={newVehicleData.vehicleNumber}
onChange={(e) => onNewVehicleDataChange("vehicleNumber", e.target.value)}
placeholder="12가1234"
/>
</div>
<div className="space-y-2">
<Label htmlFor="newVehicleType"></Label>
<Input
id="newVehicleType"
value={newVehicleData.vehicleType || ""}
onChange={(e) => onNewVehicleDataChange("vehicleType", e.target.value)}
placeholder="1톤 카고"
/>
</div>
</div>
<ResizableDialogFooter>
<Button type="button" variant="outline" onClick={onCloseVehicleRegisterModal}>
</Button>
<Button type="button" onClick={onRegisterVehicle}>
</Button>
</ResizableDialogFooter>
</ResizableDialogContent>
</ResizableDialog>
)}
</>
);
}

View File

@ -9,7 +9,10 @@ import {
updateDriverProfile,
updateDriverStatus,
deleteDriverAccount,
deleteDriverVehicle,
registerDriverVehicle,
DriverProfile,
VehicleRegisterData,
} from "@/lib/api/driver";
import { DriverInfo, DriverFormData } from "@/components/layout/ProfileModal";
@ -58,12 +61,22 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
// 운전자 정보 상태
const [isDriver, setIsDriver] = useState(false);
const [hasVehicle, setHasVehicle] = useState(false); // 차량 보유 여부
const [driverInfo, setDriverInfo] = useState<DriverInfo | null>(null);
const [driverFormData, setDriverFormData] = useState<DriverFormData>({
vehicleNumber: "",
vehicleType: "",
licenseNumber: "",
phoneNumber: "",
branchName: "",
});
// 새 차량 등록 모달 상태
const [isVehicleRegisterModalOpen, setIsVehicleRegisterModalOpen] = useState(false);
const [newVehicleData, setNewVehicleData] = useState<VehicleRegisterData>({
vehicleNumber: "",
vehicleType: "",
branchName: "",
});
// 알림 모달 표시 함수
@ -99,21 +112,27 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
const response = await getDriverProfile();
if (response.success && response.data) {
setIsDriver(true);
// 차량 보유 여부 확인
const vehicleExists = !!response.data.vehicleNumber;
setHasVehicle(vehicleExists);
setDriverInfo({
vehicleNumber: response.data.vehicleNumber,
vehicleType: response.data.vehicleType,
licenseNumber: response.data.licenseNumber,
phoneNumber: response.data.phoneNumber,
vehicleStatus: response.data.vehicleStatus,
branchName: response.data.branchName,
});
setDriverFormData({
vehicleNumber: response.data.vehicleNumber || "",
vehicleType: response.data.vehicleType || "",
licenseNumber: response.data.licenseNumber || "",
phoneNumber: response.data.phoneNumber || "",
branchName: response.data.branchName || "",
});
} else {
setIsDriver(false);
setHasVehicle(false);
setDriverInfo(null);
}
} catch (error) {
@ -229,6 +248,83 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
}
}, [showAlert]);
/**
*
*/
const handleDeleteVehicle = useCallback(async () => {
if (!confirm("이 차량을 더 이상 사용하지 않습니까?\n차량 정보가 삭제됩니다.")) {
return;
}
try {
const response = await deleteDriverVehicle();
if (response.success) {
showAlert("삭제 완료", "차량이 삭제되었습니다.", "success");
// 운전자 정보 새로고침
await loadDriverInfo();
} else {
showAlert("삭제 실패", response.message || "차량 삭제에 실패했습니다.", "error");
}
} catch (error) {
console.error("차량 삭제 실패:", error);
showAlert("오류", "차량 삭제 중 오류가 발생했습니다.", "error");
}
}, [showAlert, loadDriverInfo]);
/**
*
*/
const openVehicleRegisterModal = useCallback(() => {
setNewVehicleData({
vehicleNumber: "",
vehicleType: "",
branchName: driverFormData.branchName || "", // 기존 소속 지점 유지
});
setIsVehicleRegisterModalOpen(true);
}, [driverFormData.branchName]);
/**
*
*/
const closeVehicleRegisterModal = useCallback(() => {
setIsVehicleRegisterModalOpen(false);
}, []);
/**
*
*/
const updateNewVehicleData = useCallback((field: keyof VehicleRegisterData, value: string) => {
setNewVehicleData((prev) => ({
...prev,
[field]: value,
}));
}, []);
/**
*
*/
const handleRegisterVehicle = useCallback(async () => {
if (!newVehicleData.vehicleNumber) {
showAlert("입력 오류", "차량번호는 필수입니다.", "error");
return;
}
try {
const response = await registerDriverVehicle(newVehicleData);
if (response.success) {
showAlert("등록 완료", "차량이 등록되었습니다.", "success");
setIsVehicleRegisterModalOpen(false);
// 운전자 정보 새로고침
await loadDriverInfo();
} else {
showAlert("등록 실패", response.message || "차량 등록에 실패했습니다.", "error");
}
} catch (error) {
console.error("차량 등록 실패:", error);
showAlert("오류", "차량 등록 중 오류가 발생했습니다.", "error");
}
}, [newVehicleData, showAlert, loadDriverInfo]);
/**
*
*/
@ -341,6 +437,7 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
licenseNumber: driverFormData.licenseNumber,
vehicleNumber: driverFormData.vehicleNumber,
vehicleType: driverFormData.vehicleType,
branchName: driverFormData.branchName,
});
if (!driverResponse.success) {
@ -400,9 +497,14 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
// 운전자 관련 상태
isDriver,
hasVehicle,
driverInfo,
driverFormData,
// 새 차량 등록 모달 상태
isVehicleRegisterModalOpen,
newVehicleData,
// 액션
openProfileModal,
closeProfileModal,
@ -415,5 +517,10 @@ export const useProfile = (user: any, refreshUserData: () => Promise<void>, refr
updateDriverFormData,
handleDriverStatusChange,
handleDriverAccountDelete,
handleDeleteVehicle,
openVehicleRegisterModal,
closeVehicleRegisterModal,
updateNewVehicleData,
handleRegisterVehicle,
};
};

View File

@ -9,6 +9,7 @@ export interface DriverProfile {
vehicleNumber: string;
vehicleType: string | null;
vehicleStatus: string | null;
branchName: string | null;
}
export interface DriverProfileUpdateData {
@ -17,6 +18,7 @@ export interface DriverProfileUpdateData {
licenseNumber?: string;
vehicleNumber?: string;
vehicleType?: string;
branchName?: string;
}
/**
@ -72,6 +74,47 @@ export async function updateDriverStatus(
}
}
/**
* ( )
*/
export async function deleteDriverVehicle(): Promise<{
success: boolean;
message?: string;
}> {
try {
const response = await apiClient.delete("/driver/vehicle");
return response.data;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || "차량 삭제에 실패했습니다.",
};
}
}
/**
*
*/
export interface VehicleRegisterData {
vehicleNumber: string;
vehicleType?: string;
branchName?: string;
}
export async function registerDriverVehicle(
data: VehicleRegisterData
): Promise<{ success: boolean; message?: string }> {
try {
const response = await apiClient.post("/driver/vehicle", data);
return response.data;
} catch (error: any) {
return {
success: false,
message: error.response?.data?.message || "차량 등록에 실패했습니다.",
};
}
}
/**
*
*/