|
|
@@ -3,32 +3,28 @@ import businessItems from "@/data/business";
|
|
|
import type {BusinessItem} from "@/data/business";
|
|
|
import DarkOverlay from "@/components/common/DarkOverlay";
|
|
|
import IndicatorDots from "@/components/common/IndicatorDots";
|
|
|
+import { useScrollAnimation } from "@/hooks/useScrollAnimation";
|
|
|
|
|
|
const Sections = () => {
|
|
|
const [selectedItem, setSelectedItem] = useState<BusinessItem | null>(null);
|
|
|
const [currentSubIndex, setCurrentSubIndex] = useState(0);
|
|
|
+ const { ref, isVisible } = useScrollAnimation({ threshold: 0.1 });
|
|
|
|
|
|
const handleSelectItem = (item: BusinessItem) => {
|
|
|
setSelectedItem(item);
|
|
|
- setCurrentSubIndex(0); // 새 항목 선택 시 초기화
|
|
|
+ setCurrentSubIndex(0);
|
|
|
};
|
|
|
|
|
|
const handlePrev = () => {
|
|
|
const images = selectedItem?.subImages;
|
|
|
if (!images) return;
|
|
|
-
|
|
|
- setCurrentSubIndex((prev) =>
|
|
|
- prev === 0 ? images.length - 1 : prev - 1
|
|
|
- );
|
|
|
+ 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
|
|
|
- );
|
|
|
+ setCurrentSubIndex((prev) => prev === images.length - 1 ? 0 : prev + 1);
|
|
|
};
|
|
|
|
|
|
const handleDotClick = (index: number) => {
|
|
|
@@ -38,90 +34,123 @@ const Sections = () => {
|
|
|
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={() => handleSelectItem(item)}
|
|
|
- >
|
|
|
- <DarkOverlay/>
|
|
|
- <div className="relative p-2">
|
|
|
- <div className="text-white text-lg font-semibold font-['Noto_Sans_KR']">{item.label}</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- ))}
|
|
|
- </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 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"/>
|
|
|
- </div>
|
|
|
- <div className="w-1/2 flex items-center justify-center px-4">
|
|
|
- <div className="text-black text-xl font-light leading-9 whitespace-pre-line">
|
|
|
- {selectedItem.description2}
|
|
|
+ <div ref={ref} className="px-4 sm:px-8 py-8 sm:py-12">
|
|
|
+ <div className={`transition-all duration-1000 ${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10'}`}>
|
|
|
+
|
|
|
+ {/* 썸네일 선택 */}
|
|
|
+ <div className="max-w-7xl mx-auto mb-8 sm:mb-12">
|
|
|
+ <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-2 sm:gap-4">
|
|
|
+ {businessItems.map((item, index) => (
|
|
|
+ <div
|
|
|
+ key={index}
|
|
|
+ className="relative h-24 sm:h-32 lg:h-36 bg-cover bg-center cursor-pointer rounded-lg overflow-hidden shadow-md hover:shadow-lg transition-shadow duration-200"
|
|
|
+ style={{backgroundImage: `url(${item.image})`}}
|
|
|
+ onClick={() => handleSelectItem(item)}
|
|
|
+ >
|
|
|
+ <DarkOverlay/>
|
|
|
+ <div className="relative p-2 sm:p-3 h-full flex items-end">
|
|
|
+ <div className="text-white text-xs sm:text-sm lg:text-base font-semibold font-['Noto_Sans_KR'] antialiased leading-tight">
|
|
|
+ {item.label}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- {/* 중간 타이틀 */}
|
|
|
- <div className="h-28 flex flex-col justify-center my-10 items-center gap-9">
|
|
|
- <div className="text-center text-neutral-800 text-2xl font-medium">대표공사실적</div>
|
|
|
+ ))}
|
|
|
</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {selectedItem && (
|
|
|
+ <div className="space-y-8 sm:space-y-12 lg:space-y-16">
|
|
|
+
|
|
|
+ {/* 타이틀 */}
|
|
|
+ <div className="text-center space-y-4 sm:space-y-6">
|
|
|
+ <h1 className="text-2xl sm:text-3xl lg:text-4xl xl:text-5xl font-bold font-['Noto_Sans_KR'] antialiased text-gray-800">
|
|
|
+ {selectedItem.label}
|
|
|
+ </h1>
|
|
|
+ <p className="text-base sm:text-lg lg:text-xl font-medium font-['Noto_Sans_KR'] antialiased text-gray-600 whitespace-pre-line max-w-4xl mx-auto">
|
|
|
+ {selectedItem.description}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
|
|
|
- {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 className="max-w-7xl mx-auto">
|
|
|
+ <div className="flex flex-col lg:flex-row bg-gray-100 rounded-lg overflow-hidden shadow-lg">
|
|
|
+ <div className="w-full lg:w-1/2 h-64 sm:h-80 lg:h-96">
|
|
|
+ <img className="w-full h-full object-cover" src={selectedItem.image} alt={selectedItem.label}/>
|
|
|
+ </div>
|
|
|
+ <div className="w-full lg:w-1/2 flex items-center justify-center p-6 sm:p-8 lg:p-12">
|
|
|
+ <div className="text-sm sm:text-base lg:text-lg font-medium font-['Noto_Sans_KR'] antialiased text-gray-700 leading-relaxed whitespace-pre-line">
|
|
|
+ {selectedItem.description2}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
+ </div>
|
|
|
|
|
|
- <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 className="text-center">
|
|
|
+ <h2 className="text-xl sm:text-2xl lg:text-3xl font-bold font-['Noto_Sans_KR'] antialiased text-gray-800">
|
|
|
+ 대표공사실적
|
|
|
+ </h2>
|
|
|
+ <div className="w-20 h-1 bg-blue-900 mx-auto mt-4"></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 cursor-pointer"
|
|
|
- onClick={handlePrev}>
|
|
|
- <span className="text-black text-lg font-thin">{'<'}</span>
|
|
|
+ {/* 이미지 슬라이더 */}
|
|
|
+ {Array.isArray(subImages) && subImages.length > 0 ? (
|
|
|
+ <div className="max-w-7xl mx-auto">
|
|
|
+ <div className="relative">
|
|
|
+ <div
|
|
|
+ className="relative h-64 sm:h-80 lg:h-96 xl:h-[30rem] bg-cover bg-center rounded-lg overflow-hidden shadow-lg transition-all duration-500"
|
|
|
+ style={{backgroundImage: `url(${subImages[currentSubIndex]})`}}
|
|
|
+ >
|
|
|
+ <div className="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent"></div>
|
|
|
+
|
|
|
+ <div className="absolute bottom-4 sm:bottom-6 left-4 sm:left-6 right-4 sm:right-6">
|
|
|
+ <h3 className="text-white text-lg sm:text-xl lg:text-2xl font-bold font-['Noto_Sans_KR'] antialiased">
|
|
|
+ BNK 부산은행 전산 & 데이터센터
|
|
|
+ </h3>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 네비게이션 버튼 */}
|
|
|
+ {subImages.length > 1 && (
|
|
|
+ <>
|
|
|
+ <button
|
|
|
+ className="absolute left-2 sm:left-4 top-1/2 -translate-y-1/2 w-10 h-10 sm:w-12 sm:h-12 bg-white/80 hover:bg-white rounded-full flex items-center justify-center cursor-pointer shadow-lg transition-colors"
|
|
|
+ onClick={handlePrev}
|
|
|
+ >
|
|
|
+ <span className="text-gray-800 text-lg sm:text-xl">{'<'}</span>
|
|
|
+ </button>
|
|
|
+
|
|
|
+ <button
|
|
|
+ className="absolute right-2 sm:right-4 top-1/2 -translate-y-1/2 w-10 h-10 sm:w-12 sm:h-12 bg-white/80 hover:bg-white rounded-full flex items-center justify-center cursor-pointer shadow-lg transition-colors"
|
|
|
+ onClick={handleNext}
|
|
|
+ >
|
|
|
+ <span className="text-gray-800 text-lg sm:text-xl">{'>'}</span>
|
|
|
+ </button>
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* 인디케이터 */}
|
|
|
+ {subImages.length > 1 && (
|
|
|
+ <div className="flex justify-center mt-6">
|
|
|
+ <IndicatorDots
|
|
|
+ count={subImages.length}
|
|
|
+ activeIndex={currentSubIndex}
|
|
|
+ onClick={handleDotClick}
|
|
|
+ activeColorClass="bg-blue-900"
|
|
|
+ inactiveColorClass="bg-blue-900/20"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
</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 cursor-pointer"
|
|
|
- onClick={handleNext}>
|
|
|
- <span className="text-black text-lg font-thin">{'>'}</span>
|
|
|
- </div>
|
|
|
+ ) : (
|
|
|
+ <div className="max-w-7xl mx-auto flex items-center justify-center bg-gray-100 min-h-[200px] sm:min-h-[300px] rounded-lg">
|
|
|
+ <span className="text-gray-500 text-lg sm:text-xl font-medium font-['Noto_Sans_KR'] antialiased">이미지가 없습니다</span>
|
|
|
</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>
|
|
|
+ )}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
);
|
|
|
};
|