/
SOFG1
/
hasida
Обзор
Документация
Войти
/
SOFG1
/
hasida
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/components/common/FieldInputComponent.tsx
377 строк
10 KB
Eddy
initial commit
22 июл 2024, 17:14
22 июл 2024, 17:14
b43c0d0
Код
Авторство
О чём код?
import React, { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import styled from "styled-components"; import { IField, useUserGetFieldOptionsQuery } from "../../api/user"; import { DateInput } from "../../UI/DateInput"; import { Dropdown } from "../../UI/Dropdown"; import { Input } from "../../UI/Input"; import { Radio } from "../../UI/Radio"; import { Textarea } from "../../UI/Textarea"; import HeightFieldComponent from "./HeightFieldComponent"; import IncomeFieldComponent from "./IncomeFieldComponent"; import GenderFieldComponent from "./GenderFieldComponent"; import { USCountryCode } from "../../constants"; import MobilePhoneInput from "./MobilePhoneInput"; import { ColorInput } from "../../UI/ColorInput"; import ChildrenInputComponent from "./ChildrenInputComponent"; import EditEducationComponent from "./EditEducationComponent"; import OrientationFieldComponent from "./OrientationFieldComponent"; //const colorInputsNames = ["hair_color_childhood", "eye_color", "hair_color"]; const colorInputsNames: string[] = []; interface IProps { field: IField; value: any; onChange: (v: any) => void; selectedCountryId?: number; selectedStateId?: number; hint?: string; currency?: string; } // const EthicBackgroundBox = styled.div` // display: flex; // flex-direction: column; // gap: 20px; // margin-bottom: 20px; // `; const StyledBox = styled.div` display: flex; align-items: center; flex-wrap: wrap; gap: 20px; margin-bottom: 20px; `; const StyledTextarea = styled(Textarea)` margin-bottom: 30px; `; const FieldInputComponent = React.memo( ({ field, value, onChange, selectedCountryId, selectedStateId, hint, currency, }: IProps): any => { const { t, i18n } = useTranslation(); const [isFetchInstitutionsOptions, setIsFetchInstitutionsOptions] = useState<boolean>(true); const skipOptsFetching = useMemo(() => { if (field.name === "education") return isFetchInstitutionsOptions; if (field.type !== "ForeignKey") return true; if (field.name === "state" && selectedCountryId !== USCountryCode) return true; if (field.name === "city" && !selectedCountryId) return true; return false; }, [field.type, selectedCountryId, selectedStateId, isFetchInstitutionsOptions]); const { data, isFetching } = useUserGetFieldOptionsQuery( { field: field.name === 'education' ? 'institution' : field.name, country_id: selectedCountryId, state_id: selectedStateId, }, { skip: skipOptsFetching } ); const fetchedOptions = useMemo(() => { return data?.map((o) => ({ label: o.name, value: o.id })) || []; }, [data]); //Select income currency according to app language useEffect(() => { if(field.name === "income_curency" && i18n.language === "en-US") { onChange({label: "USD", value: "USD"}) } if(field.name === "income_curency" && i18n.language === "he") { onChange({label: "ILS", value: "ILS"}) } }, [field, i18n.language]) /////////////////////Exceptions at first /////////////////////////////////////////////// //Hide State if country no US if (field.name === "state" && selectedCountryId !== USCountryCode) { return null; } //Exception for height input 'Integer' if (field.type === "Integer" && field.name === "hight") { return ( <HeightFieldComponent label={field.view_name} value={value} onChange={onChange} /> ); } //Exception for children input if (field.type === "Integer" && field.name === "children") { return ( <ChildrenInputComponent label={field.view_name} value={value ? String(value) : ""} onChange={onChange} /> ); } //Exception for hair color if (colorInputsNames.includes(field.name)) { const options = field.options.map((o) => ({ label: o, value: o })); return ( <ColorInput label={field.view_name} value={value} onChange={onChange} options={options} /> ); } //Exception for mobile phone if (field.type === "String" && field.name === "mobile_phone") { return ( <MobilePhoneInput label={field.view_name} value={value} onChange={onChange} hint={hint} /> ); } //Exception for birth_date if (field.type === "Date" && field.name === "birth_date") { //Max date 18 years behind (only 18+) const date = new Date(); const year = date.getFullYear() - 18; const month = date.getMonth() + 1; const day = date.getDate(); const maxDate = new Date( `${month < 10 ? 0 + month : month}-${day}-${year}` ); return ( <DateInput label={field.view_name} value={value} onChange={onChange} maxDate={maxDate} hint={hint} /> ); } //Exception for 'income' range if (field.type === "Integer" && field.name === "income") { return ( <IncomeFieldComponent currency={currency} label={field.view_name} value={value} onChange={onChange} /> ); } //Exception for 'gender' dropdown if (field.name === "gender") { return ( <GenderFieldComponent hint={t("field-gender_hint")} label={field.view_name} value={value} onChange={onChange} options={field.options} /> ); } //Exception for 'ethnic_background' // if (field.name === "ethnic_background") { // return ( // <EthicBackgroundBox> // <p>{field.view_name}</p> // <StyledBox> // {field.options.map(o => <Radio // active={value?.label === o} // onChange={(v) => onChange({ label: o, value: o })} // label={o} // />)} // </StyledBox> // </EthicBackgroundBox> // ); // } //Exception for 'sexual_orientation' dropdown if (field.name === "sexual_orientation") { return ( <OrientationFieldComponent hint={t("field-orientation_hint")} label={field.view_name} value={value} onChange={onChange} options={field.options} /> ); } //////////////// Other inputs/////////////////////////////// //Date inputs if (field.type === "Date") { return ( <DateInput label={field.view_name} value={value} onChange={onChange} /> ); } if (field.type === "Many2Many") { let options if (field.name === "who_can_see") { options = [ { label: field.options[2], value: field.options[2] }, { label: field.options[1], value: field.options[1] }, { label: t("other"), value: t("other") } ]; const otherValueChecked = value?.map((v: any) => v.label) if (otherValueChecked?.includes(t("other"))) { options = field.options.map((o) => ({ label: o, value: o })); value = value.filter((v: any) => v.label !== t("other")); } } else { options = field.options.map((o) => ({ label: o, value: o })); } return ( <Dropdown label={field.view_name} value={value} onChange={onChange} options={options} multiselect={true} /> ); } //Text inputs if options length > 0 it's a dropdown if (field.type === "String" && !field?.options?.length) { return ( <Input type="text" label={field.view_name} value={value || ""} onChange={onChange} hint={hint} /> ); } //Dropdowns, if options length > 0 it's a dropdown if (field.type === "String" && field?.options?.length) { const options = field.options.map((o) => ({ label: o, value: o })); return ( <Dropdown label={field.view_name} value={value} onChange={onChange} options={options} /> ); } //Radio inputs if (field.type === "Boolean") { return ( <StyledBox> <p>{field.view_name}</p> <Radio active={value === true} onChange={(v) => onChange(true)} label={t("field-yes")} /> <Radio active={value === false} onChange={(v) => onChange(false)} label={t("field-no")} /> </StyledBox> ); } //Integer inputs if (field.type === "Integer") { return ( <Input type="number" label={field.view_name} value={value > 99 ? [...String(value)][0] + [...String(value)][1] : value || ""} onChange={onChange} /> ); } //Textarea inputs if (field.type === "Text") { let error; if (value?.length > 1000) { error = "Maximum 1000 characters !"; } return ( <StyledTextarea label={field.view_name} value={value || ""} onChange={onChange} error={error} hint={`${value?.length || 0}/1000`} /> ); } //Dropdowns with fetchable options if (field.type === "ForeignKey") { return ( <Dropdown label={field.view_name} value={value} onChange={onChange} options={fetchedOptions} loading={isFetching} multiselect={field.name === "family_origin"} /> ); } //JSONField if (field.type === "JSONField") { return ( <EditEducationComponent value={value} onChange={onChange} field={field} fetchedOptions={fetchedOptions} isFetching={isFetching} setIsFetchInstitutionsOptions={setIsFetchInstitutionsOptions} /> ); } } ); export default FieldInputComponent;