diff --git a/src/app/global.css b/src/app/global.css index 8602d86..891dc43 100644 --- a/src/app/global.css +++ b/src/app/global.css @@ -101,4 +101,8 @@ input[type='number'] { .shadow-button { box-shadow: 4px 4px 20px 0px rgba(55, 127, 248, 0.1); } + + .shadow-noticeItem { + box-shadow: 2px 8px 40px -3.034px rgba(50, 65, 96, 0.1); + } } diff --git a/src/app/stackflow/Stack.tsx b/src/app/stackflow/Stack.tsx index 1717a06..932f1e7 100644 --- a/src/app/stackflow/Stack.tsx +++ b/src/app/stackflow/Stack.tsx @@ -4,10 +4,12 @@ import { stackflow } from '@stackflow/react'; import { LoginScreen } from '@/screen/login/ui'; import { HomeScreen } from '@/screen/home/ui'; +import { NoticeScreen } from '@/screen/notice/ui'; +import { NoticeContentScreen } from '@/screen/notice-content/ui'; export const { Stack, useFlow } = stackflow({ transitionDuration: 350, - activities: { LoginScreen, HomeScreen }, + activities: { NoticeScreen, NoticeContentScreen, LoginScreen, HomeScreen }, plugins: [ basicRendererPlugin(), basicUIPlugin({ diff --git a/src/assets/icon/icon-message.svg b/src/assets/icon/icon-message.svg new file mode 100644 index 0000000..016c988 --- /dev/null +++ b/src/assets/icon/icon-message.svg @@ -0,0 +1,41 @@ + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/assets/icon/icon-notification.svg b/src/assets/icon/icon-notification.svg new file mode 100644 index 0000000..6bc0461 --- /dev/null +++ b/src/assets/icon/icon-notification.svg @@ -0,0 +1,21 @@ + + +
+ + + + + + + + + + + + + + + + + +
diff --git a/src/assets/icon/index.ts b/src/assets/icon/index.ts index 89cbc40..197429c 100644 --- a/src/assets/icon/index.ts +++ b/src/assets/icon/index.ts @@ -1,5 +1,7 @@ import UserIcon from './icon-user.png'; import ResultIcon from './icon-result.svg'; import NoticeIcon from './icon-notice.svg'; +import NotificationIcon from './icon-notification.svg'; +import MessageIcon from './icon-message.svg'; -export { UserIcon, ResultIcon, NoticeIcon }; +export { UserIcon, ResultIcon, NoticeIcon, NotificationIcon, MessageIcon }; diff --git a/src/features/notice/mock/index.ts b/src/features/notice/mock/index.ts new file mode 100644 index 0000000..6351718 --- /dev/null +++ b/src/features/notice/mock/index.ts @@ -0,0 +1 @@ +export * from './notice'; diff --git a/src/features/notice/mock/notice.ts b/src/features/notice/mock/notice.ts new file mode 100644 index 0000000..9fb973b --- /dev/null +++ b/src/features/notice/mock/notice.ts @@ -0,0 +1,40 @@ +import type { Notice } from '../types'; + +export const NOTICE_MOCK: Notice[] = [ + { + id: 1, + title: '2025년 봄학기 개강 안내', + type: 'NOTIFICATION', + date: '2025-03-01', + }, + { + id: 2, + title: '홈페이지 점검 일정 안내', + type: 'NOTIFICATION', + date: '2025-03-05', + }, + { + id: 3, + title: '중간고사 일정 공지', + type: 'NOTIFICATION', + date: '2025-04-10', + }, + { + id: 4, + title: '신입생 오리엔테이션 안내', + type: 'NOTIFICATION', + date: '2025-02-25', + }, + { + id: 5, + title: '장학금 신청 기간 안내', + type: 'MESSAGE', + date: '2025-03-15', + }, + { + id: 6, + title: '건물 전기 점검에 따른 이용 제한 안내', + type: 'MESSAGE', + date: '2025-03-20', + }, +]; diff --git a/src/features/notice/types/index.ts b/src/features/notice/types/index.ts new file mode 100644 index 0000000..6351718 --- /dev/null +++ b/src/features/notice/types/index.ts @@ -0,0 +1 @@ +export * from './notice'; diff --git a/src/features/notice/types/notice.ts b/src/features/notice/types/notice.ts new file mode 100644 index 0000000..c72e46b --- /dev/null +++ b/src/features/notice/types/notice.ts @@ -0,0 +1,8 @@ +export type NoticeType = 'MESSAGE' | 'NOTIFICATION'; + +export type Notice = { + id: number; + title: string; + type: NoticeType; + date: string; +}; diff --git a/src/features/notice/ui/NoticeItem.tsx b/src/features/notice/ui/NoticeItem.tsx new file mode 100644 index 0000000..04673a1 --- /dev/null +++ b/src/features/notice/ui/NoticeItem.tsx @@ -0,0 +1,44 @@ +import { MessageIcon, NotificationIcon } from '@/assets/icon'; +import type { Notice } from '../types'; + +import { cn } from '@/shared/utils'; +import { useFlow } from '@/app/stackflow'; +import { PATH } from '@/shared/constants'; + +export default function NoticeItem({ id, title, type, date }: Notice) { + const typeLabel = type === 'NOTIFICATION' ? '알림' : '예정'; + const { push } = useFlow(); + + return ( + + ); +} diff --git a/src/features/notice/ui/NoticeList.tsx b/src/features/notice/ui/NoticeList.tsx new file mode 100644 index 0000000..17b20fb --- /dev/null +++ b/src/features/notice/ui/NoticeList.tsx @@ -0,0 +1,12 @@ +import { NOTICE_MOCK } from '../mock'; +import NoticeItem from './NoticeItem'; + +export default function NoticeList() { + return ( +
+ {NOTICE_MOCK.map(({ id, title, type, date }) => ( + + ))} +
+ ); +} diff --git a/src/features/notice/ui/index.ts b/src/features/notice/ui/index.ts new file mode 100644 index 0000000..86f9a8f --- /dev/null +++ b/src/features/notice/ui/index.ts @@ -0,0 +1,2 @@ +export { default as NoticeList } from './NoticeList'; +export { default as NoticeItem } from './NoticeItem'; diff --git a/src/screen/notice-content/ui/NoticeContentScreen.tsx b/src/screen/notice-content/ui/NoticeContentScreen.tsx new file mode 100644 index 0000000..8ff5767 --- /dev/null +++ b/src/screen/notice-content/ui/NoticeContentScreen.tsx @@ -0,0 +1,24 @@ +import { AppScreen } from '@stackflow/plugin-basic-ui'; + +import { TitleAppBar } from '@/shared/ui'; +import type { Notice } from '@/features/notice/types'; +import type { ActivityComponentType } from '@stackflow/react'; +import { NoticeContentContainer } from '@/widgets/notice-content/ui'; + +const NoticeContentScreen: ActivityComponentType<{ notice: Notice }> = ({ + params, +}: { + params: { notice: Notice }; +}) => { + return ( + + + + ); +}; + +export default NoticeContentScreen; diff --git a/src/screen/notice-content/ui/index.ts b/src/screen/notice-content/ui/index.ts new file mode 100644 index 0000000..bf9a859 --- /dev/null +++ b/src/screen/notice-content/ui/index.ts @@ -0,0 +1 @@ +export { default as NoticeContentScreen } from './NoticeContentScreen'; diff --git a/src/screen/notice/ui/NoticeScreen.tsx b/src/screen/notice/ui/NoticeScreen.tsx new file mode 100644 index 0000000..e0a01cd --- /dev/null +++ b/src/screen/notice/ui/NoticeScreen.tsx @@ -0,0 +1,16 @@ +import { AppScreen } from '@stackflow/plugin-basic-ui'; + +import { TitleAppBar } from '@/shared/ui'; +import { NoticeContainer } from '@/widgets/notice/ui'; + +export default function NoticeScreen() { + return ( + + + + ); +} diff --git a/src/screen/notice/ui/index.ts b/src/screen/notice/ui/index.ts new file mode 100644 index 0000000..a894689 --- /dev/null +++ b/src/screen/notice/ui/index.ts @@ -0,0 +1 @@ +export { default as NoticeScreen } from './NoticeScreen'; diff --git a/src/shared/constants/path.ts b/src/shared/constants/path.ts index 54b2534..3e37f52 100644 --- a/src/shared/constants/path.ts +++ b/src/shared/constants/path.ts @@ -1,4 +1,6 @@ export const PATH = { HOME: 'HomeScreen', LOGIN: 'LoginScreen', + NOTICE: 'NoticeScreen', + NOTICE_CONTENT: 'NoticeContentScreen', } as const; diff --git a/src/shared/ui/AppBar.tsx b/src/shared/ui/AppBar.tsx index 3e564fb..8e745bc 100644 --- a/src/shared/ui/AppBar.tsx +++ b/src/shared/ui/AppBar.tsx @@ -19,3 +19,9 @@ export const HomeAppBar = { ), renderRight: () => user, }; + +export const TitleAppBar = (title: string) => ({ + ...baseStyle, + backgroundColor: '#fff', + title: title, +}); diff --git a/src/widgets/home/ui/HomeContainer.tsx b/src/widgets/home/ui/HomeContainer.tsx index 922fe87..08ddabd 100644 --- a/src/widgets/home/ui/HomeContainer.tsx +++ b/src/widgets/home/ui/HomeContainer.tsx @@ -28,7 +28,7 @@ export default function HomeContainer() { title="공지사항" description="예정된 선거를 확인해보세요" icon={NoticeIcon} - to={PATH.HOME} + to={PATH.NOTICE} /> @@ -47,7 +47,11 @@ const ServiceButton = ({ + ))} + + + + ); +} diff --git a/src/widgets/notice/ui/index.ts b/src/widgets/notice/ui/index.ts new file mode 100644 index 0000000..f9c4f46 --- /dev/null +++ b/src/widgets/notice/ui/index.ts @@ -0,0 +1 @@ +export { default as NoticeContainer } from './NoticeContainer';