184 lines
5.0 KiB
TypeScript
184 lines
5.0 KiB
TypeScript
import React, { useState } from "react";
|
|
import {
|
|
View,
|
|
Text,
|
|
TouchableOpacity,
|
|
StyleSheet,
|
|
Modal,
|
|
Platform,
|
|
ScrollView,
|
|
} from "react-native";
|
|
import { Ionicons } from "@expo/vector-icons";
|
|
import { TripStatus } from "./types";
|
|
import { useI18n } from "@/hooks/use-i18n";
|
|
import { useThemeContext } from "@/hooks/use-theme-context";
|
|
|
|
interface StatusDropdownProps {
|
|
value: TripStatus | null;
|
|
onChange: (value: TripStatus | null) => void;
|
|
}
|
|
|
|
export default function StatusDropdown({
|
|
value,
|
|
onChange,
|
|
}: StatusDropdownProps) {
|
|
const { t } = useI18n();
|
|
const { colors } = useThemeContext();
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
const STATUS_OPTIONS: Array<{ value: TripStatus | null; label: string }> = [
|
|
{ value: null, label: t("diary.statusDropdown.placeholder") },
|
|
{ value: 0, label: t("diary.statusDropdown.created") },
|
|
{ value: 1, label: t("diary.statusDropdown.pending") },
|
|
{ value: 2, label: t("diary.statusDropdown.approved") },
|
|
{ value: 3, label: t("diary.statusDropdown.active") },
|
|
{ value: 4, label: t("diary.statusDropdown.completed") },
|
|
{ value: 5, label: t("diary.statusDropdown.cancelled") },
|
|
];
|
|
|
|
const selectedLabel =
|
|
STATUS_OPTIONS.find((opt) => opt.value === value)?.label || t("diary.statusDropdown.placeholder");
|
|
|
|
const handleSelect = (status: TripStatus | null) => {
|
|
onChange(status);
|
|
setIsOpen(false);
|
|
};
|
|
|
|
const themedStyles = {
|
|
label: { color: colors.text },
|
|
selector: { backgroundColor: colors.card, borderColor: colors.border },
|
|
selectorText: { color: colors.text },
|
|
placeholder: { color: colors.textSecondary },
|
|
modalContent: { backgroundColor: colors.card },
|
|
option: { borderBottomColor: colors.separator },
|
|
selectedOption: { backgroundColor: colors.backgroundSecondary },
|
|
optionText: { color: colors.text },
|
|
};
|
|
|
|
return (
|
|
<View style={styles.container}>
|
|
<Text style={[styles.label, themedStyles.label]}>{t("diary.statusDropdown.label")}</Text>
|
|
<TouchableOpacity
|
|
style={[styles.selector, themedStyles.selector]}
|
|
onPress={() => setIsOpen(true)}
|
|
activeOpacity={0.7}
|
|
>
|
|
<Text style={[styles.selectorText, themedStyles.selectorText, !value && themedStyles.placeholder]}>
|
|
{selectedLabel}
|
|
</Text>
|
|
<Ionicons name="ellipsis-horizontal" size={20} color={colors.textSecondary} />
|
|
</TouchableOpacity>
|
|
|
|
<Modal
|
|
visible={isOpen}
|
|
transparent
|
|
animationType="fade"
|
|
onRequestClose={() => setIsOpen(false)}
|
|
>
|
|
<TouchableOpacity
|
|
style={styles.modalOverlay}
|
|
activeOpacity={1}
|
|
onPress={() => setIsOpen(false)}
|
|
>
|
|
<View style={[styles.modalContent, themedStyles.modalContent]}>
|
|
<ScrollView>
|
|
{STATUS_OPTIONS.map((option, index) => (
|
|
<TouchableOpacity
|
|
key={index}
|
|
style={[
|
|
styles.option,
|
|
themedStyles.option,
|
|
value === option.value && themedStyles.selectedOption,
|
|
]}
|
|
onPress={() => handleSelect(option.value)}
|
|
>
|
|
<Text
|
|
style={[
|
|
styles.optionText,
|
|
themedStyles.optionText,
|
|
]}
|
|
>
|
|
{option.label}
|
|
</Text>
|
|
{value === option.value && (
|
|
<Ionicons name="checkmark" size={20} color={colors.primary} />
|
|
)}
|
|
</TouchableOpacity>
|
|
))}
|
|
</ScrollView>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</Modal>
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
marginBottom: 20,
|
|
},
|
|
label: {
|
|
fontSize: 16,
|
|
fontWeight: "600",
|
|
marginBottom: 8,
|
|
fontFamily: Platform.select({
|
|
ios: "System",
|
|
android: "Roboto",
|
|
default: "System",
|
|
}),
|
|
},
|
|
selector: {
|
|
flexDirection: "row",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
borderWidth: 1,
|
|
borderRadius: 8,
|
|
paddingHorizontal: 16,
|
|
paddingVertical: 12,
|
|
},
|
|
selectorText: {
|
|
fontSize: 16,
|
|
fontFamily: Platform.select({
|
|
ios: "System",
|
|
android: "Roboto",
|
|
default: "System",
|
|
}),
|
|
},
|
|
modalOverlay: {
|
|
flex: 1,
|
|
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
},
|
|
modalContent: {
|
|
borderRadius: 12,
|
|
width: "80%",
|
|
maxHeight: "60%",
|
|
overflow: "hidden",
|
|
shadowColor: "#000",
|
|
shadowOffset: {
|
|
width: 0,
|
|
height: 4,
|
|
},
|
|
shadowOpacity: 0.3,
|
|
shadowRadius: 8,
|
|
elevation: 8,
|
|
},
|
|
option: {
|
|
flexDirection: "row",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
paddingHorizontal: 20,
|
|
paddingVertical: 16,
|
|
borderBottomWidth: 1,
|
|
},
|
|
optionText: {
|
|
fontSize: 16,
|
|
fontFamily: Platform.select({
|
|
ios: "System",
|
|
android: "Roboto",
|
|
default: "System",
|
|
}),
|
|
},
|
|
});
|