Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"dotenv": "^16.4.5",
"firebase": "^11.3.1",
"js-base64": "^3.7.7",
"js-cookie": "^3.0.5",
"lodash": "^4.17.21",
"lucide-react": "^0.475.0",
"next": "^15.0.3",
Expand All @@ -62,6 +63,7 @@
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@types/jest": "^29.5.12",
"@types/js-cookie": "^3.0.6",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
Expand Down
3 changes: 3 additions & 0 deletions public/assets/icons/icon-fee-check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 120 additions & 0 deletions public/assets/icons/side-menu/admin-homepage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion src/app/callback/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useEffect, Suspense } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
import { handleLoginSuccess } from '@/utils/loginHandler';
import Cookies from 'js-cookie';

function CallbackContent() {
const searchParams = useSearchParams();
Expand All @@ -13,7 +14,7 @@ function CallbackContent() {
const email = searchParams.get('email');
const accessToken = searchParams.get('accessToken');

localStorage.setItem('email', email || '');
Cookies.set('email', email || '');

if (!status) return;

Expand Down
5 changes: 2 additions & 3 deletions src/app/mobile/admin/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import { useState, useEffect } from 'react';
import MobileLayout from '@/components/mobile/layout';
import Header from '@/components/mobile/Header';
import Dropdown from '@/components/mobile/Dropdown';
import useDropdown from '@/hooks/useDropdown';
Expand Down Expand Up @@ -104,7 +103,7 @@ export default function Dashboard() {
};

return (
<MobileLayout>
<div>
<Header title="관리자 대시보드" />

<section className="itmes-center mt-2.5 flex w-full justify-between px-5">
Expand Down Expand Up @@ -171,6 +170,6 @@ export default function Dashboard() {
hideDropdown={hideDropdown}
positionClasses="top-[80px] right-5"
/>
</MobileLayout>
</div>
);
}
5 changes: 2 additions & 3 deletions src/app/mobile/admin/notification/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import { useEffect, useState } from 'react';
import MobileLayout from '@/components/mobile/layout';
import NotificationItem from '@/components/mobile/NotificationItem';
import Header from '@/components/mobile/Header';
import { elapsedTime } from '@/utils/elapsedTime';
Expand Down Expand Up @@ -32,7 +31,7 @@ export default function Notification() {
};

return (
<MobileLayout>
<div>
<Header title="관리자 알림" />
{notificationDetail?.length === 0 ? (
<div className="flex h-dvh items-center justify-center text-gray-secondary">
Expand All @@ -53,6 +52,6 @@ export default function Notification() {
/>
))
)}
</MobileLayout>
</div>
);
}
5 changes: 2 additions & 3 deletions src/app/mobile/history/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import { useEffect, useState, useMemo } from 'react';
import MobileLayout from '@/components/mobile/layout';
import Header from '@/components/mobile/Header';
import ReturnItem from '@/app/mobile/history/_components/ReturnItem';
import RentalItem from '@/app/mobile/history/_components/RentalItem';
Expand Down Expand Up @@ -194,7 +193,7 @@ export default function UserRentalList() {
);

return (
<MobileLayout>
<div>
<Header title="대여 기록" menu />

{/* 반납이 필요한 물품 */}
Expand Down Expand Up @@ -287,6 +286,6 @@ export default function UserRentalList() {
<div className="text-body-2-normal_medi">© wink</div>
</div>
</div>
</MobileLayout>
</div>
);
}
44 changes: 44 additions & 0 deletions src/app/mobile/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
'use client';

import useAuthRedirect from '@/hooks/useAuthRedirect';
import React, { useEffect } from 'react';
import { usePathname } from 'next/navigation';

export default function MobileLayout({
children,
}: {
children: React.ReactNode;
}) {
const pathname = usePathname();

// 제외할 경로 목록
const excludedRoutes = ['/mobile/sign-in', '/mobile/sign-up'];

const isExcluded = excludedRoutes.includes(pathname);

useAuthRedirect();

useEffect(() => {
if (!isExcluded) {
const originalBgColor = document.body.style.backgroundColor;
document.body.style.backgroundColor = '#F3F4F6';

return () => {
document.body.style.backgroundColor = originalBgColor;
};
}

return undefined;
}, [isExcluded]);

if (isExcluded) {
// 레이아웃 없이 children만 렌더링
return children;
}

return (
<div className="flex min-h-screen justify-center">
<div className="flex w-full max-w-md flex-col">{children}</div>
</div>
);
}
9 changes: 6 additions & 3 deletions src/app/mobile/main/_components/MainHeader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import Sidebar from '@/components/mobile/SidebarMenu/index';
import { useEffect, useState } from 'react';
import IconAlarm from 'public/assets/icons/icon-alarm.svg';
import IconHamburger from 'public/assets/icons/icon-hamburger.svg';
import IconFeeCheck from 'public/assets/icons/icon-fee-check.svg';
import { getNotificationCount } from '@/apis/notification';
import Cookies from 'js-cookie';

export default function MainHeader() {
const router = useRouter();
Expand All @@ -15,6 +17,7 @@ export default function MainHeader() {
name: string;
id: string;
role: string;
isFeePaid: boolean;
} | null>(null);

useEffect(() => {
Expand All @@ -31,7 +34,7 @@ export default function MainHeader() {
}, []);

useEffect(() => {
const storedUser = localStorage.getItem('user');
const storedUser = Cookies.get('user');
if (storedUser) {
setUser(JSON.parse(storedUser));
}
Expand All @@ -40,8 +43,8 @@ export default function MainHeader() {
return (
<>
<section className="fixed top-0 z-10 flex h-10 w-full max-w-md items-center justify-between bg-[#F3F4F6] px-4 py-1.5">
<div className="text-heading-3_D font-semibold text-black-primary">
{user?.name}님
<div className="flex items-center gap-2 text-heading-3_D font-semibold text-black-primary">
{user?.name}님{user?.isFeePaid ? <IconFeeCheck /> : null}
</div>
<div className="flex gap-[7px]">
<button
Expand Down
16 changes: 8 additions & 8 deletions src/app/mobile/main/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client';

import { useEffect, useState } from 'react';
import MobileLayout from '@/components/mobile/layout';
import MainHeader from '@/app/mobile/main/_components/MainHeader';
import Carousel from '@/app/mobile/main/_components/Carousel';
import WelfareItem from '@/app/mobile/main/_components/WelfareItem';
Expand All @@ -12,6 +11,7 @@ import IconSearch from 'public/assets/icons/icon-search.svg';
import { useRouter } from 'next/navigation';
import { requestNotificationPermission } from '@/utils/pushNotification';
import PopUp from '@/components/mobile/PopUp';
import Cookies from 'js-cookie';

export default function MobileMain() {
const [isBottomSheetOpen, setIsBottomSheetOpen] = useState(false);
Expand Down Expand Up @@ -42,7 +42,7 @@ export default function MobileMain() {
}, [searchQuery]);

useEffect(() => {
if (!localStorage.getItem('token')) {
if (!Cookies.get('token')) {
router.replace('/mobile/sign-in');
return;
}
Expand All @@ -51,7 +51,7 @@ export default function MobileMain() {
requestNotificationPermission();

// "다시 보지 않기" 플래그가 없으면 팝업 표시
if (!localStorage.getItem('popUpDismissed2')) {
if (!Cookies.get('popUpDismissed3')) {
setShowPopUp(true);
}
}, []);
Expand All @@ -77,9 +77,9 @@ export default function MobileMain() {
};

return (
<MobileLayout>
<div>
<MainHeader />
<div className="mt-10 flex flex-col gap-[50px] px-4 pt-4">
<div className="mt-10 flex flex-col gap-[50px] px-4 py-4">
<Carousel images={images} />

<section className="flex flex-col gap-4">
Expand Down Expand Up @@ -113,11 +113,11 @@ export default function MobileMain() {
{showPopUp && (
<PopUp
title="🚨 공지사항 안내 🚨"
content={`시험기간(04.14.~04.28.) 동안\n복지물품 대여가 일시 중단됩니다.\n
content={`2025년 1학기 복지물품 대여는\n6월 2일(월)부로 종료됩니다.\n
이용에 참고 부탁드립니다!`}
onClickCta={() => setShowPopUp(false)}
onClickOther={() => {
localStorage.setItem('popUpDismissed2', 'true');
Cookies.set('popUpDismissed3', 'true');
setShowPopUp(false);
}}
/>
Expand All @@ -129,6 +129,6 @@ export default function MobileMain() {
onCloseAction={() => setIsBottomSheetOpen(false)}
item={selectedItem}
/>
</MobileLayout>
</div>
);
}
8 changes: 4 additions & 4 deletions src/app/mobile/notification/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
import MobileLayout from '@/components/mobile/layout';
import {
userNotificationGet,
readNotificationPatch,
Expand All @@ -12,6 +11,7 @@ import NotificationItem from '@/components/mobile/NotificationItem';
import Header from '@/components/mobile/Header';
import { elapsedTime } from '@/utils/elapsedTime';
import { NotificationProps } from '@/types/notificationType';
import Cookies from 'js-cookie';

type UserNotificationType = NotificationProps;

Expand All @@ -23,7 +23,7 @@ export default function Notification() {
>([]);

useEffect(() => {
const user = localStorage.getItem('user');
const user = Cookies.get('user');

if (!user) {
alert('로그인 후 사용 가능합니다.');
Expand All @@ -50,7 +50,7 @@ export default function Notification() {
};

return (
<MobileLayout>
<div>
<Header title="알림" />
{notificationDetail?.length === 0 ? (
<div className="flex h-dvh items-center justify-center text-gray-secondary">
Expand Down Expand Up @@ -84,6 +84,6 @@ export default function Notification() {
))}
</div>
)}
</MobileLayout>
</div>
);
}
5 changes: 2 additions & 3 deletions src/app/mobile/privacy-policy/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
'use client';

import MobileLayout from '@/components/mobile/layout';
import Header from '@/components/mobile/Header';
import privacyPolicy from './privacyPolicyData';

export default function UserRentalList() {
return (
<MobileLayout>
<div>
<Header title="개인정보 이용약관" menu={false} />

{/* 반납이 필요한 물품 */}
Expand Down Expand Up @@ -42,6 +41,6 @@ export default function UserRentalList() {
<div className="fixed bottom-0 left-0 right-0 flex h-12 items-center justify-center bg-[#F3F4F6]">
<div className="text-body-2-normal_medi">© wink</div>
</div>
</MobileLayout>
</div>
);
}
3 changes: 2 additions & 1 deletion src/app/mobile/sign-in/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import { getUA } from 'react-device-detect';
import Alert from '@/components/mobile/Alert';
import Cookies from 'js-cookie';

export default function SignIn() {
const router = useRouter();
Expand Down Expand Up @@ -102,7 +103,7 @@ export default function SignIn() {
};

useEffect(() => {
if (localStorage.getItem('token') && localStorage.getItem('user')) {
if (Cookies.get('token') && Cookies.get('user')) {
router.replace('/mobile/main');
}
}, []);
Expand Down
7 changes: 4 additions & 3 deletions src/app/mobile/sign-up/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import axios from 'axios';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import postSignUp from '@/services/sign-up';
import Cookies from 'js-cookie';

export default function SignUp() {
const router = useRouter();
Expand Down Expand Up @@ -38,7 +39,7 @@ export default function SignUp() {
const handleSignUp = async () => {
if (!validateForm()) return;

const email = localStorage.getItem('email');
const email = Cookies.get('email');
if (!email) {
alert('이메일 정보가 없습니다. 다시 로그인해 주세요.');
return;
Expand All @@ -53,8 +54,8 @@ export default function SignUp() {

const userInfo = { name: studentName, id: studentId, role: 'USER' };

localStorage.setItem('token', data.accessToken);
localStorage.setItem('user', JSON.stringify(userInfo));
Cookies.set('token', data.accessToken);
Cookies.set('user', JSON.stringify(userInfo));

router.push('/mobile/main');
} catch (e) {
Expand Down
3 changes: 2 additions & 1 deletion src/components/desktop/NavBar/NavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import toast from 'react-hot-toast';
import { clearAllCookies } from '@/utils/clearAllCookies';

interface NavBarItem {
name: string;
Expand Down Expand Up @@ -40,7 +41,7 @@ export default function NavBar() {
router.push(`${item.link}`);

if (item.name === '로그아웃') {
localStorage.clear();
clearAllCookies();
toast.success('로그아웃에 성공했습니다!');
}

Expand Down
Loading