diff --git a/apps.config.js b/apps.config.js index 6437403a..c1d9b425 100644 --- a/apps.config.js +++ b/apps.config.js @@ -6,6 +6,7 @@ import { displayChrome } from './components/apps/chrome'; import { displayTrash } from './components/apps/trash'; import { displayGedit } from './components/apps/gedit'; import { displayAboutVivek } from './components/apps/vivek'; +import { displayCalendar } from './components/apps/calendar'; import { displayTerminalCalc } from './components/apps/calc'; const apps = [ @@ -35,6 +36,15 @@ const apps = [ favourite: true, desktop_shortcut: true, screen: displayAboutVivek, + }, + { + id: "calendar", + title: "Void Calendar", + icon: './themes/Yaru/apps/calendar.png', + disabled: false, + favourite: true, + desktop_shortcut: true, + screen: displayCalendar, }, { id: "vscode", @@ -113,4 +123,4 @@ const apps = [ }, ] -export default apps; \ No newline at end of file +export default apps; diff --git a/components/apps/calendar.js b/components/apps/calendar.js new file mode 100644 index 00000000..2cfa1eec --- /dev/null +++ b/components/apps/calendar.js @@ -0,0 +1,1039 @@ +import React, { useState, useEffect } from 'react'; + +const Calendar = () => { + const [currentDate, setCurrentDate] = useState(new Date()); + const [selectedDate, setSelectedDate] = useState(new Date()); + const [events, setEvents] = useState({}); + const [showEventModal, setShowEventModal] = useState(false); + const [eventText, setEventText] = useState(''); + const [eventTime, setEventTime] = useState('09:00'); + const [eventCategory, setEventCategory] = useState('personal'); + const [filterCategory, setFilterCategory] = useState('all'); + const [searchQuery, setSearchQuery] = useState(''); + + // US Federal Holidays 2024-2026 + const holidays = { + '2025-01-01': 'New Year\'s Day', + '2025-01-20': 'Martin Luther King Jr. Day', + '2025-02-17': 'Presidents\' Day', + '2025-05-26': 'Memorial Day', + '2025-06-19': 'Juneteenth', + '2025-07-04': 'Independence Day', + '2025-09-01': 'Labor Day', + '2025-10-13': 'Columbus Day', + '2025-11-11': 'Veterans Day', + '2025-11-27': 'Thanksgiving', + '2025-12-25': 'Christmas Day', + '2024-01-01': 'New Year\'s Day', + '2024-01-15': 'Martin Luther King Jr. Day', + '2024-02-19': 'Presidents\' Day', + '2024-05-27': 'Memorial Day', + '2024-06-19': 'Juneteenth', + '2024-07-04': 'Independence Day', + '2024-09-02': 'Labor Day', + '2024-10-14': 'Columbus Day', + '2024-11-11': 'Veterans Day', + '2024-11-28': 'Thanksgiving', + '2024-12-25': 'Christmas Day', + '2026-01-01': 'New Year\'s Day', + '2026-01-19': 'Martin Luther King Jr. Day', + '2026-02-16': 'Presidents\' Day', + '2026-05-25': 'Memorial Day', + '2026-06-19': 'Juneteenth', + '2026-07-03': 'Independence Day (Observed)', + '2026-09-07': 'Labor Day', + '2026-10-12': 'Columbus Day', + '2026-11-11': 'Veterans Day', + '2026-11-26': 'Thanksgiving', + '2026-12-25': 'Christmas Day' + }; + + useEffect(() => { + try { + const savedEvents = localStorage.getItem('ubuntu_calendar_events'); + if (savedEvents) { + setEvents(JSON.parse(savedEvents)); + } + } catch (e) { + console.error('Error loading events:', e); + } + }, []); + + useEffect(() => { + try { + localStorage.setItem('ubuntu_calendar_events', JSON.stringify(events)); + } catch (e) { + console.error('Error saving events:', e); + } + }, [events]); + + const getDaysInMonth = (date) => { + return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); + }; + + const getFirstDayOfMonth = (date) => { + return new Date(date.getFullYear(), date.getMonth(), 1).getDay(); + }; + + const formatDateKey = (date) => { + return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`; + }; + + const monthNames = [ + 'January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December' + ]; + + const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; + + const previousMonth = () => { + setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() - 1)); + }; + + const nextMonth = () => { + setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1)); + }; + + const goToToday = () => { + const today = new Date(); + setCurrentDate(today); + setSelectedDate(today); + }; + + const jumpToDate = () => { + const input = prompt('Enter date (YYYY-MM-DD):'); + if (input) { + const date = new Date(input); + if (!isNaN(date.getTime())) { + setCurrentDate(date); + setSelectedDate(date); + } + } + }; + + const handleDateClick = (day) => { + const newDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), day); + setSelectedDate(newDate); + }; + + const handleAddEvent = () => { + if (eventText.trim()) { + const dateKey = formatDateKey(selectedDate); + const newEvent = { + text: eventText, + time: eventTime, + category: eventCategory, + id: Date.now() + }; + + setEvents(prev => ({ + ...prev, + [dateKey]: [...(prev[dateKey] || []), newEvent] + })); + + setEventText(''); + setEventTime('09:00'); + setEventCategory('personal'); + setShowEventModal(false); + } + }; + + const handleDeleteEvent = (dateKey, eventId) => { + setEvents(prev => ({ + ...prev, + [dateKey]: prev[dateKey].filter(e => e.id !== eventId) + })); + }; + + const getFilteredEvents = (dateKey) => { + const dayEvents = events[dateKey] || []; + if (filterCategory === 'all') return dayEvents; + return dayEvents.filter(e => e.category === filterCategory); + }; + + const searchEvents = () => { + if (!searchQuery.trim()) return []; + const results = []; + Object.keys(events).forEach(dateKey => { + events[dateKey].forEach(event => { + if (event.text.toLowerCase().includes(searchQuery.toLowerCase())) { + results.push({ ...event, date: dateKey }); + } + }); + }); + return results; + }; + + const renderCalendarDays = () => { + const daysInMonth = getDaysInMonth(currentDate); + const firstDay = getFirstDayOfMonth(currentDate); + const days = []; + const today = new Date(); + const isCurrentMonth = currentDate.getMonth() === today.getMonth() && + currentDate.getFullYear() === today.getFullYear(); + + for (let i = 0; i < firstDay; i++) { + days.push(
); + } + + for (let day = 1; day <= daysInMonth; day++) { + const date = new Date(currentDate.getFullYear(), currentDate.getMonth(), day); + const dateKey = formatDateKey(date); + const isToday = isCurrentMonth && day === today.getDate(); + const isSelected = selectedDate.getDate() === day && + selectedDate.getMonth() === currentDate.getMonth() && + selectedDate.getFullYear() === currentDate.getFullYear(); + const dayEvents = getFilteredEvents(dateKey); + const hasEvents = dayEvents.length > 0; + const holiday = holidays[dateKey]; + const isWeekend = date.getDay() === 0 || date.getDay() === 6; + + days.push( +No events scheduled
+ Click "Add Event" to create one +It's {holiday}!
+No events found
+