access logs + audio
This commit is contained in:
@@ -1,18 +1,16 @@
|
||||
import { FC, useEffect, useRef, useState } from 'react'
|
||||
import { FC, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Input from '../../components/Input'
|
||||
import Button from '../../components/Button'
|
||||
import SwitchComponent from '../../components/Switch'
|
||||
import { TickCircle } from 'iconsax-react'
|
||||
import "quill/dist/quill.snow.css";
|
||||
// import Quill from 'quill';
|
||||
import { useFormik } from 'formik'
|
||||
import { BlogCategoryType, CreateBlogType } from './types/BlogTypes'
|
||||
import { useCreateBlog, useGetBlogCategories } from './hooks/useBlogData'
|
||||
import * as Yup from 'yup'
|
||||
import CheckBoxComponent from '../../components/CheckBoxComponent'
|
||||
import UploadBoxDraggble from '../../components/UploadBoxDraggble'
|
||||
import Quill from 'quill'
|
||||
import QuillEditor from '../../components/QuillEditor'
|
||||
import { useSingleUpload } from '../service/hooks/useServiceData'
|
||||
import { toast } from 'react-toastify'
|
||||
import { ErrorType } from '../../helpers/types'
|
||||
@@ -22,30 +20,9 @@ const CreateBlog: FC = () => {
|
||||
|
||||
const { t } = useTranslation('global')
|
||||
const [file, setFile] = useState<File>()
|
||||
const [audioFile, setAudioFile] = useState<File>()
|
||||
const singleSlug = useSingleUpload()
|
||||
const editorRef = useRef<HTMLDivElement>(null)
|
||||
const editorRef2 = useRef<HTMLDivElement>(null)
|
||||
useEffect(() => {
|
||||
const quill = new Quill('#editor', {
|
||||
theme: 'snow',
|
||||
});
|
||||
|
||||
quill.on('text-change', () => {
|
||||
const html = editorRef.current?.querySelector('.ql-editor')?.innerHTML || '';
|
||||
formik.setFieldValue('previewContent', html);
|
||||
});
|
||||
const quill2 = new Quill('#editor2', {
|
||||
theme: 'snow',
|
||||
});
|
||||
|
||||
quill2.on('text-change', () => {
|
||||
const html = editorRef2.current?.querySelector('.ql-editor')?.innerHTML || '';
|
||||
formik.setFieldValue('content', html);
|
||||
});
|
||||
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
const audioUpload = useSingleUpload()
|
||||
|
||||
const navigate = useNavigate()
|
||||
const createBlog = useCreateBlog()
|
||||
@@ -57,6 +34,7 @@ const CreateBlog: FC = () => {
|
||||
previewContent: '',
|
||||
content: '',
|
||||
imageUrl: '',
|
||||
audioUrl: '',
|
||||
isActive: false,
|
||||
isPinned: false,
|
||||
metaDescription: '',
|
||||
@@ -80,6 +58,12 @@ const CreateBlog: FC = () => {
|
||||
toast.error(t('errors.required'))
|
||||
return
|
||||
}
|
||||
|
||||
if (!audioFile) {
|
||||
values.audioUrl = undefined
|
||||
}
|
||||
|
||||
// آپلود تصویر
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
await singleSlug.mutateAsync(formData, {
|
||||
@@ -88,6 +72,17 @@ const CreateBlog: FC = () => {
|
||||
},
|
||||
})
|
||||
|
||||
// آپلود فایل صوتی در صورت وجود
|
||||
if (audioFile) {
|
||||
const audioFormData = new FormData()
|
||||
audioFormData.append('file', audioFile)
|
||||
await audioUpload.mutateAsync(audioFormData, {
|
||||
onSuccess(data) {
|
||||
values.audioUrl = data.data.url
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
createBlog.mutate(values, {
|
||||
onSuccess() {
|
||||
toast.success(t('success'))
|
||||
@@ -110,7 +105,7 @@ const CreateBlog: FC = () => {
|
||||
<Button
|
||||
className='w-[172px]'
|
||||
onClick={() => formik.handleSubmit()}
|
||||
isLoading={createBlog.isPending || singleSlug.isPending}
|
||||
isLoading={createBlog.isPending || singleSlug.isPending || audioUpload.isPending}
|
||||
>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<TickCircle size={20} color='white' />
|
||||
@@ -141,7 +136,13 @@ const CreateBlog: FC = () => {
|
||||
|
||||
<p className='mt-6 text-sm'>{t('blog.blog_summary')}</p>
|
||||
<div className='mt-1'>
|
||||
<div className='min-h-[120px]' ref={editorRef} id='editor'></div>
|
||||
<QuillEditor
|
||||
id="preview-editor"
|
||||
value={formik.values.previewContent}
|
||||
onChange={(content) => formik.setFieldValue('previewContent', content)}
|
||||
placeholder={t('blog.enter_blog_summary')}
|
||||
minHeight="120px"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{
|
||||
@@ -152,7 +153,13 @@ const CreateBlog: FC = () => {
|
||||
|
||||
<p className='mt-6 text-sm'>{t('blog.content')}</p>
|
||||
<div className='mt-1'>
|
||||
<div className='min-h-[200px]' ref={editorRef2} id='editor2'></div>
|
||||
<QuillEditor
|
||||
id="content-editor"
|
||||
value={formik.values.content}
|
||||
onChange={(content) => formik.setFieldValue('content', content)}
|
||||
placeholder={t('blog.enter_blog_content')}
|
||||
minHeight="200px"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{
|
||||
@@ -216,7 +223,7 @@ const CreateBlog: FC = () => {
|
||||
checked={formik.values.categoryId === item.id}
|
||||
onChange={(e) => formik.setFieldValue('categoryId', e.target.checked ? item.id : '')}
|
||||
/>
|
||||
<div>{item.title}</div>
|
||||
<div className='text-[13px]'>{item.title}</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
@@ -231,6 +238,16 @@ const CreateBlog: FC = () => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-8'>
|
||||
<p className='text-sm'>{t('blog.audio_file')}</p>
|
||||
<div className='mt-4'>
|
||||
<UploadBoxDraggble
|
||||
label={t('blog.audio_file')}
|
||||
onChange={(files) => setAudioFile(files[0])}
|
||||
accept="audio/*"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<p className='mt-6 text-sm'>{t('blog.tags')}</p>
|
||||
<div className='mt-6'>
|
||||
<Input
|
||||
|
||||
+55
-41
@@ -1,18 +1,16 @@
|
||||
import { FC, useEffect, useRef, useState } from 'react'
|
||||
import { FC, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Input from '../../components/Input'
|
||||
import Button from '../../components/Button'
|
||||
import SwitchComponent from '../../components/Switch'
|
||||
import { TickCircle } from 'iconsax-react'
|
||||
import "quill/dist/quill.snow.css";
|
||||
// import Quill from 'quill';
|
||||
import { useFormik } from 'formik'
|
||||
import { BlogCategoryType, CreateBlogType } from './types/BlogTypes'
|
||||
import { useGetBlogCategories, useGetBlogDetail, useUpdateBlog } from './hooks/useBlogData'
|
||||
import * as Yup from 'yup'
|
||||
import CheckBoxComponent from '../../components/CheckBoxComponent'
|
||||
import UploadBoxDraggble from '../../components/UploadBoxDraggble'
|
||||
import Quill from 'quill'
|
||||
import QuillEditor from '../../components/QuillEditor'
|
||||
import { useSingleUpload } from '../service/hooks/useServiceData'
|
||||
import { toast } from 'react-toastify'
|
||||
import { ErrorType } from '../../helpers/types'
|
||||
@@ -23,31 +21,10 @@ const UpdateBlog: FC = () => {
|
||||
const { id } = useParams()
|
||||
const { t } = useTranslation('global')
|
||||
const [file, setFile] = useState<File>()
|
||||
const [audioFile, setAudioFile] = useState<File>()
|
||||
const singleSlug = useSingleUpload()
|
||||
const editorRef = useRef<HTMLDivElement>(null)
|
||||
const editorRef2 = useRef<HTMLDivElement>(null)
|
||||
const audioUpload = useSingleUpload()
|
||||
const getBlogDetail = useGetBlogDetail(id || '')
|
||||
useEffect(() => {
|
||||
const quill = new Quill('#editor', {
|
||||
theme: 'snow',
|
||||
});
|
||||
|
||||
quill.on('text-change', () => {
|
||||
const html = editorRef.current?.querySelector('.ql-editor')?.innerHTML || '';
|
||||
formik.setFieldValue('previewContent', html);
|
||||
});
|
||||
const quill2 = new Quill('#editor2', {
|
||||
theme: 'snow',
|
||||
});
|
||||
|
||||
quill2.on('text-change', () => {
|
||||
const html = editorRef2.current?.querySelector('.ql-editor')?.innerHTML || '';
|
||||
formik.setFieldValue('content', html);
|
||||
});
|
||||
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const navigate = useNavigate()
|
||||
const updateBlog = useUpdateBlog()
|
||||
@@ -59,6 +36,7 @@ const UpdateBlog: FC = () => {
|
||||
previewContent: '',
|
||||
content: '',
|
||||
imageUrl: '',
|
||||
audioUrl: '',
|
||||
isActive: false,
|
||||
isPinned: false,
|
||||
metaDescription: '',
|
||||
@@ -78,6 +56,7 @@ const UpdateBlog: FC = () => {
|
||||
slug: Yup.string().required(t('errors.required')),
|
||||
}),
|
||||
onSubmit: async (values) => {
|
||||
// آپلود تصویر در صورت انتخاب فایل جدید
|
||||
if (file) {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
@@ -88,6 +67,20 @@ const UpdateBlog: FC = () => {
|
||||
})
|
||||
}
|
||||
|
||||
if (!audioFile) {
|
||||
values.audioUrl = undefined
|
||||
}
|
||||
|
||||
// آپلود فایل صوتی در صورت وجود
|
||||
if (audioFile) {
|
||||
const audioFormData = new FormData()
|
||||
audioFormData.append('file', audioFile)
|
||||
await audioUpload.mutateAsync(audioFormData, {
|
||||
onSuccess(data) {
|
||||
values.audioUrl = data.data.url
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
updateBlog.mutate({ id: id || '', params: values }, {
|
||||
onSuccess() {
|
||||
@@ -105,16 +98,6 @@ const UpdateBlog: FC = () => {
|
||||
if (getBlogDetail.data) {
|
||||
formik.setValues(getBlogDetail.data?.data?.blog)
|
||||
formik.setFieldValue('categoryId', getBlogDetail.data?.data?.blog.category.id)
|
||||
|
||||
const editorElement = editorRef.current?.querySelector('.ql-editor');
|
||||
if (editorElement) {
|
||||
editorElement.innerHTML = getBlogDetail.data?.data?.blog?.previewContent || '';
|
||||
}
|
||||
|
||||
const editorElement2 = editorRef2.current?.querySelector('.ql-editor');
|
||||
if (editorElement2) {
|
||||
editorElement2.innerHTML = getBlogDetail.data?.data?.blog?.content || '';
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [getBlogDetail.data])
|
||||
@@ -129,7 +112,7 @@ const UpdateBlog: FC = () => {
|
||||
<Button
|
||||
className='w-[172px]'
|
||||
onClick={() => formik.handleSubmit()}
|
||||
isLoading={updateBlog.isPending || singleSlug.isPending}
|
||||
isLoading={updateBlog.isPending || singleSlug.isPending || audioUpload.isPending}
|
||||
>
|
||||
<div className='flex gap-2 items-center'>
|
||||
<TickCircle size={20} color='white' />
|
||||
@@ -160,7 +143,13 @@ const UpdateBlog: FC = () => {
|
||||
|
||||
<p className='mt-6 text-sm'>{t('blog.blog_summary')}</p>
|
||||
<div className='mt-1'>
|
||||
<div className='min-h-[120px]' ref={editorRef} id='editor'></div>
|
||||
<QuillEditor
|
||||
id="preview-editor-update"
|
||||
value={formik.values.previewContent}
|
||||
onChange={(content) => formik.setFieldValue('previewContent', content)}
|
||||
placeholder={t('blog.enter_blog_summary')}
|
||||
minHeight="120px"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{
|
||||
@@ -171,7 +160,13 @@ const UpdateBlog: FC = () => {
|
||||
|
||||
<p className='mt-6 text-sm'>{t('blog.content')}</p>
|
||||
<div className='mt-1'>
|
||||
<div className='min-h-[200px]' ref={editorRef2} id='editor2'></div>
|
||||
<QuillEditor
|
||||
id="content-editor-update"
|
||||
value={formik.values.content}
|
||||
onChange={(content) => formik.setFieldValue('content', content)}
|
||||
placeholder={t('blog.enter_blog_content')}
|
||||
minHeight="200px"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{
|
||||
@@ -235,7 +230,7 @@ const UpdateBlog: FC = () => {
|
||||
checked={formik.values.categoryId === item.id}
|
||||
onChange={(e) => formik.setFieldValue('categoryId', e.target.checked ? item.id : '')}
|
||||
/>
|
||||
<div>{item.title}</div>
|
||||
<div className='text-[13px]'>{item.title}</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
@@ -250,6 +245,25 @@ const UpdateBlog: FC = () => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-8'>
|
||||
<p className='text-sm'>{t('blog.audio_file')}</p>
|
||||
<div className='mt-4'>
|
||||
<UploadBoxDraggble
|
||||
label={t('blog.audio_file')}
|
||||
onChange={(files) => setAudioFile(files[0])}
|
||||
accept="audio/*"
|
||||
/>
|
||||
</div>
|
||||
{formik.values.audioUrl && (
|
||||
<div className='mt-2'>
|
||||
<p className='text-xs text-gray-500'>{t('blog.current_audio_file')}:</p>
|
||||
<audio controls className='w-full mt-1'>
|
||||
<source src={formik.values.audioUrl} type="audio/mpeg" />
|
||||
{t('blog.audio_not_supported')}
|
||||
</audio>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<p className='mt-6 text-sm'>{t('blog.tags')}</p>
|
||||
<div className='mt-6'>
|
||||
<Input
|
||||
|
||||
@@ -3,6 +3,7 @@ export type CreateBlogType = {
|
||||
previewContent: string;
|
||||
content: string;
|
||||
imageUrl: string;
|
||||
audioUrl?: string;
|
||||
metaTitle: string;
|
||||
metaDescription: string;
|
||||
tags: string[];
|
||||
|
||||
Reference in New Issue
Block a user