diff --git a/src/api/workbook.ts b/src/api/workbook.ts index e6a246e3..17f6dde5 100644 --- a/src/api/workbook.ts +++ b/src/api/workbook.ts @@ -27,6 +27,7 @@ export const getWorkbookQuestion = async ( return response.data; }; +// 문제집 리스트 export const getWorkbookList = async ({ page = 0, size = 8, @@ -64,7 +65,12 @@ export const addWorkbookQuestion = async (formData: FieldValues) => { return response; }; -export const uploadimageWorkbook = async (formData: FieldValues) => { - const response = await instance.post(`/api/upload`, formData); +export const uploadimageWorkbook = async ({ id, formData }: any) => { + const response = await instance.post(`/api/workbook/upload/${id}`, formData); + return response; +}; + +export const getWorkbookimage = async () => { + const response = await instance.get(`/api/workbook/images`); return response; }; diff --git a/src/assets/workbook.png b/src/assets/workbook.png new file mode 100644 index 00000000..93336635 Binary files /dev/null and b/src/assets/workbook.png differ diff --git a/src/components/commons/Admin/WorkbookImgModal/index.tsx b/src/components/commons/Admin/WorkbookImgModal/index.tsx index b2c43439..d862662e 100644 --- a/src/components/commons/Admin/WorkbookImgModal/index.tsx +++ b/src/components/commons/Admin/WorkbookImgModal/index.tsx @@ -1,19 +1,28 @@ import { useState } from 'react'; -import axios from 'axios'; +import workbook from 'assets/workbook.png'; +import { AiOutlineClose } from 'react-icons/ai'; + import useGetWorkbookList from 'hooks/@query/workbook/useGetWorkbookList'; +import { useUploadImgWorkbook } from 'hooks/@query/workbook/useUploadWorkbook'; +import * as S from './style'; + +interface handleIsModalProps { + handleIsModal: (isModalOpen: boolean) => void; +} -const WorkbookImageUpload = () => { +const WorkbookImageUpload = ({ handleIsModal }: handleIsModalProps) => { const [selectedFile, setSelectedFile] = useState(null); const [uploading, setUploading] = useState(false); + const [previewUrl, setPreviewUrl] = useState(''); const handleFileChange = (e: any) => { setSelectedFile(e.target.files[0]); + setPreviewUrl(URL.createObjectURL(e.target.files[0])); // 생성된 URL로 미리보기 이미지 설정 }; + const workbookList = useGetWorkbookList({ title: '', description: '' }); + const workbookImgUpload = useUploadImgWorkbook({ handleIsModal }); console.log(workbookList); - const lastWorkbook = workbookList?.content[workbookList?.content.length - 1]; - const newId = lastWorkbook ? lastWorkbook.id + 1 : 1; - console.log(newId); const handleUpload = () => { if (!selectedFile) return; @@ -22,14 +31,30 @@ const WorkbookImageUpload = () => { const formData = new FormData(); formData.append('file', selectedFile); + + const lastWorkbook = workbookList?.content.length; + const id = lastWorkbook ? lastWorkbook + 1 : null; + + workbookImgUpload({ id, formData }); }; + return ( -
- - -
+ + + handleIsModal(false)}> + + + + + + + ); }; diff --git a/src/components/commons/Admin/WorkbookImgModal/style.ts b/src/components/commons/Admin/WorkbookImgModal/style.ts new file mode 100644 index 00000000..f7a5f812 --- /dev/null +++ b/src/components/commons/Admin/WorkbookImgModal/style.ts @@ -0,0 +1,58 @@ +import { COLOR } from 'constants/Color'; +import { SHADOW } from 'constants/Shadow'; +import styled from 'styled-components'; + +export const Backdrop = styled.div` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100vh; + z-index: 100; + background-color: rgba(0, 0, 0, 0.4); +`; + +export const Container = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + position: fixed; + top: 50%; + left: 50%; + z-index: 100; + width: 58rem; + height: 57rem; + border-radius: 3.2rem; + background-color: ${COLOR.WHITE}; + transform: translate(-50%, -50%); + animation: showModal 0.25s ease-in-out; + + @keyframes showModal { + 0% { + transform: translate(-50%, -50%) scale(0.8); + opacity: 0; + } + 100% { + transform: translate(-50%, -50%) scale(1); + opacity: 1; + } + } +`; + +export const XButton = styled.span` + position: absolute; + top: 2.5rem; + right: 2.5rem; + cursor: pointer; +`; +export const PreviewImage = styled.img` + max-width: 100%; + max-height: 200px; + margin-top: 0.5rem; + margin-bottom: 1.5rem; +`; + +export const FileInput = styled.input` + /* display: none; */ +`; diff --git a/src/components/unit/Workbook/WorkbookCard/index.tsx b/src/components/unit/Workbook/WorkbookCard/index.tsx index fe321bc3..23a6d755 100644 --- a/src/components/unit/Workbook/WorkbookCard/index.tsx +++ b/src/components/unit/Workbook/WorkbookCard/index.tsx @@ -37,9 +37,9 @@ const WorkBookCard = ({ return ( + {title} {createdAt} - {description} diff --git a/src/components/unit/Workbook/WorkbookCard/style.ts b/src/components/unit/Workbook/WorkbookCard/style.ts index a75b7865..f80a2d0b 100644 --- a/src/components/unit/Workbook/WorkbookCard/style.ts +++ b/src/components/unit/Workbook/WorkbookCard/style.ts @@ -4,13 +4,11 @@ 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}; + display: flex; + overflow: hidden; + flex-direction: column; + border: 1px solid #dce1e5; + border-radius: 16px; `; export const Title = styled.div` @@ -28,12 +26,10 @@ export const Time = styled.div` 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; + display: flex; + min-height: 210px; + flex-direction: column; + flex-grow: 1; + justify-content: space-between; + padding: 24px; `; diff --git a/src/components/unit/Workbook/WorkbookCards/style.ts b/src/components/unit/Workbook/WorkbookCards/style.ts index 8e79b97f..055c9847 100644 --- a/src/components/unit/Workbook/WorkbookCards/style.ts +++ b/src/components/unit/Workbook/WorkbookCards/style.ts @@ -2,7 +2,7 @@ import styled from 'styled-components'; export const WorkBookCards = styled.section` display: grid; - grid-template-columns: repeat(4, 1fr); + grid-template-columns: repeat(3, 1fr); justify-items: center; grid-gap: 3rem; diff --git a/src/hooks/@query/workbook/useGetWorkbookImg.ts b/src/hooks/@query/workbook/useGetWorkbookImg.ts new file mode 100644 index 00000000..1ba20d9b --- /dev/null +++ b/src/hooks/@query/workbook/useGetWorkbookImg.ts @@ -0,0 +1,11 @@ +import { useQuery } from '@tanstack/react-query'; +import { getWorkbookimage } from 'api/workbook'; + +const useGetWorkbookImg = () => { + const { data: workbookImgList } = useQuery(['workbookimgList'], () => + getWorkbookimage(), + ); + return workbookImgList; +}; + +export default useGetWorkbookImg; diff --git a/src/hooks/@query/workbook/useUploadWorkbook.ts b/src/hooks/@query/workbook/useUploadWorkbook.ts index c8ab0240..7aad05a2 100644 --- a/src/hooks/@query/workbook/useUploadWorkbook.ts +++ b/src/hooks/@query/workbook/useUploadWorkbook.ts @@ -1,29 +1,27 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { updateWorkbook } from 'api/workbook'; +import { updateWorkbook, uploadimageWorkbook } from 'api/workbook'; -interface UpdateWorkbookProps { - handleIsLoading: (isLoading: boolean) => void; - handleIsActive: (isActive: boolean) => void; +interface UploadImgWorkbookProps { + handleIsModal: (isModalOpen: boolean) => void; } -export const useUploadWorkbook = ({ - handleIsLoading, - handleIsActive, -}: UpdateWorkbookProps) => { +export const useUploadImgWorkbook = ({ + handleIsModal, +}: UploadImgWorkbookProps) => { const queryClient = useQueryClient(); - const { mutate: UpdateWorkbook } = useMutation(updateWorkbook, { + const { mutate: useUploadImgWorkbook } = useMutation(uploadimageWorkbook, { onSuccess: () => { - alert('문제집 정보 수정에 성공했습니다.'); - queryClient.invalidateQueries(['workbook']); + queryClient.invalidateQueries(['workbookimage']); + + alert('이미지 저장에 성공했습니다.'); }, onError: () => { - alert('문제집 정보 수정에 실패했습니다.'); + alert('이미지 저장에 실패했습니다.'); }, onSettled: () => { - handleIsActive(false); - handleIsLoading(false); + handleIsModal(false); }, }); - return UpdateWorkbook; + return useUploadImgWorkbook; }; diff --git a/src/hooks/@redux/filterSlice.ts b/src/hooks/@redux/filterSlice.ts index 993a51a7..80471756 100644 --- a/src/hooks/@redux/filterSlice.ts +++ b/src/hooks/@redux/filterSlice.ts @@ -144,13 +144,13 @@ const NoticeFilterSlice = createSlice({ const workbookFilterSlice = createSlice({ name: 'workbookFilter', initialState: { - pageNumber: 0, + pageNum: 0, title: '', description: '', }, reducers: { - setPageNumber(state, action) { - state.pageNumber = action.payload; + setPageNum(state, action) { + state.pageNum = action.payload; }, setTitle(state, action) { state.title = action.payload; @@ -158,8 +158,9 @@ const workbookFilterSlice = createSlice({ setDescription(state, action) { state.description = action.payload; }, + reset(state) { - state.pageNumber = 0; + state.pageNum = 0; state.title = ''; state.description = ''; }, @@ -175,7 +176,8 @@ export const { setContenthInput: setNoticeFilterSearchContent, setSearchReset: setNoticeFilterSearchReset, } = NoticeFilterSlice.actions; -export const { setTitle, setDescription } = workbookFilterSlice.actions; +export const { setTitle, setDescription, setPageNum } = + workbookFilterSlice.actions; export const { setStatus, setStatusValue, toggleStatusActive } = statusFilterSlice.actions; diff --git a/src/hooks/Workbook/useWorkbookFilter.ts b/src/hooks/Workbook/useWorkbookFilter.ts index 73a6197b..8617eb2a 100644 --- a/src/hooks/Workbook/useWorkbookFilter.ts +++ b/src/hooks/Workbook/useWorkbookFilter.ts @@ -2,6 +2,7 @@ import { setTitle, setDescription, setPageNumber, + setPageNum, } from 'hooks/@redux/filterSlice'; import { useCallback } from 'react'; import { FieldValues, SubmitHandler } from 'react-hook-form'; @@ -18,7 +19,7 @@ const useWorkbookFilter = () => { const handlePage = useCallback( (page: number) => { - dispatch(setPageNumber(page)); + dispatch(setPageNum(page)); }, [workbookFilter], ); diff --git a/src/pages/Admin/CreateWorkbook/index.tsx b/src/pages/Admin/CreateWorkbook/index.tsx index 9c0aac3c..f1d0e882 100644 --- a/src/pages/Admin/CreateWorkbook/index.tsx +++ b/src/pages/Admin/CreateWorkbook/index.tsx @@ -9,11 +9,12 @@ import AdminInput from 'components/commons/Admin/AdminInput'; import FormSection from 'components/commons/Admin/FormSection'; import { useWorkbookSet } from 'hooks/@query/workbook/useWorkbookSet'; import { Button } from 'components/commons/Button/Style'; +import WorkbookImageUpload from 'components/commons/Admin/WorkbookImgModal'; const CreateWorkbook = () => { const navigate = useNavigate(); const [isLoading, setIsLoading] = useState(false); - const [isModalOpen, setIsModalOpen] = useState(false); + const [isModalOpen, setIsModalOpen] = useState(true); const { register, handleSubmit, @@ -81,6 +82,7 @@ const CreateWorkbook = () => { + {isModalOpen && } ); diff --git a/src/pages/Notice/index.tsx b/src/pages/Notice/index.tsx index 6872d806..cd986d12 100644 --- a/src/pages/Notice/index.tsx +++ b/src/pages/Notice/index.tsx @@ -34,6 +34,7 @@ const Notice = () => { title: noticeFilter.SearchTitle, content: noticeFilter.SearchContent, }); + console.log(noticeList); return ( diff --git a/src/pages/Workbook/index.tsx b/src/pages/Workbook/index.tsx index 50f40107..2099f785 100644 --- a/src/pages/Workbook/index.tsx +++ b/src/pages/Workbook/index.tsx @@ -11,6 +11,7 @@ import ContentContainer from 'components/commons/ContentContainer'; import Pagination from 'components/commons/Pagination'; import WorkbookCards from 'components/unit/Workbook/WorkbookCards'; import Container from 'components/commons/Container'; +import useGetWorkbookImg from 'hooks/@query/workbook/useGetWorkbookImg'; const Workbook = () => { const { register, handleSubmit, reset } = useForm({ @@ -21,14 +22,16 @@ const Workbook = () => { const { workbookFilter, handlePage, onSubmit } = useWorkbookFilter(); const workbookList = useGetWorkbookList({ - page: workbookFilter.pageNumber, + page: workbookFilter.pageNum, title: workbookFilter.title, description: workbookFilter.description, }); + const workbookImgList = useGetWorkbookImg(); + console.log(workbookImgList); console.log(workbookList); const handleReset = () => { - reset(); + // reset(); // workbookFilter.reset(); }; @@ -57,16 +60,16 @@ const Workbook = () => { 문제집이 없습니다. )} - {(workbookList?.totalPages as number) > 1 && ( - - - - )} + {/* {(workbookList?.totalPages as number) > 1 && ( + )} */} + + + );