upgrade edit for /sight route to create articles
				
					
				
			This commit is contained in:
		
							
								
								
									
										116
									
								
								src/components/CreateSightArticle.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/components/CreateSightArticle.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| import {Typography, Button, Box, Accordion, AccordionSummary, AccordionDetails, useTheme, TextField} from '@mui/material' | ||||
| import ExpandMoreIcon from '@mui/icons-material/ExpandMore' | ||||
| import {axiosInstance} from '../providers/data' | ||||
| import {BACKEND_URL} from '../lib/constants' | ||||
| import {useForm, Controller} from 'react-hook-form' | ||||
| import {MarkdownEditor} from './MarkdownEditor' | ||||
| import React from 'react' | ||||
|  | ||||
| const MemoizedSimpleMDE = React.memo(MarkdownEditor) | ||||
|  | ||||
| type Props = { | ||||
|   parentId: string | number | ||||
|   parentResource: string | ||||
|   childResource: string | ||||
|   title: string | ||||
| } | ||||
|  | ||||
| export const CreateSightArticle = ({parentId, parentResource, childResource, title}: Props) => { | ||||
|   const theme = useTheme() | ||||
|  | ||||
|   const { | ||||
|     register: registerItem, | ||||
|     control: controlItem, | ||||
|     handleSubmit: handleSubmitItem, | ||||
|     reset: resetItem, | ||||
|     formState: {errors: itemErrors}, | ||||
|   } = useForm({ | ||||
|     defaultValues: { | ||||
|       heading: '', | ||||
|       body: '', | ||||
|     }, | ||||
|   }) | ||||
|  | ||||
|   const simpleMDEOptions = React.useMemo( | ||||
|     () => ({ | ||||
|       placeholder: 'Введите контент в формате Markdown...', | ||||
|       spellChecker: false, | ||||
|     }), | ||||
|     [], | ||||
|   ) | ||||
|  | ||||
|   const handleCreate = async (data: {heading: string; body: string}) => { | ||||
|     try { | ||||
|       const response = await axiosInstance.post(`${BACKEND_URL}/${childResource}`, data) | ||||
|       const itemId = response.data.id | ||||
|  | ||||
|       const existingItemsResponse = await axiosInstance.get(`${BACKEND_URL}/${parentResource}/${parentId}/${childResource}`) | ||||
|       const existingItems = existingItemsResponse.data || [] | ||||
|  | ||||
|       const nextPageNum = existingItems.length + 1 | ||||
|  | ||||
|       await axiosInstance.post(`${BACKEND_URL}/${parentResource}/${parentId}/${childResource}/`, { | ||||
|         [`${childResource}_id`]: itemId, | ||||
|         page_num: nextPageNum, | ||||
|       }) | ||||
|  | ||||
|       resetItem() | ||||
|       window.location.reload() | ||||
|     } catch (err: any) { | ||||
|       console.error('Error creating item:', err) | ||||
|       if (err?.response) { | ||||
|         console.error('Error response:', err.response.data) | ||||
|         console.error('Error status:', err.response.status) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return ( | ||||
|     <Accordion> | ||||
|       <AccordionSummary | ||||
|         expandIcon={<ExpandMoreIcon />} | ||||
|         sx={{ | ||||
|           marginTop: 2, | ||||
|           background: theme.palette.background.paper, | ||||
|           borderBottom: `1px solid ${theme.palette.divider}`, | ||||
|         }} | ||||
|       > | ||||
|         <Typography variant="subtitle1" fontWeight="bold"> | ||||
|           Создать {title} | ||||
|         </Typography> | ||||
|       </AccordionSummary> | ||||
|       <AccordionDetails sx={{background: theme.palette.background.paper}}> | ||||
|         <Box component="form" onSubmit={handleSubmitItem(handleCreate)}> | ||||
|           <TextField | ||||
|             {...registerItem('heading', { | ||||
|               required: 'Это поле является обязательным', | ||||
|             })} | ||||
|             error={!!(itemErrors as any)?.heading} | ||||
|             helperText={(itemErrors as any)?.heading?.message} | ||||
|             margin="normal" | ||||
|             fullWidth | ||||
|             InputLabelProps={{shrink: true}} | ||||
|             type="text" | ||||
|             label="Заголовок *" | ||||
|           /> | ||||
|  | ||||
|           <Controller control={controlItem} name="body" rules={{required: 'Это поле является обязательным'}} defaultValue="" render={({field: {onChange, value}}) => <MemoizedSimpleMDE value={value} onChange={onChange} options={simpleMDEOptions} className="my-markdown-editor" />} /> | ||||
|  | ||||
|           <Box sx={{mt: 2, display: 'flex', gap: 2}}> | ||||
|             <Button variant="contained" color="primary" type="submit"> | ||||
|               Создать | ||||
|             </Button> | ||||
|             <Button | ||||
|               variant="outlined" | ||||
|               onClick={() => { | ||||
|                 resetItem() | ||||
|               }} | ||||
|             > | ||||
|               Очистить | ||||
|             </Button> | ||||
|           </Box> | ||||
|         </Box> | ||||
|       </AccordionDetails> | ||||
|     </Accordion> | ||||
|   ) | ||||
| } | ||||
| @@ -4,9 +4,12 @@ import {useForm} from '@refinedev/react-hook-form' | ||||
| import {Controller} from 'react-hook-form' | ||||
| import {useParams} from 'react-router' | ||||
| import {LinkedItems} from '../../components/LinkedItems' | ||||
| import {CreateSightArticle} from '../../components/CreateSightArticle' | ||||
| import {ArticleItem, articleFields} from './types' | ||||
|  | ||||
| export const SightEdit = () => { | ||||
|   const {id: sightId} = useParams<{id: string}>() | ||||
|  | ||||
|   const { | ||||
|     saveButtonProps, | ||||
|     register, | ||||
| @@ -14,8 +17,6 @@ export const SightEdit = () => { | ||||
|     formState: {errors}, | ||||
|   } = useForm({}) | ||||
|  | ||||
|   const {id: sightId} = useParams<{id: string}>() | ||||
|  | ||||
|   const {autocompleteProps: cityAutocompleteProps} = useAutocomplete({ | ||||
|     resource: 'city', | ||||
|     onSearch: (value) => [ | ||||
| @@ -98,7 +99,14 @@ export const SightEdit = () => { | ||||
|           )} | ||||
|         /> | ||||
|       </Box> | ||||
|       {sightId && <LinkedItems<ArticleItem> type="edit" parentId={sightId} parentResource="sight" childResource="article" fields={articleFields} title="статьи" />} | ||||
|  | ||||
|       {sightId && ( | ||||
|         <Box sx={{mt: 3}}> | ||||
|           <LinkedItems<ArticleItem> type="edit" parentId={sightId} parentResource="sight" childResource="article" fields={articleFields} title="статьи" /> | ||||
|  | ||||
|           <CreateSightArticle parentId={sightId} parentResource="sight" childResource="article" title="статью" /> | ||||
|         </Box> | ||||
|       )} | ||||
|     </Edit> | ||||
|   ) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user