306 lines
7.6 KiB
TypeScript
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;
|