Skip to content
Snippets Groups Projects
Commit a9faac79 authored by 준현 강's avatar 준현 강
Browse files

[ADD] 가장 많은 사람들이 가능한 일정 추가

[EDIT] media query 추가
parent 19f7676d
No related branches found
No related tags found
No related merge requests found
...@@ -115,7 +115,7 @@ const CalendarWeek = ({ ...@@ -115,7 +115,7 @@ const CalendarWeek = ({
const weekDates = weeks[currentWeekIndex] || []; const weekDates = weeks[currentWeekIndex] || [];
return ( return (
<div className="wrap"> <div className="calendarWeekContainer wrap">
<div className="button-container"> <div className="button-container">
<button onClick={handlePrevWeek} disabled={currentWeekIndex === 0}> <button onClick={handlePrevWeek} disabled={currentWeekIndex === 0}>
Prev Week Prev Week
......
...@@ -13,7 +13,70 @@ function ResultMakeForm() { ...@@ -13,7 +13,70 @@ function ResultMakeForm() {
const [hoveredInfo, setHoveredInfo] = useState(null); const [hoveredInfo, setHoveredInfo] = useState(null);
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [mostAvailableDates, setMostAvailableDates] = useState([]);
const [topAvailableDates, setTopAvailableDates] = useState([]);
useEffect(() => {
if (meetingData && meetingData.participants) {
calculateTopAvailableDates();
}
}, [meetingData]);
const calculateTopAvailableDates = () => {
let dateAvailability = {};
meetingData.participants.forEach((participant) => {
participant.availableSchedules.forEach((schedule) => {
if (!dateAvailability[schedule.availableDate]) {
dateAvailability[schedule.availableDate] = {};
}
schedule.availableTimes.forEach((time) => {
if (!dateAvailability[schedule.availableDate][time]) {
dateAvailability[schedule.availableDate][time] = 0;
}
dateAvailability[schedule.availableDate][time]++;
});
});
});
let dateCounts = Object.entries(dateAvailability).map(([date, times]) => {
let maxCount = Math.max(...Object.values(times));
let count = Object.values(times).filter((val) => val === maxCount).length;
return { date, count, maxCount };
});
dateCounts.sort((a, b) => b.maxCount - a.maxCount || b.count - a.count);
setTopAvailableDates(dateCounts.slice(0, 5));
};
useEffect(() => {
if (meetingData && meetingData.participants) {
calculateMostAvailableDates();
}
}, [meetingData]);
const calculateMostAvailableDates = () => {
let dateAvailabilityCount = {};
meetingData.participants.forEach((participant) => {
participant.availableSchedules.forEach((schedule) => {
if (!dateAvailabilityCount[schedule.availableDate]) {
dateAvailabilityCount[schedule.availableDate] = new Set();
}
schedule.availableTimes.forEach((time) => {
dateAvailabilityCount[schedule.availableDate].add(time);
});
});
});
const sortedDates = Object.entries(dateAvailabilityCount)
.map(([date, times]) => ({ date, count: times.size }))
.sort((a, b) => b.count - a.count)
.slice(0, 5);
setMostAvailableDates(sortedDates);
};
useEffect(() => { useEffect(() => {
const fetchMeetingData = async () => { const fetchMeetingData = async () => {
setIsLoading(true); setIsLoading(true);
...@@ -141,15 +204,15 @@ function ResultMakeForm() { ...@@ -141,15 +204,15 @@ function ResultMakeForm() {
<h1 className="title-box">{meetingData?.title}</h1> <h1 className="title-box">{meetingData?.title}</h1>
{meetingData.maxParticipants && ( {meetingData.maxParticipants && (
<div> <div>
현재 완료한 인원수 {meetingData?.currentParticipants} /{" "} 현재 완료한 인원수 : {meetingData?.currentParticipants} /{" "}
{meetingData?.maxParticipants} {meetingData?.maxParticipants}
</div> </div>
)} )}
{!meetingData.maxParticipants && ( {!meetingData.maxParticipants && (
<div>현재 완료한 인원수 {meetingData?.currentParticipants}</div> <div>현재 완료한 인원수 : {meetingData?.currentParticipants}</div>
)} )}
<div>종료까지 남은 시간 {timeLeft}</div> <div>종료까지 남은 시간 : {timeLeft}</div>
<button onClick={handleEdit}>수정하기</button> <button onClick={handleEdit}>수정하기</button>
<button onClick={closeMeeting}>투표 종료하기</button> <button onClick={closeMeeting}>투표 종료하기</button>
</div> </div>
...@@ -174,33 +237,42 @@ function ResultMakeForm() { ...@@ -174,33 +237,42 @@ function ResultMakeForm() {
onRequestClose={handleModalClose} onRequestClose={handleModalClose}
onSubmit={handlePasswordSubmit} onSubmit={handlePasswordSubmit}
/> />
<span className="mostTime"> <div className="flex-bottom-container">
<div style={{ textAlign: "center" }}> <span className="mostTime">
가장 많은 사람들이 가능한 일정 <strong style={{ textAlign: "center" }}>
</div> 가장 많은 사람들이 가능한 일정
<ol>//일정 5개 나열</ol> </strong>
</span> <ol>
<span className="possible"> {topAvailableDates.map((dateInfo, index) => (
{!hoveredInfo && ( <li key={index}>
<div> {dateInfo.date} ({dateInfo.maxCount}명이 가능한 시간대:{" "}
<strong>가능한 사람들이 표시됩니다.</strong> {dateInfo.count} )
<p>마우스를 달력 위에 올려보세요!</p> </li>
</div> ))}
)} </ol>
</span>
{hoveredInfo && ( <span className="possible">
<div style={{ textAlign: "center" }}> {!hoveredInfo && (
<strong> <div>
{hoveredInfo.date} {hoveredInfo.time} 가능한 사람: <strong>가능한 사람들이 표시됩니다.</strong>
</strong> <p>마우스를 달력 위에 올려보세요!</p>
<ul> </div>
{hoveredInfo.participants.map((name) => ( )}
<li key={name}>{name}</li>
))} {hoveredInfo && (
</ul> <div style={{ textAlign: "center" }}>
</div> <strong>
)} {hoveredInfo.date} {hoveredInfo.time} 가능한 사람:
</span> </strong>
<ul>
{hoveredInfo.participants.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
</div>
)}
</span>
</div>
</> </>
); );
} }
......
.calendar-container { .calendarWeekContainer .calendar-container {
margin-top: 20px; margin-top: 20px;
width: 100%; width: 100%;
background-color: #5fbdff; background-color: #5fbdff;
} }
.button-container {
.calendarWeekContainer .button-container {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
.button-container button:first-child {
margin-right: 20px; .calendarWeekContainer .button-container button:first-child {
margin-right: 10%;
margin-left: 10%;
} }
.button-container button:last-child {
margin-left: 20px; .calendarWeekContainer .button-container button:last-child {
margin-right: 10%;
margin-left: 10%;
} }
.wrap {
.calendarWeekContainer .wrap {
width: 80%; width: 80%;
} }
table {
.calendarWeekContainer table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
text-align: center; text-align: center;
margin-bottom: 4%; margin-bottom: 4%;
} }
th, .calendarWeekContainer th,
td { .calendarWeekContainer td {
border: 1px solid #ddd; border: 1px solid #ddd;
padding: 10px; padding: 10px;
} }
th { .calendarWeekContainer th {
background-color: #f4f4f4; background-color: #f4f4f4;
} }
td { .calendarWeekContainer td {
background-color: #f4f4f4; background-color: #f4f4f4;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s ease, transform 0.3s ease, transition: background-color 0.3s ease, transform 0.3s ease,
box-shadow 0.3s ease; /* 부드러운 애니메이션 효과 */ box-shadow 0.3s ease;
} }
td:hover {
.calendarWeekContainer td:hover {
background-color: aqua; background-color: aqua;
transform: scale(1.05); /* 셀을 약간 확대 */ transform: scale(1.05);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); /* 셀에 그림자 추가 */ box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
border: 1px solid #5fbdff; /* 셀 주위에 테두리 추가 */ border: 1px solid #5fbdff;
}
.calendarWeekContainer .selected {
background-color: #e0ffe0;
} }
.selected { @media screen and (max-width: 768px) {
background-color: #e0ffe0; /* 선택된 셀의 배경색 */ .calendarWeekContainer .wrap {
display: flex;
width: 100%;
}
} }
...@@ -9,11 +9,11 @@ ...@@ -9,11 +9,11 @@
} }
.form-container label { .form-container label {
display: flex; display: flex;
align-items: center; /* 라디오 버튼과 텍스트를 세로 중앙에 맞춤 */ align-items: center;
margin: 20px 0; /* 라벨 간에 여백을 추가 */ margin: 20px 0;
} }
.form-container input[type="radio"] { .form-container input[type="radio"] {
margin-right: 10px; /* 라디오 버튼과 텍스트 사이의 공간 조정 */ margin-right: 10px;
width: 20%; width: 20%;
} }
...@@ -24,11 +24,9 @@ ...@@ -24,11 +24,9 @@
.possible { .possible {
position: fixed; position: fixed;
right: 0; /* 화면의 오른쪽 끝에 고정 */ right: 0;
top: 60%; /* 화면의 상단으로부터 50%의 위치에 고정 */ top: 60%;
transform: translateY( transform: translateY(-50%);
-50%
); /* 상단 50% 위치에서 자기 자신의 높이의 절반을 위로 이동 */
width: 20%; width: 20%;
border: 1px solid black; border: 1px solid black;
padding: 20px; padding: 20px;
...@@ -45,3 +43,15 @@ ...@@ -45,3 +43,15 @@
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
@media screen and (max-width: 768px) {
.possible {
position: static;
width: 40%;
margin: 200px 20px;
}
.flex-row {
flex-direction: column;
width: 100%;
}
}
...@@ -18,15 +18,60 @@ ...@@ -18,15 +18,60 @@
box-shadow: 0px 1px 5px rgba(95, 189, 255, 0.5); /* 구분선에 그림자 효과 추가 */ box-shadow: 0px 1px 5px rgba(95, 189, 255, 0.5); /* 구분선에 그림자 효과 추가 */
padding-top: 20px; padding-top: 20px;
margin-top: 30px; margin-top: 30px;
width: 50%;
overflow-x: auto;
}
.mostTime,
.possible {
border: 1px solid #ddd;
padding: 20px;
margin: 10px; /* 각 요소 주변의 공간을 더욱 명확히 */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 세련된 그림자 효과 */
border-radius: 8px; /* 모서리를 둥글게 */
background-color: #ffffff; /* 배경색 설정 */
box-sizing: border-box; /* 패딩과 보더를 너비에 포함 */
} }
.mostTime { .mostTime {
position: fixed; position: fixed;
right: 0; right: 0;
top: 30%; top: 30%;
transform: translateY(-50%); transform: translateY(-60%);
width: 20%;
border: 1px solid black;
padding: 20px;
margin-right: 2%;
}
.possible {
position: fixed;
right: 0;
top: 60%;
transform: translateY(-40%);
width: 20%; width: 20%;
border: 1px solid black; border: 1px solid black;
padding: 20px; padding: 20px;
margin-right: 2%; margin-right: 2%;
} }
@media screen and (max-width: 768px) {
.flex-bottom-container {
display: flex;
justify-content: space-between;
width: 100%;
bottom: 0;
left: 0;
}
.mostTime,
.possible {
position: static;
width: 40%;
margin: 200px 20px;
}
.flex-row {
flex-direction: column;
width: 100%;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment