diff --git a/frontend/src/components/Switch/Switch.styled.ts b/frontend/src/components/Switch/Switch.styled.ts index 8f55d2c46..6fdb9de94 100644 --- a/frontend/src/components/Switch/Switch.styled.ts +++ b/frontend/src/components/Switch/Switch.styled.ts @@ -19,6 +19,7 @@ export const SwitchButton = styled.button<{ selected: boolean }>` font-size: 1rem; background-color: ${({ theme, selected }) => (selected ? theme.primary[500] : theme.gray[100])}; color: ${({ theme, selected }) => (selected ? theme.white : theme.black[500])}; + cursor: pointer; &:last-of-type { margin-right: 0; diff --git a/frontend/src/constants/routes.tsx b/frontend/src/constants/routes.tsx index 147693ba1..314e67824 100644 --- a/frontend/src/constants/routes.tsx +++ b/frontend/src/constants/routes.tsx @@ -1,5 +1,6 @@ import React, { ReactNode } from 'react'; import GuestMain from 'pages/GuestMain/GuestMain'; +import GuestMapContainer from 'pages/GuestMap/GuestMapContainer'; import ManagerMapList from 'pages/ManagerMapList/ManagerMapList'; import PATH from './path'; @@ -55,7 +56,7 @@ export const PUBLIC_ROUTES: Route[] = [ }, { path: PATH.GUEST_MAP, - component: , + component: , }, { path: PATH.GUEST_RESERVATION, diff --git a/frontend/src/hooks/useTimePicker.ts b/frontend/src/hooks/useTimePicker.ts index 6b5e64b22..fdafc9415 100644 --- a/frontend/src/hooks/useTimePicker.ts +++ b/frontend/src/hooks/useTimePicker.ts @@ -3,7 +3,7 @@ import { MouseEventHandler, useState } from 'react'; import { Step } from 'components/TimePicker/TimePicker'; import { Midday, Range, Time } from 'types/time'; -type SelectedTime = keyof Range | null; +export type SelectedTime = keyof Range | null; interface Props { initialStartTime?: Date; diff --git a/frontend/src/pages/GuestMap/GuestMap.styles.ts b/frontend/src/pages/GuestMap/GuestMap.styles.ts index 5e5342731..a4f297e9f 100644 --- a/frontend/src/pages/GuestMap/GuestMap.styles.ts +++ b/frontend/src/pages/GuestMap/GuestMap.styles.ts @@ -13,47 +13,6 @@ export const MapContainer = styled.div` position: relative; `; -export const MapItem = styled.div<{ width: number; height: number }>` - flex: 1; - padding: 1.5rem; - min-width: ${({ width }) => width}px; - min-height: ${({ height }) => height}px; - display: flex; - justify-content: center; - align-items: center; - - @media (max-width: ${({ width }) => width}px) { - position: absolute; - top: 0; - left: 0; - } -`; - -export const Space = styled.g` - cursor: pointer; -`; - -export const SpaceRect = styled.rect` - &:hover { - opacity: 0.5; - } -`; - -export const SpacePolygon = styled.polygon` - &:hover { - opacity: 0.5; - } -`; - -export const SpaceAreaText = styled.text` - dominant-baseline: middle; - text-anchor: middle; - fill: ${({ theme }) => theme.black[700]}; - font-size: 1rem; - pointer-events: none; - user-select: none; -`; - export const SelectBox = styled.div` display: flex; flex-direction: column; diff --git a/frontend/src/pages/GuestMap/GuestMap.tsx b/frontend/src/pages/GuestMap/GuestMap.tsx index b535807aa..17e6e9b67 100644 --- a/frontend/src/pages/GuestMap/GuestMap.tsx +++ b/frontend/src/pages/GuestMap/GuestMap.tsx @@ -1,38 +1,42 @@ import { AxiosError } from 'axios'; import dayjs, { Dayjs } from 'dayjs'; -import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; +import { useContext, useEffect, useMemo, useRef, useState } from 'react'; import { useMutation } from 'react-query'; import { useHistory, useLocation, useParams } from 'react-router-dom'; import { deleteGuestReservation } from 'api/guestReservation'; import Header from 'components/Header/Header'; -import { EDITOR } from 'constants/editor'; import MESSAGE from 'constants/message'; -import PALETTE from 'constants/palette'; -import PATH, { HREF } from 'constants/path'; -import useGuestMap from 'hooks/query/useGuestMap'; +import { HREF } from 'constants/path'; import useGuestReservations from 'hooks/query/useGuestReservations'; import useGuestSpaces from 'hooks/query/useGuestSpaces'; import { AccessTokenContext } from 'providers/AccessTokenProvider'; -import { Area, MapDrawing, MapItem, Reservation, ScrollPosition, Space } from 'types/common'; -import { DrawingAreaShape } from 'types/editor'; +import { Area, MapItem, Reservation, ScrollPosition, Space } from 'types/common'; import { GuestPageURLParams } from 'types/guest'; import { ErrorResponse } from 'types/response'; import { formatDate } from 'utils/datetime'; -import { getPolygonCenterPoint } from 'utils/editor'; import { isNullish } from 'utils/type'; import * as Styled from './GuestMap.styles'; +import { GuestMapFormContext } from './providers/GuestMapFormProvider'; import Aside from './units/Aside'; +import GuestMapDrawing from './units/GuestMapDrawing'; import LoginPopup from './units/LoginPopup'; import PasswordInputModal from './units/PasswordInputModal'; +export const SWITCH_LABEL_LIST = ['예약하기', '예약현황']; + export interface GuestMapState { spaceId?: Space['id']; targetDate?: Dayjs; scrollPosition?: ScrollPosition; } -const GuestMap = (): JSX.Element => { +interface GuestMapProps { + map: MapItem; +} + +const GuestMap = ({ map }: GuestMapProps): JSX.Element => { const { accessToken } = useContext(AccessTokenContext); + const { setSelectedSpaceId: setSelectedSpaceIdForm } = useContext(GuestMapFormContext); const [passwordInputModalOpen, setPasswordInputModalOpen] = useState(false); const [selectedReservation, setSelectedReservation] = useState(); @@ -49,34 +53,16 @@ const GuestMap = (): JSX.Element => { const targetDate = location.state?.targetDate; const scrollPosition = location.state?.scrollPosition; - const [map, setMap] = useState(null); - const mapDrawing = map?.mapDrawing; - useGuestMap( - { sharingMapId }, - { - onError: () => { - history.replace(PATH.NOT_FOUND); - }, - onSuccess: (response) => { - const mapData = response.data; - - try { - setMap({ - ...mapData, - mapDrawing: JSON.parse(mapData.mapDrawing) as MapDrawing, - }); - } catch (error) { - alert(MESSAGE.GUEST_MAP.MAP_DRAWING_PARSE_ERROR); - } - }, - retry: false, - } - ); + const mapDrawing = map.mapDrawing; const [spaceList, setSpaceList] = useState([]); const [selectedSpaceId, setSelectedSpaceId] = useState(spaceId ?? null); const [date, setDate] = useState(targetDate ? dayjs(targetDate).tz() : dayjs().tz()); + const [selectedSwitchLabel, setSelectedSwitchLabel] = useState( + SWITCH_LABEL_LIST[0] + ); + const spaces = useMemo(() => { const result: { [key: string]: Space } = {}; spaceList.forEach((item) => (result[item.id] = item)); @@ -85,9 +71,9 @@ const GuestMap = (): JSX.Element => { }, [spaceList]); useGuestSpaces( - { mapId: map?.mapId as number }, + { mapId: map.mapId }, { - enabled: map?.mapId !== undefined, + enabled: map.mapId !== undefined, onSuccess: (response) => { const { spaces } = response.data; @@ -102,7 +88,7 @@ const GuestMap = (): JSX.Element => { const getReservations = useGuestReservations( { - mapId: map?.mapId as number, + mapId: map.mapId, spaceId: selectedSpaceId as number, date: formatDate(date), }, @@ -123,8 +109,16 @@ const GuestMap = (): JSX.Element => { }, }); + const handleClickSwitch = (label: typeof SWITCH_LABEL_LIST[number]) => { + setSelectedSwitchLabel(label); + }; + const handleClickSpaceArea = (spaceId: number) => { - setSelectedSpaceId(spaceId); + if (selectedSwitchLabel === SWITCH_LABEL_LIST[0]) { + setSelectedSpaceIdForm?.(`${spaceId}`); + } else if (selectedSwitchLabel === SWITCH_LABEL_LIST[1]) { + setSelectedSpaceId(spaceId); + } }; const handleEdit = (reservation: Reservation) => { @@ -133,7 +127,7 @@ const GuestMap = (): JSX.Element => { history.push({ pathname: HREF.GUEST_RESERVATION_EDIT(sharingMapId), state: { - mapId: map?.mapId, + mapId: map.mapId, spaceId: spaces[selectedSpaceId].id, reservation, selectedDate: formatDate(date), @@ -143,22 +137,22 @@ const GuestMap = (): JSX.Element => { }; const deleteLoginReservation = (reservationId: number) => { - if (typeof map?.mapId !== 'number' || selectedSpaceId === null) return; + if (typeof map.mapId !== 'number' || selectedSpaceId === null) return; if (!window.confirm(MESSAGE.GUEST_MAP.DELETE_CONFIRM)) return; removeReservation.mutate({ - mapId: map?.mapId, + mapId: map.mapId, spaceId: selectedSpaceId, reservationId: reservationId, }); }; const handleDeleteGuestReservation = (passwordInput: string) => { - if (typeof map?.mapId !== 'number' || selectedSpaceId === null) return; + if (typeof map.mapId !== 'number' || selectedSpaceId === null) return; removeReservation.mutate({ - mapId: map?.mapId, + mapId: map.mapId, spaceId: selectedSpaceId, password: passwordInput, reservationId: Number(selectedReservation?.id), @@ -180,7 +174,7 @@ const GuestMap = (): JSX.Element => { history.push({ pathname: HREF.GUEST_RESERVATION(sharingMapId), state: { - mapId: map?.mapId, + mapId: map.mapId, spaceId: spaces[selectedSpaceId].id, selectedDate: formatDate(date), scrollPosition: { x: mapRef?.current?.scrollLeft, y: mapRef?.current?.scrollTop }, @@ -205,87 +199,16 @@ const GuestMap = (): JSX.Element => { }, [targetDate]); return ( - - {map &&