diff --git a/index.html b/index.html index 22ff2f9..158c5cf 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,6 @@ Admin panel -
diff --git a/public/env.js b/public/env.js deleted file mode 100644 index c7a5eeb..0000000 --- a/public/env.js +++ /dev/null @@ -1,3 +0,0 @@ -window.__ENV__ = window.__ENV__ || { - API_BASE_URL: 'http://localhost:8081', -}; diff --git a/src/api/apiContent.js b/src/api/apiContent.js deleted file mode 100644 index 271c9a7..0000000 --- a/src/api/apiContent.js +++ /dev/null @@ -1,117 +0,0 @@ -import { API, authHeader } from './apiSlice' -import { CONTENT_RESOURCES } from '../config/contentResources' - -const buildListQuery = (basePath, { usesLimit = false } = {}) => - ({ search = '', page = 1, perPage = 20 } = {}) => { - let queryString = `?page=${page}` - if (usesLimit) { - queryString += `&limit=${perPage}` - } else { - queryString += `&perPage=${perPage}` - } - if (search) { - queryString += `&search=${encodeURIComponent(search)}` - } - return { - url: `${basePath}/list${queryString}`, - } - } - -const injectResource = (resourceKey) => { - const { basePath, listUsesLimit } = CONTENT_RESOURCES[resourceKey] - const cap = resourceKey - .split('-') - .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) - .join('') - - return API.injectEndpoints({ - endpoints: (build) => ({ - [`get${cap}List`]: build.query({ - query: buildListQuery(basePath, { usesLimit: listUsesLimit }), - refetchOnMountOrArgChange: true, - keepUnusedDataFor: 0, - }), - [`get${cap}Item`]: build.query({ - query: (id) => ({ - url: `${basePath}/${id}`, - }), - }), - [`create${cap}`]: build.mutation({ - query: (data) => ({ - url: `${basePath}/create`, - method: 'POST', - headers: authHeader(), - body: JSON.stringify(data), - }), - }), - [`update${cap}`]: build.mutation({ - query: ({ id, data }) => ({ - url: `${basePath}/${id}`, - method: 'PUT', - headers: authHeader(), - body: JSON.stringify(data), - }), - }), - [`delete${cap}`]: build.mutation({ - query: (id) => ({ - url: `${basePath}/${id}`, - method: 'DELETE', - headers: authHeader(), - }), - }), - }), - overrideExisting: false, - }) -} - -const newsApi = injectResource('news') -const promoApi = injectResource('promo') -const diseaseApi = injectResource('disease') -const medicalCenterApi = injectResource('medical-center') -const articleApi = injectResource('article') -const siteServicesApi = injectResource('site-services') - -export const contentHooks = { - news: { - useListQuery: newsApi.useGetNewsListQuery, - useItemQuery: newsApi.useGetNewsItemQuery, - useCreateMutation: newsApi.useCreateNewsMutation, - useUpdateMutation: newsApi.useUpdateNewsMutation, - useDeleteMutation: newsApi.useDeleteNewsMutation, - }, - promo: { - useListQuery: promoApi.useGetPromoListQuery, - useItemQuery: promoApi.useGetPromoItemQuery, - useCreateMutation: promoApi.useCreatePromoMutation, - useUpdateMutation: promoApi.useUpdatePromoMutation, - useDeleteMutation: promoApi.useDeletePromoMutation, - }, - disease: { - useListQuery: diseaseApi.useGetDiseaseListQuery, - useItemQuery: diseaseApi.useGetDiseaseItemQuery, - useCreateMutation: diseaseApi.useCreateDiseaseMutation, - useUpdateMutation: diseaseApi.useUpdateDiseaseMutation, - useDeleteMutation: diseaseApi.useDeleteDiseaseMutation, - }, - 'medical-center': { - useListQuery: medicalCenterApi.useGetMedicalCenterListQuery, - useItemQuery: medicalCenterApi.useGetMedicalCenterItemQuery, - useCreateMutation: medicalCenterApi.useCreateMedicalCenterMutation, - useUpdateMutation: medicalCenterApi.useUpdateMedicalCenterMutation, - useDeleteMutation: medicalCenterApi.useDeleteMedicalCenterMutation, - }, - article: { - useListQuery: articleApi.useGetArticleListQuery, - useItemQuery: articleApi.useGetArticleItemQuery, - useCreateMutation: articleApi.useCreateArticleMutation, - useUpdateMutation: articleApi.useUpdateArticleMutation, - useDeleteMutation: articleApi.useDeleteArticleMutation, - }, - 'site-services': { - useListQuery: siteServicesApi.useGetSiteServicesListQuery, - useItemQuery: siteServicesApi.useGetSiteServicesItemQuery, - useCreateMutation: siteServicesApi.useCreateSiteServicesMutation, - useUpdateMutation: siteServicesApi.useUpdateSiteServicesMutation, - useDeleteMutation: siteServicesApi.useDeleteSiteServicesMutation, - }, -} diff --git a/src/api/apiSlice.js b/src/api/apiSlice.js index 1058946..8056e6d 100644 --- a/src/api/apiSlice.js +++ b/src/api/apiSlice.js @@ -1,5 +1,4 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' -import { API_BASE_URL } from '@/config/api' export const authHeader = () => { const token = localStorage.getItem('token') @@ -9,7 +8,7 @@ export const authHeader = () => { export const API = createApi({ reducerPath: 'API', baseQuery: fetchBaseQuery({ - baseUrl: API_BASE_URL, + baseUrl: 'https://api.sovamed.ru', credentials: 'include', }), endpoints: (builder) => ({ diff --git a/src/components/Docs/Certificates.jsx b/src/components/Docs/Certificates.jsx index bfcbfa6..e97ebf9 100644 --- a/src/components/Docs/Certificates.jsx +++ b/src/components/Docs/Certificates.jsx @@ -1,6 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { apiUrl } from '@/config/api'; import { CertEditor } from '../Editors/CertEditor' const isValidImage = (file) => { @@ -16,7 +15,7 @@ export function CertificatesForm({ initCertificates, onChange }) { const [certificates, setCertificates] = useState([]); useEffect(() => { - const certificatesWithPictureUrl = initCertificates.map((init) => ({ ...init, picture: apiUrl(`/uploads/${init.picture}`)})) + const certificatesWithPictureUrl = initCertificates.map((init) => ({ ...init, picture: `https://api.sovamed.ru/uploads/${init.picture}`})) setInitialCertificates([...certificatesWithPictureUrl]) setCertificates([...certificatesWithPictureUrl]) }, [initCertificates]) diff --git a/src/components/Docs/Portfolio.jsx b/src/components/Docs/Portfolio.jsx index ff8897f..72084bf 100644 --- a/src/components/Docs/Portfolio.jsx +++ b/src/components/Docs/Portfolio.jsx @@ -1,6 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { apiUrl } from '@/config/api'; import { CertEditor } from '../Editors/CertEditor' const isValidImage = (file) => { @@ -18,7 +17,7 @@ export function PortfolioForm({ initPortfolios, onChange }) { useEffect(() => { // console.log(initPortfolios) const portfolioWithPictureUrl = initPortfolios.map((init) => { - if ( init.picture ) return ({ ...init, picture: apiUrl(`/uploads/${init.picture}`)}) + if ( init.picture ) return ({ ...init, picture: `https://api.sovamed.ru/uploads/${init.picture}`}) return { ...init } }) setInitialPorfolios([...portfolioWithPictureUrl]) diff --git a/src/components/Docs/Stocks.jsx b/src/components/Docs/Stocks.jsx index edd1471..18c6408 100644 --- a/src/components/Docs/Stocks.jsx +++ b/src/components/Docs/Stocks.jsx @@ -1,6 +1,5 @@ import React, { useState, useEffect, useRef } from 'react'; -import { apiUrl } from '@/config/api'; import { CertEditor } from '../Editors/CertEditor' const isValidImage = (file) => { @@ -23,7 +22,7 @@ export function StocksForm({ initStocks, onChange }) { // console.log(initStocks[0]?.startDate) // console.log(typeof initStocks[0]?.startDate) const portfolioWithPictureUrl = initStocks.map((init) => { - if ( init.picture ) return ({ ...init, picture: apiUrl(`/uploads/${init.picture}`)}) + if ( init.picture ) return ({ ...init, picture: `https://api.sovamed.ru/uploads/${init.picture}`}) return { ...init } }).map(init => { const dateStart = new Date(init.startDate); diff --git a/src/config/api.js b/src/config/api.js deleted file mode 100644 index 6a6ff0d..0000000 --- a/src/config/api.js +++ /dev/null @@ -1,10 +0,0 @@ -export const API_BASE_URL = - (typeof window !== 'undefined' && window.__ENV__?.API_BASE_URL) || - import.meta.env.VITE_API_BASE_URL || - 'https://api.sovamed.ru' - -export const apiUrl = (path) => { - const base = API_BASE_URL.replace(/\/$/, '') - const suffix = path.startsWith('/') ? path : `/${path}` - return `${base}${suffix}` -} diff --git a/src/config/contentResources.js b/src/config/contentResources.js deleted file mode 100644 index 02795e1..0000000 --- a/src/config/contentResources.js +++ /dev/null @@ -1,223 +0,0 @@ -const baseContentFields = [ - { key: 'name', label: 'Название', type: 'text' }, - { key: 'active', label: 'Активно', type: 'checkbox' }, - { key: 'regionId', label: 'Регион', type: 'region' }, - { key: 'alias', label: 'Alias', type: 'text' }, - { key: 'anons', label: 'Анонс', type: 'html' }, - { key: 'content', label: 'Контент', type: 'html' }, -] - -const json = (key, label) => ({ key, label: `${label} (JSON)`, type: 'json' }) -const text = (key, label) => ({ key, label, type: 'text' }) - -export const CONTENT_RESOURCES = { - news: { - slug: 'news', - basePath: '/news', - title: 'Новости', - titleSingle: 'новость', - icon: 'fas fa-newspaper', - listColumns: [ - { key: 'id', label: 'ID' }, - { key: 'name', label: 'Название' }, - { key: 'alias', label: 'Alias' }, - { key: 'active', label: 'Активно', format: 'bool' }, - { key: 'regionId', label: 'Регион' }, - ], - fields: [ - ...baseContentFields, - text('shortName', 'Короткое название'), - text('linkElPrice', 'Ссылка на прайс'), - text('timer', 'Таймер'), - text('timerBg', 'Фон таймера'), - json('formOrder', 'formOrder'), - json('linkServices', 'linkServices'), - json('linkStaff', 'linkStaff'), - json('photos', 'photos'), - ], - }, - promo: { - slug: 'site-promo', - basePath: '/promo', - title: 'Промо (контент)', - titleSingle: 'промо', - icon: 'fas fa-bullhorn', - listColumns: [ - { key: 'id', label: 'ID' }, - { key: 'name', label: 'Название' }, - { key: 'alias', label: 'Alias' }, - { key: 'active', label: 'Активно', format: 'bool' }, - { key: 'regionId', label: 'Регион' }, - ], - fields: [ - ...baseContentFields, - text('shortName', 'Короткое название'), - text('period', 'Период'), - text('timer', 'Таймер'), - text('timerBg', 'Фон таймера'), - json('clinics', 'clinics'), - json('linkServices', 'linkServices'), - json('linkStaff', 'linkStaff'), - json('photos', 'photos'), - ], - }, - disease: { - slug: 'disease', - basePath: '/disease', - title: 'Заболевания', - titleSingle: 'заболевание', - icon: 'fas fa-heartbeat', - listColumns: [ - { key: 'id', label: 'ID' }, - { key: 'name', label: 'Название' }, - { key: 'alias', label: 'Alias' }, - { key: 'active', label: 'Активно', format: 'bool' }, - ], - fields: [ - ...baseContentFields, - text('previewPicture', 'previewPicture'), - { key: 'hidePicture', label: 'hidePicture', type: 'checkbox' }, - text('readTime', 'readTime'), - text('diseasesName', 'diseasesName'), - text('diseasesOtherName', 'diseasesOtherName'), - text('symptom', 'symptom'), - text('staff', 'staff'), - text('bibliography', 'bibliography'), - json('tagsImportant', 'tagsImportant'), - json('tags', 'tags'), - json('linkServices', 'linkServices'), - json('staffList', 'staffList'), - json('staffPost', 'staffPost'), - json('staffPostExclude', 'staffPostExclude'), - json('linkFaq', 'linkFaq'), - json('staffCheck', 'staffCheck'), - ], - }, - 'medical-center': { - slug: 'medical-center', - basePath: '/medical-center', - title: 'Медцентры', - titleSingle: 'медцентр', - icon: 'fas fa-hospital', - listColumns: [ - { key: 'id', label: 'ID' }, - { key: 'name', label: 'Название' }, - { key: 'alias', label: 'Alias' }, - { key: 'active', label: 'Активно', format: 'bool' }, - ], - fields: [ - ...baseContentFields, - text('mainLinkStaff', 'mainLinkStaff'), - text('plusText', 'plusText'), - text('plusTitle', 'plusTitle'), - text('processText', 'processText'), - text('processTitle', 'processTitle'), - text('servicesTitle', 'servicesTitle'), - text('trainingText', 'trainingText'), - text('trainingTextTitle', 'trainingTextTitle'), - text('whyText', 'whyText'), - text('whyTitle', 'whyTitle'), - { key: 'hidePicture', label: 'hidePicture', type: 'number' }, - json('kodUslug', 'kodUslug'), - json('doctors', 'doctors'), - json('services', 'services'), - json('articles', 'articles'), - json('txtUp', 'txtUp'), - json('contraindications', 'contraindications'), - json('indications', 'indications'), - json('linkSale', 'linkSale'), - json('plusList', 'plusList'), - json('servicesList', 'servicesList'), - json('servicesPhotos', 'servicesPhotos'), - json('sortStaff', 'sortStaff'), - ], - }, - article: { - slug: 'article', - basePath: '/article', - title: 'Статьи', - titleSingle: 'статью', - icon: 'fas fa-file-alt', - listUsesMeta: true, - listUsesLimit: true, - listColumns: [ - { key: 'id', label: 'ID' }, - { key: 'name', label: 'Название' }, - { key: 'alias', label: 'Alias' }, - { key: 'active', label: 'Активно', format: 'bool' }, - ], - fields: [ - ...baseContentFields, - text('previewPicture', 'previewPicture'), - json('doctors', 'doctors'), - json('services', 'services'), - ], - }, - 'site-services': { - slug: 'site-services', - basePath: '/site-services', - title: 'Услуги сайта', - titleSingle: 'услугу', - icon: 'fas fa-concierge-bell', - listColumns: [ - { key: 'id', label: 'ID' }, - { key: 'name', label: 'Название' }, - { key: 'alias', label: 'Alias' }, - { key: 'active', label: 'Активно', format: 'bool' }, - ], - fields: [ - ...baseContentFields, - text('previewImg', 'previewImg'), - text('partPrice', 'partPrice'), - text('pokazaniya', 'pokazaniya'), - text('preparation', 'preparation'), - text('protivopokazaniya', 'protivopokazaniya'), - text('bannerImg', 'bannerImg'), - text('bannerImgM', 'bannerImgM'), - text('bannerImgUrl', 'bannerImgUrl'), - text('downloadFile', 'downloadFile'), - text('fullWidthBanner', 'fullWidthBanner'), - text('kodUslug', 'kodUslug'), - text('linkPrice', 'linkPrice'), - text('photosTitle', 'photosTitle'), - text('contraindicationsList', 'contraindicationsList'), - text('customBlockText', 'customBlockText'), - text('customBlockText2', 'customBlockText2'), - text('customBlockTitle', 'customBlockTitle'), - text('customBlockTitle2', 'customBlockTitle2'), - text('indicationsList', 'indicationsList'), - text('plusList', 'plusList'), - text('plusText', 'plusText'), - text('plusTitle', 'plusTitle'), - text('prepareTitle', 'prepareTitle'), - text('processText', 'processText'), - text('processTitle', 'processTitle'), - text('servicesList', 'servicesList'), - text('servicesTitle', 'servicesTitle'), - text('textUp', 'textUp'), - text('trainingText', 'trainingText'), - text('whyText', 'whyText'), - text('whyTitle', 'whyTitle'), - { key: 'hidePicture', label: 'hidePicture', type: 'number' }, - json('linkVideoreviews', 'linkVideoreviews'), - json('faq', 'faq'), - json('hideSignBtn', 'hideSignBtn'), - json('quiz', 'quiz'), - json('tags', 'tags'), - json('tagsImportant', 'tagsImportant'), - json('clinics', 'clinics'), - json('staffUp', 'staffUp'), - json('advantages', 'advantages'), - json('saleId', 'saleId'), - json('sortStaff', 'sortStaff'), - json('linkArticlesServices', 'linkArticlesServices'), - json('servicesPhotos', 'servicesPhotos'), - json('linkFaq', 'linkFaq'), - json('linkServices', 'linkServices'), - json('linkStaff', 'linkStaff'), - json('photos', 'photos'), - ], - }, -} - -export const CONTENT_RESOURCE_KEYS = Object.keys(CONTENT_RESOURCES) diff --git a/src/hooks/useLostLocations.jsx b/src/hooks/useLostLocations.jsx index c054a21..58dac55 100644 --- a/src/hooks/useLostLocations.jsx +++ b/src/hooks/useLostLocations.jsx @@ -2,8 +2,6 @@ import { useState, useEffect } from 'react'; import axios from 'axios'; import { useSelector } from 'react-redux'; -import { apiUrl } from '@/config/api'; - import { useGetFilialsQuery } from '../api/apiFilial'; import { useGetDepartmentsQuery } from '../api/apiDepartment'; import { selectRegions } from '../store/slice/regionSlice'; @@ -33,7 +31,7 @@ export function useLostDoctors() { Promise.all( data.data.map(item => { const fetchString = fetchParams.filter((param => Boolean(item[param]))).map(param => `${param}=${item[param]}`).join('&'); - return axios.get(apiUrl(`/idoctor/list?${fetchString}`), { + return axios.get(`https://api.sovamed.ru/idoctor/list?${fetchString}`, { headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } }) .then(res => { diff --git a/src/hooks/useSpecialist.jsx b/src/hooks/useSpecialist.jsx index 78f7d38..3ce82e2 100644 --- a/src/hooks/useSpecialist.jsx +++ b/src/hooks/useSpecialist.jsx @@ -2,8 +2,6 @@ import { useState, useEffect } from 'react'; import axios from 'axios'; import { useSelector } from 'react-redux'; -import { apiUrl } from '@/config/api'; - import { useGetSpecialistsQuery, useGetSpecialistQuery } from '../api/apiSpecialist'; import { useGetKodopersQuery } from '../api/apiKodoper'; import { useGetFilialsQuery } from '../api/apiFilial'; @@ -29,7 +27,7 @@ export function useSpecialist(id) { Promise.all( specialist.kodoper.map(code => - axios.get(apiUrl(`/pricelist/list?search=${code}`), { + axios.get(`https://api.sovamed.ru/pricelist/list?search=${code}`, { headers: { Authorization: `Bearer ${localStorage.getItem('token')}` } }) .then(res => { diff --git a/src/pages/EditFilialPage.jsx b/src/pages/EditFilialPage.jsx index 5fc135b..b054812 100644 --- a/src/pages/EditFilialPage.jsx +++ b/src/pages/EditFilialPage.jsx @@ -2,8 +2,6 @@ import { useEffect, useState, useRef } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { useSelector } from 'react-redux'; -import { apiUrl } from '@/config/api'; - import { useGetFilialsQuery, useUpdateFilialMutation, useUploadFilialPictureMutation } from '../api/apiFilial'; import { selectUtils } from '../store/slice/utilsSlice'; import { selectRegions } from '../store/slice/regionSlice'; @@ -71,7 +69,7 @@ export const EditFilialPage = () => { email: filial.email, fid: filial.fid, origin: filial.origin, - picture: apiUrl(filial.pictureLink), + picture: `https://api.sovamed.ru${filial.pictureLink}`, policy: filial.policy, } setForm({... filialData}) diff --git a/src/pages/EditSpecialistPage.jsx b/src/pages/EditSpecialistPage.jsx index 651d939..54ddf53 100644 --- a/src/pages/EditSpecialistPage.jsx +++ b/src/pages/EditSpecialistPage.jsx @@ -2,8 +2,6 @@ import {useEffect, useState, useMemo, useRef} from 'react' import {useParams, useNavigate, useLocation } from 'react-router-dom' import DatePicker from "react-datepicker"; -import { apiUrl } from '@/config/api'; - import { useUpdateSpecialistMutation, useDeleteSpecialistMutation, useUploadSpecialistPictureMutation } from '../api/apiSpecialist' import { useCreateLocationMutation, useUpdateLocationMutation, useDeleteLocationMutation } from '/src/api/apiLocation.js' import { @@ -388,7 +386,7 @@ export const EditSpecialistPage = () => { } updateField('category', formatCategory(specialist.category)); - updateField('previewPicture', apiUrl(specialist.pictureLink)); + updateField('previewPicture', `https://api.sovamed.ru${specialist.pictureLink}`); const formattedDate = specialist.experience ? `${specialist.experience}-01-01` diff --git a/src/pages/EditStockPage.jsx b/src/pages/EditStockPage.jsx index 89443b4..e779c19 100644 --- a/src/pages/EditStockPage.jsx +++ b/src/pages/EditStockPage.jsx @@ -1,8 +1,6 @@ import { useState, useEffect, useRef } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; -import { apiUrl } from '@/config/api'; - import { useGetStockQuery, useUpdateStockMutation, @@ -87,7 +85,7 @@ export function EditStockPage() { name: stock.name ?? '', startDate: datetimeLocalStart, endDate: datetimeLocalEnd, - picture: stock.picture ? apiUrl(`/uploads/${stock.picture}`) : '', + picture: stock.picture ? `https://api.sovamed.ru/uploads/${stock.picture}` : '', })); setAnons( stock.anons ) diff --git a/src/pages/content/ContentEditPage.jsx b/src/pages/content/ContentEditPage.jsx deleted file mode 100644 index 76e3888..0000000 --- a/src/pages/content/ContentEditPage.jsx +++ /dev/null @@ -1,370 +0,0 @@ -import { useEffect, useRef, useState } from 'react' -import { useNavigate, useParams } from 'react-router-dom' -import { useSelector } from 'react-redux' - -import { selectRegions } from '../../store/slice/regionSlice' -import { TextEditor } from '../../components/Editors/TextEditor' -import { LoadingComponent } from '../../components/Placeholders/LoadingComponent' -import { ErrorComponent } from '../../components/Placeholders/ErrorComponent' -import { NotFindElement } from '../../components/Placeholders/NotFindElement' -import { EditElementForm } from '../../components/Forms/EditElementForm' -import Modal from '../../components/Modals/Modal' -import { parseSaveError } from '../../utils/parseSaveError' - -const SUCCESS_MODAL_MS = 2000 - -const emptyFormFromConfig = (fields) => { - const form = {} - fields.forEach((field) => { - if (field.type === 'checkbox') { - form[field.key] = false - } else if (field.type === 'number' || field.type === 'region') { - form[field.key] = '' - } else { - form[field.key] = '' - } - }) - return form -} - -const itemToForm = (item, fields) => { - const form = {} - fields.forEach((field) => { - const value = item[field.key] - if (field.type === 'json') { - form[field.key] = value == null ? '' : JSON.stringify(value, null, 2) - } else if (field.type === 'checkbox') { - form[field.key] = Boolean(value) - } else if (field.type === 'region' || field.type === 'number') { - form[field.key] = value ?? '' - } else { - form[field.key] = value ?? '' - } - }) - return form -} - -const formToPayload = (form, fields) => { - const data = {} - fields.forEach((field) => { - const raw = form[field.key] - if (field.type === 'json') { - if (!raw || !String(raw).trim()) { - data[field.key] = null - return - } - try { - data[field.key] = JSON.parse(raw) - } catch { - const error = new Error('Невалидный JSON — проверьте синтаксис') - error.fieldKey = field.key - throw error - } - return - } - if (field.type === 'checkbox') { - data[field.key] = Boolean(raw) - return - } - if (field.type === 'region' || field.type === 'number') { - data[field.key] = raw === '' ? null : Number(raw) - return - } - data[field.key] = raw === '' ? null : raw - }) - return data -} - -const FieldHint = ({ message }) => - message ? {message} : null - -const fieldWrapperClass = (hasError, extra = '') => - ['form-group', extra, hasError ? 'content-field--has-error' : ''].filter(Boolean).join(' ') - -const ContentField = ({ field, form, updateField, regions, fieldErrors }) => { - const value = form[field.key] - const errorMessage = fieldErrors[field.key] - const hasError = Boolean(errorMessage) - const labelClass = hasError ? 'content-field-error-label' : undefined - const controlClass = `form-control${hasError ? ' is-invalid' : ''}` - - if (field.type === 'checkbox') { - return ( -
- updateField(field.key, e.target.checked)} - /> - - -
- ) - } - - if (field.type === 'region') { - const selectValue = value === '' || value == null ? '' : String(value) - return ( -
- - - -
- ) - } - - if (field.type === 'html') { - return ( -
- - updateField(field.key, html)} /> - -
- ) - } - - if (field.type === 'json') { - return ( -
- -