Skip to content

Commit

Permalink
[Feature] 구글 로그인 회원가입 및 온보딩 페이지 구현 (#20)
Browse files Browse the repository at this point in the history
* feat: 더미 사이드바 UI 구현

* feat: `Input` 컴포넌트 구현

* feat: `Checkbox` 구현

* feat: 회원가입 Form UI 구현

* feat: 로그인 Form 구현

* feat: 로그인 페이지 및 리다이렉트 구현

* docs: 이용 약관 작성

* feat: 회원가입 폼 UI 디자인 구현

* feat: 회원가입 서버 통신 로직 구현

* feat: 폼 제출간 로딩 구현

* feat: 온보딩 페이지 기초 레이아웃 구성

* feat: 온보딩 페이지 UI 구현

* feat: 온보딩 네트워크 통신 로직 구현

* feat: 유효성 검사 로직 일부 구현

* feat: 로그인 페이지 권한 검사 미들웨어 구현

* refactor: 미들웨어 추상화

* feat: 토큰 만료에 따른 refresh 로직 추가

* docs: 개인정보 처리방침 작성

* fix: 이용약관 및 개인정보 처리 방침 수정

* refactor: 메인 페이지 기본 딜레이 시간을 공용 함수에서 제거

* refactor: 권한 관리 미들웨어 리팩토링

* chore: 미사용 빌드 타임 스탬프 제거

* fix: 스토리북 패키지 의존성 수정

* fix: chromatic 워크플로우 수정

* chore: `SignUpForm` 스토리 제거

* feat: 스토리북에 msw 추가

* refactor: 테스트 환경 분리

* test: 유효성 검사 테스트 작성

* test: 퍼널 페이지 테스트 및 스토리 작성

* design: 스토리북 커스터마이징

* fix: 스토리북 데코레이터를 워크샵에서 관리하도록 수정

* fix: 에러 발생하는 스토리 빌드 제외

* fix: 스토리북 환경에서의 `prefetch` 비활성화

* refactor: `Storybook` 에러 해결을 위한 `Link` 래퍼 구현

related on: #22

* fix: 온보딩 뒤로 가기 제거
  • Loading branch information
cobocho authored Jun 13, 2024
1 parent ef1ed62 commit f9d4fa4
Show file tree
Hide file tree
Showing 140 changed files with 5,456 additions and 288 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ jobs:
run: pnpm install -no-frozen-lockfile
working-directory: apps/workshop

- name: Build Design System Package
run: pnpm run build
working-directory: packages/design-system

- name: Publish Chromatic
id: chromatic
uses: chromaui/action@latest
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.tsdk": "node_modules/typescript/lib",
"liveServer.settings.port": 5501
}
25 changes: 17 additions & 8 deletions apps/extension/components/TermItem/TermItem.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,27 @@ const meta = {
'<strong>서버</strong>는 네트워크에 연결된 컴퓨터로 클라이언트의 요청을 받아 처리하고 결과를 응답으로 보냅니다. 웹 <strong>서버</strong>, 데이터 베이스 <strong>서버</strong>, 메일 <strong>서버</strong> 등이 <strong>서버</strong>에 속합니다.',
},
},
decorators: [
(Story) => (
<div style={{ width: '600px' }}>
<Story />
</div>
),
],
argTypes: {
term: {
control: {
type: 'object',
},
},
},
tags: ['autodocs'],
} satisfies Meta<typeof TermItem>

export default meta

type Story = StoryObj<typeof meta>

export const Preview: Story = {}
export const Preview: Story = {
args: {
term: {
term: '<strong>서버</strong>',
synonyms: 'Server',
meaning:
'<strong>서버</strong>는 네트워크에 연결된 컴퓨터로 클라이언트의 요청을 받아 처리하고 결과를 응답으로 보냅니다. 웹 <strong>서버</strong>, 데이터 베이스 <strong>서버</strong>, 메일 <strong>서버</strong> 등이 <strong>서버</strong>에 속합니다.',
},
},
}
1 change: 1 addition & 0 deletions apps/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@types/node": "^20.11.24",
"@types/react": "^18.2.61",
"@types/react-dom": "^18.2.19",
"@vitejs/plugin-react": "^4.3.1",
"@vitest/ui": "^1.6.0",
"@vook-client/eslint-config": "*",
"eslint": "^8.57.0",
Expand Down
3 changes: 3 additions & 0 deletions apps/web/.env.development
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NEXT_PUBLIC_DOMAIN=http://localhost:3000
NEXT_PUBLIC_API_URL=https://dev.vook-api.seungyeop-lee.com
NEXT_PUBLIC_GOOGLE_LOGIN_URL=https://dev.vook-api.seungyeop-lee.com/oauth2/authorization/google
2 changes: 2 additions & 0 deletions apps/web/.env.staging
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
NEXT_PUBLIC_DOMAIN=https://stag.vook.seungyeop-lee.com
NEXT_PUBLIC_API_URL=https://stag.vook-api.seungyeop-lee.com
NEXT_PUBLIC_GOOGLE_LOGIN_URL=https://stag.vook-api.seungyeop-lee.com/oauth2/authorization/google
20 changes: 18 additions & 2 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,52 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "eslint . --max-warnings 0"
"lint": "eslint . --max-warnings 0",
"test": "vitest"
},
"dependencies": {
"@hookform/resolvers": "^3.6.0",
"@tanstack/react-query": "^5.32.0",
"@types/js-cookie": "^3.0.6",
"@vanilla-extract/css": "^1.14.2",
"@vanilla-extract/css-utils": "^0.1.3",
"@vanilla-extract/dynamic": "^2.1.0",
"@vanilla-extract/recipes": "^0.5.2",
"@vanilla-extract/sprinkles": "^1.6.1",
"@vook-client/api": "*",
"@vook-client/design-system": "*",
"js-cookie": "^3.0.5",
"next": "^14.1.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.51.5",
"vite-tsconfig-paths": "^4.3.2",
"zod": "^3.23.8",
"zustand": "^4.5.2"
},
"devDependencies": {
"@next/eslint-plugin-next": "^14.1.1",
"@storybook/react": "^8.0.10",
"@storybook/test": "^8.0.10",
"@tanstack/react-query-devtools": "^5.32.0",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^15.0.5",
"@testing-library/user-event": "^14.5.2",
"@types/eslint": "^8.56.5",
"@types/node": "^20.11.24",
"@types/react": "^18.2.61",
"@types/react-dom": "^18.2.19",
"@vanilla-extract/next-plugin": "^2.4.0",
"@vanilla-extract/vite-plugin": "^4.0.9",
"@vanilla-extract/webpack-plugin": "^2.3.7",
"@vitejs/plugin-react": "^4.3.1",
"@vook-client/eslint-config": "*",
"@vook-client/typescript-config": "*",
"clsx": "^2.1.1",
"eslint": "^8.57.0"
"dotenv": "^16.4.5",
"eslint": "^8.57.0",
"jsdom": "^24.0.0",
"msw": "^2.3.1",
"vitest": "^1.5.2"
}
}
29 changes: 29 additions & 0 deletions apps/web/setupTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import '@testing-library/jest-dom'
import { handlers } from '@vook-client/api'
import { setupServer } from 'msw/node'
import { cleanup } from '@testing-library/react'
import { afterEach } from 'vitest'

const mswServer = setupServer(...handlers)

vi.mock('next/font/local', () => {
return {
default: () => {},
}
})

vi.mock('next/navigation', () => ({
useRouter() {
return {
prefetch: () => null,
}
},
}))

afterEach(() => {
cleanup()
})

beforeAll(() => mswServer.listen())

afterAll(() => mswServer.close())
7 changes: 7 additions & 0 deletions apps/web/src/app/(afterLogin)/layout.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { style } from '@vanilla-extract/css'

import { SIDE_BAR_WIDTH } from '@/styles/layout'

export const mainArea = style({
marginLeft: SIDE_BAR_WIDTH,
})
16 changes: 16 additions & 0 deletions apps/web/src/app/(afterLogin)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React, { PropsWithChildren } from 'react'

import { Sidebar } from '@/components/Sidebar'

import { mainArea } from './layout.css'

const Layout = ({ children }: PropsWithChildren) => {
return (
<div className={mainArea}>
<Sidebar />
{children}
</div>
)
}

export default Layout
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ import { Term } from '@/components/Term/Term'

const Home = () => {
return (
<main className={main}>
<div className={main}>
<Header />

<div style={{ flex: 1 }}>
<Search />
<Term />
</div>

<Footer />
</main>
</div>
)
}

Expand Down
48 changes: 48 additions & 0 deletions apps/web/src/app/(beforeLogin)/auth/token/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use client'

import { userInfoService, UserStatus } from '@vook-client/api'
import Cookies from 'js-cookie'
import { useRouter } from 'next/navigation'
import { useEffect } from 'react'

interface AuthCallbackQueryParams {
searchParams: {
access: string
refresh: string
}
}

const AuthCallbackPage = ({
searchParams: { access, refresh },
}: AuthCallbackQueryParams) => {
const router = useRouter()

useEffect(() => {
Cookies.set('access', access, {
secure: true,
})
Cookies.set('refresh', refresh, {
secure: true,
})

const checkUserRegistered = async () => {
const userInfo = await userInfoService.getUserInfo({
access,
refresh,
})
const isRegistered = userInfo.result.status === UserStatus.Registered

if (isRegistered) {
router.push('/')
return
}
router.push('/signup')
}

checkUserRegistered()
}, [access, refresh, router])

return null
}

export default AuthCallbackPage
10 changes: 10 additions & 0 deletions apps/web/src/app/(beforeLogin)/login/layout.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { style } from '@vanilla-extract/css'

export const loginLayout = style({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',

width: '100dvw',
height: '100dvh',
})
9 changes: 9 additions & 0 deletions apps/web/src/app/(beforeLogin)/login/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React, { PropsWithChildren } from 'react'

import { loginLayout } from './layout.css'

const Layout = ({ children }: PropsWithChildren) => {
return <div className={loginLayout}>{children}</div>
}

export default Layout
5 changes: 5 additions & 0 deletions apps/web/src/app/(beforeLogin)/login/page.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { style } from '@vanilla-extract/css'

export const loginFormArea = style({
width: 380,
})
15 changes: 15 additions & 0 deletions apps/web/src/app/(beforeLogin)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react'

import { LoginForm } from '@/components/LoginForm'

import { loginFormArea } from './page.css'

const LoginPage = () => {
return (
<div className={loginFormArea}>
<LoginForm />
</div>
)
}

export default LoginPage
10 changes: 10 additions & 0 deletions apps/web/src/app/(beforeLogin)/signup/layout.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { style } from '@vanilla-extract/css'

export const loginLayout = style({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',

width: '100dvw',
height: '100dvh',
})
9 changes: 9 additions & 0 deletions apps/web/src/app/(beforeLogin)/signup/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { PropsWithChildren } from 'react'

import { loginLayout } from './layout.css'

const Layout = ({ children }: PropsWithChildren) => {
return <div className={loginLayout}>{children}</div>
}

export default Layout
5 changes: 5 additions & 0 deletions apps/web/src/app/(beforeLogin)/signup/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const Loading = () => {
return <div />
}

export default Loading
5 changes: 5 additions & 0 deletions apps/web/src/app/(beforeLogin)/signup/page.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { style } from '@vanilla-extract/css'

export const signupForm = style({
width: 380,
})
13 changes: 13 additions & 0 deletions apps/web/src/app/(beforeLogin)/signup/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { SignUpForm } from '@/components/SignUpForm'

import { signupForm } from './page.css'

const SignUpPage = () => {
return (
<div className={signupForm}>
<SignUpForm />
</div>
)
}

export default SignUpPage
6 changes: 6 additions & 0 deletions apps/web/src/app/(beforeLogin)/terms/layout.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { style } from '@vanilla-extract/css'

export const termsLayout = style({
width: 780,
margin: '30px auto',
})
9 changes: 9 additions & 0 deletions apps/web/src/app/(beforeLogin)/terms/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { PropsWithChildren } from 'react'

import { termsLayout } from './layout.css'

const Layout = ({ children }: PropsWithChildren) => {
return <div className={termsLayout}>{children}</div>
}

export default Layout
Loading

0 comments on commit f9d4fa4

Please sign in to comment.