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
10 changes: 5 additions & 5 deletions design-system/ui/modals/QrModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,33 +68,33 @@ const QrModal = ({
<div className="space-y-1 text-deDayTextDark">
<IconText
size="xSmall"
iconPath={<img src={qr_calendar} alt="qr_calendar" />}
iconPath={<img src={qr_calendar} alt="qr_calendar" className='mr-1'/>}
children={formattedDate}
className="text-11"
></IconText>
<IconText
size="xSmall"
iconPath={<img src={qr_location} alt="qr_location" />}
iconPath={<img src={qr_location} alt="qr_location" className='mr-1'/>}
children={location}
className="text-11"
></IconText>
<IconText
size="xSmall"
iconPath={<img src={qr_ticket} alt="qr_ticket" />}
iconPath={<img src={qr_ticket} alt="qr_ticket" className='mr-1'/>}
children={ticketName}
className="text-11"
></IconText>
<span className="text-sm font-bold">{formattedPrice}원</span>
<hr />
<IconText
size="xSmall"
iconPath={<img src={qr_check} alt="qr_check" />}
iconPath={<img src={qr_check} alt="qr_check" className='mr-1'/>}
children={orderStatus === 'COMPLETED' ? '승인됨' : '대기 중'}
className="text-11"
></IconText>
<IconText
size="xSmall"
iconPath={<img src={qr_check} alt="qr_check" />}
iconPath={<img src={qr_check} alt="qr_check" className='mr-1'/>}
children={isCheckIn ? '체크인 완료' : '체크인 미완료'}
className="text-11"
></IconText>
Expand Down
5 changes: 5 additions & 0 deletions src/features/event-manage/event-create/api/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ export const createEvent = async (data: CreateEventRequest) => {
const response = await axiosClient.post('/events', data);
return response.data;
};

export const readEventDetail = async (eventId: number) => {
const response = await axiosClient.get(`/events/${eventId}`);
return response.data;
};
17 changes: 6 additions & 11 deletions src/features/ticket/api/order.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import { axiosClient } from "../../../shared/types/api/http-client"
export const readMyTickets = {
get: async (page: number = 0, size: number = 10) => {
try {
const response = await axiosClient.get("/orders", {
params: { page, size },
});
return response.data;
} catch (error) {
console.error("티켓 조회 중 오류 발생:", error);
throw error;
}
},
get: async (page: number = 0, size: number = 10) => {
const response = await axiosClient.get("/orders", {
params: { page, size },
});
return response.data;
},
}
108 changes: 80 additions & 28 deletions src/pages/event/ui/EventDetailsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,54 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { eventData } from '../../../shared/types/eventDetailType';
import OrganizerInfo from '../../../widgets/event/ui/OrganizerInfo';
import Header from '../../../../design-system/ui/Header';
import Search from '../../../../design-system/icons/Search.svg';
import IconButton from '../../../../design-system/ui/buttons/IconButton';
import banner from '../../../../public/assets/banners/1.png';
import share from '../../../../public/assets/event-manage/details/Share.svg';
import like from '../../../../public/assets/event-manage/details/Like.svg';
import liked from '../../../../public/assets/event-manage/details/ClickedLike.svg';
import TicketInfo from '../../../widgets/event/ui/TicketInfo';
import link from '../../../../public/assets/event-manage/details/Link.svg';
import ShareEventModal from '../../../features/event-manage/event-create/ui/ShareEventModal';
import { readEventDetail } from '../../../features/event-manage/event-create/api/event';
import participantsImg from '../../../../public/assets/event-manage/details/People.svg';
import dateImg from '../../../../public/assets/event-manage/details/Date.svg';
import timeImg from '../../../../public/assets/event-manage/details/Time.svg';
import locationImg from '../../../../public/assets/event-manage/details/Location.svg';
import KakaoMap from '../../../shared/ui/KakaoMap';

interface ReadEvent {
id: number;
bannerImageUrl: string;
title: string;
participantCount: number;
startDate: string;
endDate: string;
startTime: string;
endTime: string;
address: string;
location: { lat: number; lng: number };
description: string;
hostChannelName: string;
hostChannelDescription: string;
organizerEmail: string;
organizerPhoneNumber: string;
referenceLinks: { title: string; url: string };
category: string;
onlineType: string;
status: string;
hashtags: string[];
}

const EventDetailsPage = () => {
const navigate = useNavigate();
const [title, setTitle] = useState('');
const [isModalOpen, setIsModalOpen] = useState(false);
const [clickedLike, setClickedLike] = useState(false);

const [event, setEvent] = useState<ReadEvent | null>(null);
const eventId = 1; //수정 필요
Comment on lines +49 to +50
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

하드코딩된 이벤트 ID
현재 eventId 값이 1로 고정되어 있습니다. 추후 라우트 파라미터 등을 통해 동적으로 받아오도록 개선이 필요합니다.


const handleShareClick = (title: string) => {
setTitle(title);
setIsModalOpen(true);
Expand All @@ -38,6 +68,19 @@ const EventDetailsPage = () => {
}
}, [isModalOpen]);

useEffect(() => {
const fetchEventDetail = async () => {
try {
const response = await readEventDetail(eventId);
setEvent(response.result);
} catch (error) {
console.error('이벤트 상세 정보 불러오기 실패:', error);
}
};
fetchEventDetail();
}, []);


return (
<>
<Header
Expand All @@ -47,17 +90,18 @@ const EventDetailsPage = () => {
centerContent="같이가요"
rightContent={<img src={Search} alt="검색" className="w-4" />}
/>
<>
<img src={banner} alt="이벤트 배너" className="w-full h-64 mb-6" />
<div className="flex flex-col gap-3 px-4 md:px-6">
{eventData.map(event => (
{event ? (
<>
<img src={event.bannerImageUrl} alt="이벤트 배너" className="w-full h-64 mb-6" />
<div className="flex flex-col gap-3 px-4 md:px-6">

<div key={event.id} className="flex flex-col gap-2">
<h1 className="text-xl md:text-2xl font-bold">{event.title}</h1>
<div className="flex justify-between items-center gap-1">
<div className="flex gap-2">
<img src={event.participantsImg} alt="인원수 이미지" />
<img src={participantsImg} alt="인원수 이미지" />
<span className="font-bold text-base md:text-lg py-2">
현재 {event.participants}명이 참가 신청했습니다.
현재 {event.participantCount}명이 참가 신청했습니다.
</span>
</div>
<div className="flex gap-3">
Expand All @@ -72,38 +116,46 @@ const EventDetailsPage = () => {
</div>
</div>
<div className="flex gap-2">
<img src={event.dateImg} alt="달력 이미지" />
<span className="text-sm md:text-base">{event.date}</span>
<img src={dateImg} alt="달력 이미지" />
<span className="text-sm md:text-base">{event.startDate} ~ {event.endDate}</span>
</div>
<div className="flex gap-2">
<img src={event.timeImg} alt="시간 이미지" />
<span className="text-sm md:text-base">{event.time}</span>
<img src={timeImg} alt="시간 이미지" />
<span className="text-sm md:text-base">{event.startTime} ~ {event.endTime}</span>
</div>
<div className="flex gap-2">
<img src={event.locationImg} alt="위치 이미지" />
<span className="text-sm md:text-base">{event.location}</span>
<img src={locationImg} alt="위치 이미지" />
<span className="text-sm md:text-base">{event.address}</span>
</div>
<span className="text-sm md:text-base py-3">{event.detail}</span>
<span className="text-sm md:text-base py-3">{event.description}</span>
</div>
))}

<h2 className="font-bold text-xl">위치</h2>
<div className="w-full h-48 bg-gray2" />

<OrganizerInfo />
<h2 className="font-bold text-xl">위치</h2>
<KakaoMap lat={event.location.lat} lng={event.location.lng} />

<h2 className="font-bold text-xl">티켓 옵션</h2>
<TicketInfo />
<OrganizerInfo
name={event.hostChannelName}
description={event.hostChannelDescription}
phone={event.organizerPhoneNumber}
email={event.organizerEmail}
/>

<div className="flex flex-col gap-2">
<h2 className="font-bold text-xl">관련 링크</h2>
<div className="flex items-center gap-3 mb-4">
<img src={link} alt="링크 이모지" />
<span>공식 웹사이트</span>
<h2 className="font-bold text-xl">티켓 옵션</h2>
<TicketInfo eventId={event.id} />

<div className="flex flex-col gap-2">
<h2 className="font-bold text-xl">관련 링크</h2>
<div className="flex items-center gap-3 mb-4">
<img src={link} alt="링크 이모지" />
<span>공식 웹사이트</span>
</div>
</div>
</div>
</div>
</>
</>
) : (
<div className="flex justify-center items-center h-screen">로딩 중...</div>
)}
{isModalOpen && <ShareEventModal closeModal={closeModal} eventName={title} />}
</>
);
Expand Down
48 changes: 26 additions & 22 deletions src/pages/menu/ui/MyTicketPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@ import ticketImg from '../../../../public/assets/menu/Ticket.svg';

type Ticket = {
id: number;
eventId: number;
bannerImageUrl: string;
title: string;
hostChannelName: string;
address: string;
startDate: string;
event: {
id: number;
bannerImageUrl: string;
title: string;
hostChannelName: string;
address: string;
startDate: string;
remainDays: string;
hashtags: string[];
onlineType: "ONLINE" | "OFFLINE"; // onlineType 추가
};
ticketQrCode: string;
ticketName: string;
orderStatus: "COMPLETED" | "PENDING" | "CANCELED";
remainDays: string;
ticketPrice: number;
ticketQrCode: string;
orderStatus: "COMPLETED" | "PENDING" | "CANCELED";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

❓ Verification inconclusive

취소된 티켓 상태 처리 필요

orderStatus에 "CANCELED" 상태가 정의되어 있지만, UI에서는 완료("COMPLETED")와 대기 중("PENDING") 상태만 처리하고 있습니다. 취소된 티켓의 표시 방법도 구현해야 합니다.

69-80줄의 렌더링 로직에서 취소된 티켓에 대한 처리가 누락되어 있습니다. 아래 코드가 필요할 수 있습니다:


🏁 Script executed:

#!/bin/bash
# 프로젝트 내에서 취소된 티켓 상태를 처리하는 로직이 존재하는지 확인
rg "CANCELED.*orderStatus" --type ts

Length of output: 38


취소된 티켓 상태 UI 처리 추가 필요

  • orderStatus 타입에 "CANCELED" 상태가 포함되어 있으나, 현재 src/pages/menu/ui/MyTicketPage.tsx 파일의 렌더링 로직(대략 69-80줄)에서는 "CANCELED" 상태에 대한 처리가 누락되어 있습니다.
  • 취소된 티켓에 대해 별도의 UI 처리를 추가해 주시기 바랍니다. 예를 들어, 아래와 같이 분기 처리를 추가하는 것을 고려해 보세요:
{orderStatus === "CANCELED" && (
  // 취소된 티켓에 대한 UI 처리 로직 추가
)}

해당 변경이 다른 컴포넌트나 페이지와 연계되어 있는지 추가 검토하시고, 필요한 부분에 반영해 주시기 바랍니다.

checkIn: boolean;
hashtags: [];
};

const MyTicketPage = () => {
Expand All @@ -36,6 +39,7 @@ const MyTicketPage = () => {
try {
const response = await readMyTickets.get(0, 10);
setMyTickets(response.result || []);
console.log(response.result);
} catch (error) {
console.error("티켓 목록 불러오기 실패:", error);
}
Expand All @@ -50,13 +54,13 @@ const MyTicketPage = () => {
{myTickets.map((ticket, index) => (
<EventCard
key={index}
img={ticket.bannerImageUrl}
eventTitle={ticket.title}
dDay={ticket.remainDays}
host={ticket.hostChannelName}
eventDate={ticket.startDate}
location={ticket.address}
hashtags={ticket.hashtags}
img={ticket.event.bannerImageUrl}
eventTitle={ticket.event.title}
dDay={ticket.event.remainDays}
host={ticket.event.hostChannelName}
eventDate={ticket.event.startDate}
location={ticket.event.address}
hashtags={ticket.event.hashtags}
onClick={() => {
setSelectedTicket(ticket);
setIsModalOpen(true);
Expand Down Expand Up @@ -86,16 +90,16 @@ const MyTicketPage = () => {
isChecked={true}
iconPath1={<img src={QRbackground} alt="QRbackground" />}
ticketQrCode = {selectedTicket.ticketQrCode}
title={selectedTicket.title}
hostName={selectedTicket.hostChannelName}
date={selectedTicket.startDate}
location={selectedTicket.address}
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.remainDays}
remainDays={selectedTicket.event.remainDays}
onClick={() => setIsModalOpen(false)}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/shared/ui/EventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const EventCard = ({ img, eventTitle, dDay, host, eventDate, location, hashtags,
{children}
{/* 해시태그 */}
<div className="flex flex-wrap w-full h-6 mt-2 overflow-hidden text-xs font-semibold text-gray-700 whitespace-nowrap">
{hashtags.map((tag, index) => (
{(hashtags ?? []).map((tag, index) => (
<span key={index} className="flex items-center justify-center h-6 px-2 mr-2 bg-gray-200 rounded last:mr-0">
{tag}
</span>
Expand Down
26 changes: 16 additions & 10 deletions src/widgets/event/ui/OrganizerInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import { hostInfo } from '../../../shared/types/hostInfoType';
import phoneImg from '../../../../public/assets/event-manage/details/Phone.svg';
import emailImg from '../../../../public/assets/event-manage/details/Email.svg';

const OrganizerInfo = () => {
const host = hostInfo.find(host => host.id === 1);
if (!host) return null;
interface OrganizerInfoProps {
name: string;
description: string;
phone: string;
email: string;
}

const OrganizerInfo = ({ name, description, phone, email}: OrganizerInfoProps) => {

return (
<div className="flex flex-col w-full h-full bg-gray-100 px-4 py-3 md:px-6 md:py-4 rounded-[10px] gap-1">
<h1 className="font-bold text-lg">주최자</h1>
<span className="font-semibold">{host.name}</span>
<span className="text-sm md:text-base">{host.description}</span>
<span className="font-semibold">{name}</span>
<span className="text-sm md:text-base">{description}</span>
<div className="flex gap-3">
<img src={host.phoneImg} alt="번호 이미지" />
<span className="text-sm md:text-base">{host.phone}</span>
<img src={phoneImg} alt="번호 이미지" />
<span className="text-sm md:text-base">{phone}</span>
</div>
<div className="flex gap-3">
<img src={host.emailImg} alt="이메일 이미지" />
<span className="text-sm md:text-base">{host.email}</span>
<img src={emailImg} alt="이메일 이미지" />
<span className="text-sm md:text-base">{email}</span>
</div>
</div>
);
Expand Down
Loading