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
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
VITE_API_BASE_URL=
VITE_KAKAO_MAP_API_KEY=
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ dist-ssr
*.sw?

*storybook.log
.env
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<script type="module" src="/src/main.tsx"></script>
<script
type="text/javascript"
src="//dapi.kakao.com/v2/maps/sdk.js?appkey=&libraries=services,clusterer&autoload=false"
src="//dapi.kakao.com/v2/maps/sdk.js?appkey=%VITE_KAKAO_MAP_API_KEY%&libraries=services,clusterer&autoload=true"
></script>
</body>
</html>
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"chromatic": "npx chromatic --project-token=chpt_d390af66464013e"
},
"dependencies": {
"@hookform/resolvers": "^4.1.3",
"@tanstack/react-query": "^5.61.3",
"autoprefixer": "^10.4.20",
"axios": "^1.8.1",
Expand All @@ -22,6 +23,7 @@
"postcss": "^8.4.49",
"react": "^18.3.1",
"react-datepicker": "^7.5.0",
"react-daum-postcode": "^3.2.0",
"react-dom": "^18.3.1",
"react-hook-form": "^7.54.2",
"react-kakao-maps-sdk": "^1.1.27",
Expand All @@ -31,6 +33,7 @@
"swiper": "^11.2.1",
"tailwind-scrollbar-hide": "^2.0.0",
"tailwindcss": "^3.4.15",
"zod": "^3.24.2",
"zustand": "^5.0.2"
},
"devDependencies": {
Expand Down
14 changes: 0 additions & 14 deletions src/features/dashboard/ui/KakaoMap.tsx

This file was deleted.

8 changes: 8 additions & 0 deletions src/features/event-manage/event-create/api/eventCreation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { axiosClient } from '../../../../shared/types/api/http-client';
import { CreateEventRequest } from '../model/eventCreation';

const createEvent = async (data: CreateEventRequest) => {
const response = await axiosClient.post('/events', data);
return response.data;
};
export default createEvent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { AxiosError } from 'axios';
import { ApiResponse } from '../../../../shared/types/api/apiResponse';
import createEvent from '../api/eventCreation';
import { CreateEventRequest } from '../model/eventCreation';
import { useMutation } from '@tanstack/react-query';

const useEventCreation = () => {
return useMutation<ApiResponse<null>, AxiosError, CreateEventRequest>({
mutationFn: async (requestBody: CreateEventRequest) => {
return await createEvent(requestBody);
},
});
};
export default useEventCreation;
Original file line number Diff line number Diff line change
@@ -1,27 +1,8 @@
import React, { createContext, ReactNode, useContext, useState } from 'react';
import { CreateEventRequest } from './eventCreation';

export interface FunnelState {
formState: {
hostChannelId: number;
hostProfileImageUrl?: string;
hostChannelName: string;
hostEmail: string;
channelDescription: string;
title: string;
startDate?: string;
startTime: string;
endDate?: string;
endTime: string;
organizerEmail: string;
organizerPhoneNumber: string;
bannerImageUrl: string;
description: string;
referenceLinks: { title: string; url: string }[];
onlineType: 'ONLINE' | 'OFFLINE';
location: string;
category: string;
hashtags: string[];
};
formState: CreateEventRequest;
setFormState: React.Dispatch<React.SetStateAction<FunnelState['formState']>>;
}

Expand All @@ -30,10 +11,6 @@ const FunnelContext = createContext<FunnelState | undefined>(undefined);
export const FunnelProvider = ({ children }: { children: ReactNode }) => {
const [formState, setFormState] = useState<FunnelState['formState']>({
hostChannelId: 0,
hostProfileImageUrl: '',
hostChannelName: '',
hostEmail: '',
channelDescription: '',
title: '',
startDate: '',
startTime: '',
Expand All @@ -45,7 +22,8 @@ export const FunnelProvider = ({ children }: { children: ReactNode }) => {
description: '',
referenceLinks: [],
onlineType: 'ONLINE',
location: '',
address: '',
location: { lat: 37.5665, lng: 126.978 },
category: '',
hashtags: [],
});
Expand Down
18 changes: 18 additions & 0 deletions src/features/event-manage/event-create/model/eventCreation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface CreateEventRequest {
hostChannelId: number;
title: string;
startDate: string;
endDate: string;
startTime: string;
endTime: string;
bannerImageUrl: string;
description: string;
referenceLinks: { address: string; detailAddress: string; title: string; url: string }[];
onlineType: 'ONLINE' | 'OFFLINE';
address: string;
location: { lat: number; lng: number };
category: string;
hashtags: string[];
organizerEmail: string;
organizerPhoneNumber: string;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react';
import CategoryButton from '../../../../public/assets/event-manage/creation/BackBtn(black).svg';
import CategoryButton from '../../../../../public/assets/event-manage/creation/BackBtn(black).svg';
import { FunnelState } from '../model/FunnelContext';

interface Category {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
import HostSelectionPage from '../../../pages/event-manage/ui/HostSelectionPage';
import HostCreationPage from '../../../pages/event-manage/ui/HostCreationPage';
import EventTitlePage from '../../../pages/event-manage/ui/EventTitlePage';
import EventPeriodPage from '../../../pages/event-manage/ui/EventPeriodPage';
import EventInfoPage from '../../../pages/event-manage/ui/EventInfoPage';
import EventTypePage from '../../../pages/event-manage/ui/EventTypePage';
import EventTagPage from '../../../pages/event-manage/ui/EventTagPage';
import EventOrganizerInfoPage from '../../../pages/event-manage/ui/EventOrganizerInfoPage';
import EventRegisterLayout from '../../../shared/ui/backgrounds/EventRegisterLayout';
import HostSelectionPage from '../../../../pages/event-manage/ui/HostSelectionPage';
import HostCreationPage from '../../../../pages/event-manage/ui/HostCreationPage';
import EventTitlePage from '../../../../pages/event-manage/ui/EventTitlePage';
import EventPeriodPage from '../../../../pages/event-manage/ui/EventPeriodPage';
import EventInfoPage from '../../../../pages/event-manage/ui/EventInfoPage';
import EventTypePage from '../../../../pages/event-manage/ui/EventTypePage';
import EventTagPage from '../../../../pages/event-manage/ui/EventTagPage';
import EventOrganizerInfoPage from '../../../../pages/event-manage/ui/EventOrganizerInfoPage';
import EventRegisterLayout from '../../../../shared/ui/backgrounds/EventRegisterLayout';
import { useNavigate } from 'react-router-dom';
import { EventFunnelInterface, StepNames } from '../../../../shared/types/funnelType';
import { useFunnelState } from '../model/FunnelContext';
import { EventFunnelInterface, StepNames } from '../../../shared/types/funnelType';
import useEventCreation from '../hooks/useEventCreationHook';

const EventFunnel = ({ onNext, onPrev, Funnel, Step, currentStep }: EventFunnelInterface) => {
const { formState } = useFunnelState();
const navigate = useNavigate();
const { formState } = useFunnelState();
const { mutate: createEvent } = useEventCreation();

const handleNext = (nextStep: string) => {
console.log('이벤트 주최 데이터:', formState);
onNext(nextStep);
if (currentStep === 7) {
createEvent(formState, {
onSuccess: () => {
navigate('/');
},
onError: error => {
console.error('API 호출 실패:', error);
},
});
} else {
onNext(nextStep);
}
};

return (
Expand All @@ -27,6 +39,7 @@ const EventFunnel = ({ onNext, onPrev, Funnel, Step, currentStep }: EventFunnelI
title="이벤트를 호스팅할 채널을 선택해주세요"
onNext={() => handleNext(String(currentStep + 2))}
onPrev={() => navigate(-1)}
requireValidation={true}
>
<HostSelectionPage onNext={handleNext} currentStep={currentStep} />
</EventRegisterLayout>
Expand All @@ -45,6 +58,7 @@ const EventFunnel = ({ onNext, onPrev, Funnel, Step, currentStep }: EventFunnelI
title="이벤트 제목을 입력해주세요"
onNext={() => handleNext(String(currentStep + 1))}
onPrev={() => onPrev(String(currentStep - 1))}
requireValidation={true}
>
<EventTitlePage />
</EventRegisterLayout>
Expand All @@ -63,6 +77,7 @@ const EventFunnel = ({ onNext, onPrev, Funnel, Step, currentStep }: EventFunnelI
title="이벤트 주최자 정보를 입력해주세요"
onNext={() => handleNext(String(currentStep + 1))}
onPrev={() => onPrev(String(currentStep - 1))}
requireValidation={true}
>
<EventOrganizerInfoPage />
</EventRegisterLayout>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChangeEvent, KeyboardEvent, useState } from 'react';
import { FunnelState } from '../model/FunnelContext';
import MultilineTextField from '../../../../design-system/ui/textFields/MultilineTextField';
import MultilineTextField from '../../../../../design-system/ui/textFields/MultilineTextField';

interface EventTagProps {
formState?: FunnelState['formState'];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
import OnlineIcon from '../../../../public/assets/event-manage/creation/OnlineIcon.svg';
import OfflineIcon from '../../../../public/assets/event-manage/creation/OfflineIcon.svg';
import SearchBar from '../../../shared/ui/SearchBar';
import OnlineIcon from '../../../../../public/assets/event-manage/creation/OnlineIcon.svg';
import OfflineIcon from '../../../../../public/assets/event-manage/creation/OfflineIcon.svg';
import { useFunnelState } from '../model/FunnelContext';
import KakaoMap from '../../../../shared/ui/KakaoMap';
import { AddressSearch } from '../../../../shared/ui/AddressSearch';
import { useState } from 'react';

interface EventTypeProps {
className?: string;
}

const EventType = ({ className }: EventTypeProps) => {
const { formState, setFormState } = useFunnelState();
const [address, setAddress] = useState('');
const [detailAddress, setDetailAddress] = useState('');

const handleTypeClick = (type: 'ONLINE' | 'OFFLINE') => {
setFormState(prev => ({
...prev,
onlineType: type,
}));
};

const handleAddressChange = (address: string) => {
setAddress(address);
setFormState(prev => ({
...prev,
address: `${address} ${detailAddress}`.trim(),
}));
};

const handleDetailAddressChange = (detailAddress: string) => {
setDetailAddress(detailAddress);
setFormState(prev => ({
...prev,
address: `${address} ${detailAddress}`.trim(),
}));
};

const handleLocationChange = (lat: number, lng: number) => {
setFormState(prev => ({
...prev,
location: { lat, lng },
}));
};

return (
<div className={`flex flex-col justify-center w-full ${className}`}>
<div className="flex flex-col justify-start">
Expand Down Expand Up @@ -46,7 +74,13 @@ const EventType = ({ className }: EventTypeProps) => {
{formState.onlineType === 'OFFLINE' && (
<div className="mt-6 space-y-2">
<h1 className="font-bold text-black text-lg">이벤트는 어디서 진행되나요?</h1>
<SearchBar placeholder="장소를 입력하세요." className="w-full" />
<AddressSearch
address={address}
setAddress={handleAddressChange}
onLocationChange={handleLocationChange}
onDetailAddressChange={handleDetailAddressChange}
/>
<KakaoMap lat={formState.location.lat} lng={formState.location.lng} />
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import FileUploadImage from '../../../../public/assets/event-manage/creation/FileUpload.svg';
import FileUploadImage from '../../../../../public/assets/event-manage/creation/FileUpload.svg';

const FileUpload = () => {
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import AddButton from '../../../../public/assets/event-manage/creation/AddBtn.svg';
import CloseButton from '../../../../public/assets/event-manage/creation/CloseBtn.svg';
import Link from '../../../../public/assets/event-manage/creation/Link.svg';
import AddButton from '../../../../../public/assets/event-manage/creation/AddBtn.svg';
import CloseButton from '../../../../../public/assets/event-manage/creation/CloseBtn.svg';
import Link from '../../../../../public/assets/event-manage/creation/Link.svg';
import { FunnelState } from '../model/FunnelContext';

interface LinkInputProps {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import profile from '../../../../public/assets/banners/1.png';
import link from '../../../../public/assets/event-manage/details/Link.svg';
import kakao from '../../../../public/assets/event-manage/details/KaKao.svg';
import profile from '../../../../../public/assets/banners/1.png';
import link from '../../../../../public/assets/event-manage/details/Link.svg';
import kakao from '../../../../../public/assets/event-manage/details/KaKao.svg';

interface ShareEventModalProp {
closeModal: () => void;
Expand Down
6 changes: 3 additions & 3 deletions src/pages/dashboard/ui/EventDetailPage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useNavigate } from 'react-router-dom';
import Button from '../../../../design-system/ui/Button';
import FileUpload from '../../../features/event-manage/ui/FileUpload';
import LinkInput from '../../../features/event-manage/ui/LinkInput';
import TextEditor from '../../../features/event-manage/ui/TextEditor';
import FileUpload from '../../../features/event-manage/event-create/ui/FileUpload';
import LinkInput from '../../../features/event-manage/event-create/ui/LinkInput';
import TextEditor from '../../../features/event-manage/event-create/ui/TextEditor';
import DashboardLayout from '../../../shared/ui/backgrounds/DashboardLayout';

const EventDetailPage = () => {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/dashboard/ui/EventInfoPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import ChoiceChip from '../../../../design-system/ui/ChoiceChip';
import DefaultTextField from '../../../../design-system/ui/textFields/DefaultTextField';
import EventDatePicker from '../../../features/event-manage/ui/DatePicker';
import EventDatePicker from '../../../features/event-manage/event-create/ui/DatePicker';
import DashboardLayout from '../../../shared/ui/backgrounds/DashboardLayout';
import SearchBar from '../../../shared/ui/SearchBar';
import { useNavigate } from 'react-router-dom';
Expand Down
4 changes: 2 additions & 2 deletions src/pages/dashboard/ui/EventTagPage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useNavigate } from 'react-router-dom';
import DashboardLayout from '../../../shared/ui/backgrounds/DashboardLayout';
import Button from '../../../../design-system/ui/Button';
import EventCategory from '../../../features/event-manage/ui/EventCategory';
import EventTag from '../../../features/event-manage/ui/EventTag';
import EventCategory from '../../../features/event-manage/event-create/ui/EventCategory';
import EventTag from '../../../features/event-manage/event-create/ui/EventTag';

const EventTagPage = () => {
const navigate = useNavigate();
Expand Down
2 changes: 1 addition & 1 deletion src/pages/dashboard/ui/mail/EmailEditPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom';
import DashboardLayout from '../../../../shared/ui/backgrounds/DashboardLayout';
import EmailInput from '../../../../features/dashboard/ui/EmailInput';
import { participantsInfo } from '../../../../shared/types/participantInfoType';
import TimePicker from '../../../../features/event-manage/ui/TimePicker';
import TimePicker from '../../../../features/event-manage/event-create/ui/TimePicker';
import Button from '../../../../../design-system/ui/Button';
import SelectTicketModal from '../../../../widgets/dashboard/ui/SelectTicketModal';

Expand Down
2 changes: 1 addition & 1 deletion src/pages/dashboard/ui/mail/EmailPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import DashboardLayout from '../../../../shared/ui/backgrounds/DashboardLayout';
import Button from '../../../../../design-system/ui/Button';
import TimePicker from '../../../../features/event-manage/ui/TimePicker';
import TimePicker from '../../../../features/event-manage/event-create/ui/TimePicker';
import EmailInput from '../../../../features/dashboard/ui/EmailInput';
import { participantsInfo } from '../../../../shared/types/participantInfoType';
import { useState } from 'react';
Expand Down
2 changes: 1 addition & 1 deletion src/pages/dashboard/ui/ticket/TicketCreatePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { TwoOptions } from '../../../../../design-system/stories/ChoiceChip.stor
import ChoiceChip from '../../../../../design-system/ui/ChoiceChip';
import DefaultTextField from '../../../../../design-system/ui/textFields/DefaultTextField';
import Button from '../../../../../design-system/ui/Button';
import EventDatePicker from '../../../../features/event-manage/ui/DatePicker';
import EventDatePicker from '../../../../features/event-manage/event-create/ui/DatePicker';

const TicketCreatePage = () => {
const [price, setPrice] = useState<number>(0);
Expand Down
Loading