
해당 POST 는 ad-fi-admin 프로젝트의 src > Views > Brand > DashBoard > AdRevenue 를 참고하여 작성되었습니다.
DIRECTORY STRUCTURE
`ad-fi-admin`
└── . . .
└── src
│ └── . . .
│ └── Views
│ │ └── . . .
│ │ └── Brand
│ │ │ └── . . .
│ │ │ └── Dashboard
│ │ │ │ └── AdRevenue
│ │ │ │ │ └── AdRevenueByDate.graphql
│ │ │ │ │ └── AdRevenue.tsx
│ │ │ │ │ └── DefaultProps.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ │ └── types.tsx
│ │ │ │ └── . . .Step By Step 🚶
Container 작성
File Naming Convention : Container 파일의 명칭은 index.tsx 로 작성합니다.
- 전체 코드#
알아두기
유사한 문구
Types:graphql-codegen을 사용하여 자동으로 생성된 코드 입니다.
./Types: 개발자가 직접 작성한 코드로type,interface,checker를export합니다.
재사용 하는 모듈
useError:Contexts/erroHandlerContext에 작성해놓은 모듈을 사용합니다.
Loader:Components/Loader에 작성해놓은 모듈을 사용합니다.
// => 파일명 : index.tsx
import React from "react";
import { useBrandGetPureRevenueByDateQuery } from "Types";
import { useError } from "Contexts/errorHandlerContext";
import AdRevenue from "./AdRevenue";
import Loader from "Components/Loader";
import moment from "moment";
import { barData } from "./Types";
export default function AdRevenueContainer() {
const { onError } = useError();
const start = moment().subtract(29, "day").startOf("day").toISOString();
const end = moment().endOf("day").toISOString();
const { data, loading } = useBrandGetPureRevenueByDateQuery({
variables: { start, end },
onError,
fetchPolicy: "network-only",
});
return (
<>
{loading && <Loader />}
<AdRevenue barData={barData(data)} />
</>
);
}Presenter 작성
File Naming Convention : Presenter 파일의 명칭은 폴더명 과 동일하게 작성합니다.
- 전체 코드#
material-ui를 사용한 컴포넌트 디자인, 구성등을 Presenter 컴포넌트에 작성합니다.
import React from "react";
import { Grid } from "@material-ui/core";
import BarChartCard from "Components/BrandBarChartCard";
import { PropType } from "./Types";
import { PureRevenueIcon } from "Components/Icons";
import { theme } from "theme";
import DefaultProps from "./DefaultProps";
export default function ClickPlayCountByBrand(props: PropType) {
const { barData } = props;
return (
<Grid item xs={12}>
<BarChartCard
title="광고 순 매출"
icon={PureRevenueIcon}
data={barData}
keys={Object.keys(barData[0]).splice(1)}
indexBy="day"
colors={[theme.danbiTheme.colors.middle_danbiblue]}
legendBottom=""
legendLeft=""
legend={false}
tooltipState={true}
tooltip="30일 간의 광고 순매출을 나타낸 그래프"
/>
</Grid>
);
}
ClickPlayCountByBrand.defaultProps = DefaultProps;Graphql 작성
알아두기
query 혹은 mutation 키워드와 같이 작성하는 함수명은 기본적으로는 선택사항입니다.하지만, graphql-codegen 을 사용하여 type, hook, lazy hook 을 만들기 위해서는 필수적으로 기입해야 하는 사항입니다.Bad Code
query ($start: DateTime!, $end: DateTime!) { . . . }Good Code
query brandGetPureRevenueByDate($start: DateTime!, $end: DateTime!) { . . . }- query 정상동작 확인#
danbi-apigraphql playground 를 통해서 작성한query,mutation의 정상 동작을 확인 합니다.

- query 작성#graphql playground 를 통해서 정상동작이 확인된
graphql코드를 복사하여 파일을 생성합니다.
AdPureRevenueByDate.graphql
query brandGetPureRevenueByDate($start: DateTime!, $end: DateTime!) {
me {
brand {
pureRevenueByDate(start: $start, end: $end) {
date
pureRevenue
}
}
}
}Type 생성
알아두기
graphql-codegen 을 사용하면 Type, Hook, Lazy Hook 이 자동으로 생성됩니다.이렇게 생성된 Type, Hook, Lazy Hook 은 data type을 고정하거나 react.js 에서 data 를 불러올때 사용됩니다.- Script 실행#
yarn dev:codegen- Script 실행 결과
`ad-fi-admin`
└── . . .
└── src
│ └── Types
│ │ └── index.tsx <= Look Here !!!
│ └── . . .
│ └── Views
│ │ └── . . .
│ │ └── Brand
│ │ │ └── . . .
│ │ │ └── Dashboard
│ │ │ │ └── AdRevenue
│ │ │ │ │ └── AdRevenueByDate.graphql
│ │ │ │ │ └── AdRevenue.tsx
│ │ │ │ │ └── DefaultProps.tsx
│ │ │ │ │ └── index.tsx
│ │ │ │ │ └── types.tsx
│ │ │ │ └── . . .types.tsx 작성
types.tsx 는 총 3개의 모듈을 export 합니다.- Checker#
알아두기
lodash 라이브러리를 사용하여 아래와 같은 상황에서의 예외처리를 진행합니다.- 데이터가 Undefined인 경우 :
isUndefined()
- 데이터가 Null인 경우 :
isNull()
- 데이터가 빈 배열인 경우 :
isEmpty()
import { BrandGetPureRevenueByDateQuery } from "Types";
import { BarDatum } from "@nivo/bar";
import defaultBarData from "./DefaultProps";
import { isUndefined, isNull, isEmpty, compact } from "lodash";
export const barData = (data: BrandGetPureRevenueByDateQuery | undefined) => {
if (isUndefined(data) || isNull(data)) return defaultBarData;
if (isUndefined(data.me) || isNull(data.me))
throw new Error("로그인하지 않았습니다.");
if (
isUndefined(data.me.brand) ||
isNull(data.me.brand) ||
isEmpty(data.me.brand)
)
throw new Error("브랜드 사용자가 아닙니다.");
const {
me: {
brand: [{ pureRevenueByDate }],
},
} = data;
if (isUndefined(pureRevenueByDate) || isNull(pureRevenueByDate))
return defaultBarData;
const result = compact(
pureRevenueByDate.map((item) => {
return {
day: item ? item.date : "_",
revenue: item ? item.pureRevenue : 0,
};
}),
);
return result;
};
. . .type barData
. . .
export type barData = BarDatum[];interface PropTypePresenter 컴포넌트에서props의type으로 사용됩니다.
. . .
export interface PropType {
barData: barData;
}etc .
defaultProps초기값을 설정하여 컴포넌트 렌더링시 컴포넌트가 비어있는것을 방지합니다.
DefaultProp.tsx
export default [
{
day: "_",
revenue: 0,
},
];

