Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
64 changes: 34 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@
[PikCha]는 다양한 영화에서 두 가지를 선택해 **A/B 테스트로 비교**하는 웹 애플리케이션입니다.
사용자는 결과를 공유하고, 후기·별점 데이터를 기반으로 영화 랭킹을 확인할 수 있습니다.

- [🧷 요구사항 가이드](https://www.notion.so/631abba6780048859d73d74eabf0070f?pvs=21)
- [🧷 API 문서 (Swagger)](https://mogazoa-api.vercel.app/docs/#/)
- [🧷 Figma - 디자인](https://www.figma.com/design/mo37KmYpd3ZsJ6Ojay2u83/%5BCCC%5DMogazoa?node-id=0-1&t=tcmXymiGLgoJ6for-1)
- [🧷 Figma - User Flow](https://www.figma.com/board/dst53QIQUDpW5ZTefQLntS/mogajoa-userflow?node-id=0-1&p=f&t=ZTPVGfnpShbiv65H-0)
- [🧷 요구사항 가이드](https://www.notion.so/631abba6780048859d73d74eabf0070f?pvs=21)
- [🧷 API 문서 (Swagger)](https://mogazoa-api.vercel.app/docs/#/)
- [🧷 Figma - 디자인](https://www.figma.com/design/mo37KmYpd3ZsJ6Ojay2u83/%5BCCC%5DMogazoa?node-id=0-1&t=tcmXymiGLgoJ6for-1)
- [🧷 Figma - User Flow](https://www.figma.com/board/dst53QIQUDpW5ZTefQLntS/mogajoa-userflow?node-id=0-1&p=f&t=ZTPVGfnpShbiv65H-0)

---

## 📝 프로젝트 문서

- [🧷 수행 계획서](https://www.notion.so/25405a1cda5a808695a7d738d0fdd9c4?pvs=21)
- [🧷 프로젝트 일정관리](https://www.notion.so/25405a1cda5a80bc8345e1b637c6dca5?pvs=21)
- [🧷 구현 상세 계획](https://www.notion.so/25405a1cda5a8040bc02e47eab05c1b7?pvs=21)
- [🧷 수행 계획서](https://www.notion.so/25405a1cda5a808695a7d738d0fdd9c4?pvs=21)
- [🧷 프로젝트 일정관리](https://www.notion.so/25405a1cda5a80bc8345e1b637c6dca5?pvs=21)
- [🧷 구현 상세 계획](https://www.notion.so/25405a1cda5a8040bc02e47eab05c1b7?pvs=21)

---

Expand Down Expand Up @@ -76,18 +76,19 @@

## 👥 팀 구성 및 역할

| 이름 | 역할 |
|------|-------------------------|
| 김성주 | 유저정보, 내정보, 팔로워/팔로잉 모달 |
| 나소연 | 메인, 비교하기 모달, GNB, 컬러·폰트 |
| 이름 | 역할 |
| ------ | ------------------------------------ |
| 김성주 | 유저정보, 내정보, 팔로워/팔로잉 모달 |
| 나소연 | 메인, 비교하기 모달, GNB, 컬러·폰트 |
| 남만재 | 상품 상세, 상품 등록/편집, 리뷰 기능 |
| 배민지 | 로그인, 회원가입, 폼/입력 UI |
| 배민지 | 로그인, 회원가입, 폼/입력 UI |

---

## 🔍 QA & 코드 리뷰
- [🧷 QA 체크리스트](https://www.notion.so/25e05a1cda5a80ff8772e35060c6ddd2?pvs=21)
- [🧷 2차 QA 체크리스트](https://www.notion.so/26505a1cda5a808e8f02e24e58c5f205?pvs=21)

- [🧷 QA 체크리스트](https://www.notion.so/25e05a1cda5a80ff8772e35060c6ddd2?pvs=21)
- [🧷 2차 QA 체크리스트](https://www.notion.so/26505a1cda5a808e8f02e24e58c5f205?pvs=21)

**코드 리뷰 담당자**
| 작성자 | 리뷰어 |
Expand All @@ -100,27 +101,30 @@
---

## 🎨 디자인 & 요구사항
- [🧷 User Flow](https://www.figma.com/board/dst53QIQUDpW5ZTefQLntS/mogajoa-userflow?node-id=0-1&p=f&t=ZTPVGfnpShbiv65H-0)
- [🧷 요구사항](https://docs.google.com/spreadsheets/d/13eRz1_guXs7pYHc8VXqhDdhGtIV06gvn9Pc64pF2dUI/edit?gid=0#gid=0)

- [🧷 User Flow](https://www.figma.com/board/dst53QIQUDpW5ZTefQLntS/mogajoa-userflow?node-id=0-1&p=f&t=ZTPVGfnpShbiv65H-0)
- [🧷 요구사항](https://docs.google.com/spreadsheets/d/13eRz1_guXs7pYHc8VXqhDdhGtIV06gvn9Pc64pF2dUI/edit?gid=0#gid=0)

---

## 🔌 기술 스택
- **Frontend**: Next.js 15(App Router), React, TypeScript, Tailwind CSS v4, shadcn/ui
- **State Management**: Zustand
- **Auth**: OAuth2.0, NextAuth
- **Form & Validation**: react-hook-form, zod
- **Build & Deploy**: Webpack, Vercel
- **Collaboration**: GitHub, Linear, Notion

- **Frontend**: Next.js 15(App Router), React, TypeScript, Tailwind CSS v4, shadcn/ui
- **State Management**: Zustand
- **Auth**: OAuth2.0, NextAuth
- **Form & Validation**: react-hook-form, zod
- **Build & Deploy**: Webpack, Vercel
- **Collaboration**: GitHub, Linear, Notion

---

## 📚 참고 문서
- [TypeScript](https://www.typescriptlang.org/docs/)
- [React](https://react.dev/)
- [Next.js](https://nextjs.org/docs)
- [Tailwind CSS](https://tailwindcss.com/docs)
- [shadcn/ui](https://ui.shadcn.com/docs/components)
- [Zustand](https://docs.pmnd.rs/zustand/getting-started/introduction)
- [Vercel](https://vercel.com/docs)
- [OAuth 2.0](https://oauth.net/2/)

- [TypeScript](https://www.typescriptlang.org/docs/)
- [React](https://react.dev/)
- [Next.js](https://nextjs.org/docs)
- [Tailwind CSS](https://tailwindcss.com/docs)
- [shadcn/ui](https://ui.shadcn.com/docs/components)
- [Zustand](https://docs.pmnd.rs/zustand/getting-started/introduction)
- [Vercel](https://vercel.com/docs)
- [OAuth 2.0](https://oauth.net/2/)
101 changes: 48 additions & 53 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
@import 'tw-animate-css';
@import 'tailwind-scrollbar-hide/v4';

@custom-variant light (&:is(.light *));
/*---break---*/
@custom-variant dark (&:is(.dark *));

@theme {
--color-background: var(--background);
Expand Down Expand Up @@ -138,6 +139,8 @@
@apply text-2xl font-semibold;
}

/*---break---*/

@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
Expand Down Expand Up @@ -176,42 +179,9 @@
--color-sidebar-ring: var(--sidebar-ring);
}

:root {
--radius: 0.625rem;
--background: #ffffff;
--foreground: #1c1c22;
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
}
/*---break---*/

.dark {
:root {
--radius: 0.625rem;
--background: #1c1c22;
--foreground: #f1f1f5;
Expand Down Expand Up @@ -246,17 +216,52 @@
--sidebar-ring: oklch(0.708 0 0);
}

/*---break---*/

.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.556 0 0);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.556 0 0);
}

html {
scrollbar-gutter: stable; /* 스크롤바가 생길 때 레이아웃이 움직이는 현상 방지 */
}

body {
font-family: var(--font-pretendard);
transition:
background-color 0.3s ease,
color 0.3s ease;
}

/*---break---*/

@layer base {
* {
border-color: var(--border);
Expand All @@ -275,26 +280,16 @@ button:disabled {
cursor: default;
}

.dark input:-webkit-autofill,
.dark input:-webkit-autofill:hover,
.dark input:-webkit-autofill:focus,
.dark input:-webkit-autofill:active {
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 1000px #252530 inset;
-webkit-text-fill-color: #f1f1f5 !important;
color: #f1f1f5 !important;
caret-color: #f1f1f5;
}

:root:not(.dark) input:-webkit-autofill,
:root:not(.dark) input:-webkit-autofill:hover,
:root:not(.dark) input:-webkit-autofill:focus,
:root:not(.dark) input:-webkit-autofill:active {
-webkit-box-shadow: 0 0 0 1000px #ffffff inset;
-webkit-text-fill-color: #111111 !important;
color: #111111 !important;
caret-color: #111111;
}

[data-sonner-toaster] {
z-index: 50 !important;
}
Expand Down
7 changes: 7 additions & 0 deletions src/app/head.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function Head() {
return (
<>
<meta name='color-scheme' content='light dark' />
</>
);
}
32 changes: 11 additions & 21 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { SpeedInsights } from '@vercel/speed-insights/next';
import { SessionProvider } from 'next-auth/react';
import { ThemeProvider } from 'next-themes';

import FooterLazy from '@/components/common/Footer/FooterLazy';
import GlobalNav from '@/components/common/gnb/GlobalNav';
Expand All @@ -18,28 +17,19 @@ export const metadata: Metadata = {
description: 'Generated by create next app',
};

export default async function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
return (
<html lang='ko'>
<html lang='ko' className={'theme'}>
<body className={pretendard.variable}>
<ThemeProvider
attribute='class' // Tailwind v4 class 전략
defaultTheme='dark' // 기본 테마
enableSystem={false} // 시스템 모드 비활성화
themes={['light', 'dark']} // 사용 테마 제한
storageKey='pickcha-theme' // 로컬스토리지 키
>
<SessionProvider>
{/* 서버 컴포넌트에서 세션 정보를 가져와 클라이언트 컴포넌트에 전달 */}
<GlobalNav />
{children}
<FooterLazy />
<FloatingButton />
<SonnerToast />
<SpeedInsights />
<ModalContainer />
</SessionProvider>
</ThemeProvider>
<SessionProvider>
<GlobalNav />
{children}
<FooterLazy />
<FloatingButton />
<SonnerToast />
<SpeedInsights />
<ModalContainer />
</SessionProvider>
</body>
</html>
);
Expand Down
1 change: 0 additions & 1 deletion src/components/common/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
data-slot='input'
className={cn(
'bg-black-252530 text-mogazoa-14px-400 border-black-353542',
'light:bg-white light:text-black',
hasError ? 'border-red-ff0000' : 'border-black-353542',
'rounded-[8px] border outline-none',
'flex h-[55px] w-full py-6 pr-10 pl-5 xl:h-[70px]',
Expand All @@ -56,7 +55,7 @@
if (maxLength) e.target.value = truncated(e.target.value, maxLength);
return e.target.value.length;
});
setError && setError(false);

Check warning on line 58 in src/components/common/Input.tsx

View workflow job for this annotation

GitHub Actions / build-and-test

Expected an assignment or function call and instead saw an expression
props.onChange?.(e);
}}
/>
Expand Down