Skip to content

Commit cc53d54

Browse files
authored
Merge pull request #74 from Pyotato/73-refactor_project_structure
73-refactor_project_structure
2 parents cee8536 + fd18e84 commit cc53d54

File tree

96 files changed

+7814
-2333
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+7814
-2333
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module.exports = {
1111
'next/core-web-vitals',
1212
'plugin:@typescript-eslint/recommended',
1313
'prettier',
14+
'plugin:storybook/recommended',
1415
],
1516
rules: {
1617
//#region //*=========== jsx-a11y/label-has-associated-control ===========

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,5 @@ next-env.d.ts
4040
robots.txt
4141
sitemap.xml
4242
sitemap-*.xml
43+
44+
*storybook.log

.storybook/main.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import type { StorybookConfig } from '@storybook/nextjs';
2+
3+
const config: StorybookConfig = {
4+
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
5+
addons: [
6+
'@storybook/addon-onboarding',
7+
'@storybook/addon-links',
8+
'@storybook/addon-essentials',
9+
'@chromatic-com/storybook',
10+
'@storybook/addon-interactions',
11+
'@storybook/addon-styling-webpack',
12+
'storybook-dark-mode',
13+
'@storybook/addon-styling',
14+
'storybook-addon-mantine',
15+
'@tomfreudenberg/next-auth-mock/storybook',
16+
],
17+
framework: {
18+
name: '@storybook/nextjs',
19+
options: {},
20+
},
21+
docs: {
22+
autodocs: 'tag',
23+
},
24+
staticDirs: ['../public'],
25+
};
26+
export default config;

.storybook/preview.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import '@mantine/core/styles.css';
2+
import '@mantine/tiptap/styles.css';
3+
import 'reactflow/dist/style.css';
4+
5+
import type { Preview } from '@storybook/react';
6+
7+
const preview: Preview = {
8+
parameters: {
9+
controls: {
10+
matchers: {
11+
color: /(background|color)$/i,
12+
date: /Date$/i,
13+
},
14+
},
15+
nextjs: {
16+
appDirectory: true,
17+
},
18+
},
19+
};
20+
21+
export default preview;

.storybook/preview.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { MantineProvider } from '@mantine/core';
2+
3+
import { withThemeFromJSXProvider } from '@storybook/addon-themes';
4+
5+
import React from 'react';
6+
import { GlobalStyle } from '../src/styles/globalStyle';
7+
8+
import { ModalsProvider } from '@mantine/modals';
9+
import '@mantine/tiptap/styles.css';
10+
import 'reactflow/dist/style.css';
11+
import { ThemeProvider } from 'styled-components';
12+
import SessionWrapper from '../src/providers/SessionProvider';
13+
import StyledComponentsProvider from '../src/providers/StyledComponentsProvider';
14+
15+
export const parameters = {
16+
actions: { argTypesRegex: '^on[A-Z].*' },
17+
};
18+
19+
const GlobalStyles = GlobalStyle;
20+
21+
export const decorators = [
22+
(renderStory: any) => (
23+
<MantineProvider>
24+
<SessionWrapper>
25+
<ModalsProvider>
26+
<StyledComponentsProvider>{renderStory()}</StyledComponentsProvider>
27+
</ModalsProvider>
28+
</SessionWrapper>
29+
</MantineProvider>
30+
),
31+
withThemeFromJSXProvider({
32+
Provider: ThemeProvider,
33+
GlobalStyles,
34+
}),
35+
];

package.json

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
"format": "prettier -w .",
1616
"format:check": "prettier -c .",
1717
"postbuild": "next-sitemap --config next-sitemap.config.js",
18-
"prepare": "husky"
18+
"prepare": "husky",
19+
"storybook": "storybook dev -p 6006",
20+
"build-storybook": "storybook build"
1921
},
2022
"dependencies": {
2123
"@auth/core": "^0.28.0",
@@ -33,6 +35,7 @@
3335
"@mantine/rte": "^5.10.5",
3436
"@mantine/spotlight": "^7.5.2",
3537
"@mantine/tiptap": "^7.6.1",
38+
"@storybook/addon-themes": "^8.0.8",
3639
"@tabler/icons-react": "^2.47.0",
3740
"@tanstack/react-query": "^5.24.7",
3841
"@tiptap/extension-bullet-list": "^2.2.4",
@@ -51,6 +54,7 @@
5154
"@tiptap/pm": "^2.2.4",
5255
"@tiptap/react": "^2.2.4",
5356
"@tiptap/starter-kit": "^2.2.4",
57+
"@tomfreudenberg/next-auth-mock": "^0.5.6",
5458
"dayjs": "^1.11.10",
5559
"elkjs": "^0.9.2",
5660
"embla-carousel-react": "^8.0.0-rc22",
@@ -74,8 +78,19 @@
7478
"zustand": "^4.5.0"
7579
},
7680
"devDependencies": {
81+
"@chromatic-com/storybook": "^1.3.3",
7782
"@commitlint/cli": "^18.6.0",
7883
"@commitlint/config-conventional": "^18.6.0",
84+
"@storybook/addon-essentials": "^8.0.8",
85+
"@storybook/addon-interactions": "^8.0.8",
86+
"@storybook/addon-links": "^8.0.8",
87+
"@storybook/addon-onboarding": "^8.0.8",
88+
"@storybook/addon-styling": "^1.3.7",
89+
"@storybook/addon-styling-webpack": "^1.0.0",
90+
"@storybook/blocks": "^8.0.8",
91+
"@storybook/nextjs": "^8.0.8",
92+
"@storybook/react": "^8.0.8",
93+
"@storybook/test": "^8.0.8",
7994
"@svgr/webpack": "^8.1.0",
8095
"@tanstack/eslint-plugin-query": "^5.20.1",
8196
"@tanstack/react-query-devtools": "^5.24.7",
@@ -92,6 +107,7 @@
92107
"eslint-config-next": "14.1.0",
93108
"eslint-config-prettier": "^9.1.0",
94109
"eslint-plugin-simple-import-sort": "^12.0.0",
110+
"eslint-plugin-storybook": "^0.8.0",
95111
"eslint-plugin-unused-imports": "^3.0.0",
96112
"husky": "^9.0.10",
97113
"jest": "^29.7.0",
@@ -103,6 +119,9 @@
103119
"postcss": "^8.4.35",
104120
"postcss-simple-vars": "^7.0.1",
105121
"prettier": "^3.2.5",
122+
"storybook": "^8.0.8",
123+
"storybook-addon-mantine": "^4.0.2",
124+
"storybook-dark-mode": "^4.0.1",
106125
"ts-node": "^10.9.2",
107126
"typescript": "^5.3.3"
108127
},

src/components/MainPage.tsx renamed to src/app/MainPage.tsx

Lines changed: 9 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,22 @@
11
'use client';
22

33
import { useInfiniteQuery } from '@tanstack/react-query';
4-
import { PropsWithChildren, useEffect } from 'react';
4+
import { useEffect } from 'react';
55
import { useInView } from 'react-intersection-observer';
66

7-
import { apiRoutes } from '@/constants';
7+
import { API_ROUTES } from '@/constants';
8+
import { getApiResponse } from '@/utils/get-api-response';
89
import { getPageNum } from '@/utils/shared';
9-
import { getApiResponse } from '@/utils/shared/get-api-response';
1010

11-
import { ArticlesCardsGrid } from './shared/grid/ArticlesCardsGrid';
12-
import { SkeletonCardsGrid } from './shared/grid/SkeletonGrid';
11+
import { ItemsCardsGrid } from '../components/shared/ItemsCardsGrid';
12+
import { SkeletonCardsGrid } from '../components/shared/SkeletonGrid';
1313

14-
import { DataWithPages } from '@/types';
14+
import { Postdata } from '@/types/post';
1515

16-
export interface Member {
17-
id: number;
18-
email: string;
19-
nickname: string;
20-
bio: string;
21-
avatarUrl: null | string;
22-
githubUrl: null | string;
23-
blogUrl: null | string;
24-
baekjoonId: null | string;
25-
}
26-
export interface Post {
27-
id: number;
28-
title: string;
29-
description: string;
30-
thumbnailUrl: typeof url;
31-
likeCount: number;
32-
joinCount: number;
33-
createdAt: Date | string;
34-
updatedAt: Date | string;
35-
member: Member;
36-
}
37-
export const url = `${apiRoutes.roadmapPaged}2&order-type=recent`;
38-
39-
export interface Postdata extends DataWithPages {
40-
result: Array<Post | null>;
41-
}
42-
43-
export interface PageProps extends PropsWithChildren {
44-
postData: Postdata | null;
45-
}
4616
const loadDataFromApi = async ({ pageParam }: { pageParam: number }) => {
4717
const [postData] = await Promise.all([
4818
getApiResponse<Postdata>({
49-
apiEndpoint: `${apiRoutes.roadmapPaged}${pageParam}&order-type=recent`,
19+
apiEndpoint: `${API_ROUTES.roadmapPaged}${pageParam}&order-type=recent`,
5020
revalidate: 60 * 12, // 30 mins cache
5121
}),
5222
]);
@@ -100,16 +70,13 @@ export default function Mainpage() {
10070
<section>
10171
{posts.pages.map(({ postData }, index) =>
10272
postData?.next ? (
103-
<ArticlesCardsGrid
73+
<ItemsCardsGrid
10474
key={index}
10575
postData={postData?.result}
10676
innerRef={ref}
10777
/>
10878
) : (
109-
<ArticlesCardsGrid
110-
key={index}
111-
postData={postData?.result || []}
112-
/>
79+
<ItemsCardsGrid key={index} postData={postData?.result || []} />
11380
),
11481
)}
11582
</section>

src/app/api/auth/[...nextauth]/auth.ts

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,13 @@ import NextAuth, { User } from 'next-auth';
22
import CredentialsProvider from 'next-auth/providers/credentials';
33

44
// import GithubProvider from 'next-auth/providers/github';
5-
import { apiRoutes } from '@/constants';
5+
import { API_ROUTES } from '@/constants';
6+
import { consoleLog } from '@/utils/console-log';
7+
import { getApiResponse } from '@/utils/get-api-response';
68
import { omit } from '@/utils/shared';
7-
import { consoleLog } from '@/utils/shared/console-log';
8-
import { getApiResponse } from '@/utils/shared/get-api-response';
9-
export const runtime = 'edge';
109

11-
interface Member {
12-
id: number;
13-
email: string;
14-
nickname: string;
15-
bio?: null | string;
16-
avatarUrl?: null | string;
17-
githubUrl?: null | string;
18-
blogUrl?: null | string;
19-
baekjoonId?: null | string;
20-
provider?: string;
21-
accessToken?: string;
22-
}
10+
import { Member } from '@/types/user';
11+
export const runtime = 'edge';
2312

2413
interface AuthResponse {
2514
member?: Member | null;
@@ -57,7 +46,7 @@ export const {
5746
password: credentials.password,
5847
}),
5948
headers: { 'Content-Type': 'application/json' },
60-
apiEndpoint: `${apiRoutes.signin}`,
49+
apiEndpoint: `${API_ROUTES.signin}`,
6150
method: 'POST',
6251
}),
6352
);
@@ -66,7 +55,7 @@ export const {
6655
const userInfo = await Promise.resolve(
6756
getApiResponse<AuthResponse | null>({
6857
headers: { 'Content-Type': 'application/json' },
69-
apiEndpoint: `${apiRoutes.userInfoSlash}${res?.id}`,
58+
apiEndpoint: `${API_ROUTES.userInfoSlash}${res?.id}`,
7059
}),
7160
);
7261
const user = {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Box, Text } from '@mantine/core';
2+
import { signIn } from 'next-auth/react';
3+
4+
const LoginButton = () => {
5+
return (
6+
<Box mt='lg'>
7+
<Text className='hvr txt' onClick={() => signIn()} size='sm' ta='center'>
8+
로그인하러 가기
9+
</Text>
10+
</Box>
11+
);
12+
};
13+
export default LoginButton;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import LoginButton from '@/app/auth/components/LoginButton';
2+
3+
export default {
4+
title: '회원가입/로그인하러 가기',
5+
component: LoginButton,
6+
args: { primary: true, label: '로그인하러 가기' },
7+
tags: ['autodocs'],
8+
};
9+
10+
export const Default = {};
11+
export const Secondary = { args: { primary: false } };
12+
export const Large = { args: { size: 'large' } };
13+
export const LargeSecondary = { args: { ...Large.args, ...Secondary.args } };

0 commit comments

Comments
 (0)