-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Merge branch 'main' into sign-up-form/#7
- Loading branch information
Showing
32 changed files
with
473 additions
and
64 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
export default function Manual() { | ||
return ( | ||
<div className="flex justify-center"> | ||
<div className="flex flex-col gap-6"> | ||
<h1 className="text-center text-3xl font-bold p-4 border-b-2 border-gray-100 md:text-4xl"> | ||
한 번의 성적표 입력으로 | ||
<br /> 맞춤형 결과를 확인하세요 ! | ||
</h1> | ||
<div className="text-base flex flex-col gap-2 md:text-lg"> | ||
<div> | ||
1. | ||
<a | ||
target="_blank" | ||
className="pl-1 text-primary hover:text-dark-hover" | ||
href="https://msi.mju.ac.kr/servlet/security/MySecurityStart" | ||
> | ||
MyiWeb MSI | ||
</a> | ||
에 접속 후 로그인(PC환경 권장) | ||
</div> | ||
<div>2. 좌측 성적/졸업 메뉴 → 성적표(상담용,B4)클릭</div> | ||
<div>3. 우측 상단 조회버튼 클릭 → 프린트 아이콘 클릭</div> | ||
<div>4. 인쇄 정보의 대상(PDF로 저장) 설정 → 하단 저장 버튼 클릭 </div> | ||
<div>5. 저장한 파일 업로드 </div> | ||
<div className="text-xs md:text-sm text-primary"> | ||
• 회원 가입한 학번과 일치하는 학번의 성적표를 입력해야 합니다. | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import ContentContainer from '../../ui/view/atom/content-container'; | ||
import Manual from './components/manual'; | ||
import UploadTakenLecture from '../../ui/lecture/upload-taken-lecture/upload-taken-lecture'; | ||
|
||
export default function GradeUploadPage() { | ||
return ( | ||
<ContentContainer className="flex flex-col justify-center gap-8 min-h-[70vh]"> | ||
<Manual /> | ||
<UploadTakenLecture /> | ||
</ContentContainer> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import UploadPdf from '@/app/ui/view/molecule/upload-pdf/upload-pdf'; | ||
import { render, screen } from '@testing-library/react'; | ||
import { userEvent } from '@testing-library/user-event'; | ||
|
||
describe('성적 업로드', () => { | ||
it('파일이 업로드 될 때, pdf file을 업로드 하면 file명이 노출된다.', async () => { | ||
render(<UploadPdf />); | ||
|
||
const targetFile = new File(['grade'], 'grade.pdf', { | ||
type: 'text/plain', | ||
}); | ||
|
||
const uploadBox = await screen.findByTestId('upload-box'); | ||
await userEvent.upload(uploadBox, targetFile); | ||
|
||
expect(screen.getByText(targetFile.name)).toBeInTheDocument(); | ||
}); | ||
|
||
it('파일이 업로드 될 때, pdf가 아닌 file을 업로드 하면 변화가 발생하지않는다.', async () => { | ||
render(<UploadPdf />); | ||
|
||
const targetFile = new File(['grade'], 'grade.png', { | ||
type: 'text/plain', | ||
}); | ||
|
||
const uploadBox = await screen.findByTestId('upload-box'); | ||
await userEvent.upload(uploadBox, targetFile); | ||
expect(screen.queryByText('마우스로 드래그 하거나 아이콘을 눌러 추가해주세요.')).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
'use server'; | ||
import { FormState } from '@/app/ui/view/molecule/form/form-root'; | ||
import { API_PATH } from '../api-path'; | ||
|
||
export const registerUserGrade = async (prevState: FormState, formData: FormData) => { | ||
const parsingText = await parsePDFtoText(formData); | ||
|
||
const res = await fetch(API_PATH.registerUserGrade, { | ||
method: 'POST', | ||
body: JSON.stringify({ parsingText }), | ||
}); | ||
|
||
if (!res.ok) { | ||
return { | ||
errors: {}, | ||
message: 'fail upload grade', | ||
}; | ||
} | ||
|
||
return { | ||
errors: {}, | ||
message: '', | ||
}; | ||
}; | ||
|
||
export const parsePDFtoText = async (formData: FormData) => { | ||
const res = await fetch(API_PATH.parsePDFtoText, { method: 'POST', body: formData }); | ||
if (!res.ok) { | ||
return { | ||
errors: {}, | ||
message: 'fail parsing to text', | ||
}; | ||
} | ||
return await res.json(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { useState } from 'react'; | ||
import { z } from 'zod'; | ||
|
||
export type FileType = File | null; | ||
|
||
export default function usePdfFile() { | ||
const [file, setFile] = useState<FileType>(null); | ||
|
||
const changeFile = (file: File) => { | ||
if (!validate.parse(file.name)) return; | ||
setFile(file); | ||
}; | ||
|
||
const validate = z.string().refine((value) => value.endsWith('.pdf'), { | ||
message: 'File must be a PDF', | ||
}); | ||
|
||
return { file, changeFile }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,22 @@ | ||
import { HttpResponse, http } from 'msw'; | ||
import { HttpResponse, http, delay } from 'msw'; | ||
import { API_PATH } from '../../business/api-path'; | ||
import { mockDatabase } from '../db.mock'; | ||
import { parsePDF } from '../data.mock'; | ||
|
||
export const takenLectureHandlers = [ | ||
http.get(API_PATH.takenLectures, () => { | ||
const takenLectures = mockDatabase.getTakenLectures(); | ||
|
||
return HttpResponse.json(takenLectures[0]); | ||
}), | ||
http.post(API_PATH.parsePDFtoText, async () => { | ||
await delay(1000); | ||
console.log(parsePDF); | ||
return HttpResponse.json(parsePDF); | ||
}), | ||
|
||
http.post(API_PATH.registerUserGrade, async () => { | ||
await delay(1000); | ||
throw new HttpResponse(null, { status: 200 }); | ||
}), | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { atom } from 'jotai'; | ||
import { LectureInfo } from '../type/lecture'; | ||
|
||
export const isCustomizingAtom = atom<boolean>(false); | ||
|
||
export const customLectureAtom = atom<LectureInfo[]>([]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,17 @@ | ||
export type LectureInfo = { | ||
export interface LectureInfo { | ||
[index: string]: string | number; | ||
id: number; | ||
year: string; | ||
semester: string; | ||
lectureCode: string; | ||
lectureName: string; | ||
credit: number; | ||
}; | ||
} | ||
|
||
export interface SearchedLectureInfo { | ||
[index: string]: string | number; | ||
id: number; | ||
lectureCode: string; | ||
name: string; | ||
credit: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
'use client'; | ||
import React from 'react'; | ||
import LectureSearchBar from './lecture-search-bar'; | ||
import LectureSearchResultContainer from './lecture-search-result-container'; | ||
import { isCustomizingAtom } from '@/app/store/custom-taken-lecture'; | ||
import { useAtomValue } from 'jotai'; | ||
|
||
export default function LectureSearch() { | ||
const isCustomizing = useAtomValue(isCustomizingAtom); | ||
if (!isCustomizing) return null; | ||
return ( | ||
<div className="flex flex-col gap-4" data-testid="lecture-search-component"> | ||
<LectureSearchBar /> | ||
<LectureSearchResultContainer /> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import Select from '../../view/molecule/select'; | ||
import TextInput from '../../view/atom/text-input/text-input'; | ||
import { MagnifyingGlassIcon } from '@radix-ui/react-icons'; | ||
|
||
export default function LectureSearchBar() { | ||
// 검색 기능을 해당 컴포넌트에서 구현 예정 | ||
return ( | ||
<div className="flex justify-between"> | ||
<div className="w-[15%]"> | ||
<Select defaultValue="lectureName" placeholder="과목명"> | ||
<Select.Item value="lectureName" placeholder="과목명" /> | ||
<Select.Item value="lectureCode" placeholder="과목코드" /> | ||
</Select> | ||
</div> | ||
<div className="w-[40%] flex justify-between"> | ||
<TextInput placeholder="검색어를 입력해주세요" icon={MagnifyingGlassIcon} /> | ||
</div> | ||
</div> | ||
); | ||
} |
47 changes: 47 additions & 0 deletions
47
app/ui/lecture/lecture-search/lecture-search-result-container.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import List from '../../view/molecule/list'; | ||
import Image from 'next/image'; | ||
import searchResultIcon from '@/public/assets/searchResultIcon.svg'; | ||
import Grid from '../../view/molecule/grid'; | ||
import { SearchedLectureInfo } from '@/app/type/lecture'; | ||
import AddTakenLectureButton from '../taken-lecture/add-taken-lecture-button'; | ||
|
||
const emptyDataRender = () => { | ||
return ( | ||
<div className="flex flex-col items-center justify-center gap-2"> | ||
<Image src={searchResultIcon} alt="search-result-icon" width={40} height={40} /> | ||
<div className="text-md font-medium text-gray-400">검색 결과가 표시됩니다</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default function LectureSearchResultContainer() { | ||
const renderAddActionButton = (item: SearchedLectureInfo) => { | ||
return <AddTakenLectureButton lectureItem={item} />; | ||
}; | ||
const render = (item: SearchedLectureInfo, index: number) => { | ||
const searchLectureItem = item; | ||
return ( | ||
<List.Row key={index}> | ||
<Grid cols={4}> | ||
{Object.keys(searchLectureItem).map((key, index) => { | ||
if (key === 'id') return null; | ||
return <Grid.Column key={index}>{searchLectureItem[key]}</Grid.Column>; | ||
})} | ||
{renderAddActionButton ? <Grid.Column>{renderAddActionButton(searchLectureItem)}</Grid.Column> : null} | ||
</Grid> | ||
</List.Row> | ||
); | ||
}; | ||
|
||
return ( | ||
<List | ||
data={[ | ||
{ id: 3, lectureCode: 'HCB03490', name: '경영정보사례연구', credit: 3 }, | ||
{ id: 4, lectureCode: 'HCB03490', name: '게임을통한경영의이해', credit: 3 }, | ||
]} | ||
render={render} | ||
isScrollList={true} | ||
emptyDataRender={emptyDataRender} | ||
/> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { SearchedLectureInfo } from '@/app/type/lecture'; | ||
import Button from '../../view/atom/button/button'; | ||
import { useAtom } from 'jotai'; | ||
import { customLectureAtom } from '@/app/store/custom-taken-lecture'; | ||
|
||
interface AddTakenLectureButtonProps { | ||
lectureItem: SearchedLectureInfo; | ||
} | ||
export default function AddTakenLectureButton({ lectureItem }: AddTakenLectureButtonProps) { | ||
const [customLecture, setCustomLecture] = useAtom(customLectureAtom); | ||
const addLecture = () => { | ||
setCustomLecture([ | ||
...customLecture, | ||
{ | ||
id: lectureItem.id, | ||
year: 'CUSTOM', | ||
semester: 'CUSTOM', | ||
lectureCode: lectureItem.lectureCode, | ||
lectureName: lectureItem.name, | ||
credit: lectureItem.credit, | ||
}, | ||
]); | ||
}; | ||
return <Button variant="list" label="추가" onClick={addLecture} />; | ||
} |
14 changes: 14 additions & 0 deletions
14
app/ui/lecture/taken-lecture/delete-taken-lecture-button.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { useAtom } from 'jotai'; | ||
import Button from '../../view/atom/button/button'; | ||
import { customLectureAtom } from '@/app/store/custom-taken-lecture'; | ||
|
||
interface DeleteTakenLectureButtonProps { | ||
lectureId: number; | ||
} | ||
export default function DeleteTakenLectureButton({ lectureId }: DeleteTakenLectureButtonProps) { | ||
const [customLecture, setCustomLecture] = useAtom(customLectureAtom); | ||
const deleteLecture = () => { | ||
setCustomLecture(customLecture.filter((lecture) => lecture.id !== lectureId)); | ||
}; | ||
return <Button label="삭제" variant="list" data-testid="taken-lecture-delete-button" onClick={deleteLecture} />; | ||
} |
Oops, something went wrong.