katej927 / dashboard-app

[Team Project]

Home Page:https://dashboard-app-1a.netlify.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

๐Ÿšฉ ํ”„๋กœ์ ํŠธ ์ƒ์„ธ

๐Ÿš€ Deploy Link

Netlify Status

๐Ÿš€ Server Link

๋งค๋“œ์—… ์„ ๋ฐœ ๊ณผ์ œ๋กœ ๊ทธ๋ž˜ํ”„๋ฅผ ์ด์šฉํ•œ ๋งˆ์ผ€ํŒ… ๋ฐ์ดํ„ฐ ์‹œ๊ฐํ™” ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค.

โ˜‘๏ธ ์š”๊ตฌ ์‚ฌํ•ญ

  1. ์ œ์‹œ ๋œ Figma ๋””์ž์ธ๊ณผ ์ฝ”๋ฉ˜ํŠธ์— ๋”ฐ๋ฅธ ํ™”๋ฉด ๋ฐ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  2. ์ž„์˜์ ์œผ๋กœ Fetch ํƒ€์ž„์„ ๋งŒ๋“ค์–ด ๋กœ๋”ฉํ™”๋ฉด ์ง€์›
  3. ํ™”๋ฉด ์ด๋™ ํ›„ ๋ณต๊ท€ ์‹œ ๋งˆ์ง€๋ง‰ ์ƒํƒœ ์œ ์ง€

๐Ÿ‘ค ํŒ€์›, ๊ธฐ๊ฐ„

  • ํŒ€์› : ๋ฐ•์†”์ฐฌ ์‹ ๊ฐ€์€ ์ด๋‹ค์Šฌ ์ •์„ ๋ฏธ ํ™์„ ์˜
  • ๊ธฐ๊ฐ„ : 2022 / 05 / 22 ~ 2022 / 05 / 26

โš’๏ธ ์‚ฌ์šฉ ๊ธฐ์ˆ , ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • react , typescript, scss
  • react-query
  • recoil (์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ)
  • victory
  • react-datepicker
  • react-loading
  • dayjs

๐Ÿ’ก์‹คํ–‰ ๋ฐฉ๋ฒ•

  1. repository clone

    git clone https://github.com/wanted-pre-onboarding-FE-01/dashboard-app-1A.git
  2. ํ•ด๋‹น ํ”„๋กœ์ ํŠธ ํด๋”๋กœ ์ด๋™

    cd dashboard-app-1A
  3. ํ•„์š” package๋“ค ์„ค์น˜

    npm intall 
    or 
    yarn install
  4. ํ”„๋กœ์ ํŠธ ์‹คํ–‰

    npm start

๊ตฌํ˜„ ๊ธฐ๋Šฅ

๋Œ€์‹œ๋ณด๋“œ ํŽ˜์ด์ง€

1. date picker

  • ๊ตฌํ˜„์‚ฌํ•ญ
    • react-datepicker ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ปค์Šคํ…€
    • customHeader๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ˜„์žฌ ์„ ํƒํ•œ(์‹œ์ž‘~๋) ๋‚ ์งœ ํ‘œ์‹œ
    • ์„ ํƒํ•œ ๋‚ ์งœ ์ ์šฉ ์‹œ recoil ์ „์—ญ ์ƒํƒœ๋กœ ์ €์žฅ

2. ํ†ตํ•ฉ ๊ด‘๊ณ  ํ˜„ํ™ฉ

2.1. ๊ด‘๊ณ  ํ˜„ํ™ฉ

  • ๊ตฌํ˜„์‚ฌํ•ญ
    • ์„ ํƒ๋œ ๋‚ ์งœ์˜ ํ†ตํ•ฉ ์ƒํƒœ๋ฅผ ์ œ๊ณต
    • ์„ ํƒ๋œ ๋‚ ์งœ์˜ ๋ฐ์ดํ„ฐ์™€ ์ด์ „ ๋‚ ์งœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ตํ•ด ๋…ธ์ถœ ๋ฐ์ดํ„ฐ ๊ณ„์‚ฐ
      • ๋น„๊ต๋ฅผ ํ†ตํ•ด ์ฆ๊ฐ์—ฌ๋ถ€๋ฅผ ํ‘œํ˜„
    • ๊ฐ’์˜ ๋‹จ์œ„์— ๋”ฐ๋ฅธ Unit ๋ณ€ํ™˜
      • ์˜ˆ๋กœ ๋ฉ”์ธ ๊ฐ’์ด โ€˜์–ต'๋‹จ์œ„ ์ผ ๋•Œ, ์ฆ๊ฐ ์—ฌ๋ถ€์˜ ๊ฐ’ ๋‹จ์œ„๊ฐ€ โ€˜๋งŒ'์ธ ๊ฒฝ์šฐ 0.1์–ต ์ด๋Ÿฐ ์‹์œผ๋กœ ์น˜ํ™˜
  • ์–ด๋ ค์› ๋˜ ์ 
    • ๊ฐ’์˜ ๋‹จ์œ„๋ฅผ ํ†ต์ผ์‹œํ‚ค๊ธฐ ์œ„ํ•œ ์œ ํ‹ธ ์ž‘์„ฑ์„ ์œ„ํ•ด ๊ณตํ†ต์˜ ์ผ€์ด์Šค๋ฅผ ์ฐพ๊ธฐ๊ฐ€ ์–ด๋ ค์› ์Œ
    • ์„ ํƒ๋œ ๋‚ ์งœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ถ€๋ถ„์ด ๋น„๊ต์  ๊น”๊ธˆํ•˜์ง€ ๋ชปํ•จ

2.2. ํ†ตํ•ฉ ๊ด‘๊ณ  ํ˜„ํ™ฉ ๊ทธ๋ž˜ํ”„

  1. ๋“œ๋กญ ๋‹ค์šด
์ฃผ๊ฐ„/์ผ๋ณ„ ๋กœ ์„ ํƒ๊ฐ€๋Šฅ
  • ์ฃผ๊ฐ„

    • ์„ ํƒ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ

      7์ผ ์ดํ•˜์˜ ๊ธฐ๊ฐ„ ์„ ํƒ ์‹œ, ๊ธฐ๊ฐ„์„ ์„ ํƒํ•˜๋Š” ๋“œ๋กญ๋‹ค์šด์„ ๋น„ํ™œ์„ฑํ™” ์‹œ์ผœ ์ฃผ๊ฐ„ ์„ ํƒ ๋ถˆ๊ฐ€

    • ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

      ๋™์ผ ์ฃผ์ฐจ์˜ ํ‰๊ท ์„ ๊ตฌํ•˜์—ฌ ์ฃผ์ฐจ ๋ณ„๋กœ ๋ฐ˜ํ™˜

      1. ์„ ํƒํ•œ ๋‚ ์งœ๋“ค์ด ํ•ด๋‹นํ•˜๋Š” ์›”์˜ ์ฃผ์ฐจ(n์›” n์ฃผ)๋ฅผ ๊ตฌํ•จ

      2. ๋™์ผํ•œ ์ฃผ์— ํ•ด๋‹นํ•˜๋Š” ๋‚ ์งœ๋“ค์˜ ๊ฐฏ์ˆ˜๋ฅผ ๊ตฌํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋Š” ๋ชจ๋‘ ๋”ํ•œ ํ›„ ํ•ด๋‹น ์ฃผ์ฐจ์˜ ๋ฐ์ดํ„ฐ ์ดํ•ฉ/ํ•ด๋‹น ์ฃผ์ฐจ์˜ ๋‚ ์งœ ์ด ๊ฐฏ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์ฃผ์ฐจ๋ณ„ ํ‰๊ท ์„ ๋ฐ˜ํ™˜

  • ์ผ๋ณ„

    ์„ ํƒํ•œ ๊ธฐ๊ฐ„์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ผ๋ณ„๋กœ ๋ณด์—ฌ์ฃผ๋˜ x์ถ•์€ ๊ธฐ๋ณธ์ ์œผ๋กœ tickCount ๊ฐ€ 7๋กœ ์„ค์ •๋˜์–ด ์‹ค์ œ ์‚ฌ์ดํŠธ์™€ ๋™์ผํ•œ x์ถ•์˜ ๊ฐฏ์ˆ˜ ์ถœํ˜„

์„ ํƒ ์‹œ ๋ฐ˜ํ™˜ํ•  ๋ฐ์ดํ„ฐ ๊ณ„์‚ฐ

3๊ฐ€์ง€์˜ ๋“œ๋กญ๋‹ค์šด์—์„œ ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด ํ•ด๋‹น ์˜ต์…˜์— ๋Œ€ํ•˜์—ฌ ๊ทธ๋ž˜ํ”„์— ๊ทธ๋ ค์ค„ ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต

๋‹จ์œ„ ๊ฐ’ (%, ์›, ํšŒ), ๊ทธ๋ž˜ํ”„์— ๋ณด์—ฌ์ค„ ๋ฐ์ดํ„ฐ ๋ฐฐ์—ด, y์ถ• ๊ฐ’ (y๊ฐ’ ์ค‘์˜ ์ตœ๋Œ€๊ฐ’) ๋“ฑ

const formatReturnData = (unitVal: string, integratedAdInfo: IDay[], btn: Btn, periodOption: PeriodOptions) => {
  const formatedData =
    periodOption === '์ผ๊ฐ„' ? convertDailyData(integratedAdInfo, btn) : convertWeeklyData(integratedAdInfo, btn);
  return {
    unit: unitVal,
    formatedData,
    maxValue: formatedData && Math.max(...formatedData.map((obj: IFormatedData) => obj.y)),
  };
};

export const convertData = (integratedAdInfo: IDay[], btnOption: PrimaryOptions, periodOption: PeriodOptions) => {
  if (btnOption === 'ROAS') return formatReturnData('%', integratedAdInfo, 'roas', periodOption);
  if (btnOption === '๊ด‘๊ณ ๋น„') return formatReturnData('์›', integratedAdInfo, 'cost', periodOption);
  if (btnOption === 'ํด๋ฆญ ์ˆ˜') return formatReturnData('ํšŒ', integratedAdInfo, 'click', periodOption);
  if (btnOption === '๋…ธ์ถœ ์ˆ˜') return formatReturnData('ํšŒ', integratedAdInfo, 'imp', periodOption);
  if (btnOption === '๋งค์ถœ') return formatReturnData('์›', integratedAdInfo, 'convValue', periodOption);
  if (btnOption === '์ „ํ™˜ ์ˆ˜') return formatReturnData('ํšŒ', integratedAdInfo, ['cvr', 'click'], periodOption);
  return undefined;
};
์ฒซ ๋ฒˆ์งธ ๋“œ๋กญ๋‹ค์šด์—์„œ ์„ ํƒํ•œ ์ง€ํ‘œ๋ฅผ ๋‘๋ฒˆ์งธ ๋“œ๋กญ๋‹ค์šด(์˜ต์…”๋„)์—์„œ ์„ ํƒ ๋ถˆ๊ฐ€

filter ๋ฅผ ํ™œ์šฉํ•ด์„œ ์ œ์ž‘

2๊ฐ€์ง€ ๋“œ๋กญ๋‹ค์šด์ด ๋ชจ๋‘ ์„ ํƒ๋  ๊ฒฝ์šฐ, ๊ทธ๋ž˜ํ”„ ์šฐ์ธก์— y2 ๋ˆˆ๊ธˆ์ž ์ œ๊ณต

y2์ถ•์— ํ• ๋‹นํ•  VictoryAxis์™€ VictoryLine ๋ฅผ key๋กœ ์—ฐ๊ฒฐํ•˜์—ฌ ์ถœํ˜„์‹œํ‚ด

  1. ๊ทธ๋ž˜ํ”„
์ˆซ์ž ๋‹จ์œ„ ๋ณ€ํ™˜
  • ๊ฐ’์ด 1๋งŒ ์ดํ•˜์ผ ๊ฒฝ์šฐ

    ๋ฐ˜์˜ฌ๋ฆผ์œผ๋กœ ์†Œ์ˆ˜์  ์ œ๊ฑฐ ํ›„, ์ฒœ ๋‹จ์œ„๋งˆ๋‹ค ์ฝค๋งˆ(,) ํ˜•์„ฑ

  • ๊ฐ’์ด 1๋งŒ~1์กฐ ์ผ ๊ฒฝ์šฐ

    ํ•œ๊ธ€ ๋‹จ์œ„๋กœ ๋ณ€ํ™˜ (ex. 5๋ฐฑ๋งŒ์›)

export const convertNumToUnit = (num: number) => {
  if (num < 10000) {
    return Math.round(num)
      .toString()
      .replace(/\B(?=(\d{3})+(?!\d))/g, ',');
  }

  const transUnit = [
    { value: 1e12, symbol: '์กฐ' },
    { value: 1e11, symbol: '์ฒœ์–ต' },
    { value: 1e10, symbol: '๋ฐฑ์–ต' },
    { value: 1e9, symbol: '์‹ญ์–ต' },
    { value: 1e8, symbol: '์–ต' },
    { value: 1e7, symbol: '์ฒœ๋งŒ' },
    { value: 1e6, symbol: '๋ฐฑ๋งŒ' },
    { value: 1e5, symbol: '์‹ญ๋งŒ' },
    { value: 1e4, symbol: '๋งŒ' },
    { value: 1e3, symbol: '์ฒœ' },
  ];
  let i;
  for (i = 0; i < transUnit.length; i += 1) {
    if (num >= transUnit[i].value) {
      return (num / transUnit[i].value).toFixed(1).replace(/\.?0+$/, '') + transUnit[i].symbol;
    }
  }
  return num;
};
ํˆดํŒ ์ œ๊ณต

๊ทธ๋ž˜ํ”„์˜ ์„ ์„ hoverํ•˜๋ฉด ํˆดํŒ ํ™•์ธ ๊ฐ€๋Šฅ

3. ๋งค์ฒด ํ˜„ํ™ฉ

3.1. ๋งค์ฒด ํ˜„ํ™ฉ ๊ทธ๋ž˜ํ”„

2022-05-25.11.28.19.mov
  • ๊ตฌํ˜„ ์‚ฌํ•ญ

    • service/fetchMediaChannelData : ์„ ํƒ๋œ ๋‚ ์งœ์— ํ•ด๋‹นํ•˜๋Š” ๋ฐ์ดํ„ฐ api ํ˜ธ์ถœ
    • util/formatMediaChannelGraph : ๋ฐ˜ํ™˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ž˜ํ”„ ํ˜•์‹์— ๋งž๊ฒŒ ๊ณ„์‚ฐํ•˜์—ฌ ๋ฐ˜ํ™˜
    • ์†Œ์ˆ˜์  3์ž๋ฆฌ๋ฒ„๋ฆผ
    • ๊ฐ ํ•ญ๋ชฉ ๋ณ„ ๊ฐ’ tooltip์— ํ‘œ์‹œ
    • ๊ทธ๋ž˜ํ”„ ๋ Œ๋”๋ง ์‹œ ์• ๋‹ˆ๋ฉ”์ด์…˜
  • ์–ด๋ ค์› ๋˜ ์ 

    • y์ถ• ํ•ญ๋ชฉ๋“ค์˜ ๋ˆ„์  ๊ฐ’์„ ๊ตฌํ•œ ํ›„ ์ „์ฒด ๋ฐ์ดํ„ฐ์— ํ•ด๋‹นํ•˜๋Š” ๋น„์œจ์„ ๊ณ„์‚ฐํ•˜๋Š” ๊ฒƒ,
    • ํˆดํŒ์—๋Š” ๋น„์œจ์ด ์•„๋‹Œ ์‹ค์ œ ๋ฐ์ดํ„ฐ ๊ฐ’์„ ๋„ฃ๋Š” ๊ฒƒ์ด ๋ณต์žกํ–ˆ๋‹ค.

3.2. ๋งค์ฒด ํ˜„ํ™ฉ ํ…Œ์ด๋ธ” ์ฐจํŠธ

  • ๊ตฌํ˜„ ์‚ฌํ•ญ
    • util/formatMediaChannelTableData ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋ฐ›์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ Œ๋”๋ง
    • ๋ชจ๋‹ˆํ„ฐ ํฌ๊ธฐ์— ๋”ฐ๋ฅธ ํšก์Šคํฌ๋กค ์‚ฝ์ž…

๊ด‘๊ณ ๊ด€๋ฆฌ ํŽ˜์ด์ง€

1. ๊ด‘๊ณ  ๋ฐ์ดํ„ฐ ๋ Œ๋”๋ง

2022-05-26.11.36.23.mov
  • ๊ตฌํ˜„ ์‚ฌํ•ญ
    • react-query๋ฅผ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜จ ํ›„, ํ•ด๋‹น ๋ฐ์ดํ„ฐ ๋ Œ๋”๋ง.
    • ๋ฐ›์•„ ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๋“œ๋กญ๋‹ค์šด์˜ ํด๋ฆญํ•œ item ๊ฐ’์— ๋งž๊ฒŒ ํ•„ํ„ฐ๋ง.

About

[Team Project]

https://dashboard-app-1a.netlify.app/


Languages

Language:TypeScript 65.7%Language:SCSS 33.0%Language:HTML 1.2%Language:JavaScript 0.1%