Skip to content

Commit

Permalink
[feat] noti 갯수 노출 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
zestlee1106 committed Nov 29, 2023
1 parent f51f6ca commit a030375
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 14 deletions.
8 changes: 7 additions & 1 deletion components/Nav/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Me from '@/public/icons/me.svg';
import HugeIcon from '@/public/icons/huge-icon.svg';
import { useRouter } from 'next/router';
import { UserInfoProps } from '@/context/UserInfoProvider.tsx';
import useNotification from '@/hooks/useNotification';
import styles from './Nav.module.scss';

const defaultStrokeColor = 'stroke-g4 stroke-[1.5px]';
Expand Down Expand Up @@ -53,6 +54,7 @@ export default function Nav({ initMenu, profile }: NavProps) {
);
}
};
const { notificationCount } = useNotification();

return (
<div className={`${styles.container} grid grid-cols-4 bg-g0 w-full h-[66px] text-center relative`}>
Expand All @@ -74,7 +76,11 @@ export default function Nav({ initMenu, profile }: NavProps) {
hoverMenu === index ? 'cursor-pointer' : ''
}`}
/>
<div className="w-[15px] h-[15px] bg-r1 absolute top-0 left-[20px] rounded-[20px]" />
{notificationCount > 0 && menu.name === 'Notice' && (
<div className="w-fit h-fit min-w-[16px] min-h-[16px] bg-r2 absolute top-[-2px] left-[12px] rounded-[20px] text-[11px] font-medium text-white">
{notificationCount}
</div>
)}
</div>
</div>
<div className={styles[`${menu.router === router.pathname ? 'nav-activeText' : 'nav-text'}`]}>
Expand Down
25 changes: 24 additions & 1 deletion components/layouts/AppLayout/AppLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
import React, { ReactNode } from 'react';
import React, { ReactNode, useCallback, useEffect } from 'react';
import { useRouter } from 'next/router';
import { getNotifications } from '@/api/notification';
import useNotification from '@/hooks/useNotification';
import styles from './AppLayout.module.scss';

interface AppLayoutProps {
children: ReactNode;
}

function AppLayout({ children }: AppLayoutProps) {
const router = useRouter();
const { setNotificationCount } = useNotification();

const fetchNotification = useCallback(async () => {
if (router.pathname === '/notice') {
return;
}
const data = await getNotifications();
if (!data) {
return;
}
// TODO: 확인 안 한 응답 데이터로 변경
setNotificationCount(data.length);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
fetchNotification();
}, [router, fetchNotification]);

return (
<div className={`${styles.appLayout} ${styles.center}`}>
<div className={`${styles.appLayout} ${styles.width}`}>{children}</div>
Expand Down
27 changes: 27 additions & 0 deletions context/NotificationProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { useState, useMemo } from 'react';

interface ComponentProps {
children: React.ReactNode;
}

interface SetterProps {
setState: React.Dispatch<number>;
}

export const NotificationStateContext = React.createContext<number>(0);
export const NotificationSetterContext = React.createContext<SetterProps | null>(null);

function ModalProvider({ children }: ComponentProps) {
const [state, setState] = useState<number>(0);

const memoizedSetterValue = useMemo(() => ({ setState }), [setState]);
const memoizedStateValue = useMemo(() => state, [state]);

return (
<NotificationSetterContext.Provider value={memoizedSetterValue}>
<NotificationStateContext.Provider value={memoizedStateValue}>{children}</NotificationStateContext.Provider>
</NotificationSetterContext.Provider>
);
}

export default ModalProvider;
21 changes: 21 additions & 0 deletions hooks/useNotification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useContext } from 'react';
import { NotificationSetterContext, NotificationStateContext } from '@/context/NotificationProvider.tsx';

function useNotification() {
const setNotificationState = useContext(NotificationSetterContext);
const notificationCount = useContext(NotificationStateContext);

if (!setNotificationState) {
throw new Error('NotificationSetterContext is not properly initialized');
}

const setNotificationCount = (count: number) => {
if (setNotificationState) {
setNotificationState.setState(count);
}
};

return { setNotificationCount, notificationCount };
}

export default useNotification;
27 changes: 15 additions & 12 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import UserInfoProvider from '@/context/UserInfoProvider.tsx';
import ModalProvider from '../context/ModalProvider.tsx';
import ModalContainer from '../components/Modal/ModalContainer.tsx';
import AppLayout from '../components/layouts/AppLayout/AppLayout.tsx';
import NotificationProvider from '../context/NotificationProvider.tsx';

type NextPageWithLayout = NextPage & {
getLayout?: (page: React.ReactElement) => React.ReactNode;
Expand Down Expand Up @@ -69,18 +70,20 @@ function MyApp({ Component, pageProps }: LayoutAppProps): React.ReactElement {
</Head>
<meta content="width=device-width, initial-scale=1" name="viewport" />
<Providers>
<SessionProvider>
<ModalProvider>
<UserInfoProvider>
{data && (
<AppLayout>
{getLayout(<Component {...pageProps} />)}
<ModalContainer />
</AppLayout>
)}
</UserInfoProvider>
</ModalProvider>
</SessionProvider>
<NotificationProvider>
<SessionProvider>
<ModalProvider>
<UserInfoProvider>
{data && (
<AppLayout>
{getLayout(<Component {...pageProps} />)}
<ModalContainer />
</AppLayout>
)}
</UserInfoProvider>
</ModalProvider>
</SessionProvider>
</NotificationProvider>
</Providers>
<Toaster
toastOptions={{
Expand Down

0 comments on commit a030375

Please sign in to comment.