Skip to content

Commit

Permalink
Merge pull request #88 from k-impossible/feat/nav
Browse files Browse the repository at this point in the history
[FE] Nav 전역 상태 완료
  • Loading branch information
k-impossible authored Sep 2, 2023
2 parents d78b50d + 3d22608 commit 15f899c
Show file tree
Hide file tree
Showing 19 changed files with 212 additions and 57 deletions.
Binary file added client/public/images/chapter2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 1 addition & 3 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Routes, Route } from 'react-router-dom';
import MainPage from './pages/Main/MainPage';
import { Container } from '@mui/material';
function App() {
export default function App() {
return (
<Container
sx={{
Expand All @@ -17,5 +17,3 @@ function App() {
</Container>
);
}

export default App;
30 changes: 30 additions & 0 deletions client/src/common/data/chapterData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Chapter, UserChapter } from '../../interfaces/Chapter.interface';

export const chapterData: Array<Chapter> = [
{
title: '인사 나누기',
chapterId: 1,
chapterWords: [1, 2, 3]
},
{
title: '활동에 대해 말하기',
chapterId: 2,
chapterWords: [4, 5, 6]
}
];

export const userChapterData: UserChapter = {
chapterList: [
{
chapterId: 1,
chapterStatus: true,
progress: [1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1]
},
{
chapterId: 2,
chapterStatus: false,
progress: [1, 1, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0]
}
],
learningChapterId: 2
};
Empty file removed client/src/common/data/index.ts
Empty file.
Empty file.
17 changes: 10 additions & 7 deletions client/src/components/Enter/Enter.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { Box, Button, Container, Typography } from '@mui/material';
import GuideBook from '../GuideBook/GuideBook';
import { useAppSelector } from '../../redux/hooks';

function Enter() {
const imgSrc = `images/chapter${1}.png`;
export default function Enter() {
const chapter = useAppSelector((state) => state.chapter);
const imgSrc = `images/chapter${chapter.chapterId}.png`;

console.log(chapter);
return (
<Container
sx={{
Expand All @@ -18,10 +22,10 @@ function Enter() {
marginBottom={1}
fontWeight={600}
>
Chapter 1
Chapter {chapter.chapterId}
</Typography>
<Typography paragraph align="center" color="text.secondary">
인사나누기
{chapter.title}
</Typography>
<Box
sx={{
Expand All @@ -42,14 +46,13 @@ function Enter() {
size="large"
color="primary"
sx={{ marginTop: 10 }}
disabled={chapter.chapterStatus}
>
학습하기
{chapter.chapterStatus ? '학습완료' : '학습하기'}
</Button>
</Box>
</Box>
<GuideBook />
</Container>
);
}

export default Enter;
7 changes: 7 additions & 0 deletions client/src/components/GuideBook/GuideBook.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { Box, Typography } from '@mui/material';
import { grey } from '@mui/material/colors';
import { useAppSelector } from '../../redux/hooks';

export default function GuideBook() {
const chapter = useAppSelector((state) => state.chapter);
return (
<Box sx={{ width: '100%', background: grey[200] }}>
<Typography variant="h4" fontWeight={600}>
Guide Book 자리
<div>
{chapter.chapterWords.map((el) => (
<p key={el}>단어 ID : {el}</p>
))}
</div>
</Typography>
</Box>
);
Expand Down
Empty file.
42 changes: 20 additions & 22 deletions client/src/components/Nav/Nav.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
import { Box, List, ListItemButton, ListItemText, Avatar } from '@mui/material';
import DoneIcon from '@mui/icons-material/Done';
import { grey } from '@mui/material/colors';
import { Box, List } from '@mui/material';
import { Chapter } from '../../interfaces/Chapter.interface';
import NavItem from './NavItem';

interface NavProps {
chapterList?: Array<Chapter>;
location: string;
}

export default function Nav(props: NavProps) {
const chapterList = props.chapterList;
const location = props.location;

function Nav() {
return (
<Box
sx={{
width: '100%',
maxWidth: 300,
height: '100vh',
borderRight: 1,
borderColor: grey[300]
overflowY: 'scroll',
padding: 0
}}
>
<List>
<ListItemButton sx={{ borderBottom: 1, borderColor: grey[200] }}>
<ListItemText
primary="Chapter 1"
primaryTypographyProps={{ style: { overflowWrap: 'break-word' } }}
secondary="인사 나누기"
/>
<Avatar sx={{ bgcolor: 'success.light' }}>
<DoneIcon />
</Avatar>
</ListItemButton>
<ListItemButton sx={{ borderBottom: 1, borderColor: grey[200] }}>
<ListItemText primary="Chapter 2" secondary="활동에 대해 말하기" />
</ListItemButton>
<List sx={{ padding: 0 }}>
{location === '/'
? chapterList?.map((el) => (
<NavItem key={el.chapterId} chapter={el} />
))
: null}
</List>
</Box>
);
}

export default Nav;
47 changes: 47 additions & 0 deletions client/src/components/Nav/NavItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Chapter } from '../../interfaces/Chapter.interface';
import DoneIcon from '@mui/icons-material/Done';
import { grey } from '@mui/material/colors';
import { ListItemButton, ListItemText, Avatar } from '@mui/material';
import React from 'react';
import { useAppSelector, useAppDispatch } from '../../redux/hooks';
import { setChapter } from '../../redux/slices/chapter';

interface NavItemProps {
chapter?: Chapter;
}

export default function NavItem(props: NavItemProps) {
const chapter = props.chapter;
const chapterBigTitle = `Chapter ${chapter ? chapter.chapterId : 0}`;
const selectedChapter = useAppSelector((state) => state.chapter);
const dispatch = useAppDispatch();

const handleSelectChapter = () => {
dispatch(setChapter(chapter!));
};
return (
<React.Fragment>
{chapter ? (
<ListItemButton
onClick={handleSelectChapter}
sx={{
borderBottom: 1,
borderBottomColor: grey[200],
borderLeft: 8,
borderLeftColor:
chapter.chapterId === selectedChapter.chapterId
? 'primary.main'
: '#1976d200'
}}
>
<ListItemText primary={chapterBigTitle} secondary={chapter.title} />
{chapter.chapterStatus ? (
<Avatar sx={{ bgcolor: 'success.main' }}>
<DoneIcon />
</Avatar>
) : null}
</ListItemButton>
) : null}
</React.Fragment>
);
}
19 changes: 19 additions & 0 deletions client/src/interfaces/Chapter.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface Chapter {
chapterId: number;
title: string;
chapterWords: Array<number>;
chapterStatus?: boolean;
learningChapterId?: number;
progress?: number[];
}

export interface UserChapterListItem {
chapterId: number;
chapterStatus: boolean;
progress: number[];
}

export interface UserChapter {
chapterList: Array<UserChapterListItem>;
learningChapterId: number;
}
Empty file.
50 changes: 45 additions & 5 deletions client/src/pages/Main/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,53 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import Enter from '../../components/Enter/Enter';
import Nav from '../../components/Nav/Nav';
function MainPage() {
import { chapterData, userChapterData } from '../../common/data/chapterData';
import { Chapter, UserChapter } from '../../interfaces/Chapter.interface';
import { useLocation } from 'react-router-dom';
import { useAppDispatch } from '../../redux/hooks';
import { setChapter } from '../../redux/slices/chapter';
export default function MainPage() {
const [chapterList, setChapterList] = useState<Chapter[]>([]);
// const [userChapter, setUserChapter] = useState<UserChapter>();
const location = useLocation().pathname;
const dispatch = useAppDispatch();

useEffect(() => {
// 회원정보가 있는 유저일 경우
// 챕터 완료 상태 변경
const changeStatusList = chapterData.map((chapter) => {
const sameChapter = userChapterData?.chapterList.find(
(userChapter) => userChapter.chapterId === chapter.chapterId
);

if (sameChapter?.chapterStatus) {
return {
...chapter,
chapterStatus: true,
learningChapterId: userChapterData.learningChapterId,
progress: sameChapter?.progress
};
} else {
return {
...chapter,
chapterStatus: false,
learningChapterId: userChapterData.learningChapterId,
progress: sameChapter?.progress
};
}
});
setChapterList(changeStatusList);
dispatch(setChapter(changeStatusList[0]));
// setUserChapter(userChapterData);

// TODO: 회원정보가 없는 유저일 경우
// localStorage Get Set
}, []);

return (
<React.Fragment>
<Nav />
<Nav chapterList={chapterList} location={location} />
<Enter />
</React.Fragment>
);
}

export default MainPage;
Empty file.
2 changes: 1 addition & 1 deletion client/src/redux/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ import type { RootState, AppDispatch } from './store';

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
29 changes: 29 additions & 0 deletions client/src/redux/slices/chapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { createSlice } from '@reduxjs/toolkit';
import { RootState } from '../store';
import { Chapter } from '../../interfaces/Chapter.interface';

const initialState: Chapter = {
title: '인사 나누기',
chapterId: 1,
chapterWords: [1, 2, 3],
chapterStatus: false,
learningChapterId: 1,
progress: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
};

export const chapterSlice = createSlice({
name: 'chapter',
initialState,
reducers: {
setChapter: (state, action: { payload: Chapter }) => {
state = action.payload;
return state;
}
}
});

export const { setChapter } = chapterSlice.actions;

export const selectChapter = (state: RootState) => state.chapter;

export default chapterSlice.reducer;
4 changes: 3 additions & 1 deletion client/src/redux/store.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
import userReducer from './slices/user';
import chapterReducer from './slices/chapter';

export const store = configureStore({
reducer: {
user: userReducer
user: userReducer,
chapter: chapterReducer
}
});

Expand Down
Empty file removed client/src/style/App.styled.js
Empty file.
18 changes: 0 additions & 18 deletions client/src/style/Global.styled.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,6 @@
import { createGlobalStyle } from 'styled-components';

export const GlobalStyle = createGlobalStyle`
:root {
--main-width: 1264px;
--main-height: calc(100vh - 382px);
--orange : #EA862B;
--blue : #0A95FF;
--blue-hover : #0074CC;
--sky-blue : #E1ECF4;
--white: #ffffff;
--white-10 : #f1f2f3;
--black: #000000;
--black-10: #0000001a;
--black-50: #0000005a;
--gray: #888888;
--gray-10 : #D9D9D9;
--gray-20 : #525960;
}
* {
box-sizing: border-box;
padding: 0;
Expand All @@ -31,7 +14,6 @@ export const GlobalStyle = createGlobalStyle`
min-height : 100vh;
width: 100vw;
overflow-x: hidden;
/* overflow-y: scroll; */
}
ol, ul {
Expand Down

0 comments on commit 15f899c

Please sign in to comment.