Cập nhật tab Nhật ký ( CRUD chuyến đi, CRUD thuyền viên trong chuyến đi )
This commit is contained in:
@@ -227,6 +227,30 @@ export default function TripFormModal({
|
||||
Alert.alert(t("common.error"), t("diary.validation.datesRequired"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate: thời điểm khởi hành phải từ hiện tại trở đi
|
||||
const now = new Date();
|
||||
const startMinutes = Math.floor(startDate.getTime() / 60000);
|
||||
const nowMinutes = Math.floor(now.getTime() / 60000);
|
||||
if (startMinutes < nowMinutes) {
|
||||
Alert.alert(
|
||||
t("common.error"),
|
||||
t("diary.validation.startDateNotInPast") ||
|
||||
"Thời điểm khởi hành không được ở quá khứ"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate: thời điểm kết thúc phải sau thời điểm khởi hành
|
||||
if (endDate <= startDate) {
|
||||
Alert.alert(
|
||||
t("common.error"),
|
||||
t("diary.validation.endDateAfterStart") ||
|
||||
"Thời điểm kết thúc phải sau thời điểm khởi hành"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!tripName.trim()) {
|
||||
Alert.alert(t("common.error"), t("diary.validation.tripNameRequired"));
|
||||
return false;
|
||||
@@ -237,7 +261,6 @@ export default function TripFormModal({
|
||||
// Build API body
|
||||
const buildApiBody = useCallback((): Model.TripAPIBody => {
|
||||
return {
|
||||
thing_id: selectedShipId,
|
||||
name: tripName,
|
||||
departure_time: startDate?.toISOString() || "",
|
||||
departure_port_id: departurePortId,
|
||||
@@ -257,7 +280,6 @@ export default function TripFormModal({
|
||||
})),
|
||||
};
|
||||
}, [
|
||||
selectedShipId,
|
||||
tripName,
|
||||
startDate,
|
||||
endDate,
|
||||
@@ -293,10 +315,28 @@ export default function TripFormModal({
|
||||
isEditMode ? "Error updating trip:" : "Error creating trip:",
|
||||
error
|
||||
);
|
||||
Alert.alert(
|
||||
t("common.error"),
|
||||
isEditMode ? t("diary.updateTripError") : t("diary.createTripError")
|
||||
);
|
||||
|
||||
// Lấy message từ server response
|
||||
const serverMessage = error.response?.data || "";
|
||||
|
||||
// Kiểm tra lỗi cụ thể: trip already exists
|
||||
if (
|
||||
serverMessage.includes &&
|
||||
serverMessage.includes("already exists and not completed")
|
||||
) {
|
||||
// Đánh dấu lỗi đã được xử lý (axios sẽ không hiển thị toast cho status 400)
|
||||
Alert.alert(
|
||||
t("common.warning") || "Cảnh báo",
|
||||
t("diary.tripAlreadyExistsError") ||
|
||||
"Chuyến đi đang diễn ra chưa hoàn thành. Vui lòng hoàn thành chuyến đi hiện tại trước khi tạo chuyến mới."
|
||||
);
|
||||
} else {
|
||||
// Các lỗi khác
|
||||
Alert.alert(
|
||||
t("common.error"),
|
||||
isEditMode ? t("diary.updateTripError") : t("diary.createTripError")
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
@@ -356,7 +396,10 @@ export default function TripFormModal({
|
||||
{!isEditMode && <AutoFillSection onAutoFill={handleAutoFill} />}
|
||||
|
||||
{/* Section 1: Basic Information */}
|
||||
<FormSection title={t("diary.formSection.basicInfo")} icon="boat-outline">
|
||||
<FormSection
|
||||
title={t("diary.formSection.basicInfo")}
|
||||
icon="boat-outline"
|
||||
>
|
||||
{/* Ship Selector - disabled in edit mode */}
|
||||
<ShipSelector
|
||||
selectedShipId={selectedShipId}
|
||||
@@ -369,7 +412,10 @@ export default function TripFormModal({
|
||||
</FormSection>
|
||||
|
||||
{/* Section 2: Schedule & Location */}
|
||||
<FormSection title={t("diary.formSection.schedule")} icon="calendar-outline">
|
||||
<FormSection
|
||||
title={t("diary.formSection.schedule")}
|
||||
icon="calendar-outline"
|
||||
>
|
||||
{/* Trip Duration */}
|
||||
<TripDurationPicker
|
||||
startDate={startDate}
|
||||
@@ -394,13 +440,27 @@ export default function TripFormModal({
|
||||
</FormSection>
|
||||
|
||||
{/* Section 3: Equipment */}
|
||||
<FormSection title={t("diary.formSection.equipment")} icon="construct-outline">
|
||||
<FishingGearList items={fishingGears} onChange={setFishingGears} hideTitle />
|
||||
<FormSection
|
||||
title={t("diary.formSection.equipment")}
|
||||
icon="construct-outline"
|
||||
>
|
||||
<FishingGearList
|
||||
items={fishingGears}
|
||||
onChange={setFishingGears}
|
||||
hideTitle
|
||||
/>
|
||||
</FormSection>
|
||||
|
||||
{/* Section 4: Costs */}
|
||||
<FormSection title={t("diary.formSection.costs")} icon="wallet-outline">
|
||||
<MaterialCostList items={tripCosts} onChange={setTripCosts} hideTitle />
|
||||
<FormSection
|
||||
title={t("diary.formSection.costs")}
|
||||
icon="wallet-outline"
|
||||
>
|
||||
<MaterialCostList
|
||||
items={tripCosts}
|
||||
onChange={setTripCosts}
|
||||
hideTitle
|
||||
/>
|
||||
</FormSection>
|
||||
</ScrollView>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user