Skip to content

Commit

Permalink
design : 홈 화면에 찜 많은 순,예약 많은 순으로 숙소 보여주기
Browse files Browse the repository at this point in the history
  • Loading branch information
kyumho kim committed Feb 8, 2024
1 parent 8971072 commit 4c495d7
Show file tree
Hide file tree
Showing 6 changed files with 316 additions and 12 deletions.
4 changes: 4 additions & 0 deletions src/components/Main.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react'
import HomeBanner from './HomeBanner'
import RecentHotels from './hotel/RecentHotels'
import HotelOrderByLikes from './hotel/HotelOrderByLikes'
import HotelOrderByReservationCnt from './hotel/HotelOrderByReservationCnt'

export default function Main() {
return (
Expand All @@ -10,6 +12,8 @@ export default function Main() {
</div>
<div className='min-h-[30vh]'>
<RecentHotels />
<HotelOrderByLikes />
<HotelOrderByReservationCnt />
</div>
</section>
)
Expand Down
120 changes: 120 additions & 0 deletions src/components/hotel/HotelOrderByLikes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
'use client'

import React from 'react'

import { useHotelsSortedByLikes } from '@/hooks/useHotel'
import Image from 'next/image'
import Link from 'next/link'

import 'swiper/css'
import 'swiper/css/navigation'
import 'swiper/css/pagination'

import { Swiper, SwiperSlide } from 'swiper/react'
import { Navigation, Scrollbar, Autoplay, Grid } from 'swiper/modules'
import SwiperCore from 'swiper'
import { MdChevronLeft, MdChevronRight } from 'react-icons/md'
import { AiFillHeart } from 'react-icons/ai'
import { FaSpinner } from 'react-icons/fa'

export default function HotelOrderByLikes() {
const {
hotelsSortedByLikes,
isLoading,
isFetching,
isError,
error,
isPlaceholderData,
} = useHotelsSortedByLikes(0, 20)

if (isLoading || isFetching) {
return (
<div className='flex mt-48 text-coral-500 justify-center items-center'>
<FaSpinner className='animate-spin' size='2em' />
</div>
)
}

const { content, totalPages } = hotelsSortedByLikes.objData

SwiperCore.use([Navigation, Scrollbar, Autoplay])

return (
<div className='swiper-container h-auto w-[80vw] mx-auto mt-16 relative'>
<h1 className='text-xl font-bold'># 인기 추천 숙소</h1>
<Swiper
slidesPerView={2}
slidesPerGroup={2}
grid={{ rows: 2, fill: 'row' }}
spaceBetween={10}
navigation={{
nextEl: '.next-slide-button2',
prevEl: '.prev-slide-button2',
}}
modules={[Navigation, Grid]}
breakpoints={{
780: {
slidesPerView: 4,
slidesPerGroup: 4,
grid: {
rows: 1,
},
},
1024: {
slidesPerView: 5,
slidesPerGroup: 5,
spaceBetween: 20,
grid: {
rows: 1,
},
},
}}>
{content.map((hotel) => (
<SwiperSlide key={hotel.id}>
<div>
<Link
href={`/hotel/${hotel.id}`}
className='flex flex-col w-full h-full mt-10'>
<Image
src={hotel.imagesResponse.imageUrl[0]}
alt={hotel.nickname}
width={1000}
height={1000}
objectFit='cover'
layout='responsive'
/>
<div className='flex flex-col'>
<p className='text-xs text-gray-500 mt-2'>
{hotel?.hotelType}
</p>
{/* nickname과 price를 같은 크기로 설정하고 검정색으로 설정 */}
<p className='text-md font-sm text-black '>
{hotel?.nickname}
</p>
<p className='text-xs text-gray-500 mt-1'>
{hotel?.address}, {hotel.addressDetail}
</p>
<p className='text-md font-sm text-black mt-1'>
{hotel?.price}
</p>
<div className='flex items-center bg-pink-200 w-2/3 text-white p-1 rounded-lg'>
<AiFillHeart className='mr-1' size='1.5em' />{' '}
{hotel?.likesCount}
</div>
</div>
</Link>
</div>
</SwiperSlide>
))}
</Swiper>
{/* 이전 슬라이드 버튼 */}
<div className='prev-slide-button2 absolute left-[-30px] top-1/2 -translate-y-1/2 z-10 flex items-center justify-center bg-white rounded-full p-1 shadow-lg border border-gray-200'>
<MdChevronLeft size='2em' className='text-gray-600' />
</div>

<div className='next-slide-button2 absolute right-[-30px] top-1/2 -translate-y-1/2 z-10 flex items-center justify-center bg-white rounded-full p-1 shadow-lg border border-gray-200'>
<MdChevronRight size='2em' className='text-gray-600' />
</div>
</div>
)
}
117 changes: 117 additions & 0 deletions src/components/hotel/HotelOrderByReservationCnt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
'use client'

import React from 'react'

import { useHotelsSortedByReservation } from '@/hooks/useHotel'
import Image from 'next/image'
import Link from 'next/link'

import 'swiper/css'
import 'swiper/css/navigation'
import 'swiper/css/pagination'

import { Swiper, SwiperSlide } from 'swiper/react'
import { Navigation, Scrollbar, Autoplay, Grid } from 'swiper/modules'
import SwiperCore from 'swiper'
import { MdChevronLeft, MdChevronRight } from 'react-icons/md'
import { AiFillFire } from 'react-icons/ai'

export default function HotelOrderByReservationCnt() {
const {
hotelsSortedByReservation,
isLoading,
isFetching,
isError,
error,
isPlaceholderData,
} = useHotelsSortedByReservation(0, 20)

if (isLoading || isFetching) {
return <div></div>
}

const { content, totalPages } = hotelsSortedByReservation.objData

console.log(content)

SwiperCore.use([Navigation, Scrollbar, Autoplay])

return (
<div className='swiper-container h-auto w-[80vw] mx-auto mt-16 relative'>
<h1 className='text-xl font-bold'># 마감 임박 숙소</h1>
<Swiper
slidesPerView={2}
slidesPerGroup={2}
grid={{ rows: 2, fill: 'row' }}
spaceBetween={10}
navigation={{
nextEl: '.next-slide-button3',
prevEl: '.prev-slide-button3',
}}
modules={[Navigation, Grid]}
breakpoints={{
780: {
slidesPerView: 4,
slidesPerGroup: 4,
grid: {
rows: 1,
},
},
1024: {
slidesPerView: 5,
slidesPerGroup: 5,
spaceBetween: 20,
grid: {
rows: 1,
},
},
}}>
{content.map((hotel) => (
<SwiperSlide key={hotel.id}>
<div>
<Link
href={`/hotel/${hotel.id}`}
className='flex flex-col w-full h-full mt-10'>
<Image
src={hotel.imagesResponse.imageUrl[0]}
alt={hotel.nickname}
width={1000}
height={1000}
objectFit='cover'
layout='responsive'
/>
<div className='flex flex-col'>
<p className='text-xs text-gray-500 mt-2'>
{hotel?.hotelType}
</p>
{/* nickname과 price를 같은 크기로 설정하고 검정색으로 설정 */}
<p className='text-md font-sm text-black '>
{hotel?.nickname}
</p>
<p className='text-xs text-gray-500 mt-1'>
{hotel?.address}, {hotel.addressDetail}
</p>
<p className='text-md font-sm text-black mt-1'>
{hotel?.price}
</p>
<div className='flex items-center bg-red-200 w-2/3 text-white p-1 rounded-lg'>
<AiFillFire className='mr-1' size='1.5em' />
예약 {hotel?.reservationCountResponse.reservationsCount}
</div>
</div>
</Link>
</div>
</SwiperSlide>
))}
</Swiper>
{/* 이전 슬라이드 버튼 */}
<div className='prev-slide-button3 absolute left-[-30px] top-1/2 -translate-y-1/2 z-10 flex items-center justify-center bg-white rounded-full p-1 shadow-lg border border-gray-200'>
<MdChevronLeft size='2em' className='text-gray-600' />
</div>

<div className='next-slide-button3 absolute right-[-30px] top-1/2 -translate-y-1/2 z-10 flex items-center justify-center bg-white rounded-full p-1 shadow-lg border border-gray-200'>
<MdChevronRight size='2em' className='text-gray-600' />
</div>
</div>
)
}
5 changes: 0 additions & 5 deletions src/components/hotel/LatestHotelsCarousel.js

This file was deleted.

12 changes: 5 additions & 7 deletions src/components/hotel/RecentHotels.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ export default function RecentHotels() {
return <div></div>
}

console.log(hotels)

const { content, totalPages } = hotels.objData

SwiperCore.use([Navigation, Scrollbar, Autoplay])
Expand All @@ -37,8 +35,8 @@ export default function RecentHotels() {
grid={{ rows: 2, fill: 'row' }}
spaceBetween={10}
navigation={{
nextEl: '.next-slide-button',
prevEl: '.prev-slide-button',
nextEl: '.next-slide-button1',
prevEl: '.prev-slide-button1',
}}
modules={[Navigation, Grid]}
breakpoints={{
Expand Down Expand Up @@ -66,7 +64,7 @@ export default function RecentHotels() {
className='flex flex-col w-full h-full mt-10'>
<Image
src={hotel.imagesResponse.imageUrl[0]}
alt={hotel.name}
alt={hotel.nickname}
width={1000}
height={1000}
objectFit='cover'
Expand All @@ -93,11 +91,11 @@ export default function RecentHotels() {
))}
</Swiper>
{/* 이전 슬라이드 버튼 */}
<div className='prev-slide-button absolute left-[-30px] top-1/2 -translate-y-1/2 z-10 flex items-center justify-center bg-white rounded-full p-1 shadow-lg border border-gray-200'>
<div className='prev-slide-button1 absolute left-[-30px] top-1/2 -translate-y-1/2 z-10 flex items-center justify-center bg-white rounded-full p-1 shadow-lg border border-gray-200'>
<MdChevronLeft size='2em' className='text-gray-600' />
</div>

<div className='next-slide-button absolute right-[-30px] top-1/2 -translate-y-1/2 z-10 flex items-center justify-center bg-white rounded-full p-1 shadow-lg border border-gray-200'>
<div className='next-slide-button1 absolute right-[-30px] top-1/2 -translate-y-1/2 z-10 flex items-center justify-center bg-white rounded-full p-1 shadow-lg border border-gray-200'>
<MdChevronRight size='2em' className='text-gray-600' />
</div>
</div>
Expand Down
70 changes: 70 additions & 0 deletions src/hooks/useHotel.js
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,73 @@ export const useSearchHotels = (
isPlaceholderData,
}
}

const fetchHotelsSortedByLikes = async (page, size) => {
const { data } = await axios.get(
`/api/v1/hotels/likes-sorted?page=${page}&size=${size}`
)

console.log('fetchHotelsSortedByLikes')

return data
}

export const useHotelsSortedByLikes = (page, size) => {
const {
data: hotelsSortedByLikes,
isLoading,
isFetching,
isError,
error,
isPlaceholderData,
} = useQuery({
queryKey: ['hotelsSortedByLikes', page, size],
queryFn: () => fetchHotelsSortedByLikes(page, size),
retry: 0,
placeholderData: keepPreviousData,
})

return {
hotelsSortedByLikes,
isLoading,
isFetching,
isError,
error,
isPlaceholderData,
}
}

const fetchHotelsSortedByReservation = async (page, size) => {
const { data } = await axios.get(
`/api/v1/hotels/reservation-sorted?page=${page}&size=${size}`
)

console.log('fetchHotelsSortedByReservation')

return data
}

export const useHotelsSortedByReservation = (page, size) => {
const {
data: hotelsSortedByReservation,
isLoading,
isFetching,
isError,
error,
isPlaceholderData,
} = useQuery({
queryKey: ['hotelsSortedByReservation', page, size],
queryFn: () => fetchHotelsSortedByReservation(page, size),
retry: 0,
placeholderData: keepPreviousData,
})

return {
hotelsSortedByReservation,
isLoading,
isFetching,
isError,
error,
isPlaceholderData,
}
}

0 comments on commit 4c495d7

Please sign in to comment.