Hồng Phúc

54 bundles
1 file4 months ago
1

import React, {useState} from 'react';

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
import React, {useState} from 'react'; import {View, StyleSheet, Platform, StyleProp} from 'react-native'; import {StackNavigationProp} from '@react-navigation/stack'; import {Formik} from 'formik'; import * as Yup from 'yup'; import { getUploadUri, getUploadFileName, uploadImage, getDownloadUrl, addProduct, } from '../../utils'; //@ts-ignore import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scrollview'; import {Layout, Button} from '@ui-kitten/components'; import NumberFormat from 'react-number-format'; import { ImageLibraryOptions, ImagePickerResponse, launchImageLibrary, } from 'react-native-image-picker'; import Input, {ErrorText} from '../../pureComponent/Input'; import commonStyles from '../../theme/commonStyles'; import PreviewImage from '../../pureComponent/PreviewImage/PreviewImage'; import {ImageStyle} from 'react-native-fast-image'; const stringSchema = Yup.string() .min(2, 'Too Short!') .max(50, 'Too Long!') .required('This field is required'); const FormProductSchema = Yup.object().shape({ brandName: stringSchema, productName: stringSchema, productDescription: stringSchema, productPrice: Yup.string().required('This field is required'), thumbnails: Yup.array() .of(Yup.string()) .length(1, 'Thumbnails must be have at least 1 items'), }); const MAX_UPLOAD_IMAGE = 6; type FormProductModalNavigationProp = StackNavigationProp<any>; type Props = { navigation: FormProductModalNavigationProp; }; const FormProductModal: React.FC<Props> = ({navigation}) => { const [uploading, setUploading] = useState(false); const [uploadingIndex, setUploadingIndex] = useState(0); const [thumbnails, setThumbnails] = useState<ImagePickerResponse[]>( [] as ImagePickerResponse[], ); return ( <Layout style={StyleSheet.flatten([commonStyles.fullScreen, commonStyles.p3])}> <Formik initialValues={{ brandName: '', productName: '', productDescription: '', productPrice: '', thumbnails: [], }} validationSchema={FormProductSchema} onSubmit={async (values) => { await addProduct({ id: '', brandName: values.brandName, productName: values.productName, productDescription: values.productDescription, productPrice: values.productPrice.replace('.', ''), productImage: { landscape: '', portrait: '', thumbnails: values.thumbnails, }, }); navigation.goBack(); }}> {({ values, errors, touched, isSubmitting, handleChange, handleBlur, handleSubmit, setFieldValue, setFieldError, }) => { const handleUploadImage = () => { launchImageLibrary( { mediaType: 'photo', includeBase64: false, } as ImageLibraryOptions, async (response: ImagePickerResponse) => { const uri = response.uri; if (uri) { const updatedThumbnails = [...thumbnails, response]; setFieldError('thumbnails', undefined); setThumbnails(updatedThumbnails); setUploadingIndex(updatedThumbnails.length - 1); setUploading(true); const fileName = getUploadFileName(uri); const uploadUri = getUploadUri(uri, Platform.OS); try { const task = uploadImage(fileName, uploadUri); await task; const downloadUrl = await getDownloadUrl(fileName); setFieldValue('thumbnails', [ ...values.thumbnails, downloadUrl, ]); } catch (error) { // @TODO: Show a toast message console.log(error); } finally { setUploading(false); } } }, ); }; return ( <View style={commonStyles.fullScreen}> <KeyboardAwareScrollView> <Input style={commonStyles.mt3} status={ errors.brandName && touched.brandName ? 'danger' : 'primary' } errorMessage={errors.brandName} showError={!!errors.brandName && touched.brandName} label="Brand Name" placeholder="Ex: Luis Vuiton" value={values.brandName} onBlur={handleBlur('brandName')} onChangeText={handleChange('brandName')} /> <Input style={commonStyles.mt3} status={ errors.productName && touched.productName ? 'danger' : 'primary' } errorMessage={errors.productName} showError={ errors.productName && touched.productName ? true : false } label="Product Name" placeholder="Ex: Dior Sauvage" value={values.productName} onBlur={handleBlur('productName')} onChangeText={handleChange('productName')} /> <Input style={commonStyles.mt3} status={ errors.productDescription && touched.productDescription ? 'danger' : 'primary' } errorMessage={errors.productDescription} showError={ errors.productDescription && touched.productDescription ? true : false } multiline={true} textStyle={styles.multilineInput} label="Product Description" placeholder="Enter description about the product" value={values.productDescription} onBlur={handleBlur('productDescription')} onChangeText={handleChange('productDescription')} /> <NumberFormat value={values.productPrice} thousandSeparator={'.'} decimalSeparator={','} displayType={'text'} renderText={(value) => ( <Input style={commonStyles.mt3} status={ errors.productPrice && touched.productPrice ? 'danger' : 'primary' } errorMessage={errors.productPrice} showError={ errors.productPrice && touched.productPrice ? true : false } label="Product Price" placeholder="Ex: 20000" keyboardType={'number-pad'} value={value} onBlur={handleBlur('productPrice')} onChangeText={handleChange('productPrice')} /> )} /> <View> <View style={StyleSheet.flatten([ commonStyles.flexWrap, commonStyles.row, commonStyles.alignItemsCenter, commonStyles.p2, commonStyles.mt3, styles.previewImageContainer, errors.thumbnails && touched.thumbnails ? {borderColor: '#B00020'} : {borderColor: '#3366ff'}, ])}> {thumbnails.map((item, index) => { const previewImageStyle: StyleProp<ImageStyle> = { aspectRatio: item.width && item.height ? item.width / item.height : 1 / 1, width: 100, }; return ( <PreviewImage containerStyle={styles.previewImage} imageStyle={previewImageStyle} loading={uploading && uploadingIndex === index} key={item.uri} source={{uri: item.uri}} /> ); })} <Button style={styles.buttonUpload} disabled={ thumbnails.length === MAX_UPLOAD_IMAGE || uploading || isSubmitting } onPress={handleUploadImage}> {'Upload Image'} </Button> </View> {errors.thumbnails && touched.thumbnails && ( <ErrorText errorMessage={errors.thumbnails.toString()} /> )} </View> <Button style={commonStyles.mt3} disabled={uploading || isSubmitting} onPress={handleSubmit}> {'Save'} </Button> </KeyboardAwareScrollView> </View> ); }} </Formik> </Layout> ); }; const styles = StyleSheet.create({ multilineInput: { minHeight: 64, textAlignVertical: 'top', paddingTop: 0, paddingBottom: 0, }, previewImage: { borderWidth: 1, borderStyle: 'solid', borderColor: '#3366ff', marginHorizontal: 6, }, previewImageContainer: { borderWidth: 1, borderStyle: 'solid', marginTop: 8, }, buttonUpload: { width: 110, height: 110, }, }); export default FormProductModal;