-
-
-
-
-
-
-
-
+ isOpen && (
+
+
+
+
+
+
+
+
{userData.nickname}
+
+
+
+
+
+
+
+
-
+ )
);
}
diff --git a/components/Spinner/Spinner.tsx b/components/Spinner/Spinner.tsx
new file mode 100644
index 0000000..fe7bd56
--- /dev/null
+++ b/components/Spinner/Spinner.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+
+export default function Spinner() {
+ return (
+
+ );
+}
diff --git a/hooks/useGetNotification.ts b/hooks/useGetNotification.ts
new file mode 100644
index 0000000..4050f11
--- /dev/null
+++ b/hooks/useGetNotification.ts
@@ -0,0 +1,23 @@
+import { useQuery } from '@tanstack/react-query';
+import {
+ MyNotificationListQuery,
+ MyNotificationListResponse,
+} from '@/pages/api/myNotifications/apiMyNotifications.types';
+import { apiMyNotificationList } from '@/pages/api/myNotifications/apiMyNotifications';
+import useLoginState from './useLoginState';
+
+export default function useGetNotification(query: MyNotificationListQuery) {
+ const { cursorId = undefined, size = 10 } = query;
+ const { isLoggedIn } = useLoginState();
+
+ const { data, isLoading, isError } = useQuery<
+ MyNotificationListResponse,
+ Error
+ >({
+ queryKey: ['myNotification', query],
+ queryFn: () => apiMyNotificationList({ cursorId, size }),
+ enabled: !!isLoggedIn,
+ });
+
+ return { data, isLoading, isError };
+}
diff --git a/hooks/useLogin.ts b/hooks/useLogin.ts
index 7fd33aa..d07cba2 100644
--- a/hooks/useLogin.ts
+++ b/hooks/useLogin.ts
@@ -9,7 +9,6 @@ import useLoginState from './useLoginState';
export default function useLogin() {
const { setIsLoggedIn } = useLoginState();
- const router = useRouter();
const { openPopup } = usePopup();
const postLoginMutation: UseMutationResult<
LoginResponse,
diff --git a/hooks/useLogout.ts b/hooks/useLogout.ts
index 13d87dc..9563b53 100644
--- a/hooks/useLogout.ts
+++ b/hooks/useLogout.ts
@@ -1,12 +1,15 @@
+import { useRouter } from 'next/router';
import useLoginState from './useLoginState';
export default function useLogout() {
const { setIsLoggedIn } = useLoginState();
+ const route = useRouter();
const logout = () => {
localStorage.removeItem('refreshToken');
localStorage.removeItem('userId');
setIsLoggedIn(false);
+ route.push('/');
};
return logout;
diff --git a/hooks/useReservationList.ts b/hooks/useReservationList.ts
new file mode 100644
index 0000000..6b85bca
--- /dev/null
+++ b/hooks/useReservationList.ts
@@ -0,0 +1,21 @@
+import { useQuery } from '@tanstack/react-query';
+import { apiMyReservationList } from '@/pages/api/myReservations/apiMyReservations';
+import { useUserData } from './useUserData';
+import { MyReservationListResponse } from '@/pages/api/myReservations/apiMyReservations.types';
+
+export const useReservationList = () => {
+ const userData = useUserData();
+
+ const { data: myReservationList } = useQuery
({
+ queryKey: ['myReservationList', userData.id],
+ queryFn: () =>
+ apiMyReservationList({
+ cursorId: undefined,
+ size: undefined,
+ status: undefined,
+ }),
+ enabled: !!userData.id,
+ });
+
+ return myReservationList;
+};
diff --git a/hooks/useSideNavigation.ts b/hooks/useSideNavigation.ts
new file mode 100644
index 0000000..41f30a3
--- /dev/null
+++ b/hooks/useSideNavigation.ts
@@ -0,0 +1,16 @@
+import { sideNavigationState } from '@/states/sideNavigationState';
+import { useRecoilState } from 'recoil';
+
+export const useSideNavigation = () => {
+ const [isOpen, setIsOpen] = useRecoilState(sideNavigationState);
+
+ const openSideNavigation = () => {
+ setIsOpen(true);
+ };
+
+ const closeSideNavigation = () => {
+ setIsOpen(false);
+ };
+
+ return { isOpen, openSideNavigation, closeSideNavigation };
+};
diff --git a/hooks/useUserData.ts b/hooks/useUserData.ts
index c647a01..07b77fa 100644
--- a/hooks/useUserData.ts
+++ b/hooks/useUserData.ts
@@ -3,15 +3,17 @@ import { userState } from '@/states/userState';
import { useQuery } from '@tanstack/react-query';
import { useEffect, useState } from 'react';
import { useRecoilState } from 'recoil';
+import useLoginState from './useLoginState';
export const useUserData = () => {
const [userId, setUserId] = useState();
const [userData, setUserData] = useRecoilState(userState);
+ const { isLoggedIn } = useLoginState();
- const { data: userResponseData } = useQuery({
+ const { data: userResponseData, isError } = useQuery({
queryKey: ['user', userId],
queryFn: apiMyInfo,
- enabled: !!userId,
+ enabled: !!isLoggedIn,
});
useEffect(() => {
@@ -21,6 +23,7 @@ export const useUserData = () => {
}, [userResponseData]);
useEffect(() => {
+ console.log('hi');
const userId = localStorage.getItem('userId') || '';
setUserId(userId);
}, []);
diff --git a/package-lock.json b/package-lock.json
index e5734aa..a771457 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2405,20 +2405,6 @@
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
},
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
diff --git a/package.json b/package.json
index 0eefc74..113eb5b 100644
--- a/package.json
+++ b/package.json
@@ -17,10 +17,10 @@
"react-calendar": "^5.0.0",
"react-dom": "^18",
"react-hook-form": "^7.52.1",
- "react-slick": "^0.30.2",
"recoil": "^0.7.7",
- "slick-carousel": "^1.8.1",
- "tailwind-scrollbar-hide": "^1.1.7"
+ "tailwind-scrollbar-hide": "^1.1.7",
+ "react-slick": "^0.30.2",
+ "slick-carousel": "^1.8.1"
},
"devDependencies": {
"@types/node": "^20",
diff --git a/pages/404.tsx b/pages/404.tsx
new file mode 100644
index 0000000..0ebce76
--- /dev/null
+++ b/pages/404.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import Image from 'next/image';
+import { PrimaryButton } from '@/components/Button/Button';
+import { useRouter } from 'next/router';
+
+export default function NonePage() {
+ const router = useRouter();
+
+ const handleToMain = () => {
+ router.push('/');
+ };
+
+ return (
+
+ );
+}
diff --git a/pages/Navtest.tsx b/pages/Navtest.tsx
deleted file mode 100644
index 9c01740..0000000
--- a/pages/Navtest.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import CatergoryBtn from '@/components/CatergoryBtn/CatergoryBtn';
-import NavigationBar from '@/components/Layout/NavigationBar';
-import MyPageInput from '@/components/MyPage/MyPageInput';
-import PriceFilterBtn from '@/components/PriceFilterBtn/PriceFilterBtn';
-import SidenNavigation from '@/components/SideNavigation/SideNavigation';
-
-export default function Navtest() {
- return (
- <>
-
-
- >
- );
-}
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 3b5cc82..dae4e75 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -8,10 +8,31 @@ import Layout from '@/components/Layout/Layout';
import Modal from '@/components/Modal/Modal';
import LayoutMobile from '@/components/Layout/LayoutMobile';
import SilentRefresh from '@/hooks/useSilentRefresh';
+import Spinner from '@/components/Spinner/Spinner';
+import { useEffect, useState } from 'react';
+import { Router } from 'next/router';
+import SidenNavigationMobile from '@/components/SideNavigation/SideNavigationMobile';
const queryClient = new QueryClient();
export default function App({ Component, pageProps }: AppProps) {
+ const [isLoading, setIsLoading] = useState(false);
+
+ useEffect(() => {
+ const start = () => setIsLoading(true);
+ const end = () => setIsLoading(false);
+
+ Router.events.on('routeChangeStart', start);
+ Router.events.on('routeChangeComplete', end);
+ Router.events.on('routeChangeError', end);
+
+ return () => {
+ Router.events.off('routeChangeStart', start);
+ Router.events.off('routeChangeComplete', end);
+ Router.events.off('routeChangeError', end);
+ };
+ }, []);
+
let childContent: React.ReactNode;
switch (pageProps.layoutType) {
@@ -36,12 +57,17 @@ export default function App({ Component, pageProps }: AppProps) {
return (
-
- {childContent}
-
-
-
-
+ {isLoading ? (
+
+ ) : (
+
+ {childContent}
+
+
+
+
+
+ )}
);
}
diff --git a/pages/_document.tsx b/pages/_document.tsx
index 546ebc6..e70b684 100644
--- a/pages/_document.tsx
+++ b/pages/_document.tsx
@@ -6,10 +6,20 @@ export default function Document() {
GlobalNomad
+
+
+
+
+ {/* */}
+
diff --git a/pages/activity-details/[id].tsx b/pages/activity-details/[id].tsx
index 5aa7ae0..4a072a5 100644
--- a/pages/activity-details/[id].tsx
+++ b/pages/activity-details/[id].tsx
@@ -1,7 +1,7 @@
import ActivityDetails from '@/components/ActivityDetails/ActivityDetails';
import { useRouter } from 'next/router';
-export default function activityDetails() {
+export default function ActivityDetailsPage() {
const router = useRouter();
const { id } = router.query;
const activityId = typeof id === 'string' ? parseInt(id, 10) : undefined;
diff --git a/pages/api/myReservations/apiMyReservations.types.ts b/pages/api/myReservations/apiMyReservations.types.ts
index d81372f..1a8498a 100644
--- a/pages/api/myReservations/apiMyReservations.types.ts
+++ b/pages/api/myReservations/apiMyReservations.types.ts
@@ -21,7 +21,7 @@ export interface MyReservationListResponse {
id: number;
};
scheduleId: number;
- status: string;
+ status: 'pending' | 'confirmed' | 'declined' | 'canceled' | 'completed';
reviewSubmitted: boolean;
totalPrice: number;
headCount: number;
diff --git a/pages/login.tsx b/pages/login.tsx
index aafe288..e08a503 100644
--- a/pages/login.tsx
+++ b/pages/login.tsx
@@ -11,6 +11,14 @@ import useLoginState from '@/hooks/useLoginState';
import { useRouter } from 'next/router';
import { GetServerSideProps } from 'next';
+export const getServerSideProps: GetServerSideProps = async () => {
+ return {
+ props: {
+ layoutType: 'removeLayout',
+ },
+ };
+};
+
export default function LoginPage() {
const { postLoginMutation } = useLogin();
const { isLoggedIn } = useLoginState();
@@ -35,11 +43,11 @@ export default function LoginPage() {
const isFormFilled = !!email && !!password;
return isFormFilled && isNotError;
- }, [errors.email, errors.password, watchFields]);
+ }, [errors.email, errors.password, getValues]);
useEffect(() => {
- if (isLoggedIn) router.push('/mypage');
- }, [isLoggedIn]);
+ if (isLoggedIn) router.push('/');
+ }, [isLoggedIn, router]);
return (
diff --git a/pages/logoutTest.tsx b/pages/logoutTest.tsx
deleted file mode 100644
index 260c729..0000000
--- a/pages/logoutTest.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import useLoginState from '@/hooks/useLoginState';
-import useLogout from '@/hooks/useLogout';
-
-export default function logoutTest() {
- const logout = useLogout();
- const { isLoggedIn } = useLoginState();
-
- console.log(isLoggedIn);
-
- return (
-
-
-
- );
-}
diff --git a/pages/myActivity/register.tsx b/pages/myActivity/register.tsx
new file mode 100644
index 0000000..7ba0e88
--- /dev/null
+++ b/pages/myActivity/register.tsx
@@ -0,0 +1,77 @@
+import { FieldValues, useForm } from 'react-hook-form';
+import { PrimaryButton } from '@/components/Button/Button';
+import InputBox from '@/components/InputBox/InputBox';
+import KategorieDropdown from '@/components/KategorieDropdown/KategorieDropdown';
+import TextArea from '@/components/InputBox/TextArea';
+import TimeSlot from '@/components/MyActivity/Register/TimeSlot';
+import CustomCalendar from '@/components/CustomCalendar/CustomCalendar';
+import {
+ UploadBannerImage,
+ UploadDetailImage,
+} from '@/components/MyActivity/Register/UploadImage';
+
+function RegisterActivity() {
+ const {
+ register,
+ handleSubmit,
+ getValues,
+ setValue,
+ formState: { errors },
+ } = useForm
({ mode: 'onChange' });
+
+ const handleClickRegister = () => {};
+
+ return (
+
+ );
+}
+
+export default RegisterActivity;
diff --git a/pages/mypage.tsx b/pages/mypage.tsx
index 535d700..00cb6b6 100644
--- a/pages/mypage.tsx
+++ b/pages/mypage.tsx
@@ -1,63 +1,19 @@
-import { CircleCloseButton } from '@/components/Button/Button';
-import MyPageInput from '@/components/MyPage/MyPageInput';
+import MyPageInput from '@/components/MyPageInput/MyPageInput';
import SidenNavigation from '@/components/SideNavigation/SideNavigation';
import SidenNavigationMobile from '@/components/SideNavigation/SideNavigationMobile';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
export default function MyPage() {
- const router = useRouter();
- const [screenSize, setScreenSize] = useState('');
- const [activeSection, setActiveSection] = useState(null);
-
- const handleNavigate = (section: string) => {
- setActiveSection(section);
- };
- const onCircleClick = () => {
- setActiveSection(null);
- };
-
- useEffect(() => {
- function handleResize() {
- const width = window.innerWidth;
- if (width <= 743) {
- setScreenSize('m');
- } else {
- setScreenSize('');
- }
- }
-
- handleResize();
-
- window.addEventListener('resize', handleResize);
- return () => {
- window.removeEventListener('resize', handleResize);
- };
- }, [screenSize, activeSection]);
return (
<>
- {screenSize !== 'm' ? (
-
+
+
-
- ) : (
- <>
- {!activeSection && (
-
-
-
- )}
- {activeSection === 'mypage' && (
-
- )}
- >
- )}
+
+
+
>
);
}
diff --git a/pages/reservation.tsx b/pages/reservation.tsx
new file mode 100644
index 0000000..672cb64
--- /dev/null
+++ b/pages/reservation.tsx
@@ -0,0 +1,76 @@
+import ReservationListCard from '@/components/ReservationListCard/ReservationListCard';
+import ReservationFilter from '@/components/ReservationFilter/ReservationFilter';
+import SideNavigation from '@/components/SideNavigation/SideNavigation';
+import Image from 'next/image';
+import { useEffect, useState } from 'react';
+import { useReservationList } from '@/hooks/useReservationList';
+import {
+ MyReservationProps,
+ statusType,
+} from '@/components/ReservationFilter/myReservationTypes.types';
+
+export default function MyReservationPage() {
+ const [filterOption, setFilterOption] = useState
();
+ const [reservationListByFilter, setReservationListByFilter] = useState<
+ MyReservationProps[]
+ >([]);
+ const myReservationList = useReservationList();
+
+ useEffect(() => {
+ if (myReservationList) {
+ const reservationList = myReservationList.reservations;
+ if (filterOption) {
+ const filteredData = reservationList.filter(
+ (card) => card.status === filterOption
+ );
+ setReservationListByFilter(filteredData);
+ } else {
+ setReservationListByFilter(reservationList);
+ }
+ }
+ }, [myReservationList, filterOption]);
+
+ return (
+
+
+
+
+
예약 내역
+ {reservationListByFilter && (
+
+ )}
+
+
+ {reservationListByFilter.length > 0 ? (
+ reservationListByFilter.map(
+ (reservationData: MyReservationProps) => {
+ return (
+
+
+
+ );
+ }
+ )
+ ) : (
+
+
+
+
+
+ 등록된 체험이 없어요
+
+
+ )}
+
+
+
+ );
+}
diff --git a/pages/signup.tsx b/pages/signup.tsx
index bca6927..35a7c1e 100644
--- a/pages/signup.tsx
+++ b/pages/signup.tsx
@@ -10,8 +10,9 @@ import { SignupBody } from './api/users/apiUser.types';
import { useEffect, useMemo, useState } from 'react';
import useLoginState from '@/hooks/useLoginState';
import { useRouter } from 'next/router';
+import { GetServerSideProps } from 'next';
-export const getStaticProps = async () => {
+export const getServerSideProps: GetServerSideProps = async () => {
return {
props: {
layoutType: 'removeLayout',
@@ -60,14 +61,15 @@ export default function SingupPage() {
errors.password,
errors.passwordCheck,
errors.nickname,
- watchFields,
+ getValues,
+ isChecked,
]);
useEffect(() => {
if (isLoggedIn) {
router.push('/mypage');
}
- }, [isLoggedIn]);
+ }, [isLoggedIn, router]);
return (
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..accbae2
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/icon/hamburger_icon.svg b/public/icon/hamburger_icon.svg
new file mode 100644
index 0000000..5d6f2e0
--- /dev/null
+++ b/public/icon/hamburger_icon.svg
@@ -0,0 +1,9 @@
+
diff --git a/public/image/404.png b/public/image/404.png
new file mode 100644
index 0000000..b3195c9
Binary files /dev/null and b/public/image/404.png differ
diff --git a/states/mainPageState.tsx b/states/mainPageState.tsx
index 11669ec..09d15b4 100644
--- a/states/mainPageState.tsx
+++ b/states/mainPageState.tsx
@@ -5,7 +5,7 @@ export const mainPageState = atom
({
key: 'mainPageState',
default : {
currentPage: 1,
- itemsPerPage: 9,
+ itemsPerPage: 8,
selectedKategorie: '',
selectedSorted: '',
}
diff --git a/states/sideNavigationState.tsx b/states/sideNavigationState.tsx
new file mode 100644
index 0000000..9eee6ce
--- /dev/null
+++ b/states/sideNavigationState.tsx
@@ -0,0 +1,6 @@
+import { atom } from 'recoil';
+
+export const sideNavigationState = atom({
+ key: 'sideNavigationState',
+ default: false,
+});
diff --git a/tailwind.config.js b/tailwind.config.js
index 15b1294..f725c95 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -53,8 +53,9 @@ module.exports = {
},
boxShadow: {
card: '0px 4px 16px 0px rgba(17, 34, 17, 0.05)',
+ kategorieDropdown: '0px 10px 30px 3px rgba(5, 16, 55, 0.15);',
},
},
},
- plugins: [require("tailwind-scrollbar-hide")],
+ plugins: [require('tailwind-scrollbar-hide')],
};