Skip to content

Commit

Permalink
Merge pull request #404 from Bamdoliro/develop
Browse files Browse the repository at this point in the history
어드민
  • Loading branch information
SEOKKAMONI authored Sep 18, 2023
2 parents 52dbcf1 + d28d0cb commit 7105df4
Show file tree
Hide file tree
Showing 18 changed files with 425 additions and 31 deletions.
54 changes: 44 additions & 10 deletions apps/admin/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
'use client';

import ButtonMenu from '@/components/common/ButtonMenu/ButtonMenu';
import ButtonMenuItem from '@/components/common/ButtonMenu/ButtonMenuItem/ButtonMenuItem';
import FormList from '@/components/main/FormList/FormList';
import AppLayout from '@/layouts/AppLayout';
import initMockAPI from '@/mocks';
import { useFormListQuery } from '@/services/form/queries';
import { Button, Column, Row, SearchInput, Text } from '@maru/ui';
import { IconCheckDocument, IconEditDocument, IconPrint, IconUpload } from '@maru/icon';
import { color } from '@maru/theme';
import { Column, Row, SearchInput, Text } from '@maru/ui';
import { flex } from '@maru/utils';
import { styled } from 'styled-components';

Expand All @@ -13,19 +16,50 @@ if (process.env.NODE_ENV === 'development') {
}

const MainPage = () => {
const { data: formListData } = useFormListQuery();

return (
<AppLayout>
<StyledMainPage>
<Text fontType="H1">원서 관리</Text>
<Column gap={36}>
<Row justifyContent="space-between" alignItems="center">
<Text fontType="H5">{formListData?.length}</Text>
<Row gap={8}>
<SearchInput placeholder="통합 검색" />
<Button size="SMALL">검색</Button>
</Row>
<Row justifyContent="space-between">
<SearchInput placeholder="통합검색" />
<ButtonMenu
width={280}
menuItemList={[
<ButtonMenuItem>
<IconCheckDocument
color={color.gray600}
width={24}
height={24}
/>
<Text fontType="p2" color={color.gray900}>
검토해야 하는 원서 모아보기
</Text>
</ButtonMenuItem>,
<ButtonMenuItem>
<IconEditDocument
color={color.gray600}
width={24}
height={24}
/>
<Text fontType="p2" color={color.gray900}>
2차 전형 점수 입력하기
</Text>
</ButtonMenuItem>,
<ButtonMenuItem>
<IconUpload color={color.gray600} width={24} height={24} />
<Text fontType="p2" color={color.gray900}>
명단 엑셀로 내보내기
</Text>
</ButtonMenuItem>,
<ButtonMenuItem>
<IconPrint color={color.gray600} width={24} height={24} />
<Text fontType="p2" color={color.gray900}>
원서 출력하기
</Text>
</ButtonMenuItem>,
]}
/>
</Row>
<FormList />
</Column>
Expand Down
59 changes: 59 additions & 0 deletions apps/admin/src/components/common/ButtonMenu/ButtonMenu.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { IconCheckDocument, IconEditDocument, IconPrint, IconUpload } from "@maru/icon";
import { color } from "@maru/theme";
import { Text } from "@maru/ui";
import type { Meta, StoryObj } from "@storybook/react";
import ButtonMenu from "./ButtonMenu";
import ButtonMenuItem from "./ButtonMenuItem/ButtonMenuItem";

export default {
component: ButtonMenu,
title: "ButtonMenu",
tags: ["autodocs"],
} satisfies Meta<typeof ButtonMenu>;

export const Default: StoryObj<typeof ButtonMenu> = {
args: {
menuItemList: [
<ButtonMenuItem>
<IconCheckDocument
color={color.gray600}
width={24}
height={24}
/>
<Text fontType="p2" color={color.gray900}>
검토해야 하는 원서 모아보기
</Text>
</ButtonMenuItem>,
<ButtonMenuItem>
<IconEditDocument
color={color.gray600}
width={24}
height={24}
/>
<Text fontType="p2" color={color.gray900}>
2차 전형 점수 입력하기
</Text>
</ButtonMenuItem>,
<ButtonMenuItem>
<IconUpload
color={color.gray600}
width={24}
height={24}
/>
<Text fontType="p2" color={color.gray900}>
명단 엑셀로 내보내기
</Text>
</ButtonMenuItem>,
<ButtonMenuItem>
<IconPrint
color={color.gray600}
width={24}
height={24}
/>
<Text fontType="p2" color={color.gray900}>
원서 출력하기
</Text>
</ButtonMenuItem>,
]
},
};
90 changes: 90 additions & 0 deletions apps/admin/src/components/common/ButtonMenu/ButtonMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { useBooleanState, useOutsideClick } from '@maru/hooks';
import { IconArrowBottom, IconArrowTop } from '@maru/icon';
import { color } from '@maru/theme';
import { Text } from '@maru/ui';
import { flex } from '@maru/utils';
import { CSSProperties, ReactNode } from 'react';
import styled, { css } from 'styled-components';

interface Props {
width?: CSSProperties['width'];
menuItemList: ReactNode[];
}

const ButtonMenu = ({ width, menuItemList = [] }: Props) => {
const {
value: isOpen,
setFalse: closeMenu,
toggle: handleToggleButtonClick,
} = useBooleanState();

const menuRef = useOutsideClick(closeMenu);

return (
<div style={{ width: 120 }} ref={menuRef}>
<StyledButtonMenu $isOpen={isOpen} onClick={handleToggleButtonClick}>
<Text fontType="p2" color={color.gray700}>
추가 기능
</Text>
{isOpen ? (
<IconArrowTop color={color.gray600} width={24} height={24} />
) : (
<IconArrowBottom color={color.gray600} width={24} height={24} />
)}
</StyledButtonMenu>
<MenuListBox $isOpen={isOpen}>
<MenuList style={{ width }}>
{menuItemList.map((menuItem) => (
<MenuItem onClick={closeMenu}>{menuItem}</MenuItem>
))}
</MenuList>
</MenuListBox>
</div>
);
};

export default ButtonMenu;

const StyledButtonMenu = styled.div<{ $isOpen: boolean }>`
${flex({ alignItems: 'center', justifyContent: 'space-between' })}
width: 100%;
height: 40px;
padding: 0 10px 0 16px;
background-color: ${color.white};
border-radius: 6px;
cursor: pointer;
${(props) =>
props.$isOpen
? css`
border: 1px solid ${color.maruDefault};
outline: 2px solid rgba(20, 112, 255, 0.25);
`
: css`
border: 1px solid ${color.gray400};
`}
`;

const MenuListBox = styled.div<{ $isOpen: boolean }>`
position: relative;
display: ${(props) => (props.$isOpen ? 'block' : 'none')};
`;

const MenuList = styled.div`
z-index: 1;
position: absolute;
right: 0;
margin-top: 8px;
padding: 8px;
min-width: 120px;
background-color: ${color.white};
border: 1px solid ${color.gray200};
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.08);
border-radius: 12px;
`;

const MenuItem = styled.div`
width: 100%;
height: 44px;
cursor: pointer;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { Meta, StoryObj } from "@storybook/react";
import ButtonMenuItem from "./ButtonMenuItem";

export default {
component: ButtonMenuItem,
title: "ButtonMenuItem",
tags: ["autodocs"],
} satisfies Meta<typeof ButtonMenuItem>;

export const Default: StoryObj<typeof ButtonMenuItem> = {
args: {
children: '이것은 버튼 메뉴 아이템입니다~~'
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { color } from '@maru/theme';
import { flex } from '@maru/utils';
import { ReactNode } from 'react';
import styled from 'styled-components';

interface Props {
children: ReactNode;
}

const ButtonMenuItem = ({ children }: Props) => {
return <StyledButtonMenuItem>{children}</StyledButtonMenuItem>;
};

export default ButtonMenuItem;

const StyledButtonMenuItem = styled.div`
${flex({ alignItems: 'center' })}
gap: 12px;
width: 100%;
height: 44px;
padding: 0 8px;
&:hover {
background-color: ${color.gray100};
}
`;
4 changes: 4 additions & 0 deletions apps/admin/src/components/main/FormList/FormList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ const FormList = () => {
school={item.school}
status={item.status}
type={item.type}
totalScore={item.totalScore}
hasDocument={item.hasDocument}
firstRoundPassed={item.firstRoundPassed}
secondRoundPassed={item.secondRoundPassed}
/>
))}
</Column>
Expand Down
17 changes: 14 additions & 3 deletions apps/admin/src/components/main/FormListHeader/FormListHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,20 @@ const FormListHeader = () => {
전형
</Text>
</Row>
<Text fontType="p2" width={80}>
상태
</Text>
<Row gap={48}>
<Text fontType="p2" width={80}>
제출서류
</Text>
<Text fontType="p2" width={80}>
1차 결과
</Text>
<Text fontType="p2" width={80}>
최종 점수
</Text>
<Text fontType="p2" width={80}>
2차 결과
</Text>
</Row>
</TableHeader>
);
};
Expand Down
52 changes: 38 additions & 14 deletions apps/admin/src/components/main/FormListItem/FormListItem.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
import TableItem from '@/components/common/TableItem/TableItem';
import { FORM_TYPE } from '@/constants/main/constants';
import { FormStatus, FormType, GraduationType } from '@/types/main/client';
import { Form, FormType } from '@/types/main/client';
import { color } from '@maru/theme';
import { Row, Text } from '@maru/ui';

interface Props {
id: number;
name: string;
birthday: string;
graduationType: GraduationType;
school: string;
status: FormStatus;
type: FormType;
}
const FormListItem = ({
id,
name,
birthday,
graduationType,
school,
type,
totalScore,
hasDocument,
firstRoundPassed,
secondRoundPassed,
}: Form) => {
const getStatusColor = (status: boolean | null) => {
return typeof status !== 'boolean' ? color.gray600 : status ? color.maruDefault : color.red;
};

const getStatusString = (status: boolean | null, trueString: string, falseString: string) => {
return typeof status !== 'boolean' ? '미정' : status ? trueString : falseString;
};

const FormListItem = ({ id, name, birthday, graduationType, school, type, status }: Props) => {
return (
<TableItem>
<Row gap={48}>
Expand All @@ -33,9 +43,23 @@ const FormListItem = ({ id, name, birthday, graduationType, school, type, status
{FORM_TYPE[type as FormType]}
</Text>
</Row>
<Text fontType="p2" width={80}>
{status}
</Text>
<Row gap={48}>
<Text fontType="p2" width={80} color={getStatusColor(hasDocument)}>
{getStatusString(hasDocument, '제출', '미제출')}
</Text>
<Text fontType="p2" width={80} color={getStatusColor(firstRoundPassed)}>
{getStatusString(firstRoundPassed, '합격', '불합격')}
</Text>
<Text
fontType="p2"
width={80}
color={typeof totalScore !== 'number' ? color.gray600 : color.gray900}>
{typeof totalScore !== 'number' ? '미정' : totalScore}
</Text>
<Text fontType="p2" width={80} color={getStatusColor(secondRoundPassed)}>
{getStatusString(secondRoundPassed, '합격', '불합격')}
</Text>
</Row>
</TableItem>
);
};
Expand Down
Loading

1 comment on commit 7105df4

@vercel
Copy link

@vercel vercel bot commented on 7105df4 Sep 18, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.