infinite-agents-public/src_group/ui_hybrid_5/script.js

541 lines
17 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Art Deco Time Manager - Interactive JavaScript
class TimeManager {
constructor() {
this.currentView = 'calendar';
this.timerInterval = null;
this.timerSeconds = 0;
this.timerRunning = false;
this.selectedDate = new Date();
this.events = this.loadFromStorage('events') || {};
this.schedule = this.loadFromStorage('schedule') || [];
this.deadlines = this.loadFromStorage('deadlines') || [];
this.init();
}
init() {
this.setupNavigationListeners();
this.setupTimeDisplay();
this.setupCalendar();
this.setupTimer();
this.setupSchedule();
this.setupTimezone();
this.setupDeadlines();
this.updateWorldClocks();
setInterval(() => this.updateWorldClocks(), 1000);
}
// Navigation Management
setupNavigationListeners() {
const navTabs = document.querySelectorAll('.nav-tab');
navTabs.forEach(tab => {
tab.addEventListener('click', (e) => {
this.switchView(e.target.dataset.view);
});
});
}
switchView(viewName) {
// Update navigation tabs
document.querySelectorAll('.nav-tab').forEach(tab => {
tab.classList.toggle('active', tab.dataset.view === viewName);
});
// Update view panels
document.querySelectorAll('.view-panel').forEach(panel => {
panel.classList.toggle('active', panel.id === `${viewName}View`);
});
this.currentView = viewName;
}
// Time Display
setupTimeDisplay() {
const updateTime = () => {
const now = new Date();
const timeStr = now.toLocaleTimeString('en-US', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
const dateStr = now.toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
document.getElementById('currentTime').textContent = timeStr;
document.getElementById('currentDate').textContent = dateStr;
};
updateTime();
setInterval(updateTime, 1000);
}
// Calendar Functionality
setupCalendar() {
this.renderCalendar();
document.getElementById('prevMonth').addEventListener('click', () => {
this.selectedDate.setMonth(this.selectedDate.getMonth() - 1);
this.renderCalendar();
});
document.getElementById('nextMonth').addEventListener('click', () => {
this.selectedDate.setMonth(this.selectedDate.getMonth() + 1);
this.renderCalendar();
});
}
renderCalendar() {
const year = this.selectedDate.getFullYear();
const month = this.selectedDate.getMonth();
const firstDay = new Date(year, month, 1).getDay();
const daysInMonth = new Date(year, month + 1, 0).getDate();
const daysInPrevMonth = new Date(year, month, 0).getDate();
// Update month/year display
document.getElementById('monthYear').textContent =
new Date(year, month).toLocaleDateString('en-US', {
month: 'long',
year: 'numeric'
});
// Clear existing calendar days
const grid = document.getElementById('calendarGrid');
const existingDays = grid.querySelectorAll('.calendar-day');
existingDays.forEach(day => day.remove());
// Add previous month's trailing days
for (let i = firstDay - 1; i >= 0; i--) {
const dayEl = this.createCalendarDay(
daysInPrevMonth - i,
month - 1,
year,
true
);
grid.appendChild(dayEl);
}
// Add current month's days
for (let day = 1; day <= daysInMonth; day++) {
const dayEl = this.createCalendarDay(day, month, year, false);
grid.appendChild(dayEl);
}
// Add next month's leading days
const totalCells = grid.children.length - 7; // Subtract header row
const remainingCells = 42 - totalCells; // 6 weeks * 7 days
for (let day = 1; day <= remainingCells; day++) {
const dayEl = this.createCalendarDay(day, month + 1, year, true);
grid.appendChild(dayEl);
}
this.renderEvents();
}
createCalendarDay(day, month, year, isOtherMonth) {
const dayEl = document.createElement('div');
dayEl.className = 'calendar-day';
if (isOtherMonth) dayEl.classList.add('other-month');
const date = new Date(year, month, day);
const today = new Date();
if (this.isSameDay(date, today)) {
dayEl.classList.add('today');
}
dayEl.textContent = day;
dayEl.addEventListener('click', () => this.selectDate(date));
// Check for events
const dateKey = this.getDateKey(date);
if (this.events[dateKey]) {
dayEl.style.borderBottom = '3px solid var(--deco-gold)';
}
return dayEl;
}
selectDate(date) {
this.selectedDate = date;
this.renderEvents();
}
renderEvents() {
const eventsList = document.getElementById('eventsList');
eventsList.innerHTML = '';
const dateKey = this.getDateKey(this.selectedDate);
const dayEvents = this.events[dateKey] || [];
if (dayEvents.length === 0) {
eventsList.innerHTML = '<li class="event-item">No appointments scheduled</li>';
return;
}
dayEvents.forEach(event => {
const li = document.createElement('li');
li.className = 'event-item';
li.textContent = event;
eventsList.appendChild(li);
});
}
// Timer Functionality
setupTimer() {
document.getElementById('startTimer').addEventListener('click', () => this.startTimer());
document.getElementById('pauseTimer').addEventListener('click', () => this.pauseTimer());
document.getElementById('resetTimer').addEventListener('click', () => this.resetTimer());
// Preset buttons
document.querySelectorAll('.preset-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const minutes = parseInt(e.target.dataset.minutes);
this.timerSeconds = minutes * 60;
this.updateTimerDisplay();
});
});
}
startTimer() {
if (!this.timerRunning) {
this.timerRunning = true;
this.timerInterval = setInterval(() => {
if (this.timerSeconds > 0) {
this.timerSeconds--;
this.updateTimerDisplay();
} else {
this.pauseTimer();
this.showNotification('Timer Complete!');
}
}, 1000);
}
}
pauseTimer() {
this.timerRunning = false;
if (this.timerInterval) {
clearInterval(this.timerInterval);
this.timerInterval = null;
}
}
resetTimer() {
this.pauseTimer();
this.timerSeconds = 0;
this.updateTimerDisplay();
}
updateTimerDisplay() {
const hours = Math.floor(this.timerSeconds / 3600);
const minutes = Math.floor((this.timerSeconds % 3600) / 60);
const seconds = this.timerSeconds % 60;
const display = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
document.getElementById('timerDisplay').textContent = display;
}
// Schedule Functionality
setupSchedule() {
const form = document.getElementById('scheduleForm');
form.addEventListener('submit', (e) => {
e.preventDefault();
this.addScheduleItem();
});
this.renderSchedule();
}
addScheduleItem() {
const time = document.getElementById('scheduleTime').value;
const task = document.getElementById('scheduleTask').value;
if (time && task) {
this.schedule.push({ time, task });
this.schedule.sort((a, b) => a.time.localeCompare(b.time));
this.saveToStorage('schedule', this.schedule);
this.renderSchedule();
// Reset form
document.getElementById('scheduleForm').reset();
}
}
renderSchedule() {
const timeline = document.getElementById('scheduleTimeline');
timeline.innerHTML = '';
if (this.schedule.length === 0) {
timeline.innerHTML = '<div class="timeline-item">No appointments scheduled</div>';
return;
}
this.schedule.forEach((item, index) => {
const itemEl = document.createElement('div');
itemEl.className = 'timeline-item';
itemEl.innerHTML = `
<span class="timeline-time">${item.time}</span>
<span class="timeline-task">${item.task}</span>
`;
timeline.appendChild(itemEl);
});
}
// Timezone Functionality
setupTimezone() {
document.getElementById('convertTime').addEventListener('click', () => {
this.convertTime();
});
}
updateWorldClocks() {
const cards = document.querySelectorAll('.timezone-card');
cards.forEach(card => {
const timezone = card.dataset.tz;
const timeEl = card.querySelector('.tz-time');
const time = new Date().toLocaleTimeString('en-US', {
timeZone: timezone,
hour12: false,
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
timeEl.textContent = time;
});
}
convertTime() {
const time = document.getElementById('converterTime').value;
const fromTz = document.getElementById('fromTimezone').value;
const results = document.getElementById('converterResults');
if (!time) {
results.innerHTML = '<p>Please select a time to convert</p>';
return;
}
const [hours, minutes] = time.split(':').map(Number);
const date = new Date();
date.setHours(hours, minutes, 0, 0);
const zones = [
{ name: 'New York', tz: 'America/New_York' },
{ name: 'London', tz: 'Europe/London' },
{ name: 'Paris', tz: 'Europe/Paris' },
{ name: 'Tokyo', tz: 'Asia/Tokyo' }
];
results.innerHTML = '<h4>Converted Times:</h4>';
zones.forEach(zone => {
const convertedTime = date.toLocaleTimeString('en-US', {
timeZone: zone.tz,
hour12: false,
hour: '2-digit',
minute: '2-digit'
});
results.innerHTML += `<p>${zone.name}: ${convertedTime}</p>`;
});
}
// Deadlines Functionality
setupDeadlines() {
const form = document.getElementById('deadlineForm');
form.addEventListener('submit', (e) => {
e.preventDefault();
this.addDeadline();
});
this.renderDeadlines();
setInterval(() => this.updateDeadlineCountdowns(), 60000); // Update every minute
}
addDeadline() {
const title = document.getElementById('deadlineTitle').value;
const date = document.getElementById('deadlineDate').value;
const priority = document.getElementById('deadlinePriority').value;
if (title && date) {
const deadline = {
id: Date.now(),
title,
date: new Date(date),
priority
};
this.deadlines.push(deadline);
this.deadlines.sort((a, b) => a.date - b.date);
this.saveToStorage('deadlines', this.deadlines);
this.renderDeadlines();
// Reset form
document.getElementById('deadlineForm').reset();
}
}
renderDeadlines() {
const list = document.getElementById('deadlinesList');
list.innerHTML = '';
if (this.deadlines.length === 0) {
list.innerHTML = '<div class="deadline-item">No deadlines set</div>';
return;
}
this.deadlines.forEach(deadline => {
const itemEl = document.createElement('div');
itemEl.className = `deadline-item ${deadline.priority}-priority`;
const countdown = this.getCountdown(deadline.date);
itemEl.innerHTML = `
<div class="deadline-header">
<span class="deadline-title-text">${deadline.title}</span>
<span class="deadline-priority">${deadline.priority.toUpperCase()}</span>
</div>
<div class="deadline-date">${deadline.date.toLocaleString()}</div>
<div class="deadline-countdown">${countdown}</div>
<button class="deadline-remove" data-id="${deadline.id}">×</button>
`;
const removeBtn = itemEl.querySelector('.deadline-remove');
removeBtn.addEventListener('click', () => this.removeDeadline(deadline.id));
list.appendChild(itemEl);
});
}
removeDeadline(id) {
this.deadlines = this.deadlines.filter(d => d.id !== id);
this.saveToStorage('deadlines', this.deadlines);
this.renderDeadlines();
}
updateDeadlineCountdowns() {
if (this.currentView === 'deadlines') {
this.renderDeadlines();
}
}
getCountdown(targetDate) {
const now = new Date();
const diff = targetDate - now;
if (diff < 0) {
return 'Overdue';
}
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
if (days > 0) {
return `${days} days, ${hours} hours remaining`;
} else if (hours > 0) {
return `${hours} hours, ${minutes} minutes remaining`;
} else {
return `${minutes} minutes remaining`;
}
}
// Utility Functions
isSameDay(date1, date2) {
return date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate();
}
getDateKey(date) {
return `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
}
showNotification(message) {
// Create a temporary notification
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
padding: 20px;
background: var(--deco-gold);
color: var(--deco-black);
border: 2px solid var(--deco-black);
font-family: var(--font-accent);
text-transform: uppercase;
letter-spacing: 0.1rem;
z-index: 1000;
animation: slideIn 0.5s ease;
`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
notification.style.animation = 'slideOut 0.5s ease';
setTimeout(() => notification.remove(), 500);
}, 3000);
}
// Storage Functions
saveToStorage(key, data) {
try {
localStorage.setItem(`timeManager_${key}`, JSON.stringify(data));
} catch (e) {
console.error('Failed to save to storage:', e);
}
}
loadFromStorage(key) {
try {
const data = localStorage.getItem(`timeManager_${key}`);
if (data) {
const parsed = JSON.parse(data);
// Convert date strings back to Date objects for deadlines
if (key === 'deadlines') {
return parsed.map(d => ({
...d,
date: new Date(d.date)
}));
}
return parsed;
}
} catch (e) {
console.error('Failed to load from storage:', e);
}
return null;
}
}
// Add animations to stylesheet dynamically
const style = document.createElement('style');
style.textContent = `
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes slideOut {
from {
transform: translateX(0);
opacity: 1;
}
to {
transform: translateX(100%);
opacity: 0;
}
}
`;
document.head.appendChild(style);
// Initialize Time Manager when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
new TimeManager();
});