Skip to content

Commit

Permalink
feat:문제집 상세페이지 구현(#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
cleooo5857 committed Oct 9, 2023
1 parent 4535509 commit 4155544
Show file tree
Hide file tree
Showing 23 changed files with 822 additions and 25 deletions.
46 changes: 40 additions & 6 deletions src/api/workbook.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,54 @@
import { instance } from 'api';
import { FieldValues } from 'react-hook-form';
import { WorkbookSetForm } from 'types/Form';

/* -------- Get 요청 -------- */

// 문제집리스트

/* -------- POST 요청 -------- */
import { Workbook, WorkbookList, WorkbookQuestion } from 'types/api';

// 문제집 생성
export const workbookSet = async (formData: WorkbookSetForm) => {
const response = await instance.post('/api/workbook', formData);
return response;
};

// 문제집 정보 요청
export const getWorkbook = async (id: string): Promise<Workbook> => {
const response = await instance.get(`/api/workbook/${id}`);
return response.data;
};

export const getWorkbookQuestion = async (
id = '',
page = 0,
size = 10,
sort = '',
): Promise<WorkbookQuestion> => {
const response = await instance.get(
`/api/workbook/${id}/questions?page=${page}&size=${size}&sort=${sort}`,
);
return response.data;
};

export const getWorkbookList = async ({
page = 0,
size = 8,
title = '',
sort = '',
description = '',
}): Promise<WorkbookList> => {
const response = await instance.get(
`/api/workbook?page=${page}&size=${size}&sort=${sort}&title=${title}&description=${description}`,
);
return response.data;
};

export const updateWorkbook = async (formData: FieldValues) => {
const response = await instance.post(`/api/workbook/update`, formData);
return response;
};

export const workbookQuestionDelete = async (formData: FieldValues) => {
const response = await instance.post(
`/api/workbook/question/delete`,
formData,
);
return response;
};
12 changes: 0 additions & 12 deletions src/components/commons/Admin/AdminNotice/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
import ContentContainer from 'components/commons/ContentContainer';
import { FieldValues, useForm } from 'react-hook-form';
import * as S from './style';
import useGetNoticeList from 'hooks/@query/board/useGetNoticeList';
import useNoticeFilter from 'hooks/Notice/useNoticeFilter';
import Pagination from 'components/commons/Pagination';
import NoticeList from 'components/unit/Board';
import { RequestNoticeList } from 'types/api';
import NoData from 'components/commons/NoData';
import ContentBodyWrapper from 'components/commons/ContentBodyWrapper';
import { useState } from 'react';
import { Button } from 'components/commons/Button/Style';
import AdminNoticeListCard from './adminNoticeListCard';
import NoticeAdminOptionGroup from './noticeAdminOption';

interface AdminNoticeListProps {
adminnoticeList: RequestNoticeList;
Expand Down
4 changes: 1 addition & 3 deletions src/components/commons/ContentHeaderWrapper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ import { isAdmin } from 'repository/auth';
import { useUpdateWorkbook } from 'hooks/@query/workbook/useUpdateWorkbook';

interface CreateContestProps {
title: string;
desc?: string;
admin?: boolean;
adminLink?: string;
}

const ContentHeaderWrapper = ({
title,
desc,
admin,
adminLink,
Expand Down Expand Up @@ -81,7 +79,7 @@ const ContentHeaderWrapper = ({
</Styled.AdminWrapper>
)}
{isAdmin() && adminLink && (
<StyleLink className="lg navy style" to="admin">
<StyleLink className="lg navy style" to="admin/CreateWorkbook">
{adminLink}
</StyleLink>
)}
Expand Down
49 changes: 49 additions & 0 deletions src/components/unit/Workbook/WorkbookCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { useCallback } from 'react';
import { Link } from 'react-router-dom';
import * as Styled from './style';

interface WorkBookCardProps {
id: number;
title: string;
description: string;
createdAt: string;
}

const WorkBookCard = ({
id,
title,
createdAt,
description,
}: WorkBookCardProps) => {
// const loginModal = useLoginModal();
// const checkAndDisplayLoginModal = (e: React.MouseEvent) => {
// if (!isLogin()) {
// e.preventDefault();
// loginModal.onOpen();
// }
// };

const getCategory = useCallback((title: string) => {
const categories = ['자바', '데이터베이스', '네트워크', '운영체제'];

for (const category of categories) {
if (title.includes(category)) {
return category;
}
}
return '';
}, []);

return (
<Styled.WorkBookCard>
<Link to={`${id}`}>
<Styled.Title>{title}</Styled.Title>
<Styled.Time>{createdAt}</Styled.Time>
<Styled.Img category={getCategory(title)} />
<Styled.Description>{description}</Styled.Description>
</Link>
</Styled.WorkBookCard>
);
};

export default WorkBookCard;
39 changes: 39 additions & 0 deletions src/components/unit/Workbook/WorkbookCard/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import styled from 'styled-components';
import { COLOR } from 'constants/Color';
import { FONT } from 'constants/Font';
import { SHADOW } from 'constants/Shadow';

export const WorkBookCard = styled.article`
width: 24rem;
height: 35.2rem;
padding: 2rem;
background-color: ${COLOR.WHITE};
border: 0.1rem solid ${COLOR.WHITE};
border-radius: 1.6rem;
box-shadow: ${SHADOW.CONTENTBOX_LG};
`;

export const Title = styled.div`
${FONT.H1}
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;

export const Time = styled.div`
font-size: ${FONT.REGULAR_12};
color: #949494;
`;

export const Img = styled.div<{ category?: string }>``;

export const Description = styled.div`
display: -webkit-box;
margin-top: 2rem;
font-size: ${FONT.REGULAR_14};
text-overflow: ellipsis;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
word-break: break-all;
overflow: hidden;
`;
26 changes: 26 additions & 0 deletions src/components/unit/Workbook/WorkbookCards/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { memo } from 'react';
import { WorkbookList } from 'types/api';
import WorkBookCard from '../WorkbookCard';
import * as Styled from './style';

interface WorkbookCardsProps {
workbookList: WorkbookList;
}

const WorkbookCards = ({ workbookList }: WorkbookCardsProps) => {
return (
<Styled.WorkBookCards>
{workbookList?.content?.map(({ id, title, description, createdAt }) => (
<WorkBookCard
key={id}
id={id}
title={title}
description={description}
createdAt={createdAt}
/>
))}
</Styled.WorkBookCards>
);
};

export default memo(WorkbookCards);
16 changes: 16 additions & 0 deletions src/components/unit/Workbook/WorkbookCards/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import styled from 'styled-components';

export const WorkBookCards = styled.section`
display: grid;
grid-template-columns: repeat(4, 1fr);
justify-items: center;
grid-gap: 3rem;
@media all and (max-device-width: 1200px) {
grid-template-columns: repeat(3, 1fr);
}
@media all and (max-device-width: 720px) {
grid-template-columns: repeat(2, 1fr);
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useState, memo } from 'react';
import {
FieldValues,
SubmitHandler,
UseFormHandleSubmit,
UseFormReset,
} from 'react-hook-form';
import { useWorkbookQuestionDelete } from 'hooks/@query/workbook/useWorkbookQuestionDelete';
import { Link } from 'react-router-dom';
import { isAdmin } from 'repository/auth';

interface WorkbookQuestionAdminOptionGroupProps {
questionId: string;
handleSubmit: UseFormHandleSubmit<FieldValues>;
reset: UseFormReset<FieldValues>;
}

const WorkbookQuestionAdminOptionGroup = ({
questionId,
handleSubmit,
reset,
}: WorkbookQuestionAdminOptionGroupProps) => {
const [isLoading, setIsLoading] = useState(false);

const handleIsLoading = (isLoading: boolean) => {
setIsLoading(isLoading);
};

const WorkbookQuestionDelete = useWorkbookQuestionDelete({ handleIsLoading });

const onSubmit: SubmitHandler<FieldValues> = data => {
const isArray = Array.isArray(data.questionIds);
const customQuestionIds = isArray
? data.questionIds?.map((questionId: (string | number)[]) => ({
id: +questionId,
}))
: (data.questionIds = [{ id: +data.questionIds }]);

const formData = {
workbookId: parseInt(questionId as string),
questionIds: customQuestionIds,
};

WorkbookQuestionDelete(formData);
reset();
};
return (
<>
{isAdmin() && (
<>
<Link to="adminadd" className="navy xl style">
문제 추가하기
</Link>
<button
className="revert--red xl style"
onClick={handleSubmit(onSubmit)}
disabled={isLoading}
>
문제 삭제하기
</button>
</>
)}
</>
);
};

export default WorkbookQuestionAdminOptionGroup;
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { memo } from 'react';
import { FieldErrors, FieldValues, UseFormRegister } from 'react-hook-form';
import { TBodyTd } from 'components/commons/Table/style';
import { WorkbookQuestionContent } from 'types/api';
import { Link } from 'react-router-dom';
import AdminInput from 'components/commons/Admin/AdminInput';
import { isAdmin } from 'repository/auth';

interface WorkbookQuestionTableListProps {
content: WorkbookQuestionContent;
register: UseFormRegister<FieldValues>;
errors: FieldErrors<FieldValues>;
}

const WorkbookQuestionTableList = ({
content,
register,
errors,
}: WorkbookQuestionTableListProps) => {
const { questionId, title } = content;
return (
<tr>
<TBodyTd>{questionId}</TBodyTd>
<TBodyTd className="bold">
<Link to={`/problemset/${questionId}`}>{title}</Link>
</TBodyTd>
{isAdmin() && (
<TBodyTd>
<AdminInput
type="checkbox"
name="questionIds"
register={register}
errors={errors}
value={`${questionId}`}
required
/>
</TBodyTd>
)}
</tr>
);
};

export default memo(WorkbookQuestionTableList);
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { FieldErrors, FieldValues, UseFormRegister } from 'react-hook-form';
import { WorkbookQuestionContent } from 'types/api';
import WorkbookQuestionTableList from '../WorkbookQuestionTableList';

interface WorkbookQuestionTableListsProps {
workbookContent: WorkbookQuestionContent[];
register: UseFormRegister<FieldValues>;
errors: FieldErrors<FieldValues>;
}

const WorkbookQuestionTableLists = ({
workbookContent,
register,
errors,
}: WorkbookQuestionTableListsProps) => {
return (
<>
{workbookContent?.map(content => (
<WorkbookQuestionTableList
key={content.questionId}
content={content}
register={register}
errors={errors}
/>
))}
</>
);
};

export default WorkbookQuestionTableLists;
Loading

0 comments on commit 4155544

Please sign in to comment.