import { queryConfirmAlarm, queryrUnconfirmAlarm, } from "@/controller/AlarmController"; import { useThemeContext } from "@/hooks/use-theme-context"; import { Ionicons } from "@expo/vector-icons"; import dayjs from "dayjs"; import React, { useMemo, useState } from "react"; import { ActivityIndicator, Alert, Modal, StyleSheet, Text, TextInput, TouchableOpacity, View, } from "react-native"; interface AlarmCardProps { alarm: Model.Alarm; onReload?: (onReload: boolean) => void; } export const AlarmCard: React.FC = ({ alarm, onReload }) => { const { colors } = useThemeContext(); const [showModal, setShowModal] = useState(false); const [note, setNote] = useState(""); const [submitting, setSubmitting] = useState(false); const canSubmit = useMemo( () => note.trim().length > 0 || alarm.confirmed, [note, alarm.confirmed] ); // Determine level and colors based on alarm level const getAlarmConfig = (level?: number) => { if (level === 3) { // Danger - Red return { level: 3, icon: "warning" as const, bgColor: "#fee2e2", borderColor: "#DC0E0E", iconColor: "#dc2626", statusBg: "#dcfce7", statusText: "#166534", }; } else if (level === 2) { // Caution - Yellow/Orange return { level: 2, icon: "alert-circle" as const, bgColor: "#fef3c7", borderColor: "#FF6C0C", iconColor: "#d97706", statusBg: "#fef08a", statusText: "#713f12", }; } else { // Info - Green return { level: 1, icon: "information-circle" as const, bgColor: "#fffefe", borderColor: "#FF937E", iconColor: "#FF937E", statusBg: "#dcfce7", statusText: "#166534", }; } }; const config = getAlarmConfig(alarm.level); const formatDate = (timestamp?: number) => { if (!timestamp) return "N/A"; return dayjs.unix(timestamp).format("YYYY-MM-DD HH:mm"); }; const ensurePayload = () => { if (!alarm.id || !alarm.thing_id || !alarm.time) { Alert.alert("Thiếu dữ liệu", "Không đủ thông tin để xác nhận cảnh báo"); return false; } return true; }; const submitConfirm = async (action: "confirm" | "unconfirm") => { if (!ensurePayload()) return; if (action === "confirm" && note.trim().length === 0) { Alert.alert("Thông báo", "Vui lòng nhập ghi chú để xác nhận"); return; } try { setSubmitting(true); if (action === "confirm") { await queryConfirmAlarm({ id: alarm.id!, thing_id: alarm.thing_id!, time: alarm.time!, description: note.trim(), }); } else { await queryrUnconfirmAlarm({ id: alarm.id!, thing_id: alarm.thing_id!, time: alarm.time!, }); } onReload?.(true); } catch (error: any) { console.error("Cannot confirm/unconfirm alarm: ", error); const status = error?.response?.status ?? error?.status; // If server returns 404, ignore silently if (status !== 404) { Alert.alert("Lỗi", "Không thể xử lý yêu cầu. Vui lòng thử lại."); } } finally { setSubmitting(false); setShowModal(false); setNote(""); } }; const handlePress = (alarm: Model.Alarm) => { if (alarm.confirmed) { Alert.alert( "Thông báo", "Bạn có chắc muốn ngừng xác nhận cảnh báo này?", [ { text: "Hủy", style: "cancel" }, { text: "Ngừng xác nhận", style: "destructive", onPress: () => submitConfirm("unconfirm"), }, ] ); } else { setShowModal(true); } }; return ( {/* Left Side - Icon and Content */} {/* Icon */} {/* Title and Info */} {/* Name */} {alarm.name || alarm.thing_name || "Unknown"} {/* Location (thing_name) and Time */} Trạm {alarm.thing_name || "Unknown"} Thời gian {formatDate(alarm.time)} {/* Status Badge */} handlePress(alarm)} activeOpacity={0.7} > {alarm.confirmed ? "Đã xác nhận" : "Chờ xác nhận"} {alarm.confirmed && ( )} setShowModal(false)} > Nhập ghi chú xác nhận { setShowModal(false); setNote(""); }} disabled={submitting} > Hủy submitConfirm("confirm")} disabled={submitting || !canSubmit} > {submitting ? ( ) : ( Xác nhận )} ); }; const styles = StyleSheet.create({ card: { borderRadius: 12, // borderWidth: 1, paddingVertical: 16, paddingHorizontal: 12, marginBottom: 12, }, container: { flexDirection: "row", alignItems: "flex-start", justifyContent: "space-between", }, content: { flex: 1, flexDirection: "row", alignItems: "flex-start", }, iconContainer: { width: 48, height: 48, borderRadius: 12, alignItems: "flex-start", justifyContent: "flex-start", // marginRight: 5, }, textContainer: { flex: 1, }, titleRow: { marginBottom: 8, }, code: { fontSize: 12, fontWeight: "600", marginBottom: 4, }, title: { fontSize: 16, fontWeight: "600", marginBottom: 8, }, infoRow: { flexDirection: "row", justifyContent: "space-between", marginBottom: 12, gap: 16, }, infoItem: { flex: 1, }, infoLabel: { fontSize: 12, marginBottom: 4, }, infoValue: { fontSize: 14, fontWeight: "500", }, statusContainer: { marginTop: 8, }, statusBadge: { alignSelf: "flex-start", paddingVertical: 6, paddingHorizontal: 12, borderRadius: 20, borderWidth: 0.2, }, statusText: { fontSize: 12, fontWeight: "600", }, rightIcon: { width: 24, height: 24, alignItems: "center", justifyContent: "center", marginLeft: 12, }, modalOverlay: { flex: 1, backgroundColor: "rgba(0,0,0,0.3)", justifyContent: "center", paddingHorizontal: 16, }, modalContent: { borderRadius: 12, padding: 16, gap: 12, }, modalTitle: { fontSize: 16, fontWeight: "700", }, input: { minHeight: 80, borderRadius: 8, borderWidth: 1, borderColor: "#e5e7eb", padding: 12, textAlignVertical: "top", }, modalActions: { flexDirection: "row", justifyContent: "flex-end", gap: 12, }, modalButton: { paddingHorizontal: 16, paddingVertical: 10, borderRadius: 8, }, cancelButton: { backgroundColor: "#e5e7eb", }, confirmButton: { backgroundColor: "#dc2626", }, disabledButton: { opacity: 0.6, }, cancelText: { color: "#111827", fontWeight: "600", }, confirmText: { color: "#fff", fontWeight: "700", }, }); export default AlarmCard;