diff --git a/package-lock.json b/package-lock.json index 6dfdd286..2ed647cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,6 +28,7 @@ "react-helmet-async": "^2.0.4", "react-hook-form": "^7.49.2", "react-icons": "^4.12.0", + "react-intersection-observer": "^9.5.3", "react-kakao-maps-sdk": "^1.1.24", "react-mobile-datepicker": "^4.0.2", "react-router-dom": "^6.21.1", @@ -10984,6 +10985,14 @@ "react": "*" } }, + "node_modules/react-intersection-observer": { + "version": "9.5.3", + "resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.5.3.tgz", + "integrity": "sha512-NJzagSdUPS5rPhaLsHXYeJbsvdpbJwL6yCHtMk91hc0ufQ2BnXis+0QQ9NBh6n9n+Q3OyjR6OQLShYbaNBkThQ==", + "peerDependencies": { + "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index 6e28e42a..3f46b91c 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "react-helmet-async": "^2.0.4", "react-hook-form": "^7.49.2", "react-icons": "^4.12.0", + "react-intersection-observer": "^9.5.3", "react-kakao-maps-sdk": "^1.1.24", "react-mobile-datepicker": "^4.0.2", "react-router-dom": "^6.21.1", diff --git a/src/api/review.ts b/src/api/review.ts new file mode 100644 index 00000000..238619bb --- /dev/null +++ b/src/api/review.ts @@ -0,0 +1,20 @@ +import axios from 'axios'; + +export const reviewRequest = { + getMyReview: async ({pageParam}: {pageParam: number}) => { + try { + const res = await axios.get('/api/members/my-reviews', { + params: { + size: 5, + page: pageParam, + }, + withCredentials: true, + }); + console.log(res); + + return res.data; + } catch (error) { + console.log(error); + } + }, +}; diff --git a/src/api/spaces.ts b/src/api/spaces.ts index eab1dfdb..1b6a4442 100644 --- a/src/api/spaces.ts +++ b/src/api/spaces.ts @@ -13,6 +13,21 @@ export const spacesRequest = { } }, + getOutdated: async ({pageParam}: {pageParam: number}) => { + try { + const res = await axios.get('/api/members/my-spaces/outdated', { + params: { + size: 5, + page: pageParam, + }, + withCredentials: true, + }); + return res.data; + } catch (error) { + console.log(error); + } + }, + post: async () => { try { const res = await axios.post('/api/spaces', {withCredentials: true}); diff --git a/src/assets/icons/city_default.svg b/src/assets/icons/city_default.svg new file mode 100644 index 00000000..083314f6 --- /dev/null +++ b/src/assets/icons/city_default.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/spinner.gif b/src/assets/spinner.gif new file mode 100644 index 00000000..7d4a4b26 Binary files /dev/null and b/src/assets/spinner.gif differ diff --git a/src/components/Auth/Input/Input.module.scss b/src/components/Auth/Input/Input.module.scss index 2ebe0eea..2e7b91eb 100644 --- a/src/components/Auth/Input/Input.module.scss +++ b/src/components/Auth/Input/Input.module.scss @@ -1,4 +1,4 @@ -@use "@/sass" as *; +@use '@/sass' as *; .email, .sertCode, @@ -124,6 +124,7 @@ height: 7.2rem; padding: 8px; border-radius: 50%; + border: 1px solid $neutral200; &__camera { background-color: $neutral100; diff --git a/src/components/MySpaceBody/MySpaceBody.tsx b/src/components/MySpaceBody/MySpaceBody.tsx index ccb5eeae..b07d032c 100644 --- a/src/components/MySpaceBody/MySpaceBody.tsx +++ b/src/components/MySpaceBody/MySpaceBody.tsx @@ -1,134 +1,18 @@ -import { useEffect, useState } from "react"; +import {useState} from 'react'; -import styles from "./MySpaceBody.module.scss"; +import styles from './MySpaceBody.module.scss'; -import MySpaceList from "./MySpaceList/MySpaceList"; -import Tab from "./Tab/Tab"; - -import { MySpaces } from "@/types/user"; - -const upcomming = [ - { - id: 12312, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2024-01-12", - endDate: "2024-01-14", - dueDate: 0, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, - { - id: 12321, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2024-01-18", - endDate: "2024-01-22", - dueDate: 4, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, - { - id: 12334, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2024-01-18", - endDate: "2024-01-22", - dueDate: 15, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, - { - id: 12343, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2024-01-18", - endDate: "2024-01-22", - dueDate: 15, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, - { - id: 12352, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2024-01-18", - endDate: "2024-01-22", - dueDate: 15, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, - { - id: 12315, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2024-01-18", - endDate: "2024-01-22", - dueDate: 15, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, - { - id: 123253, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2024-01-18", - endDate: "2024-01-22", - dueDate: 15, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, - { - id: 1231617, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2025-01-18", - endDate: "2025-01-22", - dueDate: 418, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, -]; - -const outdated = [ - { - id: 812367, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2023-12-17", - endDate: "2023-12-21", - dueDate: 0, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, - { - id: 867123, - title: "캐리비안베이, 로만바스 온천, 라마드 호텔, 에버랜드", - startDate: "2023-04-17", - endDate: "2023-04-20", - dueDate: 0, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, - { - id: 67123, - title: "강릉, 속초, 전주, 여수 여행", - startDate: "2022-12-29", - endDate: "2022-12-30", - dueDate: 0, - thumbnail: - "https://media.istockphoto.com/id/1356118511/photo/smart-city-and-abstract-dot-point-connect-with-gradient-line.jpg?s=612x612&w=0&k=20&c=GJldTyxDEt0GodKxGONHz9PrN9QcQQAGKONUM0vBvYc=", - }, -]; +import MySpaceList from './MySpaceList/MySpaceList'; +import Tab from './Tab/Tab'; function MySpaceBody() { - const [tab, setTab] = useState("upcomming"); - const [data, setData] = useState(null); - - useEffect(() => { - // const res = await() api호출부 - // const spaces = res.data.data; - // tmp mock data - const spaces = tab === "upcomming" ? upcomming : outdated; - setData(spaces); - }); + const [tab, setTab] = useState('upcoming'); return (
- +
); } diff --git a/src/components/MySpaceBody/MySpaceList/MySpaceList.module.scss b/src/components/MySpaceBody/MySpaceList/MySpaceList.module.scss index 63f2013f..b3ac41dd 100644 --- a/src/components/MySpaceBody/MySpaceList/MySpaceList.module.scss +++ b/src/components/MySpaceBody/MySpaceList/MySpaceList.module.scss @@ -1,4 +1,4 @@ -@use "@/sass" as *; +@use '@/sass' as *; .container { display: flex; @@ -24,9 +24,14 @@ width: 6.6rem; background-position: center; background-size: cover; + background-repeat: no-repeat; background-blend-mode: darken; border-radius: 16px 0px 0px 16px; + &.default { + background-size: 70% 70%; + } + & > span { z-index: 100; @include typography(button); @@ -34,7 +39,7 @@ } &::after { - content: ""; + content: ''; position: absolute; width: 100%; height: 100%; diff --git a/src/components/MySpaceBody/MySpaceList/MySpaceList.tsx b/src/components/MySpaceBody/MySpaceList/MySpaceList.tsx index e47fb7d5..6033d464 100644 --- a/src/components/MySpaceBody/MySpaceList/MySpaceList.tsx +++ b/src/components/MySpaceBody/MySpaceList/MySpaceList.tsx @@ -1,43 +1,73 @@ -import styles from "./MySpaceList.module.scss"; +import styles from './MySpaceList.module.scss'; -import { setSpaceDate } from "@/utils/formatDate"; +import {useGetSpaces, useGetSpacesOut} from '@/hooks/Spaces/useSpaces'; +import {useInfiniteScroll} from '@/hooks/useInfiniteScroll'; -import { MySpaceListProps } from "@/types/user"; +import ObserveTarget from '@/components/Route/ObserveTarget/ObserveTarget'; + +import defaultCity from '@/assets/icons/city_default.svg'; +import {setSpaceDate} from '@/utils/formatDate'; + +import {Spaces} from '@/types/sidebar'; +import {MySpaceListProps} from '@/types/user'; + +function MySpaceList({tab}: MySpaceListProps) { + const {data: upcomingData} = useGetSpaces(true); + const [outdatedData, hasNextData, inViewRef] = useInfiniteScroll(useGetSpacesOut); -function MySpaceList({ data, tab }: MySpaceListProps) { return ( ); } diff --git a/src/components/MySpaceBody/Tab/Tab.tsx b/src/components/MySpaceBody/Tab/Tab.tsx index b67d124d..f9d3f8fa 100644 --- a/src/components/MySpaceBody/Tab/Tab.tsx +++ b/src/components/MySpaceBody/Tab/Tab.tsx @@ -1,36 +1,28 @@ -import styles from "./Tab.module.scss"; +import styles from './Tab.module.scss'; -import { TabProps } from "@/types/user"; +import {TabProps} from '@/types/user'; -function Tab({ tab, setTab }: TabProps) { +function Tab({tab, setTab}: TabProps) { return ( ); } diff --git a/src/components/Route/ObserveTarget/ObserveTarget.module.scss b/src/components/Route/ObserveTarget/ObserveTarget.module.scss new file mode 100644 index 00000000..db63f67f --- /dev/null +++ b/src/components/Route/ObserveTarget/ObserveTarget.module.scss @@ -0,0 +1,10 @@ +@use '@/sass' as *; + +.container { + display: flex; + justify-content: center; + + & > img { + width: 30px; + } +} diff --git a/src/components/Route/ObserveTarget/ObserveTarget.tsx b/src/components/Route/ObserveTarget/ObserveTarget.tsx new file mode 100644 index 00000000..c2de17ab --- /dev/null +++ b/src/components/Route/ObserveTarget/ObserveTarget.tsx @@ -0,0 +1,15 @@ +import {LegacyRef} from 'react'; + +import styles from './ObserveTarget.module.scss'; + +import spinner from '@/assets/spinner.gif'; + +function ObserveTarget({inViewRef}: {inViewRef: LegacyRef}) { + return ( +
+ 데이터 로딩 중 +
+ ); +} + +export default ObserveTarget; diff --git a/src/components/User/Mywork/Mywork.module.scss b/src/components/User/Mywork/Mywork.module.scss index 055963d1..a073ca43 100644 --- a/src/components/User/Mywork/Mywork.module.scss +++ b/src/components/User/Mywork/Mywork.module.scss @@ -1,4 +1,4 @@ -@use "@/sass" as *; +@use '@/sass' as *; .container { display: flex; @@ -35,6 +35,6 @@ } .title { - @include typography(subTitle); + @include typography(tabLabel); } } diff --git a/src/components/User/Profile/Profile.module.scss b/src/components/User/Profile/Profile.module.scss index 32ea1f7b..cde4b547 100644 --- a/src/components/User/Profile/Profile.module.scss +++ b/src/components/User/Profile/Profile.module.scss @@ -1,4 +1,4 @@ -@use "@/sass" as *; +@use '@/sass' as *; .container { } @@ -13,6 +13,7 @@ width: 7.2rem; height: 7.2rem; border-radius: 50%; + border: 1px solid $neutral200; background-position: center; background-repeat: no-repeat; diff --git a/src/components/User/Profile/Profile.tsx b/src/components/User/Profile/Profile.tsx index fa978fde..5d86025c 100644 --- a/src/components/User/Profile/Profile.tsx +++ b/src/components/User/Profile/Profile.tsx @@ -15,7 +15,7 @@ function Profile({data}: ProfileProps) {
-
- - -
- +
-
{rating}
-
{`${setMyReviewDate(visitedAt)} 방문`}
-
+ +
+ +
+
{rating}
-

{content}

+
{`${setMyReviewDate(visitedAt)} 방문`}
+
- {images && } - - ))} +

{content}

+ + {images && } + + )), + )} + {hasNextData && } + ; } + +export interface Reviews { + content: string; + id: number; + images: string[]; + place: Place; + rating: number; + visitedAt: string; +} + +export interface Place { + area: string; + category: string; + id: number; + thumbnail: string; + title: string; +} diff --git a/src/types/user.ts b/src/types/user.ts index a0621cda..47a3c0fc 100644 --- a/src/types/user.ts +++ b/src/types/user.ts @@ -28,6 +28,5 @@ export interface TabProps { } export interface MySpaceListProps { - data: MySpaces | null; tab: string; }