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

부산대_FE_이민경_2주차 과제 Step2 #48

Open
wants to merge 49 commits into
base: mingkyeongg
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a7da156
docs: add a list of feature
mingkyeongg Jul 2, 2024
0f966b8
chore: set react router dom
mingkyeongg Jul 2, 2024
36069cd
feat: create router components
mingkyeongg Jul 2, 2024
08af419
fix: resolve ESLint errors
mingkyeongg Jul 2, 2024
d43ad6a
feat: add header
mingkyeongg Jul 2, 2024
f94ddda
design: add header style
mingkyeongg Jul 2, 2024
6c0ffea
feat: add footer
mingkyeongg Jul 2, 2024
04db1dc
docs: check create header and footer
mingkyeongg Jul 2, 2024
598be91
feat: add category section at main page
mingkyeongg Jul 3, 2024
acc2b68
feat: add friend select section
mingkyeongg Jul 3, 2024
ea3d9ce
design: fixed Link style
mingkyeongg Jul 3, 2024
377de07
design: fixed Link style at Header
mingkyeongg Jul 3, 2024
7d1a89c
docs: check navigation to Theme page
mingkyeongg Jul 3, 2024
217e164
design: add footer style
mingkyeongg Jul 3, 2024
50d9dc4
feat: add recommendation button at main page
mingkyeongg Jul 3, 2024
29988de
refactor: Restructure project folders and organize components
mingkyeongg Jul 3, 2024
b9d5a21
feat: create ranking header and filter button
mingkyeongg Jul 4, 2024
b0dd818
design: add css at filter button
mingkyeongg Jul 4, 2024
89c05de
feat: create filtertabs
mingkyeongg Jul 4, 2024
045c6f2
design: add css at FilterTabs
mingkyeongg Jul 4, 2024
068824e
design: fix mainpage margin
mingkyeongg Jul 4, 2024
d8661c6
fix: Ensure only one filter button can be active at a time
mingkyeongg Jul 4, 2024
af9f3fc
feat: create item ranking
mingkyeongg Jul 4, 2024
0373f90
fix: remove temporary data
mingkyeongg Jul 4, 2024
45548a1
feat: Add filtering functionality to RankingItems component
mingkyeongg Jul 4, 2024
89bd545
design: adjust margin
mingkyeongg Jul 4, 2024
d5cb1c1
feat: create detail button
mingkyeongg Jul 4, 2024
790e8fc
feat: Implement 더보기 and 접기 button functionality for ranking items
mingkyeongg Jul 4, 2024
8709dda
docs: check completed to-do
mingkyeongg Jul 4, 2024
c21b97f
feat: add theme key
mingkyeongg Jul 4, 2024
8d781c7
disign: add ThemeHeader style
mingkyeongg Jul 4, 2024
39ac728
feat: create theme good list
mingkyeongg Jul 4, 2024
de489e4
feat: add login page
mingkyeongg Jul 4, 2024
1a2349d
feat: add login functionality
mingkyeongg Jul 5, 2024
2207db5
feat: change header navigator name
mingkyeongg Jul 5, 2024
d4e2a0e
docs: check login functionality
mingkyeongg Jul 5, 2024
d49c9f6
feat: create my-account page
mingkyeongg Jul 5, 2024
e8aaa8b
feat: set user name at account page
mingkyeongg Jul 5, 2024
322def2
feat: addlogout functionality
mingkyeongg Jul 5, 2024
9dff204
docs: check complete funtionality
mingkyeongg Jul 5, 2024
eb49f2a
refactor: Separate components
mingkyeongg Jul 5, 2024
f690c83
refactor: Separate components
mingkyeongg Jul 5, 2024
cb15690
docs: fix README.md
mingkyeongg Jul 5, 2024
eb2cade
docs: add step2 list
mingkyeongg Jul 5, 2024
2716148
feat: create private route
mingkyeongg Jul 5, 2024
79e623e
feat: save the ID to the authToken key in session storage at login
mingkyeongg Jul 5, 2024
d10f707
feat: add contextAPI
mingkyeongg Jul 5, 2024
4bc9aa7
feat: manage login status with context API
mingkyeongg Jul 5, 2024
f8ca635
docs: check complete funtionality
mingkyeongg Jul 5, 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
110 changes: 110 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,113 @@
## Week 2. 1단계 - 페이지 만들기

[🔗 link](https://edu.nextstep.camp/s/hazAC9xa/ls/QzV1ncxk)

---

# 구현 목록

## 1단계

- [x] react router dom 세팅

- 공통 컴포넌트 만들기
- [x] Header
- [x] Footer

- 페이지 만들기
- 메인 페이지 (/)
- [x] Theme 카테고리 섹션 추가
- [x] Theme 페이지 이동
- [x] 실시간 급상승 선물랭킹
- [x] 필터 기능을 hooks를 사용하여 구현 (ex. 전체, 여성이, 남성이, 청소년이 / 받고 싶어한, 많이 선물한, 위시로 받은)
- [x] 상품 목록 접기
- [x] 상품 목록 펼치기
- Theme 페이지(/theme :themeKey)
- [x] Header 섹션 추가
- [x] 재사용성을 고려하여 Header 섹션 만들기 (themeKey에 따라 label, title, description, backgroundColor가 달라짐)
- [x] 상품 목록 섹션을 추가.
- 로그인 페이지(/login)
- [x] 로그인 기능 추가 (ID와 PW는 아무 값을 입력해도 통과되도록)
- 나의 페이지(/my-account)
- [x] 로그아웃 버튼 추가
- [x] 로그아웃 기능 추가


## 2단계

- [ ] 로그인 페이지에서 ID와 PW를 입력하면 직전 페이지로 Redirect 되도록 해요.
- [x] Fake 로그인 기능을 구현해요.
- [x] 로그인 페이지에서 ID와 PW를 입력하면 ID를 sessionStorage의 authToken key에 저장해요.
- [x] 모든 페이지 진입 시 authToken을 토대로 로그인 여부를 판단하는 로직을 추가해요. (ContextAPI 활용)
- [x] Header에서 로그인 한 경우 내 계정을 로그인 하지 않은 경우 로그인 버튼을 추가해요.
- [x] 내 계정(/my-account) 페이지는 로그인 한 사람만 접근 가능하게 해요. (로그인 하지 않은 유저는 로그인 페이지로 연결해요)
- [x] 내 계정 페이지에서 로그아웃을 할 수 있도록 해요. (로그아웃 후 메인 페이지(/) 로 Redirect 되도록 해요)



---



# 폴더 구조

```text
src
├── components
│ ├── common
│ │ ├── Button
│ │ │ ├── index.stories.tsx
│ │ │ ├── index.tsx
│ │ ├── FilterButton
│ │ │ ├── FilterButton.tsx
│ │ ├── Form
│ │ │ ├── Input
│ │ │ │ ├── UnderlineTextField.stories.tsx
│ │ │ │ ├── UnderlineTextField.tsx
│ │ ├── GoodsItem
│ │ │ ├── Default.stories.tsx
│ │ │ ├── Default.tsx
│ │ │ ├── Ranking.stories.tsx
│ │ │ ├── Ranking.tsx
│ │ ├── Image
│ │ │ ├── index.stories.tsx
│ │ │ ├── index.tsx
│ │ ├── layouts
│ │ │ ├── Container
│ │ │ │ ├── index.stories.tsx
│ │ │ │ ├── index.tsx
│ │ │ ├── Grid
│ │ │ │ ├── index.stories.tsx
│ │ │ │ ├── index.tsx
│ ├── Footer
│ │ ├── Footer.tsx
│ ├── GoodsCategory
│ │ ├── GoodsCategory.tsx
│ ├── Header
│ │ ├── Header.tsx
│ ├── Items
│ │ ├── Items.tsx
│ ├── Ranking
│ │ ├── Detail
│ │ │ ├── DetailButton.tsx
│ │ ├── Filter
│ │ │ ├── Filter.tsx
│ │ │ ├── FilterTab.tsx
│ │ │ ├── FilterTabs.tsx
│ │ ├── RankingItems
│ │ │ ├── RankingItems.tsx
│ │ │ ├── RankingHeader.tsx
│ ├── SelectFriend
│ │ ├── SelectFriend.tsx
│ ├── ThemeGoods
│ │ ├── ThemeGoods.tsx
│ ├── ThemeHeader
│ │ ├── ThemeHeader.tsx
├── pages
│ ├── Home.tsx
│ ├── Login.tsx
│ ├── MyAccount.tsx
├── routes
│ ├── index.tsx

```
41 changes: 40 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-router-dom": "^6.24.0"
},
"devDependencies": {
"react-scripts": "5.0.1",
"typescript": "^4.9.5",
"@craco/craco": "^7.1.0",
"@emotion/eslint-plugin": "^11.11.0",
"@storybook/addon-essentials": "^7.6.17",
Expand Down Expand Up @@ -65,8 +64,10 @@
"eslint-plugin-storybook": "^0.8.0",
"prettier": "^3.2.5",
"prop-types": "^15.8.1",
"react-scripts": "5.0.1",
"storybook": "^7.6.17",
"tsconfig-paths-webpack-plugin": "^4.1.0",
"typescript": "^4.9.5",
"webpack": "^5.90.3"
},
"overrides": {
Expand Down
15 changes: 4 additions & 11 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
import styled from '@emotion/styled';
import Router from './routes';

const App = () => {
const name = 'Josh Perez';

return (
<div>
<Title>Hello, {name}</Title>
</div>
<>
<Router />
</>
);
};

export default App;

const Title = styled.h1`
font-size: 1.5em;
color: gray;
`;
21 changes: 21 additions & 0 deletions src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/** @jsxImportSource @emotion/react */
import styled from '@emotion/styled';
import React from "react";

const FooterContainer = styled.footer`
display: flex;
justify-content: space-between;
width: 100%;
height: 150px;
background-color: #f5f5f5;
`;

const Footer: React.FC = () => {
return (
<FooterContainer>
<p css={{marginTop: '30px', marginLeft:'10px'}}>카카오톡 선물하기</p>
</FooterContainer>
);
}

export default Footer;
52 changes: 52 additions & 0 deletions src/components/GoodsCategory/GoodsCategory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import styled from "@emotion/styled";
import React from "react";

import { Grid } from "@/components/common/layouts/Grid";
import Item from "@/components/Items/items";

interface ItemType {
image: string;
label: string;
themekey: string;
radius?: 'circle' | number;
}

const imageUrls = {
img: 'https://img1.daumcdn.net/thumb/S104x104/?fname=https%3A%2F%2Ft1.daumcdn.net%2Fgift%2Fhome%2Ftheme%2F292020231106_MXMUB.png',
friendImg: 'https://gift-s.kakaocdn.net/dn/gift/images/m640/bg_profile_default.png'
};

const items: ItemType[] = [
{ image: imageUrls.img, label: '생일', themekey: 'birthday' },
{ image: imageUrls.img, label: '졸업선물', themekey: 'graduation'},
{ image: imageUrls.img, label: '명품선물', themekey: 'luxury'},
{ image: imageUrls.img, label: '스몰럭셔리', themekey: 'luxury'},
{ image: imageUrls.img, label: '결혼/집들이', themekey: 'wedding'},
{ image: imageUrls.img, label: '따뜻한선물' , themekey: 'warm'},
{ image: imageUrls.img, label: '가벼운선물' , themekey: 'light'},
{ image: imageUrls.img, label: '팬심저격', themekey: 'fan'},
{ image: imageUrls.img, label: '교환권', themekey: 'exchange'},
{ image: imageUrls.img, label: '건강/비타민', themekey: 'health'},
{ image: imageUrls.img, label: '과일/한우', themekey: 'fruit'},
{ image: imageUrls.img, label: '출산/키즈', themekey: 'kids'},
];

const GridWrapper = styled.div`
width: 95%;
margin: 0 auto;
align-items: center;
`;

const GoodsCatygory: React.FC = () => {
return (
<GridWrapper>
<Grid columns={4} gap={20}>
{items.map((item, index) => (
<Item key={index} image={item.image} label={item.label} radius={item.radius} themekey={item.themekey}/>
))}
</Grid>
</GridWrapper>
);
};

export default GoodsCatygory;
52 changes: 52 additions & 0 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import styled from '@emotion/styled';
import React from 'react';
import { Link } from 'react-router-dom';

const HeaderContainer = styled.header`
display: flex;
justify-content: space-between;
padding: 10px 20px;
background-color: #fff;
border-bottom: 1px solid #ccc;
`;

const Nav = styled.nav`
display: flex;
width: 100%;
justify-content: space-between;
`;

const NavItem = styled.div`
display: flex;
align-items: center;
`;

const StyledLink = styled(Link)`
text-decoration: none;
color: black;
font-weight: bold;
outline: none;
`;

interface HeaderProps {
isLoggedIn: boolean;
}

const Header: React.FC<HeaderProps> = ({isLoggedIn}) => {
return (
<HeaderContainer>
<Nav>
<NavItem>
<StyledLink to="/">선물하기</StyledLink>
</NavItem>
<NavItem>
<StyledLink to={isLoggedIn ? '/my-account' : '/login'}>
{isLoggedIn ? '내 계정' : '로그인'}
</StyledLink>
</NavItem>
</Nav>
</HeaderContainer>
);
};

export default Header;
Loading