243 lines
8.0 KiB
TypeScript
243 lines
8.0 KiB
TypeScript
import { IconSymbol } from "@/components/ui/icon-symbol";
|
|
import { useI18n } from "@/hooks/use-i18n";
|
|
import React, { useEffect, useState } from "react";
|
|
import {
|
|
KeyboardAvoidingView,
|
|
Modal,
|
|
Platform,
|
|
ScrollView,
|
|
Text,
|
|
TextInput,
|
|
TouchableOpacity,
|
|
View,
|
|
} from "react-native";
|
|
import styles from "./style/TripCostDetailModal.styles";
|
|
|
|
// ---------------------------
|
|
// 🧩 Interface
|
|
// ---------------------------
|
|
interface TripCostDetailModalProps {
|
|
visible: boolean;
|
|
onClose: () => void;
|
|
data: Model.TripCost[];
|
|
}
|
|
|
|
// ---------------------------
|
|
// 💰 Component Modal
|
|
// ---------------------------
|
|
const TripCostDetailModal: React.FC<TripCostDetailModalProps> = ({
|
|
visible,
|
|
onClose,
|
|
data,
|
|
}) => {
|
|
const { t } = useI18n();
|
|
const [isEditing, setIsEditing] = useState(false);
|
|
const [editableData, setEditableData] = useState<Model.TripCost[]>(data);
|
|
|
|
// Cập nhật editableData khi props data thay đổi (API fetch xong)
|
|
useEffect(() => {
|
|
setEditableData(data);
|
|
}, [data]);
|
|
|
|
const tongCong = editableData.reduce((sum, item) => sum + item.total_cost, 0);
|
|
|
|
const handleEdit = () => {
|
|
setIsEditing(!isEditing);
|
|
};
|
|
|
|
const handleSave = () => {
|
|
setIsEditing(false);
|
|
// TODO: Save data to backend
|
|
console.log("Saved data:", editableData);
|
|
};
|
|
|
|
const handleCancel = () => {
|
|
setIsEditing(false);
|
|
setEditableData(data); // Reset to original data
|
|
};
|
|
|
|
const updateItem = (
|
|
index: number,
|
|
field: keyof Model.TripCost,
|
|
value: string
|
|
) => {
|
|
setEditableData((prev) =>
|
|
prev.map((item, idx) => {
|
|
if (idx === index) {
|
|
const updated = { ...item, [field]: value };
|
|
// Recalculate total_cost
|
|
if (field === "amount" || field === "cost_per_unit") {
|
|
const amount =
|
|
Number(field === "amount" ? value : item.amount) || 0;
|
|
const costPerUnit =
|
|
Number(field === "cost_per_unit" ? value : item.cost_per_unit) ||
|
|
0;
|
|
updated.total_cost = amount * costPerUnit;
|
|
}
|
|
return updated;
|
|
}
|
|
return item;
|
|
})
|
|
);
|
|
};
|
|
|
|
return (
|
|
<Modal
|
|
visible={visible}
|
|
animationType="slide"
|
|
presentationStyle="pageSheet"
|
|
onRequestClose={onClose}
|
|
>
|
|
<KeyboardAvoidingView
|
|
style={{ flex: 1 }}
|
|
behavior={Platform.OS === "ios" ? "padding" : "height"}
|
|
keyboardVerticalOffset={60}
|
|
>
|
|
<View style={styles.container}>
|
|
{/* Header */}
|
|
<View style={styles.header}>
|
|
<Text style={styles.title}>{t("trip.costDetailModal.title")}</Text>
|
|
<View style={styles.headerButtons}>
|
|
{isEditing ? (
|
|
<>
|
|
<TouchableOpacity
|
|
onPress={handleCancel}
|
|
style={styles.cancelButton}
|
|
>
|
|
<Text style={styles.cancelButtonText}>
|
|
{t("trip.costDetailModal.cancel")}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
<TouchableOpacity
|
|
onPress={handleSave}
|
|
style={styles.saveButton}
|
|
>
|
|
<Text style={styles.saveButtonText}>
|
|
{t("trip.costDetailModal.save")}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
</>
|
|
) : (
|
|
<TouchableOpacity
|
|
onPress={handleEdit}
|
|
style={styles.editButton}
|
|
>
|
|
<View style={styles.editIconButton}>
|
|
<IconSymbol
|
|
name="pencil"
|
|
size={28}
|
|
color="#fff"
|
|
weight="heavy"
|
|
/>
|
|
</View>
|
|
</TouchableOpacity>
|
|
)}
|
|
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
|
<View style={styles.closeIconButton}>
|
|
<IconSymbol name="xmark" size={28} color="#fff" />
|
|
</View>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Content */}
|
|
<ScrollView style={styles.content}>
|
|
{editableData.map((item, index) => (
|
|
<View key={index} style={styles.itemCard}>
|
|
{/* Loại */}
|
|
<View style={styles.fieldGroup}>
|
|
<Text style={styles.label}>
|
|
{t("trip.costDetailModal.costType")}
|
|
</Text>
|
|
<TextInput
|
|
style={[styles.input, !isEditing && styles.inputDisabled]}
|
|
value={item.type}
|
|
onChangeText={(value) => updateItem(index, "type", value)}
|
|
editable={isEditing}
|
|
placeholder={t("trip.costDetailModal.enterCostType")}
|
|
/>
|
|
</View>
|
|
|
|
{/* Số lượng & Đơn vị */}
|
|
<View style={styles.rowGroup}>
|
|
<View
|
|
style={[styles.fieldGroup, { flex: 1, marginRight: 8 }]}
|
|
>
|
|
<Text style={styles.label}>
|
|
{t("trip.costDetailModal.quantity")}
|
|
</Text>
|
|
<TextInput
|
|
style={[styles.input, !isEditing && styles.inputDisabled]}
|
|
value={String(item.amount ?? "")}
|
|
onChangeText={(value) =>
|
|
updateItem(index, "amount", value)
|
|
}
|
|
editable={isEditing}
|
|
keyboardType="numeric"
|
|
placeholder="0"
|
|
/>
|
|
</View>
|
|
<View style={[styles.fieldGroup, { flex: 1, marginLeft: 8 }]}>
|
|
<Text style={styles.label}>
|
|
{t("trip.costDetailModal.unit")}
|
|
</Text>
|
|
<TextInput
|
|
style={[styles.input, !isEditing && styles.inputDisabled]}
|
|
value={item.unit}
|
|
onChangeText={(value) => updateItem(index, "unit", value)}
|
|
editable={isEditing}
|
|
placeholder={t("trip.costDetailModal.placeholder")}
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
{/* Chi phí/đơn vị */}
|
|
<View style={styles.fieldGroup}>
|
|
<Text style={styles.label}>
|
|
{t("trip.costDetailModal.costPerUnit")}
|
|
</Text>
|
|
<TextInput
|
|
style={[styles.input, !isEditing && styles.inputDisabled]}
|
|
value={String(item.cost_per_unit ?? "")}
|
|
onChangeText={(value) =>
|
|
updateItem(index, "cost_per_unit", value)
|
|
}
|
|
editable={isEditing}
|
|
keyboardType="numeric"
|
|
placeholder="0"
|
|
/>
|
|
</View>
|
|
|
|
{/* Tổng chi phí */}
|
|
<View style={styles.fieldGroup}>
|
|
<Text style={styles.label}>
|
|
{t("trip.costDetailModal.totalCost")}
|
|
</Text>
|
|
<View style={styles.totalContainer}>
|
|
<Text style={styles.totalText}>
|
|
{item.total_cost.toLocaleString()}{" "}
|
|
{t("trip.costDetailModal.vnd")}
|
|
</Text>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
))}
|
|
|
|
{/* Footer Total */}
|
|
<View style={styles.footerTotal}>
|
|
<Text style={styles.footerLabel}>
|
|
{t("trip.costDetailModal.total")}
|
|
</Text>
|
|
<Text style={styles.footerAmount}>
|
|
{tongCong.toLocaleString()} {t("trip.costDetailModal.vnd")}
|
|
</Text>
|
|
</View>
|
|
</ScrollView>
|
|
</View>
|
|
</KeyboardAvoidingView>
|
|
</Modal>
|
|
);
|
|
};
|
|
|
|
export default TripCostDetailModal;
|