티켓(입장권)
diff --git a/src/pages/dashboard/ui/ticket/TicketOptionCreatePage.tsx b/src/pages/dashboard/ui/ticket/TicketOptionCreatePage.tsx
index 68c864c7..dd24ed7d 100644
--- a/src/pages/dashboard/ui/ticket/TicketOptionCreatePage.tsx
+++ b/src/pages/dashboard/ui/ticket/TicketOptionCreatePage.tsx
@@ -25,7 +25,7 @@ const TicketOptionCreatePage = () => {
}, [isEditing, optionDetail]);
return (
-
+
티켓 옵션 생성
티켓 옵션을 생성할 수 있습니다.
diff --git a/src/pages/dashboard/ui/ticket/TicketOptionPage.tsx b/src/pages/dashboard/ui/ticket/TicketOptionPage.tsx
index 967ed77c..57a52284 100644
--- a/src/pages/dashboard/ui/ticket/TicketOptionPage.tsx
+++ b/src/pages/dashboard/ui/ticket/TicketOptionPage.tsx
@@ -66,7 +66,7 @@ const TicketOptionPage = () => {
: [];
return (
-
+
티켓에 추가 옵션 부착 하기
diff --git a/src/pages/event/ui/AllEventsPage.tsx b/src/pages/event/ui/AllEventsPage.tsx
index 79782548..156cb277 100644
--- a/src/pages/event/ui/AllEventsPage.tsx
+++ b/src/pages/event/ui/AllEventsPage.tsx
@@ -8,6 +8,7 @@ import { useNavigate } from 'react-router-dom';
import useAuthStore from '../../../app/provider/authStore';
import { AnimatePresence } from 'framer-motion';
import LoginModal from '../../../widgets/main/ui/LoginModal';
+import ProfileCircle from '../../../../design-system/ui/Profile';
const AllEventsPage = () => {
const navigater = useNavigate();
@@ -21,19 +22,18 @@ const AllEventsPage = () => {
iconPath={
}
onClick={() => navigater('/search')}
onChange={() => {}}
- placeholder="입력해주세요"
+ placeholder="검색어를 입력해주세요"
/>
}
leftButtonClassName="sm:text-lg md:text-xl lg:text-2xl font-extrabold font-nexon"
leftButtonClick={() => navigater('/')}
leftButtonLabel="같이가요"
rightContent={
-
+ isLoggedIn ? (
+
+ ) : (
+
+ )
}
/>
{isModalOpen && }
diff --git a/src/pages/event/ui/EventDetailsPage.tsx b/src/pages/event/ui/EventDetailsPage.tsx
index 1443870a..8f401669 100644
--- a/src/pages/event/ui/EventDetailsPage.tsx
+++ b/src/pages/event/ui/EventDetailsPage.tsx
@@ -136,24 +136,27 @@ const EventDetailsPage = () => {
티켓 옵션
-
-
관련 링크
-
- {event.result.referenceLinks.map((link: { title: string; url: string }, index: number) => (
-
- ))}
-
-
+ {event.result.referenceLinks && event.result.referenceLinks.length > 0 && (
+
+
관련 링크
+
+ {event.result.referenceLinks.map((link: { title: string; url: string }, index: number) => (
+
+ ))}
+
+
+)}
+
>
) : (
diff --git a/src/pages/home/ui/MainPage.tsx b/src/pages/home/ui/MainPage.tsx
index 3e8e6802..f07bc1b9 100644
--- a/src/pages/home/ui/MainPage.tsx
+++ b/src/pages/home/ui/MainPage.tsx
@@ -42,7 +42,7 @@ const MainPage = () => {
iconPath={
}
onClick={() => navigate('/search')}
onChange={() => {}}
- placeholder="입력해주세요"
+ placeholder="검색어를 입력해주세요"
/>
}
leftButtonClassName="sm:text-lg md:text-xl lg:text-2xl font-extrabold font-nexon"
diff --git a/src/pages/join/AgreementPage.tsx b/src/pages/join/AgreementPage.tsx
index 89cf3663..9852a4e5 100644
--- a/src/pages/join/AgreementPage.tsx
+++ b/src/pages/join/AgreementPage.tsx
@@ -4,28 +4,13 @@ import Button from '../../../design-system/ui/Button';
import AgreementList from '../../features/join/ui/AgreementList';
import { useAgreementStore } from '../../features/join/model/agreementStore';
import { useNavigate } from 'react-router-dom';
-import { useAgreeTerms } from '../../features/join/hooks/useUserHook';
-import { TermsAgreementRequest } from '../../features/join/model/userInformation';
const AgreementPage: React.FC = () => {
- const { isAllRequiredAgreed, getAgreementStates } = useAgreementStore();
+ const { isAllRequiredAgreed } = useAgreementStore();
const navigate = useNavigate();
- const { mutate:agreeTerms } = useAgreeTerms();
const handleAgree = () => {
- const states = getAgreementStates();
- const agreementData: TermsAgreementRequest = {
- serviceAgreed: states.serviceAgreed,
- privacyPolicyAgree: states.privacyPolicyAgree,
- personalInfoUsageAgreed: states.personalInfoUsageAgreed,
- marketingAgreed: states.marketingAgreed,
- };
-
- agreeTerms(agreementData, {
- onSuccess: () => {
- navigate('/join/info-input');
- },
- });
+ navigate('/join/info-input');
};
return (
diff --git a/src/pages/join/InfoInputPage.tsx b/src/pages/join/InfoInputPage.tsx
index d95fa829..8659a196 100644
--- a/src/pages/join/InfoInputPage.tsx
+++ b/src/pages/join/InfoInputPage.tsx
@@ -5,9 +5,10 @@ import Header from '../../../design-system/ui/Header';
import Button from '../../../design-system/ui/Button';
import UnderlineTextField from '../../../design-system/ui/textFields/UnderlineTextField';
import { FormData, zodValidation } from '../../shared/lib/formValidation';
-import { useUserInfo, useUserUpdate } from '../../features/join/hooks/useUserHook';
+import { useAgreeTerms, useUserInfo, useUserUpdate } from '../../features/join/hooks/useUserHook';
import useAuthStore from '../../app/provider/authStore';
import { formatPhoneNumber } from '../../shared/utils/phoneFormatter';
+import { useAgreementStore } from '../../features/join/model/agreementStore';
const InfoInputPage = () => {
const { data, isLoading } = useUserInfo();
@@ -32,6 +33,8 @@ const InfoInputPage = () => {
const navigate = useNavigate();
const phoneValue = watch('phone');
+ const { getAgreementStates } = useAgreementStore();
+ const { mutate: agreeTerms } = useAgreeTerms();
const handlePhoneChange = (e: React.ChangeEvent) => {
const formatted = formatPhoneNumber(e.target.value);
@@ -39,17 +42,33 @@ const InfoInputPage = () => {
};
const onSubmit: SubmitHandler = formData => {
+ const agreementStates = getAgreementStates();
const updatedData = {
- name: data?.name || '',
+ name: formData.name,
email: data?.email || '',
phoneNumber: formData.phone,
};
updateUser(updatedData, {
onSuccess: () => {
- login();
- setName(data?.name || '사용자');
- alert('정보가 성공적으로 업데이트되었습니다.');
- navigate('/');
+ agreeTerms(
+ {
+ serviceAgreed: agreementStates.serviceAgreed,
+ privacyPolicyAgree: agreementStates.privacyPolicyAgree,
+ personalInfoUsageAgreed: agreementStates.personalInfoUsageAgreed,
+ marketingAgreed: agreementStates.marketingAgreed,
+ },
+ {
+ onSuccess: () => {
+ login();
+ setName(formData.name);
+ alert('회원가입이 완료되었습니다.');
+ navigate('/');
+ },
+ onError: () => {
+ alert('약관 동의 처리에 실패했습니다.');
+ },
+ }
+ );
},
onError: err => {
alert('정보 업데이트에 실패했습니다. 다시 시도해주세요.');
diff --git a/src/pages/menu/ui/MyTicketPage.tsx b/src/pages/menu/ui/MyTicketPage.tsx
index 2e267b41..54cc9fd2 100644
--- a/src/pages/menu/ui/MyTicketPage.tsx
+++ b/src/pages/menu/ui/MyTicketPage.tsx
@@ -40,7 +40,11 @@ const MyTicketPage = () => {
);
if (invalidTickets.length > 0) {
- alert('이미 시작된 이벤트의 티켓은 취소할 수 없습니다.');
+ const titles = invalidTickets.map(ticket => `• ${ticket.event.title}`).join('\n');
+ alert(`❗해당 이벤트는 이미 시작되어 취소할 수 없습니다\n\n${titles}`);
+ setIsDeleteModalOpen(false);
+ setIsCancelMode(false);
+ setSelectedIds([]);
return;
}
@@ -106,6 +110,7 @@ const MyTicketPage = () => {
onClick={() => handleEventCardClick(ticket)}
className={`transition-transform duration-200 ${isCancelMode && selectedIds.includes(ticket.id) ? 'scale-95 border-2 border-pink-400' : ''
}`}
+ aspectRatio='md:aspect-[3/4.7] sm:aspect-[1/2]'
>

@@ -131,23 +136,23 @@ const MyTicketPage = () => {
{isModalOpen && selectedTicket && (
- }
- ticketQrCode={selectedTicket.ticketQrCode}
- title={selectedTicket.event.title}
- hostName={selectedTicket.event.hostChannelName}
- date={selectedTicket.event.startDate}
- location={selectedTicket.event.address}
- ticketName={selectedTicket.ticketName}
- price={selectedTicket.ticketPrice}
- orderStatus={selectedTicket.orderStatus}
- isCheckIn={selectedTicket.checkIn}
- isCountdownChecked={true}
- remainDays={selectedTicket.event.remainDays}
- onClick={() => setIsModalOpen(false)}
- />
-
+
}
+ ticketQrCode={selectedTicket.ticketQrCode}
+ title={selectedTicket.event.title}
+ hostName={selectedTicket.event.hostChannelName}
+ date={selectedTicket.event.startDate}
+ location={selectedTicket.event.address}
+ ticketName={selectedTicket.ticketName}
+ price={selectedTicket.ticketPrice}
+ orderStatus={selectedTicket.orderStatus}
+ isCheckIn={selectedTicket.checkIn}
+ isCountdownChecked={true}
+ remainDays={selectedTicket.event.remainDays}
+ onClick={() => setIsModalOpen(false)}
+ />
+
)}
{isDeleteModalOpen && (
@@ -166,6 +171,9 @@ const MyTicketPage = () => {
},
onError: () => {
alert('티켓 취소에 실패했습니다.');
+ setIsDeleteModalOpen(false);
+ setIsCancelMode(false);
+ setSelectedIds([]);
},
});
}}
diff --git a/src/pages/menu/ui/myHost/HostDetailPage.tsx b/src/pages/menu/ui/myHost/HostDetailPage.tsx
index aafd2937..74ff56a8 100644
--- a/src/pages/menu/ui/myHost/HostDetailPage.tsx
+++ b/src/pages/menu/ui/myHost/HostDetailPage.tsx
@@ -37,6 +37,7 @@ const HostDetailPage = () => {
eventDate={event.startDate}
location={event.onlineType}
hashtags={event.hashtags}
+ aspectRatio='md:aspect-[3/4.7] sm:aspect-[1/1.8]'
/>
))
)}
diff --git a/src/pages/menu/ui/myHost/MyHostPage.tsx b/src/pages/menu/ui/myHost/MyHostPage.tsx
index a241588b..2f476ccf 100644
--- a/src/pages/menu/ui/myHost/MyHostPage.tsx
+++ b/src/pages/menu/ui/myHost/MyHostPage.tsx
@@ -74,6 +74,7 @@ const MyHostPage = () => {
onDeleteSuccess={(deletedEventId: number) => {
setDeletedEventId(prev => [...prev, deletedEventId]);
}}
+ aspectRatio='md:aspect-[3/4.7] sm:aspect-[1/1.8]'
/>
))}
diff --git a/src/pages/search/ui/SearchPage.tsx b/src/pages/search/ui/SearchPage.tsx
index d80c00fd..bba1af16 100644
--- a/src/pages/search/ui/SearchPage.tsx
+++ b/src/pages/search/ui/SearchPage.tsx
@@ -69,7 +69,7 @@ const SearchPage = () => {
@@ -96,6 +96,7 @@ const SearchPage = () => {
host={event.hostChannelName}
hashtags={event.hashtags}
dDay={event.remainDays}
+ onClick={() => navigate(`/event-details/${event.id}`)}
/>
);
diff --git a/src/shared/hooks/useImageUpload.ts b/src/shared/hooks/useImageUpload.ts
index 6e4d0a42..f707a980 100644
--- a/src/shared/hooks/useImageUpload.ts
+++ b/src/shared/hooks/useImageUpload.ts
@@ -1,6 +1,6 @@
import { useRef, useState, useCallback, useEffect } from 'react';
import { uploadFile } from '../../features/event/hooks/usePresignedUrlHook';
-import basicProfile from '../../../public/assets/event-manage/creation/BasicProfile.png';
+export const DEFAULT_BASIC_PROFILE = 'https://gotogetherbucket.s3.ap-northeast-2.amazonaws.com/default.png';
const useImageUpload = ({
value,
@@ -18,9 +18,9 @@ const useImageUpload = ({
useEffect(() => {
if (value) {
setPreviewUrl(value);
- } else if (useDefaultImage && previewUrl !== basicProfile) {
- setPreviewUrl(basicProfile);
- onSuccess?.(basicProfile);
+ } else if (useDefaultImage && previewUrl !== DEFAULT_BASIC_PROFILE) {
+ setPreviewUrl(DEFAULT_BASIC_PROFILE);
+ onSuccess?.(DEFAULT_BASIC_PROFILE);
}
}, [value, onSuccess, useDefaultImage, previewUrl]);
diff --git a/src/shared/types/dashboardType.ts b/src/shared/types/dashboardType.ts
index 7c38faae..b1a942a0 100644
--- a/src/shared/types/dashboardType.ts
+++ b/src/shared/types/dashboardType.ts
@@ -18,6 +18,8 @@ import participants from '../../../public/assets/dashboard/menu/Participants(bla
import clickedParticipants from '../../../public/assets/dashboard/menu/Participants(pink).svg';
import response from '../../../public/assets/dashboard/menu/Response(black).svg';
import clickedResponse from '../../../public/assets/dashboard/menu/Response(pink).svg';
+import qr from '../../../public/assets/dashboard/menu/QR(black).svg';
+import clickedQr from '../../../public/assets/dashboard/menu/QR(pink).svg';
export const getMenuLists = (id: string | number) => [
{ text: '대시보드', icon: dashboard, clickedIcon: clickedDashboard, path: `/dashboard/${id}` },
@@ -34,10 +36,6 @@ export const getMenuLists = (id: string | number) => [
{ text: '사용자 응답 관리', icon: response, clickedIcon: clickedResponse, path: `/dashboard/${id}/responses-management`},
{ text: '이메일 예약 발송', icon: email, clickedIcon: clickedEmail, path: `/dashboard/${id}/email` },
{ text: '보낸 이메일', icon: sentEmail, clickedIcon: clickedSentEmail, path: `/dashboard/${id}/mailBox` },
- {
- text: '구매/참가자 관리',
- icon: participants,
- clickedIcon: clickedParticipants,
- path: `/dashboard/${id}/participants-management`,
- },
+ { text: '구매/참가자 관리', icon: participants, clickedIcon: clickedParticipants, path: `/dashboard/${id}/participants-management` },
+ { text: 'QR코드로 체크인', icon: qr, clickedIcon: clickedQr, path: `/dashboard/${id}/check-in` },
];
diff --git a/src/shared/ui/EventCard.tsx b/src/shared/ui/EventCard.tsx
index b5aaaf24..3566466d 100644
--- a/src/shared/ui/EventCard.tsx
+++ b/src/shared/ui/EventCard.tsx
@@ -24,6 +24,8 @@ interface EventCardProps {
children?: React.ReactNode;
isDelete?: boolean;
onDeleteSuccess?: (eventId: number) => void;
+ onlineType?: 'OFFLINE' | 'ONLINE';
+ aspectRatio?: string;
}
const EventCard = ({
@@ -40,6 +42,8 @@ const EventCard = ({
children,
isDelete = false,
onDeleteSuccess,
+ onlineType,
+ aspectRatio = 'md:aspect-[3/4.3] sm:aspect-[3/4.5]'
}: EventCardProps) => {
const navigate = useNavigate();
const { pathname } = useLocation();
@@ -49,96 +53,102 @@ const EventCard = ({
const isHostPage = pathname.startsWith(`/menu/myHost`) || pathname.startsWith(`/menu/hostDetail`);
return (
-