문재인 5 kuukautta sitten
vanhempi
sitoutus
e85da7e4fc

+ 1 - 1
index.html

@@ -6,7 +6,7 @@
     <link rel="preconnect" href="https://fonts.googleapis.com">
     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
     <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100..900&display=swap" rel="stylesheet">
-    <title>(주)반도산전</title>
+    <title>반도산전(주)</title>
     <script type="text/javascript" src="https://oapi.map.naver.com/openapi/v3/maps.js?ncpKeyId=10byjktu3p"></script>
   </head>
   <body>

BIN
public/image/banner.png


BIN
public/image/layout/주요실적.jpg


+ 29 - 14
src/components/Header.tsx

@@ -9,6 +9,13 @@ const Header = () => {
   const [mobileActiveIndex, setMobileActiveIndex] = useState<number | null>(null);
   const [isMenuHovered, setIsMenuHovered] = useState(false);
 
+  const scrollToTop = () => {
+    window.scrollTo({
+      top: 0,
+      behavior: 'smooth'
+    });
+  };
+
   return (
     <header className="fixed top-0 left-0 right-0 flex items-center h-16 sm:h-20 w-full bg-white z-30">
       <article
@@ -22,6 +29,7 @@ const Header = () => {
           setActiveIndex(null);
           setMobileMenuOpen(false);
           setMobileActiveIndex(null);
+          scrollToTop();
         }}
         className="absolute left-4 sm:left-[40px] top-1/2 transform -translate-y-1/2 flex items-center gap-1 w-32"
       >
@@ -54,18 +62,18 @@ const Header = () => {
       </nav>
 
       <button
-        className="lg:hidden absolute right-4 top-1/2 transform -translate-y-1/2 flex flex-col justify-center items-center w-8 h-8 space-y-1"
+        className="lg:hidden absolute right-4 top-1/2 transform -translate-y-1/2 flex flex-col justify-center items-center w-8 h-8 rounded-md hover:bg-gray-100 transition-colors duration-200"
         onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
       >
-        <span className={`block w-6 h-0.5 bg-gray-600 transition-all duration-300 ${mobileMenuOpen ? 'rotate-45 translate-y-2' : ''}`}></span>
-        <span className={`block w-6 h-0.5 bg-gray-600 transition-all duration-300 ${mobileMenuOpen ? 'opacity-0' : ''}`}></span>
-        <span className={`block w-6 h-0.5 bg-gray-600 transition-all duration-300 ${mobileMenuOpen ? '-rotate-45 -translate-y-2' : ''}`}></span>
+        <span className={`block w-5 h-0.5 bg-gray-700 transition-all duration-300 ${mobileMenuOpen ? 'rotate-45 translate-y-1.5' : 'mb-1'}`}></span>
+        <span className={`block w-5 h-0.5 bg-gray-700 transition-all duration-300 ${mobileMenuOpen ? 'opacity-0' : 'mb-1'}`}></span>
+        <span className={`block w-5 h-0.5 bg-gray-700 transition-all duration-300 ${mobileMenuOpen ? '-rotate-45 -translate-y-1.5' : ''}`}></span>
       </button>
 
       {isMenuHovered && (
         <div 
           id="menuBox" 
-          className="hidden lg:block absolute w-full h-[50vh] top-16 sm:top-20 border bg-blue-900"
+          className="hidden lg:block absolute w-full h-[40vh] top-16 sm:top-20 border bg-blue-900"
           onMouseEnter={() => setIsMenuHovered(true)}
           onMouseLeave={() => {
             setIsMenuHovered(false);
@@ -85,6 +93,7 @@ const Header = () => {
                         onClick={() => {
                           setActiveIndex(null);
                           setIsMenuHovered(false);
+                          scrollToTop();
                         }}
                       >
                         <span className="relative inline-block">
@@ -102,31 +111,37 @@ const Header = () => {
       )}
 
       {mobileMenuOpen && (
-        <div className="lg:hidden absolute top-16 sm:top-20 left-0 w-full bg-white shadow-lg border-t">
+        <div className="lg:hidden absolute top-16 sm:top-20 left-0 w-full bg-white shadow-xl border-t transform animate-in slide-in-from-top-2 duration-300">
           <nav className="flex flex-col">
             {menuItems.map((item, index) => (
-              <div key={index} className="border-b border-gray-200">
+              <div key={index} className="border-b border-gray-100">
                 <div
-                  className="flex justify-between items-center px-4 py-4 text-gray-600 font-bold cursor-pointer hover:bg-gray-50"
+                  className="flex justify-between items-center px-5 py-3.5 text-gray-700 font-medium text-sm cursor-pointer hover:bg-blue-50 hover:text-blue-700 transition-all duration-200"
                   onClick={() => setMobileActiveIndex(mobileActiveIndex === index ? null : index)}
                 >
                   <span>{item.label}</span>
                   {item.children.length > 0 && (
-                    <span className={`transition-transform duration-300 ${mobileActiveIndex === index ? 'rotate-180' : ''}`}>
-                      ▼
-                    </span>
+                    <svg 
+                      className={`w-4 h-4 transition-transform duration-200 ${mobileActiveIndex === index ? 'rotate-180' : ''}`}
+                      fill="none" 
+                      stroke="currentColor" 
+                      viewBox="0 0 24 24"
+                    >
+                      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
+                    </svg>
                   )}
                 </div>
                 {mobileActiveIndex === index && item.children.length > 0 && (
-                  <div className="bg-gray-50">
+                  <div className="bg-gray-50 animate-in slide-in-from-top-1 duration-200">
                     {item.children.map((child, cIdx) => (
                       <Link
                         to={`${item.href}/${child.href}`}
                         key={cIdx}
-                        className="block px-8 py-3 text-gray-600 hover:text-blue-600 hover:bg-white transition-colors duration-200"
+                        className="block px-8 py-2.5 text-sm text-gray-600 hover:text-blue-600 hover:bg-white transition-colors duration-200 border-l-2 border-transparent hover:border-blue-500"
                         onClick={() => {
                           setMobileActiveIndex(null);
                           setMobileMenuOpen(false);
+                          scrollToTop();
                         }}
                       >
                         {child.label}
@@ -143,4 +158,4 @@ const Header = () => {
   );
 };
 
-export default Header;
+export default Header;

+ 18 - 0
src/components/common/LoadingSpinner.tsx

@@ -0,0 +1,18 @@
+import React from 'react';
+
+const LoadingSpinner = () => {
+  return (
+    <div className="flex items-center justify-center min-h-[200px] w-full">
+      <div className="flex flex-col items-center space-y-4">
+        <div className="relative">
+          <div className="w-8 h-8 border-3 border-blue-900/20 border-t-blue-900 rounded-full animate-spin"></div>
+        </div>
+        <div className="text-sm text-gray-600 font-medium font-['Noto_Sans_KR'] antialiased">
+          로딩 중...
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default LoadingSpinner;

+ 11 - 7
src/components/common/Pagination.tsx

@@ -27,14 +27,16 @@ const Pagination: React.FC<PaginationProps> = ({currentPage, totalItems, itemsPe
     };
 
     return (
-        <div className="flex w-full max-w-lg mx-auto items-center justify-center gap-2 sm:gap-3 my-8 sm:my-12 lg:my-16 px-4">
+        <div className="flex w-full max-w-md mx-auto items-center justify-center gap-1 sm:gap-2 my-6 sm:my-8 lg:my-10 px-4">
             {/* Prev 버튼 */}
             <button
-                className="w-10 h-10 sm:w-12 sm:h-12 border border-gray-300 rounded disabled:opacity-40 enabled:cursor-pointer hover:bg-gray-50 transition-colors font-['Noto_Sans_KR'] antialiased"
+                className="w-8 h-8 sm:w-9 sm:h-9 border border-gray-300 rounded disabled:opacity-40 enabled:cursor-pointer hover:bg-gray-50 transition-colors font-['Noto_Sans_KR'] antialiased flex items-center justify-center"
                 onClick={() => handleClick(currentPage - 1)}
                 disabled={currentPage === 1}
             >
-                <div className="text-center text-gray-600 text-lg sm:text-xl">{'<'}</div>
+                <svg className="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
+                </svg>
             </button>
 
             {/* 페이지 버튼들 */}
@@ -46,11 +48,11 @@ const Pagination: React.FC<PaginationProps> = ({currentPage, totalItems, itemsPe
                     <button
                         key={page}
                         onClick={() => handleClick(page)}
-                        className={`w-10 h-10 sm:w-12 sm:h-12 cursor-pointer rounded transition-colors font-['Noto_Sans_KR'] antialiased ${
+                        className={`w-8 h-8 sm:w-9 sm:h-9 cursor-pointer rounded transition-colors font-['Noto_Sans_KR'] antialiased flex items-center justify-center ${
                             isActive
                                 ? 'bg-blue-900 text-white font-semibold'
                                 : 'border border-gray-300 text-gray-600 hover:bg-gray-50'
-                        } text-sm sm:text-base lg:text-lg`}
+                        } text-xs sm:text-sm lg:text-base`}
                     >
                         {page}
                     </button>
@@ -59,11 +61,13 @@ const Pagination: React.FC<PaginationProps> = ({currentPage, totalItems, itemsPe
 
             {/* Next 버튼 */}
             <button
-                className="w-10 h-10 sm:w-12 sm:h-12 border border-gray-300 rounded disabled:opacity-40 enabled:cursor-pointer hover:bg-gray-50 transition-colors font-['Noto_Sans_KR'] antialiased"
+                className="w-8 h-8 sm:w-9 sm:h-9 border border-gray-300 rounded disabled:opacity-40 enabled:cursor-pointer hover:bg-gray-50 transition-colors font-['Noto_Sans_KR'] antialiased flex items-center justify-center"
                 onClick={() => handleClick(currentPage + 1)}
                 disabled={currentPage === totalPages}
             >
-                <div className="text-center text-gray-600 text-lg sm:text-xl">{'>'}</div>
+                <svg className="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
+                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
+                </svg>
             </button>
         </div>
     );

+ 3 - 3
src/components/common/Tabs.tsx

@@ -27,10 +27,10 @@ const Tabs: React.FC<TabsProps> = ({
           <div
             key={tab.id}
             className={`w-full py-3 sm:py-4 cursor-pointer text-sm sm:text-lg lg:text-2xl font-semibold font-['Noto_Sans_KR'] antialiased ${
-              idx !== 0 ? 'border-l border-gray-200' : ''} ${
-              idx !== items.length - 1 ? 'border-r border-gray-200' : ''} ${
+              idx !== 0 ? 'border-l border-gray-300' : ''} ${
+              idx !== items.length - 1 ? 'border-r border-gray-300' : ''} ${
               activeTab === tab.id ? 'text-black' : 'text-black/25'
-            }`}
+            } border-opacity-50`}
             onClick={() => onTabChange(tab.id)}
           >
             {tab.label}

+ 14 - 15
src/components/main/Business.tsx

@@ -48,14 +48,14 @@ const Business = () => {
                         <a
                             key={index}
                             href={item.url}
-                            className="relative flex-[0_0_calc(50%-4px)] sm:flex-[0_0_calc(33.33%-8px)] lg:flex-[0_0_calc((100%-24px)/5)] bg-cover bg-center aspect-[16/10] cursor-pointer"
+                            className="relative flex-[0_0_calc(50%-4px)] sm:flex-[0_0_calc(33.33%-8px)] lg:flex-[0_0_calc((100%-24px)/5)] bg-cover bg-center h-24 sm:aspect-[16/10] cursor-pointer"
                             style={{backgroundImage: `url(${item.image})`}}
                         >
                             <DarkOverlay />
                             
                             <div className="relative p-2 sm:p-4">
-                                <div className="text-white text-xs sm:text-sm lg:text-md font-semibold font-['Noto_Sans_KR'] whitespace-pre-line antialiased">{item.label}</div>
-                                <div className="text-white text-xs sm:text-sm font-semibold font-['Noto_Sans_KR'] antialiased"></div>
+                                <div className="text-white text-sm sm:text-base lg:text-lg font-semibold font-['Noto_Sans_KR'] whitespace-pre-line antialiased">{item.label}</div>
+                                <div className="text-white text-xs sm:text-sm font-semibold font-['Noto_Sans_KR'] antialiased">상세보기</div>
                             </div>
                         </a>
                     ))}
@@ -80,24 +80,23 @@ const Business = () => {
                             <span className="text-blue-900 text-lg sm:text-xl lg:text-2xl xl:text-3xl">947</span>억 매출을 달성한 외감법인입니다.
                         </div>
                     </div>
-                    <div className="flex justify-center items-center lg:h-60 gap-4 lg:gap-8">
+                    <div className="flex flex-wrap justify-center items-center gap-3 sm:gap-4 lg:gap-8 max-w-6xl mx-auto">
                         <div className="flex justify-center">
                             {RankBox("전기공사", "15위", "5%")}
                         </div>
                         
                         <div className="w-px h-16 lg:h-24 bg-gray-200"></div>
                         
-                        <div className="flex flex-col lg:flex-row items-center gap-4 lg:gap-8">
-                            <div className="flex justify-center items-center">
-                                <svg width="40" height="41" viewBox="0 0 98 99" fill="none" xmlns="http://www.w3.org/2000/svg" className="w-10 h-10 lg:w-16 lg:h-16">
-                                    <path d="M40.8333 45.4166H65.3333L89.7925 4.58325H65.2925L40.8333 45.4166Z" fill="#1E3A8A"/>
-                                    <path d="M57.1258 45.4166H32.6258L8.16666 4.58325H32.6667L57.1258 45.4166Z" fill="#1E3A8A"/>
-                                    <path d="M49 94.4167C64.7862 94.4167 77.5833 81.6195 77.5833 65.8333C77.5833 50.0472 64.7862 37.25 49 37.25C33.2139 37.25 20.4167 50.0472 20.4167 65.8333C20.4167 81.6195 33.2139 94.4167 49 94.4167Z" fill="#E7ECEF"/>
-                                </svg>
-                            </div>
-                            <div className="flex justify-center">
-                                {RankBox("통신공사", "1위", "1%")}
-                            </div>
+                        <div className="flex justify-center items-center">
+                            <svg width="40" height="41" viewBox="0 0 98 99" fill="none" xmlns="http://www.w3.org/2000/svg" className="w-8 h-8 sm:w-10 sm:h-10 lg:w-16 lg:h-16">
+                                <path d="M40.8333 45.4166H65.3333L89.7925 4.58325H65.2925L40.8333 45.4166Z" fill="#1E3A8A"/>
+                                <path d="M57.1258 45.4166H32.6258L8.16666 4.58325H32.6667L57.1258 45.4166Z" fill="#1E3A8A"/>
+                                <path d="M49 94.4167C64.7862 94.4167 77.5833 81.6195 77.5833 65.8333C77.5833 50.0472 64.7862 37.25 49 37.25C33.2139 37.25 20.4167 50.0472 20.4167 65.8333C20.4167 81.6195 33.2139 94.4167 49 94.4167Z" fill="#E7ECEF"/>
+                            </svg>
+                        </div>
+                        
+                        <div className="flex justify-center">
+                            {RankBox("통신공사", "1위", "1%")}
                         </div>
                         
                         <div className="w-px h-16 lg:h-24 bg-gray-200"></div>

+ 1 - 3
src/components/main/Hero.tsx

@@ -6,9 +6,7 @@ import {useScrollAnimation} from "@/hooks/useScrollAnimation";
 import { Link } from "react-router-dom";
 
 const images = [
-    `${IMAGE_PREFIX}/hero.jpg`,
-    // '/hero2.png',
-    `${IMAGE_PREFIX}/hero.jpg`,
+    `${IMAGE_PREFIX}/banner.png`,
 ];
 
 const Hero = () => {

+ 3 - 3
src/components/main/Partners.tsx

@@ -14,7 +14,7 @@ const Partners = () => {
             style={{backgroundImage: `url(${IMAGE_PREFIX}/partners-bg.jpg)`}}
         >
             <DarkOverlay/>
-            <div className={`max-w-7xl mx-auto relative flex-col justify-items-center px-4 sm:px-0 transition-all duration-1000 ${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10'}`}>
+            <div className={`max-w-7xl mx-auto relative flex-col justify-items-center px-6 sm:px-0 transition-all duration-1000 ${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10'}`}>
                 <div className="w-full mb-6 sm:mb-8 lg:mb-12">
                     <div className="relative w-full space-y-2 text-center sm:text-left">
                         <div className="text-white text-3xl sm:text-4xl lg:text-5xl font-bold font-['Noto_Sans_KR'] antialiased">협력사</div>
@@ -23,9 +23,9 @@ const Partners = () => {
                     </div>
                 </div>
 
-                <div className="mb-5 grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 justify-items-center gap-x-4 sm:gap-x-8 lg:gap-x-20 gap-y-6 sm:gap-y-8 lg:gap-y-10">
+                <div className="mb-5 grid grid-cols-3 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 justify-items-center gap-x-4 sm:gap-x-8 lg:gap-x-20 gap-y-4 sm:gap-y-8 lg:gap-y-10">
                     {partnerList.map((partner, index) => (
-                        <div key={index} className="w-28 sm:w-32 lg:w-36 h-12 sm:h-14 lg:h-16 bg-white flex items-center justify-center">
+                        <div key={index} className="w-24 sm:w-32 lg:w-36 h-10 sm:h-14 lg:h-16 bg-white flex items-center justify-center p-2 sm:p-3 shadow-sm">
                             <img
                                 src={partner.imageUrl}
                                 alt={`Partner logo ${index}`}

+ 1 - 0
src/data/menuItems.ts

@@ -50,6 +50,7 @@ const menuItems: MenuItem[] = [
     {
         label: "주요실적",
         href: "/score",
+        layoutImg: `${LAYOUT_IMAGE_PREFIX}/주요실적.jpg`,
         description: "반도산전의 주요 실적입니다.",
         children: [
             { label: "인증서 및 면허", href: "certification" },

+ 36 - 27
src/data/project.ts

@@ -14,7 +14,9 @@ export interface MajorProject {
 const projectList: MajorProject[] = [
   {
     title: "BNK 부산은행 전산 & 데이터센터",
-    description: "",
+    client: "BNK부산은행(주)",
+    contractAmount: "₩1,486,082,000",
+    description: "전산 & 데이터센터 신축, 이전공사",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/데이터센터.jpg`,
     subImgUrl: [
       `${PROJECT_SUBIMAGE_PREFIX}/ICT.jpg`,
@@ -32,37 +34,58 @@ const projectList: MajorProject[] = [
   },
   {
     title: "부산 북항 협성마리나 G7",
+    client: "협성르네상스",
+    contractAmount: "₩6,963,000,000",
+    period: "2018.02 - 2021.03",
     description: "",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/G7.png`,
   },
   {
     title: "국방광대역 통합망",
-    description: "",
+    client: "케이국방주식회사",
+    contractAmount: "₩12,624,850,700",
+    period: "2022.09 - 2024.09",
+    description: "차기 국방광대역통합망(M-BcN) 구축 민간투자사업(BTL)",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/통합망.jpg`,
   },
   {
     title: "수원 덕산종합병원",
-    description: "",
+    client: "계룡건설산업㈜",
+    contractAmount: "₩6,644,000,000",
+    period: "2022.01 - 2025.10",
+    description: "덕산의료재단 수원덕산병원 신축 건설공사 중 통신공사",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/덕산병원.jpg`,
   },
   {
     title: "부산 강서구 BGF 리테일 CU 물류창고",
-    description: "",
+    client: "㈜비지에프리테일",
+    contractAmount: "₩4,972,000,000",
+    period: "2024.07 - 2026.09",
+    description: "BGF리테일 부산센터 구축공사 소방전기공사",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/CU물류창고.jpg`,
   },
   {
     title: "부산 동부산 관광단지 오시리아 메디타운",
-    description: "",
+    client: "한화건설",
+    contractAmount: "₩4,061,200,000",
+    period: "2024.02 - 2025.03",
+    description: "오시리아 메디타운 중 약전설비공사",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/메디타운.jpg`,
   },
   {
     title: "부산대학교병원 아트리움",
-    description: "",
+    client: "계룡건설산업㈜, 부산대학교병원",
+    contractAmount: "₩4,661,600,000",
+    period: "2010.12 - 2016.08",
+    description: "외상전문센터 통신공사, 호흡기전문질환센터 통신공사, B동 아트리움 증축 통신공사, 기타 외상전문센터 통신공사",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/아트리움.jpg`,
   },
   {
     title: "김해물류센터",
-    description: "",
+    client: "엘티삼보㈜",
+    contractAmount: "₩7,077,400,000",
+    period: "2022.12 - 2024.10",
+    description: "김해물류센터신축공사(전기설비공사,소방시설공사)",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/김해물류센터.png`,
   },
   {
@@ -72,31 +95,17 @@ const projectList: MajorProject[] = [
   },
   {
     title: "롯데리조트제주 아트발라스",
+    client: "롯데건설",
+    contractAmount: "₩1,040,216,100",
+    period: "2010.09 - 2012.04",
     description: "",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/롯데리조트제주.jpg`,
   },
   {
     title: "부암 서희 스타힐스",
-    description: "",
-    imageUrl: `${PROJECT_IMAGE_PREFIX}/서희스타힐스.jpg`,
-  },
-  {
-    title: "부암 서희 스타힐스",
-    description: "",
-    imageUrl: `${PROJECT_IMAGE_PREFIX}/서희스타힐스.jpg`,
-  },
-  {
-    title: "부암 서희 스타힐스",
-    description: "",
-    imageUrl: `${PROJECT_IMAGE_PREFIX}/서희스타힐스.jpg`,
-  },
-  {
-    title: "부암 서희 스타힐스",
-    description: "",
-    imageUrl: `${PROJECT_IMAGE_PREFIX}/서희스타힐스.jpg`,
-  },
-  {
-    title: "부암 서희 스타힐스",
+    client: "서희건설",
+    contractAmount: "₩11,443,774,000",
+    period: "2022.06 - 2025.03",
     description: "",
     imageUrl: `${PROJECT_IMAGE_PREFIX}/서희스타힐스.jpg`,
   },

+ 2 - 1
src/pages/Main.tsx

@@ -1,5 +1,6 @@
 import React, { lazy, Suspense } from 'react';
 import TopButton from "@/components/common/TopButton";
+import LoadingSpinner from "@/components/common/LoadingSpinner";
 
 const Hero = lazy(() => import("@/components/main/Hero.jsx"));
 const Business = lazy(() => import("@/components/main/Business.jsx"));
@@ -11,7 +12,7 @@ const Footer = lazy(() => import("@/components/main/Footer.jsx"));
 const Main = () => {
   return (
     <>
-      <Suspense fallback={<div>로딩 중...</div>}>
+      <Suspense fallback={<LoadingSpinner />}>
         <Hero/>
         <Business/>
         <Project/>

+ 3 - 3
src/pages/about/History.tsx

@@ -3,9 +3,9 @@ import Tabs, {TabItem} from "@/components/common/Tabs";
 import { useScrollAnimation } from "@/hooks/useScrollAnimation";
 
 const tabItems: TabItem[] = [
-  {id: '1', label: '현재'},
-  {id: '2', label: '2010 ~ 2020'},
   {id: '3', label: '~ 2010'},
+  {id: '2', label: '2010 ~ 2020'},
+  {id: '1', label: '현재'},
 ];
 
 const tabYears: Record<string, { start: string; end: string }> = {
@@ -73,7 +73,7 @@ const historyItems = [
 ];
 
 const History: React.FC = () => {
-  const [activeTab, setActiveTab] = useState('1');
+  const [activeTab, setActiveTab] = useState('3');
   const { ref, isVisible } = useScrollAnimation({ threshold: 0.1 });
   
   // 연도 필터링 함수

+ 1 - 1
src/pages/business/Landmarks.tsx

@@ -49,7 +49,7 @@ const Landmarks = () => {
                     }}>
                   {project.title}
                 </h3>
-                <div className="text-xs text-white/80 font-medium font-['Noto_Sans_KR'] antialiased">MORE +</div>
+                <div className="text-xs text-white/80 font-medium font-['Noto_Sans_KR'] antialiased">상세보기</div>
               </div>
             </div>
 

+ 51 - 49
src/pages/score/Sheet.tsx

@@ -135,61 +135,63 @@ const Sheet: React.FC = () => {
   }, 0);
 
   return (
-    <div className="max-w-7xl mx-auto px-4 py-10">
+    <div className="max-w-7xl mx-auto px-4 sm:px-6 py-8 sm:py-10">
       {activeTab && (
         <Tabs items={tabItems} activeTab={activeTab} onTabChange={setActiveTab}>
-          <div className="text-center mb-6">
-            <div className="inline-block font-bold underline text-xl tracking-widest">
-              공     황 ({activeTab})
+          <div className="text-center mb-6 sm:mb-8">
+            <div className="inline-block font-bold text-lg sm:text-xl lg:text-2xl text-gray-800 border-b-2 border-blue-900 pb-2">
+              공사계약현황 ({activeTab})
             </div>
           </div>
-          <div className="overflow-y-scroll max-h-[600px]">
-            <table className="min-w-full border border-gray-300 text-sm table-fixed">
-            <thead>
-            <tr className="bg-gray-100 text-center sticky top-0 z-10">
-              <th className="border px-2 py-2 w-[10%] bg-gray-100">발주처</th>
-              <th className="border px-2 py-2 w-[40%] bg-gray-100">공사명</th>
-              <th className="border px-2 py-2 w-[15%] bg-gray-100">계약금액</th>
-              <th className="border px-2 py-2 w-[11%] bg-gray-100">계약일</th>
-              <th className="border px-2 py-2 w-[11%] bg-gray-100">착공일</th>
-              <th className="border px-2 py-2 w-[13%] bg-gray-100">준공일</th>
-            </tr>
-            </thead>
-            <tbody>
-            {filteredRows.length > 0 ? (
-              filteredRows.slice(0, -1).map((row: any, index: number) => (
-                <tr key={index} className={row._highlight ? "bg-yellow-200" : ""}>
-                  <td className="border px-2 py-1 w-[10%] truncate font-bold">{row["발주처"]}</td>
-                  <td className="border px-2 py-1 w-[40%] truncate">{row["공사명"]}</td>
-                  <td className="border px-2 py-1 w-[15%] text-right">
-                    {typeof row["계약금액"] === "number"
-                      ? new Intl.NumberFormat("ko-KR").format(row["계약금액"])
-                      : row["계약금액"]}
+          <div className="overflow-x-auto">
+            <div className="overflow-y-auto max-h-[500px] sm:max-h-[600px] border border-gray-200 rounded-lg shadow-sm">
+              <table className="min-w-full text-xs sm:text-sm table-fixed bg-white">
+              <thead>
+                <tr className="bg-blue-50 text-center sticky top-0 z-10">
+                  <th className="border-b border-r border-gray-200 px-2 py-3 w-[10%] bg-blue-50 font-semibold text-gray-700">발주처</th>
+                  <th className="border-b border-r border-gray-200 px-2 py-3 w-[40%] bg-blue-50 font-semibold text-gray-700">공사명</th>
+                  <th className="border-b border-r border-gray-200 px-2 py-3 w-[15%] bg-blue-50 font-semibold text-gray-700">계약금액</th>
+                  <th className="border-b border-r border-gray-200 px-2 py-3 w-[11%] bg-blue-50 font-semibold text-gray-700">계약일</th>
+                  <th className="border-b border-r border-gray-200 px-2 py-3 w-[11%] bg-blue-50 font-semibold text-gray-700">착공일</th>
+                  <th className="border-b border-gray-200 px-2 py-3 w-[13%] bg-blue-50 font-semibold text-gray-700">준공일</th>
+                </tr>
+              </thead>
+              <tbody>
+                {filteredRows.length > 0 ? (
+                  filteredRows.slice(0, -1).map((row: any, index: number) => (
+                    <tr key={index} className={`hover:bg-gray-50 transition-colors ${row._highlight ? "bg-yellow-100" : index % 2 === 0 ? "bg-white" : "bg-gray-50"}`}>
+                      <td className="border-b border-r border-gray-200 px-2 py-2 w-[10%] truncate font-medium text-gray-800">{row["발주처"]}</td>
+                      <td className="border-b border-r border-gray-200 px-2 py-2 w-[40%] truncate text-gray-700">{row["공사명"]}</td>
+                      <td className="border-b border-r border-gray-200 px-2 py-2 w-[15%] text-right font-medium text-gray-800">
+                        {typeof row["계약금액"] === "number"
+                          ? new Intl.NumberFormat("ko-KR").format(row["계약금액"])
+                          : row["계약금액"]}
+                      </td>
+                      <td className="border-b border-r border-gray-200 px-2 py-2 w-[11%] text-center text-gray-600">{row["계약일"]}</td>
+                      <td className="border-b border-r border-gray-200 px-2 py-2 w-[11%] text-center text-gray-600">{row["착공일"]}</td>
+                      <td className="border-b border-gray-200 px-2 py-2 w-[13%] text-center text-gray-600">{row["준공일"]}</td>
+                    </tr>
+                  ))
+                ) : (
+                  <tr>
+                    <td className="border-b border-gray-200 px-4 py-8 text-center text-gray-500" colSpan={6}>
+                      데이터가 없습니다.
+                    </td>
+                  </tr>
+                )}
+              </tbody>
+              <tfoot>
+                <tr className="bg-blue-100 font-bold text-center sticky bottom-0">
+                  <td className="border-t border-r border-gray-300 px-2 py-3 bg-blue-100"/>
+                  <td className="border-t border-r border-gray-300 px-2 py-3 bg-blue-100 text-gray-800">합계</td>
+                  <td className="border-t border-r border-gray-300 px-2 py-3 text-right bg-blue-100 text-blue-900 font-bold">
+                    {new Intl.NumberFormat("ko-KR").format(totalAmount)}
                   </td>
-                  <td className="border px-2 py-1 w-[11%] text-center">{row["계약일"]}</td>
-                  <td className="border px-2 py-1 w-[11%] text-center">{row["착공일"]}</td>
-                  <td className="border px-2 py-1 w-[13%] text-center">{row["준공일"]}</td>
+                  <td className="border-t border-gray-300 px-2 py-3 bg-blue-100" colSpan={3}/>
                 </tr>
-              ))
-            ) : (
-              <tr>
-                <td className="border px-4 py-2 text-center" colSpan={6}>
-                  데이터가 없습니다.
-                </td>
-              </tr>
-            )}
-            </tbody>
-            <tfoot>
-            <tr className="bg-gray-100 font-bold text-center">
-              <td className="border px-2 py-1"/>
-              <td className="border px-2 py-1">합계</td>
-              <td className="border px-2 py-1 text-right">
-                {new Intl.NumberFormat("ko-KR").format(totalAmount)}
-              </td>
-              <td className="border px-2 py-1" colSpan={3}/>
-            </tr>
-            </tfoot>
-          </table>
+              </tfoot>
+            </table>
+            </div>
           </div>
         </Tabs>
       )}

+ 2 - 1
src/utils/lazyImport.tsx

@@ -10,6 +10,7 @@
 
 /// <reference types="vite/client" />
 import React, { lazy, Suspense } from 'react';
+import LoadingSpinner from '@/components/common/LoadingSpinner';
 
 // Vite glob으로 모든 페이지 import
 const pages = import.meta.glob('@/pages/**/*.tsx');
@@ -57,7 +58,7 @@ export const lazyImport = (path: string) => {
 export const withSuspense = (
   Component: React.LazyExoticComponent<React.ComponentType>
 ) => (
-  <Suspense fallback={<div>로딩 중...</div>}>
+  <Suspense fallback={<LoadingSpinner />}>
     <Component />
   </Suspense>
 );