Untitled
unknown
typescript
a year ago
3.8 kB
5
Indexable
import {
Dispatch,
SetStateAction,
useEffect,
useMemo,
useRef,
useState,
} from "react"
import { Roster } from "@/src/constants/Types"
import { Button } from "react-native-paper"
import {
View,
Text,
FlatList,
TouchableOpacity,
StyleSheet,
Animated,
} from "react-native"
import dayjs from "dayjs"
import utc from "dayjs/plugin/utc"
import timezone from "dayjs/plugin/timezone"
import updateLocale from "dayjs/plugin/updateLocale"
dayjs.extend(utc)
dayjs.extend(timezone)
dayjs.extend(updateLocale)
dayjs.updateLocale("en", { weekStart: 1 })
export default function RosterPicker({
rosters,
currentRoster,
setCurrentRoster,
}: {
rosters: Roster[]
currentRoster: Roster | null
setCurrentRoster: Dispatch<SetStateAction<Roster | null>>
}) {
const [isOpen, setIsOpen] = useState(false)
const heightAnim = useRef(new Animated.Value(0)).current
const toggleVisible = () => {
setIsOpen(!isOpen)
}
const onItemPress = (roster: Roster) => {
setCurrentRoster(roster)
toggleVisible()
}
useEffect(() => {
Animated.timing(heightAnim, {
toValue: isOpen ? 175: 0,
duration: 200,
useNativeDriver: false,
}).start()
}, [heightAnim, isOpen])
const RenderItem = ({ item }: { item: Roster }) => {
const isSelected = item.id === currentRoster?.id
const backgroundColor = useMemo(
() => (isSelected ? "#9f9f9f" : "#f9f9f9"),
[isSelected]
)
const textColor = useMemo(
() => (isSelected ? "white" : "black"),
[isSelected]
)
return (
<Item
item={item}
onPress={() => onItemPress(item)}
backgroundColor={backgroundColor}
textColor={textColor}
/>
)
}
return (
<View style={styles.container}>
<Button
mode="contained"
onPress={toggleVisible}
style={styles.button}
contentStyle={styles.buttonContent}
labelStyle={styles.buttonLabel}
icon={isOpen ? "chevron-up" : "chevron-down"}
>
{formatRosterText(currentRoster)}
</Button>
<View style={styles.dropdownContainer}>
<Animated.View
style={[
styles.animatedView,
{
height: heightAnim,
},
]}
>
<View style={styles.listContainer}>
<FlatList
data={rosters}
renderItem={({ item }) => (
<RenderItem item={item} />
)}
keyExtractor={(item) => item.id.toString()}
extraData={currentRoster?.id}
/>
</View>
</Animated.View>
</View>
</View>
)
}
const styles = StyleSheet.create({
container: {
width: "auto",
alignSelf: "flex-end",
padding: 3,
zIndex: 10,
},
dropdownContainer: {
position: "relative",
},
animatedView: {
position: "absolute",
overflow: "hidden",
marginTop: 1,
width: "100%",
},
listContainer: {
padding: 4,
backgroundColor: "white",
borderRadius: 8,
borderWidth: 1,
borderColor: "#ccc",
elevation: 2, // Android shadow
shadowColor: "#000", // iOS shadow
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 4,
},
button: {
backgroundColor: "#aaa",
borderRadius: 8,
},
buttonContent: {
gap: 4,
flexDirection: "row-reverse",
padding: 4,
},
buttonLabel: {
color: "rgba(0, 0, 0, 0.88)",
},
})
type ItemProps = {
item: Roster
onPress: () => void
backgroundColor: string
textColor: string
}
const Item = ({ item, onPress, backgroundColor, textColor }: ItemProps) => (
<TouchableOpacity
onPress={onPress}
style={{
padding: 10,
marginVertical: 4,
marginLeft: 4,
marginRight: 8,
backgroundColor,
}}
>
<Text
style={{
color: textColor,
}}
>
{formatRosterText(item)}
</Text>
</TouchableOpacity>
)
const formatRosterText = (roster: Roster | null) => {
if (!roster) return "No rosters"
const start = roster.start.format("D MMM")
const end = roster.end.format("D MMM")
return start + " - " + end
}
Editor is loading...
Leave a Comment