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] 챕터 진행상황, 문제 조회 api 연결 작업 #136

Merged
merged 22 commits into from
Sep 16, 2023
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fbbe01f
Merge pull request #2 from k-impossible/feat/learn
k-impossible Sep 10, 2023
7d02ae6
Merge pull request #3 from k-impossible/feat/questions
k-impossible Sep 11, 2023
1ce9411
[test] env api url test
k-impossible Sep 11, 2023
73e5b22
[fix] Main - get chapterList api 수정
k-impossible Sep 12, 2023
8fb0399
[merge] front merge
k-impossible Sep 12, 2023
4c34b43
[feat] Question 작업중
k-impossible Sep 12, 2023
1ac0853
[feat] Questions 작업중
k-impossible Sep 12, 2023
efd994e
[fix] deploy 수정
k-impossible Sep 12, 2023
ca73beb
Merge pull request #4 from k-impossible/feat/questions
k-impossible Sep 12, 2023
fa82eaf
[test] 배포 테스트
k-impossible Sep 12, 2023
ee56ccd
[feat] Main 쿼리 변경, queries 폴더 생성
k-impossible Sep 13, 2023
3db653b
[feat] Questions 작업중
k-impossible Sep 13, 2023
b349cf0
[merge] merge front
k-impossible Sep 13, 2023
1371832
[merge] merge front
k-impossible Sep 13, 2023
8c4ec52
[fix] 배포 테스트
k-impossible Sep 14, 2023
c94f14a
[feat] 유저 챕터목록 조회, 문제조회 api 연결 작업중
k-impossible Sep 15, 2023
36f28f2
Merge branch 'front' into feat/questions
k-impossible Sep 15, 2023
270a833
[feat] Nav 변경중
k-impossible Sep 15, 2023
8049f57
[merge] merge front
k-impossible Sep 15, 2023
885b038
[feat] 유저 챕터 전체 조회 - api, 로컬스토리지 완료
k-impossible Sep 16, 2023
1406077
[fix] mypage 오류 수정
k-impossible Sep 16, 2023
a5a05bf
[feat] questions 작업중
k-impossible Sep 16, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/fe_deploy.yml
Original file line number Diff line number Diff line change
@@ -27,6 +27,6 @@ jobs:
run: |
aws s3 sync \
--region ap-northeast-2 \
build s3://i-learn \
build s3://i-learn.site \
--delete
working-directory: ./client
2 changes: 1 addition & 1 deletion client/public/index.html
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="https://s3.amazonaws.com/i-learn.site/favicon.ico" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
145 changes: 77 additions & 68 deletions client/src/common/data/chapterData.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,79 @@
import { Chapter, UserChapter } from '../../interfaces/Chapter.interface';
// import {
// Chapter,
// UserChapter,
// UserChapterListItem
// } from '../../interfaces/Chapter.interface';

export const chapterData: Array<Chapter> = [
{
title: '인사 나누기',
chapterId: 1,
wordId: [1, 2, 3]
},
{
title: '쇼핑 및 주문하기',
chapterId: 2,
wordId: [4, 5, 6]
},
{
title: '활동에 대해 말하기',
chapterId: 3,
wordId: [71, 28, 66]
},
{
title: '활동에 대해 말하기',
chapterId: 3,
wordId: [71, 28, 66]
},
{
title: '활동에 대해 말하기',
chapterId: 5,
wordId: [71, 28, 66]
},
{
title: '활동에 대해 말하기',
chapterId: 3,
wordId: [71, 28, 66]
},
{
title: '활동에 대해 말하기',
chapterId: 7,
wordId: [71, 28, 66]
},
{
title: '활동에 대해 말하기',
chapterId: 3,
wordId: [71, 28, 66]
},
{
title: '활동에 대해 말하기',
chapterId: 3,
wordId: [71, 28, 66]
}
];
// export const chapterData: Array<Chapter> = [
// {
// title: '인사 나누기',
// chapterId: 1,
// wordId: [1, 2, 3]
// },
// {
// title: '쇼핑 및 주문하기',
// chapterId: 2,
// wordId: [4, 5, 6]
// },
// {
// title: '활동에 대해 말하기',
// chapterId: 3,
// wordId: [71, 28, 66]
// },
// {
// title: '활동에 대해 말하기',
// chapterId: 3,
// wordId: [71, 28, 66]
// },
// {
// title: '활동에 대해 말하기',
// chapterId: 5,
// wordId: [71, 28, 66]
// },
// {
// title: '활동에 대해 말하기',
// chapterId: 3,
// wordId: [71, 28, 66]
// },
// {
// title: '활동에 대해 말하기',
// chapterId: 7,
// wordId: [71, 28, 66]
// },
// {
// title: '활동에 대해 말하기',
// chapterId: 3,
// wordId: [71, 28, 66]
// },
// {
// title: '활동에 대해 말하기',
// chapterId: 3,
// wordId: [71, 28, 66]
// }
// ];

export const userChapterAllData: 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]
},
{
chapterId: 3,
chapterStatus: false,
progress: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
],
learningChapterId: 3
};
// export const userChapterAllData: 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]
// },
// {
// chapterId: 3,
// chapterStatus: false,
// progress: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
// }
// ]
// };

// export const userChapterData: UserChapterListItem = {
// chapterId: 1,
// chapterStatus: false,
// progress: [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
// };
4 changes: 2 additions & 2 deletions client/src/common/data/learningData.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { LearningInterface } from '../../interfaces/Learning.interface';
export const correct: LearningInterface = {
import { Learning } from '../../interfaces/Learning.interface';
export const learningData: Learning = {
questionNum: 1,
questionType: 1, // or 2
question: '안녕',
32 changes: 32 additions & 0 deletions client/src/common/utils/localStorageFuncs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ChapterList, UserChapter } from '../../interfaces/Chapter.interface';

export function localStorageInit(allChapterList: ChapterList) {
if (localStorageIsNull()) {
const localUserChapter: UserChapter = {
data: []
};
const initList = allChapterList.data.map((el, idx) => {
return {
chapterId: idx + 1,
chapterStatus: false,
progress: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] as (0 | 1 | 2)[]
};
});
localUserChapter.data = initList;

localStorageSet(localUserChapter);
}
}

export function localStorageIsNull() {
return localStorage.getItem('userChapter') == null;
}

export function localStorageGet(): UserChapter {
const localUserChapter = localStorage.getItem('userChapter');
return JSON.parse(localUserChapter!);
}

export function localStorageSet(userChapter: UserChapter) {
localStorage.setItem('userChapter', JSON.stringify(userChapter));
}
4 changes: 2 additions & 2 deletions client/src/common/utils/pointCalculator.ts
Original file line number Diff line number Diff line change
@@ -3,8 +3,8 @@ export function pointAcc(progress: (0 | 1 | 2)[]) {
if (cur === 0 || cur === 2) return acc;

if (cur === 1)
if (i === 9 || i === 10 || i === 11) return acc + 3;
else if (i === 2 || i === 5 || i === 8) return acc + 2;
if (i === 3 || i === 7 || i === 11) return acc + 3;
else if (i === 2 || i === 6 || i === 10) return acc + 2;
else return acc + 1;

return acc;
1 change: 0 additions & 1 deletion client/src/common/utils/speak.ts
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@ synth.onvoiceschanged = () => {
const desiredVoice = synth
.getVoices()
.find((voice) => voice.name === desiredVoiceName);
console.log('loaded');
if (desiredVoice) {
utterance.voice = desiredVoice;
}
37 changes: 19 additions & 18 deletions client/src/components/Enter/Enter.tsx
Original file line number Diff line number Diff line change
@@ -3,28 +3,29 @@ import GuideBook from '../GuideBook/GuideBook';
import { useAppSelector } from '../../redux/hooks';
import { Link } from 'react-router-dom';
import { grey } from '@mui/material/colors';
import Progress from './MainProgress';
import MainProgress from '../Progress/MainProgress';
import CheckOutlinedIcon from '@mui/icons-material/CheckOutlined';
import EastOutlinedIcon from '@mui/icons-material/EastOutlined';
import { pointAcc } from '../../common/utils/pointCalculator';
export default function Enter() {
const chapter = useAppSelector((state) => state.chapter);

function pointAcc() {
let point = 0;
// function pointAcc() {
// let point = 0;

for (let i = 0; i < chapter.progress!.length; i++) {
if (chapter.progress![i] === 1) {
if (i === 9 || i === 10 || i === 11) {
point += 3;
} else if (i === 2 || i === 5 || i === 8) {
point += 2;
} else {
point += 1;
}
}
}
return point;
}
// for (let i = 0; i < chapter.progress!.length; i++) {
// if (chapter.progress![i] === 1) {
// if (i === 9 || i === 10 || i === 11) {
// point += 3;
// } else if (i === 2 || i === 5 || i === 8) {
// point += 2;
// } else {
// point += 1;
// }
// }
// }
// return point;
// }
return (
<Container
sx={{
@@ -141,15 +142,15 @@ export default function Enter() {
}}
>
<Typography variant="h4" color={grey[700]}>
{pointAcc()}
{pointAcc(chapter.progress!)}
</Typography>
<Typography variant="subtitle2" color={grey[700]}>
포인트
</Typography>
</Box>
</Box>

<Progress progress={chapter.progress!} />
<MainProgress progress={chapter.progress!} />
</Box>
</Box>
</Container>
2 changes: 1 addition & 1 deletion client/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -104,7 +104,7 @@ export default function Header(props: HeaderProp) {
</Tooltip>
<Tooltip title="내 정보">
<IconButton
onClick={() => handleNavigate('/my-profile')}
onClick={() => handleNavigate('/my-page')}
sx={{
width: '40px',
height: '40px',
6 changes: 2 additions & 4 deletions client/src/components/Nav/Nav.tsx
Original file line number Diff line number Diff line change
@@ -6,23 +6,21 @@ import MainNavItem from './MainNavItem';
interface NavProps {
chapterList?: Chapter[];
location: string;
memberStatus: boolean;
myWordList?: number[];
myWordList?: number[]; // TODO: Word 인터페이스 추가
}

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

console.log(props);
function handleNavPage() {
if (location === '/') {
return chapterList?.map((el) => (
<MainNavItem key={el.chapterId} chapter={el} />
));
} else if (location === '/my-word') {
// word page
// WordNavItem.tsx 렌더링
return myWordList;
} else {
return null;
3 changes: 3 additions & 0 deletions client/src/components/Nav/WordNavItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
interface WordNavItemProps {}

export default function WordNavItem() {}
Original file line number Diff line number Diff line change
@@ -8,10 +8,10 @@ import TimelineOppositeContent from '@mui/lab/TimelineOppositeContent';
import { Typography } from '@mui/material';
import { grey } from '@mui/material/colors';

interface Progress {
export interface Progress {
progress: number[];
}
export default function Progress({ progress }: Progress) {
export default function MainProgress({ progress }: Progress) {
function itemMapping(el: number, idx: number) {
let status = '';
let point = '';
@@ -22,9 +22,9 @@ export default function Progress({ progress }: Progress) {
if (el === 1) {
status = 'Success';
statusColor = 'success.main';
if (idx === 9 || idx === 10 || idx === 11) {
if (idx === 3 || idx === 7 || idx === 11) {
point = '+ 3';
} else if (idx === 2 || idx === 5 || idx === 8) {
} else if (idx === 2 || idx === 6 || idx === 10) {
point = '+ 2';
} else {
point = '+ 1';
@@ -35,21 +35,21 @@ export default function Progress({ progress }: Progress) {
point = '+ 0';
}

if (idx === 0 || idx === 3 || idx === 6) {
qType = '영단어 선택하기';
} else if (idx === 1 || idx === 4 || idx === 7) {
qType = '의미 선택하기';
} else if (idx === 2 || idx === 5 || idx === 8) {
qType = '소리 듣고 입력하기';
if (idx === 0 || idx === 4 || idx === 8) {
qType = '영단어 고르기';
} else if (idx === 1 || idx === 5 || idx === 9) {
qType = '뜻 고르기';
} else if (idx === 2 || idx === 6 || idx === 10) {
qType = '스펠링 입력하기';
} else {
qType = '문장 채우기';
qType = '빈칸 채우기';
}

if (idx === 0 || idx === 1 || idx === 2 || idx === 9) {
if (idx === 0 || idx === 1 || idx === 2 || idx === 3) {
qTypeNo = 1;
} else if (idx === 3 || idx === 4 || idx === 5 || idx === 10) {
} else if (idx === 4 || idx === 5 || idx === 6 || idx === 7) {
qTypeNo = 2;
} else if (idx === 6 || idx === 7 || idx === 8 || idx === 11) {
} else {
qTypeNo = 3;
}

58 changes: 58 additions & 0 deletions client/src/components/Progress/QuestionProgress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {
Timeline,
TimelineConnector,
TimelineDot,
TimelineItem,
TimelineSeparator
} from '@mui/lab';
import { Progress } from './MainProgress';
import { Typography } from '@mui/material';

export default function QuestionProgress({ progress }: Progress) {
function itemMapping(el: number, idx: number) {
let statusColor = 'default';

if (el === 1) {
statusColor = 'success.main';
} else if (el === 2) {
statusColor = 'error.main';
}

return (
<TimelineItem key={idx}>
<TimelineSeparator>
{idx === 0 ? null : <TimelineConnector />}
<TimelineDot
sx={{
width: '40px',
height: '40px',
justifyContent: 'center',
alignItems: 'center',
boxShadow: 'rgba(0, 0, 0, 0.2) 0px 0px 10px',
backgroundColor: statusColor,
rotate: '90deg'
}}
>
<Typography variant="subtitle2">{idx + 1}</Typography>
</TimelineDot>
{idx === 11 ? null : <TimelineConnector />}
</TimelineSeparator>
</TimelineItem>
);
}
return (
<Timeline
position="right"
sx={{
rotate: '-90deg',
position: 'absolute',
left: '47%',
top: '-350px'
}}
>
{progress.map((el, idx) => {
return itemMapping(el, idx);
})}
</Timeline>
);
}
9 changes: 0 additions & 9 deletions client/src/components/Questions/Progress.tsx

This file was deleted.

1 change: 0 additions & 1 deletion client/src/components/Word/Word.tsx
Original file line number Diff line number Diff line change
@@ -12,7 +12,6 @@ import { AxiosError } from 'axios';
import api from '../../common/utils/api';
import AddWord from './AddWord';
const defaultTheme = createTheme();
console.log(defaultTheme);

export default function Word(props: { wordId: number }) {
const [detailCategory, setDetailCategory] = useState(0);
14 changes: 11 additions & 3 deletions client/src/interfaces/Chapter.interface.ts
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ export interface Chapter {
title: string;
wordId: Array<number>;
chapterStatus?: boolean;
learningChapterId?: number;
progress?: (0 | 1 | 2)[];
}

@@ -14,6 +13,15 @@ export interface UserChapterListItem {
}

export interface UserChapter {
chapterList: Array<UserChapterListItem>;
learningChapterId: number;
data: Array<UserChapterListItem>;
}

export interface ChapterListItem {
title: string;
chapterId: number;
wordId: number[];
}

export interface ChapterList {
data: Array<ChapterListItem>;
}
4 changes: 2 additions & 2 deletions client/src/interfaces/Learning.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export interface LearningInterface {
export interface Learning {
questionNum: number;
questionType: number;
questionType: number; //
question: string; // 뜻 또는 단어
examples: string[]; // 예시 선택지
correct: number; // examples의 정답인 단어의 인덱스
128 changes: 51 additions & 77 deletions client/src/pages/Main/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -1,100 +1,78 @@
import React, { useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import Enter from '../../components/Enter/Enter';
import Nav from '../../components/Nav/Nav';
// import { chapterData, userChapterAllData } from '../../common/data/chapterData';
import { Chapter, UserChapter } from '../../interfaces/Chapter.interface';
import {
Chapter,
ChapterList,
UserChapter
} from '../../interfaces/Chapter.interface';
import { useLocation } from 'react-router-dom';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import { setChapter } from '../../redux/slices/chapter';
import Header from '../../components/Header/Header';
import { Box } from '@mui/material';
import { useQuery } from '@tanstack/react-query';
import api from '../../common/utils/api';
import useAllChapterQuery from '../../queries/useAllChapterQuery';
import useAllUserChapterQuery from '../../queries/useAllUserChapterQuery';
import {
localStorageGet,
localStorageInit
} from '../../common/utils/localStorageFuncs';

export default function MainPage() {
const [chapterList, setChapterList] = useState<Chapter[]>([]);
// const [userChapter, setUserChapter] = useState<UserChapter>();
const location = useLocation().pathname;
const { pathname: location } = useLocation();
const dispatch = useAppDispatch();
const userInfo = useAppSelector((state) => state.user);
const selectedChapter = useAppSelector((state) => state.chapter);

const getChapter = useQuery({
queryKey: ['getChapterList'],
queryFn: () => api('/learning', 'get').then(({ data }) => data.data)
});
const { data: allChapterList } = useAllChapterQuery();
const { data: allUserChapterList } = useAllUserChapterQuery(userInfo.userId);

useEffect(() => {
if (getChapter.isError) {
alert('Error!');
function getUserChapters(): UserChapter {
if (!userInfo.memberStatus) {
localStorageInit(allChapterList as ChapterList);
return localStorageGet();
} else {
return allUserChapterList as UserChapter;
}
}

if (!getChapter.isLoading) {
if (!userInfo.memberStatus && !localStorage.getItem('userChapter')) {
const localUserChapter = {
chapterList: [{}],
learningChapterId: 1
};
function setUserChapters(): void {
const userChapter = getUserChapters();

for (let i = 0; i < getChapter.data.length; i++) {
localUserChapter.chapterList[i] = {
chapterId: i + 1,
chapterStatus: false,
progress: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
};
}
localStorage.setItem('userChapter', JSON.stringify(localUserChapter));
}
const changeStatusList = allChapterList!.data.map((chapter) => {
const sameChapter = userChapter?.data.find(
(userChapter) => userChapter.chapterId === chapter.chapterId
);

let userChapter: UserChapter = {
chapterList: [
{
chapterId: 1,
chapterStatus: false,
progress: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
],
learningChapterId: 1
};
const chapterData: Chapter[] = getChapter.data;

if (userInfo.memberStatus) {
console.log('get 유저 챕터');
if (sameChapter?.chapterStatus) {
return {
...chapter,
chapterStatus: true,
progress: sameChapter?.progress
};
} else {
const localUserChapter = localStorage.getItem('userChapter');
if (localUserChapter !== null) {
const parseUserChapter = JSON.parse(localUserChapter);

userChapter = parseUserChapter;
}
return {
...chapter,
chapterStatus: false,
progress: sameChapter?.progress
};
}
});

const changeStatusList = chapterData.map((chapter) => {
const sameChapter = userChapter?.chapterList.find(
(userChapter) => userChapter.chapterId === chapter.chapterId
);
setChapterList(changeStatusList);

if (sameChapter?.chapterStatus) {
return {
...chapter,
chapterStatus: true,
learningChapterId: userChapter.learningChapterId,
progress: sameChapter?.progress
};
} else {
return {
...chapter,
chapterStatus: false,
learningChapterId: userChapter.learningChapterId,
progress: sameChapter?.progress
};
}
});
console.log(changeStatusList);
setChapterList(changeStatusList);
// 첫 접속시 Enter, Nav 첫 챕터로 세팅
if (selectedChapter.chapterId === 0) {
dispatch(setChapter(changeStatusList[0]));
}
}, [getChapter.isLoading]);
}

useEffect(() => {
if (allChapterList !== undefined) {
setUserChapters();
}
}, [allChapterList]);
return (
<Box
sx={{
@@ -104,11 +82,7 @@ export default function MainPage() {
backgroundColor: '#f5f7fa'
}}
>
<Nav
chapterList={chapterList}
location={location}
memberStatus={userInfo.memberStatus}
/>
<Nav chapterList={chapterList} location={location} />
<Box
sx={{
width: 'calc(100% - 270px)',
133 changes: 76 additions & 57 deletions client/src/pages/MyPage/MyPage.tsx
Original file line number Diff line number Diff line change
@@ -37,66 +37,74 @@ const topMargin = {
};

export default function MyPage() {
const [editFlag, setEditFlag] = useState(false);
const [editedUser, setEditedUser] = useState({
nickname: '',
username: '',
email: ''
});
// const [user, setUser] = useState(false);
// const [editedUser, setEditedUser] = useState({
// nickname: data.nickname,
// username: data.username,
// email: data.email
// });

const userInfo = useAppSelector((state) => state.user);
const { isLoading, error, data } = useQuery({
queryKey: ['username', userInfo.userId],
queryFn: () =>
api(`/members/${userInfo.userId}`, 'get').then(({ data }) => data.data)
});
if (isLoading)
return (
<Box
sx={{
backgroundColor: 'white',
width: '55rem',
height: '40rem',
p: 4,
display: 'flex',
flexDirection: 'column',
gap: 2,
borderRadius: 4,
boxShadow: (theme) => theme.shadows[3]
}}
>
{' '}
로딩중...{' '}
</Box>
);

if (error) {
const myError = error as AxiosError;
return (
<Box
sx={{
backgroundColor: 'white',
width: '55rem',
height: '40rem',
p: 4,
display: 'flex',
flexDirection: 'column',
gap: 2,
borderRadius: 4,
boxShadow: (theme) => theme.shadows[3]
}}
>
{' '}
에러: {myError.message}{' '}
</Box>
);
}
const [user, setUser] = useState(false);
const [editedUser, setEditedUser] = useState({
nickname: data.nickname,
username: data.username,
email: data.email
});
// if (isLoading)
// return (
// <Box
// sx={{
// backgroundColor: 'white',
// width: '55rem',
// height: '40rem',
// p: 4,
// display: 'flex',
// flexDirection: 'column',
// gap: 2,
// borderRadius: 4,
// boxShadow: (theme) => theme.shadows[3]
// }}
// >
// {' '}
// 로딩중...{' '}
// </Box>
// );

// if (error) {
// const myError = error as AxiosError;
// return (
// <Box
// sx={{
// backgroundColor: 'white',
// width: '55rem',
// height: '40rem',
// p: 4,
// display: 'flex',
// flexDirection: 'column',
// gap: 2,
// borderRadius: 4,
// boxShadow: (theme) => theme.shadows[3]
// }}
// >
// {' '}
// 에러: {myError.message}{' '}
// </Box>
// );
// }

const handleEditClick = () => {
setUser(true);
setEditFlag(true);
};

const handleReadClick = () => {
setUser(false);
setEditFlag(false);
};

const handleFieldChange =
@@ -107,13 +115,24 @@ export default function MyPage() {
});
};

useEffect(() => {
if (data !== undefined) {
setEditedUser({
nickname: data.nickname,
username: data.username,
email: data.email
});
}
}, [data]);

return (
<ThemeProvider theme={defaultTheme}>
<div style={centerStyle}>
<Card sx={{ minWidth: 1000 }}>
<CardContent style={{ paddingLeft: '60px', paddingTop: '50px' }}>
<Typography variant="h5" component="div">
{data.username}
{/* {data.username} */}
{editedUser.username}
</Typography>
<Typography variant="body2">2023년 8월 28일 가입</Typography>
</CardContent>
@@ -127,12 +146,12 @@ export default function MyPage() {
닉네임
</Typography>
<TextField
required={user}
required={editFlag}
id="outlined-read-only-input"
value={editedUser.nickname}
onChange={handleFieldChange('nickname')}
InputProps={{
readOnly: !user
readOnly: !editFlag
}}
/>
</div>
@@ -146,12 +165,12 @@ export default function MyPage() {
아이디
</Typography>
<TextField
required={user}
required={editFlag}
id="outlined-read-only-input"
value={editedUser.username}
onChange={handleFieldChange('username')}
InputProps={{
readOnly: !user
readOnly: !editFlag
}}
/>
</div>
@@ -164,12 +183,12 @@ export default function MyPage() {
이메일
</Typography>
<TextField
required={user}
required={editFlag}
id="outlined-read-only-input"
value={editedUser.email}
onChange={handleFieldChange('email')}
InputProps={{
readOnly: !user
readOnly: !editFlag
}}
/>
</div>
@@ -182,7 +201,7 @@ export default function MyPage() {
}}
>
<div style={centerStyle}>
{!user && (
{!editFlag && (
<Button
variant="outlined"
style={{ marginLeft: '8px' }}
@@ -191,7 +210,7 @@ export default function MyPage() {
내 정보 수정
</Button>
)}
{user && (
{editFlag && (
<Button
variant="outlined"
style={{ marginLeft: '8px' }}
84 changes: 76 additions & 8 deletions client/src/pages/Questions/Questions.tsx
Original file line number Diff line number Diff line change
@@ -3,36 +3,104 @@ import { Link, useNavigate } from 'react-router-dom';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';
import QTypeChoice from '../../components/Questions/QTypeChoice';
import QTypeTyping from '../../components/Questions/QTypeTyping';
import Progress from '../../components/Questions/Progress';
import { useEffect, useState } from 'react';

import QuestionProgress from '../../components/Progress/QuestionProgress';
import { grey } from '@mui/material/colors';
import { useAppSelector } from '../../redux/hooks';
import {
UserChapter,
UserChapterListItem
} from '../../interfaces/Chapter.interface';
export default function Questions() {
const navigate = useNavigate();

const handleExit = () => {
const handleLearningExit = () => {
const conf = confirm('학습을 종료하시겠습니까?');
if (conf) {
navigate('/');
}
};

const selectedChapter = useAppSelector((state) => state.chapter);
const userInfo = useAppSelector((state) => state.user);
const [progress, setProgress] = useState<(0 | 1 | 2)[]>([]);

// function getUserChapter(): UserChapterListItem {}
useEffect(() => {
let selectedUserChapter: UserChapterListItem = {
chapterId: 1,
chapterStatus: false,
progress: [0]
};

// 비회원이 문제풀이 할 시
if (!userInfo.memberStatus) {
const localUserChapter = localStorage.getItem('userChapter');
if (localUserChapter !== null) {
const parseUserChapter = JSON.parse(localUserChapter);
// 선택된 챕터정보 로컬스토리지의 챕터리스트에서 가져오기
const localSelectedUserChapter: UserChapterListItem =
parseUserChapter.chapterList.find(
(el: UserChapterListItem) =>
selectedChapter.chapterId === el.chapterId
);
selectedUserChapter = localSelectedUserChapter;
}
} else {
console.log('get 유저 챕터 진행상황 상세');
}
// 챕터에서 풀지 않은 문제 번호
// TODO : 로컬스토리지에서 가져오기, 챕터 진행상황 상세조회 api 연결

const learnQuestionNum = selectedUserChapter.progress.findIndex(
(el) => el === 0
);
setProgress(selectedUserChapter.progress);

// 문제타입 별 렌더링
}, []);
function handleQTypeRender() {}
return (
<Container
sx={{
display: 'flex',
width: '100%',
flexDirection: 'column'
flexDirection: 'column',
height: '100vh'
}}
maxWidth={false}
disableGutters
>
<Box sx={{ width: '100%', textAlign: 'right', padding: '20px' }}>
<IconButton aria-label="delete" size="large" onClick={handleExit}>
<Box
sx={{
width: '100%',
textAlign: 'right',
padding: '20px',
position: 'relative'
}}
>
<QuestionProgress progress={progress} />
<IconButton
aria-label="delete"
size="large"
onClick={handleLearningExit}
>
<CloseRoundedIcon fontSize={'large'} />
</IconButton>
</Box>
<Container>
<Container
sx={{
display: 'flex',
width: '100%',
flexDirection: 'column',
marginTop: '30px',
height: '100vh'
}}
>
<QTypeChoice />
<QTypeTyping />
<Progress />
</Container>
<Box sx={{ width: '100%', padding: '20px' }} bgcolor={grey[300]}></Box>
</Container>
);
}
16 changes: 16 additions & 0 deletions client/src/queries/useAllChapterQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import api from '../common/utils/api';
import { useQuery } from '@tanstack/react-query';
import { ChapterList } from '../interfaces/Chapter.interface';

export const QUERY_KEY = '/allChapter';
const fetcher = async (): Promise<ChapterList> => {
const response = await api('/learning', 'get');
return response.data;
};
// const fetcher = () => api('/learning', 'get').then((res) => res.data);

const useAllChapterQuery = () => {
return useQuery<ChapterList>([QUERY_KEY], fetcher);
};

export default useAllChapterQuery;
16 changes: 16 additions & 0 deletions client/src/queries/useAllUserChapterQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import api from '../common/utils/api';
import { useQuery } from '@tanstack/react-query';
import { UserChapter } from '../interfaces/Chapter.interface';

export const QUERY_KEY = '/allUserChapter';

const fetcher = async (memberId: number): Promise<UserChapter> => {
const response = await api(`/manage/${memberId}`, 'get');
return response.data;
};

const useAllUserChapterQuery = (memberId: number) => {
return useQuery<UserChapter>([QUERY_KEY, memberId], () => fetcher(memberId));
};

export default useAllUserChapterQuery;
9 changes: 4 additions & 5 deletions client/src/redux/slices/chapter.ts
Original file line number Diff line number Diff line change
@@ -3,12 +3,11 @@ import { RootState } from '../store';
import { Chapter } from '../../interfaces/Chapter.interface';

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

export const chapterSlice = createSlice({
16 changes: 12 additions & 4 deletions client/src/redux/slices/user.ts
Original file line number Diff line number Diff line change
@@ -2,13 +2,21 @@ import { createSlice } from '@reduxjs/toolkit';
import { RootState } from '../store';
import { UserState } from '../../interfaces/User.interface';

// const initialState: UserState = {
// email: '',
// username: '',
// userId: 1,
// nickname: '',
// point: 0,
// memberStatus: false
// };
const initialState: UserState = {
email: '',
username: '',
userId: 0,
nickname: '',
username: 'aa',
userId: 1,
nickname: 'sasas',
point: 0,
memberStatus: false
memberStatus: true
};

export const userSlice = createSlice({