Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix/#152]:랜딩페이지 #154

Merged
merged 22 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
113 changes: 66 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,82 @@
## 🧑‍💻 프로젝트 소개
### 우리들의 행복한 시간 ⏰

### 우리들의 행복한 시간 ⏰

> 우리FIS 아카데미 교육생들을 대상으로 공부한 시간을 측정하여 학습 기록을 확인할 수 있는 서비스

[우행시에 접속하고 싶다면? 클릭해주세요! 👀](https://woohangshi.vercel.app/)
- 테스트 유저 ID: [email protected]
[우행시에 접속하고 싶다면? 클릭해주세요! 👀](https://woohangshi.vercel.app/)

- 테스트 유저 ID: [email protected]
- 테스트 유저 PW: test1234!

<br/>

## 👻 팀원구성

| <img src="https://github.com/riverkite0708.png" width="200" /> | <img src="https://github.com/Kong-E.png" width="200" /> | <img src="https://github.com/doyi0107.png" width="200" /> |
|:---:|:---:|:---:|
| [강재연](https://github.com/riverkite0708) | [공소연](https://github.com/Kong-E) | [이도이](https://github.com/doyi0107) |
| 프론트엔드 | 프론트엔드 | 프론트엔드 |
| UI 가이드라인, <br /> 기록확인, 마이페이지 구현 | 인증/인가,공부하기 구현, <br /> API 설정 | 랜딩 페이지, 과목선택, <br /> 순위조회 구현 |
| :------------------------------------------------------------: | :-----------------------------------------------------: | :-------------------------------------------------------: |
| [강재연](https://github.com/riverkite0708) | [공소연](https://github.com/Kong-E) | [이도이](https://github.com/doyi0107) |
| 프론트엔드 | 프론트엔드 | 프론트엔드 |
| UI 가이드라인, <br /> 기록확인, 마이페이지 구현 | 인증/인가,공부하기 구현, <br /> API 설정 | 랜딩 페이지, 과목선택, <br /> 순위조회 구현 |

| <img src="https://github.com/khwoowoo.png" width="200" /> | <img src="https://github.com/rlfrkdms1.png" width="200" /> | <img src="https://github.com/qbobl5.png" width="200" /> | <img src="https://github.com/yaejinkong.png" width="200" /> |
|:---:|:---:|:---:|:---:|
| [강현우(팀장)](https://github.com/khwoowoo) | [길가은](https://github.com/rlfrkdms1) | [김혜빈](https://github.com/qbobl5) | [공예진](https://github.com/yaejinkong) |
| 백엔드 | 백엔드 | 백엔드 | 백엔드 |
| 클라우드 인프라 구축, <br /> 랭킹 API 개발 | 백엔드 | 백엔드 | 백엔드 |
| :-------------------------------------------------------: | :--------------------------------------------------------: | :-----------------------------------------------------: | :---------------------------------------------------------: |
| [강현우(팀장)](https://github.com/khwoowoo) | [길가은](https://github.com/rlfrkdms1) | [김혜빈](https://github.com/qbobl5) | [공예진](https://github.com/yaejinkong) |
| 백엔드 | 백엔드 | 백엔드 | 백엔드 |
| 클라우드 인프라 구축, <br /> 랭킹 API 개발 | 백엔드 | 백엔드 | 백엔드 |

## 🎞️ 시연영상

https://github.com/CSID-DGU/2023-S-VSA-DingDong-5/assets/96400257/600cb770-32b7-48e9-a07e-87b7f9f425e9

<br/>

## ⚙️ 시스템 아키텍처
### 프로젝트 구조도
![프로젝트 구조도](https://github.com/user-attachments/assets/97c151ee-4875-4c52-b446-0f5b88dabaaa)
---
### 인프라 구조도

### 프로젝트 구조도

## ![프로젝트 구조도](https://github.com/user-attachments/assets/97c151ee-4875-4c52-b446-0f5b88dabaaa)

### 인프라 구조도

![인프라 구조도](https://github.com/user-attachments/assets/81017061-93c3-4720-9abc-eafc10874017)

<br/>

## 📚 기술 스택
### Common

### Common

![Notion](https://img.shields.io/badge/Notion-eeeeee.svg?style=flat-square&logo=notion&logoColor=000000)
![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=flat-square&logo=github&logoColor=white)
![Postman](https://img.shields.io/badge/Postman-FF6C37?style=flat-square&logo=postman&logoColor=white)

### UI/UX
### UI/UX

![Radix UI](https://img.shields.io/badge/radix%20ui-161618.svg?style=flat-square&logo=radix-ui&logoColor=white)
![figma](https://img.shields.io/badge/figma-f24e1e?style=flat-square&logo=figma&logoColor=ffffff)

### Frontend
### Frontend

![Next JS](https://img.shields.io/badge/Next.js-black?style=flat-square&logo=next.js&logoColor=white)
![Zustand](https://img.shields.io/badge/Zustand-orange?style=flat-square&logo=zustand&logoColor=white)
![TypeScript](https://img.shields.io/badge/TypeScript-%23007ACC.svg?style=flat-square&logo=typescript&logoColor=white)
![authjs](https://img.shields.io/badge/Auth.js-1eabf4?style=flat-square&logo=nextauth&logoColor=black)
![SWR](https://img.shields.io/badge/SWR-black.svg?style=flat-square&logo=swr&logoColor=white)
![SWR](https://img.shields.io/badge/SWR-black.svg?style=flat-square&logo=swr&logoColor=white)
![ESLint](https://img.shields.io/badge/ESLint-4B3263?style=flat-square&logo=ESLint&logoColor=white)
![Prettier](https://img.shields.io/badge/prettier-%23F7B93E.svg?style=flat-square&logo=prettier&logoColor=black)
![Vercel](https://img.shields.io/badge/Vercel-000000?style=flat-square&logo=Vercel&logoColor=white)

### Backend
### Backend

<img src="https://img.shields.io/badge/SpringBoot-6DB33F?style=flat-square&logo=SpringBoot&logoColor=white"> <img src="https://img.shields.io/badge/SpringDataJpa-6DB33F?style=flat-square&logo=SpringDataJpat&logoColor=white"> <img src="https://img.shields.io/badge/QueryDsl-137CBD?style=flat-square&logo=QueryDsl&logoColor=white"> <img src="https://img.shields.io/badge/Gradle-02303A?style=flat-square&logo=Gradle&logoColor=white"> <img src="https://img.shields.io/badge/Swagger-85EA2D?style=flat-square&logo=Swagger&logoColor=white"> <img src="https://img.shields.io/badge/JWT-black?style=flat-square&logo=JSON%20web%20tokens">

### Infra & DB
### Infra & DB

<img src="https://img.shields.io/badge/MySQL-4479A1?style=flat-square&logo=MySQL&logoColor=white"> <img src="https://img.shields.io/badge/AmazonEC2-FF9900?style=flat-square&logo=AmazonEC2&logoColor=white"> <img src="https://img.shields.io/badge/AmazonRDS-527FFF?style=flat-square&logo=AmazonRDS&logoColor=white"> <img src="https://img.shields.io/badge/AmazonS3-569A31?style=flat-square&logo=AmazonS3&logoColor=white"> <img src="https://img.shields.io/badge/Redis-DC382D?style=flat-square&logo=Redis&logoColor=white">

### CI/CD
### CI/CD

<img src="https://img.shields.io/badge/GithubActions-2088FF?style=flat-square&logo=GithubActions&logoColor=white"> <img src="https://img.shields.io/badge/AmazonElasticBeanstalk-yellow?style=flat-square&logo=AmazonAWS&logoColor=white" alt="Amazon Elastic Beanstalk Status" />

<br/>
Expand All @@ -75,18 +90,18 @@ https://github.com/CSID-DGU/2023-S-VSA-DingDong-5/assets/96400257/600cb770-32b7-
│   ├── easteregg/ ▶️ 이스터에그 폴더
│   ├── icons/ ▶️ 아이콘 폴더
│   ├── imgs/ ▶️ 이미지 폴더
│   └── fonts/ 폰트 폴더
│   └── fonts/ 폰트 폴더
├── app/ ▶️ 앱 라우팅 폴더
│   ├── (auth)/ ▶️ 인증 인가 폴더
│   ├── actions/ ▶️ auth.js 함수 호출 폴더
│   ├── (auth)/ ▶️ 인증 인가 폴더
│   ├── actions/ ▶️ auth.js 함수 호출 폴더
│   ├── api/auth/[...nextauth]/ ▶️ auth.js 설정 폴더
│   ├── mypage/ ▶️ 마이페이지 폴더
│   ├── ranking/ ▶️ 순위조회 폴더
│   ├── record/ ▶️ 기록확인 폴더
│   ├── study/ ▶️ 공부시작 폴더
│   ├── page.tsx ▶️ root 경로 페이지
│   └── layout.tsx ▶️ root 경로 레이아웃 구조
├── components/ ▶️ 컴포넌트 폴더
│   ├── page.tsx ▶️ root 경로 페이지
│   └── layout.tsx ▶️ root 경로 레이아웃 구조
├── components/ ▶️ 컴포넌트 폴더
│   ├── common/ ▶️ 공통 컴포넌트 폴더
│   │   ├── Header/
│   │   │   ├── Header컴포넌트.tsx
Expand All @@ -97,15 +112,15 @@ https://github.com/CSID-DGU/2023-S-VSA-DingDong-5/assets/96400257/600cb770-32b7-
│   │   ├── 컴포넌트.tsx
│   │   └── 컴포넌트.module.css
│   ├── 라우팅폴더명/컴포넌트.tsx
│   └── 라우팅폴더명/컴포넌트.module.css
│   └── 라우팅폴더명/컴포넌트.module.css
├── constants/
│   └── 상수명.ts
├── hooks/
│   └── 커스텀훅.ts
├── apis/
│   ├── instancs.ts ▶️ api 요청 기본 설정 파일
│   └── 도메인Api.ts
├── stores/ ▶️ Zustand Store 폴더
├── stores/ ▶️ Zustand Store 폴더
│   └── 도메인Store.ts
├── types/ ▶️ TypeScript Interface 설정 폴더
│   └── 도메인Type.ts
Expand All @@ -122,36 +137,40 @@ https://github.com/CSID-DGU/2023-S-VSA-DingDong-5/assets/96400257/600cb770-32b7-
<br/>

## 💙 Lighthouse 성능 지표 💙

### 개선 전
- 문제점: <img> 태그에서 alt 누락
<img width=800px src="https://github.com/woorifisa-service-dev-3rd/frontend-1st-woohaengshi/assets/23547185/890129f5-fdc6-4a64-96f4-93e88309acab">
<img width=800px src="https://github.com/woorifisa-service-dev-3rd/frontend-1st-woohaengshi/assets/23547185/d1c42379-833a-44ca-8443-9a789a118494">

- 문제점: <img> 태그에서 alt 누락
<img width=800px src="https://github.com/woorifisa-service-dev-3rd/frontend-1st-woohaengshi/assets/23547185/890129f5-fdc6-4a64-96f4-93e88309acab">
<img width=800px src="https://github.com/woorifisa-service-dev-3rd/frontend-1st-woohaengshi/assets/23547185/d1c42379-833a-44ca-8443-9a789a118494">

### 개선 후

<img width=800px src="https://github.com/woorifisa-service-dev-3rd/frontend-1st-woohaengshi/assets/23547185/84455224-1711-40f6-8679-8e54cca17043">

## 💙 Commit 방법 💙

## 💙 Commit 방법 💙
꼭 다음의 방법을 따라서 커밋할 필요는 없지만, 알아보기 쉽게하기 위함.
\
커밋의 제목은 타입을 기재 후 간단한 요약(명령조)을 기재 함.
\
본문 작성시 자세한 내용을 누구든 알아볼 수 있기 기재 함(어떻게 보다 **왜**에 초점을 맞춰 작성).
\
**타입은 다음과 같음.**
* feat : 새로운 기능 추가
* fix : 버그 수정
* docs : 문서 수정
* style : 코드 formatting, 세미콜론(;) 누락, 코드 변경이 없는 경우
* refactor : 코드 리팩터링
* test : 테스트 코드, 리팩터링 테스트 코드 추가(프로덕션 코드 변경 X)
* chore : 빌드 업무 수정, 패키지 매니저 수정(프로덕션 코드 변경 X)
* design : CSS 등 사용자 UI 디자인 변경
* comment : 필요한 주석 추가 및 변경
* rename : 파일 혹은 폴더명을 수정하거나 옮기는 작업만인 경우
* remove : 파일을 삭제하는 작업만 수행한 경우
* !BREAKING CHANGE : 커다란 API 변경의 경우
* !HOTFIX : 급하게 치명적인 버그를 고쳐야 하는 경우

- feat : 새로운 기능 추가
- fix : 버그 수정
- docs : 문서 수정
- style : 코드 formatting, 세미콜론(;) 누락, 코드 변경이 없는 경우
- refactor : 코드 리팩터링
- test : 테스트 코드, 리팩터링 테스트 코드 추가(프로덕션 코드 변경 X)
- chore : 빌드 업무 수정, 패키지 매니저 수정(프로덕션 코드 변경 X)
- design : CSS 등 사용자 UI 디자인 변경
- comment : 필요한 주석 추가 및 변경
- rename : 파일 혹은 폴더명을 수정하거나 옮기는 작업만인 경우
- remove : 파일을 삭제하는 작업만 수행한 경우
- !BREAKING CHANGE : 커다란 API 변경의 경우
- !HOTFIX : 급하게 치명적인 버그를 고쳐야 하는 경우

예시
`[feat/#이슈번호]: 타워 추가`
19 changes: 18 additions & 1 deletion apis/authApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { BASE_URL } from '@/constants/url';
import { instance } from './instance';

// 로그인
export const signIn = async ({ email, password }: { email: string; password: string }) => {
const response = await instance('sign-in', {
body: JSON.stringify({ email, password }),
Expand Down Expand Up @@ -43,24 +44,28 @@ export const reissueToken = async (refresh_token: string) => {
return { accessToken, refreshToken };
};

// 회원가입
export const signUp = async ({
name,
email,
password,
image,
course,
}: {
name: string;
email: string;
password: string;
image: string;
course: string;
}) => {
const response = await instance('sign-up', {
body: JSON.stringify({ name, email, password, course }),
body: JSON.stringify({ name, email, password, image, course }),
method: 'POST',
});
return response;
};

//로그아웃
export const signOut = async () => {
const response = await instance('sign-out', {
method: 'POST',
Expand All @@ -69,3 +74,15 @@ export const signOut = async () => {

return response;
};

//프로필 이미지 업데이트
export const patchPrpfileImg = async (formData: FormData) => {
console.log(typeof formData);

const response = await instance('members/image', {
body: formData,
method: 'PATCH',
});

return response;
};
14 changes: 11 additions & 3 deletions apis/instance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,26 @@ import { redirect } from 'next/dist/server/api-utils';

interface RequestOptions {
headers?: Record<string, string>;
[key: string]: string | Record<string, string> | undefined;
isMultipart?: boolean; // 멀티파트 여부를 나타내는 속성 추가
body?: any; // 요청 본문에 대한 타입 정의
[key: string]: any; // 다른 속성 허용
}

const fetchInstance = async (url: string, options: RequestOptions = {}) => {
const session = await auth();
const accessToken = session?.user?.accessToken;

const headers: RequestOptions['headers'] = {
'Content-Type': 'application/json',
...options.headers,
};

// FormData인 경우 Content-Type 설정 제거
if (options.body instanceof FormData) {
delete headers['Content-Type'];
} else {
headers['Content-Type'] = 'application/json';
}

if (accessToken) {
headers.Authorization = `Bearer ${accessToken}`;
}
Expand All @@ -35,7 +43,7 @@ const fetchInstance = async (url: string, options: RequestOptions = {}) => {
console.error('Token Expired');
}
console.error('Fetch Error:', errorResponse);
return { error: errorResponse };
return response;
}

if (response.headers.get('Content-Type')?.includes('application/json')) {
Expand Down
2 changes: 1 addition & 1 deletion apis/rankingApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { instance } from './instance';
import { ApiResponse } from '../types/rankingType';
import rankingImg from '../assets/icons/ranking_profile_img.png';
import rankingImg from '@/public/imgs/ranking/ranking_profile_img.png';

//랭킹 조회 api
export const getMemberRanking = async ({
Expand Down
4 changes: 2 additions & 2 deletions app/(auth)/join/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import { useJoinStore } from '@/stores/authStore';
import { useRouter } from 'next/navigation';

export default function Join() {
const { email, name, password, course, setAllEmpty } = useJoinStore();
const { email, name, password, image, course, setAllEmpty } = useJoinStore();
const route = useRouter();

const handleJoin = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const response = await signUp({ email, name, password, course });
const response = await signUp({ email, name, password, image, course });

// response가 error 속성을 가지고 있다면 에러 처리
if (response.error) {
Expand Down
39 changes: 22 additions & 17 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
import { Box, Flex, Text } from '@radix-ui/themes';
import { Box } from '@radix-ui/themes';
import Image from 'next/image';
import Landing from '@/components/landing/Landing';

export default function Page() {
const rand = Math.floor(Math.random() * 3);
// const rand = Math.floor(Math.random() * 3);
return (
<Box p="6">
<Flex justify="center" align="center" direction="column">
<div
style={{
backgroundImage: `url(/easteregg/${rand}.jpg)`,
backgroundPosition: '50% 50%',
backgroundSize: 'cover',
}}
>
<Image src={`/easteregg/bg.jpg`} alt="이스터에그" width={445} height={500} style={{ visibility: 'hidden' }} />
</div>
<Text as="p" mt="2">
업데이트 예정입니다 ^^
</Text>
</Flex>
<Box>
<Landing />
</Box>

// <Box p="6">
// <Flex justify="center" align="center" direction="column">
// <div
// style={{
// backgroundImage: `url(/easteregg/${rand}.jpg)`,
// backgroundPosition: '50% 50%',
// backgroundSize: 'cover',
// }}
// >
// <Image src={`/easteregg/bg.jpg`} alt="이스터에그" width={445} height={500} style={{ visibility: 'hidden' }} />
// </div>
// <Text as="p" mt="2">
// 업데이트 예정입니다 ^^
// </Text>
// </Flex>
// </Box>
);
}
2 changes: 1 addition & 1 deletion app/ranking/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import TopRankings from '@/components/ranking/topRanking';
import FullRankingList from '@/components/ranking/fullRankingList';
import { Box, Flex } from '@radix-ui/themes';
import styles from './page.module.css';
import rankingImg from '@/assets/icons/ranking_profile_img.png';
import rankingImg from '@/public/imgs/ranking/ranking_profile_img.png';
import { getMemberRanking } from '@/apis/rankingApi';
import { Student, ApiResponse } from '@/types/rankingType';

Expand Down
Binary file removed assets/icons/ranking_1.png
Binary file not shown.
Binary file removed assets/icons/ranking_2.png
Binary file not shown.
Binary file removed assets/icons/ranking_3.png
Binary file not shown.
Binary file removed assets/icons/subject_edit_close_btn.png
Binary file not shown.
Loading