-
Notifications
You must be signed in to change notification settings - Fork 0
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
grade upload/#9 #41
grade upload/#9 #41
Changes from 12 commits
2dfa861
75c9882
c3bc1ba
8c37597
d0548ce
1930ff7
7ea12c6
4dc8853
edad423
8006519
39fe4d7
421c5d0
c87c9fc
b38ff02
b3dac84
a7486e6
f05c75e
c54c917
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
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> | ||
); | ||
} |
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 UploadGradeCard from '../../ui/lecture/upload-taken-lecture/upload-grade-card'; | ||
|
||
export default function GradeUploadPage() { | ||
return ( | ||
<ContentContainer className="flex flex-col justify-center gap-8 min-h-[70vh]"> | ||
<Manual /> | ||
<UploadGradeCard /> | ||
</ContentContainer> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import UploadPdf from '@/app/ui/view/molecule/upload-pdf/upload-pdf'; | ||
import { render, screen } from '@testing-library/react'; | ||
import fireEvent from '@testing-library/user-event'; | ||
|
||
describe('์ฑ์ ์ ๋ก๋', () => { | ||
it('pdf๊ฐ ์๋ ํ์ผ์ ์ ๋ก๋ํ ์ ์๋ค', async () => { | ||
render(<UploadPdf />); | ||
|
||
const targetFile = new File(['grade'], 'grade.pdf', { | ||
type: 'text/plain', | ||
}); | ||
|
||
const uploadBox = await screen.findByTestId('upload-box'); | ||
fireEvent.upload(uploadBox, targetFile); | ||
|
||
expect(screen.queryByText('์ถ๊ฐ')).not.toBeInTheDocument(); | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [request change]
|
||
}); |
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 registUserGrade = async (prevState: FormState, formData: FormData) => { | ||
const parsingText = await parsePDFtoText(formData); | ||
|
||
const res = await fetch(API_PATH.registUserGrade, { | ||
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(); | ||
}; |
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 useFile() { | ||
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 }; | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ํด๋๋ช
์ upload-taken-lecture์ธ๋ฐ ์ปดํฌ๋ํธ๋ช
์ upload-grade-card๋ก ๋์ด์๋ค์ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. upload-taken-lecture๊ฐ ๋ ๋ช ํํ๊ฒ ์๋ฟ์ ์ ์๊ฒ ๋ค์. ๊ฐ์ฌํฉ๋๋ค :) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
'use client'; | ||
|
||
import { registUserGrade } from '@/app/business/lecture/taken-lecture.command'; | ||
import UploadPdf from '@/app/ui/view/molecule/upload-pdf/upload-pdf'; | ||
import Form from '../../view/molecule/form'; | ||
|
||
function UploadGradeCard() { | ||
return ( | ||
<Form action={registUserGrade} id="์ฑ์ ์ ๋ก๋"> | ||
<UploadPdf /> | ||
<Form.SubmitButton label="๊ฒฐ๊ณผ ๋ณด๋ฌ๊ฐ๊ธฐ" position="center" size="md" /> | ||
</Form> | ||
); | ||
} | ||
|
||
export default UploadGradeCard; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
import UploadPdf from './upload-pdf'; | ||
|
||
const meta = { | ||
title: 'ui/view/molecule/UploadFile', | ||
component: UploadPdf, | ||
} satisfies Meta<typeof UploadPdf>; | ||
|
||
export default meta; | ||
|
||
export const Default: StoryObj<typeof meta> = { | ||
render: () => <UploadPdf />, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
'use client'; | ||
import Image from 'next/image'; | ||
import uploadBox from '@/public/assets/upload-box.svg'; | ||
import checkedBox from '@/public/assets/checked-box.svg'; | ||
import useFile from '@/app/hooks/useFile'; | ||
import { ChangeEvent, DragEvent } from 'react'; | ||
|
||
function UploadPdf() { | ||
const { file, changeFile } = useFile(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [comment]
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
https://legacy.reactjs.org/docs/uncontrolled-components.html There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ํ์ผ์ ์ ๋ฌด์ ๋ฐ๋ผ ๋ ๋๋ง์ controlํ๋ ค๋ ๋ชฉ์ ์ผ๋ก ์์ด๋ฌ๋ํ๊ฒ๋ ์๋๋ ์ผ์นํ์ง๋ง Controlled Component, Uncontrolled Component์ ๊ฐ๋ ์ ์ธ ๋ถ๋ถ์ ์๊ณ ๊ฐ๋ฐ์ ์ ์ฉํ๋ ๋ถ๋ถ์ ์๋์๋๋ฐ ๋๋ถ์ ๊ณต๋ถํด๋ณผ ์ ์์์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค :) |
||
|
||
const handleClickInputBox = (event: ChangeEvent) => { | ||
const { files } = event.target as HTMLInputElement; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if (files) changeFile(files[0]); | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [request change]
|
||
|
||
const handleDrop = (event: DragEvent<HTMLDivElement>) => { | ||
event.preventDefault(); | ||
const targetFile = event.dataTransfer.files[0]; | ||
changeFile(targetFile); | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [comment]
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ์ค์ํ ๋ถ๋ถ์ ๋์น๊ณ ์์๋ค์ ๋ฐ์ํด์ ์์ ํ์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค ! |
||
|
||
const handleDragOver = (event: DragEvent<HTMLDivElement>) => { | ||
event.preventDefault(); | ||
}; | ||
|
||
return ( | ||
<div className="relative flex flex-col items-center gap-4"> | ||
<input | ||
onChange={handleClickInputBox} | ||
type="file" | ||
className="absolute opacity-0 h-full w-full" | ||
name="file" | ||
accept=".pdf" | ||
data-testid="upload-box" | ||
required | ||
/> | ||
<div | ||
role="button" | ||
onDrop={handleDrop} | ||
onDragOver={handleDragOver} | ||
className="p-2 m-auto w-96 flex flex-col justify-center items-center gap-2 border-dashed border-2 rounded-sm rounded-bl-xl border-light-blue-6 bg-light-blue-1 text-light-blue-6 max-lg:w-80" | ||
> | ||
<Image src={file ? checkedBox : uploadBox} width={40} height={28} className="mx-auto" alt="upload-button" /> | ||
<span className="text-center break-keep whitespace-pre-line max-w-48"> | ||
{file ? file.name : '๋ง์ฐ์ค๋ก ๋๋๊ทธ ํ๊ฑฐ๋ ์์ด์ฝ์ ๋๋ฌ ์ถ๊ฐํด์ฃผ์ธ์.'} | ||
</span> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default UploadPdf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ํน์ ํ์ด์ง๋ ๊ทธ๋๋ก gradeupload๋ก ๊ฐ์ ธ๊ฐ๋ ์ด์ ๊ฐ ์์๊น์?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/taken-lecture-upload
๋ณด๋ค ์ฌ์ฉ์์๊ฒ/grade-upload
๊ฐ ๋ ์ง๊ด์ ์ผ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ ๋ณ๊ฒฝ์ ์งํํ์ง ์์์ต๋๋ค !There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๋ต ์๊ฒ ์ต๋๋ค!