Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
81f24c6
feature: 그래프 추가
six-standard Dec 24, 2024
809745d
modify: 500 오류 해결
six-standard Dec 24, 2024
672c13d
feature: 업데이트 시간 표시
six-standard Dec 24, 2024
fd7abc5
refactor: 네이밍 규칙 맞춤
six-standard Dec 24, 2024
395598e
refactor: 디자인 맞춤
six-standard Dec 24, 2024
c6ba088
refactor: API 요청 분리
six-standard Dec 24, 2024
430311b
refactor: 필요 없는 빈 공간 제거
six-standard Dec 24, 2024
4e00d9f
refactor: 폴더 이름 변경
six-standard Dec 24, 2024
558614d
refactor: 필요없는 파일 제거
six-standard Dec 24, 2024
3fb2282
refactor: 경로 정리
six-standard Dec 24, 2024
1a4e287
refactor: 필요 없는 주석 제거
six-standard Dec 24, 2024
69f199a
feature: 로그인 페이지 반응형 추가
six-standard Dec 24, 2024
f286a63
refactor: 색상 이름 변경
six-standard Dec 24, 2024
14cb7b2
refactor: 잡다한 리팩토링
six-standard Dec 24, 2024
76f224a
refactor: 색상 변경 깜빡함
six-standard Dec 24, 2024
db0190d
refactor: 반응형 고침
six-standard Dec 24, 2024
286a33b
modify: 반응형 깜빡함..
six-standard Dec 24, 2024
2d3c55e
refactor: 또 색상 깜빡함
six-standard Dec 24, 2024
28d023c
add: 필요한 라이브러리 추가
six-standard Dec 27, 2024
a86fd79
modify: import 관련 오류 수정
six-standard Dec 27, 2024
ebed432
modify: 데이터가 없을 경우 설정
six-standard Dec 27, 2024
3e94264
modify: CORS 관련 오류 해결
six-standard Dec 27, 2024
7d6ae1c
refactor: 여러 가지 리팩토링
six-standard Dec 27, 2024
fdd9cd5
feature: 대시보드 페이지 일부 제작
six-standard Dec 27, 2024
2264a40
feature: 스타일 팔레트 설정
six-standard Dec 27, 2024
e9a69ea
modify: 스크롤 관련 오류 해결
six-standard Dec 27, 2024
8dc72aa
feature: 개발 예정 텍스트 추가
six-standard Dec 27, 2024
d3f3a07
feature: 중간에 깜빡한 요소들
six-standard Dec 27, 2024
2ef003f
modify: 필요없는 데이터 제거
six-standard Dec 27, 2024
3d97339
modify: 페이지 체류시간 이벤트 조회
six-standard Dec 27, 2024
4cb1352
modify: 쿠키 시큐어 값 추가 및 릴리즈 데이터 추가
Nuung Dec 28, 2024
e38498d
modify: deprecated된 코드 제거
six-standard Dec 28, 2024
7d465c4
modify: 실제 module 버전이랑 다른 오류 해결
six-standard Dec 28, 2024
ae219f3
refactor: 코드 합침
six-standard Dec 28, 2024
1fda5b5
feature: 여려 API
six-standard Dec 28, 2024
ae03cab
modify: cors 관련 오류 해결
six-standard Dec 28, 2024
90ff606
feature: 트래커 다시 붙임
six-standard Dec 28, 2024
2e1f0b0
add: 필요한 라이브러리 추가
six-standard Dec 28, 2024
85f3b00
refactor: 필요없는 코드 제거
six-standard Dec 28, 2024
b6eee05
refactor: api 파일 정리
six-standard Dec 28, 2024
7e36d53
refactor: 로그아웃 추가
six-standard Dec 28, 2024
a33e07e
refacftor: 배포 환경일 경우에만 이벤트 수집
six-standard Dec 28, 2024
ff670a7
modify: Devtool 추가
six-standard Dec 28, 2024
60e29bd
modify: 핫픽스
six-standard Dec 28, 2024
698b283
refactor: ssr 수리 및 페이지 이동
six-standard Dec 29, 2024
2820576
refactor: 필요없는 코드 제거
six-standard Dec 29, 2024
bbfb8b9
refactor: 필요없는 코드 제거
six-standard Dec 29, 2024
cfaa259
refactor: 필요없는 코드 제거
six-standard Dec 30, 2024
7f0d4e4
feature: 게시글 상세조회 기능
six-standard Dec 30, 2024
25ef09b
modify: 날짜 제한 지정
six-standard Dec 30, 2024
9ef2690
refactor: 미사용 타입 제거
six-standard Dec 31, 2024
3c4bb83
modify: 타입 맞춤
six-standard Dec 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": [
"next/core-web-vitals",
"next/typescript"
]
}
11 changes: 10 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,16 @@ import pluginImport from 'eslint-plugin-import';
/** @type {import('eslint').Linter.Config[]} */
export default [
{ files: ['**/*.{js,mjs,cjs,ts,jsx,tsx}'] },
{ languageOptions: { globals: { ...globals.browser, ...globals.node } } },
{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
React: true,
NodeJS: true,
},
},
},
...tseslint.strict,
...tseslint.recommended,
pluginJs.configs.recommended,
Expand Down
7 changes: 7 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ const nextConfig = {
});
return config;
},

images: {
remotePatterns: [
{ protocol: 'https', hostname: 'velog.velcdn.com', pathname: '**' },
{ protocol: 'https', hostname: 'images.velog.io', pathname: '**' },
],
},
};
export default withSentryConfig(nextConfig, {
// For all available options, see:
Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,27 @@
"test": "jest"
},
"dependencies": {
"@sentry/nextjs": "^8",
"@tanstack/react-query": "^5.61.3",
"@tanstack/react-query-devtools": "^5.62.11",
"chart.js": "^4.4.7",
"js-cookie": "^3.0.5",
"next": "14.2.18",
"react": "^18",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18",
"react-hook-form": "^7.53.2",
"react-intersection-observer": "^9.14.0",
"react-toastify": "^10.0.6",
"return-fetch": "^0.4.6"
},
"devDependencies": {
"@eslint/js": "^9.15.0",
"@sentry/nextjs": "^8.47.0",
"@svgr/webpack": "^8.1.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/eslint-config-prettier": "^6.11.3",
"@types/jest": "^29.5.14",
"@types/js-cookie": "^3.0.6",
"@types/node": "^20",
Expand Down
3,393 changes: 1,317 additions & 2,076 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

Binary file removed public/favicon.jpg
Binary file not shown.
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- `git clone https://github.com/Check-Data-Out/velog-dashboard-v2-fe.git`
- `cd velog-dashboard-v2-fe`
- `pnpm install`
- `NODE_ENV=development pnpm install`
- `pnpm dev`

## 린팅
Expand Down
4 changes: 2 additions & 2 deletions src/__test__/login.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { act, screen } from '@testing-library/react';
import { ToastContainer } from 'react-toastify';
import { useRouter } from 'next/navigation';
import fetchMock from 'jest-fetch-mock';
import { renderWithQueryClient } from '@/utils';
import { renderWithQueryClient } from '@/utils/componentUtil';
import { TimeoutError } from '@/errors';
import { Login } from '@/app';
import { default as Login } from '@/app/(with-tracker)/(login)/page';

jest.mock('next/navigation', () => ({
useRouter: jest.fn(),
Expand Down
28 changes: 28 additions & 0 deletions src/apis/dashboard.request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { PostDetailDto, PostListDto, PostSummaryDto } from '@/types';
import { PATHS } from '@/constants';
import { InitType, instance } from './instance.request';

type SortType = {
asc: boolean;
sort: string;
};

export const postList = async (
props: InitType<PostListDto>,
sort: SortType,
cursor?: number | string,
) =>
await instance<null, PostListDto>(
cursor
? `${PATHS.POSTS}?cursor=${cursor}&asc=${sort.asc}&sort=${sort.sort}`
: `${PATHS.POSTS}?asc=${sort.asc}&sort=${sort.sort}`,
props,
);

export const postSummary = async (props: InitType<PostSummaryDto>) =>
await instance<null, PostSummaryDto>(PATHS.SUMMARY, props);

export const postDetail = async (path: string, start: string, end: string) =>
await instance<null, PostDetailDto>(
`${PATHS.DETAIL}/${path}?start=${start}&end=${end}`,
);
3 changes: 3 additions & 0 deletions src/apis/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './dashboard.request';
export * from './instance.request';
export * from './user.request';
38 changes: 30 additions & 8 deletions src/api/index.ts → src/apis/instance.request.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import returnFetch, { FetchArgs } from 'return-fetch';
import * as sentry from '@sentry/nextjs';

import { ServerNotRespondingError } from '@/errors';

const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;
Expand All @@ -16,15 +15,29 @@ if (!BASE_URL) {

type ErrorObject = Record<string, Error>;

type SuccessType<T> = {
success: true;
message: string;
data: T;
error: null;
};

export type InitType<I> = Omit<NonNullable<FetchArgs[1]>, 'body'> & {
body?: I | object;
};

const abortPolyfill = (ms: number) => {
const controller = new AbortController();
setTimeout(() => controller.abort(), ms);
return controller.signal;
};

const fetch = returnFetch({
baseUrl: BASE_URL + '/api',
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
baseUrl: BASE_URL,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
interceptors: {
response: async (response) => {
if (!response.ok) {
Expand All @@ -38,23 +51,32 @@ const fetch = returnFetch({
},
});

export const instance = async (
export const instance = async <I, R>(
input: URL | RequestInfo,
init?: Omit<NonNullable<FetchArgs[1]>, 'body'> & { body: object },
init?: InitType<I>,
error?: ErrorObject,
) => {
): Promise<R> => {
try {
const data = await fetch(input, {
const data = await fetch('/api' + input, {
...init,
body: init?.body ? JSON.stringify(init.body) : undefined,
signal: AbortSignal.timeout
? AbortSignal.timeout(ABORT_MS)
: abortPolyfill(ABORT_MS),
credentials: 'include',
});

return data as Awaited<ReturnType<typeof fetch>>;
return (data.body as unknown as SuccessType<R>).data;
} catch (err: any) {
const context = err as Response;
if (
location &&
!context.ok &&
(context.status === 401 || context.status === 403)
) {
location.replace('/');
}

sentry.setContext('Request', {
path: context.url,
status: context.status,
Expand Down
22 changes: 22 additions & 0 deletions src/apis/user.request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { NotFoundError } from '@/errors';
import { PATHS } from '@/constants';
import { LoginVo, UserDto } from '@/types';
import { InitType, instance } from './instance.request';

export const login = async (body: LoginVo) =>
await instance(
PATHS.LOGIN,
{ method: 'POST', body },
{
'404': new NotFoundError(
'일치하는 계정을 찾을 수 없습니다',
'CannotFindAccount',
),
},
);

export const me = async (props: InitType<UserDto>) =>
await instance<null, UserDto>(PATHS.ME, props);

export const logout = async () =>
await instance(PATHS.LOGOUT, { method: 'POST', body: undefined });
3 changes: 0 additions & 3 deletions src/app/(auth-required)/compare/page.tsx

This file was deleted.

11 changes: 0 additions & 11 deletions src/app/(auth-required)/layout.tsx

This file was deleted.

3 changes: 0 additions & 3 deletions src/app/(auth-required)/leaderboards/page.tsx

This file was deleted.

73 changes: 0 additions & 73 deletions src/app/(auth-required)/main/page.tsx

This file was deleted.

Loading