Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[비즈니스] 이벤트, 메뉴 관련 이슈 수정 #332

Merged
merged 6 commits into from
May 10, 2024
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
33 changes: 19 additions & 14 deletions src/page/AddMenu/components/AddMenuImgModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,40 @@ import { createPortal } from 'react-dom';
import { ReactComponent as CancelIcon } from 'assets/svg/addmenu/mobile-cancle-icon.svg';
import useAddMenuStore from 'store/addMenu';
import ErrorMessage from 'page/Auth/Signup/component/ErrorMessage';
import { ERRORMESSAGE } from 'page/ShopRegistration/constant/errorMessage'; import useImagesUpload from 'utils/hooks/useImagesUpload';
import { ERRORMESSAGE } from 'page/ShopRegistration/constant/errorMessage';
import { UploadError } from 'utils/hooks/useImagesUpload';
import styles from './AddMenuImgModal.module.scss';

interface AddMenuImgModalProps {
isOpen: boolean;
closeModal: (event?: React.MouseEvent | React.KeyboardEvent) => void;
imageObject: {
imageFile: string[];
imgRef: React.RefObject<HTMLInputElement>;
saveImgFile: () => Promise<void>;
uploadError: UploadError;
setImageFile: React.Dispatch<React.SetStateAction<string[]>>;
}
}

export default function AddMenuImgModal({ isOpen, closeModal }: AddMenuImgModalProps) {
export default function AddMenuImgModal({ isOpen, closeModal, imageObject }: AddMenuImgModalProps) {
const { setImageUrls } = useAddMenuStore();

const {
imageFile, imgRef, saveImgFile, uploadError,
} = useImagesUpload();

const triggerFileInput = () => {
imgRef.current?.click();
imageObject.imgRef.current?.click();
};
const handleImageChange = async () => {
await saveImgFile();
await imageObject.saveImgFile();
};
const triggerCameraInput = () => {
imgRef.current?.click();
imageObject.imgRef.current?.click();
};
useEffect(() => {
if (imageFile && !uploadError) {
setImageUrls(imageFile);
if (imageObject.imageFile && !imageObject.uploadError) {
setImageUrls(imageObject.imageFile);
closeModal();
}
}, [imageFile, uploadError, setImageUrls, closeModal]);
}, [imageObject.imageFile, imageObject.uploadError, setImageUrls, closeModal]);

if (!isOpen) return null;

Expand All @@ -45,12 +49,13 @@ export default function AddMenuImgModal({ isOpen, closeModal }: AddMenuImgModalP
<span className={styles['content__main-text']}>이미지 추가</span>
<span className={styles['content__sub-text']}>메뉴 사진을 추가할 수 있습니다.</span>
<div className={styles['content__button-container']}>
<input type="file" accept="image/*" style={{ display: 'none' }} onChange={handleImageChange} ref={imgRef} multiple />
<input type="file" accept="image/*" style={{ display: 'none' }} onChange={handleImageChange} ref={imageObject.imgRef} multiple />
<button type="button" className={styles['content__album-button']} onClick={triggerFileInput}>사진 앨범</button>
<button type="button" className={styles['content__camera-button']} onClick={triggerCameraInput}>카메라 촬영</button>
</div>
<div className={styles['content__image-error-message']}>
{uploadError && <ErrorMessage message={ERRORMESSAGE[uploadError]} />}
{imageObject.uploadError
&& <ErrorMessage message={ERRORMESSAGE[imageObject.uploadError]} />}
</div>
</div>
</div>,
Expand Down
25 changes: 16 additions & 9 deletions src/page/AddMenu/components/MenuImage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,23 @@ export default function MenuImage({ isComplete }: MenuImageProps) {
} = useBooleanState(false);

const {
imageFile, imgRef, saveImgFile, uploadError,
imageFile, imgRef, saveImgFile, uploadError, setImageFile,
} = useImagesUpload();
const imageObject = {
imageFile, imgRef, saveImgFile, uploadError, setImageFile,
}; // AddMenuImgModal에 넘길 props
Comment on lines -27 to +31
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구두) 요렇게하면 새로운 객체를 만드는 게 아닌, 필요한 값을 꺼내쓴 느낌을 줄 수 있을거로 보여용. 타입도 안정적이구요

const imageObject = useImagesUpload();
const { imageFile, ... } = imageObject;

const handleAddImage = () => {
imgRef.current?.click();
};
const handleDeleteImage = (image: string) => {
removeImageUrl(image);
setImageFile(imageFile.filter((img) => img !== image)); // pc 버전 이미지 동기화
};

const handleImageChange = async () => {
await saveImgFile();
};

useEffect(() => {
if (imageFile) {
setImageUrls(imageFile);
Expand All @@ -50,14 +56,14 @@ export default function MenuImage({ isComplete }: MenuImageProps) {
</div>
<div className={styles['mobile__new-image__container']}>
{!isComplete && (
<button
type="button"
className={styles['mobile__new-image__add-btn']}
onClick={openAddMenuImgModal}
>
<ImgPlusIcon className={styles['mobile__new-image__plusIcon']} />
<div className={styles['mobile__new-image__add-caption']}>이미지 추가</div>
</button>
<button
type="button"
className={styles['mobile__new-image__add-btn']}
onClick={openAddMenuImgModal}
>
<ImgPlusIcon className={styles['mobile__new-image__plusIcon']} />
<div className={styles['mobile__new-image__add-caption']}>이미지 추가</div>
</button>
)}
{imageUrl.map((image, index) => (
<div key={image} className={styles['mobile__new-image__item']}>
Expand All @@ -78,6 +84,7 @@ export default function MenuImage({ isComplete }: MenuImageProps) {
<AddMenuImgModal
isOpen={isAddMenuImgModal}
closeModal={closeAddMenuImgModal}
imageObject={imageObject}
/>
</div>
) : (
Expand Down
44 changes: 28 additions & 16 deletions src/page/ManageEvent/AddingEvent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useState } from 'react';
import ReactQuill from 'react-quill';
import 'react-quill/dist/quill.snow.css';
import { useAddEvent } from 'query/event';
import { useNavigate, useParams } from 'react-router-dom';
Expand Down Expand Up @@ -97,17 +96,25 @@ export const initialError = {
export default function AddingEvent() {
const [eventInfo, setEventInfo] = useState<EventInfo>(initialState);
const [error, setError] = useState(initialError);
const [editor, setEditor] = useState('');
const [isAlertModalOpen, setIsAlertModalOpen] = useState(false);
const param = useParams();

const { mutate: addEvent, isPending } = useAddEvent(param.id!);
const navigate = useNavigate();

const changeInput = (e: React.ChangeEvent<HTMLInputElement>, type: 'title' | 'start' | 'end', change?: Change) => {
const changeInput = (
e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>,
type: 'title' | 'start' | 'end' | 'content',
change?: Change,
) => {
const value = e.target.value.replaceAll(/[\D]/gi, '');
if (type === 'title' && e.target.value.length <= 25) {
setEventInfo({ ...eventInfo, title: e.target.value });
setError({ ...error, title: false });
}
if (type === 'content' && e.target.value.length <= 500) {
setEventInfo({ ...eventInfo, content: e.target.value });
setError({ ...error, content: false });
}
if (type === 'start') {
if (change === 'year' && e.target.value.length <= 4) {
Expand All @@ -116,6 +123,7 @@ export default function AddingEvent() {
if (change !== 'year' && e.target.value.length <= 2) {
setEventInfo({ ...eventInfo, start_date: { ...eventInfo.start_date, [change!]: value } });
}
setError({ ...error, date: false });
}
if (type === 'end') {
if (change === 'year' && e.target.value.length <= 4) {
Expand All @@ -124,8 +132,8 @@ export default function AddingEvent() {
if (change !== 'year' && e.target.value.length <= 2) {
setEventInfo({ ...eventInfo, end_date: { ...eventInfo.end_date, [change!]: value } });
}
setError({ ...error, date: false });
}
setError({ ...error, title: false });
};

const validation = () => {
Expand All @@ -134,7 +142,7 @@ export default function AddingEvent() {
setError((prevError) => ({ ...prevError, title: true }));
flag = true;
}
if (editor.length === 0) {
if (eventInfo.content.length === 0) {
setError((prevError) => ({ ...prevError, content: true }));
flag = true;
}
Expand Down Expand Up @@ -185,7 +193,7 @@ export default function AddingEvent() {

const requestData = {
title: eventInfo.title,
content: editor,
content: eventInfo.content,
start_date: startDate,
end_date: endDate,
thumbnail_images: eventInfo.thumbnail_image,
Expand Down Expand Up @@ -292,21 +300,25 @@ export default function AddingEvent() {
<div>
<div className={styles.event__divide}>
<p className={styles.event__paragraph}>이벤트/공지 내용</p>
<small className={styles.event__count} />
<small className={
cn({
[styles.event__count]: true,
[styles['event__count--full']]: eventInfo.content.length === 500,
})
}
>
{`${eventInfo.content.length} / 500`}
</small>
</div>
<div>
<ReactQuill
theme="snow"
value={editor}
onChange={(e) => {
setError({ ...error, content: false });
return setEditor(e);
}}
modules={modules}
placeholder="이벤트/공지 내용을 입력해 주세요."
<textarea
value={eventInfo.content}
placeholder="이벤트 내용을 입력해주세요"
className={cn({
[styles['error-border']]: error.content,
[styles.event__content]: true,
})}
onChange={(e) => changeInput(e, 'content')}
/>
</div>
{error.content && <div className={styles['error-message']}>필수 입력 항목입니다.</div>}
Expand Down
60 changes: 41 additions & 19 deletions src/page/ManageEvent/ModifyEvent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useLocation, useNavigate } from 'react-router-dom';
import { useState } from 'react';
import {
initialError, EventInfo, modules, uploadImage, Change, validateDate,
initialError, EventInfo, uploadImage, Change, validateDate,
} from 'page/ManageEvent/AddingEvent/index';
import AlertModal from 'component/common/Modal/alertModal';
import ReactQuill from 'react-quill';
import showToast from 'utils/ts/showToast';
import { getCoopUrl } from 'api/uploadFile';
import { ReactComponent as Delete } from 'assets/svg/myshop/delete.svg';
Expand Down Expand Up @@ -51,24 +50,43 @@ export default function ModifyEvent() {

const [eventInfo, setEventInfo] = useState<EventInfo>(initialState);
const [error, setError] = useState(initialError);
const [editor, setEditor] = useState(event.content);
const [isAlertModalOpen, setIsAlertModalOpen] = useState(false);

const { mutate: modifyEvent, isPending } = useModifyEvent(event.shop_id, event.event_id);
const navigate = useNavigate();

const changeInput = (e: React.ChangeEvent<HTMLInputElement>, type: 'title' | 'start' | 'end', change?: Change) => {
const changeInput = (
e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>,
type: 'title' | 'start' | 'end' | 'content',
change?: Change,
) => {
const value = e.target.value.replaceAll(/[\D]/gi, '');
if (type === 'title' && e.target.value.length <= 25) {
setEventInfo({ ...eventInfo, title: e.target.value });
setError({ ...error, title: false });
}
if (type === 'content' && e.target.value.length <= 500) {
setEventInfo({ ...eventInfo, content: e.target.value });
setError({ ...error, content: false });
}
if (type === 'start') {
setEventInfo({ ...eventInfo, start_date: { ...eventInfo.start_date, [change!]: value } });
if (change === 'year' && e.target.value.length <= 4) {
setEventInfo({ ...eventInfo, start_date: { ...eventInfo.start_date, [change!]: value } });
}
if (change !== 'year' && e.target.value.length <= 2) {
setEventInfo({ ...eventInfo, start_date: { ...eventInfo.start_date, [change!]: value } });
}
setError({ ...error, date: false });
}
if (type === 'end') {
setEventInfo({ ...eventInfo, end_date: { ...eventInfo.end_date, [change!]: value } });
if (change === 'year' && e.target.value.length <= 4) {
setEventInfo({ ...eventInfo, end_date: { ...eventInfo.end_date, [change!]: value } });
}
if (change !== 'year' && e.target.value.length <= 2) {
setEventInfo({ ...eventInfo, end_date: { ...eventInfo.end_date, [change!]: value } });
}
setError({ ...error, date: false });
}
setError({ ...error, title: false });
};

const validation = () => {
Expand All @@ -77,7 +95,7 @@ export default function ModifyEvent() {
setError((prevError) => ({ ...prevError, title: true }));
flag = true;
}
if (editor.length === 0) {
if (eventInfo.content.length === 0) {
setError((prevError) => ({ ...prevError, content: true }));
flag = true;
}
Expand Down Expand Up @@ -129,7 +147,7 @@ export default function ModifyEvent() {

const requestData = {
title: eventInfo.title,
content: editor,
content: eventInfo.content,
start_date: startDate,
end_date: endDate,
thumbnail_images: eventInfo.thumbnail_image,
Expand Down Expand Up @@ -215,21 +233,25 @@ export default function ModifyEvent() {
<div>
<div className={styles.event__divide}>
<p className={styles.event__paragraph}>이벤트/공지 내용</p>
<small className={styles.event__count} />
<small className={
cn({
[styles.event__count]: true,
[styles['event__count--full']]: eventInfo.content.length === 500,
})
}
>
{`${eventInfo.content.length} / 500`}
</small>
</div>
<div>
<ReactQuill
theme="snow"
value={editor}
onChange={(e) => {
setError({ ...error, content: false });
return setEditor(e);
}}
modules={modules}
placeholder="이벤트/공지 내용을 입력해 주세요."
<textarea
value={eventInfo.content}
placeholder="이벤트 내용을 입력해주세요"
className={cn({
[styles['error-border']]: error.content,
[styles.event__content]: true,
})}
onChange={(e) => changeInput(e, 'content')}
/>
</div>
{error.content && <div className={styles['error-message']}>필수 입력 항목입니다.</div>}
Expand Down
9 changes: 9 additions & 0 deletions src/page/ManageEvent/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@
height: 40px;
padding: 5px 10px;
}

&__content {
border: 1px solid #e1e1e1;
border-radius: 5px;
width: 100%;
height: 100px;
padding: 5px 10px;
box-sizing: border-box;
}
}

.event-day {
Expand Down
11 changes: 7 additions & 4 deletions src/page/ModifyMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@ import MenuDetail from 'page/AddMenu/components/MenuDetail';
import GoMyShopModal from 'page/AddMenu/components/GoMyShop';
import MobileDivide from 'page/AddMenu/components/MobileDivide';
import useScrollToTop from 'utils/hooks/useScrollToTop';
import useFormValidation from 'page/AddMenu/hook/useFormValidation';

export default function ModifyMenu() {
useScrollToTop();
const { isMobile } = useMediaQuery();
const [isComplete, setIsComplete] = useState<boolean>(false);
const { validateFields } = useFormValidation();
const toggleConfirmClick = () => {
if (validateFields()) {
setIsComplete((prevState) => !prevState);
}
};
const { menuId } = useParams();

assert(menuId != null, 'menuId가 없습니다.');
Expand All @@ -31,10 +38,6 @@ export default function ModifyMenu() {
navigate('/owner');
};

const toggleConfirmClick = () => {
setIsComplete((prevState) => !prevState);
};

const { deleteMenuMutation } = useDeleteMenu();

const handleMobileDeleteMenu = () => {
Expand Down
Loading
Loading