diff --git a/.yarn/cache/@types-daum-postcode-npm-2.0.3-f480b4f904-72283bd2c3.zip b/.yarn/cache/@types-daum-postcode-npm-2.0.3-f480b4f904-72283bd2c3.zip
new file mode 100644
index 00000000..66715a55
Binary files /dev/null and b/.yarn/cache/@types-daum-postcode-npm-2.0.3-f480b4f904-72283bd2c3.zip differ
diff --git a/package.json b/package.json
index 280f4e70..18914cd6 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"@testing-library/react": "^12.1.2",
"@testing-library/react-hooks": "^7.0.2",
"@testing-library/user-event": "^13.5.0",
+ "@types/daum-postcode": "^2.0.3",
"@types/editorjs__header": "^2.6.0",
"@types/jest": "^27.4.0",
"@types/lodash-es": "^4.17.6",
diff --git a/public/index.html b/public/index.html
index 25433363..5b9493d7 100644
--- a/public/index.html
+++ b/public/index.html
@@ -40,6 +40,7 @@
/>
+
diff --git a/src/components/Schedule/ScheduleTemplate/ScheduleTemplate.component.tsx b/src/components/Schedule/ScheduleTemplate/ScheduleTemplate.component.tsx
index 45b7104c..e61862c2 100644
--- a/src/components/Schedule/ScheduleTemplate/ScheduleTemplate.component.tsx
+++ b/src/components/Schedule/ScheduleTemplate/ScheduleTemplate.component.tsx
@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { useFieldArray, useFormContext } from 'react-hook-form';
import { useRecoilValue } from 'recoil';
-import { DatePickerField, InputField, SelectField } from '@/components';
+import { Button, DatePickerField, InputField, RadioButtonField, SelectField } from '@/components';
import { InputSize } from '@/components/common/Input/Input.component';
import * as Styled from './ScheduleTemplate.styled';
import { $generations } from '@/store';
@@ -9,7 +9,7 @@ import { SelectOption } from '@/components/common/Select/Select.component';
import { SessionTemplate } from '../SessionTemplate';
import Plus from '@/assets/svg/plus-20.svg';
import { EventCreateRequest } from '@/types';
-import { ScheduleFormValues } from '@/utils';
+import { LocationType, ScheduleFormValues } from '@/utils';
const DEFAULT_SESSION: EventCreateRequest = {
startedAt: '',
@@ -19,9 +19,12 @@ const DEFAULT_SESSION: EventCreateRequest = {
};
const ScheduleTemplate = () => {
- const { register, control, formState, getValues } = useFormContext();
+ const { register, control, formState, getValues, watch, setValue } =
+ useFormContext();
const generations = useRecoilValue($generations);
+ const locationType = watch('locationType');
+
const { fields, append, remove } = useFieldArray({
name: 'sessions',
control,
@@ -37,6 +40,31 @@ const ScheduleTemplate = () => {
const defaultOption = generationOptions.find(
(option) => option.value === getValues('generationNumber')?.toString(),
);
+ const handleClickAddressSearch = () => {
+ new window.daum.Postcode({
+ async oncomplete(data: { address: string }) {
+ const res = await fetch(
+ `https://dapi.kakao.com/v2/local/search/address?query=${data.address}`,
+ {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: 'KakaoAK cc4af66dc10aa1a20830f3cc62c40a87',
+ },
+ },
+ );
+ const json = await res.json();
+ const roadAddress = json.documents[0].road_address;
+ setValue('locationInfo', {
+ address: roadAddress.address_name,
+ latitude: roadAddress.y,
+ longitude: roadAddress.x,
+ placeName: roadAddress.building_name ?? roadAddress.address_name,
+ });
+ setValue('placeName', roadAddress.building_name);
+ },
+ }).open();
+ };
return (
<>
@@ -66,6 +94,38 @@ const ScheduleTemplate = () => {
defaultDate={getValues('date')}
{...register('date', { required: true })}
/>
+
+
+ 장소
+
+
+
+
+
+
+ {locationType === LocationType.OFFLINE && (
+
+
+
+
+ )}
+
세션 정보
diff --git a/src/components/Schedule/ScheduleTemplate/ScheduleTemplate.styled.ts b/src/components/Schedule/ScheduleTemplate/ScheduleTemplate.styled.ts
index 85092199..4dd16bc6 100644
--- a/src/components/Schedule/ScheduleTemplate/ScheduleTemplate.styled.ts
+++ b/src/components/Schedule/ScheduleTemplate/ScheduleTemplate.styled.ts
@@ -6,7 +6,6 @@ export const ScheduleContent = styled.div`
display: flex;
flex-direction: column;
gap: 2rem;
- height: 36.9rem;
padding: 2.4rem;
background-color: ${theme.colors.white};
border: 0.1rem solid ${theme.colors.gray30};
@@ -43,3 +42,32 @@ export const AddButton = styled.button`
margin-top: 2.4rem;
background-color: transparent;
`;
+
+export const InputLabel = styled.label`
+ ${({ theme }) => css`
+ ${theme.fonts.medium15}
+ display: flex;
+ margin-bottom: 0.6rem;
+ color: ${theme.colors.gray70};
+ `}
+`;
+
+export const RequiredDot = styled.span`
+ width: 0.6rem;
+ min-width: 0.6rem;
+ height: 0.6rem;
+ margin: 0.8rem 0 0 0.6rem;
+ background-color: #eb6963;
+ border-radius: 50%;
+`;
+
+export const RadioButtonGroup = styled.div`
+ display: flex;
+ gap: 2rem;
+ margin-bottom: 1rem;
+`;
+
+export const InputWithButton = styled.div`
+ display: flex;
+ gap: 1rem;
+`;
diff --git a/src/components/ScheduleDetail/ScheduleInfoList/ScheduleInfoList.component.tsx b/src/components/ScheduleDetail/ScheduleInfoList/ScheduleInfoList.component.tsx
index b49e2aad..37dd9dd4 100644
--- a/src/components/ScheduleDetail/ScheduleInfoList/ScheduleInfoList.component.tsx
+++ b/src/components/ScheduleDetail/ScheduleInfoList/ScheduleInfoList.component.tsx
@@ -11,6 +11,10 @@ interface ScheduleInfoListProps {
startedAt: string;
publishedAt?: string;
status: ValueOf;
+ location: {
+ address: string | null;
+ placeName: string;
+ };
}
const ScheduleInfoList = ({
@@ -20,6 +24,7 @@ const ScheduleInfoList = ({
createdAt,
publishedAt,
status,
+ location,
}: ScheduleInfoListProps) => {
const scheduleInfoListItem = useMemo(() => {
return [
@@ -39,6 +44,13 @@ const ScheduleInfoList = ({
label: '등록 일시',
value: formatDate(createdAt, 'YYYY년 M월 D일 A hh시 mm분'),
},
+ {
+ label: '장소',
+ value:
+ location.address === null
+ ? location.placeName
+ : `${location.placeName}, ${location.address}`,
+ },
{
label: '배포 일시',
value: formatDate(publishedAt, 'YYYY년 M월 D일 A hh시 mm분'),
@@ -48,7 +60,7 @@ const ScheduleInfoList = ({
value: getScheduleStatusText(status),
},
];
- }, [createdAt, generationNumber, name, publishedAt, startedAt, status]);
+ }, [createdAt, generationNumber, name, publishedAt, startedAt, status, location]);
return (
diff --git a/src/components/common/RadioButton/RadioButton.styled.ts b/src/components/common/RadioButton/RadioButton.styled.ts
index 1ea0ad75..ee44d722 100644
--- a/src/components/common/RadioButton/RadioButton.styled.ts
+++ b/src/components/common/RadioButton/RadioButton.styled.ts
@@ -67,6 +67,6 @@ export const RadioButtonMark = styled.span`
export const RadioButtonText = styled.span`
${({ theme }) => css`
${theme.fonts.medium14}
- padding-left: 3.8rem;
+ padding-left: 3rem;
`}
`;
diff --git a/src/pages/ScheduleDetail/ScheduleDetail.page.tsx b/src/pages/ScheduleDetail/ScheduleDetail.page.tsx
index e131dd3c..647cb07f 100644
--- a/src/pages/ScheduleDetail/ScheduleDetail.page.tsx
+++ b/src/pages/ScheduleDetail/ScheduleDetail.page.tsx
@@ -29,6 +29,7 @@ const ScheduleDetail = () => {
publishedAt,
status,
eventList: sessionList,
+ location,
} = useRecoilValue($scheduleDetail({ scheduleId: scheduleId ?? '' }));
const isPublished = status === ScheduleStatus.PUBLIC;
@@ -147,6 +148,7 @@ const ScheduleDetail = () => {
createdAt={createdAt}
publishedAt={publishedAt}
status={status}
+ location={location}
/>
diff --git a/src/types/dto/schedule.ts b/src/types/dto/schedule.ts
index 4fd79c8e..4bb70b4e 100644
--- a/src/types/dto/schedule.ts
+++ b/src/types/dto/schedule.ts
@@ -31,6 +31,10 @@ export interface ScheduleCreateRequest {
name: string;
startedAt: string;
eventsCreateRequests: EventCreateRequest[];
+ address?: string;
+ latitude?: number;
+ longitude?: number;
+ placeName?: string;
}
export interface ScheduleUpdateRequest {
@@ -39,6 +43,10 @@ export interface ScheduleUpdateRequest {
name: string;
startedAt: string;
eventsCreateRequests: EventCreateRequest[];
+ address?: string;
+ latitude?: number;
+ longitude?: number;
+ placeName?: string;
}
export interface ScheduleResponse {
@@ -51,6 +59,12 @@ export interface ScheduleResponse {
publishedAt?: string;
eventList: Session[];
status: ValueOf;
+ location: {
+ address: string | null;
+ latitude: number | null;
+ longitude: number | null;
+ placeName: string;
+ };
}
export interface QRCodeRequest {
diff --git a/src/utils/schedule.ts b/src/utils/schedule.ts
index 399c45d0..caaa7a89 100644
--- a/src/utils/schedule.ts
+++ b/src/utils/schedule.ts
@@ -9,11 +9,24 @@ import {
} from '@/types';
import { formatDate, toUtcFormat } from '.';
+export const LocationType = {
+ OFFLINE: 'offline',
+ ONLINE: 'online',
+} as const;
+
export interface ScheduleFormValues {
name: string;
generationNumber: number;
date: Dayjs;
sessions: EventCreateRequest[];
+ locationType: ValueOf;
+ placeName?: string;
+ locationInfo?: {
+ address: string;
+ latitude: string;
+ longitude: string;
+ placeName: string;
+ };
}
export const getScheduleStatusText = (status: ValueOf) => {
@@ -30,7 +43,7 @@ export const getScheduleStatusText = (status: ValueOf) =>
export const parseScheduleResponseToFormValues = (
response: ScheduleResponse,
): ScheduleFormValues => {
- const { name, generationNumber, startedAt, eventList } = response;
+ const { name, generationNumber, startedAt, eventList, location } = response;
const date: Dayjs = dayjs(startedAt, 'YYYY-MM-DD').startOf('day');
@@ -45,18 +58,22 @@ export const parseScheduleResponseToFormValues = (
})),
}));
+ const isOffline = !!location.address;
+
return {
name,
generationNumber,
date,
sessions,
+ locationType: isOffline ? LocationType.OFFLINE : LocationType.ONLINE,
+ placeName: isOffline ? location.placeName : undefined,
};
};
export const parseFormValuesToScheduleRequest = (
formValues: ScheduleFormValues,
): ScheduleCreateRequest | ScheduleUpdateRequest => {
- const { generationNumber, date, sessions, name } = formValues;
+ const { generationNumber, date, sessions, name, locationType, locationInfo } = formValues;
const formattedDate = date.format('YYYY-MM-DD');
@@ -81,5 +98,12 @@ export const parseFormValuesToScheduleRequest = (
eventsCreateRequests,
};
+ if (locationType === LocationType.OFFLINE && locationInfo) {
+ scheduleRequest.address = locationInfo.address;
+ scheduleRequest.latitude = Number(locationInfo.latitude);
+ scheduleRequest.longitude = Number(locationInfo.longitude);
+ scheduleRequest.placeName = locationInfo.placeName;
+ }
+
return scheduleRequest;
};
diff --git a/yarn.lock b/yarn.lock
index 289cee3c..9cdd74b6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3921,6 +3921,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/daum-postcode@npm:^2.0.3":
+ version: 2.0.3
+ resolution: "@types/daum-postcode@npm:2.0.3"
+ checksum: 72283bd2c3bb17073eb1324089e2bc5f5ff6df89c8731e1b9123620328cca0f7b77ac6480a06b5e35c0436c652782af376a896af5044416e2dfb809d040ee728
+ languageName: node
+ linkType: hard
+
"@types/editorjs__header@npm:^2.6.0":
version: 2.6.0
resolution: "@types/editorjs__header@npm:2.6.0"
@@ -12951,6 +12958,7 @@ __metadata:
"@testing-library/react": ^12.1.2
"@testing-library/react-hooks": ^7.0.2
"@testing-library/user-event": ^13.5.0
+ "@types/daum-postcode": ^2.0.3
"@types/editorjs__header": ^2.6.0
"@types/jest": ^27.4.0
"@types/lodash-es": ^4.17.6