diff --git a/app/frontend/src/hooks/useRouter.tsx b/app/frontend/src/hooks/useRouter.tsx
index 75f2a8cba..2f362e635 100644
--- a/app/frontend/src/hooks/useRouter.tsx
+++ b/app/frontend/src/hooks/useRouter.tsx
@@ -11,6 +11,7 @@ import {
Groups,
ProfilePage,
NotFound,
+ GroupJoinPage,
} from '@/pages';
export const useRouter = () =>
@@ -50,6 +51,10 @@ export const useRouter = () =>
path: 'groups',
element: ,
},
+ {
+ path: 'group/join',
+ element: ,
+ },
],
},
{
diff --git a/app/frontend/src/pages/Groups/Join/index.css.ts b/app/frontend/src/pages/Groups/Join/index.css.ts
new file mode 100644
index 000000000..951a99f41
--- /dev/null
+++ b/app/frontend/src/pages/Groups/Join/index.css.ts
@@ -0,0 +1,75 @@
+import { style } from '@vanilla-extract/css';
+
+import { fontStyle, vars } from '@/styles';
+
+const { grayscale200, morakGreen } = vars.color;
+const { sansRegular18, sansRegular16, sansBold20 } = fontStyle;
+
+export const buttons = style({
+ display: 'flex',
+ gap: '0.8rem',
+});
+
+export const closedText = style([
+ sansRegular18,
+ {
+ textAlign: 'center',
+ lineHeight: '2.4rem',
+ },
+]);
+
+export const container = style({
+ display: 'flex',
+ flexDirection: 'column',
+ maxWidth: '80rem',
+ margin: '0 auto',
+ gap: '2.4rem',
+});
+
+export const form = style([
+ sansRegular18,
+ {
+ display: 'flex',
+ flexDirection: 'column',
+ gap: '1.6rem',
+ alignItems: 'center',
+ },
+]);
+
+export const group = style({
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ gap: '0.8rem',
+ padding: '1.2rem',
+ border: `1px solid ${morakGreen}`,
+ borderRadius: '1.6rem',
+ color: morakGreen,
+});
+
+export const groupTitle = style([
+ sansBold20,
+ {
+ display: 'flex',
+ alignItems: 'center',
+ gap: '0.4rem',
+ },
+]);
+
+export const participants = style([
+ sansRegular16,
+ {
+ display: 'flex',
+ gap: '0.4rem',
+ alignItems: 'center',
+ color: grayscale200,
+ },
+]);
+
+export const subText = style([
+ sansRegular16,
+ {
+ color: grayscale200,
+ },
+]);
diff --git a/app/frontend/src/pages/Groups/Join/index.tsx b/app/frontend/src/pages/Groups/Join/index.tsx
new file mode 100644
index 000000000..63a821320
--- /dev/null
+++ b/app/frontend/src/pages/Groups/Join/index.tsx
@@ -0,0 +1,78 @@
+import { useNavigate, useParams } from 'react-router-dom';
+
+import { Button } from '@morak/ui';
+
+import { ReactComponent as Lock } from '@/assets/icons/lock.svg';
+import { ReactComponent as People } from '@/assets/icons/people.svg';
+import { useGroupJoinAndLeave } from '@/components/Group/hooks/useGroupJoinLeave';
+import { useGroupModal } from '@/components/Group/hooks/useGroupModal';
+import { fontStyle, vars } from '@/styles';
+
+import * as styles from './index.css';
+
+const { sansBold36 } = fontStyle;
+const { grayscale200 } = vars.color;
+
+export function GroupJoinPage() {
+ const navigate = useNavigate();
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const { access_code: accessCode } = useParams();
+
+ const { openJoinModal } = useGroupModal();
+ const { handleJoin } = useGroupJoinAndLeave();
+
+ // accessCode로 그룹 정보 페칭 필요
+ const { id, closed } = { id: '1', closed: true };
+
+ const goBack = () => navigate(-1);
+
+ const onClickJoin = () =>
+ openJoinModal({ onClickConfirm: () => handleJoin(id) });
+
+ return (
+
+
그룹 참여
+
+
+ 부스트캠프 웹·모바일 9기
+ {closed && }
+
+
+
+ 120
+
+
+
+ {closed ? (
+
+
그룹에 가입 신청할까요?
+
+ 비공개 그룹은 그룹장의 승인 후 참여 처리됩니다.
+
+
+ ) : (
+ '이 그룹에 참여할까요?'
+ )}
+
+
+ {closed ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+}
diff --git a/app/frontend/src/pages/index.ts b/app/frontend/src/pages/index.ts
index be3bc46ce..e9577523a 100644
--- a/app/frontend/src/pages/index.ts
+++ b/app/frontend/src/pages/index.ts
@@ -1,5 +1,6 @@
export * from './Calendar';
export * from './Groups';
+export * from './Groups/Join';
export * from './Main';
export * from './Map';
export * from './Mogaco';