chore: file formatting
This commit is contained in:
@@ -1,40 +1,35 @@
|
||||
import {useEffect, useRef, useState} from "react";
|
||||
import {useNavigate, useParams} from "react-router-dom";
|
||||
import {BytescaleUploader} from "@/components/BytescaleUploader/BytescaleUploader";
|
||||
import EditorJS, {OutputData} from "@editorjs/editorjs";
|
||||
import Header from "@editorjs/header";
|
||||
import List from "@editorjs/list";
|
||||
import ImageTool from "@editorjs/image";
|
||||
import Quote from "@editorjs/quote";
|
||||
import Table from "@editorjs/table";
|
||||
import CodeTool from "@editorjs/code";
|
||||
import Embed from "@editorjs/embed";
|
||||
import Delimiter from "@editorjs/delimiter";
|
||||
import axios from "axios";
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { BytescaleUploader } from '@/components/BytescaleUploader/BytescaleUploader';
|
||||
import EditorJS, { OutputData } from '@editorjs/editorjs';
|
||||
import Header from '@editorjs/header';
|
||||
import List from '@editorjs/list';
|
||||
import ImageTool from '@editorjs/image';
|
||||
import Quote from '@editorjs/quote';
|
||||
import Table from '@editorjs/table';
|
||||
import CodeTool from '@editorjs/code';
|
||||
import Embed from '@editorjs/embed';
|
||||
import Delimiter from '@editorjs/delimiter';
|
||||
import axios from 'axios';
|
||||
|
||||
import {
|
||||
createBlogApi,
|
||||
updateBlogApi,
|
||||
getBlogByIdApi,
|
||||
uploadImageApi,
|
||||
} from "@/api/blog";
|
||||
import { createBlogApi, updateBlogApi, getBlogByIdApi, uploadImageApi } from '@/api/blog';
|
||||
|
||||
import {Card, CardContent, CardHeader, CardTitle} from "@/components/ui/card";
|
||||
import {Input} from "@/components/ui/input";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
export default function BlogEditorPage() {
|
||||
const baseURL = import.meta.env.VITE_API_URL;
|
||||
const {id} = useParams();
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const editorRef = useRef<EditorJS | null>(null);
|
||||
const hasInitialized = useRef(false);
|
||||
const hasRenderedContent = useRef(false);
|
||||
|
||||
const [title, setTitle] = useState("");
|
||||
const [writer, setWriter] = useState("");
|
||||
const [coverImage, setCoverImage] = useState("");
|
||||
const [title, setTitle] = useState('');
|
||||
const [writer, setWriter] = useState('');
|
||||
const [coverImage, setCoverImage] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const isEdit = Boolean(id);
|
||||
@@ -47,16 +42,16 @@ export default function BlogEditorPage() {
|
||||
|
||||
const initEditor = async () => {
|
||||
editor = new EditorJS({
|
||||
holder: "editorjs",
|
||||
holder: 'editorjs',
|
||||
|
||||
placeholder: "Write blog content...",
|
||||
placeholder: 'Write blog content...',
|
||||
|
||||
tools: {
|
||||
header: {
|
||||
class: Header,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
placeholder: "Enter heading",
|
||||
placeholder: 'Enter heading',
|
||||
levels: [1, 2, 3, 4],
|
||||
defaultLevel: 2,
|
||||
},
|
||||
@@ -66,7 +61,7 @@ export default function BlogEditorPage() {
|
||||
class: List,
|
||||
inlineToolbar: true,
|
||||
config: {
|
||||
defaultStyle: "unordered",
|
||||
defaultStyle: 'unordered',
|
||||
},
|
||||
},
|
||||
|
||||
@@ -82,38 +77,33 @@ export default function BlogEditorPage() {
|
||||
uploader: {
|
||||
uploadByFile: async (file: File) => {
|
||||
if (file.size > 5 * 1024 * 1024) {
|
||||
alert("File is too large (Max 5MB)");
|
||||
return {success: 0, file: {url: ""}};
|
||||
alert('File is too large (Max 5MB)');
|
||||
return { success: 0, file: { url: '' } };
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
formData.append("folderPath", "/blog");
|
||||
formData.append('file', file);
|
||||
formData.append('folderPath', '/blog');
|
||||
|
||||
try {
|
||||
const response = await axios.post(
|
||||
`${baseURL}/upload`,
|
||||
formData,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
const response = await axios.post(`${baseURL}/upload`, formData, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
success: 1,
|
||||
file: {url: response.data.fileUrl},
|
||||
file: { url: response.data.fileUrl },
|
||||
};
|
||||
} catch (e: any) {
|
||||
console.error("EditorJS Image Upload Error:", e);
|
||||
const errorMessage =
|
||||
e.response?.data?.error || e.message || "Upload failed";
|
||||
console.error('EditorJS Image Upload Error:', e);
|
||||
const errorMessage = e.response?.data?.error || e.message || 'Upload failed';
|
||||
alert(`Upload Error: ${errorMessage}`);
|
||||
|
||||
return {
|
||||
success: 0,
|
||||
file: {url: ""},
|
||||
file: { url: '' },
|
||||
};
|
||||
}
|
||||
},
|
||||
@@ -132,7 +122,7 @@ export default function BlogEditorPage() {
|
||||
|
||||
setTitle(res.title);
|
||||
setWriter(res.writer);
|
||||
setCoverImage(res.image || "");
|
||||
setCoverImage(res.image || '');
|
||||
|
||||
if (res.content) {
|
||||
await editor.blocks.clear();
|
||||
@@ -170,7 +160,7 @@ export default function BlogEditorPage() {
|
||||
await createBlogApi(payload);
|
||||
}
|
||||
|
||||
navigate("/blog");
|
||||
navigate('/blog');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
@@ -182,47 +172,28 @@ export default function BlogEditorPage() {
|
||||
<div className="p-6 max-w-5xl mx-auto space-y-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>{isEdit ? "Edit Blog" : "Create Blog"}</CardTitle>
|
||||
<CardTitle>{isEdit ? 'Edit Blog' : 'Create Blog'}</CardTitle>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="space-y-4">
|
||||
<Input
|
||||
placeholder="Blog Title"
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
/>
|
||||
<Input placeholder="Blog Title" value={title} onChange={(e) => setTitle(e.target.value)} />
|
||||
|
||||
<Input
|
||||
placeholder="Writer Name"
|
||||
value={writer}
|
||||
onChange={(e) => setWriter(e.target.value)}
|
||||
/>
|
||||
<Input placeholder="Writer Name" value={writer} onChange={(e) => setWriter(e.target.value)} />
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Cover Image</label>
|
||||
|
||||
<BytescaleUploader
|
||||
value={coverImage}
|
||||
folderPath="/blog"
|
||||
onChange={(url) => setCoverImage(url)}
|
||||
/>
|
||||
<BytescaleUploader value={coverImage} folderPath="/blog" onChange={(url) => setCoverImage(url)} />
|
||||
|
||||
{coverImage && (
|
||||
<img
|
||||
src={coverImage}
|
||||
alt="cover"
|
||||
className="w-full max-h-[250px] object-cover rounded-md"
|
||||
/>
|
||||
<img src={coverImage} alt="cover" className="w-full max-h-[250px] object-cover rounded-md" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="editorjs"
|
||||
className="border rounded-md p-4 bg-white min-h-[300px]"
|
||||
/>
|
||||
<div id="editorjs" className="border rounded-md p-4 bg-white min-h-[300px]" />
|
||||
|
||||
<Button onClick={handleSave} disabled={loading}>
|
||||
{loading ? "Saving..." : "Save Blog"}
|
||||
{loading ? 'Saving...' : 'Save Blog'}
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user