Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/components/common/quillEditor/QuillEditor.tsx
Original file line number Diff line number Diff line change
@@ -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<ReactQuill, QuillEditorPropsType>(
({ className, onChangeHandler, id, value, placeholder, ...rest }, ref) => {
const modules = {
toolbar: { container: '#toolbar' },
};
return (
<div>
<QuillToolbar />
<ReactQuill
modules={modules}
placeholder={placeholder || '내용을 입력하세요'}
onChange={onChangeHandler}
id={id}
value={value}
ref={ref}
{...rest}
className={className}
/>
</div>
);
},
);

QuillEditor.displayName = 'QuillEditor';
export default QuillEditor;
13 changes: 5 additions & 8 deletions src/components/my-page/edit/ContentEditor.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -14,8 +16,6 @@ export const ContentEditor = ({
value,
onChange,
quillRef,
modules,
formats,
}: ContentEditorProps) => {
return (
<div className={styles.formGroup}>
Expand All @@ -24,15 +24,12 @@ export const ContentEditor = ({
className={styles.visuallyHidden}>
아이디어 내용
</label>
<ReactQuill
<QuillEditor
ref={quillRef}
id='editor'
value={value}
onChange={onChange}
onChangeHandler={onChange}
className={styles.editor}
theme='snow'
modules={modules}
formats={formats}
placeholder='아이디어 내용을 입력하세요. (필수)'
/>
</div>
Expand Down
25 changes: 13 additions & 12 deletions src/components/my-page/portfolio/AddPortfolioModal.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;
}
Expand All @@ -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();
Expand Down Expand Up @@ -172,18 +176,15 @@ export const AddPortfolioModal = forwardRef<
<div>
<div className={classNames(styles.inputTitle)}>포트폴리오 내용</div>
<div className={classNames(styles.contentInputWrapper)}>
<QuillToolbar />
<Controller
name='content'
control={control}
render={({ field }) => (
<ReactQuill
<QuillEditor
{...field}
ref={quillRef}
modules={modules}
className={classNames(styles.textInput)}
placeholder='내용을 입력하세요'
onChange={(content: string) => field.onChange(content)}
onChangeHandler={(content: string) => field.onChange(content)}
/>
)}
/>
Expand Down
14 changes: 6 additions & 8 deletions src/components/my-page/portfolio/PortfolioDetailModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ChangeEvent,
forwardRef,
lazy,
useContext,
useEffect,
useRef,
Expand All @@ -27,14 +28,14 @@ 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';
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;
Expand All @@ -46,9 +47,6 @@ export const PortfolioDetailModal = forwardRef<
HTMLDivElement,
PortfolioDetailModalPropsType
>(({ onClose, cardId, editable = true }, ref) => {
const modules = {
toolbar: { container: '#toolbar' },
};
const quillRef = useRef<ReactQuill>(null);
const { errorToast, successToast } = useContext(ToastContext);
const IMAGE_BASE_URL = import.meta.env.VITE_S3_URL;
Expand Down Expand Up @@ -253,18 +251,18 @@ export const PortfolioDetailModal = forwardRef<
포트폴리오 내용
</div>
<div className={classNames(styles.contentInputWrapper)}>
<QuillToolbar />
<Controller
name='content'
control={control}
render={({ field }) => (
<ReactQuill
<QuillEditor
{...field}
ref={quillRef}
modules={modules}
className={classNames(styles.textInput)}
placeholder='내용을 입력하세요'
onChange={(content: string) => field.onChange(content)}
onChangeHandler={(content: string) =>
field.onChange(content)
}
/>
)}
/>
Expand Down
56 changes: 6 additions & 50 deletions src/pages/collaboration/CollaborationRegister.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;
Expand Down Expand Up @@ -78,8 +80,6 @@ const visibilityToEnum: Record<string, PostAuth> = {
비공개: 'ME',
};

const MAX_FILE_SIZE = 5 * 1024 * 1024;

const BASE_URL = import.meta.env.VITE_BASE_URL;
import { MetaTag } from '../../seoMetaTag';

Expand Down Expand Up @@ -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 (
<>
<MetaTag
Expand Down Expand Up @@ -540,15 +499,12 @@ const CollaborationRegister = () => {
className={styles.visuallyHidden}>
아이디어 내용
</label>
<ReactQuill
<QuillEditor
ref={quillRef}
id='editor'
value={content}
onChange={setContent}
onChangeHandler={setContent}
className={styles.editor}
theme='snow'
modules={modules}
formats={formats}
placeholder='아이디어 내용을 입력하세요. (필수)'
/>
</div>
Expand Down
Loading