98 lines
2.8 KiB
TypeScript
98 lines
2.8 KiB
TypeScript
import React from 'react'
|
|
import { View } from 'react-native'
|
|
import { Image } from 'expo-image'
|
|
import Ionicons from '@expo/vector-icons/Ionicons'
|
|
import { MaterialIcons } from '@expo/vector-icons'
|
|
import tw from '../lib/tailwind'
|
|
import MyText from './text'
|
|
import MyTouchableOpacity from './touchable-opacity'
|
|
import usePickImage from './use-pick-image'
|
|
|
|
export interface ImageUploaderNeoItem {
|
|
imgUrl: string
|
|
mimeType: string | null
|
|
}
|
|
|
|
export interface ImageUploaderNeoPayload {
|
|
url: string
|
|
mimeType: string | null
|
|
}
|
|
|
|
interface ImageUploaderNeoProps {
|
|
images: ImageUploaderNeoItem[]
|
|
onImageAdd: (images: ImageUploaderNeoPayload[]) => void
|
|
onImageRemove: (image: ImageUploaderNeoPayload) => void
|
|
allowMultiple?: boolean
|
|
}
|
|
|
|
const ImageUploaderNeo: React.FC<ImageUploaderNeoProps> = ({
|
|
images,
|
|
onImageAdd,
|
|
onImageRemove,
|
|
allowMultiple = true,
|
|
}) => {
|
|
const totalImageCount = images.length
|
|
|
|
const handleAddImages = (files: any) => {
|
|
if (!files) return
|
|
|
|
const assets = Array.isArray(files) ? files : [files]
|
|
const payload = assets.map((asset) => ({
|
|
url: asset.uri,
|
|
mimeType: asset.mimeType ?? null,
|
|
}))
|
|
|
|
onImageAdd(payload)
|
|
}
|
|
|
|
const handlePickImage = usePickImage({
|
|
setFile: handleAddImages,
|
|
multiple: allowMultiple,
|
|
})
|
|
|
|
// console.log({images})
|
|
return (
|
|
<View style={tw`mb-4`}>
|
|
<View style={tw`flex-row flex-wrap -mx-1`}>
|
|
{images.map((image, index) => (
|
|
<View key={`neo-${index}`} style={tw`w-1/3 px-1 mb-2 relative`}>
|
|
<Image
|
|
source={{ uri: image.imgUrl }}
|
|
style={tw`w-full aspect-square rounded`}
|
|
/>
|
|
<MyTouchableOpacity
|
|
onPress={() =>
|
|
onImageRemove({
|
|
url: image.imgUrl,
|
|
mimeType: image.mimeType ?? null,
|
|
})
|
|
}
|
|
style={tw`absolute top-0 right-0 bg-red-500 rounded-full p-1`}
|
|
>
|
|
<Ionicons name='close' size={16} color='white' />
|
|
</MyTouchableOpacity>
|
|
</View>
|
|
))}
|
|
<MyTouchableOpacity
|
|
disabled={!allowMultiple && totalImageCount >= 1}
|
|
onPress={handlePickImage}
|
|
style={tw`w-1/3 px-1 mb-2`}
|
|
>
|
|
<View style={tw`w-full aspect-square bg-gray-200 rounded justify-center items-center opacity-75`}>
|
|
{!allowMultiple && totalImageCount >= 1 ? (
|
|
<View style={tw`absolute inset-0 bg-white/70 rounded justify-center items-center`}>
|
|
<MyText style={tw`text-center text-gray-500`}>
|
|
Only one image allowed
|
|
</MyText>
|
|
</View>
|
|
) : (
|
|
<MaterialIcons name='add' size={32} color='black' />
|
|
)}
|
|
</View>
|
|
</MyTouchableOpacity>
|
|
</View>
|
|
</View>
|
|
)
|
|
}
|
|
|
|
export default ImageUploaderNeo
|