diff --git a/src/assets/selectedRadio.png b/src/assets/selectedRadio.png index 4d95acb..e653cad 100644 Binary files a/src/assets/selectedRadio.png and b/src/assets/selectedRadio.png differ diff --git a/src/assets/unselectedRadio.png b/src/assets/unselectedRadio.png index 1af21c4..1f0cf9c 100644 Binary files a/src/assets/unselectedRadio.png and b/src/assets/unselectedRadio.png differ diff --git a/src/components/DatePicker.js b/src/components/DatePicker.js index ab6940c..37a7945 100644 --- a/src/components/DatePicker.js +++ b/src/components/DatePicker.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { View, StyleSheet, Text } from 'react-native'; import ReactDatePicker from 'react-native-datepicker'; +const DEFAULT_DATETIME_FORMAT = 'YYYY-MM-DD h:mm a'; const DEFAULT_DATE_FORMAT = 'YYYY-MM-DD'; const CONFIRM_BUTTON_TEXT = 'Confirm'; const CANCEL_BUTTON_TEXT = 'Cancel'; @@ -19,11 +20,12 @@ export default function Datepicker(props) { key={name} style={styles.date} date={value} - mode="date" - format={DEFAULT_DATE_FORMAT} + mode={meta.isDateTime ? "datetime" : "date"} + format={meta.isDateTime ? DEFAULT_DATETIME_FORMAT : DEFAULT_DATE_FORMAT} confirmBtnText={CONFIRM_BUTTON_TEXT} cancelBtnText={CANCEL_BUTTON_TEXT} onDateChange={onChangeInputValue} + disabled={meta.disabled === true ? true : false} /> ); diff --git a/src/components/InputText.js b/src/components/InputText.js index c5fbe3d..fa6ec69 100644 --- a/src/components/InputText.js +++ b/src/components/InputText.js @@ -7,19 +7,27 @@ import { color } from '../styles'; export default function InputText(props) { const { - name, value, meta, style, onChangeInputValue, isMandatory + name, value, meta, style, onChangeInputValue, isMandatory, imgView, inputStyle } = props; return ( - - {`${meta.label} ${isMandatory ? '*' : ''}`} + + {imgView ? + + {imgView()} + + {`${meta.label} ${isMandatory ? '*' : ''}`} + + : + {`${meta.label} ${isMandatory ? '*' : ''}`} + } () => onChangeInputValue(value); return ( - - {`${meta.text} ${isMandatory ? '*' : ''}`} + + {`${meta.text} ${isMandatory ? '*' : ''}`} + + + {meta.data.map((item, index) => ( - + + - {item.label} + {item.label} ))} + ); } @@ -66,7 +78,7 @@ const styles = StyleSheet.create({ }, radioContainer: { paddingVertical: 10, - width: '100%', + width: 'auto', height: 40, paddingLeft: 10, } diff --git a/src/components/Rating.js b/src/components/Rating.js index 84af052..3f782ad 100644 --- a/src/components/Rating.js +++ b/src/components/Rating.js @@ -7,18 +7,19 @@ import { export default function Rating(props) { const { - name, meta, style, onChangeInputValue, isMandatory + name, meta, style, value = 0, onChangeInputValue, isMandatory } = props; const recordRating = rating => onChangeInputValue(rating); return ( - + {`${meta.label} ${isMandatory ? '*' : ''}`} diff --git a/src/index.js b/src/index.js index 7ea8e21..f85dcec 100644 --- a/src/index.js +++ b/src/index.js @@ -1,132 +1,347 @@ import React, { useEffect, useState } from 'react'; import { - View, StyleSheet + View, StyleSheet, + ScrollView, + Dimensions, } from 'react-native'; import PropTypes from 'prop-types'; import { Button } from 'react-native-elements'; import { componentName, skipValidationForFields } from './constant'; import { getComponent, getValidator } from './componentMap'; -export default function DynamicForm({ formTemplate, onSubmit, buttonStyles }) { - const [formFields, setFormFields] = useState({}); - const [isValidFormFields, setValid] = useState(false); - const mandatoryFields = formTemplate.data.filter(data => data.is_mandatory); - - useEffect(() => { - formTemplate.data.sort((a, b) => a.index - b.index); - setFormFields({ - ...formFields, - ...setDefaultForFields() - }); - }, []); - - useEffect(() => { - const isValid = checkAllMandatoryFields(); - setValid(isValid); - }, [JSON.stringify(formFields)]); - - const onChangeInputValue = (fieldName, inputType) => value => { - setFormFields({ - ...formFields, - [fieldName]: { - ...formFields[fieldName] || {}, - value, - inputType, - } - }); + +const { width: deviceWidth, height: deviceHeight } = Dimensions.get('window'); + + + +const DynamicForm = React.forwardRef( + ({ + formTemplate, + onSubmit, + buttonStyles, + hideButtons = false, + formValues = null, + isTherapistQuestionnaire = true, + showCarousel = false, + setCurrentPage = null, + imgView, + inputStyle + }, ref) => { + + + React.useImperativeHandle(ref, () => ({ + submitForm: async function () { + onSumbitButtonPress(); + }, + nextPage: function () { + if (activePage < formTemplate.data.length - 1) { + scrollToIndex(activePage + 1); + // setCurrentIndex(currentIndex + 1); + } + }, + prevPage: function () { + if (activePage > 0) { + scrollToIndex(activePage - 1); + // setCurrentIndex(currentIndex + 1); + } + }, + })); + + + const refScroll = React.useRef(null); + + const [currentIndex, setCurrentIndex] = useState(0); + const [formFields, setFormFields] = useState({}); + const [isValidFormFields, setValid] = useState(false); + const mandatoryFields = formTemplate.data.filter(data => data.is_mandatory); + + + // Function to scroll to a specific index + const scrollToIndex = (index) => { + if (refScroll.current) { + refScroll.current.scrollTo({ + x: index * deviceWidth, // Calculate horizontal position based on index + animated: true, // Smooth scrolling + }); + } }; - const setDefaultForFields = () => { - const fields = {}; - formTemplate.data.forEach(data => { - if (data.component === componentName.CHECKBOX) { - fields[data.field_name] = { - value: false, - inputType: data.component, - }; + + useEffect(() => { + formTemplate.data.sort((a, b) => a.index - b.index); + + if (formValues) { + setFormFields(formValues); + } else { + setFormFields({ + ...formFields, + ...setDefaultForFields() + }); } - if (data.component === componentName.DATE_PICKER) { - const today = new Date(); - const currentDate = `${today.getFullYear()}-${`0${today.getMonth() + 1}`.slice(-2)}-` - + `${today.getDate()}`; - - fields[data.field_name] = { - value: currentDate, - inputType: data.component, - }; + + + }, [formValues]); + + useEffect(() => { + const isValid = checkAllMandatoryFields(); + setValid(isValid); + }, [JSON.stringify(formFields)]); + + + + const onChangeInputValue = (fieldName, inputType) => value => { + setFormFields({ + ...formFields, + [fieldName]: { + ...formFields[fieldName] || {}, + value, + inputType, + } + }); + }; + + const setDefaultForFields = () => { + const fields = {}; + formTemplate.data.forEach(data => { + if (data.component === componentName.CHECKBOX) { + fields[data.field_name] = { + value: false, + inputType: data.component, + }; + } + if (data.component === componentName.DATE_PICKER) { + const today = new Date(); + const currentDate = `${today.getFullYear()}-${`0${today.getMonth() + 1}`.slice(-2)}-` + + `${today.getDate()}`; + + fields[data.field_name] = { + value: currentDate, + inputType: data.component, + }; + } + }); + + return fields; + }; + + const getValue = element => formFields[element.field_name]?.value; + + const onSumbitButtonPress = (sendToTherapist = false) => { + + onSubmit(formFields, sendToTherapist); + + }; + + const checkAllMandatoryFields = () => { + for (const field of mandatoryFields) { + const key = field.field_name; + + if (skipValidationForFields.includes(field.component)) { + continue; + } + + const data = formFields[key]; + const validator = data && getValidator(data.inputType); + + if (!data || (!data.value || (validator && !validator(data.value, key))) + && (data.value !== false && data.value !== 0)) { + return false; + } } - }); - return fields; - }; + return true; + }; - const getValue = element => formFields[element.field_name]?.value; + const [activePage, setActivePage] = useState(0); // Active page index - const onSumbitButtonPress = () => { - onSubmit(formFields); + // Handle scroll event to calculate the active page + const handleScroll = (event) => { + const scrollPosition = event.nativeEvent.contentOffset.x; // Current scroll position + const currentPage = Math.round(scrollPosition / deviceWidth); // Calculate active page + setActivePage(currentPage); // Update active page + console.log('FormBuilder:currentPage', currentPage); + setCurrentPage && setCurrentPage(currentPage); }; - const checkAllMandatoryFields = () => { - for (const field of mandatoryFields) { - const key = field.field_name; - if (skipValidationForFields.includes(field.component)) { - continue; - } - const data = formFields[key]; - const validator = data && getValidator(data.inputType); + if (showCarousel) { - if (!data || (!data.value || (validator && !validator(data.value, key))) - && (data.value !== false && data.value !== 0)) { - return false; - } + const nArray = Array.from({ length: formTemplate?.data?.length }, (_, index) => index); + + return ( + + + + refScroll.current = ref} + horizontal={true} + showsHorizontalScrollIndicator={false} + // snapToAlignment='center' + // snapToInterval={true} + pagingEnabled={true} + onScroll={handleScroll} + scrollEventThrottle={16} // Optimize scroll event handling + style={{flexShrink:1, width: deviceWidth, borderWidth:0 }} + contentContainerStyle={{minHeight:200, width: 'auto', paddingHorizontal: 0 }} + > + { + + formTemplate && formTemplate.data.map(element => { + const Component = getComponent(element.component); + return Component && ( + + ); + }) + + } + + {/* Pagination Dots */} + + {nArray?.map((index) => ( + + ))} + + + + + + ) + + } else { + + return ( + + { + formTemplate && formTemplate.data.map(element => { + const Component = getComponent(element.component); + return Component && ( + + ); + }) + + } + + + {hideButtons ? + null : + (isTherapistQuestionnaire ? + +