Files
sgw-owner-app/components/alarm/AlarmSearchForm.tsx
2025-12-09 11:37:19 +07:00

306 lines
7.6 KiB
TypeScript

import Select, { SelectOption } from "@/components/Select";
import { ThemedText } from "@/components/themed-text";
import { ThemedView } from "@/components/themed-view";
import { useThemeContext } from "@/hooks/use-theme-context";
import { Ionicons } from "@expo/vector-icons";
import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
import { StyleSheet, TextInput, TouchableOpacity, View } from "react-native";
interface AlarmSearchFormProps {
initialValue?: {
name?: string;
level?: number;
confirmed?: boolean;
};
onSubmit: (payload: {
name?: string;
level?: number;
confirmed?: boolean;
}) => void;
onReset?: () => void;
}
interface FormData {
name: string;
level: number;
confirmed: string; // Using string for Select component compatibility
}
const AlarmSearchForm: React.FC<AlarmSearchFormProps> = ({
initialValue,
onSubmit,
onReset,
}) => {
const { colors } = useThemeContext();
const levelOptions: SelectOption[] = [
{ label: "Tất cả", value: 0 },
{ label: "Cảnh báo", value: 1 },
{ label: "Nguy hiểm", value: 2 },
];
const confirmedOptions: SelectOption[] = [
{ label: "Tất cả", value: "" },
{ label: "Đã xác nhận", value: "true" },
{ label: "Chưa xác nhận", value: "false" },
];
const { control, handleSubmit, reset } = useForm<FormData>({
defaultValues: {
name: initialValue?.name || "",
level: initialValue?.level || 0,
confirmed:
initialValue?.confirmed !== undefined
? initialValue.confirmed.toString()
: "",
},
});
useEffect(() => {
if (initialValue) {
reset({
name: initialValue.name || "",
level: initialValue.level || 0,
confirmed:
initialValue.confirmed !== undefined
? initialValue.confirmed.toString()
: "",
});
}
}, [initialValue, reset]);
const onFormSubmit = (data: FormData) => {
const payload: {
name?: string;
level?: number;
confirmed?: boolean;
} = {
...(data.name && { name: data.name }),
...(data.level !== 0 && { level: data.level }),
...(data.confirmed !== "" && {
confirmed: data.confirmed === "true",
}),
};
onSubmit(payload);
};
const handleReset = () => {
reset({
name: "",
level: 0,
confirmed: undefined,
});
// Submit empty payload to reset filters
onSubmit({});
onReset?.();
};
return (
<ThemedView
style={[
styles.container,
{
backgroundColor: colors.background,
borderBottomColor: colors.border,
height: "auto",
},
]}
>
<View style={styles.content}>
{/* Search Input */}
<Controller
control={control}
name="name"
render={({ field: { onChange, onBlur, value } }) => (
<View style={styles.inputContainer}>
<ThemedText style={styles.label}>Tìm kiếm</ThemedText>
<View
style={[styles.inputWrapper, { borderColor: colors.border }]}
>
<TextInput
style={[styles.input, { color: colors.text }]}
placeholder="Tìm theo tên cảnh báo"
placeholderTextColor={colors.textSecondary}
value={value}
onChangeText={onChange}
onBlur={onBlur}
/>
{value ? (
<TouchableOpacity
onPress={() => onChange("")}
style={styles.clearButton}
>
<Ionicons
name="close-circle"
size={20}
color={colors.textSecondary}
/>
</TouchableOpacity>
) : null}
</View>
</View>
)}
/>
{/* Level and Confirmed Selects */}
<View style={styles.row}>
<View style={styles.halfWidth}>
<Controller
control={control}
name="level"
render={({ field: { onChange, value } }) => (
<View style={styles.selectContainer}>
<ThemedText style={styles.label}>Mức đ</ThemedText>
<Select
placeholder="Chọn mức độ"
value={value}
onChange={onChange}
options={levelOptions}
size="middle"
/>
</View>
)}
/>
</View>
<View style={styles.halfWidth}>
<Controller
control={control}
name="confirmed"
render={({ field: { onChange, value } }) => (
<View style={styles.selectContainer}>
<ThemedText style={styles.label}>Trạng thái</ThemedText>
<Select
placeholder="Chọn trạng thái"
value={value}
onChange={onChange}
options={confirmedOptions}
size="middle"
/>
</View>
)}
/>
</View>
</View>
{/* Action Buttons */}
<View style={styles.buttonRow}>
<TouchableOpacity
style={[
styles.button,
styles.secondaryButton,
{
backgroundColor: colors.backgroundSecondary,
borderColor: colors.border,
},
]}
onPress={handleReset}
>
<ThemedText style={[styles.buttonText, { color: colors.text }]}>
Đt lại
</ThemedText>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.button,
styles.primaryButton,
{ backgroundColor: colors.primary },
]}
onPress={handleSubmit(onFormSubmit)}
>
<ThemedText style={[styles.buttonText, { color: "#fff" }]}>
Tìm kiếm
</ThemedText>
</TouchableOpacity>
</View>
</View>
</ThemedView>
);
};
const styles = StyleSheet.create({
container: {
borderBottomWidth: 1,
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.1,
shadowRadius: 3.84,
elevation: 5,
zIndex: 100,
},
content: {
padding: 16,
overflow: "visible",
},
inputContainer: {
marginBottom: 16,
},
label: {
fontSize: 14,
fontWeight: "500",
marginBottom: 6,
},
inputWrapper: {
flexDirection: "row",
alignItems: "center",
borderWidth: 1,
borderRadius: 8,
paddingHorizontal: 12,
},
input: {
flex: 1,
height: 40,
fontSize: 16,
},
clearButton: {
marginLeft: 8,
padding: 4,
},
row: {
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 16,
zIndex: 10,
},
halfWidth: {
width: "48%",
zIndex: 5000,
},
selectContainer: {
// flex: 1, // Remove this to prevent taking full width
zIndex: 5000,
},
buttonRow: {
flexDirection: "row",
justifyContent: "space-between",
gap: 12,
marginTop: 16,
},
button: {
flex: 1,
height: 40,
borderRadius: 8,
justifyContent: "center",
alignItems: "center",
},
secondaryButton: {
borderWidth: 1,
},
primaryButton: {
// backgroundColor is set dynamically
},
buttonText: {
fontSize: 16,
fontWeight: "600",
},
});
export default AlarmSearchForm;