-
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 16 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-taken-lecture'; | ||
|
||
export default function GradeUploadPage() { | ||
return ( | ||
<ContentContainer className="flex flex-col justify-center gap-8 min-h-[70vh]"> | ||
<Manual /> | ||
<UploadGradeCard /> | ||
</ContentContainer> | ||
); | ||
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. ํน์ ํ์ด์ง๋ ๊ทธ๋๋ก gradeupload๋ก ๊ฐ์ ธ๊ฐ๋ ์ด์ ๊ฐ ์์๊น์?! 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. ๋ต ์๊ฒ ์ต๋๋ค! |
||
} |
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 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 }; | ||
} |
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 UploadTakenLecture() { | ||
return ( | ||
<Form action={registUserGrade} id="์ฑ์ ์ ๋ก๋"> | ||
<UploadPdf /> | ||
<Form.SubmitButton label="๊ฒฐ๊ณผ ๋ณด๋ฌ๊ฐ๊ธฐ" position="center" size="md" /> | ||
</Form> | ||
); | ||
} | ||
|
||
export default UploadTakenLecture; |
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,40 @@ | ||
'use client'; | ||
import Image from 'next/image'; | ||
import uploadBox from '@/public/assets/upload-box.svg'; | ||
import checkedBox from '@/public/assets/checked-box.svg'; | ||
import usePdfFile from '@/app/hooks/usePdfFile'; | ||
import { ChangeEvent } from 'react'; | ||
|
||
function UploadPdf() { | ||
const { file, changeFile } = usePdfFile(); | ||
|
||
const handleChangeFileInput = (event: ChangeEvent<HTMLInputElement>) => { | ||
const { files } = event.target; | ||
if (files) changeFile(files[0]); | ||
}; | ||
|
||
return ( | ||
<div className="flex flex-col items-center gap-4"> | ||
<div | ||
role="button" | ||
className="relative 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 truncate"> | ||
{file ? file.name : '๋ง์ฐ์ค๋ก ๋๋๊ทธ ํ๊ฑฐ๋ ์์ด์ฝ์ ๋๋ฌ ์ถ๊ฐํด์ฃผ์ธ์.'} | ||
</span> | ||
<input | ||
onChange={handleChangeFileInput} | ||
type="file" | ||
className="absolute bg-black opacity-0 w-96 max-lg:w-80 h-full" | ||
name="file" | ||
accept=".pdf" | ||
data-testid="upload-box" | ||
required | ||
/> | ||
</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.
import๋ฌธ์ ์์ง upload grade card๋ค์!