xtablo-source/xtablo-expo/components/tasks/AssigneePicker.tsx

140 lines
3.8 KiB
TypeScript

import React from "react";
import {
View,
Text,
TouchableOpacity,
Modal,
FlatList,
StyleSheet,
} from "react-native";
import { X, Check } from "lucide-react-native";
import { useThemeColor } from "@/hooks/useThemeColor";
import { useColorScheme } from "@/hooks/useColorScheme";
import { TabloMember } from "@/hooks/members";
type AssigneePickerProps = {
visible: boolean;
onClose: () => void;
members: TabloMember[];
selectedId: string | null;
onSelect: (memberId: string | null) => void;
};
export default function AssigneePicker({
visible,
onClose,
members,
selectedId,
onSelect,
}: AssigneePickerProps) {
const colorScheme = useColorScheme();
const isDark = colorScheme === "dark";
const bgColor = useThemeColor({ light: "#ffffff", dark: "#1f2937" }, "background");
const textColor = useThemeColor({ light: "#1f2937", dark: "#f9fafb" }, "text");
const subtextColor = useThemeColor({ light: "#6b7280", dark: "#9ca3af" }, "text");
const borderColor = isDark ? "#374151" : "#e5e7eb";
const handleSelect = (id: string | null) => {
onSelect(id);
onClose();
};
return (
<Modal visible={visible} animationType="slide" transparent onRequestClose={onClose}>
<View style={styles.overlay}>
<View style={[styles.sheet, { backgroundColor: bgColor }]}>
<View style={[styles.header, { borderBottomColor: borderColor }]}>
<Text style={[styles.title, { color: textColor }]}>Assigné à</Text>
<TouchableOpacity onPress={onClose}>
<X size={22} color={textColor} />
</TouchableOpacity>
</View>
<TouchableOpacity
style={[styles.row, { borderBottomColor: borderColor }]}
onPress={() => handleSelect(null)}
>
<View style={[styles.avatar, styles.avatarEmpty]} />
<Text style={[styles.name, { color: subtextColor }]}>Non assigné</Text>
{selectedId === null && <Check size={18} color="#3b82f6" />}
</TouchableOpacity>
<FlatList
data={members}
keyExtractor={(item) => item.id}
renderItem={({ item }) => (
<TouchableOpacity
style={[styles.row, { borderBottomColor: borderColor }]}
onPress={() => handleSelect(item.id)}
>
<View style={styles.avatar}>
<Text style={styles.avatarText}>
{item.name.charAt(0).toUpperCase()}
</Text>
</View>
<Text style={[styles.name, { color: textColor }]}>{item.name}</Text>
{selectedId === item.id && <Check size={18} color="#3b82f6" />}
</TouchableOpacity>
)}
/>
</View>
</View>
</Modal>
);
}
const styles = StyleSheet.create({
overlay: {
flex: 1,
justifyContent: "flex-end",
backgroundColor: "rgba(0,0,0,0.4)",
},
sheet: {
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
maxHeight: "60%",
paddingBottom: 34,
},
header: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
padding: 16,
borderBottomWidth: StyleSheet.hairlineWidth,
},
title: {
fontSize: 17,
fontWeight: "700",
},
row: {
flexDirection: "row",
alignItems: "center",
paddingVertical: 12,
paddingHorizontal: 16,
borderBottomWidth: StyleSheet.hairlineWidth,
gap: 12,
},
avatar: {
width: 32,
height: 32,
borderRadius: 16,
backgroundColor: "#3b82f6",
alignItems: "center",
justifyContent: "center",
},
avatarEmpty: {
backgroundColor: "transparent",
borderWidth: 1.5,
borderColor: "#d1d5db",
borderStyle: "dashed",
},
avatarText: {
color: "#ffffff",
fontSize: 14,
fontWeight: "600",
},
name: {
flex: 1,
fontSize: 15,
},
});