ProjectModal.tsx 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import React, { useState } from 'react';
  2. import { MajorProject } from "@/data/project";
  3. import IndicatorDots from "@/components/common/IndicatorDots";
  4. interface CommonModalProps {
  5. isOpen: boolean;
  6. onClose: () => void;
  7. item: MajorProject | null;
  8. }
  9. export const ProjectModal: React.FC<CommonModalProps> = ({ isOpen, onClose, item }) => {
  10. const [currentIndex, setCurrentIndex] = useState(0);
  11. if (!isOpen || !item) return null;
  12. const images = item.subImgUrl ?? [];
  13. const handlePrev = () => {
  14. if (images.length === 0) return;
  15. setCurrentIndex((prev) => (prev === 0 ? images.length - 1 : prev - 1));
  16. };
  17. const handleNext = () => {
  18. if (images.length === 0) return;
  19. setCurrentIndex((prev) => (prev === images.length - 1 ? 0 : prev + 1));
  20. };
  21. return (
  22. <div
  23. className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"
  24. onClick={onClose}
  25. >
  26. <div
  27. className="relative bg-white w-[1222px] h-[901px] p-10 rounded-lg overflow-hidden"
  28. onClick={(e) => e.stopPropagation()}
  29. >
  30. {/* 닫기 버튼 */}
  31. <button
  32. className="absolute top-6 right-6 text-black text-2xl font-light cursor-pointer"
  33. onClick={onClose}
  34. >
  35. ×
  36. </button>
  37. {/* 제목 및 정보 */}
  38. <div className="mb-6">
  39. <h2 className="text-4xl font-extrabold mb-2">{item.title}</h2>
  40. <div className="text-base font-light space-y-1">
  41. <p>발주처 : {item.client}</p>
  42. <p>계약금액 : {item.contractAmount}</p>
  43. <p>공사기간 : {item.period}</p>
  44. </div>
  45. </div>
  46. {/* 이미지 및 컨트롤 */}
  47. <div className="relative w-full h-[578px] flex justify-center items-center">
  48. {images.length > 0 && (
  49. <img
  50. src={images[currentIndex]}
  51. alt={`image-${currentIndex}`}
  52. className="rounded max-h-full object-contain"
  53. />
  54. )}
  55. <button
  56. onClick={handlePrev}
  57. className="absolute left-4 top-1/2 -translate-y-1/2 bg-gray-300/75 w-14 h-14 text-2xl cursor-pointer"
  58. >
  59. {'<'}
  60. </button>
  61. <button
  62. onClick={handleNext}
  63. className="absolute right-4 top-1/2 -translate-y-1/2 bg-gray-300/75 w-14 h-14 text-2xl cursor-pointer"
  64. >
  65. {'>'}
  66. </button>
  67. </div>
  68. {/* 페이지 인디케이터 */}
  69. <div className="flex justify-center gap-2 mt-4">
  70. <IndicatorDots
  71. count={images.length}
  72. activeIndex={currentIndex}
  73. onClick={(index) => setCurrentIndex(index)}
  74. activeColorClass="bg-blue-900"
  75. inactiveColorClass="bg-blue-900/20"
  76. />
  77. </div>
  78. </div>
  79. </div>
  80. );
  81. };