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

feat: add List component #1343

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
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
92 changes: 92 additions & 0 deletions packages/web/src/common/components/List/index.tsx
Copy link
Contributor

Choose a reason for hiding this comment

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

List 폴더 만들거면 ListItem도 이 폴더에 옮기면 좋을 것 같아요

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, { ReactNode } from "react";

import styled from "styled-components";

import FlexWrapper from "@sparcs-clubs/web/common/components/FlexWrapper";
import Typography, {
ThemeColors,
} from "@sparcs-clubs/web/common/components/Typography";
import { Theme } from "@sparcs-clubs/web/styles/themes";

const FlexTypography = styled(Typography)`
display: flex;
flex-direction: column;
gap: 12px;
align-items: flex-start;
align-self: stretch;
`;

interface ListProps {
dataList: Array<string | ReactNode>;
listType: "bullet" | "number";
startIndex?: number;
gap: number;
// Typography의 props
fs?: number;
lh?: number;
fw?: keyof Theme["fonts"]["WEIGHT"];
ff?: keyof Theme["fonts"]["FAMILY"];
color?: ThemeColors;
}

interface ListItemProps {
children: string | ReactNode;
index: number;
fs?: number;
lh?: number;
fw?: keyof Theme["fonts"]["WEIGHT"];
ff?: keyof Theme["fonts"]["FAMILY"];
color?: ThemeColors;
}

// ActivityReportDetailFrame의 ActivityDetail 구현에서 따왔습니다.
const ListItem: React.FC<ListItemProps> = ({
children = "",
index = -1,
fs = 16,
fw = "REGULAR",
lh = 20,
ff = "PRETENDARD",
color = "BLACK",
}) => {
const isString: boolean = typeof children === "string";
return (
<FlexTypography fw={fw} fs={fs} lh={lh} ff={ff} color={color}>
{isString ? `${index === -1 ? "•" : `${index}.`} ${children}` : children}
</FlexTypography>
);
};

const List: React.FC<ListProps> = ({
dataList = [""],
listType = "bullet",
startIndex = 1,
gap = 16,
fs = 16,
fw = "REGULAR",
lh = 20,
ff = "PRETENDARD",
color = "BLACK",
}) => (
<FlexWrapper
direction="column"
gap={gap}
style={{ alignItems: "flex-start", alignSelf: "stretch" }}
>
{dataList.map((data, index) => (
<ListItem
key={`${(index + startIndex).toString()}`}
index={listType === "number" ? index + startIndex : -1}
fs={fs}
fw={fw}
lh={lh}
ff={ff}
color={color}
>
{data}
</ListItem>
))}
</FlexWrapper>
);

export default List;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import React, { ReactNode, useCallback, useMemo } from "react";
import React, { useCallback, useMemo } from "react";

import { useParams, useRouter } from "next/navigation";
import { overlay } from "overlay-kit";
Expand All @@ -13,6 +13,7 @@ import Button from "@sparcs-clubs/web/common/components/Button";
import Card from "@sparcs-clubs/web/common/components/Card";
import ThumbnailPreviewList from "@sparcs-clubs/web/common/components/File/ThumbnailPreviewList";
import FlexWrapper from "@sparcs-clubs/web/common/components/FlexWrapper";
import List from "@sparcs-clubs/web/common/components/List";
import Modal from "@sparcs-clubs/web/common/components/Modal";
import CancellableModalContent from "@sparcs-clubs/web/common/components/Modal/CancellableModalContent";
import ConfirmModalContent from "@sparcs-clubs/web/common/components/Modal/ConfirmModalContent";
Expand Down Expand Up @@ -67,29 +68,8 @@ const ActivitySection: React.FC<ActivitySectionProps> = ({
</FlexWrapper>
);
// ActivitySection은 활동 보고서에서 구분된 각 영역을 나타냅니다.
// label prop으로 이름을 넣고, children으로 ActivityDetail들을 넣어 주세요.

const FlexTypography = styled(Typography)`
display: flex;
flex-direction: column;
gap: 12px;
align-items: flex-start;
align-self: stretch;
`;

const ActivityDetail: React.FC<{ children: string | ReactNode }> = ({
children = "",
}) => {
const isString: boolean = typeof children === "string";
return (
<FlexTypography fw="REGULAR" fs={16} lh={20}>
{isString ? `• ${children}` : children}
</FlexTypography>
);
};
// ActivityDetail은 세부 활동 내역을 나타냅니다.
// string이면 bullet point가 자동으로 포함됩니다.
// string이 아닌 경우는 FilePreview가 들어가는 경우입니다. padding이 포함됩니다.
// label prop으로 이름을 넣고, children으로 List 컴포넌트 또는 기타 children을 넣어주세요.
// 들여쓰기가 필요한 경우 FlexWrapper를 활용해 주세요.

const FilePreviewContainerWrapper = styled(FlexWrapper)`
padding-left: 24px;
Expand Down Expand Up @@ -294,11 +274,16 @@ const ActivityReportDetailFrame: React.FC<ActivityReportDetailFrameProps> = ({
)}

<ActivitySection label="활동 정보">
<ActivityDetail>{`활동명: ${data.name}`}</ActivityDetail>
<ActivityDetail>
{`활동 분류: ${getActivityTypeLabel(data.activityTypeEnumId)}`}
</ActivityDetail>
<ActivityDetail>활동 기간:</ActivityDetail>
<List
dataList={[
`활동명: ${data.name}`,
`활동 분류: ${getActivityTypeLabel(data.activityTypeEnumId)}`,
"활동 기간:",
]}
listType="bullet"
gap={16}
/>

<FlexWrapper
direction="column"
gap={12}
Expand All @@ -310,28 +295,45 @@ const ActivityReportDetailFrame: React.FC<ActivityReportDetailFrameProps> = ({
</Typography>
))}
</FlexWrapper>
<ActivityDetail>{`활동 장소: ${data.location}`}</ActivityDetail>
<ActivityDetail>{`활동 목적: ${data.purpose}`}</ActivityDetail>
<ActivityDetail>{`활동 내용: ${data.detail}`}</ActivityDetail>
<List
dataList={[
`활동 장소: ${data.location}`,
`활동 목적: ${data.purpose}`,
`활동 내용: ${data.detail}`,
]}
listType="bullet"
gap={16}
/>
</ActivitySection>
<ActivitySection label={`활동 인원(${data.participants.length}명)`}>
{data.participants.map(participant => (
<ActivityDetail
key={participant.id}
>{`${participant.studentNumber} ${participant.name}`}</ActivityDetail>
))}
<List
dataList={data.participants.map(
participant =>
`${participant.studentNumber} ${participant.name}`,
)}
listType="bullet"
gap={16}
startIndex={0}
fw="REGULAR"
fs={16}
lh={20}
/>
</ActivitySection>
<ActivitySection label="활동 증빙">
<ActivityDetail>첨부 파일</ActivityDetail>
<ActivityDetail>
<FilePreviewContainer>
<ThumbnailPreviewList
fileList={data.evidenceFiles}
disabled
/>
</FilePreviewContainer>
</ActivityDetail>
<ActivityDetail>{`부가 설명: ${data.evidence}`}</ActivityDetail>
<List
dataList={[
"첨부 파일",
<FilePreviewContainer key="file-preview">
<ThumbnailPreviewList
fileList={data.evidenceFiles}
disabled
/>
</FilePreviewContainer>,
`부가 설명: ${data.evidence}`,
]}
listType="bullet"
gap={16}
/>
</ActivitySection>
{data.professorApproval !== null && (
<FlexWrapper
Expand Down