본문 바로가기
한국 20대 개발자의 성장기

웹 일정관리 캘린더(WEB Schedule Calendar) HTML CSS JS

by 멍동구 2024. 7. 30.
728x90

Chat GPT4 를 활용해서 웹 일정관리 캘린더를 만들어 보았습니다.

 

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Schedule Dashboard</title>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="styles.css">
</head>

<body>
    <div class="container mt-5">
        <div class="card shadow">
            <div class="card-body">
                <div class="d-flex justify-content-between align-items-center mb-3">
                    <button id="prevMonth" class="btn btn-primary">&lt; Prev</button>
                    <h3 id="currentMonth"></h3>
                    <button id="nextMonth" class="btn btn-primary">Next &gt;</button>
                </div>
                <div class="calendar" id="calendar"></div>
            </div>
        </div>
    </div>

    <!-- Modal for Event Details -->
    <div id="eventModal" class="modal">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 id="modalTitle" class="modal-title"></h5>
                    <button type="button" class="close" data-dismiss="modal">&times;</button>
                </div>
                <div class="modal-body">
                    <form id="eventForm">
                        <input type="hidden" id="eventId">
                        <div class="form-group">
                            <label for="eventDate">Date:</label>
                            <input type="date" id="eventDate" class="form-control" required>
                        </div>
                        <div class="form-group">
                            <label for="eventTitle">Title:</label>
                            <input type="text" id="eventTitle" class="form-control" required>
                        </div>
                        <div class="form-group">
                            <label for="eventDescription">Description:</label>
                            <textarea id="eventDescription" class="form-control" required></textarea>
                        </div>
                        <button type="submit" id="saveButton" class="btn btn-success">Save</button>
                        <button type="button" id="deleteButton" class="btn btn-danger">Delete</button>
                    </form>
                </div>
            </div>
        </div>
    </div>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
    <script src="script.js"></script>
</body>

</html>
body {
    font-family: Arial, sans-serif;
}

.card {
    border-radius: 10px;
}

.calendar {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 1px;
    border: 1px solid #ddd;
    border-radius: 10px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.day {
    border: 1px solid #ddd;
    padding: 10px;
    min-height: 100px;
    position: relative;
    transition: background-color 0.3s ease;
}

.day:hover {
    background-color: #f0f0f0;
}

.today {
    background-color: #ffeb3b;
}

.day .events {
    margin-top: 10px;
}

.event {
    background-color: #007BFF;
    color: #fff;
    padding: 5px;
    margin-top: 5px;
    cursor: pointer;
    border-radius: 3px;
    transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.event:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

.modal {
    display: none;
}

@keyframes slideIn {
    from {
        transform: translateY(-20px);
        opacity: 0;
    }

    to {
        transform: translateY(0);
        opacity: 1;
    }
}

.new-event {
    animation: slideIn 0.3s ease;
}
document.addEventListener("DOMContentLoaded", () => {
    const calendar = document.getElementById('calendar');
    const modal = new bootstrap.Modal(document.getElementById('eventModal'));
    const closeBtn = document.querySelector(".close");
    const eventForm = document.getElementById('eventForm');
    const saveButton = document.getElementById('saveButton');
    const deleteButton = document.getElementById('deleteButton');
    const modalTitle = document.getElementById('modalTitle');
    const eventId = document.getElementById('eventId');
    const eventDate = document.getElementById('eventDate');
    const eventTitle = document.getElementById('eventTitle');
    const eventDescription = document.getElementById('eventDescription');
    const currentMonthEl = document.getElementById('currentMonth');
    const prevMonthBtn = document.getElementById('prevMonth');
    const nextMonthBtn = document.getElementById('nextMonth');

    let events = [
        { id: 1, date: '2024-07-30', title: 'Event 1', description: 'Event 1 Description' },
        { id: 2, date: '2024-07-30', title: 'Event 2', description: 'Event 2 Description' },
        { id: 3, date: '2024-07-31', title: 'Event 3', description: 'Event 3 Description' },
    ];

    let currentMonth = new Date().getMonth();
    let currentYear = new Date().getFullYear();

    function renderCalendar() {
        calendar.innerHTML = '';
        const firstDayOfMonth = new Date(currentYear, currentMonth, 1).getDay();
        const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();
        currentMonthEl.innerText = `${currentYear}년 ${currentMonth + 1}월`;

        for (let i = 0; i < firstDayOfMonth; i++) {
            const emptyDiv = document.createElement('div');
            emptyDiv.classList.add('day');
            calendar.appendChild(emptyDiv);
        }

        for (let i = 1; i <= daysInMonth; i++) {
            const dayDiv = document.createElement('div');
            dayDiv.classList.add('day');
            dayDiv.innerHTML = `<div>${i}</div><div class="events"></div>`;
            const dateStr = `${currentYear}-${(currentMonth + 1).toString().padStart(2, '0')}-${i.toString().padStart(2, '0')}`;
            if (dateStr === new Date().toISOString().split('T')[0]) {
                dayDiv.classList.add('today');
            }
            const dayEvents = events.filter(event => event.date === dateStr);
            const eventsDiv = dayDiv.querySelector('.events');
            dayEvents.forEach(event => {
                const eventDiv = document.createElement('div');
                eventDiv.classList.add('event', 'new-event');
                eventDiv.innerText = event.title;
                eventDiv.addEventListener('click', (e) => {
                    e.stopPropagation();
                    openModal(event, true);
                });
                eventsDiv.appendChild(eventDiv);
            });
            dayDiv.addEventListener('dblclick', () => openModal({ date: dateStr }, false));
            calendar.appendChild(dayDiv);
        }
    }

    function openModal(event, isEdit) {
        modal.show();
        eventId.value = isEdit ? event.id : '';
        eventDate.value = event.date;
        eventTitle.value = isEdit ? event.title : '';
        eventDescription.value = isEdit ? event.description : '';
        modalTitle.innerText = isEdit ? 'Edit Event' : 'Add Event';
        deleteButton.style.display = isEdit ? 'block' : 'none';
    }

    function closeModal() {
        modal.hide();
    }

    function saveEvent(e) {
        e.preventDefault();
        const id = eventId.value;
        const date = eventDate.value;
        const title = eventTitle.value;
        const description = eventDescription.value;

        if (id) {
            const eventIndex = events.findIndex(event => event.id == id);
            events[eventIndex].date = date;
            events[eventIndex].title = title;
            events[eventIndex].description = description;
        } else {
            const newEvent = {
                id: events.length ? Math.max(...events.map(event => event.id)) + 1 : 1,
                date,
                title,
                description
            };
            events.push(newEvent);
        }
        closeModal();
        renderCalendar();
    }

    function deleteEvent() {
        const id = eventId.value;
        events = events.filter(event => event.id != id);
        closeModal();
        renderCalendar();
    }

    function prevMonth() {
        if (currentMonth === 0) {
            currentMonth = 11;
            currentYear--;
        } else {
            currentMonth--;
        }
        renderCalendar();
    }

    function nextMonth() {
        if (currentMonth === 11) {
            currentMonth = 0;
            currentYear++;
        } else {
            currentMonth++;
        }
        renderCalendar();
    }

    closeBtn.onclick = closeModal;
    window.onclick = event => {
        if (event.target === modal._element) {
            closeModal();
        }
    };
    eventForm.onsubmit = saveEvent;
    deleteButton.onclick = deleteEvent;
    prevMonthBtn.onclick = prevMonth;
    nextMonthBtn.onclick = nextMonth;

    renderCalendar();
});

 

미리보기 화면

 

감사합니다.