본문 바로가기
업무 회고

2025년 4월 개발 회고

by KUROMI98 2025. 5. 2.
  • 게시글 수정 페이지에서, 새로 수정할 값을 입력하고 다른 탭 갔다 돌아온 경우, 새로 수정한 값들이 없어지고 기존에 있던 데이터로 덮어씌워지는 이슈가 있었다. 의존성 배열에 값이 두 개가 들어가 있어서 한 값 때문에 실행되던 함수가 다른 값에 영향을 줘서 다른 페이지를 갔다 올 때마다 새로고침이 되던 거였다. 의존성 배열을 분리해 해결했다.
  • 안내 팝업을 띄우고, 유저가 확인을 누르면 일시적으로 팝업이 닫히게, 유저가 다시 보지 않기를 누르면 localStorage를 사용해 팝업을 닫고 영원히 보여주지 않게끔 함
    const [showPopup, setShowPopup] = useState(false);

    const handleCloseForever = () => {
        localStorage.setItem('hidePopupForever', 'true');
        setShowPopup(false);
    };

    useEffect(()=>{
        const hide = localStorage.getItem('hidePopupForever');
        if (user && !hide) {
            setShowPopup(true);
        }
    },[])
  • MUI Datagrid를 사용하면서 data를 flat하게 만들어서, header에 맞춘 표 형태로 데이터를 보여줄 수 있게끔 하기
    const flatRows = data?.participants?.map((item) => ({
        id: item.id,
        galleryName: item.gallery?.name ?? '',
        manager: '', // manager 없음..
        contact: item.gallery?.phone ?? '',
        email: item.gallery?.email ?? '',
        address: `${item.gallery?.address1 ?? ''} ${item.gallery?.address2 ?? ''}`,
      }))
    setRows(flatRows)
  • pagination 하기
  • MUI Datagrid 엑셀 다운로드가 가능하게끔 하기
    const [rows, setRows] = useState([])
    const columns = [
        { field: 'galleryName', headerName: t('artfair:galleryName'), width: '225', align: 'center', headerAlign: 'center'},
        { field: 'manager', headerName: t('artfair:galleryManager'), width: '100', align: 'center', headerAlign: 'center'},
        { field: 'contact', headerName: t('artfair:galleryContact'), width: '140', align: 'center', headerAlign: 'center'},
        { field: 'email', headerName: t('artfair:galleryEmail'), width: '190', align: 'center', headerAlign: 'center'},
        { field: 'address', headerName: t('artfair:galleryAddress'), width: '285', align: 'center', headerAlign: 'center'}
    ]
...

    const excelDownloader = async () => {
      const workbook = new ExcelJS.Workbook();
      const worksheet = workbook.addWorksheet('Exhibitor List');
    
      worksheet.columns = [
        { header: 'Exhibitor', key: 'galleryName', width: 30 },
        { header: 'Manager', key: 'manager', width: 15 },
        { header: 'Phone', key: 'contact', width: 20 },
        { header: 'E-mail', key: 'email', width: 30 },
        { header: 'Address', key: 'address', width: 40 },
      ];
    
      rows.forEach((row) => {
        worksheet.addRow({
          galleryName: row.galleryName,
          manager: row.manager,
          contact: row.contact,
          email: row.email,
          address: row.address,
        });
      });
    
      worksheet.getRow(1).font = { bold: true };

      const buffer = await workbook.xlsx.writeBuffer();
      const blob = new Blob([buffer], { 
        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' 
      });
      saveAs(blob, 'Exhibitors_List_by_ArtSpoon.xlsx');
    };
...
<DataGridPremium
              loading={loading}
              apiRef={apiRef}
              rows={rows}
              columns={columns}
              sx={{
                backgroundColor: 'white',
                minHeight: 300,
              }}
              pagination
              initialState={{
                  pagination: {
                      paginationModel: { pageSize: 15, page: 0 },
                  },
              }}
              slots={{
                noRowsOverlay: () => (
                  <Box
                    sx={{
                      display: 'flex',
                      justifyContent: 'center',
                      alignItems: 'center',
                      height: '100%',
                    }}
                  >
                    <div style={{display:"flex", justifyContent:"center", alignItems:"center", gap:"10px", fontSize:"16px", fontWeight:"500", fontFamily:"pretendard", color: "rgba(0, 0, 0, 0.87)"}}>
                      <Image src={'/images/noDataIcon.webp'} width={20} height={20} />
                      {t('artfair:noExhibitors')}
                    </div>
                  </Box>
                ),
              }}
              onCellClick={(e) => handleRouteToDetail(e.id)}
            />
  • 캘린더 컴포넌트 만들기
import styles from 'components/plas-calendar.module.scss'
import dayjs from 'dayjs'
import { useState } from 'react'
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';

const daysOfWeek = ['일', '월', '화', '수', '목', '금', '토']

export default function PlasCalendar() {
  const [currentDate, setCurrentDate] = useState(dayjs())
  const year = currentDate.year()
  const month = currentDate.month()

  const startOfMonth = dayjs().year(year).month(month).startOf('month')
  const endOfMonth = dayjs().year(year).month(month).endOf('month')
  const startDay = startOfMonth.day()
  const totalDays = endOfMonth.date()

  const today = dayjs()
  const days = []

  // 이전 달 날짜 추가
  const prevMonthDate = currentDate.subtract(1, 'month')
  const prevMonthDays = prevMonthDate.daysInMonth()
  for (let i = startDay - 1; i >= 0; i--) {
    days.push({
      date: dayjs().year(prevMonthDate.year()).month(prevMonthDate.month()).date(prevMonthDays - i),
      isOtherMonth: true
    })
  }

  // 이번 달 날짜 추가
  for (let i = 1; i <= totalDays; i++) {
    days.push({
      date: dayjs().year(year).month(month).date(i),
      isOtherMonth: false
    })
  }

  // 다음 달 날짜 추가 (총 42칸 맞춤)
  const nextMonthDate = currentDate.add(1, 'month')
  const remaining = 42 - days.length
  for (let i = 1; i <= remaining; i++) {
    days.push({
      date: dayjs().year(nextMonthDate.year()).month(nextMonthDate.month()).date(i),
      isOtherMonth: true
    })
  }

  const prevMonth = () => setCurrentDate(currentDate.subtract(1, 'month'))
  const nextMonth = () => setCurrentDate(currentDate.add(1, 'month'))

  return ( 
    <div className={styles.calendarRoot}>
        <div className={styles.calendarContainer}>
          <div className={styles.calendarHeader}>
            <span>{year}년 {month + 1}월</span>
            <div className={styles.calendarNav}>
              <button onClick={prevMonth}><ArrowBackIosIcon/></button>
              <button onClick={nextMonth}><ArrowForwardIosIcon/></button>
            </div>
          </div>
          <div className={styles.calendarGrid}>
              {daysOfWeek.map(day => (
              <div key={day} className={styles.dayLabel}>{day}</div>
              ))}
              {days.map(({ date, isOtherMonth }, idx) => {
              const day = date.date()
              const isToday = today.isSame(date, 'day')

              const isTargetMonth = date.year() === 2025 && date.month() === 4
              const isStart = isTargetMonth && day === 22
              const isEnd = isTargetMonth && day === 25
              const isBetween = isTargetMonth && (day === 23 || day === 24)

              const textClass = isOtherMonth ? styles.otherMonth : ''

              if (isStart) {
                  return (
                  <div key={idx} className={styles.rangeStartBox}>
                      <div className={styles.rangeCircle}>
                      <span className={textClass}>{day}</span>
                      </div>
                  </div>
                  )
              }

              if (isEnd) {
                  return (
                  <div key={idx} className={styles.rangeEndBox}>
                      <div className={styles.rangeCircle}>
                      <span className={textClass}>{day}</span>
                      </div>
                  </div>
                  )
              }

              if (isBetween) {
                  return (
                  <div key={idx} className={styles.rangeMiddleBox}>
                      <span className={textClass}>{day}</span>
                  </div>
                  )
              }

              return (
                  <div key={idx} className={`${styles.calendarDay} ${isToday ? styles.calendarToday : ''}`}>
                  <span className={textClass}>{day}</span>
                  </div>
              )
              })}
          </div>
        </div>
    </div>
  )
}

'업무 회고' 카테고리의 다른 글

배열에서 원소만 추출한 후 중복 제거하기  (1) 2025.07.08
2025년 5월 개발 회고  (1) 2025.05.30
2025년 3월 개발 회고  (1) 2025.05.02
2025년 2월 개발 회고  (0) 2025.03.04
2025년 1월 개발 회고  (0) 2025.02.18

댓글