|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Interactive Calendar</title> |
|
|
<style> |
|
|
:root { |
|
|
--primary: #4a90e2; |
|
|
--secondary: #f5f5f5; |
|
|
--text: #333; |
|
|
--shadow: 0 2px 10px rgba(0,0,0,0.1); |
|
|
} |
|
|
|
|
|
* { |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
box-sizing: border-box; |
|
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; |
|
|
} |
|
|
|
|
|
body { |
|
|
background: #f9f9f9; |
|
|
padding: 2rem; |
|
|
} |
|
|
|
|
|
.container { |
|
|
max-width: 1200px; |
|
|
margin: 0 auto; |
|
|
background: white; |
|
|
border-radius: 12px; |
|
|
box-shadow: var(--shadow); |
|
|
padding: 2rem; |
|
|
} |
|
|
|
|
|
.header { |
|
|
display: flex; |
|
|
justify-content: space-between; |
|
|
align-items: center; |
|
|
margin-bottom: 2rem; |
|
|
} |
|
|
|
|
|
.filters { |
|
|
display: flex; |
|
|
gap: 1rem; |
|
|
} |
|
|
|
|
|
.filter-btn { |
|
|
padding: 0.5rem 1rem; |
|
|
border: none; |
|
|
border-radius: 20px; |
|
|
background: var(--secondary); |
|
|
color: var(--text); |
|
|
cursor: pointer; |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
|
|
|
.filter-btn.active { |
|
|
background: var(--primary); |
|
|
color: white; |
|
|
} |
|
|
|
|
|
.calendar { |
|
|
display: grid; |
|
|
grid-template-columns: repeat(7, 1fr); |
|
|
gap: 1rem; |
|
|
} |
|
|
|
|
|
.day-header { |
|
|
text-align: center; |
|
|
font-weight: bold; |
|
|
padding: 1rem; |
|
|
background: var(--secondary); |
|
|
border-radius: 8px; |
|
|
} |
|
|
|
|
|
.day { |
|
|
min-height: 120px; |
|
|
background: white; |
|
|
border-radius: 8px; |
|
|
padding: 0.5rem; |
|
|
border: 2px solid var(--secondary); |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
|
|
|
.day.dragover { |
|
|
background: var(--secondary); |
|
|
transform: scale(1.02); |
|
|
} |
|
|
|
|
|
.event { |
|
|
background: var(--primary); |
|
|
color: white; |
|
|
padding: 0.5rem; |
|
|
border-radius: 4px; |
|
|
margin-bottom: 0.5rem; |
|
|
cursor: move; |
|
|
animation: slideIn 0.3s ease; |
|
|
} |
|
|
|
|
|
.event[data-category="work"] { background: #4a90e2; } |
|
|
.event[data-category="personal"] { background: #e24a4a; } |
|
|
.event[data-category="meeting"] { background: #4ae24a; } |
|
|
|
|
|
@keyframes slideIn { |
|
|
from { |
|
|
opacity: 0; |
|
|
transform: translateY(-10px); |
|
|
} |
|
|
to { |
|
|
opacity: 1; |
|
|
transform: translateY(0); |
|
|
} |
|
|
} |
|
|
|
|
|
.add-event { |
|
|
position: fixed; |
|
|
bottom: 2rem; |
|
|
right: 2rem; |
|
|
width: 60px; |
|
|
height: 60px; |
|
|
border-radius: 50%; |
|
|
background: var(--primary); |
|
|
color: white; |
|
|
border: none; |
|
|
font-size: 2rem; |
|
|
cursor: pointer; |
|
|
box-shadow: var(--shadow); |
|
|
transition: transform 0.3s ease; |
|
|
} |
|
|
|
|
|
.add-event:hover { |
|
|
transform: scale(1.1); |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div class="container"> |
|
|
<div class="header"> |
|
|
<h1>Calendar</h1> |
|
|
<div class="filters"> |
|
|
<button class="filter-btn active" data-category="all">All</button> |
|
|
<button class="filter-btn" data-category="work">Work</button> |
|
|
<button class="filter-btn" data-category="personal">Personal</button> |
|
|
<button class="filter-btn" data-category="meeting">Meeting</button> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="calendar"> |
|
|
<div class="day-header">Sun</div> |
|
|
<div class="day-header">Mon</div> |
|
|
<div class="day-header">Tue</div> |
|
|
<div class="day-header">Wed</div> |
|
|
<div class="day-header">Thu</div> |
|
|
<div class="day-header">Fri</div> |
|
|
<div class="day-header">Sat</div> |
|
|
</div> |
|
|
</div> |
|
|
<button class="add-event">+</button> |
|
|
|
|
|
<script> |
|
|
const calendar = document.querySelector('.calendar'); |
|
|
const filterBtns = document.querySelectorAll('.filter-btn'); |
|
|
let currentFilter = 'all'; |
|
|
|
|
|
|
|
|
const daysInMonth = 31; |
|
|
const firstDay = 3; |
|
|
|
|
|
for(let i = 0; i < firstDay; i++) { |
|
|
calendar.appendChild(createDayElement('')); |
|
|
} |
|
|
|
|
|
for(let i = 1; i <= daysInMonth; i++) { |
|
|
calendar.appendChild(createDayElement(i)); |
|
|
} |
|
|
|
|
|
function createDayElement(day) { |
|
|
const div = document.createElement('div'); |
|
|
div.className = 'day'; |
|
|
div.textContent = day; |
|
|
|
|
|
div.addEventListener('dragover', e => { |
|
|
e.preventDefault(); |
|
|
div.classList.add('dragover'); |
|
|
}); |
|
|
|
|
|
div.addEventListener('dragleave', e => { |
|
|
div.classList.remove('dragover'); |
|
|
}); |
|
|
|
|
|
div.addEventListener('drop', e => { |
|
|
e.preventDefault(); |
|
|
div.classList.remove('dragover'); |
|
|
|
|
|
const eventData = JSON.parse(e.dataTransfer.getData('text/plain')); |
|
|
const event = createEventElement(eventData.title, eventData.category); |
|
|
div.appendChild(event); |
|
|
}); |
|
|
|
|
|
return div; |
|
|
} |
|
|
|
|
|
function createEventElement(title, category) { |
|
|
const div = document.createElement('div'); |
|
|
div.className = 'event'; |
|
|
div.textContent = title; |
|
|
div.draggable = true; |
|
|
div.dataset.category = category; |
|
|
|
|
|
div.addEventListener('dragstart', e => { |
|
|
e.dataTransfer.setData('text/plain', JSON.stringify({ |
|
|
title, |
|
|
category |
|
|
})); |
|
|
}); |
|
|
|
|
|
return div; |
|
|
} |
|
|
|
|
|
|
|
|
const sampleEvents = [ |
|
|
{ day: 5, title: 'Team Meeting', category: 'work' }, |
|
|
{ day: 10, title: 'Dentist', category: 'personal' }, |
|
|
{ day: 15, title: 'Conference', category: 'meeting' }, |
|
|
{ day: 20, title: 'Project Deadline', category: 'work' } |
|
|
]; |
|
|
|
|
|
sampleEvents.forEach(event => { |
|
|
const days = document.querySelectorAll('.day'); |
|
|
const targetDay = days[event.day + firstDay - 1]; |
|
|
if(targetDay) { |
|
|
targetDay.appendChild(createEventElement(event.title, event.category)); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
filterBtns.forEach(btn => { |
|
|
btn.addEventListener('click', () => { |
|
|
filterBtns.forEach(b => b.classList.remove('active')); |
|
|
btn.classList.add('active'); |
|
|
currentFilter = btn.dataset.category; |
|
|
|
|
|
const events = document.querySelectorAll('.event'); |
|
|
events.forEach(event => { |
|
|
if(currentFilter === 'all' || event.dataset.category === currentFilter) { |
|
|
event.style.display = 'block'; |
|
|
} else { |
|
|
event.style.display = 'none'; |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
document.querySelector('.add-event').addEventListener('click', () => { |
|
|
const day = prompt('Enter day (1-31):'); |
|
|
const title = prompt('Enter event title:'); |
|
|
const category = prompt('Enter category (work/personal/meeting):'); |
|
|
|
|
|
if(day && title && category) { |
|
|
const days = document.querySelectorAll('.day'); |
|
|
const targetDay = days[parseInt(day) + firstDay - 1]; |
|
|
if(targetDay) { |
|
|
targetDay.appendChild(createEventElement(title, category)); |
|
|
} |
|
|
} |
|
|
}); |
|
|
</script> |
|
|
</body> |
|
|
</html> |