-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
634 additions
and
8 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { getAccessToken } from '@/utils/server/token'; | ||
import { NextRequest } from 'next/server'; | ||
|
||
export const GET = async (req: NextRequest) => { | ||
const baseurl = `${process.env.API_URL}`; | ||
const pathname = `/board/schedule`; | ||
const boardId = req.nextUrl.searchParams.get('boardId'); | ||
let accesstoken = await getAccessToken(); | ||
let token = accesstoken?.value || process.env.ACCESS_TOKEN; | ||
|
||
return await fetch(`${baseurl}${pathname}/${boardId}`, { | ||
method: 'GET', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: `Bearer ${token}`, | ||
}, | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
'use client'; | ||
|
||
import useModal from '@/hooks/useModal'; | ||
import * as styles from '@/styles/country/board/id/schedule-button.css'; | ||
import Image from 'next/image'; | ||
import ScheduleModal from './ScheduleModal'; | ||
|
||
const ScheduleButton = ({ | ||
startDate, | ||
endDate, | ||
country, | ||
boardId, | ||
}: { | ||
startDate: string; | ||
endDate: string; | ||
country: string; | ||
boardId: number; | ||
}) => { | ||
const { isOpen, openModal, closeModal } = useModal(); | ||
|
||
const clickHandler = () => { | ||
if (isOpen) closeModal(); | ||
else openModal(); | ||
}; | ||
|
||
return ( | ||
<div className={styles.infoContainer} onClick={clickHandler}> | ||
<p className={styles.infoTitle}>여행 일정</p> | ||
<button className={styles.scheduleButton}> | ||
<div className={styles.dateContainer}> | ||
<Image | ||
className={styles.calendarIcon} | ||
src="/icons/color_calendar.png" | ||
width={18} | ||
height={18} | ||
alt="calendarIcon" | ||
/> | ||
<span className={styles.dateText}> | ||
{startDate} ~ {endDate} | ||
</span> | ||
</div> | ||
<div className={styles.explain}>눌러서 여행 일정 확인하기!</div> | ||
</button> | ||
<ScheduleModal | ||
isOpen={isOpen} | ||
closeModal={clickHandler} | ||
boardId={boardId} | ||
startDate={startDate} | ||
endDate={endDate} | ||
country={country} | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ScheduleButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import ScheduleListItem from './ScheduleListItem'; | ||
import * as styles from '@/styles/write/thirdstep/schedule-list.css'; | ||
import { SchedulePlaceType } from '@/types/country/place'; | ||
|
||
type Props = { | ||
placeList: { [key: string]: SchedulePlaceType[] }; | ||
mapHandler: (date: string, index: number) => void; | ||
dateArray: string[]; | ||
}; | ||
|
||
const ScheduleList = ({ placeList, mapHandler, dateArray }: Props) => { | ||
return ( | ||
<div className={styles.container}> | ||
<ul className={styles.listContainer}> | ||
{dateArray.map((date, index) => ( | ||
<li className={styles.listItemContainer} key={date}> | ||
<span className={styles.listItemLine}></span> | ||
<ScheduleListItem | ||
day={index + 1} | ||
date={date} | ||
data={placeList[date]} | ||
mapHandler={mapHandler} | ||
/> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ScheduleList; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import Image from 'next/image'; | ||
import * as styles from '@/styles/write/thirdstep/schedule-list-item.css'; | ||
import { SchedulePlaceType } from '@/types/country/place'; | ||
import { container, place } from '@/styles/write/thirdstep/schedule-place.css'; | ||
|
||
type Props = { | ||
date: string; | ||
day: number; | ||
data: SchedulePlaceType[]; | ||
mapHandler: (date: string, index: number) => void; | ||
}; | ||
|
||
const ScheduleListItem = ({ date, day, data, mapHandler }: Props) => { | ||
return ( | ||
<div className={styles.container}> | ||
<div className={styles.dateContainer}> | ||
<span className={styles.dayCircle}></span> | ||
<div className={styles.dayContainer}> | ||
<Image | ||
className={styles.airplaneIcon} | ||
src="/icons/write_airplane.svg" | ||
width={16} | ||
height={16} | ||
alt="airplane_icon" | ||
/> | ||
<span>Day {day}</span> | ||
</div> | ||
<span className={styles.date}>{date}</span> | ||
<div className={styles.mapButton} onClick={() => mapHandler(date, -1)}> | ||
<Image | ||
className={styles.mapIcon} | ||
src="/icons/mini_map.svg" | ||
width={15} | ||
height={15} | ||
alt="mapIcon" | ||
/> | ||
<span>지도</span> | ||
</div> | ||
</div> | ||
<div className={styles.schedulePlaceContainer}> | ||
<ul className={styles.listOrderContainer}> | ||
{data.map((element, index) => ( | ||
<li className={styles.listOrderItem} key={element.boardScheduleId}> | ||
<span className={styles.listLine}></span> | ||
<span className={styles.listNumber}>{index + 1}</span> | ||
</li> | ||
))} | ||
</ul> | ||
|
||
<ul className={styles.placeListContainer}> | ||
{data.map((element, index) => ( | ||
<li | ||
key={element.boardScheduleId} | ||
onClick={() => mapHandler(date, index)} | ||
> | ||
<div className={container}> | ||
<span className={place}>{element.placeName}</span> | ||
</div> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ScheduleListItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import { useCallback, useEffect, useRef, useState } from 'react'; | ||
import { | ||
GoogleMap, | ||
Libraries, | ||
LoadScript, | ||
OverlayView, | ||
} from '@react-google-maps/api'; | ||
import { SchedulePlaceType } from '@/types/country/place'; | ||
import ScheduleMapMarker from '@/components/write/board/thirdstep/ScheduleMapMarker'; | ||
import { mapContainer } from '@/styles/country/board/id/schedule-modal.css'; | ||
|
||
type Props = { | ||
placeList: { [key: string]: SchedulePlaceType[] }; | ||
date: string; | ||
index: number; | ||
country: string; | ||
}; | ||
|
||
const libraries: Libraries = ['places']; | ||
|
||
const ScheduleMap = ({ placeList, date, index, country }: Props) => { | ||
const mapRef = useRef<google.maps.Map | null>(null); | ||
const [countryCenter, setCountryCenter] = useState<google.maps.LatLngLiteral>( | ||
{ lat: 0, lng: 0 }, | ||
); | ||
const [center, setCenter] = useState<google.maps.LatLngLiteral>({ | ||
lat: 0, | ||
lng: 0, | ||
}); | ||
const [markers, setMarkers] = useState<google.maps.LatLngLiteral[]>([]); | ||
const [zoom, setZoom] = useState<number>(6); | ||
|
||
const onLoad = useCallback((map: google.maps.Map) => { | ||
getCountryLocation(); | ||
mapRef.current = map; | ||
}, []); | ||
|
||
const defaultMapContainerStyle = { | ||
width: '100%', | ||
height: '100%', | ||
}; | ||
|
||
const getCountryLocation = () => { | ||
const geocoder = new window.google.maps.Geocoder(); | ||
// 나라 중심으로 처음에 지도 설정 | ||
geocoder.geocode({ address: country }, (results, status) => { | ||
if (status === 'OK' && results && results[0]) { | ||
const location = results[0].geometry.location; | ||
setCountryCenter({ | ||
lat: location.lat(), | ||
lng: location.lng(), | ||
}); | ||
} else { | ||
console.error('Geocode failed: ' + status); | ||
} | ||
}); | ||
}; | ||
|
||
useEffect(() => { | ||
if (placeList[date] !== undefined) { | ||
const dateMarkers = placeList[date].map((e) => { | ||
return { lat: e.pointX, lng: e.pointY }; | ||
}); | ||
setMarkers(dateMarkers); | ||
} | ||
}, [date, placeList[date]]); | ||
|
||
useEffect(() => { | ||
let zoom = 15; | ||
let lat = countryCenter.lat; | ||
let lng = countryCenter.lng; | ||
|
||
if (index === -1) { | ||
// 지도 버튼 클릭했을 때 index = -1 | ||
index = 0; | ||
zoom = 6; | ||
} | ||
|
||
if (placeList[date] !== undefined) { | ||
if (placeList[date][index]) { | ||
lat = placeList[date][index].pointX; | ||
lng = placeList[date][index].pointY; | ||
} else { | ||
zoom = 6; | ||
} | ||
} | ||
setZoom(zoom); | ||
setCenter({ lat, lng }); | ||
}, [date, index]); | ||
|
||
useEffect(() => { | ||
if (mapRef.current) { | ||
mapRef.current.setZoom(zoom); | ||
} | ||
}, [zoom]); | ||
|
||
useEffect(() => { | ||
if (mapRef.current) { | ||
mapRef.current.panTo(center); | ||
} | ||
}, [center]); | ||
|
||
return ( | ||
<LoadScript | ||
googleMapsApiKey={process.env.NEXT_PUBLIC_GOOGLE_MAP_API_KEY || ''} | ||
libraries={libraries} | ||
> | ||
<div className={mapContainer}> | ||
<GoogleMap | ||
mapContainerStyle={defaultMapContainerStyle} | ||
center={countryCenter} | ||
zoom={6} | ||
onLoad={onLoad} | ||
options={{ | ||
mapTypeControl: false, | ||
fullscreenControl: false, | ||
streetViewControl: false, | ||
}} | ||
> | ||
{markers.map((marker, index) => ( | ||
<OverlayView | ||
key={index} | ||
position={marker} | ||
mapPaneName={OverlayView.OVERLAY_MOUSE_TARGET} | ||
> | ||
<ScheduleMapMarker index={index} /> | ||
</OverlayView> | ||
))} | ||
</GoogleMap> | ||
</div> | ||
</LoadScript> | ||
); | ||
}; | ||
|
||
export default ScheduleMap; |
Oops, something went wrong.