최종 프로젝트 회고 #8 - 복약 전체 리스트 내 모달

DO YEON KIM·2024년 10월 22일
0


오늘은 마이페이지 내에 있는 전체 복약 리스트 내에 있는 모달 창에 대해 설명하겠다. 약 카드를 클릭 시 약 정보를 보여주고, 수정 및 삭제가 가능하도록 하였다.


🟡 폴더 구조


🟡 src\components\templates\mypage\myPageModal\MediModal.tsx

import React from "react";
import Modal from "react-modal";
import { FaTimes, FaEdit } from "react-icons/fa";
import { useMediaQuery } from 'react-responsive'; // 모바일 화면 크기 체크

interface MediRecord {
  id: string;
  medi_name: string;
  medi_nickname: string;
  times: {
    morning: boolean;
    afternoon: boolean;
    evening: boolean;
  };
  notes: string;
  start_date: string;
  end_date: string;
  created_at: string;
  user_id: string;
  itemImage?: string | null;
  notification_time?: string[];
  day_of_week?: string[];
  repeat?: boolean;
}

interface MediModalProps {
  isOpen: boolean;
  onRequestClose: () => void;
  mediRecord: MediRecord;
  onEditClick: () => void;
}

const MediModal: React.FC<MediModalProps> = ({
  isOpen,
  onRequestClose,
  mediRecord,
  onEditClick,
}) => {
  const isMobile = useMediaQuery({ query: '(max-width: 768px)' }); // 모바일 화면 크기 체크

  const formatTimes = () => {
    const times = [];
    if (mediRecord.times.morning) times.push("아침");
    if (mediRecord.times.afternoon) times.push("점심");
    if (mediRecord.times.evening) times.push("저녁");
    return times.join(", ");
  };

  const renderContent = () => (
    <div className={`bg-white rounded-md shadow-lg p-6 ${isMobile ? 'mx-4 my-4' : 'w-full max-w-[432px] mx-auto'} ${isMobile ? 'max-w-full' : ''} relative`}>
      {/* X 버튼 추가 */}
      <button
        onClick={onRequestClose}
        className="absolute top-4 right-4 text-gray-700 hover:text-gray-900 transition-colors duration-200"
      >
        <FaTimes className="text-xl" />
      </button>
      {isMobile ? (
        <>
          <div className="flex justify-between items-center px-4 py-3 bg-gray-100 border-b border-gray-300">
            <button
              type="button"
              onClick={onRequestClose}
              className="text-gray-500 hover:text-gray-700"
            >
              <FaTimes className="text-xl" />
            </button>
            <span className="text-gray-800 text-lg font-bold">나의 약 수정</span>
            <button
              type="button"
              onClick={onEditClick}
              className="text-blue-500 hover:text-blue-700"
            >
              <FaEdit className="text-xl" />
            </button>
          </div>
          <div className="p-4 bg-white rounded-md shadow-lg" style={{ width: '332px', height: '345px' }}>
            <h2 className="text-[18px] font-bold mb-2 text-brand-gray-800">{mediRecord.medi_nickname}</h2>
            <div className="text-[14px] font-bold mb-4 text-brand-gray-800">{mediRecord.medi_name}</div>
            <div className="text-[14px] font-bold mb-4 text-brand-gray-600">복용 날짜: <span className="font-bold text-brand-gray-600">{mediRecord.start_date} ~ {mediRecord.end_date}</span></div>
            
            <div className="text-[14px] font-bold mb-4 text-brand-gray-600">복용 알람: <span className="text-brand-gray-800">{mediRecord.notification_time?.[0] || '설정 안 함'}</span></div>
            <div className="flex space-x-2 mb-4">
              {['월', '화', '수', '목', '금', '토', '일'].map(day => (
                <div key={day} className={`w-8 h-8 flex items-center justify-center rounded-full ${mediRecord.day_of_week?.includes(day) ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-700'}`}>
                  {day}
                </div>
              ))}
            </div>
            <div className="text-[14px] font-bold mb-4 text-brand-gray-600">메모:</div>
            <div className="border rounded p-2 text-brand-gray-800">{mediRecord.notes}</div>
          </div>
        </>
      ) : (
        <>
          <button
            type="button"
            onClick={onRequestClose}
            className="absolute top-4 right-4 text-gray-500 hover:text-gray-700"
          >
            <FaTimes className="text-xl" />
          </button>
          <h2 className="text-[16px] font-bold mb-5">{mediRecord.medi_nickname}</h2>
          <div className="flex flex-col space-y-6 mb-10">
            <div className="flex items-center">
              <span className="w-20 text-brand-gray-600">약 정보</span>
              <span className="px-2 text-brand-gray-600">|</span>
              <span className="text-brand-primary-500">{mediRecord.medi_name}</span>
            </div>
            <div className="flex items-center">
              <span className="w-20 text-brand-gray-600">복용시간대</span>
              <span className="px-2 text-brand-gray-600">|</span>
              <span className="text-brand-gray-1000">{formatTimes()}</span>
            </div>
            <div className="flex items-center">
              <span className="w-20 text-brand-gray-600">복용기간</span>
              <span className="px-2 text-brand-gray-600">|</span>
              <span className="text-brand-gray-1000">
                {mediRecord.start_date} ~ {mediRecord.end_date}
              </span>
            </div>
            <div className="flex items-center">
              <span className="w-20 text-brand-gray-600">메모</span>
              <span className="px-2 text-brand-gray-600">|</span>
              <span className="text-brand-gray-1000">{mediRecord.notes}</span>
            </div>
          </div>
          <div className="flex justify-center mt-4">
            <button
              type="button"
              onClick={onEditClick}
              className="w-[107px] h-[40px] bg-brand-primary-500 text-white rounded-md flex items-center justify-center"
            >
              <FaEdit className="mr-2" /> 편집
            </button>
          </div>
        </>
      )}
    </div>
  );

  return isMobile ? (
    <div className="flex flex-col h-screen bg-gray-50">
      {renderContent()}
    </div>
  ) : (
    <Modal
      isOpen={isOpen}
      onRequestClose={onRequestClose}
      contentLabel="Medication Details"
      className="fixed inset-0 flex items-center justify-center z-50 px-4 py-6"
      overlayClassName="fixed inset-0 bg-gray-900 bg-opacity-75 z-40"
    >
      {renderContent()}
    </Modal>
  );
};

export default MediModal;

import React from "react";
import Modal from "react-modal";
import { FaTimes, FaEdit } from "react-icons/fa";
import { useMediaQuery } from 'react-responsive'; // 모바일 화면 크기 체크
  • FaTimes, FaEdit:

Font Awesome 아이콘을 사용해 닫기(X)와 편집 아이콘을 표시.

  • useMediaQuery:

반응형 디자인에서 모바일 화면 크기를 체크하는 데 사용

프로젝트 회고를 하면서 느끼는 건 반응형 참 일관성 없이 이것저것 가져다 쓴 거 같다.. 아무래도 기간이 촉박했던 게 티가 나는 프로젝트.

이전에 리뷰해서 썼던 건 간단하게 적거나 넘어가도록 하겠다.


const isMobile = useMediaQuery({ query: '(max-width: 768px)' }); // 모바일 화면 크기 체크

seMediaQuery를 사용해 화면 크기가 768px 이하인 경우 isMobile이 true로 설.

즉, 모바일 기기인지 여부를 확인.


const formatTimes = () => {
  const times = [];
  if (mediRecord.times.morning) times.push("아침");
  if (mediRecord.times.afternoon) times.push("점심");
  if (mediRecord.times.evening) times.push("저녁");
  return times.join(", ");
};

아점저 복용 여부에 따라 배열에 추가.


{/* X 버튼 추가 */}
<button
  onClick={onRequestClose}
  className="absolute top-4 right-4 text-gray-700 hover:text-gray-900 transition-colors duration-200"
>
  <FaTimes className="text-xl" />
</button>

FaTimes는 닫기 아이콘.


다음 회차엔 편집 모달에 대해 작성해보도록 하겠다.

profile
프론트엔드 개발자를 향해서

0개의 댓글