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:
2025-12-29 15:56:47 +07:00
parent 190e44b09e
commit 871360af49
24 changed files with 1451 additions and 407 deletions

View File

@@ -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>