From 64bc46ce3e1e9c46fe632591be97a894ff8f4d40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=8C=80=ED=9D=AC?= <joedaehui@ajou.ac.kr>
Date: Sun, 8 Dec 2024 15:57:27 +0900
Subject: [PATCH 1/6] =?UTF-8?q?stlye:=20=EC=8A=A4=EC=BC=80=EC=A4=84?=
 =?UTF-8?q?=EB=B3=84=EB=A1=9C=20=EB=8B=A4=EB=A5=B8=20=EC=83=89=EC=83=81=20?=
 =?UTF-8?q?=EC=A0=81=EC=9A=A9=20(#13)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/pages/SchedulePage.jsx | 80 +++++++++++++++++++++++++++++++++++---
 1 file changed, 74 insertions(+), 6 deletions(-)

diff --git a/src/pages/SchedulePage.jsx b/src/pages/SchedulePage.jsx
index 35a53ba..221a813 100644
--- a/src/pages/SchedulePage.jsx
+++ b/src/pages/SchedulePage.jsx
@@ -41,8 +41,52 @@ const days = ["월", "화", "수", "목", "금", "토", "일"];
 //     createdAt: "2024-12-02T09:54:53.000Z",
 //     updatedAt: "2024-12-02T09:54:53.000Z",
 //   },
+//   {
+//     id: 11,
+//     user_id: 1,
+//     title: "점심약속",
+//     is_fixed: false,
+//     time_indices: [240, 241, 242],
+//     createdAt: "2024-12-02T09:54:53.000Z",
+//     updatedAt: "2024-12-02T09:54:53.000Z",
+//   },
+//   {
+//     id: 14,
+//     user_id: 1,
+//     title: "롤 5:5",
+//     is_fixed: true,
+//     time_indices: [302, 303, 304, 305, 306, 307],
+//     createdAt: "2024-12-02T09:54:53.000Z",
+//     updatedAt: "2024-12-02T09:54:53.000Z",
+//   },
+//   {
+//     id: 20,
+//     user_id: 1,
+//     title: "토트넘 vs 첼시 경기",
+//     is_fixed: true,
+//     time_indices: [13, 14, 15, 16, 17, 18],
+//     createdAt: "2024-12-02T09:54:53.000Z",
+//     updatedAt: "2024-12-02T09:54:53.000Z",
+//   }
 // ];
 
+const colorClasses = [
+  'bg-indigo-300',
+  'bg-purple-300',
+  'bg-pink-300',
+  'bg-blue-300',
+  'bg-green-300',
+  'bg-yellow-300',
+  'bg-red-300',
+  'bg-orange-300',
+  'bg-teal-300',
+  'bg-cyan-300',
+  'bg-rose-300',
+  'bg-violet-300',
+  'bg-fuchsia-300',
+  'bg-emerald-300',
+  'bg-lime-300'
+];
 const SchedulePage = () => {
   const timeSlots = generateTimeSlots();
   const [schedules, setSchedules] = useState([]);
@@ -52,6 +96,17 @@ const SchedulePage = () => {
   const [selectedSlots, setSelectedSlots] = useState([]);
   const [newTitle, setNewTitle] = useState("");
   const [isFixed, setIsFixed] = useState(true);
+  const [titleColorMap, setTitleColorMap] = useState(new Map());
+
+  const getColorForTitle = (title) => {
+    if (!titleColorMap.has(title)) {
+      const newColor = colorClasses[titleColorMap.size % colorClasses.length];
+      setTitleColorMap(prev => new Map(prev).set(title, newColor));
+      return newColor;
+    }
+    return titleColorMap.get(title);
+  };
+
 
   useEffect(() => {
     // API
@@ -70,6 +125,19 @@ const SchedulePage = () => {
     // setSchedules(dummySchedules);
   }, []);
 
+  useEffect(() => {
+    const newColorMap = new Map();
+    schedules.forEach(schedule => {
+      if (!newColorMap.has(schedule.title)) {
+        newColorMap.set(
+          schedule.title,
+          colorClasses[newColorMap.size % colorClasses.length]
+        );
+      }
+    });
+    setTitleColorMap(newColorMap);
+  }, [schedules]);
+
   const handleSlotClick = async (timeIdx) => {
     if (!isEditMode) return;
 
@@ -216,7 +284,7 @@ const SchedulePage = () => {
           <div
             className={`relative w-12 h-6 rounded-full transition-colors ${
               isEditMode ? "bg-primary-500" : "bg-grayscale-300"
-            }`}
+              }`}
             onClick={() => {
               setIsEditMode((prev) => !prev);
               setSelectedSlots([]);
@@ -226,7 +294,7 @@ const SchedulePage = () => {
             <div
               className={`absolute top-0.5 left-0.5 h-5 w-5 rounded-full bg-white transition-transform ${
                 isEditMode ? "translate-x-6" : ""
-              }`}
+                }`}
             ></div>
           </div>
         </label>
@@ -386,11 +454,11 @@ const SchedulePage = () => {
                       key={slotIndex}
                       className={`p-2 border rounded ${
                         schedule
-                          ? "bg-primary-300 text-white cursor-not-allowed"
+                          ? `${getColorForTitle(schedule.title)} text-white`
                           : isSelected
-                          ? "bg-primary-100 border-primary-300"
-                          : "bg-grayscale-50 cursor-pointer"
-                      }`}
+                            ? "bg-primary-100 border-primary-300"
+                            : "bg-grayscale-50 cursor-pointer"
+                        }`}
                       onClick={() => handleSlotClick(slotIndex)}
                     >
                       {schedule ? schedule.title : ""}
-- 
GitLab


From 2f623b4591d71d8c31012a06a686a8b518be6a5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=8C=80=ED=9D=AC?= <joedaehui@ajou.ac.kr>
Date: Sun, 8 Dec 2024 16:02:55 +0900
Subject: [PATCH 2/6] =?UTF-8?q?style:=20=EC=8B=9C=EA=B0=84=20=EC=9D=B8?=
 =?UTF-8?q?=EB=8D=B1=EC=8A=A4=20=EC=8B=A4=EC=A0=9C=20=EC=8B=9C=EA=B0=84?=
 =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=A0=84=ED=99=98=20(#13)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/pages/SchedulePage.jsx | 132 ++++++++++++++++++++-----------------
 1 file changed, 72 insertions(+), 60 deletions(-)

diff --git a/src/pages/SchedulePage.jsx b/src/pages/SchedulePage.jsx
index 221a813..802de20 100644
--- a/src/pages/SchedulePage.jsx
+++ b/src/pages/SchedulePage.jsx
@@ -22,53 +22,53 @@ const generateTimeSlots = () => {
 
 const days = ["월", "화", "수", "목", "금", "토", "일"];
 
-// const dummySchedules = [
-//   {
-//     id: 1,
-//     user_id: 1,
-//     title: "알고리즘 스터디",
-//     is_fixed: true,
-//     time_indices: [36, 37, 38, 39],
-//     createdAt: "2024-12-02T09:52:00.000Z",
-//     updatedAt: "2024-12-02T09:52:00.000Z",
-//   },
-//   {
-//     id: 5,
-//     user_id: 1,
-//     title: "웹시설 팀플",
-//     is_fixed: true,
-//     time_indices: [165, 166, 167, 255, 256, 257],
-//     createdAt: "2024-12-02T09:54:53.000Z",
-//     updatedAt: "2024-12-02T09:54:53.000Z",
-//   },
-//   {
-//     id: 11,
-//     user_id: 1,
-//     title: "점심약속",
-//     is_fixed: false,
-//     time_indices: [240, 241, 242],
-//     createdAt: "2024-12-02T09:54:53.000Z",
-//     updatedAt: "2024-12-02T09:54:53.000Z",
-//   },
-//   {
-//     id: 14,
-//     user_id: 1,
-//     title: "롤 5:5",
-//     is_fixed: true,
-//     time_indices: [302, 303, 304, 305, 306, 307],
-//     createdAt: "2024-12-02T09:54:53.000Z",
-//     updatedAt: "2024-12-02T09:54:53.000Z",
-//   },
-//   {
-//     id: 20,
-//     user_id: 1,
-//     title: "토트넘 vs 첼시 경기",
-//     is_fixed: true,
-//     time_indices: [13, 14, 15, 16, 17, 18],
-//     createdAt: "2024-12-02T09:54:53.000Z",
-//     updatedAt: "2024-12-02T09:54:53.000Z",
-//   }
-// ];
+const dummySchedules = [
+  {
+    id: 1,
+    user_id: 1,
+    title: "알고리즘 스터디",
+    is_fixed: true,
+    time_indices: [36, 37, 38, 39],
+    createdAt: "2024-12-02T09:52:00.000Z",
+    updatedAt: "2024-12-02T09:52:00.000Z",
+  },
+  {
+    id: 5,
+    user_id: 1,
+    title: "웹시설 팀플",
+    is_fixed: true,
+    time_indices: [165, 166, 167, 255, 256, 257],
+    createdAt: "2024-12-02T09:54:53.000Z",
+    updatedAt: "2024-12-02T09:54:53.000Z",
+  },
+  {
+    id: 11,
+    user_id: 1,
+    title: "점심약속",
+    is_fixed: false,
+    time_indices: [240, 241, 242],
+    createdAt: "2024-12-02T09:54:53.000Z",
+    updatedAt: "2024-12-02T09:54:53.000Z",
+  },
+  {
+    id: 14,
+    user_id: 1,
+    title: "롤 5:5",
+    is_fixed: true,
+    time_indices: [302, 303, 304, 305, 306, 307],
+    createdAt: "2024-12-02T09:54:53.000Z",
+    updatedAt: "2024-12-02T09:54:53.000Z",
+  },
+  {
+    id: 20,
+    user_id: 1,
+    title: "토트넘 vs 첼시 경기",
+    is_fixed: true,
+    time_indices: [13, 14, 15, 16, 17, 18],
+    createdAt: "2024-12-02T09:54:53.000Z",
+    updatedAt: "2024-12-02T09:54:53.000Z",
+  }
+];
 
 const colorClasses = [
   'bg-indigo-300',
@@ -98,16 +98,6 @@ const SchedulePage = () => {
   const [isFixed, setIsFixed] = useState(true);
   const [titleColorMap, setTitleColorMap] = useState(new Map());
 
-  const getColorForTitle = (title) => {
-    if (!titleColorMap.has(title)) {
-      const newColor = colorClasses[titleColorMap.size % colorClasses.length];
-      setTitleColorMap(prev => new Map(prev).set(title, newColor));
-      return newColor;
-    }
-    return titleColorMap.get(title);
-  };
-
-
   useEffect(() => {
     // API
     const initializeSchedules = async () => {
@@ -122,7 +112,7 @@ const SchedulePage = () => {
     initializeSchedules();
 
     // 임시 코드
-    // setSchedules(dummySchedules);
+    setSchedules(dummySchedules);
   }, []);
 
   useEffect(() => {
@@ -274,6 +264,28 @@ const SchedulePage = () => {
     }
   };
 
+  const getColorForTitle = (title) => {
+    if (!titleColorMap.has(title)) {
+      const newColor = colorClasses[titleColorMap.size % colorClasses.length];
+      setTitleColorMap(prev => new Map(prev).set(title, newColor));
+      return newColor;
+    }
+    return titleColorMap.get(title);
+  };
+
+  const convertIndexToTime = (timeIndex) => {
+    const dayIndex = Math.floor(timeIndex / 96);
+    const timeSlotIndex = timeIndex % 96;
+    const hour = Math.floor(timeSlotIndex / 4);
+    const minute = (timeSlotIndex % 4) * 15;
+    
+    const day = days[dayIndex];
+    const time = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
+    
+    return `${day} ${time}`;
+  };
+
+
   return (
     <div className="min-h-screen bg-grayscale-50">
       {/* Toggle View/Edit Mode */}
@@ -321,7 +333,7 @@ const SchedulePage = () => {
                     <strong>선택된 시간:</strong>{" "}
                     {selectedSchedule.time_indices.map((time_idx) => (
                       <Label key={time_idx} theme="indigo" size="sm">
-                        {time_idx}
+                        {convertIndexToTime(time_idx)}
                       </Label>
                     ))}
                   </div>
@@ -385,7 +397,7 @@ const SchedulePage = () => {
                   <span>선택된 시간:</span>
                   {selectedSlots.map((time_idx) => (
                     <Label key={time_idx} theme="indigo" size="sm">
-                      {time_idx}
+                      {convertIndexToTime(time_idx)}
                     </Label>
                   ))}
                 </div>
-- 
GitLab


From 1f0133b66cb6e1a87835394e1a37be14c7dfa915 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=8C=80=ED=9D=AC?= <joedaehui@ajou.ac.kr>
Date: Sun, 8 Dec 2024 16:29:11 +0900
Subject: [PATCH 3/6] =?UTF-8?q?style:=20edit=20mode=20container=20?=
 =?UTF-8?q?=EC=8A=A4=ED=83=80=EC=9D=BC=20sticky=ED=95=98=EA=B2=8C=20?=
 =?UTF-8?q?=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/pages/SchedulePage.jsx | 115 ++++++++++++++++++-------------------
 1 file changed, 55 insertions(+), 60 deletions(-)

diff --git a/src/pages/SchedulePage.jsx b/src/pages/SchedulePage.jsx
index 802de20..01c851d 100644
--- a/src/pages/SchedulePage.jsx
+++ b/src/pages/SchedulePage.jsx
@@ -296,7 +296,7 @@ const SchedulePage = () => {
           <div
             className={`relative w-12 h-6 rounded-full transition-colors ${
               isEditMode ? "bg-primary-500" : "bg-grayscale-300"
-              }`}
+            }`}
             onClick={() => {
               setIsEditMode((prev) => !prev);
               setSelectedSlots([]);
@@ -306,18 +306,66 @@ const SchedulePage = () => {
             <div
               className={`absolute top-0.5 left-0.5 h-5 w-5 rounded-full bg-white transition-transform ${
                 isEditMode ? "translate-x-6" : ""
-                }`}
+              }`}
             ></div>
           </div>
         </label>
       </div>
-
+  
+      {/* Schedule Grid */}
+      <div className="p-4 pb-[210px]">
+        <div className="overflow-auto scrollbar-hide">
+          <div className="w-[100vw] tablet:w-[960px] grid grid-cols-[64px,repeat(7,1fr)] gap-2">
+            {/* Header */}
+            <div className="min-w-[54px] p-2 font-bold text-center bg-grayscale-200 select-none">
+              Time
+            </div>
+            {days.map((day) => (
+              <div key={day} className="p-2 font-bold text-center select-none bg-grayscale-200">
+                {day}
+              </div>
+            ))}
+  
+            {/* Time Slots */}
+            {timeSlots.map((time, rowIndex) => (
+              <React.Fragment key={rowIndex}>
+                {/* Time Column */}
+                <div className="min-w-[54px] p-2 font-bold text-center bg-grayscale-100 select-none">
+                  {time}
+                </div>
+                {days.map((_, colIndex) => {
+                  const slotIndex = colIndex * timeSlots.length + rowIndex;
+                  const isSelected = selectedSlots.includes(slotIndex);
+                  const schedule = schedules.find((s) =>
+                    s.time_indices.includes(slotIndex)
+                  );
+  
+                  return (
+                    <div
+                      key={slotIndex}
+                      className={`p-2 border rounded ${
+                        schedule 
+                          ? `${getColorForTitle(schedule.title)} text-white`
+                          : isSelected 
+                            ? "bg-primary-100 border-primary-300" 
+                            : "bg-grayscale-50"
+                      } cursor-pointer`}
+                      onClick={() => handleSlotClick(slotIndex)}
+                    >
+                      {schedule ? schedule.title : ""}
+                    </div>
+                  );
+                })}
+              </React.Fragment>
+            ))}
+          </div>
+        </div>
+      </div>
+  
       {/* Sticky Container in Edit Mode */}
       {isEditMode && (
-        <div className="fixed bottom-0 right-0 flex items-center justify-center w-full ">
-          <div
-            className={`transform transition-transform w-full max-w-[768px] tablet:rounded-2xl bg-primary-100 p-6 text-center shadow-lg`}
-          >
+        <div className="fixed bottom-0 right-0 flex items-center justify-center w-full z-10">
+          <div className="transform transition-transform w-full max-w-[768px] tablet:rounded-2xl bg-primary-100/90 backdrop-blur-sm p-6 text-center shadow-lg">
             {selectedSlots.length === 0 && selectedSchedule ? (
               <div className="flex flex-col items-center justify-center w-full">
                 <h3 className="mb-2 heading-2 text-primary-500">스케줄 정보</h3>
@@ -429,59 +477,6 @@ const SchedulePage = () => {
           </div>
         </div>
       )}
-
-      {/* Schedule Grid */}
-      <div className="p-4">
-        <div className="overflow-auto scrollbar-hide">
-          <div className="w-[100vw] tablet:w-[960px] grid grid-cols-[64px,repeat(7,1fr)] gap-2">
-            {/* Header */}
-            <div className="min-w-[54px] p-2 font-bold text-center bg-grayscale-200 select-none">
-              Time
-            </div>
-            {days.map((day) => (
-              <div
-                key={day}
-                className="p-2 font-bold text-center select-none bg-grayscale-200"
-              >
-                {day}
-              </div>
-            ))}
-
-            {/* Time Slots */}
-            {timeSlots.map((time, rowIndex) => (
-              <React.Fragment key={rowIndex}>
-                {/* Time Column */}
-                <div className="min-w-[54px] p-2 font-bold text-center bg-grayscale-100 select-none">
-                  {time}
-                </div>
-                {days.map((_, colIndex) => {
-                  const slotIndex = colIndex * timeSlots.length + rowIndex;
-                  const isSelected = selectedSlots.includes(slotIndex);
-                  const schedule = schedules.find((s) =>
-                    s.time_indices.includes(slotIndex)
-                  );
-
-                  return (
-                    <div
-                      key={slotIndex}
-                      className={`p-2 border rounded ${
-                        schedule
-                          ? `${getColorForTitle(schedule.title)} text-white`
-                          : isSelected
-                            ? "bg-primary-100 border-primary-300"
-                            : "bg-grayscale-50 cursor-pointer"
-                        }`}
-                      onClick={() => handleSlotClick(slotIndex)}
-                    >
-                      {schedule ? schedule.title : ""}
-                    </div>
-                  );
-                })}
-              </React.Fragment>
-            ))}
-          </div>
-        </div>
-      </div>
     </div>
   );
 };
-- 
GitLab


From b15f63c406627313cf5408652edabcbd6794cfd5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=8C=80=ED=9D=AC?= <joedaehui@ajou.ac.kr>
Date: Sun, 8 Dec 2024 19:01:33 +0900
Subject: [PATCH 4/6] =?UTF-8?q?style:=20=EC=8A=A4=EC=BC=80=EC=A4=84=20?=
 =?UTF-8?q?=ED=86=B5=ED=95=A9=20=EB=B0=8F=20=EB=8D=94=EB=B3=B4=EA=B8=B0=20?=
 =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80=20(#13)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/pages/SchedulePage.jsx | 246 ++++++++++++++++++++++---------------
 1 file changed, 144 insertions(+), 102 deletions(-)

diff --git a/src/pages/SchedulePage.jsx b/src/pages/SchedulePage.jsx
index 01c851d..d072524 100644
--- a/src/pages/SchedulePage.jsx
+++ b/src/pages/SchedulePage.jsx
@@ -22,70 +22,74 @@ const generateTimeSlots = () => {
 
 const days = ["월", "화", "수", "목", "금", "토", "일"];
 
-const dummySchedules = [
-  {
-    id: 1,
-    user_id: 1,
-    title: "알고리즘 스터디",
-    is_fixed: true,
-    time_indices: [36, 37, 38, 39],
-    createdAt: "2024-12-02T09:52:00.000Z",
-    updatedAt: "2024-12-02T09:52:00.000Z",
-  },
-  {
-    id: 5,
-    user_id: 1,
-    title: "웹시설 팀플",
-    is_fixed: true,
-    time_indices: [165, 166, 167, 255, 256, 257],
-    createdAt: "2024-12-02T09:54:53.000Z",
-    updatedAt: "2024-12-02T09:54:53.000Z",
-  },
-  {
-    id: 11,
-    user_id: 1,
-    title: "점심약속",
-    is_fixed: false,
-    time_indices: [240, 241, 242],
-    createdAt: "2024-12-02T09:54:53.000Z",
-    updatedAt: "2024-12-02T09:54:53.000Z",
-  },
-  {
-    id: 14,
-    user_id: 1,
-    title: "롤 5:5",
-    is_fixed: true,
-    time_indices: [302, 303, 304, 305, 306, 307],
-    createdAt: "2024-12-02T09:54:53.000Z",
-    updatedAt: "2024-12-02T09:54:53.000Z",
-  },
-  {
-    id: 20,
-    user_id: 1,
-    title: "토트넘 vs 첼시 경기",
-    is_fixed: true,
-    time_indices: [13, 14, 15, 16, 17, 18],
-    createdAt: "2024-12-02T09:54:53.000Z",
-    updatedAt: "2024-12-02T09:54:53.000Z",
-  }
-];
+// const dummySchedules = [
+//   {
+//     id: 1,
+//     user_id: 1,
+//     title: "알고리즘 스터디",
+//     is_fixed: true,
+//     time_indices: [36, 37, 38, 39],
+//     createdAt: "2024-12-02T09:52:00.000Z",
+//     updatedAt: "2024-12-02T09:52:00.000Z",
+//   },
+//   {
+//     id: 5,
+//     user_id: 1,
+//     title: "웹시설 팀플",
+//     is_fixed: true,
+//     time_indices: [165, 166, 167, 255, 256, 257],
+//     createdAt: "2024-12-02T09:54:53.000Z",
+//     updatedAt: "2024-12-02T09:54:53.000Z",
+//   },
+//   {
+//     id: 11,
+//     user_id: 1,
+//     title: "점심약속",
+//     is_fixed: false,
+//     time_indices: [240, 241, 242],
+//     createdAt: "2024-12-02T09:54:53.000Z",
+//     updatedAt: "2024-12-02T09:54:53.000Z",
+//   },
+//   {
+//     id: 14,
+//     user_id: 1,
+//     title: "롤 5:5",
+//     is_fixed: true,
+//     time_indices: [302, 303, 304, 305, 306, 307],
+//     createdAt: "2024-12-02T09:54:53.000Z",
+//     updatedAt: "2024-12-02T09:54:53.000Z",
+//   },
+//   {
+//     id: 20,
+//     user_id: 1,
+//     title: "토트넘 vs 첼시 경기",
+//     is_fixed: true,
+//     time_indices: [13, 14, 15, 16, 17, 18],
+//     createdAt: "2024-12-02T09:54:53.000Z",
+//     updatedAt: "2024-12-02T09:54:53.000Z",
+//   },
+//   {
+//     id: 26,
+//     user_id: 1,
+//     title: "아침 구보",
+//     is_fixed: true,
+//     time_indices: [34, 35, 130, 131, 226, 227, 322, 323, 418, 419, 514, 515, 610, 611],
+//     createdAt: "2024-12-02T09:54:53.000Z",
+//     updatedAt: "2024-12-02T09:54:53.000Z",
+//   },
+// ];
 
 const colorClasses = [
-  'bg-indigo-300',
-  'bg-purple-300',
-  'bg-pink-300',
-  'bg-blue-300',
-  'bg-green-300',
-  'bg-yellow-300',
-  'bg-red-300',
-  'bg-orange-300',
-  'bg-teal-300',
-  'bg-cyan-300',
-  'bg-rose-300',
-  'bg-violet-300',
-  'bg-fuchsia-300',
-  'bg-emerald-300',
-  'bg-lime-300'
+  'bg-indigo-300 hover:bg-indigo-400',
+  'bg-purple-300 hover:bg-purple-400',
+  'bg-pink-300 hover:bg-pink-400',
+  'bg-blue-300 hover:bg-blue-400',
+  'bg-green-300 hover:bg-green-400',
+  'bg-yellow-300 hover:bg-yellow-400',
+  'bg-red-300 hover:bg-red-400',
+  'bg-orange-300 hover:bg-orange-400',
+  'bg-teal-300 hover:bg-teal-400',
+  'bg-cyan-300 hover:bg-cyan-400',
 ];
 const SchedulePage = () => {
   const timeSlots = generateTimeSlots();
@@ -97,13 +101,21 @@ const SchedulePage = () => {
   const [newTitle, setNewTitle] = useState("");
   const [isFixed, setIsFixed] = useState(true);
   const [titleColorMap, setTitleColorMap] = useState(new Map());
+  const [showAllTimeSlot, setShowAllTimeSlot] = useState(false);
 
   useEffect(() => {
     // API
     const initializeSchedules = async () => {
       try {
         const data = await fetchAllSchedules();
-        setSchedules(data);
+
+        // 스케줄 병합을 위해서 사용
+        const sortedSchedules = [...data].sort((a, b) => {
+          const aMin = Math.min(...a.time_indices);
+          const bMin = Math.min(...b.time_indices);
+          return aMin - bMin;
+        });
+        setSchedules(sortedSchedules);
       } catch (error) {
         console.error("Failed to load schedules", error);
       }
@@ -111,8 +123,8 @@ const SchedulePage = () => {
 
     initializeSchedules();
 
-    // 임시 코드
-    setSchedules(dummySchedules);
+    // 임시 코드 
+    // setSchedules(dummySchedules);
   }, []);
 
   useEffect(() => {
@@ -278,13 +290,47 @@ const SchedulePage = () => {
     const timeSlotIndex = timeIndex % 96;
     const hour = Math.floor(timeSlotIndex / 4);
     const minute = (timeSlotIndex % 4) * 15;
-    
     const day = days[dayIndex];
     const time = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
-    
     return `${day} ${time}`;
   };
 
+  // 스케줄 통합해서 보여주기
+  const renderTimeSlot = (slotIndex, rowIndex, colIndex) => {
+    const schedule = schedules.find((s) => s.time_indices.includes(slotIndex));
+    const isSelected = selectedSlots.includes(slotIndex);
+
+    const isFirstSlot = schedule &&
+      !schedule.time_indices.includes(slotIndex - 1) &&
+      Math.floor((slotIndex - 1) / 96) === Math.floor(slotIndex / 96);
+
+    const isLastSlot = schedule &&
+      !schedule.time_indices.includes(slotIndex + 1) &&
+      Math.floor((slotIndex + 1) / 96) === Math.floor(slotIndex / 96);
+
+    return (
+      <div
+        key={slotIndex}
+        className={`p-2 border ${schedule
+          ? `${getColorForTitle(schedule.title)} text-white
+               ${!isFirstSlot && !isLastSlot ? 'border-t-0 border-b-0' : ''}
+               ${!isFirstSlot ? 'border-t-0' : ''}
+               ${!isLastSlot ? 'border-b-0' : ''}`
+          : isSelected
+            ? "bg-primary-100 border-primary-300"
+            : "bg-grayscale-50"
+          } cursor-pointer`}
+        onClick={() => handleSlotClick(slotIndex)}
+      >
+        {isFirstSlot ? schedule?.title : ""}
+      </div>
+    );
+  };
+
+  const filterTimeSlots = (time) => {
+    const hour = parseInt(time.split(":")[0]);
+    return showAllTimeSlot || (hour >= 8 && hour <= 18);
+  };
 
   return (
     <div className="min-h-screen bg-grayscale-50">
@@ -311,11 +357,23 @@ const SchedulePage = () => {
           </div>
         </label>
       </div>
-  
+
+      {/* 더보기 버튼 */}
+      <div className="flex justify-center mt-4">
+        <Label
+          theme="indigo"
+          size="lg"
+          className="cursor-pointer"
+          onClick={() => setShowAllTimeSlot(!showAllTimeSlot)}
+        >
+          {showAllTimeSlot ? "시간 접기" : "전체 시간 보기"}
+        </Label>
+      </div>
+
       {/* Schedule Grid */}
       <div className="p-4 pb-[210px]">
         <div className="overflow-auto scrollbar-hide">
-          <div className="w-[100vw] tablet:w-[960px] grid grid-cols-[64px,repeat(7,1fr)] gap-2">
+          <div className="w-[100vw] tablet:w-[960px] grid grid-cols-[64px,repeat(7,1fr)] gap-0">
             {/* Header */}
             <div className="min-w-[54px] p-2 font-bold text-center bg-grayscale-200 select-none">
               Time
@@ -325,43 +383,27 @@ const SchedulePage = () => {
                 {day}
               </div>
             ))}
-  
+
             {/* Time Slots */}
-            {timeSlots.map((time, rowIndex) => (
-              <React.Fragment key={rowIndex}>
-                {/* Time Column */}
-                <div className="min-w-[54px] p-2 font-bold text-center bg-grayscale-100 select-none">
-                  {time}
-                </div>
-                {days.map((_, colIndex) => {
-                  const slotIndex = colIndex * timeSlots.length + rowIndex;
-                  const isSelected = selectedSlots.includes(slotIndex);
-                  const schedule = schedules.find((s) =>
-                    s.time_indices.includes(slotIndex)
-                  );
-  
-                  return (
-                    <div
-                      key={slotIndex}
-                      className={`p-2 border rounded ${
-                        schedule 
-                          ? `${getColorForTitle(schedule.title)} text-white`
-                          : isSelected 
-                            ? "bg-primary-100 border-primary-300" 
-                            : "bg-grayscale-50"
-                      } cursor-pointer`}
-                      onClick={() => handleSlotClick(slotIndex)}
-                    >
-                      {schedule ? schedule.title : ""}
-                    </div>
-                  );
-                })}
-              </React.Fragment>
-            ))}
+            {timeSlots.map((time, rowIndex) => {
+              if (!filterTimeSlots(time)) return null;
+
+              return (
+                <React.Fragment key={rowIndex}>
+                  <div className="min-w-[54px] p-2 font-bold text-center bg-grayscale-100 select-none">
+                    {time}
+                  </div>
+                  {days.map((_, colIndex) => {
+                    const slotIndex = colIndex * timeSlots.length + rowIndex;
+                    return renderTimeSlot(slotIndex, rowIndex, colIndex);
+                  })}
+                </React.Fragment>
+              );
+            })}
           </div>
         </div>
       </div>
-  
+
       {/* Sticky Container in Edit Mode */}
       {isEditMode && (
         <div className="fixed bottom-0 right-0 flex items-center justify-center w-full z-10">
-- 
GitLab


From f0b4997cd54cc752f3ed82a88b231e7de1cfe40c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=8C=80=ED=9D=AC?= <joedaehui@ajou.ac.kr>
Date: Sun, 8 Dec 2024 20:28:59 +0900
Subject: [PATCH 5/6] =?UTF-8?q?style:=20cursor-not-allowed=20=EC=B6=94?=
 =?UTF-8?q?=EA=B0=80=20(#13)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/pages/SchedulePage.jsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/pages/SchedulePage.jsx b/src/pages/SchedulePage.jsx
index d072524..f352172 100644
--- a/src/pages/SchedulePage.jsx
+++ b/src/pages/SchedulePage.jsx
@@ -312,7 +312,7 @@ const SchedulePage = () => {
       <div
         key={slotIndex}
         className={`p-2 border ${schedule
-          ? `${getColorForTitle(schedule.title)} text-white
+          ? `${getColorForTitle(schedule.title)} text-white cursor-not-allowed
                ${!isFirstSlot && !isLastSlot ? 'border-t-0 border-b-0' : ''}
                ${!isFirstSlot ? 'border-t-0' : ''}
                ${!isLastSlot ? 'border-b-0' : ''}`
-- 
GitLab


From c38f1a8b36e2615dac8bb78fa8c717a0c73d9b3f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=84=9D=EC=B0=AC=20=EC=9C=A4?= <ysc0731@ajou.ac.kr>
Date: Sun, 8 Dec 2024 20:40:56 +0900
Subject: [PATCH 6/6] =?UTF-8?q?design:=20=EC=8A=A4=EC=BC=80=EB=91=98=20?=
 =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?=
 =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#13)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/pages/SchedulePage.jsx | 156 ++++++++++++++++++++++---------------
 1 file changed, 92 insertions(+), 64 deletions(-)

diff --git a/src/pages/SchedulePage.jsx b/src/pages/SchedulePage.jsx
index d072524..5febb0c 100644
--- a/src/pages/SchedulePage.jsx
+++ b/src/pages/SchedulePage.jsx
@@ -7,6 +7,7 @@ import {
   fetchAllSchedules,
   updateSchedule,
 } from "../api/schedule";
+import Button from "../components/Button";
 
 const generateTimeSlots = () => {
   const timeSlots = [];
@@ -80,16 +81,16 @@ const days = ["월", "화", "수", "목", "금", "토", "일"];
 // ];
 
 const colorClasses = [
-  'bg-indigo-300 hover:bg-indigo-400',
-  'bg-purple-300 hover:bg-purple-400',
-  'bg-pink-300 hover:bg-pink-400',
-  'bg-blue-300 hover:bg-blue-400',
-  'bg-green-300 hover:bg-green-400',
-  'bg-yellow-300 hover:bg-yellow-400',
-  'bg-red-300 hover:bg-red-400',
-  'bg-orange-300 hover:bg-orange-400',
-  'bg-teal-300 hover:bg-teal-400',
-  'bg-cyan-300 hover:bg-cyan-400',
+  "bg-indigo-300 hover:bg-indigo-400",
+  "bg-purple-300 hover:bg-purple-400",
+  "bg-pink-300 hover:bg-pink-400",
+  "bg-blue-300 hover:bg-blue-400",
+  "bg-green-300 hover:bg-green-400",
+  "bg-yellow-300 hover:bg-yellow-400",
+  "bg-red-300 hover:bg-red-400",
+  "bg-orange-300 hover:bg-orange-400",
+  "bg-teal-300 hover:bg-teal-400",
+  "bg-cyan-300 hover:bg-cyan-400",
 ];
 const SchedulePage = () => {
   const timeSlots = generateTimeSlots();
@@ -123,13 +124,13 @@ const SchedulePage = () => {
 
     initializeSchedules();
 
-    // 임시 코드 
+    // 임시 코드
     // setSchedules(dummySchedules);
   }, []);
 
   useEffect(() => {
     const newColorMap = new Map();
-    schedules.forEach(schedule => {
+    schedules.forEach((schedule) => {
       if (!newColorMap.has(schedule.title)) {
         newColorMap.set(
           schedule.title,
@@ -279,7 +280,7 @@ const SchedulePage = () => {
   const getColorForTitle = (title) => {
     if (!titleColorMap.has(title)) {
       const newColor = colorClasses[titleColorMap.size % colorClasses.length];
-      setTitleColorMap(prev => new Map(prev).set(title, newColor));
+      setTitleColorMap((prev) => new Map(prev).set(title, newColor));
       return newColor;
     }
     return titleColorMap.get(title);
@@ -291,7 +292,9 @@ const SchedulePage = () => {
     const hour = Math.floor(timeSlotIndex / 4);
     const minute = (timeSlotIndex % 4) * 15;
     const day = days[dayIndex];
-    const time = `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
+    const time = `${hour.toString().padStart(2, "0")}:${minute
+      .toString()
+      .padStart(2, "0")}`;
     return `${day} ${time}`;
   };
 
@@ -300,26 +303,29 @@ const SchedulePage = () => {
     const schedule = schedules.find((s) => s.time_indices.includes(slotIndex));
     const isSelected = selectedSlots.includes(slotIndex);
 
-    const isFirstSlot = schedule &&
+    const isFirstSlot =
+      schedule &&
       !schedule.time_indices.includes(slotIndex - 1) &&
       Math.floor((slotIndex - 1) / 96) === Math.floor(slotIndex / 96);
 
-    const isLastSlot = schedule &&
+    const isLastSlot =
+      schedule &&
       !schedule.time_indices.includes(slotIndex + 1) &&
       Math.floor((slotIndex + 1) / 96) === Math.floor(slotIndex / 96);
 
     return (
       <div
         key={slotIndex}
-        className={`p-2 border ${schedule
-          ? `${getColorForTitle(schedule.title)} text-white
-               ${!isFirstSlot && !isLastSlot ? 'border-t-0 border-b-0' : ''}
-               ${!isFirstSlot ? 'border-t-0' : ''}
-               ${!isLastSlot ? 'border-b-0' : ''}`
-          : isSelected
+        className={`p-2 border ${
+          schedule
+            ? `${getColorForTitle(schedule.title)} text-white
+               ${!isFirstSlot && !isLastSlot ? "border-t-0 border-b-0" : ""}
+               ${!isFirstSlot ? "border-t-0" : ""}
+               ${!isLastSlot ? "border-b-0" : ""}`
+            : isSelected
             ? "bg-primary-100 border-primary-300"
             : "bg-grayscale-50"
-          } cursor-pointer`}
+        } cursor-pointer`}
         onClick={() => handleSlotClick(slotIndex)}
       >
         {isFirstSlot ? schedule?.title : ""}
@@ -336,9 +342,9 @@ const SchedulePage = () => {
     <div className="min-h-screen bg-grayscale-50">
       {/* Toggle View/Edit Mode */}
       <div className="flex items-center justify-between p-4 bg-white shadow">
-        <h1 className="heading-1">Schedule</h1>
+        <h1 className="heading-2">내 시간표</h1>
         <label className="flex items-center space-x-3 cursor-pointer">
-          <span className="title-1 text-primary-500">Edit Mode</span>
+          <span className="title-1 text-primary-500">수정 모드</span>
           <div
             className={`relative w-12 h-6 rounded-full transition-colors ${
               isEditMode ? "bg-primary-500" : "bg-grayscale-300"
@@ -360,14 +366,14 @@ const SchedulePage = () => {
 
       {/* 더보기 버튼 */}
       <div className="flex justify-center mt-4">
-        <Label
-          theme="indigo"
-          size="lg"
-          className="cursor-pointer"
+        <Button
+          theme="white"
+          size="sm"
+          className="w-full mx-4 hover:bg-grayscale-50"
           onClick={() => setShowAllTimeSlot(!showAllTimeSlot)}
         >
           {showAllTimeSlot ? "시간 접기" : "전체 시간 보기"}
-        </Label>
+        </Button>
       </div>
 
       {/* Schedule Grid */}
@@ -379,7 +385,10 @@ const SchedulePage = () => {
               Time
             </div>
             {days.map((day) => (
-              <div key={day} className="p-2 font-bold text-center select-none bg-grayscale-200">
+              <div
+                key={day}
+                className="p-2 font-bold text-center select-none bg-grayscale-200"
+              >
                 {day}
               </div>
             ))}
@@ -406,7 +415,7 @@ const SchedulePage = () => {
 
       {/* Sticky Container in Edit Mode */}
       {isEditMode && (
-        <div className="fixed bottom-0 right-0 flex items-center justify-center w-full z-10">
+        <div className="fixed bottom-0 right-0 z-10 flex items-center justify-center w-full">
           <div className="transform transition-transform w-full max-w-[768px] tablet:rounded-2xl bg-primary-100/90 backdrop-blur-sm p-6 text-center shadow-lg">
             {selectedSlots.length === 0 && selectedSchedule ? (
               <div className="flex flex-col items-center justify-center w-full">
@@ -458,35 +467,50 @@ const SchedulePage = () => {
                   type="text"
                   value={newTitle}
                   onChange={(e) => setNewTitle(e.target.value)}
-                  placeholder="Enter title"
-                  className="w-full p-2 mb-4 border rounded shadow-input-box"
+                  placeholder="스케줄 제목"
+                  className="w-full p-2 px-4 mb-4 border rounded-full shadow-input-box"
                 />
                 <div className="flex items-center justify-center mb-4 space-x-4">
-                  <label className="flex items-center space-x-2">
-                    <input
-                      type="radio"
-                      name="is_fixed"
-                      value={true}
-                      checked={isFixed === true}
-                      onChange={() => setIsFixed(true)}
-                    />
-                    <span className="body-1">고정 스케줄</span>
-                  </label>
-                  <label className="flex items-center space-x-2">
-                    <input
-                      type="radio"
-                      name="is_fixed"
-                      value={false}
-                      checked={isFixed === false}
-                      onChange={() => setIsFixed(false)}
-                    />
-                    <span className="body-1">유동 스케줄</span>
-                  </label>
+                  <div className="flex items-center space-x-4">
+                    <label className="flex items-center cursor-pointer">
+                      <input
+                        type="radio"
+                        name="is_fixed"
+                        value={true}
+                        checked={isFixed === true}
+                        onChange={() => setIsFixed(true)}
+                        className="hidden peer"
+                      />
+                      <div className="flex items-center justify-center w-5 h-5 border-2 border-gray-400 rounded-full peer-checked:border-tertiary-500 peer-checked:bg-tertiary-500">
+                        <div className="w-2.5 h-2.5 bg-white rounded-full peer-checked:bg-white"></div>
+                      </div>
+                      <span className="ml-2 text-sm font-medium peer-checked:text-tertiary-500">
+                        고정 스케줄
+                      </span>
+                    </label>
+
+                    <label className="flex items-center cursor-pointer">
+                      <input
+                        type="radio"
+                        name="is_fixed"
+                        value={false}
+                        checked={isFixed === false}
+                        onChange={() => setIsFixed(false)}
+                        className="hidden peer"
+                      />
+                      <div className="flex items-center justify-center w-5 h-5 border-2 border-gray-400 rounded-full peer-checked:border-primary-500 peer-checked:bg-primary-500">
+                        <div className="w-2.5 h-2.5 bg-white rounded-full peer-checked:bg-white"></div>
+                      </div>
+                      <span className="ml-2 text-sm font-medium peer-checked:text-primary-500">
+                        유동 스케줄
+                      </span>
+                    </label>
+                  </div>
                 </div>
-                <div className="mb-4 body-1">
-                  <span>선택된 시간:</span>
+                <span className="heading-4">선택된 시간</span>
+                <div className="flex flex-wrap gap-1 p-2 m-2 border rounded-lg body-1 border-primary-500">
                   {selectedSlots.map((time_idx) => (
-                    <Label key={time_idx} theme="indigo" size="sm">
+                    <Label key={time_idx} theme="solid" size="sm">
                       {convertIndexToTime(time_idx)}
                     </Label>
                   ))}
@@ -499,19 +523,23 @@ const SchedulePage = () => {
                     수정 완료
                   </button>
                 ) : (
-                  <div className="flex justify-center mt-4 space-x-4">
-                    <button
-                      className="px-4 py-2 font-bold text-white rounded bg-tertiary-900"
+                  <div className="flex justify-center w-full mt-4 space-x-2">
+                    <Button
+                      theme="indigo"
+                      size="md"
+                      className="flex-1"
                       onClick={() => handleCancelSchedule()}
                     >
                       취소
-                    </button>
-                    <button
-                      className="px-4 py-2 font-bold text-white rounded bg-gradient-pink"
+                    </Button>
+                    <Button
+                      theme="pink"
+                      size="md"
+                      className="flex-1"
                       onClick={() => handleCreateSchedule()}
                     >
                       추가
-                    </button>
+                    </Button>
                   </div>
                 )}
               </>
-- 
GitLab