From deaa10181a7ec7fb386df78cc2f5925fcdbc1f61 Mon Sep 17 00:00:00 2001 From: dvirlabs <114520947+dvirlabs@users.noreply.github.com> Date: Wed, 10 Dec 2025 00:54:39 +0200 Subject: [PATCH] Add calander --- backend/__pycache__/main.cpython-312.pyc | Bin 4296 -> 7044 bytes frontend/src/App.css | 11 ++ frontend/src/App.jsx | 6 +- frontend/src/components/Calendar.jsx | 92 ++++++++++++++ frontend/src/style/Calendar.css | 153 +++++++++++++++++++++++ frontend/src/style/Clock.css | 5 +- 6 files changed, 263 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/Calendar.jsx create mode 100644 frontend/src/style/Calendar.css diff --git a/backend/__pycache__/main.cpython-312.pyc b/backend/__pycache__/main.cpython-312.pyc index a716d6c41a0676302b4913641f7868024b50d952..ffb9f7653afb50f51d881e8596c445d46d6c7f23 100644 GIT binary patch literal 7044 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 - +
+ + +
{/* 🔹 לוגו וכותרת במרכז */}
diff --git a/frontend/src/components/Calendar.jsx b/frontend/src/components/Calendar.jsx new file mode 100644 index 0000000..aba8c9f --- /dev/null +++ b/frontend/src/components/Calendar.jsx @@ -0,0 +1,92 @@ +import { useState, useEffect } from 'react'; +import { FaChevronDown } from 'react-icons/fa'; +import '../style/Calendar.css'; + +function Calendar() { + const [now, setNow] = useState(new Date()); + const [collapsed, setCollapsed] = useState(false); + const [currentMonth, setCurrentMonth] = useState(new Date()); + + useEffect(() => { + const timer = setInterval(() => setNow(new Date()), 1000); + return () => clearInterval(timer); + }, []); + + const getDaysInMonth = (date) => { + const year = date.getFullYear(); + const month = date.getMonth(); + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + const daysInMonth = lastDay.getDate(); + const startingDayOfWeek = firstDay.getDay(); + + return { daysInMonth, startingDayOfWeek, year, month }; + }; + + const { daysInMonth, startingDayOfWeek, year, month } = getDaysInMonth(currentMonth); + + const days = []; + for (let i = 0; i < startingDayOfWeek; i++) { + days.push(null); + } + for (let i = 1; i <= daysInMonth; i++) { + days.push(i); + } + + const isToday = (day) => { + return day === now.getDate() && + month === now.getMonth() && + year === now.getFullYear(); + }; + + const monthNames = ['January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December']; + + const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + + const prevMonth = () => { + setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1)); + }; + + const nextMonth = () => { + setCurrentMonth(new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1)); + }; + + return ( +
+
setCollapsed(!collapsed)}> + {now.toLocaleDateString('en-GB', { + weekday: 'short', + day: 'numeric', + month: 'short', + year: 'numeric' + })} + +
+ +
+
+ + {monthNames[month]} {year} + +
+ +
+ {dayNames.map(day => ( +
{day}
+ ))} + {days.map((day, idx) => ( +
+ {day} +
+ ))} +
+
+
+ ); +} + +export default Calendar; diff --git a/frontend/src/style/Calendar.css b/frontend/src/style/Calendar.css new file mode 100644 index 0000000..9376db8 --- /dev/null +++ b/frontend/src/style/Calendar.css @@ -0,0 +1,153 @@ +.calendar-container { + font-family: 'Rajdhani', sans-serif; + color: #00f0ff; + text-shadow: 0 0 6px rgba(0, 255, 255, 0.3); + user-select: none; + background: rgba(0, 20, 40, 0.8); + border: 1px solid rgba(0, 240, 255, 0.3); + border-radius: 10px; + padding: 0.7rem; + backdrop-filter: blur(10px); + display: flex; + flex-direction: column; + overflow: hidden; + transition: all 0.3s ease; + width: auto; + position: absolute; + right: 200px; +} + +.calendar-container.collapsed { + width: auto; + padding: 0.5rem; + background: transparent; + border: none; + backdrop-filter: none; +} + +.calendar-header { + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + padding-bottom: 0.4rem; + min-width: 30px; +} + +.calendar-date { + font-size: 0.85rem; + color: #999; + white-space: nowrap; + overflow: hidden; + transition: all 0.3s ease; +} + +.calendar-date.collapsed { + width: 0; + opacity: 0; +} + +.calendar-toggle-icon { + font-size: 1.4rem; + color: #00f0ff; + transition: transform 0.3s ease; + flex-shrink: 0; + transform: rotate(-90deg); +} + +.calendar-toggle-icon.collapsed { + transform: rotate(90deg); +} + +.calendar-body { + width: 220px; + overflow: hidden; + transition: all 0.3s ease; + opacity: 1; +} + +.calendar-body.collapsed { + width: 0; + opacity: 0; +} + +.calendar-month-nav { + display: flex; + justify-content: space-between; + align-items: center; + margin: 0.5rem 0; + padding-top: 0.4rem; + border-top: 1px solid rgba(0, 240, 255, 0.2); +} + +.calendar-month-year { + font-size: 0.9rem; + font-weight: 500; + color: #00f0ff; +} + +.calendar-nav-btn { + background: transparent; + border: 1px solid rgba(0, 240, 255, 0.3); + color: #00f0ff; + cursor: pointer; + font-size: 1.2rem; + width: 24px; + height: 24px; + border-radius: 5px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + padding: 0; + line-height: 1; +} + +.calendar-nav-btn:hover { + background: rgba(0, 240, 255, 0.1); + border-color: #00f0ff; + transform: scale(1.1); +} + +.calendar-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 2px; + margin-top: 0.5rem; +} + +.calendar-day-name { + text-align: center; + font-size: 0.65rem; + color: #00f0ff; + font-weight: 500; + padding: 0.2rem 0; + opacity: 0.7; +} + +.calendar-day { + text-align: center; + padding: 0.35rem; + font-size: 0.75rem; + color: #999; + border-radius: 4px; + transition: all 0.2s ease; +} + +.calendar-day:not(.empty):hover { + background: rgba(0, 240, 255, 0.1); + color: #00f0ff; + cursor: pointer; +} + +.calendar-day.today { + background: rgba(0, 240, 255, 0.2); + color: #00f0ff; + font-weight: bold; + border: 1px solid #00f0ff; + box-shadow: 0 0 8px rgba(0, 240, 255, 0.4); +} + +.calendar-day.empty { + visibility: hidden; +} diff --git a/frontend/src/style/Clock.css b/frontend/src/style/Clock.css index cee9b37..08e90dd 100644 --- a/frontend/src/style/Clock.css +++ b/frontend/src/style/Clock.css @@ -1,7 +1,4 @@ .clock-container { - position: absolute; - top: 1.5rem; - right: 2rem; text-align: right; font-family: 'Rajdhani', sans-serif; color: #00f0ff; @@ -9,6 +6,8 @@ font-size: 1rem; line-height: 1.2; user-select: none; + position: absolute; + right: 0; } .clock-time {