Skip to content

Commit

Permalink
Merge pull request #79 from bomin0830/master
Browse files Browse the repository at this point in the history
Fix: 뒤로가기 모달 이슈 수정 및 이미지 상세보기 기능 추가
  • Loading branch information
bomin0830 authored Aug 6, 2024
2 parents c099828 + 1ac8b8c commit b37ec12
Show file tree
Hide file tree
Showing 30 changed files with 128 additions and 34 deletions.
2 changes: 1 addition & 1 deletion components/ActivityDetails/ActivityDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { darkModeState } from '@/states/themeState';
import { ShareButton } from '../ShareButton/ShareButton';
import { ViewedActivitiesState } from '@/states/ViewedState';
import { ViewedActivityProps } from '../ViewedActivities/ViewedActivities.type';
import useLoginState from '@/hooks/useLoginState';
import useLoginState from '@/hooks/Auth/useLoginState';
import profileThumbnail from '@/public/image/profile-circle-icon-512x512-zxne30hp.png';
import SendChat from '../Chat/SendChat';

Expand Down
13 changes: 9 additions & 4 deletions components/ActivityDetails/ImageContainer/ImageContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { ImageContainerProps } from './ImageContainer.types';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import { PaginationButton } from '@/components/Button/Button';
import { useImageModal } from '@/hooks/useImageModal';

export default function ImageContainer({
bannerImageUrl,
subImages,
}: ImageContainerProps) {
const defaultImage = '/image/globalnomad.png';
const filledSubImages = [...subImages];
const openImageModal = useImageModal();

// 빈 자리는 기본 이미지 채워 넣음
for (let i = subImages.length + 1; i <= 4; i++) {
Expand All @@ -38,8 +40,9 @@ export default function ImageContainer({

return (
<div className="flex max-w-[1200px] h-[500px] gap-2 my-10 t:w-full t:h-[310px] m:w-full m:h-[300px] m:my-6 m:justify-center m:relative m:left-0 m:right-0">
<div
<button
className={`relative w-1/2 h-full ${shouldUseSlider ? 'm:hidden' : 'm:block m:w-full'}`}
onClick={() => openImageModal({ imageUrl: bannerImageUrl })}
>
<Image
src={bannerImageUrl}
Expand All @@ -48,12 +51,13 @@ export default function ImageContainer({
objectFit="cover"
className="object-cover rounded-l-lg m:rounded-none"
/>
</div>
</button>
<div className="w-1/2 grid grid-cols-2 grid-rows-2 gap-2 rounded-r-lg overflow-hidden m:hidden">
{filledSubImages.map((image) => (
<div
<button
key={image.id}
className="relative w-full h-full overflow-hidden"
onClick={() => openImageModal({ imageUrl: image.imageUrl })}
>
<Image
src={image.imageUrl}
Expand All @@ -62,7 +66,7 @@ export default function ImageContainer({
objectFit="cover"
className="object-cover"
/>
</div>
</button>
))}
</div>
{shouldUseSlider && (
Expand All @@ -71,6 +75,7 @@ export default function ImageContainer({
{mobileImages.map((image) => (
<div
key={image.id}
onClick={() => openImageModal({ imageUrl: image.imageUrl })}
className="m:relative m:w-full m:h-[300px] outline-none"
>
<Image
Expand Down
39 changes: 39 additions & 0 deletions components/ImageModal/ImageModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import useClickOutside from '@/hooks/useClickOutside';
import { ImageModalState } from '@/states/ImageModalState';
import Image from 'next/image';
import { useRecoilState } from 'recoil';

export default function ImageModal() {
const [ImageModal, setImageModal] = useRecoilState(ImageModalState);

const contentsArea = useClickOutside<HTMLDivElement>(() =>
setImageModal({ ...ImageModal, isOpen: false })
);

const closeModal = () => {
setImageModal({ ...ImageModal, isOpen: false });
};

return ImageModal.isOpen && window ? (
<div className="fixed inset-0 p-[50px] pt-[140px] flex items-center justify-center bg-black dark:bg-opacity-90 bg-opacity-80 z-50 m:p-0">
<div ref={contentsArea} className="relative">
<img
src={ImageModal.imageUrl}
alt="이미지 자세히보기 모달 이미지"
className="h-[600px] t:max-h-[500px] t:h-full t:min-h-[400px] t:max-w-[700px] m:w-full m:h-full"
/>
<button
onClick={closeModal}
className="absolute right-[-40px] top-[-40px] m:right-0 m:top-0"
>
<Image
src="/icon/btn_x_medium.svg"
width={40}
height={40}
alt="닫기"
/>
</button>
</div>
</div>
) : null;
}
6 changes: 6 additions & 0 deletions components/ImageModal/ImageModalProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ReactNode } from 'react';

export interface ImageModalProps {
isOpen: boolean;
imageUrl: string;
}
2 changes: 1 addition & 1 deletion components/Layout/NavigationBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import NavigationDropdown from '../NavigationDropdown/NavigationDropdown';
import useClickOutside from '@/hooks/useClickOutside';
import useGetNotification from '@/hooks/useGetNotification';
import NotificationDropdown from '../NavigationDropdown/NotificationDropdown';
import useLoginState from '@/hooks/useLoginState';
import useLoginState from '@/hooks/Auth/useLoginState';
import Spinner from '../Spinner/Spinner';
import profileThumbnail from '@/public/image/profile-circle-icon-512x512-zxne30hp.png';
import { useRecoilState } from 'recoil';
Expand Down
2 changes: 1 addition & 1 deletion components/NavigationDropdown/NavigationDropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import useLogout from '@/hooks/useLogout';
import useLogout from '@/hooks/Auth/useLogout';
import Link from 'next/link';

export default function NavigationDropdown() {
Expand Down
4 changes: 2 additions & 2 deletions components/ReservationListCard/ReservationListCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ const ReservationListCard = ({ reservationData }: ReservationCardProps) => {
}

return (
<div className="h-[204px] relative flex rounded-3xl shadow-card dark:shadow-none overflow-hidden t:h-[156px] m:h-[128px]">
<div className="min-w-[204px] h-[204px] overflow-hidden relative t:min-w-[156px] t:h-[156px] m:min-w-[110px] m:h-[128px]">
<div className="min-h-[204px] relative flex rounded-3xl shadow-card dark:shadow-none overflow-hidden t:min-h-[156px] m:min-h-[128px]">
<div className="min-w-[204px] min-h-[204px] overflow-hidden relative t:min-w-[156px] t:min-h-[156px] m:min-w-[110px] m:min-h-[128px]">
<Link
href={`/activity-details/${reservationData.activity.id}`}
className="text-[20px] font-bold mt-[8px] hover:underline"
Expand Down
2 changes: 1 addition & 1 deletion components/ViewedActivities/ViewedActivities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function ViewedActivities() {

return (
<div ref={ViewedActivitiesElement}>
<div className="fixed right-[32px] m:right-[14px] bottom-[90px] z-30 w-[40px] h-[40px] bg-gray-200 border-[1px] dark:bg-black dark:border-[2px] dark:bg-var-dark2 border-solid dark:border-var-dark3 flex items-center justify-center rounded-xl cursor-pointer hover:bg-gray-300">
<div className="fixed right-[32px] m:right-[14px] bottom-[90px] z-30 w-[40px] h-[40px] bg-gray-200 border-[1px] dark:border-[2px] dark:bg-var-dark2 border-solid dark:border-var-dark3 flex items-center justify-center rounded-xl cursor-pointer hover:bg-gray-300">
{!isOpen ? (
<Image
src={isDarkMode ? HistoryImg_white : HistoryImg_black}
Expand Down
2 changes: 0 additions & 2 deletions hooks/useAuthRedirect.ts → hooks/Auth/useAuthRedirect.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { useRouter } from 'next/router';
import { useEffect } from 'react';
import { usePopup } from './usePopup';
import useLoginState from './useLoginState';

export default function useAuthRedirect() {
const router = useRouter();
Expand Down
3 changes: 1 addition & 2 deletions hooks/useLogin.ts → hooks/Auth/useLogin.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { UseMutationResult, useMutation } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { useRouter } from 'next/router';
import { usePopup } from './usePopup';
import { usePopup } from '../usePopup';
import { LoginBody, LoginResponse } from '@/pages/api/auth/auth.types';
import { LoginAccess } from '@/pages/api/auth/auth';
import INSTANCE_URL from '@/pages/api/instance';
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion hooks/useLogout.ts → hooks/Auth/useLogout.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useRouter } from 'next/router';
import useLoginState from './useLoginState';
import { useRecoilState, useResetRecoilState, useSetRecoilState } from 'recoil';
import { useRecoilState } from 'recoil';
import { userDefaultState, userState } from '@/states/userState';
import { useQueryClient } from '@tanstack/react-query';
import socket from '@/server/server';
Expand Down
2 changes: 1 addition & 1 deletion hooks/useSignup.ts → hooks/Auth/useSignup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { apiSignup } from '@/pages/api/users/apiUsers';
import { UseMutationResult, useMutation } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { useRouter } from 'next/router';
import { usePopup } from './usePopup';
import { usePopup } from '../usePopup';

export default function useSignup() {
const router = useRouter();
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion hooks/myActivity/useMyActivityList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useInfiniteQuery } from '@tanstack/react-query';
import { getMyActivityList } from '@/pages/api/myActivities/apimyActivities';
import { getMyActivityListResponse } from '@/pages/api/myActivities/apimyActivities.types';
import { useMemo } from 'react';
import useLoginState from '../useLoginState';
import useLoginState from '../Auth/useLoginState';

const INITIAL_SIZE = 4;
const REFETCH_SIZE = 1;
Expand Down
2 changes: 1 addition & 1 deletion hooks/useGetNotification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
MyNotificationListResponse,
} from '@/pages/api/myNotifications/apiMyNotifications.types';
import { apiMyNotificationList } from '@/pages/api/myNotifications/apiMyNotifications';
import useLoginState from './useLoginState';
import useLoginState from './Auth/useLoginState';

export default function useGetNotification(query: MyNotificationListQuery) {
const { cursorId = undefined, size = 10 } = query;
Expand Down
2 changes: 1 addition & 1 deletion hooks/useGetNotificationList.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import useLoginState from './useLoginState';
import useLoginState from './Auth/useLoginState';
import { MyNotificationListResponse } from '@/components/NavigationDropdown/NotificationDropdown.types';
import { apiMyNotificationList } from '@/pages/api/myNotifications/apiMyNotifications';
import { useMemo } from 'react';
Expand Down
30 changes: 30 additions & 0 deletions hooks/useImageModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ImageModalProps } from '@/components/ImageModal/ImageModalProps';
import { ModalProps } from '@/components/Modal/Modal.types';
import { ImageModalState } from '@/states/ImageModalState';
import { modalState } from '@/states/modalState';
import { useRecoilState } from 'recoil';

export const useImageModal = () => {
const [imageModal, setImageModal] = useRecoilState(ImageModalState);

const openImageModal = (props: Omit<ImageModalProps, 'isOpen'>) => {
setImageModal({
...props,
isOpen: true,
});
};

const closeImageModal = () => {
setImageModal({
...imageModal,
isOpen: false,
});
};

// 브라우저 뒤로가기 버튼이벤트 발생 시 모달 닫기
window.addEventListener('popstate', function (event) {
closeImageModal();
});

return openImageModal;
};
5 changes: 5 additions & 0 deletions hooks/useModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@ export const useModal = () => {
});
};

// 브라우저 뒤로가기 버튼이벤트 발생 시 모달 닫기
window.addEventListener('popstate', function (event) {
closeModal();
});

return { openModal, closeModal };
};
4 changes: 2 additions & 2 deletions hooks/useUserData.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { apiMyInfo } from '@/pages/api/users/apiUsers';
import { userDefaultState, userState } from '@/states/userState';
import { userState } from '@/states/userState';
import { useQuery } from '@tanstack/react-query';
import { useEffect, useState } from 'react';
import { useRecoilState } from 'recoil';
import useLoginState from './useLoginState';
import useLoginState from './Auth/useLoginState';

export const useUserData = () => {
const [userId, setUserId] = useState<string>();
Expand Down
4 changes: 3 additions & 1 deletion pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import Popup from '@/components/Popup/Popup';
import Layout from '@/components/Layout/Layout';
import Modal from '@/components/Modal/Modal';
import SilentRefresh from '@/hooks/useSilentRefresh';
import SilentRefresh from '@/hooks/Auth/useSilentRefresh';
import Spinner from '@/components/Spinner/Spinner';
import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import SidenNavigationMobile from '@/components/SideNavigation/SideNavigationMobile';
import Theme from '@/components/Theme/Theme';
import TopButton from '@/components/Button/TopButton';
import ImageModal from '@/components/ImageModal/ImageModal';

declare global {
interface Window {
Expand Down Expand Up @@ -68,6 +69,7 @@ export default function App({ Component, pageProps }: AppProps) {
<Spinner />
) : (
<QueryClientProvider client={queryClient}>
<ImageModal />
<Theme />
{childContent}
<Popup />
Expand Down
2 changes: 1 addition & 1 deletion pages/calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { darkModeState } from '@/states/themeState';
import { InitialPageMeta } from '@/components/MetaData/MetaData';
import { GetServerSideProps } from 'next';
import { SSRMetaProps } from '@/components/MetaData/MetaData.type';
import useAuthRedirect from '@/hooks/useAuthRedirect';
import useAuthRedirect from '@/hooks/Auth/useAuthRedirect';

export const getServerSideProps: GetServerSideProps = async () => {
const OGTitle = '예약현황 | GLOBALNOMAD';
Expand Down
4 changes: 2 additions & 2 deletions pages/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { loginFormValues } from '@/components/AuthInputBox/AuthInputBox.types';
import { loginValidation } from '@/components/AuthInputBox/validation';
import Link from 'next/link';
import { PrimaryButton } from '@/components/Button/Button';
import useLogin from '@/hooks/useLogin';
import useLogin from '@/hooks/Auth/useLogin';
import { useEffect, useMemo, useState } from 'react';
import useLoginState from '@/hooks/useLoginState';
import useLoginState from '@/hooks/Auth/useLoginState';
import { useRouter } from 'next/router';
import { GetServerSideProps } from 'next';
import useEnterSubmit from '@/hooks/useEnterSubmit';
Expand Down
2 changes: 1 addition & 1 deletion pages/myactivity/edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getActivityInfo } from '../api/activities/apiactivities';
import { GetServerSideProps } from 'next';
import { InitialPageMeta } from '@/components/MetaData/MetaData';
import { SSRMetaProps } from '@/components/MetaData/MetaData.type';
import useAuthRedirect from '@/hooks/useAuthRedirect';
import useAuthRedirect from '@/hooks/Auth/useAuthRedirect';

export const getServerSideProps: GetServerSideProps = async () => {
const OGTitle = '내 체험 수정 | GLOBALNOMAD';
Expand Down
2 changes: 1 addition & 1 deletion pages/myactivity/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { darkModeState } from '@/states/themeState';
import { InitialPageMeta } from '@/components/MetaData/MetaData';
import { GetServerSideProps } from 'next';
import { SSRMetaProps } from '@/components/MetaData/MetaData.type';
import useAuthRedirect from '@/hooks/useAuthRedirect';
import useAuthRedirect from '@/hooks/Auth/useAuthRedirect';

export const getServerSideProps: GetServerSideProps = async () => {
const OGTitle = '내 체험 관리 | GLOBALNOMAD';
Expand Down
2 changes: 1 addition & 1 deletion pages/myactivity/register.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { InitialPageMeta } from '@/components/MetaData/MetaData';
import { SSRMetaProps } from '@/components/MetaData/MetaData.type';
import RegisterForm from '@/components/MyActivity/Register/RegisterForm';
import useAuthRedirect from '@/hooks/useAuthRedirect';
import useAuthRedirect from '@/hooks/Auth/useAuthRedirect';
import { GetServerSideProps } from 'next';

export const getServerSideProps: GetServerSideProps = async () => {
Expand Down
4 changes: 2 additions & 2 deletions pages/mypage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { SSRMetaProps } from '@/components/MetaData/MetaData.type';
import MyPageInput from '@/components/MyPageInput/MyPageInput';
import SidenNavigation from '@/components/SideNavigation/SideNavigation';
import SidenNavigationMobile from '@/components/SideNavigation/SideNavigationMobile';
import useAuthRedirect from '@/hooks/useAuthRedirect';
import useLoginState from '@/hooks/useLoginState';
import useAuthRedirect from '@/hooks/Auth/useAuthRedirect';
import useLoginState from '@/hooks/Auth/useLoginState';
import { useSideNavigation } from '@/hooks/useSideNavigation';
import { GetServerSideProps } from 'next';
import { useRouter } from 'next/router';
Expand Down
4 changes: 2 additions & 2 deletions pages/reservation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { darkModeState } from '@/states/themeState';
import { InitialPageMeta } from '@/components/MetaData/MetaData';
import { GetServerSideProps } from 'next';
import { SSRMetaProps } from '@/components/MetaData/MetaData.type';
import useAuthRedirect from '@/hooks/useAuthRedirect';
import useAuthRedirect from '@/hooks/Auth/useAuthRedirect';

export const getServerSideProps: GetServerSideProps = async () => {
const OGTitle = '예약내역 | GLOBALNOMAD';
Expand Down Expand Up @@ -87,7 +87,7 @@ export default function MyReservationPage({ OGTitle, OGUrl }: SSRMetaProps) {
)}
</div>
{reservationListByFilter.length > 0 ? (
<div className="flex flex-col animate-slideDown gap-[24px] overflow-auto scrollbar-hide pb-[20px] h-[calc(100vh-220px)] t:h-[calc(100vh-160px)] t:gap-[16px] m:h-[calc(100vh-100px)]">
<div className="flex w-full flex-col animate-slideDown gap-[24px] overflow-auto scrollbar-hide pb-[20px] h-[calc(100vh-220px)] t:h-[calc(100vh-160px)] t:gap-[16px] m:h-[calc(100vh-100px)]">
{reservationListByFilter.map(
(reservationData: MyReservationProps) => {
return (
Expand Down
4 changes: 2 additions & 2 deletions pages/signup.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import AuthInputBox from '@/components/AuthInputBox/AuthInputBox';
import Image from 'next/image';
import Link from 'next/link';
import useSignup from '@/hooks/useSignup';
import useSignup from '@/hooks/Auth/useSignup';
import { useForm } from 'react-hook-form';
import { signUpFormValues } from '@/components/AuthInputBox/AuthInputBox.types';
import { signupValidation } from '@/components/AuthInputBox/validation';
import { PrimaryButton } from '@/components/Button/Button';
import { SignupBody } from './api/users/apiUser.types';
import { useEffect, useMemo, useState } from 'react';
import useLoginState from '@/hooks/useLoginState';
import useLoginState from '@/hooks/Auth/useLoginState';
import { useRouter } from 'next/router';
import { GetServerSideProps } from 'next';
import useEnterSubmit from '@/hooks/useEnterSubmit';
Expand Down
10 changes: 10 additions & 0 deletions states/ImageModalState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ImageModalProps } from '@/components/ImageModal/ImageModalProps';
import { atom } from 'recoil';

export const ImageModalState = atom<ImageModalProps>({
key: 'ImageModalState',
default: {
isOpen: false,
imageUrl: '',
},
});

0 comments on commit b37ec12

Please sign in to comment.