diff --git a/frontend/src/components/optionList/WritingVoteOptionList/WritingVoteOption/WritingVoteOption.stories.tsx b/frontend/src/components/optionList/WritingVoteOptionList/WritingVoteOption/WritingVoteOption.stories.tsx index 5cfda953e..56df6f123 100644 --- a/frontend/src/components/optionList/WritingVoteOptionList/WritingVoteOption/WritingVoteOption.stories.tsx +++ b/frontend/src/components/optionList/WritingVoteOptionList/WritingVoteOption/WritingVoteOption.stories.tsx @@ -21,6 +21,7 @@ export const IsDeletable = () => { handleDeleteOptionClick={() => {}} handleRemoveImageClick={() => {}} handleUploadImage={() => {}} + handlePasteImage={() => {}} optionId={Math.floor(Math.random() * 100000)} text="방학 때 강릉으로 강아지와 기차여행을 하려했지 만 장마가 와서 취소했어요. 여행을 별로 좋" @@ -42,6 +43,7 @@ export const IsNotDeletable = () => { handleDeleteOptionClick={() => {}} handleRemoveImageClick={() => {}} handleUploadImage={() => {}} + handlePasteImage={() => {}} optionId={Math.floor(Math.random() * 100000)} text="방학 때 강릉으로 강아지와 기차여행을 하려했지 만 장마가 와서 취소했어요. 여행을 별로 좋" @@ -62,6 +64,7 @@ export const ShowImage = () => { handleDeleteOptionClick={() => {}} handleRemoveImageClick={() => {}} handleUploadImage={() => {}} + handlePasteImage={() => {}} optionId={Math.floor(Math.random() * 100000)} text="방학 때 강릉으로 강아지와 기차여행을 하려했지 만 장마가 와서 취소했어요. 여행을 별로 좋" diff --git a/frontend/src/components/optionList/WritingVoteOptionList/WritingVoteOption/index.tsx b/frontend/src/components/optionList/WritingVoteOptionList/WritingVoteOption/index.tsx index ddd51bfb7..248a7de61 100644 --- a/frontend/src/components/optionList/WritingVoteOptionList/WritingVoteOption/index.tsx +++ b/frontend/src/components/optionList/WritingVoteOptionList/WritingVoteOption/index.tsx @@ -1,5 +1,6 @@ -import { ChangeEvent, MutableRefObject } from 'react'; +import { ChangeEvent, ClipboardEvent, MutableRefObject } from 'react'; +import { POST_WRITING_OPTION } from '@constants/policy'; import { POST_OPTION_POLICY } from '@constants/policyMessage'; import OptionCancelButton from './OptionCancelButton'; @@ -11,17 +12,16 @@ interface WritingVoteOptionProps { text: string; isDeletable: boolean; ariaLabel: string; - handleUpdateOptionChange: (event: ChangeEvent) => void; + handleUpdateOptionChange: (event: ChangeEvent) => void; handleDeleteOptionClick: () => void; handleRemoveImageClick: () => void; handleUploadImage: (event: ChangeEvent) => void; + handlePasteImage: (event: ClipboardEvent) => void; imageUrl: string; contentInputRefList: MutableRefObject; index: number; } -const MAX_WRITING_LENGTH = 50; - export default function WritingVoteOption({ optionId, text, @@ -31,6 +31,7 @@ export default function WritingVoteOption({ handleDeleteOptionClick, handleRemoveImageClick, handleUploadImage, + handlePasteImage, imageUrl, contentInputRefList, index, @@ -47,9 +48,10 @@ export default function WritingVoteOption({ ) => handleUpdateOptionChange(e)} + onChange={handleUpdateOptionChange} + onPaste={handlePasteImage} placeholder={POST_OPTION_POLICY.DEFAULT} - maxLength={MAX_WRITING_LENGTH} + maxLength={POST_WRITING_OPTION.MAX_LENGTH} /> void; handleUploadImage: (event: ChangeEvent, optionId: number) => void; contentInputRefList: MutableRefObject; + handlePasteImage: (event: ClipboardEvent, optionId: number) => void; }; } @@ -33,6 +34,7 @@ export default function WritingVoteOptionList({ writingOptionHook }: WritingVote removeImage, handleUploadImage, contentInputRefList, + handlePasteImage, } = writingOptionHook; const isDeletable = optionList.length > MINIMUM_COUNT; @@ -53,6 +55,9 @@ export default function WritingVoteOptionList({ writingOptionHook }: WritingVote } imageUrl={optionItem.imageUrl} contentInputRefList={contentInputRefList} + handlePasteImage={(event: ClipboardEvent) => + handlePasteImage(event, optionItem.id) + } index={index} /> ))} diff --git a/frontend/src/hooks/useWritingOption.tsx b/frontend/src/hooks/useWritingOption.tsx index 1ada14770..a73246436 100644 --- a/frontend/src/hooks/useWritingOption.tsx +++ b/frontend/src/hooks/useWritingOption.tsx @@ -1,4 +1,4 @@ -import React, { ChangeEvent, useRef, useState } from 'react'; +import React, { ChangeEvent, ClipboardEvent, useRef, useState } from 'react'; import { POST_WRITING_OPTION } from '@constants/policy'; @@ -68,6 +68,24 @@ export const useWritingOption = (initialOptionList?: WritingVoteOptionType[]) => setOptionList(removedOptionList); }; + const handlePasteImage = (event: ClipboardEvent, optionId: number) => { + const file = event.clipboardData.files[0]; + + if (!file) return; + + if (file.type.slice(0, 5) === 'image') { + event.preventDefault(); + + const optionIndex = optionList.findIndex(option => option.id === optionId); + + uploadImage({ + imageFile: file, + inputElement: contentInputRefList.current[optionIndex], + setPreviewImageUrl: setPreviewImageUrl(optionId), + }); + } + }; + const removeImage = (optionId: number) => { const updatedOptionList = optionList.map(optionItem => { if (optionItem.id === optionId) { @@ -121,5 +139,6 @@ export const useWritingOption = (initialOptionList?: WritingVoteOptionType[]) => removeImage, handleUploadImage, contentInputRefList, + handlePasteImage, }; };