1
1
mirror of https://github.com/theoludwig/p61-project.git synced 2024-07-17 07:00:12 +02:00
p61-project/presentation/react/components/HabitCreateForm/HabitIconSelectorModal.tsx
2024-04-11 15:26:20 +02:00

151 lines
4.1 KiB
TypeScript

import React, { useState, useEffect } from "react"
import {
Modal,
IconButton,
Portal,
List,
Button,
TextInput,
Text,
} from "react-native-paper"
import { ScrollView, View, StyleSheet } from "react-native"
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome"
import type {
IconDefinition,
IconName,
} from "@fortawesome/fontawesome-svg-core"
import { library, findIconDefinition } from "@fortawesome/fontawesome-svg-core"
import { fas } from "@fortawesome/free-solid-svg-icons"
export interface HabitIconSelectorModalProps {
visible?: boolean
value: string
onDismiss: () => void
onSelect: (icon: string) => void
onPress: () => void
}
export const HabitIconSelectorModal: React.FC<HabitIconSelectorModalProps> = ({
visible = false,
value,
onDismiss,
onSelect,
onPress,
}) => {
const [selectedIcon, setSelectedIcon] = useState<string>()
const [possibleIcons, setPossibleIcons] = useState<IconDefinition[]>([])
const [searchText, setSearchText] = useState<string>(value)
useEffect(() => {
setPossibleIcons(findIconsInLibrary(searchText))
}, [searchText])
library.add(fas)
const handleIconSelect = (icon: string): void => {
setSelectedIcon(icon)
onSelect(icon)
}
const findIconsInLibrary = (icon: string): IconDefinition[] => {
const iconNames = Object.keys(fas).map((key) => {
return fas[key]?.iconName ?? ""
})
const matchedValue: string[] = iconNames.filter((name) => {
return name.includes(icon)
})
return matchedValue.length > 0
? matchedValue.map((name) => {
return findIconDefinition({
prefix: "fas",
iconName: name as IconName,
})
})
: []
}
return (
<>
<Button onPress={onPress}>Click to open icon list</Button>
<Modal
visible={visible}
onDismiss={onDismiss}
contentContainerStyle={styles.modalContent}
>
<Portal>
<View>
<ScrollView style={styles.scrollView}>
<List.Section title="Select an icon">
<View style={styles.iconContainer}>
<TextInput
label="Search"
value={searchText}
onChangeText={(text) => {
return setSearchText(text)
}}
/>
{possibleIcons.length > 0 ? (
<View>
{possibleIcons.map((icon) => {
return (
<IconButton
key={icon.iconName}
containerColor="white"
icon={({ size }) => {
return (
<FontAwesomeIcon
icon={icon}
size={size}
color={
selectedIcon === icon.iconName
? "blue"
: "black"
}
/>
)
}}
size={30}
onPress={() => {
handleIconSelect(icon.iconName)
}}
/>
)
})}
</View>
) : (
<View style={styles.noResults}>
<Text>No results found</Text>
</View>
)}
</View>
</List.Section>
</ScrollView>
</View>
</Portal>
</Modal>
</>
)
}
const styles = StyleSheet.create({
modalContent: {
backgroundColor: "white",
padding: 20,
margin: 20,
borderRadius: 10,
},
iconContainer: {
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "space-between",
},
scrollView: {
maxHeight: 10000,
maxWidth: 5000,
},
noResults: {
marginTop: 20,
alignItems: "center",
},
})