BaaS_Driver_Android_App/components/service/IssueSelectorModal.tsx

316 lines
7.9 KiB
TypeScript

import React, { useCallback, useEffect, useState } from "react";
import {
View,
Text,
TextInput,
ScrollView,
TouchableOpacity,
Modal,
StyleSheet,
} from "react-native";
import Checkbox from "expo-checkbox";
import { issueConfig } from "@/constants/config";
import CloseIcon from "@/assets/icons/close.svg";
import { getLanguage } from "@/services/i18n";
import { useFocusEffect } from "expo-router";
interface Issue {
id: number;
name: {
en: String;
hi: String;
};
}
interface IssueSelectorModalProps {
visible: boolean;
onClose: () => void;
onSelect: (selectedValues: number[]) => void;
initialSelectedValues?: number[]; // Previously saved selections
issues: Issue[];
}
export default function IssueSelectorModal({
visible,
onClose,
onSelect,
initialSelectedValues = [],
issues = [],
}: IssueSelectorModalProps) {
const [selectedValues, setSelectedValues] = useState<number[]>(
initialSelectedValues
);
const [search, setSearch] = useState("");
const [lang, setLang] = useState<"en" | "hi">("en");
const toggleValue = (id: number) => {
setSelectedValues((prev) =>
prev.includes(id) ? prev.filter((v) => v !== id) : [...prev, id]
);
};
const filteredIssues = issues.filter((issue) =>
issue.name[lang].toLowerCase().includes(search.toLowerCase().trim())
);
const clearSelection = () => setSelectedValues([]);
const hasSelection = selectedValues.length > 0;
const handleSelect = () => {
if (hasSelection) {
onSelect(selectedValues);
onClose();
}
};
const handleClose = () => {
// Reset to initial values when closing without saving
setSelectedValues(initialSelectedValues);
setSearch(""); // Also clear search
onClose();
};
// Reset selectedValues when modal becomes visible with new initial values
React.useEffect(() => {
if (visible) {
setSelectedValues(initialSelectedValues);
setSearch("");
}
}, [visible, initialSelectedValues]);
useFocusEffect(
useCallback(() => {
const fetchLang = async () => {
const selectedLang = await getLanguage();
setLang((selectedLang as "en") || "hi");
};
fetchLang();
}, []) // dependencies, can include anything that triggers refetch
);
return (
<Modal visible={visible} animationType="slide">
<View style={styles.container}>
{/* Header */}
<View style={styles.headerBar}>
<Text>Select Issue</Text>
<TouchableOpacity onPress={handleClose}>
<CloseIcon />
</TouchableOpacity>
</View>
<View style={styles.divider}></View>
<View style={styles.header}>
<TextInput
placeholder="Search"
placeholderTextColor="#939DAE"
value={search}
onChangeText={setSearch}
style={styles.searchBar}
/>
</View>
<View style={styles.counterBar}>
<Text
style={styles.counterText}
>{`${selectedValues.length}/${issues.length} Selected`}</Text>
<TouchableOpacity onPress={clearSelection} disabled={!hasSelection}>
<Text
style={[
styles.clearText,
!hasSelection && styles.clearTextDisabled,
selectedValues.length > 0 && { color: "#006C4D" },
]}
>
Clear
</Text>
</TouchableOpacity>
</View>
<ScrollView style={styles.scrollArea}>
{filteredIssues.length > 0 ? (
filteredIssues.map((issue) => (
<TouchableOpacity
key={issue.id}
style={styles.itemRow}
onPress={() => toggleValue(issue.id)}
>
<Checkbox
value={selectedValues.includes(issue.id)}
onValueChange={() => toggleValue(issue.id)}
color={
selectedValues.includes(issue.id) ? "#009E71" : undefined
}
/>
<Text style={styles.itemLabel}>{issue.name[lang]}</Text>
</TouchableOpacity>
))
) : issues.length === 0 ? (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>No issues available</Text>
</View>
) : (
<View style={styles.emptyContainer}>
<Text style={styles.emptyText}>
No issues found for "{search}"
</Text>
</View>
)}
</ScrollView>
<View style={styles.buttonsContainer}>
<TouchableOpacity style={styles.cancelButton} onPress={onClose}>
<Text style={styles.cancelText}>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.doneButton,
!hasSelection && styles.doneButtonDisabled,
]}
onPress={handleSelect}
disabled={!hasSelection}
>
<Text
style={[
styles.doneText,
!hasSelection && styles.doneTextDisabled,
]}
>
Select
</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
);
}
const styles = StyleSheet.create({
emptyContainer: {
padding: 20,
alignItems: "center",
justifyContent: "center",
},
emptyText: {
fontSize: 16,
color: "#717B8F",
textAlign: "center",
},
buttonsContainer: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 16,
paddingVertical: 20,
backgroundColor: "#FCFCFC",
height: 80,
borderTopWidth: 1,
borderTopColor: "#E5E9F0",
},
headerBar: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingHorizontal: 16,
paddingVertical: 12,
backgroundColor: "#F9F9F9",
},
cancelButton: {
flex: 1,
height: 40,
borderWidth: 1,
borderColor: "#D8DDE7",
backgroundColor: "#F3F5F8",
borderRadius: 4,
justifyContent: "center",
alignItems: "center",
marginRight: 8,
},
doneButton: {
flex: 1,
height: 40,
borderRadius: 4,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#00875F", // primary green
marginLeft: 8,
},
doneButtonDisabled: {
backgroundColor: "#E5E9F0", // disabled gray background
},
doneText: {
fontSize: 14,
fontWeight: "600",
color: "#FFFFFF",
},
doneTextDisabled: {
color: "#ADB4BD", // disabled gray text
},
cancelText: {
fontSize: 14,
fontWeight: "600",
color: "#252A34",
},
clearText: {
fontSize: 14,
color: "#ADB4BD",
},
clearTextDisabled: {
color: "#D8DDE7", // more muted when disabled
},
container: { flex: 1, backgroundColor: "#fff" },
header: {
paddingHorizontal: 16,
paddingVertical: 12,
backgroundColor: "#FCFCFC",
},
searchBar: {
backgroundColor: "#fff",
borderColor: "#D8DDE6",
borderWidth: 1,
borderRadius: 4,
paddingHorizontal: 12,
height: 36,
fontSize: 14,
color: "#252A34",
},
counterBar: {
flexDirection: "row",
justifyContent: "space-between",
paddingHorizontal: 20,
paddingVertical: 12,
backgroundColor: "#FCFCFC",
},
divider: {
height: 1,
backgroundColor: "#E5E9F0",
},
counterText: {
fontSize: 14,
color: "#555",
fontWeight: "600",
},
scrollArea: { paddingHorizontal: 0, backgroundColor: "#FCFCFC" },
category: {
fontSize: 14,
color: "#252A34",
paddingVertical: 12,
paddingHorizontal: 16,
backgroundColor: "#F9F9F9",
},
itemRow: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 8,
paddingHorizontal: 16,
backgroundColor: "#FCFCFC",
},
itemLabel: {
marginLeft: 12,
fontSize: 12,
color: "#252A34",
},
});