فهرست منبع

사업소개 디테일

home 6 ماه پیش
والد
کامیت
9e26e07610
4فایلهای تغییر یافته به همراه103 افزوده شده و 79 حذف شده
  1. BIN
      public/image/business/sub/ICT.jpg
  2. 20 24
      src/components/common/IndicatorDots.tsx
  3. 9 5
      src/data/business.ts
  4. 74 50
      src/pages/business/Sections.tsx

BIN
public/image/business/sub/ICT.jpg


+ 20 - 24
src/components/common/IndicatorDots.tsx

@@ -1,45 +1,41 @@
 import React from 'react';
 
 interface IndicatorDotsProps {
-  /**
-   * 전체 인디케이터(dot)의 개수
-   * 예: 이미지 개수, 슬라이드 개수 등
-   */
+  /** 전체 인디케이터(dot)의 개수 */
   count: number;
 
-  /**
-   * 현재 활성화된 인디케이터의 인덱스
-   * 예: 현재 보이는 이미지나 슬라이드의 순번
-   */
+  /** 현재 활성화된 인디케이터의 인덱스 */
   activeIndex: number;
 
-  /**
-   * 인디케이터(dot)를 클릭했을 때 호출되는 콜백 함수
-   * 클릭된 인덱스가 인자로 전달됨
-   */
+  /** 인디케이터(dot)를 클릭했을 때 호출되는 콜백 함수 */
   onClick: (index: number) => void;
 
-  /**
-   * 인디케이터를 감싸는 최상위 div의 추가 클래스명
-   * 위치 조정 등 외부 스타일을 조정할 때 사용
-   */
+  /** 인디케이터를 감싸는 최상위 div의 추가 클래스명 */
   className?: string;
+
+  /** 선택된 dot의 배경색 클래스 */
+  activeColorClass?: string;
+
+  /** 선택되지 않은 dot의 배경색 클래스 */
+  inactiveColorClass?: string;
 }
 
-/**
- * 범용 인디케이터(Dots) 컴포넌트
- * - 사용자가 현재 보고 있는 항목을 시각적으로 표시하며
- * - 클릭 시 해당 항목으로 이동하는 기능을 제공함
- */
-const IndicatorDots: React.FC<IndicatorDotsProps> = ({count, activeIndex, onClick, className = '',}) => {
+const IndicatorDots: React.FC<IndicatorDotsProps> = ({
+                                                       count,
+                                                       activeIndex,
+                                                       onClick,
+                                                       className = '',
+                                                       activeColorClass = 'bg-white',
+                                                       inactiveColorClass = 'bg-white/50',
+                                                     }) => {
   return (
     <div className={`inline-flex gap-2 ${className}`}>
-      {Array.from({length: count}).map((_, index) => (
+      {Array.from({ length: count }).map((_, index) => (
         <div
           key={index}
           onClick={() => onClick(index)}
           className={`w-2 h-2 relative select-none ${
-            index === activeIndex ? 'bg-white' : 'bg-white/50'
+            index === activeIndex ? activeColorClass : inactiveColorClass
           } rounded cursor-pointer`}
         />
       ))}

+ 9 - 5
src/data/business.ts

@@ -4,19 +4,23 @@ export interface BusinessItem {
   label: string;
   description?: string;
   description2?: string;
-  image: string;
   url: string;
+  image: string;
+  subImages?: string[];
 }
 
 const businessSections: BusinessItem[] = [
   {
     label: "정보통신공사",
-    description:
-      "지금의 반도산전이 있기까지\n 정보통신공사로 시작한 반도산전 30년의 탄탄한 시공능력과 도전정신이 있습니다.",
-    description2:
-      "정보통신공사란?\n정보통신 시스템 및 관련 설비를 설치·이전·변경·철거하거나,\n유지·보수하는 공사를 말합니다. 이는 전기공사와는 다르며,\n정보통신기술(IT) 기반의 인프라 구축에 초점을 둔 공사입니다.",
+    description: "지금의 반도산전이 있기까지\n 정보통신공사로 시작한 반도산전 30년의 탄탄한 시공능력과 도전정신이 있습니다.",
+    description2: "정보통신공사란?\n정보통신 시스템 및 관련 설비를 설치·이전·변경·철거하거나,\n유지·보수하는 공사를 말합니다. 이는 전기공사와는 다르며,\n정보통신기술(IT) 기반의 인프라 구축에 초점을 둔 공사입니다.",
     image: `${BUSINESS_IMAGE_PREFIX}/정보통신공사.jpg`,
     url: "/business/communication",
+    subImages: [
+      "/image/business/sub/ICT.jpg",
+      "/image/business/sub/ICT.jpg",
+      "/image/business/sub/ICT.jpg",
+    ]
   },
   {
     label: "전기설비공사",

+ 74 - 50
src/pages/business/Sections.tsx

@@ -1,21 +1,52 @@
-import React, { useState } from 'react';
+import React, {useState} from 'react';
 import businessItems from "@/data/business";
-import type { BusinessItem } from "@/data/business";
+import type {BusinessItem} from "@/data/business";
 import DarkOverlay from "@/components/common/DarkOverlay";
+import IndicatorDots from "@/components/common/IndicatorDots";
 
-
-const Landmarks = () => {
+const Sections = () => {
   const [selectedItem, setSelectedItem] = useState<BusinessItem | null>(null);
+  const [currentSubIndex, setCurrentSubIndex] = useState(0);
+
+  const handleSelectItem = (item: BusinessItem) => {
+    setSelectedItem(item);
+    setCurrentSubIndex(0); // 새 항목 선택 시 초기화
+  };
+
+  const handlePrev = () => {
+    const images = selectedItem?.subImages;
+    if (!images) return;
+
+    setCurrentSubIndex((prev) =>
+      prev === 0 ? images.length - 1 : prev - 1
+    );
+  };
+
+  const handleNext = () => {
+    const images = selectedItem?.subImages;
+    if (!images) return;
+
+    setCurrentSubIndex((prev) =>
+      prev === images.length - 1 ? 0 : prev + 1
+    );
+  };
+
+  const handleDotClick = (index: number) => {
+    setCurrentSubIndex(index);
+  };
+
+  const subImages = selectedItem?.subImages;
 
   return (
     <div className="relative h-[1453px] px-6 py-10 flex-col">
+      {/* 썸네일 선택 */}
       <div className="relative grid grid-cols-5 gap-2 w-7xl mx-auto h-44 bg-white">
         {businessItems.map((item, index) => (
           <div
             key={index}
             className="relative bg-gray-100 bg-cover bg-center cursor-pointer"
             style={{backgroundImage: `url(${item.image})`}}
-            onClick={() => setSelectedItem(item)}
+            onClick={() => handleSelectItem(item)}
           >
             <DarkOverlay/>
             <div className="relative p-2">
@@ -25,81 +56,74 @@ const Landmarks = () => {
         ))}
       </div>
 
-
       {selectedItem && (
         <>
           {/* 타이틀 */}
           <div className="h-60 flex flex-col my-10 justify-center items-center gap-9">
+            <div className="text-center text-neutral-800 text-5xl font-extrabold">{selectedItem.label}</div>
             <div
-              className="text-center justify-center text-neutral-800 text-5xl font-extrabold font-['Inter'] leading-10">{selectedItem?.label}</div>
-            <div
-              className="text-center justify-center text-neutral-800 text-2xl font-medium font-['Inter'] leading-10 whitespace-pre-line">{selectedItem?.description}</div>
+              className="text-center text-neutral-800 text-2xl font-medium whitespace-pre-line">{selectedItem.description}</div>
           </div>
 
           {/* 그림 및 설명 */}
           <div className="max-w-7xl mx-auto h-96 bg-zinc-300/75 flex">
             <div className="w-1/2 h-full">
-              <img
-                className="w-full h-full object-cover"
-                src={selectedItem.image}
-                alt="image"
-              />
+              <img className="w-full h-full object-cover" src={selectedItem.image} alt="image"/>
             </div>
             <div className="w-1/2 flex items-center justify-center px-4">
-              <div className="text-black text-xl font-light font-['Noto_Sans_KR'] leading-9 whitespace-pre-line">
-                {selectedItem?.description2}
+              <div className="text-black text-xl font-light leading-9 whitespace-pre-line">
+                {selectedItem.description2}
               </div>
             </div>
           </div>
 
           {/* 중간 타이틀 */}
           <div className="h-28 flex flex-col justify-center my-10 items-center gap-9">
-            <div
-              className="text-center justify-center text-neutral-800 text-2xl font-medium font-['Inter'] leading-10">대표공사실적
-            </div>
+            <div className="text-center text-neutral-800 text-2xl font-medium">대표공사실적</div>
           </div>
 
-          {/* 그외 밑에 */}
-          <div className="relative max-w-7xl mx-auto h-128 justify-start items-start">
-            <div className="flex items-end w-full h-full px-4 py-3 bg-gradient-to-b from-white/0 to-black/80 gap-0.5">
-              <div className="text-white text-2xl font-bold font-['Inter']">
-                BNK 경남은행 전산 & 데이터센터
+          {Array.isArray(subImages) && subImages.length > 0 ? (
+            <div
+              className="relative max-w-7xl mx-auto h-128 bg-cover bg-center transition-all duration-500"
+              style={{backgroundImage: `url(${subImages[currentSubIndex]})`}}
+            >
+              <div className="flex items-end w-full h-full px-4 py-3 bg-gradient-to-b from-white/0 to-black/80 gap-0.5">
+                <div className="text-white text-2xl font-bold">BNK 경남은행 전산 & 데이터센터</div>
               </div>
-            </div>
 
-            {/* 왼쪽 화살표 */}
-            <div className="absolute left-10 top-1/2 -translate-y-1/2 w-24 h-24 flex items-center justify-center">
-              <div className="w-14 h-14 bg-zinc-300/75 flex items-center justify-center">
-                <span className="text-black text-lg font-thin font-['Inter']">{'<'}</span>
+              <div className="flex justify-center mt-5 pb-5">
+                <IndicatorDots
+                  count={subImages.length}
+                  activeIndex={currentSubIndex}
+                  onClick={handleDotClick}
+                  activeColorClass="bg-blue-900"
+                  inactiveColorClass="bg-blue-900/20"
+                />
               </div>
-            </div>
 
-            {/* 오른쪽 화살표 */}
-            <div className="absolute right-10 top-1/2 -translate-y-1/2 w-24 h-24 flex items-center justify-center">
-              <div className="w-14 h-14 bg-zinc-300/75 flex items-center justify-center">
-                <span className="text-black text-lg font-thin font-['Inter']">{'>'}</span>
+              <div className="absolute left-10 top-1/2 -translate-y-1/2 w-24 h-24 flex items-center justify-center">
+                <div className="w-14 h-14 bg-zinc-300/75 flex items-center justify-center cursor-pointer"
+                     onClick={handlePrev}>
+                  <span className="text-black text-lg font-thin">{'<'}</span>
+                </div>
               </div>
-            </div>
 
-            {/* 인디케이터 */}
-            <div className="py-10 flex justify-center items-center gap-2">
-              <div className="w-2 h-2 relative bg-blue-900 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
-              <div className="w-2 h-2 relative bg-blue-900/20 rounded"/>
+              <div className="absolute right-10 top-1/2 -translate-y-1/2 w-24 h-24 flex items-center justify-center">
+                <div className="w-14 h-14 bg-zinc-300/75 flex items-center justify-center cursor-pointer"
+                     onClick={handleNext}>
+                  <span className="text-black text-lg font-thin">{'>'}</span>
+                </div>
+              </div>
             </div>
-          </div>
+          ) : (
+            <div className="max-w-7xl mx-auto flex items-center justify-center bg-zinc-200 min-h-[300px] mb-10">
+              <span className="text-gray-500 text-xl">이미지가 없습니다</span>
+            </div>
+          )}
         </>
       )}
     </div>
   );
 };
 
-export default Landmarks;
+export default Sections;