Khởi tạo ban đầu
This commit is contained in:
249
components/map/SosButton.tsx
Normal file
249
components/map/SosButton.tsx
Normal file
@@ -0,0 +1,249 @@
|
||||
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 { StyleSheet, Text, TextInput, View } from "react-native";
|
||||
import IconButton from "../IconButton";
|
||||
import Select from "../Select";
|
||||
import Modal from "../ui/modal";
|
||||
import { useThemeColor } from "@/hooks/use-theme-color";
|
||||
|
||||
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 [errors, setErrors] = useState<{ [key: string]: string }>({});
|
||||
const { t } = useI18n();
|
||||
|
||||
// Theme colors
|
||||
const textColor = useThemeColor({}, 'text');
|
||||
const borderColor = useThemeColor({}, 'border');
|
||||
const errorColor = useThemeColor({}, 'error');
|
||||
const backgroundColor = useThemeColor({}, 'background');
|
||||
|
||||
// Dynamic styles
|
||||
const styles = SosButtonStyles(textColor, borderColor, errorColor, backgroundColor);
|
||||
|
||||
const sosOptions = [
|
||||
...sosMessage.map((msg) => ({
|
||||
ma: msg.ma,
|
||||
moTa: msg.moTa,
|
||||
label: msg.moTa,
|
||||
value: msg.ma,
|
||||
})),
|
||||
{ ma: 999, moTa: "Khác", label: "Khác", value: 999 },
|
||||
];
|
||||
|
||||
const getSosData = async () => {
|
||||
try {
|
||||
const response = await queryGetSos();
|
||||
// console.log("SoS ResponseL: ", response);
|
||||
|
||||
setSosData(response.data);
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch SOS data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
getSosData();
|
||||
}, []);
|
||||
|
||||
const validateForm = () => {
|
||||
const newErrors: { [key: string]: string } = {};
|
||||
|
||||
if (selectedSosMessage === 999 && customMessage.trim() === "") {
|
||||
newErrors.customMessage = t("home.sos.statusRequired");
|
||||
}
|
||||
|
||||
setErrors(newErrors);
|
||||
return Object.keys(newErrors).length === 0;
|
||||
};
|
||||
|
||||
const handleConfirmSos = async () => {
|
||||
if (!validateForm()) {
|
||||
console.log("Form chưa validate");
|
||||
return; // Không đóng modal nếu validate fail
|
||||
}
|
||||
|
||||
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
|
||||
await sendSosMessage(messageToSend);
|
||||
|
||||
// Đóng modal và reset form sau khi gửi thành công
|
||||
setShowConfirmSosDialog(false);
|
||||
setSelectedSosMessage(null);
|
||||
setCustomMessage("");
|
||||
setErrors({});
|
||||
};
|
||||
|
||||
const handleClickButton = async (isActive: boolean) => {
|
||||
console.log("Is Active: ", isActive);
|
||||
|
||||
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 (
|
||||
<>
|
||||
<IconButton
|
||||
icon={<MaterialIcons name="warning" size={20} color="white" />}
|
||||
type="danger"
|
||||
size="middle"
|
||||
onPress={() => handleClickButton(sosData?.active || false)}
|
||||
style={{ borderRadius: 20 }}
|
||||
>
|
||||
{sosData?.active ? t("home.sos.active") : t("home.sos.inactive")}
|
||||
</IconButton>
|
||||
<Modal
|
||||
open={showConfirmSosDialog}
|
||||
onCancel={() => {
|
||||
setShowConfirmSosDialog(false);
|
||||
setSelectedSosMessage(null);
|
||||
setCustomMessage("");
|
||||
setErrors({});
|
||||
}}
|
||||
okText={t("home.sos.confirm")}
|
||||
cancelText={t("home.sos.cancel")}
|
||||
title={t("home.sos.title")}
|
||||
centered
|
||||
onOk={handleConfirmSos}
|
||||
>
|
||||
{/* Select Nội dung SOS */}
|
||||
<View style={styles.formGroup}>
|
||||
<Text style={styles.label}>{t("home.sos.content")}</Text>
|
||||
|
||||
<Select
|
||||
value={selectedSosMessage ?? undefined}
|
||||
options={sosOptions}
|
||||
placeholder={t("home.sos.selectReason")}
|
||||
onChange={(value) => {
|
||||
setSelectedSosMessage(value as number);
|
||||
// Clear custom message nếu chọn khác lý do
|
||||
if (value !== 999) {
|
||||
setCustomMessage("");
|
||||
}
|
||||
// Clear error if exists
|
||||
if (errors.sosMessage) {
|
||||
setErrors((prev) => {
|
||||
const newErrors = { ...prev };
|
||||
delete newErrors.sosMessage;
|
||||
return newErrors;
|
||||
});
|
||||
}
|
||||
}}
|
||||
showSearch={false}
|
||||
style={[errors.sosMessage ? styles.errorBorder : undefined]}
|
||||
/>
|
||||
{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={textColor + '99'} // Add transparency
|
||||
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>
|
||||
)}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const SosButtonStyles = (textColor: string, borderColor: string, errorColor: string, backgroundColor: string) => StyleSheet.create({
|
||||
formGroup: {
|
||||
marginBottom: 16,
|
||||
},
|
||||
label: {
|
||||
fontSize: 14,
|
||||
fontWeight: "600",
|
||||
marginBottom: 8,
|
||||
color: textColor,
|
||||
},
|
||||
errorBorder: {
|
||||
borderColor: errorColor,
|
||||
},
|
||||
input: {
|
||||
borderWidth: 1,
|
||||
borderColor: borderColor,
|
||||
borderRadius: 8,
|
||||
paddingHorizontal: 12,
|
||||
paddingVertical: 12,
|
||||
fontSize: 14,
|
||||
color: textColor,
|
||||
backgroundColor: backgroundColor,
|
||||
textAlignVertical: "top",
|
||||
},
|
||||
errorInput: {
|
||||
borderColor: errorColor,
|
||||
},
|
||||
errorText: {
|
||||
color: errorColor,
|
||||
fontSize: 12,
|
||||
marginTop: 4,
|
||||
},
|
||||
});
|
||||
|
||||
export default SosButton;
|
||||
Reference in New Issue
Block a user