Skip to content

Commit

Permalink
[Feature]: 스터디 개설 페이지 레이아웃 (#21)
Browse files Browse the repository at this point in the history
* chore: lock 패키지 변경 사항 반영

* chore: 중복된 Navbar 컴포넌트 삭제

* feat: 개설 스터디 기본 잡기

* feat: 스터디 개설 페이지 레이아웃

* fix: 찌그러짐 방지용 minWidth 추가

* feat: 스터디 개설하기 뷰 생성

* fix: 개설된 스터디로 화면 옮기기

* feat: auth 체크용 middleWare 생성

* fix: utils fetcher 함수 export 경로 변경

* feat: 스터디 생성하기 페이지 생성

* fix: router handler 삭제

* refactor: api path 상수로 수정

* feat: isAdmin 함수 추가

* fix: 코드리뷰 반영

* fix: admin여부에 따라 스터디 생성 박스 보이지 않도록

* chore: 패키지 설치

* fix: 빌드에러 고치기

* fix: isadmin 판별 로직 미들웨어에서 진행

* feat: 역할 논리 다시

* fix: 폴더명 변경

* fix: createStudy 경로 변경

* feat:wow-icons 추가

* fix: 폴더구조 변경

* fix: 폴더 복수형 변경

---------

Co-authored-by: ghdtjgus76 <[email protected]>
  • Loading branch information
eugene028 and ghdtjgus76 authored Aug 16, 2024
1 parent be97dde commit e2f6fe0
Show file tree
Hide file tree
Showing 24 changed files with 352 additions and 153 deletions.
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.fixAll.stylelint": "explicit"
},
"eslint.workingDirectories": [
{
"mode": "auto"
Expand Down
27 changes: 27 additions & 0 deletions apps/admin/apis/auth/dashboardApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { fetcher } from "@wow-class/utils";
import { apiPath } from "constants/apiPath";
import { tags } from "constants/tags";
import { cookies } from "next/headers";
import type { DashboardApiResponseDto } from "types/dto/auth";

export const dashboardApi = {
getDashboardInfo: async () => {
const cookieStore = cookies();
const accessToken = cookieStore.get("accessToken")?.value;

const response = await fetcher.get<DashboardApiResponseDto>(
apiPath.dashboard,
{
next: { tags: [tags.dashboard] },
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
);

const studyRole = response.data?.member.studyRole;
const manageRole = response.data?.member.manageRole;

return { studyRole, manageRole };
},
};
6 changes: 6 additions & 0 deletions apps/admin/app/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"use client";
const ErrorPage = () => {
return <div>error</div>;
};

export default ErrorPage;
6 changes: 1 addition & 5 deletions apps/admin/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import "./global.css";
import "wowds-ui/styles.css";
import "@wow-class/ui/styles.css";

import Navbar from "components/Navbar";
import type { Metadata } from "next";

import { JotaiProvider } from "../components/JotaiProvider";
Expand All @@ -20,10 +19,7 @@ const RootLayout = ({
return (
<html lang="ko">
<body>
<JotaiProvider>
<Navbar />
{children}
</JotaiProvider>
<JotaiProvider>{children}</JotaiProvider>
</body>
</html>
);
Expand Down
5 changes: 5 additions & 0 deletions apps/admin/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const NotFound = () => {
return <div>요청하신 페이지를 찾을 수 없어요.</div>;
};

export default NotFound;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { css } from "@styled-system/css";
import { Flex } from "@styled-system/jsx";
import Link from "next/link";
import isAdmin from "utils/isAdmin";
import { Plus } from "wowds-icons";

const CreateStudyButton = async () => {
const adminStatus = await isAdmin();

if (!adminStatus) return null;

return (
<Link href="studies/create-study">
<button className={createStudyButtonStyle}>
<Flex gap="xs">
<p className={css({ textStyle: "label1", color: "sub" })}>
새로운 스터디 개설하기
</p>
<div className={PlusIconStyle}>
<Plus height={14} width={14} />
</div>
</Flex>
</button>
</Link>
);
};

export default CreateStudyButton;

const createStudyButtonStyle = css({
width: "100%",
display: "flex",
justifyContent: "center",
borderRadius: "md",
borderStyle: "dashed",
borderWidth: "1px",
borderColor: "outline",
padding: "32px",
_hover: {
backgroundColor: "backgroundAlternative",
borderWidth: "0px",
cursor: "pointer",
},
});

const PlusIconStyle = css({
display: "flex",
justifyContent: "center",
alignItems: "center",
width: "20px",
height: "20px",
borderRadius: "full",
backgroundColor: "primary",
color: "white",
});
5 changes: 5 additions & 0 deletions apps/admin/app/studies/create-study/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const CreateStudyPage = () => {
return <div>스터디 생성</div>;
};

export default CreateStudyPage;
20 changes: 20 additions & 0 deletions apps/admin/app/studies/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Flex, styled } from "@styled-system/jsx";
import Navbar from "components/Navbar";
const StudiesLayout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return (
<>
<Navbar />
<styled.div padding="54px 101px" width="100%">
<Flex direction="column" gap="sm" width="100%">
{children}
</Flex>
</styled.div>
</>
);
};

export default StudiesLayout;
18 changes: 15 additions & 3 deletions apps/admin/app/studies/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
const Studies = () => {
return <div>Studies</div>;
import { css } from "@styled-system/css";
import { Flex } from "@styled-system/jsx";

import CreateStudyButton from "./create-study/_components/CreateStudyButton";

const StudiesPage = () => {
return (
<>
<Flex align="center" justifyContent="space-between">
<p className={css({ textStyle: "h1" })}>개설된 스터디</p>
</Flex>
<CreateStudyButton />
</>
);
};

export default Studies;
export default StudiesPage;
1 change: 1 addition & 0 deletions apps/admin/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export default Navbar;

const navbarContainerStyle = css({
width: "250px",
minWidth: "250px",
minHeight: "100vh",
paddingTop: "54px",
borderRightWidth: "arrow",
Expand Down
3 changes: 3 additions & 0 deletions apps/admin/constants/apiPath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const enum apiPath {
dashboard = "/onboarding/members/me/dashboard",
}
3 changes: 3 additions & 0 deletions apps/admin/constants/tags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const enum tags {
dashboard = "dashboard",
}
35 changes: 35 additions & 0 deletions apps/admin/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { dashboardApi } from "apis/auth/dashboardApi";
import { cookies } from "next/headers";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";

export const config = {
matcher: ["/studies/:path*", "/participants/:path*"],
};

const middleware = async (req: NextRequest) => {
const cookieStore = cookies();
const accessToken = cookieStore.get("accessToken")?.value;

if (!accessToken) {
return NextResponse.redirect(new URL("/not-found", req.url));
}

const { studyRole, manageRole } = await dashboardApi.getDashboardInfo();

if (studyRole === "STUDENT" && manageRole === "NONE") {
const url =
process.env.NODE_ENV === "production"
? process.env.CLIENT_PROD_URL
: process.env.CLIENT_DEV_URL;

return NextResponse.redirect(new URL("/auth", url));
}
const response = NextResponse.next();

response.headers.set("Authorization", `Bearer ${accessToken}`);

return response;
};

export default middleware;
47 changes: 47 additions & 0 deletions apps/admin/types/dtos/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type { StatusType } from "../entities/auth";

export interface DashboardApiResponseDto {
member: {
memberId: number;
role: "GUEST" | "ADMIN" | "REGULAR";
manageRole: "ADMIN" | "NONE";
studyRole: "MENTOR" | "STUDENT";
basicInfo: {
name: string;
studentId: string;
email: string;
department: string;
phone: string;
discordUsername: string;
nickname: string;
};
associateRequirement: {
univStatus: StatusType;
discordStatus: Extract<StatusType, "UNSATISFIED" | "SATISFIED">;
bevyStatus: Extract<StatusType, "UNSATISFIED" | "SATISFIED">;
infoStatus: Extract<StatusType, "UNSATISFIED" | "SATISFIED">;
};
};
currentRecruitmentRound: {
recruitmentId: number;
name: string;
period: {
startDate: string;
endDate: string;
open: boolean;
};
fee: number;
roundType: "FIRST" | "SECOND";
roundTypeValue: string;
};
currentMembership: {
membershipId: number;
memberId: number;
recruitmentId: number;
regularRequirement: {
paymentStatus: Extract<StatusType, "UNSATISFIED" | "SATISFIED">;
paymentSatisfied: boolean;
allSatisfied: boolean;
};
};
}
1 change: 1 addition & 0 deletions apps/admin/types/entities/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type StatusType = "UNSATISFIED" | "IN_PROGRESS" | "SATISFIED";
3 changes: 3 additions & 0 deletions apps/admin/types/role.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type ManageRole = "ADMIN" | "NONE";
export type StudyRole = "MENTOR" | "STUDENT";
export type UserRoleType = "GUEST" | "ASSOCIATE" | "REGULAR";
2 changes: 2 additions & 0 deletions apps/admin/types/status.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type Status = "UNSATISFIED" | "SATISFIED";
export type UnivEmailStatus = "IN_PROGRESS" | "UNSATISFIED" | "SATISFIED";
33 changes: 33 additions & 0 deletions apps/admin/types/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { ManageRole, StudyRole, UserRoleType } from "./role";
import type { Status, UnivEmailStatus } from "./status";

export type User = {
memberId: string; // C000000 (학번)
role: UserRoleType;
basicInfo: UserBasicInfo;
manageRole: ManageRole;
studyRole: StudyRole;
associateRequirement: {
univStatus: UnivEmailStatus;
discordStatus: Status;
bevyStatus: Status;
infoStatus: Status;
};
};

export type AssociateRequirement = {
univStatus: UnivEmailStatus;
discordStatus: Status;
bevyStatus: Status;
infoStatus: Status;
};

export type UserBasicInfo = {
name: string;
studentId: string;
email: string;
department: string;
phone: string;
discordUsername: string;
nickname: string;
};
8 changes: 8 additions & 0 deletions apps/admin/utils/isAdmin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { dashboardApi } from "apis/auth/dashboardApi";

const isAdmin = async (): Promise<boolean> => {
const { manageRole } = await dashboardApi.getDashboardInfo();
return manageRole === "ADMIN";
};

export default isAdmin;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"clsx": "^2.1.1",
"wowds-icons": "^0.1.3",
"wowds-tokens": "^0.1.1",
"wowds-ui": "^0.1.13"
"wowds-ui": "^0.1.8",
"wowds-icons": "^0.1.2"
}
}
9 changes: 5 additions & 4 deletions packages/utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
"name": "@wow-class/utils",
"version": "0.0.0",
"private": true,
"scripts": {
"test": "jest"
},
"exports": {
".": "./src/index.ts"
},
"scripts": {
"test": "jest"
},
"devDependencies": {
"@types/jest": "^29.5.12",
"@wow-class/typescript-config": "workspace:*",
"jest": "^29.7.0",
"jest-fetch-mock": "^3.0.3",
"ts-jest": "^29.2.4",
"@wow-class/eslint-config": "workspace:*"
"@wow-class/eslint-config": "workspace:*",
"typescript": "^5.3.3"
}
}
3 changes: 3 additions & 0 deletions packages/utils/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"extends": "@wow-class/typescript-config/basic.json",
"compilerOptions": {
"baseUrl": "./src"
},
"include": ["src", "jest.setup.ts"],
"exclude": ["node_modules"]
}
Loading

0 comments on commit e2f6fe0

Please sign in to comment.