Skip to content
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

refactor(member): 활동 2차 QA 피드백 반영 수정 #231

Merged
merged 10 commits into from
Sep 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/happy-clocks-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clab-platforms/member": patch
---

refactor(member): 활동 2차 QA 피드백 반영 수정
18 changes: 8 additions & 10 deletions apps/member/src/api/activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ export async function postActivityBoard({
activityGroupId: activityGroupId,
};

let fileUrl: string | null = null;
let fileUrl: Array<string> | null = null;

if (
body.category === ACTIVITY_BOARD_CATEGORY_STATE.ASSIGNMENT &&
Expand All @@ -289,7 +289,7 @@ export async function postActivityBoard({
files,
});

fileUrl = data[0].fileUrl;
fileUrl = data.map((file) => file.fileUrl);
} else if (
body.category === ACTIVITY_BOARD_CATEGORY_STATE.WEEKLY_ACTIVITY &&
memberId &&
Expand All @@ -301,7 +301,7 @@ export async function postActivityBoard({
files,
});

fileUrl = data[0].fileUrl;
fileUrl = data.map((file) => file.fileUrl);
}

const { data } = await server.post<
Expand All @@ -311,7 +311,7 @@ export async function postActivityBoard({
url: createPagination(END_POINT.ACTIVITY_GROUP_BOARD, params),
body: {
...body,
fileUrls: fileUrl ? [fileUrl] : undefined,
fileUrls: fileUrl ? fileUrl : undefined,
},
});

Expand All @@ -328,25 +328,23 @@ export async function patchActivityBoard({
body,
files,
}: PatchActivityBoardParams) {
let fileUrl: string | null = null;
let fileUrl: Array<string> | null = null;

if (groupBoardId === null && groupId && files) {
// 파일이 있을 경우 파일 업로드 진행 (주차별 활동 파일)
const data = await postUploadedFileWeekly({
groupId: groupId,
files,
});

fileUrl = data[0].fileUrl;
fileUrl = data.map((file) => file.fileUrl);
} else if (groupId && groupBoardId && files) {
// 파일이 있을 경우 파일 업로드 진행 (과제 파일)
const data = await postUploadedFileAssignment({
groupId: groupId,
groupBoardId: groupBoardId,
files,
});

fileUrl = data[0].fileUrl;
fileUrl = data.map((file) => file.fileUrl);
}

const { data } = await server.patch<
Expand All @@ -358,7 +356,7 @@ export async function patchActivityBoard({
}),
body: {
...body,
fileUrls: fileUrl ? [fileUrl] : undefined,
fileUrls: fileUrl ? fileUrl : undefined,
},
});

Expand Down
29 changes: 26 additions & 3 deletions apps/member/src/components/common/File/File.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,47 @@
import { createURL } from '@clab-platforms/utils';

import { SERVER_BASE_URL } from '@constants/api';
import useToast from '@hooks/common/useToast';

interface FileProps extends React.PropsWithChildren {
href: string;
name: string;
}

const File = ({ children, href }: FileProps) => {
const File = ({ href, name }: FileProps) => {
const toast = useToast();

if (!href.startsWith(SERVER_BASE_URL)) {
href = createURL(SERVER_BASE_URL, href);
}

const handleClickImgLink = () => {
fetch(href)
.then((res) => res.blob())
.then((blob) => {
const href = window.URL.createObjectURL(new Blob([blob]));
const a = document.createElement('a');
a.href = href;
a.download = name;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(href);
a.remove();
Comment on lines +22 to +29
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

긴 라인은 문맥을 한번 구분해주는게 가독성에 좋아요

Suggested change
const href = window.URL.createObjectURL(new Blob([blob]));
const a = document.createElement('a');
a.href = href;
a.download = name;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(href);
a.remove();
const href = window.URL.createObjectURL(new Blob([blob]));
const a = document.createElement('a');
a.href = href;
a.download = name;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(href);
a.remove();

})
.catch(() => {
toast({ state: 'error', message: '파일 다운로드에 실패했습니다' });
});
};

return (
<a
href={href}
target="_blank"
className="underline-offset-4 hover:underline"
className="text-gray-700 underline-offset-4 hover:underline"
rel="noreferrer"
onClick={handleClickImgLink}
>
{children}
{name}
Comment on lines -21 to +44
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

children말고 name로 변경한 이유가 있나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이전에는 children 으로 p태그를 받아 파일 명을 넣고 있었는데 propsname을 받아서 단순화 하고자 했어요.

</a>
);
};
Expand Down
2 changes: 1 addition & 1 deletion apps/member/src/components/common/Notice/Notice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const Notice = ({
},
)}
>
D-{dDay}
{dDay === 0 ? 'D-Day' : `D-${dDay}`}
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,17 @@ const ActivityAssignmentEditor = ({ parentId, activityGroupId }: Props) => {
};
const handleAddAssignmentClick = () => {
const formData = new FormData();
const file = uploaderRef.current?.files?.[0];
const files = uploaderRef.current?.files;

if (!board.title || !board.content || !board.dueDateTime)
return toast({
state: 'error',
message: '제목, 내용, 종료 일시는 필수 입력 요소입니다.',
});
if (file) {
formData.append(FORM_DATA_KEY, file);
if (files) {
Array.from(files).forEach((file) => {
formData.append(FORM_DATA_KEY, file);
});
}
Comment on lines +50 to 54
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

files의 형태가 array같은데 Array.from을 사용하신 이유가 있을까요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

filesFileList 형태라서 변환 없이 forEach를 사용하려고 하니 에러가 발생하여 Array.from을 사용하였어요


activityGroupBoardMutate(
Expand All @@ -60,25 +62,15 @@ const ActivityAssignmentEditor = ({ parentId, activityGroupId }: Props) => {
category: ACTIVITY_BOARD_CATEGORY_STATE.ASSIGNMENT,
...board,
},
files: file ? formData : undefined,
files: files?.length ? formData : undefined,
},
{ onSuccess: () => setBoard(defaultBoard) },
);
};

return (
<Section>
<Section.Header title="과제 관리">
<div className="space-x-2">
<Button
size="sm"
onClick={handleAddAssignmentClick}
disabled={activityGroupBoardIsPending}
>
추가
</Button>
</div>
</Section.Header>
<Section.Header title="과제 관리" />
<Section.Body className="space-y-4">
<div className="space-y-2">
<Input
Expand Down Expand Up @@ -112,10 +104,17 @@ const ActivityAssignmentEditor = ({ parentId, activityGroupId }: Props) => {
<label htmlFor="fileUpload" className="mb-1 ml-1 text-xs">
첨부 파일
</label>
<input ref={uploaderRef} id="fileUpload" type="file" />
<input ref={uploaderRef} id="fileUpload" type="file" multiple />
</div>
</Grid>
</div>
<Button
className="w-full"
onClick={handleAddAssignmentClick}
disabled={activityGroupBoardIsPending}
>
추가
</Button>
</Section.Body>
</Section>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface Props {
groupId: number;
}
interface FileUploaderProps {
uploadedFile: ResponseFile | null;
uploadedFile: Array<ResponseFile> | null;
uploaderRef: React.RefObject<HTMLInputElement>;
handleDeleteFileClick: () => void;
}
Expand All @@ -32,8 +32,8 @@ const ActivityBoardEditModal = ({ prevData, groupId }: Props) => {
const [board, setBoard] = useState<ActivityBoardType>(prevData);

const uploaderRef = useRef<HTMLInputElement>(null);
const [uploadedFile, setUploadedFile] = useState<ResponseFile | null>(
prevData?.files?.[0] || null,
const [uploadedFile, setUploadedFile] = useState<Array<ResponseFile> | null>(
prevData?.files || null,
);
const { activityGroupBoardPatchMutate, activityGroupBoardPatchIsPending } =
useActivityGroupBoardPatchMutation();
Expand All @@ -49,16 +49,18 @@ const ActivityBoardEditModal = ({ prevData, groupId }: Props) => {
};
const handleEditButtonClick = () => {
const formData = new FormData();
const file = uploaderRef.current?.files?.[0];
const files = uploaderRef.current?.files;

if (!board.title || !board.content) {
return toast({
state: 'error',
message: '제목과 내용을 입력해주세요.',
});
}
if (file) {
formData.append(FORM_DATA_KEY, file);
if (files?.length) {
Array.from(files).forEach((file) => {
formData.append(FORM_DATA_KEY, file);
});
}

activityGroupBoardPatchMutate({
Expand All @@ -70,7 +72,7 @@ const ActivityBoardEditModal = ({ prevData, groupId }: Props) => {
content: board.content,
dueDateTime: board.dueDateTime,
},
files: file ? formData : undefined,
files: files?.length ? formData : undefined,
});
closeModal();
};
Expand Down Expand Up @@ -134,22 +136,28 @@ const FileUploader = ({
}: FileUploaderProps) => {
return (
<>
{uploadedFile && (
<div className="space-y-2">
<File key={uploadedFile.fileUrl} href={uploadedFile.fileUrl}>
{uploadedFile.originalFileName}
</File>
{uploadedFile?.length ? (
<div>
{uploadedFile?.map((file) => (
<File
key={file.fileUrl}
href={file.fileUrl}
name={file.originalFileName}
/>
))}
<Button className="w-full" onClick={handleDeleteFileClick}>
첨부파일 변경하기
</Button>
</div>
) : (
<input
ref={uploaderRef}
id="uploader"
type="file"
multiple
className={cn(uploadedFile?.length && 'hidden')}
/>
)}
<input
ref={uploaderRef}
id="uploader"
type="file"
className={cn(uploadedFile && 'hidden')}
/>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ const ActivityDetailSection = ({ data }: ActivityDetailSectionProps) => {
<div className="space-y-4">
<Image
width="w-full"
height="h-[300px]"
height="h-[320px]"
src={data.imageUrl}
alt={data.name}
className="rounded-lg border object-cover"
/>
<Section>
<Section className="flex h-[160px] flex-col justify-between overflow-scroll">
<h1 className="text-xl font-bold">{data.name}</h1>
<p className="my-1 text-sm">{data.content}</p>
<p className="my-1 whitespace-pre-line text-sm ">{data.content}</p>
<div className="flex items-center gap-1 text-sm text-gray-500">
<CertificateSolidOutline />
<span>{data.category}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,7 @@ const ActivityNoticeEditor = ({ groupId, data }: ActivityNoticeEditorProps) => {
return (
<>
<Section>
<Section.Header title="공지 관리">
<div className="space-x-2">
<Button
size="sm"
onClick={handleAddNoticeButtonClick}
disabled={activityGroupBoardIsPending}
>
추가
</Button>
</div>
</Section.Header>
<Section.Header title="공지 관리" />
<Section.Body className="space-y-4">
<div className="space-y-2">
<Input
Expand All @@ -92,6 +82,13 @@ const ActivityNoticeEditor = ({ groupId, data }: ActivityNoticeEditorProps) => {
</div>
<Hr>미리보기</Hr>
<ActivityNoticeSection data={[notice, ...data]} />
<Button
className="w-full"
onClick={handleAddNoticeButtonClick}
disabled={activityGroupBoardIsPending}
>
추가
</Button>
</Section.Body>
</Section>
<ActivityConfigTableSection tableList={data} groupId={groupId} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface ActivityNoticeSectionProps {

interface ActivityNoticeSectionItemProps {
className?: string;
onClick: (content: string) => void;
onClick: (content: string, title?: string) => void;
data: ActivityBoardType;
}

Expand All @@ -37,9 +37,9 @@ const ActivityNoticeSection = ({ data }: ActivityNoticeSectionProps) => {
const latestNotice = sortedNotices[0];
const otherNotices = sortedNotices.slice(1);

const onClickAlert = (content: string) => {
const onClickAlert = (content: string, title?: string) => {
openModal({
title: '📣 공지사항',
title: `📣 ${title}`,
content: content,
});
};
Expand Down Expand Up @@ -94,11 +94,13 @@ ActivityNoticeSection.Item = ({
>
<div
className="flex cursor-pointer items-center justify-between gap-2"
onClick={() => onClick(data.content)}
onClick={() => onClick(data.content, data.title)}
>
<p className="w-full truncate">{data.title}</p>
<p className="whitespace-nowrap text-sm text-gray-500">
{formattedDate(toKoreaISOString(data.updatedAt))}
{formattedDate(
data.updatedAt ? toKoreaISOString(data.updatedAt) : String(dayjs()),
)}
</p>
</div>
</div>
Expand Down
Loading
Loading