384 lines
11 KiB
TypeScript
384 lines
11 KiB
TypeScript
import {
|
|
queryDeleteSos,
|
|
queryGetSos,
|
|
querySendSosMessage,
|
|
} from "@/controller/DeviceController";
|
|
import { useI18n } from "@/hooks/use-i18n";
|
|
import { showErrorToast } from "@/services/toast_service";
|
|
import { sosMessage } from "@/utils/sosUtils";
|
|
import { MaterialIcons } from "@expo/vector-icons";
|
|
import { useEffect, useState } from "react";
|
|
import {
|
|
FlatList,
|
|
ScrollView,
|
|
StyleSheet,
|
|
Text,
|
|
TextInput,
|
|
TouchableOpacity,
|
|
View,
|
|
} from "react-native";
|
|
import { Button, ButtonText } from "../ui/gluestack-ui-provider/button";
|
|
import {
|
|
Modal,
|
|
ModalBackdrop,
|
|
ModalBody,
|
|
ModalContent,
|
|
ModalFooter,
|
|
ModalHeader,
|
|
} from "../ui/gluestack-ui-provider/modal";
|
|
|
|
const SosButton = () => {
|
|
const [sosData, setSosData] = useState<Model.SosResponse | null>();
|
|
const [showConfirmSosDialog, setShowConfirmSosDialog] = useState(false);
|
|
const [selectedSosMessage, setSelectedSosMessage] = useState<number | null>(
|
|
null
|
|
);
|
|
const [customMessage, setCustomMessage] = useState("");
|
|
const [showDropdown, setShowDropdown] = useState(false);
|
|
const [errors, setErrors] = useState<{ [key: string]: string }>({});
|
|
const { t } = useI18n();
|
|
const sosOptions = [
|
|
...sosMessage.map((msg) => ({ ma: msg.ma, moTa: msg.moTa })),
|
|
{ ma: 999, moTa: "Khác" },
|
|
];
|
|
|
|
const getSosData = async () => {
|
|
try {
|
|
const response = await queryGetSos();
|
|
setSosData(response.data);
|
|
} catch (error) {
|
|
console.error("Failed to fetch SOS data:", error);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
getSosData();
|
|
}, []);
|
|
|
|
const validateForm = () => {
|
|
const newErrors: { [key: string]: string } = {};
|
|
|
|
// Không cần validate sosMessage vì luôn có default value (11)
|
|
|
|
if (selectedSosMessage === 999 && customMessage.trim() === "") {
|
|
newErrors.customMessage = t("home.sos.statusRequired");
|
|
}
|
|
|
|
setErrors(newErrors);
|
|
return Object.keys(newErrors).length === 0;
|
|
};
|
|
|
|
const handleConfirmSos = async () => {
|
|
if (validateForm()) {
|
|
let messageToSend = "";
|
|
if (selectedSosMessage === 999) {
|
|
messageToSend = customMessage.trim();
|
|
} else {
|
|
const selectedOption = sosOptions.find(
|
|
(opt) => opt.ma === selectedSosMessage
|
|
);
|
|
messageToSend = selectedOption ? selectedOption.moTa : "";
|
|
}
|
|
// Gửi dữ liệu đi
|
|
setShowConfirmSosDialog(false);
|
|
// Reset form
|
|
setSelectedSosMessage(null);
|
|
setCustomMessage("");
|
|
setErrors({});
|
|
await sendSosMessage(messageToSend);
|
|
}
|
|
};
|
|
|
|
const handleClickButton = async (isActive: boolean) => {
|
|
if (isActive) {
|
|
const resp = await queryDeleteSos();
|
|
if (resp.status === 200) {
|
|
await getSosData();
|
|
}
|
|
} else {
|
|
setSelectedSosMessage(11); // Mặc định chọn lý do ma: 11
|
|
setShowConfirmSosDialog(true);
|
|
}
|
|
};
|
|
|
|
const sendSosMessage = async (message: string) => {
|
|
try {
|
|
const resp = await querySendSosMessage(message);
|
|
if (resp.status === 200) {
|
|
await getSosData();
|
|
}
|
|
} catch (error) {
|
|
console.error("Error when send sos: ", error);
|
|
showErrorToast(t("home.sos.sendError"));
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Button
|
|
className="shadow-md rounded-full"
|
|
size="lg"
|
|
action="negative"
|
|
onPress={() => handleClickButton(sosData?.active || false)}
|
|
>
|
|
<MaterialIcons name="warning" size={15} color="white" />
|
|
<ButtonText className="text-center">
|
|
{sosData?.active ? t("home.sos.active") : t("home.sos.inactive")}
|
|
</ButtonText>
|
|
{/* <ButtonSpinner /> */}
|
|
{/* <ButtonIcon /> */}
|
|
</Button>
|
|
<Modal
|
|
isOpen={showConfirmSosDialog}
|
|
onClose={() => {
|
|
setShowConfirmSosDialog(false);
|
|
setSelectedSosMessage(null);
|
|
setCustomMessage("");
|
|
setErrors({});
|
|
}}
|
|
>
|
|
<ModalBackdrop />
|
|
<ModalContent>
|
|
<ModalHeader className="flex-col gap-0.5 items-center">
|
|
<Text
|
|
style={{ fontSize: 18, fontWeight: "bold", textAlign: "center" }}
|
|
>
|
|
{t("home.sos.title")}
|
|
</Text>
|
|
</ModalHeader>
|
|
<ModalBody className="mb-4">
|
|
<ScrollView style={{ maxHeight: 400 }}>
|
|
{/* Dropdown Nội dung SOS */}
|
|
<View style={styles.formGroup}>
|
|
<Text style={styles.label}>{t("home.sos.content")}</Text>
|
|
<TouchableOpacity
|
|
style={[
|
|
styles.dropdownButton,
|
|
errors.sosMessage ? styles.errorBorder : {},
|
|
]}
|
|
onPress={() => setShowDropdown(!showDropdown)}
|
|
>
|
|
<Text
|
|
style={[
|
|
styles.dropdownButtonText,
|
|
!selectedSosMessage && styles.placeholderText,
|
|
]}
|
|
>
|
|
{selectedSosMessage !== null
|
|
? sosOptions.find((opt) => opt.ma === selectedSosMessage)
|
|
?.moTa || t("home.sos.selectReason")
|
|
: t("home.sos.selectReason")}
|
|
</Text>
|
|
<MaterialIcons
|
|
name={showDropdown ? "expand-less" : "expand-more"}
|
|
size={20}
|
|
color="#666"
|
|
/>
|
|
</TouchableOpacity>
|
|
{errors.sosMessage && (
|
|
<Text style={styles.errorText}>{errors.sosMessage}</Text>
|
|
)}
|
|
</View>
|
|
|
|
{/* Input Custom Message nếu chọn "Khác" */}
|
|
{selectedSosMessage === 999 && (
|
|
<View style={styles.formGroup}>
|
|
<Text style={styles.label}>{t("home.sos.statusInput")}</Text>
|
|
<TextInput
|
|
style={[
|
|
styles.input,
|
|
errors.customMessage ? styles.errorInput : {},
|
|
]}
|
|
placeholder={t("home.sos.enterStatus")}
|
|
placeholderTextColor="#999"
|
|
value={customMessage}
|
|
onChangeText={(text) => {
|
|
setCustomMessage(text);
|
|
if (text.trim() !== "") {
|
|
setErrors((prev) => {
|
|
const newErrors = { ...prev };
|
|
delete newErrors.customMessage;
|
|
return newErrors;
|
|
});
|
|
}
|
|
}}
|
|
multiline
|
|
numberOfLines={4}
|
|
/>
|
|
{errors.customMessage && (
|
|
<Text style={styles.errorText}>{errors.customMessage}</Text>
|
|
)}
|
|
</View>
|
|
)}
|
|
</ScrollView>
|
|
</ModalBody>
|
|
<ModalFooter className="flex-row items-start gap-2">
|
|
<Button
|
|
onPress={handleConfirmSos}
|
|
// className="w-1/3"
|
|
action="negative"
|
|
>
|
|
<ButtonText>{t("home.sos.confirm")}</ButtonText>
|
|
</Button>
|
|
<Button
|
|
onPress={() => {
|
|
setShowConfirmSosDialog(false);
|
|
setSelectedSosMessage(null);
|
|
setCustomMessage("");
|
|
setErrors({});
|
|
}}
|
|
// className="w-1/3"
|
|
action="secondary"
|
|
>
|
|
<ButtonText>{t("home.sos.cancel")}</ButtonText>
|
|
</Button>
|
|
</ModalFooter>
|
|
</ModalContent>
|
|
</Modal>
|
|
|
|
{/* Dropdown Modal - Nổi lên */}
|
|
{showDropdown && showConfirmSosDialog && (
|
|
<Modal isOpen={showDropdown} onClose={() => setShowDropdown(false)}>
|
|
<TouchableOpacity
|
|
style={styles.dropdownOverlay}
|
|
activeOpacity={1}
|
|
onPress={() => setShowDropdown(false)}
|
|
>
|
|
<View style={styles.dropdownModalContainer}>
|
|
<FlatList
|
|
data={sosOptions}
|
|
keyExtractor={(item) => item.ma.toString()}
|
|
renderItem={({ item }) => (
|
|
<TouchableOpacity
|
|
style={styles.dropdownModalItem}
|
|
onPress={() => {
|
|
setSelectedSosMessage(item.ma);
|
|
setShowDropdown(false);
|
|
// Clear custom message nếu chọn khác lý do
|
|
if (item.ma !== 999) {
|
|
setCustomMessage("");
|
|
}
|
|
}}
|
|
>
|
|
<Text
|
|
style={[
|
|
styles.dropdownModalItemText,
|
|
selectedSosMessage === item.ma &&
|
|
styles.selectedItemText,
|
|
]}
|
|
>
|
|
{item.moTa}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
)}
|
|
/>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</Modal>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
formGroup: {
|
|
marginBottom: 16,
|
|
},
|
|
label: {
|
|
fontSize: 14,
|
|
fontWeight: "600",
|
|
marginBottom: 8,
|
|
color: "#333",
|
|
},
|
|
dropdownButton: {
|
|
borderWidth: 1,
|
|
borderColor: "#ddd",
|
|
borderRadius: 8,
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 12,
|
|
flexDirection: "row",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
backgroundColor: "#fff",
|
|
},
|
|
errorBorder: {
|
|
borderColor: "#ff4444",
|
|
},
|
|
dropdownButtonText: {
|
|
fontSize: 14,
|
|
color: "#333",
|
|
flex: 1,
|
|
},
|
|
placeholderText: {
|
|
color: "#999",
|
|
},
|
|
dropdownList: {
|
|
borderWidth: 1,
|
|
borderColor: "#ddd",
|
|
borderRadius: 8,
|
|
marginTop: 4,
|
|
backgroundColor: "#fff",
|
|
overflow: "hidden",
|
|
},
|
|
dropdownItem: {
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 12,
|
|
borderBottomWidth: 1,
|
|
borderBottomColor: "#eee",
|
|
},
|
|
dropdownItemText: {
|
|
fontSize: 14,
|
|
color: "#333",
|
|
},
|
|
dropdownOverlay: {
|
|
flex: 1,
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
},
|
|
dropdownModalContainer: {
|
|
backgroundColor: "#fff",
|
|
borderRadius: 12,
|
|
maxHeight: 400,
|
|
minWidth: 280,
|
|
shadowColor: "#000",
|
|
shadowOffset: { width: 0, height: 4 },
|
|
shadowOpacity: 0.3,
|
|
shadowRadius: 8,
|
|
elevation: 10,
|
|
},
|
|
dropdownModalItem: {
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 14,
|
|
borderBottomWidth: 1,
|
|
borderBottomColor: "#f0f0f0",
|
|
},
|
|
dropdownModalItemText: {
|
|
fontSize: 14,
|
|
color: "#333",
|
|
},
|
|
selectedItemText: {
|
|
fontWeight: "600",
|
|
color: "#1054C9",
|
|
},
|
|
input: {
|
|
borderWidth: 1,
|
|
borderColor: "#ddd",
|
|
borderRadius: 8,
|
|
paddingHorizontal: 12,
|
|
paddingVertical: 12,
|
|
fontSize: 14,
|
|
color: "#333",
|
|
textAlignVertical: "top",
|
|
},
|
|
errorInput: {
|
|
borderColor: "#ff4444",
|
|
},
|
|
errorText: {
|
|
color: "#ff4444",
|
|
fontSize: 12,
|
|
marginTop: 4,
|
|
},
|
|
});
|
|
|
|
export default SosButton;
|