cập nhật thông tin cảng trong modal add/edit trip, tối ưu lại UI modal add/edit trip

This commit is contained in:
2025-12-24 11:38:23 +07:00
parent 000a4ed856
commit 24847504b1
9 changed files with 491 additions and 127 deletions

View File

@@ -23,6 +23,7 @@ import PortSelector from "./PortSelector";
import BasicInfoInput from "./BasicInfoInput";
import ShipSelector from "./ShipSelector";
import AutoFillSection from "./AutoFillSection";
import FormSection from "./FormSection";
import { createTrip, updateTrip } from "@/controller/TripController";
import {
convertFishingGears,
@@ -80,15 +81,31 @@ export default function TripFormModal({
).current;
// Form state
const [selectedShipId, setSelectedShipId] = useState(DEFAULT_FORM_STATE.selectedShipId);
const [selectedShipId, setSelectedShipId] = useState(
DEFAULT_FORM_STATE.selectedShipId
);
const [tripName, setTripName] = useState(DEFAULT_FORM_STATE.tripName);
const [fishingGears, setFishingGears] = useState<FishingGear[]>(DEFAULT_FORM_STATE.fishingGears);
const [tripCosts, setTripCosts] = useState<TripCost[]>(DEFAULT_FORM_STATE.tripCosts);
const [startDate, setStartDate] = useState<Date | null>(DEFAULT_FORM_STATE.startDate);
const [endDate, setEndDate] = useState<Date | null>(DEFAULT_FORM_STATE.endDate);
const [departurePortId, setDeparturePortId] = useState(DEFAULT_FORM_STATE.departurePortId);
const [arrivalPortId, setArrivalPortId] = useState(DEFAULT_FORM_STATE.arrivalPortId);
const [fishingGroundCodes, setFishingGroundCodes] = useState(DEFAULT_FORM_STATE.fishingGroundCodes);
const [fishingGears, setFishingGears] = useState<FishingGear[]>(
DEFAULT_FORM_STATE.fishingGears
);
const [tripCosts, setTripCosts] = useState<TripCost[]>(
DEFAULT_FORM_STATE.tripCosts
);
const [startDate, setStartDate] = useState<Date | null>(
DEFAULT_FORM_STATE.startDate
);
const [endDate, setEndDate] = useState<Date | null>(
DEFAULT_FORM_STATE.endDate
);
const [departurePortId, setDeparturePortId] = useState(
DEFAULT_FORM_STATE.departurePortId
);
const [arrivalPortId, setArrivalPortId] = useState(
DEFAULT_FORM_STATE.arrivalPortId
);
const [fishingGroundCodes, setFishingGroundCodes] = useState(
DEFAULT_FORM_STATE.fishingGroundCodes
);
const [isSubmitting, setIsSubmitting] = useState(false);
// Reset form to default state
@@ -105,17 +122,22 @@ export default function TripFormModal({
}, []);
// Fill form with trip data
const fillFormWithTripData = useCallback((data: Model.Trip, prefix: string) => {
setSelectedShipId(data.vms_id || "");
setTripName(data.name || "");
setFishingGears(convertFishingGears(data.fishing_gears, prefix));
setTripCosts(convertTripCosts(data.trip_cost, prefix));
if (data.departure_time) setStartDate(new Date(data.departure_time));
if (data.arrival_time) setEndDate(new Date(data.arrival_time));
if (data.departure_port_id) setDeparturePortId(data.departure_port_id);
if (data.arrival_port_id) setArrivalPortId(data.arrival_port_id);
setFishingGroundCodes(convertFishingGroundCodes(data.fishing_ground_codes));
}, []);
const fillFormWithTripData = useCallback(
(data: Model.Trip, prefix: string) => {
setSelectedShipId(data.vms_id || "");
setTripName(data.name || "");
setFishingGears(convertFishingGears(data.fishing_gears, prefix));
setTripCosts(convertTripCosts(data.trip_cost, prefix));
if (data.departure_time) setStartDate(new Date(data.departure_time));
if (data.arrival_time) setEndDate(new Date(data.arrival_time));
if (data.departure_port_id) setDeparturePortId(data.departure_port_id);
if (data.arrival_port_id) setArrivalPortId(data.arrival_port_id);
setFishingGroundCodes(
convertFishingGroundCodes(data.fishing_ground_codes)
);
},
[]
);
// Handle animation when modal visibility changes
useEffect(() => {
@@ -185,9 +207,12 @@ export default function TripFormModal({
setSelectedShipId(selectedThingId);
setFishingGears(convertFishingGears(tripData.fishing_gears, "auto"));
setTripCosts(convertTripCosts(tripData.trip_cost, "auto"));
if (tripData.departure_port_id) setDeparturePortId(tripData.departure_port_id);
if (tripData.departure_port_id)
setDeparturePortId(tripData.departure_port_id);
if (tripData.arrival_port_id) setArrivalPortId(tripData.arrival_port_id);
setFishingGroundCodes(convertFishingGroundCodes(tripData.fishing_ground_codes));
setFishingGroundCodes(
convertFishingGroundCodes(tripData.fishing_ground_codes)
);
},
[]
);
@@ -323,47 +348,60 @@ export default function TripFormModal({
</View>
{/* Content */}
<ScrollView style={styles.content} showsVerticalScrollIndicator={false}>
<ScrollView
style={styles.content}
showsVerticalScrollIndicator={false}
>
{/* Auto Fill Section - only show in add mode */}
{!isEditMode && <AutoFillSection onAutoFill={handleAutoFill} />}
{/* Ship Selector - disabled in edit mode */}
<ShipSelector
selectedShipId={selectedShipId}
onChange={setSelectedShipId}
disabled={isEditMode}
/>
{/* Section 1: Basic Information */}
<FormSection title={t("diary.formSection.basicInfo")} icon="boat-outline">
{/* Ship Selector - disabled in edit mode */}
<ShipSelector
selectedShipId={selectedShipId}
onChange={setSelectedShipId}
disabled={isEditMode}
/>
{/* Trip Name */}
<TripNameInput value={tripName} onChange={setTripName} />
{/* Trip Name */}
<TripNameInput value={tripName} onChange={setTripName} />
</FormSection>
{/* Fishing Gear List */}
<FishingGearList items={fishingGears} onChange={setFishingGears} />
{/* Section 2: Schedule & Location */}
<FormSection title={t("diary.formSection.schedule")} icon="calendar-outline">
{/* Trip Duration */}
<TripDurationPicker
startDate={startDate}
endDate={endDate}
onStartDateChange={setStartDate}
onEndDateChange={setEndDate}
/>
{/* Trip Cost List */}
<MaterialCostList items={tripCosts} onChange={setTripCosts} />
{/* Port Selector */}
<PortSelector
departurePortId={departurePortId}
arrivalPortId={arrivalPortId}
onDeparturePortChange={setDeparturePortId}
onArrivalPortChange={setArrivalPortId}
/>
{/* Trip Duration */}
<TripDurationPicker
startDate={startDate}
endDate={endDate}
onStartDateChange={setStartDate}
onEndDateChange={setEndDate}
/>
{/* Fishing Ground Codes */}
<BasicInfoInput
fishingGroundCodes={fishingGroundCodes}
onChange={setFishingGroundCodes}
/>
</FormSection>
{/* Port Selector */}
<PortSelector
departurePortId={departurePortId}
arrivalPortId={arrivalPortId}
onDeparturePortChange={setDeparturePortId}
onArrivalPortChange={setArrivalPortId}
/>
{/* Section 3: Equipment */}
<FormSection title={t("diary.formSection.equipment")} icon="construct-outline">
<FishingGearList items={fishingGears} onChange={setFishingGears} hideTitle />
</FormSection>
{/* Fishing Ground Codes */}
<BasicInfoInput
fishingGroundCodes={fishingGroundCodes}
onChange={setFishingGroundCodes}
/>
{/* Section 4: Costs */}
<FormSection title={t("diary.formSection.costs")} icon="wallet-outline">
<MaterialCostList items={tripCosts} onChange={setTripCosts} hideTitle />
</FormSection>
</ScrollView>
{/* Footer */}
@@ -373,7 +411,9 @@ export default function TripFormModal({
onPress={handleCancel}
activeOpacity={0.7}
>
<Text style={[styles.cancelButtonText, themedStyles.cancelButtonText]}>
<Text
style={[styles.cancelButtonText, themedStyles.cancelButtonText]}
>
{t("common.cancel")}
</Text>
</TouchableOpacity>