diff --git a/src/pages/sight/create.tsx b/src/pages/sight/create.tsx index f8ca641..a745a0a 100644 --- a/src/pages/sight/create.tsx +++ b/src/pages/sight/create.tsx @@ -1,7 +1,10 @@ -import {Autocomplete, Box, TextField} from '@mui/material' +import {Autocomplete, Box, TextField, Typography, Paper} from '@mui/material' import {Create, useAutocomplete} from '@refinedev/mui' import {useForm} from '@refinedev/react-hook-form' import {Controller} from 'react-hook-form' +import {Link} from 'react-router' +import React, {useState, useEffect} from 'react' +import {TOKEN_KEY} from '../../authProvider' export const SightCreate = () => { const { @@ -9,6 +12,7 @@ export const SightCreate = () => { refineCore: {formLoading}, register, control, + watch, formState: {errors}, } = useForm({ refineCoreProps: { @@ -16,6 +20,17 @@ export const SightCreate = () => { }, }) + // Состояния для предпросмотра + const [namePreview, setNamePreview] = useState('') + const [coordinatesPreview, setCoordinatesPreview] = useState({latitude: '', longitude: ''}) + const [cityPreview, setCityPreview] = useState('') + const [thumbnailPreview, setThumbnailPreview] = useState(null) + const [watermarkLUPreview, setWatermarkLUPreview] = useState(null) + const [watermarkRDPreview, setWatermarkRDPreview] = useState(null) + const [leftArticlePreview, setLeftArticlePreview] = useState('') + const [previewArticlePreview, setPreviewArticlePreview] = useState('') + + // Автокомплиты const {autocompleteProps: cityAutocompleteProps} = useAutocomplete({ resource: 'city', onSearch: (value) => [ @@ -49,201 +64,419 @@ export const SightCreate = () => { ], }) + // Следим за изменениями во всех полях + const nameContent = watch('name') + const latitudeContent = watch('latitude') + const longitudeContent = watch('longitude') + const cityContent = watch('city_id') + const thumbnailContent = watch('thumbnail') + const watermarkLUContent = watch('watermark_lu') + const watermarkRDContent = watch('watermark_rd') + const leftArticleContent = watch('left_article') + const previewArticleContent = watch('preview_article') + + // Обновляем состояния при изменении полей + useEffect(() => { + setNamePreview(nameContent || '') + }, [nameContent]) + + useEffect(() => { + setCoordinatesPreview({ + latitude: latitudeContent || '', + longitude: longitudeContent || '', + }) + }, [latitudeContent, longitudeContent]) + + useEffect(() => { + const selectedCity = cityAutocompleteProps.options.find((option) => option.id === cityContent) + setCityPreview(selectedCity?.name || '') + }, [cityContent, cityAutocompleteProps.options]) + + useEffect(() => { + const selectedThumbnail = mediaAutocompleteProps.options.find((option) => option.id === thumbnailContent) + setThumbnailPreview(selectedThumbnail ? `https://wn.krbl.ru/media/${selectedThumbnail.id}/download?token=${localStorage.getItem(TOKEN_KEY)}` : null) + }, [thumbnailContent, mediaAutocompleteProps.options]) + + useEffect(() => { + const selectedWatermarkLU = mediaAutocompleteProps.options.find((option) => option.id === watermarkLUContent) + setWatermarkLUPreview(selectedWatermarkLU ? `https://wn.krbl.ru/media/${selectedWatermarkLU.id}/download?token=${localStorage.getItem(TOKEN_KEY)}` : null) + }, [watermarkLUContent, mediaAutocompleteProps.options]) + + useEffect(() => { + const selectedWatermarkRD = mediaAutocompleteProps.options.find((option) => option.id === watermarkRDContent) + setWatermarkRDPreview(selectedWatermarkRD ? `https://wn.krbl.ru/media/${selectedWatermarkRD.id}/download?token=${localStorage.getItem(TOKEN_KEY)}` : null) + }, [watermarkRDContent, mediaAutocompleteProps.options]) + + useEffect(() => { + const selectedLeftArticle = articleAutocompleteProps.options.find((option) => option.id === leftArticleContent) + setLeftArticlePreview(selectedLeftArticle?.heading || '') + }, [leftArticleContent, articleAutocompleteProps.options]) + + useEffect(() => { + const selectedPreviewArticle = articleAutocompleteProps.options.find((option) => option.id === previewArticleContent) + setPreviewArticlePreview(selectedPreviewArticle?.heading || '') + }, [previewArticleContent, articleAutocompleteProps.options]) + return ( - - - - + + {/* Форма создания */} + + + + - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.name : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.name.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.name : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.name.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.media_name : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.media_name : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.media_name : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.media_name : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.media_name : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.media_name : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.heading : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.heading.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.heading : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.heading.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.heading : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.heading.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.heading : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.heading.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> + + + {/* Блок предпросмотра */} + (theme.palette.mode === 'dark' ? 'background.paper' : '#fff'), + }} + > + + Предпросмотр + + + {/* Название */} + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800')}}> + {namePreview} + + + {/* Город */} + + + Город:{' '} + + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800')}}> + {cityPreview} + + + + {/* Координаты */} + + + Координаты:{' '} + + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800')}}> + {coordinatesPreview.latitude}, {coordinatesPreview.longitude} + + + + {/* Обложка */} + {thumbnailPreview && ( + + + Обложка: + + + )} - /> + + {/* Водяные знаки */} + + + Водяные знаки: + + + {watermarkLUPreview && ( + + + Левый верхний: + + + + )} + {watermarkRDPreview && ( + + + Правый нижний: + + + + )} + + + + {/* Связанные статьи */} + + + Связанные статьи: + + {leftArticlePreview && ( + + + Левая статья:{' '} + + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800'), + textDecoration: 'none', + '&:hover': { + textDecoration: 'underline', + }, + }} + > + {leftArticlePreview} + + + )} + {previewArticlePreview && ( + + + Статья-предпросмотр:{' '} + + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800'), + textDecoration: 'none', + '&:hover': { + textDecoration: 'underline', + }, + }} + > + {previewArticlePreview} + + + )} + + ) diff --git a/src/pages/sight/edit.tsx b/src/pages/sight/edit.tsx index 9e3ea09..d814bc7 100644 --- a/src/pages/sight/edit.tsx +++ b/src/pages/sight/edit.tsx @@ -1,11 +1,14 @@ -import {Autocomplete, Box, TextField} from '@mui/material' +import {Autocomplete, Box, TextField, Paper, Typography} from '@mui/material' import {Edit, useAutocomplete} from '@refinedev/mui' import {useForm} from '@refinedev/react-hook-form' import {Controller} from 'react-hook-form' import {useParams} from 'react-router' +import React, {useState, useEffect} from 'react' import {LinkedItems} from '../../components/LinkedItems' import {CreateSightArticle} from '../../components/CreateSightArticle' import {ArticleItem, articleFields} from './types' +import {TOKEN_KEY} from '../../authProvider' +import {Link} from 'react-router' export const SightEdit = () => { const {id: sightId} = useParams<{id: string}>() @@ -14,6 +17,7 @@ export const SightEdit = () => { saveButtonProps, register, control, + watch, formState: {errors}, } = useForm({}) @@ -50,201 +54,439 @@ export const SightEdit = () => { ], }) + // Состояния для предпросмотра + const [namePreview, setNamePreview] = useState('') + const [coordinatesPreview, setCoordinatesPreview] = useState({ + latitude: '', + longitude: '', + }) + const [cityPreview, setCityPreview] = useState('') + const [thumbnailPreview, setThumbnailPreview] = useState(null) + const [watermarkLUPreview, setWatermarkLUPreview] = useState(null) + const [watermarkRDPreview, setWatermarkRDPreview] = useState(null) + const [leftArticlePreview, setLeftArticlePreview] = useState('') + const [previewArticlePreview, setPreviewArticlePreview] = useState('') + + // Следим за изменениями во всех полях + const nameContent = watch('name') + const latitudeContent = watch('latitude') + const longitudeContent = watch('longitude') + const cityContent = watch('city_id') + const thumbnailContent = watch('thumbnail') + const watermarkLUContent = watch('watermark_lu') + const watermarkRDContent = watch('watermark_rd') + const leftArticleContent = watch('left_article') + const previewArticleContent = watch('preview_article') + + // Обновляем состояния при изменении полей + useEffect(() => { + setNamePreview(nameContent || '') + }, [nameContent]) + + useEffect(() => { + setCoordinatesPreview({ + latitude: latitudeContent || '', + longitude: longitudeContent || '', + }) + }, [latitudeContent, longitudeContent]) + + useEffect(() => { + const selectedCity = cityAutocompleteProps.options.find((option) => option.id === cityContent) + setCityPreview(selectedCity?.name || '') + }, [cityContent, cityAutocompleteProps.options]) + + useEffect(() => { + const selectedThumbnail = mediaAutocompleteProps.options.find((option) => option.id === thumbnailContent) + setThumbnailPreview(selectedThumbnail ? `https://wn.krbl.ru/media/${selectedThumbnail.id}/download?token=${localStorage.getItem(TOKEN_KEY)}` : null) + }, [thumbnailContent, mediaAutocompleteProps.options]) + + useEffect(() => { + const selectedWatermarkLU = mediaAutocompleteProps.options.find((option) => option.id === watermarkLUContent) + setWatermarkLUPreview(selectedWatermarkLU ? `https://wn.krbl.ru/media/${selectedWatermarkLU.id}/download?token=${localStorage.getItem(TOKEN_KEY)}` : null) + }, [watermarkLUContent, mediaAutocompleteProps.options]) + + useEffect(() => { + const selectedWatermarkRD = mediaAutocompleteProps.options.find((option) => option.id === watermarkRDContent) + setWatermarkRDPreview(selectedWatermarkRD ? `https://wn.krbl.ru/media/${selectedWatermarkRD.id}/download?token=${localStorage.getItem(TOKEN_KEY)}` : null) + }, [watermarkRDContent, mediaAutocompleteProps.options]) + + useEffect(() => { + const selectedLeftArticle = articleAutocompleteProps.options.find((option) => option.id === leftArticleContent) + setLeftArticlePreview(selectedLeftArticle?.heading || '') + }, [leftArticleContent, articleAutocompleteProps.options]) + + useEffect(() => { + const selectedPreviewArticle = articleAutocompleteProps.options.find((option) => option.id === previewArticleContent) + setPreviewArticlePreview(selectedPreviewArticle?.heading || '') + }, [previewArticleContent, articleAutocompleteProps.options]) + return ( - - - - + + {/* Форма редактирования */} + + + + - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.name : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.name.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.name : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.name.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.media_name : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.media_name : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.media_name : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.media_name : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.media_name : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.media_name : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.media_name.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.heading : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.heading.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> - )} - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.heading : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.heading.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> - ( - option.id === field.value) || null} - onChange={(_, value) => { - field.onChange(value?.id || '') - }} - getOptionLabel={(item) => { - return item ? item.heading : '' - }} - isOptionEqualToValue={(option, value) => { - return option.id === value?.id - }} - filterOptions={(options, {inputValue}) => { - return options.filter((option) => option.heading.toLowerCase().includes(inputValue.toLowerCase())) - }} - renderInput={(params) => } - /> + ( + option.id === field.value) || null} + onChange={(_, value) => { + field.onChange(value?.id || '') + }} + getOptionLabel={(item) => { + return item ? item.heading : '' + }} + isOptionEqualToValue={(option, value) => { + return option.id === value?.id + }} + filterOptions={(options, {inputValue}) => { + return options.filter((option) => option.heading.toLowerCase().includes(inputValue.toLowerCase())) + }} + renderInput={(params) => } + /> + )} + /> + + + {/* Блок предпросмотра */} + (theme.palette.mode === 'dark' ? 'background.paper' : '#fff'), + }} + > + + Предпросмотр + + + {/* Название достопримечательности */} + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800'), + mb: 3, + }} + > + {namePreview} + + + {/* Город */} + + + Город:{' '} + + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800')}}> + {cityPreview} + + + + {/* Координаты */} + + + Координаты:{' '} + + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800')}}> + {coordinatesPreview.latitude}, {coordinatesPreview.longitude} + + + + {/* Обложка */} + {thumbnailPreview && ( + + + Обложка: + + + )} - /> + + {/* Водяные знаки */} + + + Водяные знаки: + + + {watermarkLUPreview && ( + + + Левый верхний: + + + + )} + {watermarkRDPreview && ( + + + Правый нижний: + + + + )} + + + + {/* Связанные статьи */} + + {/* + Связанные статьи: + */} + {leftArticlePreview && ( + + + Левая статья:{' '} + + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800'), + textDecoration: 'none', + '&:hover': { + textDecoration: 'underline', + }, + }} + > + {leftArticlePreview} + + + )} + {previewArticlePreview && ( + + + Статья-предпросмотр:{' '} + + (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800'), + textDecoration: 'none', + '&:hover': { + textDecoration: 'underline', + }, + }} + > + {previewArticlePreview} + + + )} + + {sightId && (