diff --git a/README.md b/README.md
index b914539..04f1297 100644
--- a/README.md
+++ b/README.md
@@ -21,13 +21,8 @@
- 전시는 여러 사용자들이 관람 뿐 아니라 채팅을 통해 서로 의사소통 가능합니다.
- 전시 작가는 다양한 템플릿으로 전시를 할 수 있습니다.
- 오프라인 뿐 아니라 온라인에서도 홍보를 하고싶어 할 경우에 유용한 플랫폼입니다.
-
-
-**프로젝트 기간** : 2024.05.22 ~ 2024.07.11
+
-🔗 [D'art 서비스 둘러보기](https://www.dartgallery.site/) (데스크탑/태블릿 환경에서 이용 가능)
-
-🎬 [시연 영상 보러가기 ](--)
@@ -66,7 +61,8 @@
### 📌 실시간 채팅 서비스
-- 전시를 감상하며 나와 같이 보고 있는 사람들과 얘기를 나눌 수도, 큐레이터의 안내를 받을 수도 있습니다.
+- 전시를 감상하며 현재 해당 전시를 관람하고 있는 사람을 확인할 수 있습니다.
+- 관람객과 얘기를 나눌 수도, 작가의 안내를 받을 수도 있습니다.
### 📌 리뷰 및 공유하기
@@ -118,11 +114,11 @@
## 🧑🧑🧒🧒 Front TEAMMATE 소개
-| ![강신범](https://github.com/kangsinbeom.png) | ![김수현](https://github.com/gamjatan9.png) | ![하승진](https://github.com/j2an777.png) |
-| --------------------------------------------- | ------------------------------------------- | ----------------------------------------- | --- |
-| [강신범](https://github.com/kangsinbeom) | [김수현](https://github.com/gamjatan9) | [하승진](https://github.com/j2an777) |
-| **FrontEnd** | **FrontEnd** | **FrontEnd** | |
-| FE 팀장, 에러처리, 데이터와 토큰 관리, 배포, 메인 페이지, 공통 컴포넌트와 훅 생성 | 폼 관리, 실시간 채팅, 결제 시스템, 전시 생성 페이지 | 전시 페이지, 모달 기능, 저작권 침해 방지 마련, 전시 생성 ux 강화 |
+| ![강신범](https://github.com/kangsinbeom.png) | ![김수현](https://github.com/gamjatan9.png) | ![하승진](https://github.com/j2an777.png) |
+| --------------------------------------------------------------------------------- | ----------------------------------------------------------------- | ---------------------------------------------------------------- |
+| [강신범](https://github.comzkangsinbeom) | [김수현](https://github.com/gamjatan9) | [하승진](https://github.com/j2an777) |
+| **FrontEnd** | **FrontEnd** | **FrontEnd** |
+| FE 팀장, 에러처리, 데이터와 토큰 관리, 배포, 메인 페이지, 공통 컴포넌트와 훅 생성 | 폼 관리, 실시간 채팅, 결제 시스템, 전시 생성 페이지, 회원정보조회 | 전시 페이지, 모달 기능, 저작권 침해 방지 마련, 전시 생성 ux 강화 |
diff --git a/src/consts/postValidation.ts b/src/consts/postValidation.ts
new file mode 100644
index 0000000..4d06b66
--- /dev/null
+++ b/src/consts/postValidation.ts
@@ -0,0 +1,17 @@
+import { PostGalleries } from '@/types/post';
+
+export const postValidation = (data: PostGalleries) => {
+ if (!data.images || data.images.length < 3) {
+ throw new Error('최소 3개의 작품을 등록해주세요.');
+ }
+
+ if (!data.thumbnail) {
+ throw new Error('썸네일 이미지가 없습니다.');
+ }
+
+ if (data.gallery.fee && !data.gallery.endDate) {
+ throw new Error('유료 전시 기간을 선택해 주세요.');
+ }
+
+ return true;
+};
diff --git a/src/pages/chatModal/components/chat/ChatMenu.tsx b/src/pages/chatModal/components/chat/ChatMenu.tsx
index e6dcedf..a2977d7 100644
--- a/src/pages/chatModal/components/chat/ChatMenu.tsx
+++ b/src/pages/chatModal/components/chat/ChatMenu.tsx
@@ -9,6 +9,7 @@ import { useChatScroll } from '../../hooks/useChatScroll';
import { ChatProps } from '../..';
import * as S from './styles';
import parseDate from '@/utils/parseDate';
+import { formatDate } from '@/utils/formatDateforChat';
const ChatMenu = ({ chatRoomId, galleryNick }: Omit) => {
const [messages, setMessages] = useState([]);
@@ -60,7 +61,7 @@ const ChatMenu = ({ chatRoomId, galleryNick }: Omit) => {
const message: ChatMessageProps = {
content: newMessage,
sender: nickname,
- createdAt: new Date(),
+ createdAt: formatDate(new Date()),
isAuthor: isAuthor,
profileImageUrl: profileImage,
};
diff --git a/src/pages/payment/success/index.tsx b/src/pages/payment/success/index.tsx
index bd2ba48..b7fb9c5 100644
--- a/src/pages/payment/success/index.tsx
+++ b/src/pages/payment/success/index.tsx
@@ -10,7 +10,7 @@ const SuccessPage = () => {
switch (order) {
case 'ticket':
- title = '결재가 완료되었습니다.';
+ title = '결제가 완료되었습니다.';
content = '전시관 입장하기';
path = `/gallery/${galleryId}`;
break;
diff --git a/src/pages/post/components/stepZero/index.tsx b/src/pages/post/components/stepZero/index.tsx
index 3d22aae..7051b4a 100644
--- a/src/pages/post/components/stepZero/index.tsx
+++ b/src/pages/post/components/stepZero/index.tsx
@@ -1,13 +1,13 @@
import { useEffect } from 'react';
-import { useFormContext } from 'react-hook-form';
+import { Controller, useFormContext } from 'react-hook-form';
import DropZone from '@/components/dropZone';
-import { formatDateInKST } from '@/utils/formatDateInKST';
+import { formatDate } from '@/utils/formatDateforPost';
import * as S from './styles';
import { dateNfeeStore } from '@/stores/post';
import { Icon } from '@/components';
const StepZero = () => {
- const { setValue } = useFormContext();
+ const { setValue, control } = useFormContext();
const { activeBtn, dateRange, feeDetails, setActiveBtn, setDateRange, setFeeDetails } =
dateNfeeStore();
@@ -41,22 +41,18 @@ const StepZero = () => {
setFeeDetails({ ...feeDetails, totalPay: pay });
setDateRange({ ...dateRange, endDate });
// 이용료와 기간 formData 업데이트
- setValue('gallery.startDate', formatDateInKST(dateRange.startDate, true));
- setValue('gallery.endDate', formatDateInKST(endDate));
+ setValue('gallery.startDate', formatDate(dateRange.startDate, true));
+ setValue('gallery.endDate', formatDate(endDate));
setValue('gallery.generatedCost', pay);
} else {
// 무료 전시
setValue('gallery.generatedCost', 0);
- setValue('gallery.startDate', formatDateInKST(dateRange.startDate, true));
+ setValue('gallery.startDate', formatDate(dateRange.startDate, true));
setFeeDetails({ ...feeDetails, totalPay: 0 });
setDateRange({ ...dateRange, endDate: null });
}
}, [activeBtn, feeDetails.period, feeDetails.fee, dateRange.startDate]);
- const onFileDrop = (file: File) => {
- setValue('thumbnail', file);
- };
-
const onBtnClick = (
buttonType: 'free' | 'pay',
event: React.MouseEvent,
@@ -109,9 +105,15 @@ const StepZero = () => {
return (
- (
+ field.onChange(file)}
+ />
+ )}
/>
diff --git a/src/pages/post/hooks/useHandleErrors.ts b/src/pages/post/hooks/useHandleErrors.ts
index d592d5c..ce07cca 100644
--- a/src/pages/post/hooks/useHandleErrors.ts
+++ b/src/pages/post/hooks/useHandleErrors.ts
@@ -1,33 +1,24 @@
import { alertStore } from '@/stores/modal';
-import useCustomNavigate from '@/hooks/useCustomNavigate';
import axios from 'axios';
-import { PostGalleries } from '@/types/post';
export const useHandleErrors = () => {
const open = alertStore((state) => state.open);
- const navigate = useCustomNavigate();
- const handleErrors = (error: unknown, data: PostGalleries) => {
- if (axios.isAxiosError(error) && error.response?.status === 401) {
- open({
- title: '재로그인 필요',
- description: '로그인 시간이 만료되었습니다. 다시 로그인해 주세요.',
- buttonLabel: '확인',
- onClickButton: () => navigate('/login'),
- });
- } else if (data.images == undefined || data.images.length < 3) {
- open({
- title: '작품 등록 오류',
- description: '최소 3개의 작품을 등록해주세요.',
- buttonLabel: '확인',
- });
- } else {
- open({
- title: '전시 등록 오류',
- description: '모든 정보를 입력해 주세요.',
- buttonLabel: '확인',
- });
+ const handleErrors = (error: unknown) => {
+ let message;
+
+ if (axios.isAxiosError(error)) {
+ message = error.response?.data.message || message;
+ } else if (error instanceof Error) {
+ message = error.message;
}
+
+ open({
+ title: '작품 등록 오류',
+ description: message,
+ buttonLabel: '확인',
+ onClickButton: () => {},
+ });
};
return { handleErrors };
diff --git a/src/pages/post/index.tsx b/src/pages/post/index.tsx
index 4413f64..7f48a85 100644
--- a/src/pages/post/index.tsx
+++ b/src/pages/post/index.tsx
@@ -6,6 +6,8 @@ import { alertStore, progressStore } from '@/stores/modal';
import useCustomNavigate from '@/hooks/useCustomNavigate';
import usePostGalleries from './hooks/usePostGalleries';
import ProgressPortal from '@/components/ProgressPortal';
+import { postValidation } from '@/consts/postValidation';
+import { useHandleErrors } from './hooks/useHandleErrors';
import * as S from './styles';
@@ -15,8 +17,8 @@ const PostPage = () => {
const navigate = useCustomNavigate();
const { open } = alertStore();
const setProgress = progressStore((state) => state.setProgress);
-
const { mutate } = usePostGalleries();
+ const { handleErrors } = useHandleErrors();
const onSubmit: SubmitHandler = async (data) => {
open({
@@ -33,22 +35,23 @@ const PostPage = () => {
),
buttonLabel: '확인',
buttonCancelLabel: '취소',
- onClickButton: () => modalConfirm(data),
+ onClickButton: () => setTimeout(() => modalConfirm(data), 100),
onClickCancelButton: () => {},
});
};
const modalConfirm = async (data: PostGalleries) => {
- if (data.images == undefined || data.images.length < 3) {
- open({
- title: '작품 등록 오류',
- description: '최소 3개의 작품을 등록해주세요.',
- buttonLabel: '확인',
+ try {
+ postValidation(data);
+ setProgress(1);
+ mutate(data, {
+ onError: (error) => {
+ handleErrors(error);
+ },
});
- return;
+ } catch (error) {
+ handleErrors(error);
}
- setProgress(1);
- mutate(data);
};
return (
diff --git a/src/types/chat.ts b/src/types/chat.ts
index 5b99576..5ddc058 100644
--- a/src/types/chat.ts
+++ b/src/types/chat.ts
@@ -11,7 +11,7 @@ export interface ChatMessage {
export interface ChatMessageProps {
sender: string;
content: string;
- createdAt: Date;
+ createdAt: Date | string;
isAuthor: boolean;
profileImageUrl: string;
}
diff --git a/src/utils/formatDateforChat.ts b/src/utils/formatDateforChat.ts
new file mode 100644
index 0000000..60df017
--- /dev/null
+++ b/src/utils/formatDateforChat.ts
@@ -0,0 +1,11 @@
+export const formatDate = (date: Date) => {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0');
+ const day = String(date.getDate()).padStart(2, '0');
+ const hours = String(date.getHours()).padStart(2, '0');
+ const minutes = String(date.getMinutes()).padStart(2, '0');
+ const seconds = String(date.getSeconds()).padStart(2, '0');
+
+ const formattedDateString = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
+ return formattedDateString;
+};
diff --git a/src/utils/formatDateInKST.ts b/src/utils/formatDateforPost.ts
similarity index 79%
rename from src/utils/formatDateInKST.ts
rename to src/utils/formatDateforPost.ts
index 9d9afb3..a1a51c1 100644
--- a/src/utils/formatDateInKST.ts
+++ b/src/utils/formatDateforPost.ts
@@ -1,4 +1,4 @@
-export const formatDateInKST = (date: Date | null, startDate: boolean = false) => {
+export const formatDate = (date: Date | null, startDate: boolean = false) => {
if (!date) return null;
const year = date.getFullYear();
diff --git a/src/utils/parseDate.ts b/src/utils/parseDate.ts
index 544ce73..cf35c0b 100644
--- a/src/utils/parseDate.ts
+++ b/src/utils/parseDate.ts
@@ -1,4 +1,4 @@
-const parseDate = (value: Date) => {
+const parseDate = (value: Date | string) => {
const date = new Date(value);
const year = date.getFullYear();
const month = date.getMonth() + 1;