diff --git a/src/components/common/quillEditor/QuillEditor.tsx b/src/components/common/quillEditor/QuillEditor.tsx new file mode 100644 index 00000000..68f29e89 --- /dev/null +++ b/src/components/common/quillEditor/QuillEditor.tsx @@ -0,0 +1,38 @@ +import { forwardRef } from 'react'; +import { QuillToolbar } from '../../my-page/portfolio/QuillToolbar'; +import ReactQuill from 'react-quill-new'; +import 'react-quill-new/dist/quill.snow.css'; + +interface QuillEditorPropsType { + className: string; + onChangeHandler: (content: string) => void; + id?: string; + value?: string; + placeholder?: string; +} + +const QuillEditor = forwardRef( + ({ className, onChangeHandler, id, value, placeholder, ...rest }, ref) => { + const modules = { + toolbar: { container: '#toolbar' }, + }; + return ( +
+ + +
+ ); + }, +); + +QuillEditor.displayName = 'QuillEditor'; +export default QuillEditor; diff --git a/src/components/my-page/edit/ContentEditor.tsx b/src/components/my-page/edit/ContentEditor.tsx index d5ec34b3..5e389c06 100644 --- a/src/components/my-page/edit/ContentEditor.tsx +++ b/src/components/my-page/edit/ContentEditor.tsx @@ -1,6 +1,8 @@ -import React from 'react'; +import React, { lazy } from 'react'; + import ReactQuill from 'react-quill-new'; import styles from '../../../pages/idea-market/ideaMarketRegister.module.scss'; +const QuillEditor = lazy(() => import('../../common/quillEditor/QuillEditor')); interface ContentEditorProps { value: string; @@ -14,8 +16,6 @@ export const ContentEditor = ({ value, onChange, quillRef, - modules, - formats, }: ContentEditorProps) => { return (
@@ -24,15 +24,12 @@ export const ContentEditor = ({ className={styles.visuallyHidden}> 아이디어 내용 -
diff --git a/src/components/my-page/portfolio/AddPortfolioModal.tsx b/src/components/my-page/portfolio/AddPortfolioModal.tsx index 3547f68f..c1b3dfdb 100644 --- a/src/components/my-page/portfolio/AddPortfolioModal.tsx +++ b/src/components/my-page/portfolio/AddPortfolioModal.tsx @@ -1,16 +1,21 @@ -import { ChangeEvent, forwardRef, useContext, useRef, useState } from 'react'; +import { + ChangeEvent, + forwardRef, + lazy, + useContext, + useRef, + useState, +} from 'react'; import classNames from 'classnames'; import styles from './addPortfolioModal.module.scss'; import ReactQuill from 'react-quill-new'; -import { QuillToolbar } from './QuillToolbar'; import { FieldValues, useForm, Controller } from 'react-hook-form'; import axios from 'axios'; import { v4 as uuidv4 } from 'uuid'; import ImageInput from '../../../assets/icons/imageInput.svg?react'; import { Dropdown } from '../../common/dropdown/Dropdown'; -import 'react-quill-new/dist/quill.snow.css'; -import '../../../styles/quillStyles.css'; + import { CATEGORY_MAPPER_TO_ENG } from '../../../constants/categoryMapper'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { PostPortfolioPayload } from '../../../types/myPageType'; @@ -20,6 +25,8 @@ import { ToastContext } from '../../../contexts/toastContext'; import { formatBirth } from '../../../utils/formatBirth'; import { Image } from '../../common/image/Image'; +const QuillEditor = lazy(() => import('../../common/quillEditor/QuillEditor')); + interface AddPortfolioModalPropsType { onClose: () => void; } @@ -28,9 +35,6 @@ export const AddPortfolioModal = forwardRef< HTMLDivElement, AddPortfolioModalPropsType >(({ onClose }, ref) => { - const modules = { - toolbar: { container: '#toolbar' }, - }; const { errorToast, successToast } = useContext(ToastContext); const IMAGE_BASE_URL = import.meta.env.VITE_S3_URL; const queryClient = useQueryClient(); @@ -172,18 +176,15 @@ export const AddPortfolioModal = forwardRef<
포트폴리오 내용
- ( - field.onChange(content)} + onChangeHandler={(content: string) => field.onChange(content)} /> )} /> diff --git a/src/components/my-page/portfolio/PortfolioDetailModal.tsx b/src/components/my-page/portfolio/PortfolioDetailModal.tsx index 85049213..f0216957 100644 --- a/src/components/my-page/portfolio/PortfolioDetailModal.tsx +++ b/src/components/my-page/portfolio/PortfolioDetailModal.tsx @@ -1,6 +1,7 @@ import { ChangeEvent, forwardRef, + lazy, useContext, useEffect, useRef, @@ -27,7 +28,6 @@ import { CATEGORY_MAPPER_TO_ENG, } from '../../../constants/categoryMapper'; import ImageInput from '../../../assets/icons/imageInput.svg?react'; -import { QuillToolbar } from './QuillToolbar'; import { Dropdown } from '../../common/dropdown/Dropdown'; import { PORTFOLIO_DETAIL_INIT } from '../../../constants/initValues'; import { getPresignedURL } from '../../../apis/commonAPI'; @@ -35,6 +35,7 @@ import axios from 'axios'; import { ToastContext } from '../../../contexts/toastContext'; import { DeleteCheckModal } from './DeleteCheckModal'; import { Image } from '../../common/image/Image'; +const QuillEditor = lazy(() => import('../../common/quillEditor/QuillEditor')); interface PortfolioDetailModalPropsType { onClose: () => void; @@ -46,9 +47,6 @@ export const PortfolioDetailModal = forwardRef< HTMLDivElement, PortfolioDetailModalPropsType >(({ onClose, cardId, editable = true }, ref) => { - const modules = { - toolbar: { container: '#toolbar' }, - }; const quillRef = useRef(null); const { errorToast, successToast } = useContext(ToastContext); const IMAGE_BASE_URL = import.meta.env.VITE_S3_URL; @@ -253,18 +251,18 @@ export const PortfolioDetailModal = forwardRef< 포트폴리오 내용
- ( - field.onChange(content)} + onChangeHandler={(content: string) => + field.onChange(content) + } /> )} /> diff --git a/src/pages/collaboration/CollaborationRegister.tsx b/src/pages/collaboration/CollaborationRegister.tsx index 49b2389b..23f74cc3 100644 --- a/src/pages/collaboration/CollaborationRegister.tsx +++ b/src/pages/collaboration/CollaborationRegister.tsx @@ -1,7 +1,6 @@ -import React, { useState, useRef, useEffect, useMemo } from 'react'; +import React, { useState, useRef, useEffect, lazy } from 'react'; import ReactQuill from 'react-quill-new'; import { useNavigate } from 'react-router-dom'; -import 'react-quill-new/dist/quill.snow.css'; import styles from './collaborationRegister.module.scss'; import MainImage from '../../assets/icons/mainImage.svg?react'; import DownButton from '../../assets/icons/categoryDownButton.svg?react'; @@ -10,6 +9,9 @@ import CheckButton from '../../assets/icons/checkButton.svg?react'; import DisabledCheckButton from '../../assets/icons/disabledCheckButton.svg?react'; import { Image } from '../../components/common/image/Image'; import { ConfirmModal } from '../../components/common/modal/ConfirmModal'; +const QuillEditor = lazy( + () => import('../../components/common/quillEditor/QuillEditor'), +); interface CollaborationRequestData { title: string; @@ -78,8 +80,6 @@ const visibilityToEnum: Record = { 비공개: 'ME', }; -const MAX_FILE_SIZE = 5 * 1024 * 1024; - const BASE_URL = import.meta.env.VITE_BASE_URL; import { MetaTag } from '../../seoMetaTag'; @@ -394,47 +394,6 @@ const CollaborationRegister = () => { }; }, [previewImageUrl]); - const modules = useMemo(() => { - return { - toolbar: { - container: [ - [{ font: [] }, { size: [] }, { align: [] }], - ['link', 'image'], - ], - handlers: { - image: () => { - const input = document.createElement('input'); - input.setAttribute('type', 'file'); - input.setAttribute('accept', 'image/*'); - input.click(); - - input.onchange = async () => { - const file = input.files?.[0]; - if (file) { - if (file.size > MAX_FILE_SIZE) { - alert('이미지 파일 크기는 5MB를 초과할 수 없습니다.'); - return; - } - - const reader = new FileReader(); - reader.onload = () => { - const quill = quillRef.current?.getEditor(); - if (quill) { - const range = quill.getSelection(true); - quill.insertEmbed(range.index, 'image', reader.result); - } - }; - reader.readAsDataURL(file); - } - }; - }, - }, - }, - }; - }, []); - - const formats = ['font', 'size', 'align', 'link', 'image']; - return ( <> { className={styles.visuallyHidden}> 아이디어 내용 -
diff --git a/src/pages/idea-market/IdeaMarketRegister.tsx b/src/pages/idea-market/IdeaMarketRegister.tsx index 75de9082..68b06c15 100644 --- a/src/pages/idea-market/IdeaMarketRegister.tsx +++ b/src/pages/idea-market/IdeaMarketRegister.tsx @@ -1,7 +1,6 @@ -import React, { useState, useRef, useEffect, useMemo } from 'react'; +import React, { useState, useRef, useEffect, lazy } from 'react'; import ReactQuill from 'react-quill-new'; import { useNavigate, useLocation } from 'react-router-dom'; -import 'react-quill-new/dist/quill.snow.css'; import styles from './ideaMarketRegister.module.scss'; import MainImage from '../../assets/icons/mainImage.svg?react'; import DownButton from '../../assets/icons/categoryDownButton.svg?react'; @@ -13,6 +12,10 @@ import InfoDropdown from '../../assets/icons/infoDropdown.svg?react'; import { Image } from '../../components/common/image/Image'; import { MetaTag } from '../../seoMetaTag'; +const QuillEditor = lazy( + () => import('../../components/common/quillEditor/QuillEditor'), +); + interface IdeaMarketRequestData { title: string; content: string; @@ -76,8 +79,6 @@ const pageTypeToEnum: Record = { 'Market Place': 'MARKET_PLACE', }; -const MAX_FILE_SIZE = 5 * 1024 * 1024; - const BASE_URL = import.meta.env.VITE_BASE_URL; const OPTIONS = [ @@ -332,46 +333,44 @@ const IdeaMarketRegister = () => { }; }, [previewImageUrl]); - const modules = useMemo(() => { - return { - toolbar: { - container: [ - [{ font: [] }, { size: [] }, { align: [] }], - ['link', 'image'], - ], - handlers: { - image: () => { - const input = document.createElement('input'); - input.setAttribute('type', 'file'); - input.setAttribute('accept', 'image/*'); - input.click(); - - input.onchange = async () => { - const file = input.files?.[0]; - if (file) { - if (file.size > MAX_FILE_SIZE) { - alert('이미지 파일 크기는 5MB를 초과할 수 없습니다.'); - return; - } - - const reader = new FileReader(); - reader.onload = () => { - const quill = quillRef.current?.getEditor(); - if (quill) { - const range = quill.getSelection(true); - quill.insertEmbed(range.index, 'image', reader.result); - } - }; - reader.readAsDataURL(file); - } - }; - }, - }, - }, - }; - }, []); - - const formats = ['font', 'size', 'align', 'link', 'image']; + // const modules = useMemo(() => { + // return { + // toolbar: { + // container: [ + // [{ font: [] }, { size: [] }, { align: [] }], + // ['link', 'image'], + // ], + // handlers: { + // image: () => { + // const input = document.createElement('input'); + // input.setAttribute('type', 'file'); + // input.setAttribute('accept', 'image/*'); + // input.click(); + + // input.onchange = async () => { + // const file = input.files?.[0]; + // if (file) { + // if (file.size > MAX_FILE_SIZE) { + // alert('이미지 파일 크기는 5MB를 초과할 수 없습니다.'); + // return; + // } + + // const reader = new FileReader(); + // reader.onload = () => { + // const quill = quillRef.current?.getEditor(); + // if (quill) { + // const range = quill.getSelection(true); + // quill.insertEmbed(range.index, 'image', reader.result); + // } + // }; + // reader.readAsDataURL(file); + // } + // }; + // }, + // }, + // }, + // }; + // }, []); return ( <> @@ -545,15 +544,12 @@ const IdeaMarketRegister = () => { className={styles.visuallyHidden}> 아이디어 내용 -
diff --git a/src/pages/request-assign/RequestAssignRegister.tsx b/src/pages/request-assign/RequestAssignRegister.tsx index a76bab8a..28be78f1 100644 --- a/src/pages/request-assign/RequestAssignRegister.tsx +++ b/src/pages/request-assign/RequestAssignRegister.tsx @@ -1,7 +1,5 @@ -import React, { useState, useRef, useEffect, useMemo } from 'react'; -import ReactQuill from 'react-quill-new'; +import React, { useState, useRef, useEffect, lazy } from 'react'; import { useNavigate, useLocation } from 'react-router-dom'; -import 'react-quill-new/dist/quill.snow.css'; import styles from './requestAssignRegister.module.scss'; import MainImage from '../../assets/icons/mainImage.svg?react'; import DownButton from '../../assets/icons/categoryDownButton.svg?react'; @@ -11,6 +9,11 @@ import DisabledCheckButton from '../../assets/icons/disabledCheckButton.svg?reac import InfoDropdown from '../../assets/icons/infoDropdown.svg?react'; import { Image } from '../../components/common/image/Image'; import { MetaTag } from '../../seoMetaTag'; +import ReactQuill from 'react-quill-new'; + +const QuillEditor = lazy( + () => import('../../components/common/quillEditor/QuillEditor'), +); interface RequestAssignRequestData { title: string; @@ -89,8 +92,6 @@ const RequestTaskTypeEnumMap: Record = { TECH_ZONE: 'TECH_ZONE', }; -const MAX_FILE_SIZE = 5 * 1024 * 1024; - const BASE_URL = import.meta.env.VITE_BASE_URL; const OPTIONS = [ @@ -380,47 +381,6 @@ const RequestAssignRegisterNow = () => { }; }, [previewImageUrl]); - const modules = useMemo(() => { - return { - toolbar: { - container: [ - [{ font: [] }, { size: [] }, { align: [] }], - ['link', 'image'], - ], - handlers: { - image: () => { - const input = document.createElement('input'); - input.setAttribute('type', 'file'); - input.setAttribute('accept', 'image/*'); - input.click(); - - input.onchange = async () => { - const file = input.files?.[0]; - if (file) { - if (file.size > MAX_FILE_SIZE) { - alert('이미지 파일 크기는 5MB를 초과할 수 없습니다.'); - return; - } - - const reader = new FileReader(); - reader.onload = () => { - const quill = quillRef.current?.getEditor(); - if (quill) { - const range = quill.getSelection(true); - quill.insertEmbed(range.index, 'image', reader.result); - } - }; - reader.readAsDataURL(file); - } - }; - }, - }, - }, - }; - }, []); - - const formats = ['font', 'size', 'align', 'link', 'image']; - return ( <> { className={styles.visuallyHidden}> 아이디어 내용 - diff --git a/src/routes.tsx b/src/routes.tsx index b6373150..3ab53df8 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -4,19 +4,14 @@ import { Layout } from './pages/layout/Layout'; import { MyPageLayout } from './pages/layout/MyPageLayout'; /** 아이디어 마켓 */ -const IdeaMarketMain = lazy(() => import('./pages/idea-market/IdeaMarketMain')); -const IdeaMarketMarketPlace = lazy( - () => import('./pages/idea-market/IdeaMarketMarketPlace'), -); -const IdeaMarketRegister = lazy( - () => import('./pages/idea-market/IdeaMarketRegister'), -); +import IdeaMarketMain from './pages/idea-market/IdeaMarketMain'; +import IdeaMarketMarketPlace from './pages/idea-market/IdeaMarketMarketPlace'; +import IdeaRegisteredPage from './pages/idea-market/IdeaRegisteredPage'; +import IdeaMarketRegister from './pages/idea-market/IdeaMarketRegister'; + const IdeaMarketRegisterComplete = lazy( () => import('./pages/idea-market/IdeaMarketRegisterComplete'), ); -const IdeaRegisteredPage = lazy( - () => import('./pages/idea-market/IdeaRegisteredPage'), -); const IdeaMarketPayment = lazy( () => import('./pages/idea-market/IdeaMarketPayment'), ); @@ -28,78 +23,47 @@ const PaymentCancel = lazy(() => import('./pages/idea-market/PaymentCancel')); const PaymentSuccess = lazy(() => import('./pages/idea-market/PaymentSuccess')); /** 요청 과제 */ -const RequestAssignTechZone = lazy( - () => import('./pages/request-assign/RequestAssignTechZone'), -); +import RequestAssignMain from './pages/request-assign/RequestAssignMain'; +import RequestAssignTechZone from './pages/request-assign/RequestAssignTechZone'; +import RequestRegisteredPage from './pages/request-assign/RequestRegisteredPage'; const RequestAssignRegisterNow = lazy( () => import('./pages/request-assign/RequestAssignRegister'), ); const RequestAssignRegisterComplete = lazy( () => import('./pages/request-assign/RequestAssignRegisterComplete'), ); -const RequestRegisteredPage = lazy( - () => import('./pages/request-assign/RequestRegisteredPage'), -); -const RequestAssignMain = lazy( - () => import('./pages/request-assign/RequestAssignMain'), -); /** 협업 광장 */ -const CollaborationMain = lazy( - () => import('./pages/collaboration/CollaborationMain'), -); -const PostDetailWithLink = lazy( - () => import('./pages/collaboration/PostDetailWithLink'), -); -const CollaborationRegister = lazy( - () => import('./pages/collaboration/CollaborationRegister'), -); +import CollaborationMain from './pages/collaboration/CollaborationMain'; +import PostDetailWithLink from './pages/collaboration/PostDetailWithLink'; +import CollaborationRegister from './pages/collaboration/CollaborationRegister'; /** 마이페이지 */ -const PostsIdeaMarket = lazy( - () => import('./pages/my-page/postsIdeaMarket/PostsIdeaMarket'), -); -const Info = lazy(() => import('./pages/my-page/info/Info')); -const MyPage = lazy(() => import('./pages/my-page/myPage/MyPage')); -const RecentNews = lazy(() => import('./pages/my-page/myPage/RecentNews')); -const MyPagePosts = lazy( - () => import('./pages/my-page/myPagePosts/MyPagePosts'), -); -const PostsRequestAssign = lazy( - () => import('./pages/my-page/postsRequestAssign/PostsRequestAssign'), -); -const PostsCollaboration = lazy( - () => import('./pages/my-page/postsCollaboration/PostsCollaboration'), -); -const IdeaMarketRegistered = lazy( - () => import('./pages/my-page/postsIdeaMarket/IdeaMarketRegistered'), -); -const RequestAssignRegistered = lazy( - () => import('./pages/my-page/postsRequestAssign/RequestAssignRegistered'), -); -const CollaborationRegistered = lazy( - () => import('./pages/my-page/postsCollaboration/CollaborationRegistered'), -); -const IdeaMarketEdit = lazy( - () => import('./pages/my-page/postsIdeaMarket/IdeaMarketEdit'), -); -const PurchaseList = lazy(() => import('./pages/my-page/apply/PurchaseList')); -const ApplyRequest = lazy(() => import('./pages/my-page/apply/ApplyRequest')); -const ApplyCollaboration = lazy( - () => import('./pages/my-page/apply/ApplyCollaboration'), -); -const Portfolio = lazy(() => import('./pages/my-page/portfolio/Portfolio')); -const Message = lazy(() => import('./pages/my-page/message/Message')); -const SavedPosts = lazy(() => import('./pages/my-page/saved-posts/SavedPosts')); +import PostsIdeaMarket from './pages/my-page/postsIdeaMarket/PostsIdeaMarket'; +import Info from './pages/my-page/info/Info'; +import MyPage from './pages/my-page/myPage/MyPage'; +import RecentNews from './pages/my-page/myPage/RecentNews'; +import MyPagePosts from './pages/my-page/myPagePosts/MyPagePosts'; +import PostsRequestAssign from './pages/my-page/postsRequestAssign/PostsRequestAssign'; +import PostsCollaboration from './pages/my-page/postsCollaboration/PostsCollaboration'; +import IdeaMarketRegistered from './pages/my-page/postsIdeaMarket/IdeaMarketRegistered'; +import RequestAssignRegistered from './pages/my-page/postsRequestAssign/RequestAssignRegistered'; +import CollaborationRegistered from './pages/my-page/postsCollaboration/CollaborationRegistered'; +import IdeaMarketEdit from './pages/my-page/postsIdeaMarket/IdeaMarketEdit'; +import PurchaseList from './pages/my-page/apply/PurchaseList'; +import ApplyRequest from './pages/my-page/apply/ApplyRequest'; +import ApplyCollaboration from './pages/my-page/apply/ApplyCollaboration'; +import Portfolio from './pages/my-page/portfolio/Portfolio'; +import Message from './pages/my-page/message/Message'; +import SavedPosts from './pages/my-page/saved-posts/SavedPosts'; /** */ -const PersonalProfile = lazy( - () => import('./pages/personal-profile/PersonalProfile'), -); +import ErrorPage from './pages/errorPage/ErrorPage'; +import PersonalProfile from './pages/personal-profile/PersonalProfile'; + const Main = lazy(() => import('./pages/main/main')); const Signup = lazy(() => import('./pages/sign-up/Signup')); const Login = lazy(() => import('./pages/login/Login')); -const ErrorPage = lazy(() => import('./pages/errorPage/ErrorPage')); export const routes = createBrowserRouter([ { diff --git a/stats.html b/stats.html index f21a6432..b1d6c8aa 100644 --- a/stats.html +++ b/stats.html @@ -4929,7 +4929,7 @@