<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>할일, 메모장, 캘린더</title>
<script src="https://cdn.tiny.cloud/1/c7wny3feouvnh55eoy8dj3bvhux0ljzqqr1or3oali99mgpi/tinymce/7/tinymce.min.js" referrerpolicy="origin"></script>
<style>
:root {
--primary-color: #4a90e2;
--secondary-color: #f5a623;
--background-color: #f0f4f8;
--text-color: #333;
--task-bg-color: #ffffff;
--task-border-color: #dee2e6;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: var(--background-color);
color: var(--text-color);
}
.container {
max-width: 800px;
margin: 50px auto;
padding: 20px;
background-color: var(--task-bg-color);
border: 1px solid var(--task-border-color);
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.tabs {
display: flex;
justify-content: space-around;
margin-bottom: 20px;
}
.tabs div {
flex: 1;
text-align: center;
padding: 10px;
background-color: #f1f3f5;
border-radius: 8px;
cursor: pointer;
margin: 0 5px;
font-weight: bold;
color: var(--text-color);
transition: background-color 0.3s, color 0.3s;
}
.tabs div.active {
background-color: var(--primary-color);
color: white;
}
.tabs div:hover {
background-color: var(--primary-color);
color: white;
}
.date-selector {
display: flex;
justify-content: space-around;
margin-bottom: 20px;
font-size: 18px;
}
.date-selector div {
cursor: pointer;
padding: 5px 10px;
background-color: #f1f3f5;
border-radius: 8px;
transition: background-color 0.3s;
}
.date-selector div:hover {
background-color: var(--secondary-color);
color: white;
}
.tasks {
margin-bottom: 20px;
padding: 10px;
border-radius: 8px;
background-color: var(--task-bg-color);
}
.tasks div {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
padding: 10px;
background-color: var(--task-bg-color);
border: 1px solid var(--task-border-color);
border-radius: 8px;
transition: background-color 0.3s;
}
.tasks div:hover {
background-color: #e9ecef;
}
.tasks input[type="checkbox"] {
margin-right: 10px;
}
.tasks div.completed {
text-decoration: line-through;
color: #868e96;
background-color: #e9ecef;
}
.tasks div button {
background-color: transparent;
border: none;
font-size: 16px;
cursor: pointer;
margin-left: 10px;
}
.tasks div button.add {
color: var(--primary-color);
font-size: 20px;
margin-left: auto;
}
.tasks div button.delete {
color: #fa5252;
}
.tasks div button.editable {
flex: 1;
margin-left: 10px;
font-size: 14px;
color: var(--text-color);
background-color: transparent;
border: none;
cursor: text;
outline: none;
}
.date {
font-size: 24px;
margin-bottom: 20px;
font-weight: bold;
color: var(--text-color);
text-align: center;
}
.add {
margin-left: 93%;
}
#memopad {
width: 100%;
height: 200px;
margin-bottom: 20px;
padding: 10px;
border: 1px solid var(--task-border-color);
border-radius: 8px;
resize: vertical;
background-color: var(--task-bg-color);
color: var(--text-color);
}
#calendar {
display: none;
}
.calendar-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.calendar-grid {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
}
.calendar-day {
text-align: center;
padding: 5px;
background-color: #f1f3f5;
border-radius: 4px;
cursor: pointer;
}
.calendar-day:hover {
background-color: var(--secondary-color);
color: white;
}
.calendar-day.has-tasks {
background-color: var(--secondary-color);
}
.calendar-day.today {
border: 2px solid var(--primary-color);
font-weight: bold;
}
.calendar-day.weekday {
font-weight: bold;
background-color: var(--primary-color);
color: white;
}
#dayTasks {
margin-top: 20px;
}
@media (max-width: 600px) {
.container {
margin: 20px 10px;
padding: 10px;
}
.tabs div {
font-size: 14px;
}
.calendar-grid {
font-size: 12px;
}
}
#savedMemos {
margin-top: 20px;
border-top: 1px solid #ccc;
padding-top: 20px;
}
.saved-memo {
background-color: #f9f9f9;
border: 1px solid #ddd;
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
}
.memo-actions {
margin-top: 10px;
}
.memo-actions button {
margin-right: 5px;
}
</style>
</head>
<body>
<div class="container">
<div class="tabs">
<div class="tab active" onclick="switchTab('todo')">할일</div>
<div class="tab" onclick="switchTab('memo')">메모장</div>
<div class="tab" onclick="switchTab('calendar')">캘린더</div>
</div>
<div id="todoContent">
<div class="date-selector">
<div onclick="switchList('주')">주</div>
<div onclick="switchList('월')">월</div>
<div onclick="switchList('년')">년</div>
</div>
<div class="tasks" id="taskList"></div>
<div class="date" id="today"></div>
<div class="tasks" id="todayTaskList">
<button class="add" onclick="addTodayTask()">+</button>
</div>
</div>
<div id="memoContent" style="display:none;">
<textarea id="memopad">Welcome to TinyMCE!</textarea>
<button id="saveMemo">메모 저장</button>
<div id="savedMemos">
<h3>저장된 메모</h3>
<!-- 저장된 메모가 여기에 표시됩니다 -->
</div>
</div>
<div id="calendar" style="display:none;">
<div class="calendar-header">
<button onclick="changeMonth(-1)">이전</button>
<span id="currentMonth"></span>
<button onclick="changeMonth(1)">다음</button>
</div>
<div class="calendar-grid" id="calendarGrid"></div>
<div id="dayTasks"></div>
</div>
</div>
<script>
tinymce.init({
selector: '#memopad',
plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount',
toolbar: 'undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | link image media table | align lineheight | numlist bullist indent outdent | emoticons charmap | removeformat',
});
const tasks = {
'주': ['주 할일 1', '주 할일 2','주 할일 3'],
'월': ['월 할일 1', '월 할일 2', '월 할일 3'],
'년': ['년 할일 1', '년 할일 2', '년 할일 3']
};
let calendarTasks = {};
function switchList(period) {
const taskList = document.getElementById('taskList');
taskList.innerHTML = '';
tasks[period].forEach(task => {
taskList.innerHTML += `
<div>
<input type="checkbox" onclick="toggleComplete(this)">
<span class="editable" contenteditable="true">${task}</span>
<button onclick="deleteTask(this)">-</button>
</div>`;
});
taskList.innerHTML += '<button class="add" onclick="addTask(\'taskList\')">+</button>';
}
function toggleComplete(checkbox) {
const taskDiv = checkbox.parentElement;
if (checkbox.checked) {
taskDiv.classList.add('completed');
} else {
taskDiv.classList.remove('completed');
}
}
function deleteTask(button) {
const taskDiv = button.parentElement;
taskDiv.remove();
}
function addTask(listId) {
const taskList = document.getElementById(listId);
const newTaskDiv = document.createElement('div');
newTaskDiv.innerHTML = `
<input type="checkbox" onclick="toggleComplete(this)">
<span class="editable" contenteditable="true">새 할일</span>
<button onclick="deleteTask(this)">-</button>`;
taskList.insertBefore(newTaskDiv, taskList.querySelector('button.add'));
}
function switchTab(tab) {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
document.querySelector(`.tab:nth-child(${tab === 'todo' ? 1 : tab === 'memo' ? 2 : 3})`).classList.add('active');
document.getElementById('todoContent').style.display = tab === 'todo' ? 'block' : 'none';
document.getElementById('memoContent').style.display = tab === 'memo' ? 'block' : 'none';
document.getElementById('calendar').style.display = tab === 'calendar' ? 'block' : 'none';
if (tab === 'calendar') {
renderCalendar();
}
}
let currentDate = new Date();
function updateToday() {
const today = new Date();
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
document.getElementById('today').textContent = today.toLocaleDateString('ko-KR', options);
}
function addTodayTask() {
const todayTaskList = document.getElementById('todayTaskList');
const newTaskDiv = document.createElement('div');
newTaskDiv.innerHTML = `
<input type="checkbox" onclick="toggleComplete(this)">
<span class="editable" contenteditable="true" onblur="updateCalendarTask(this)">새 할일</span>
<button onclick="deleteTodayTask(this)">-</button>`;
todayTaskList.insertBefore(newTaskDiv, todayTaskList.querySelector('button.add'));
}
function deleteTodayTask(button) {
const taskDiv = button.parentElement;
const taskText = taskDiv.querySelector('span').textContent;
taskDiv.remove();
removeFromCalendar(taskText);
}
function updateCalendarTask(span) {
const taskText = span.textContent;
const today = new Date();
const dateString = `${today.getFullYear()}-${today.getMonth() + 1}-${today.getDate()}`;
if (!calendarTasks[dateString]) {
calendarTasks[dateString] = [];
}
calendarTasks[dateString].push({ text: taskText, completed: false });
renderCalendar();
}
function removeFromCalendar(taskText) {
const today = new Date();
const dateString = `${today.getFullYear()}-${today.getMonth() + 1}-${today.getDate()}`;
if (calendarTasks[dateString]) {
calendarTasks[dateString] = calendarTasks[dateString].filter(task => task.text !== taskText);
renderCalendar();
}
}
function renderCalendar() {
const year = currentDate.getFullYear();
const month = currentDate.getMonth();
document.getElementById('currentMonth').textContent = `${year}년 ${month + 1}월`;
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
const calendarGrid = document.getElementById('calendarGrid');
calendarGrid.innerHTML = '';
const weekdays = ['일', '월', '화', '수', '목', '금', '토'];
weekdays.forEach(day => {
const dayElement = document.createElement('div');
dayElement.textContent = day;
dayElement.classList.add('calendar-day', 'weekday');
calendarGrid.appendChild(dayElement);
});
for (let i = 0; i < firstDay.getDay(); i++) {
calendarGrid.appendChild(document.createElement('div'));
}
for (let i = 1; i <= lastDay.getDate(); i++) {
const dayElement = document.createElement('div');
dayElement.textContent = i;
dayElement.classList.add('calendar-day');
const dateString = `${year}-${month + 1}-${i}`;
if (calendarTasks[dateString] && calendarTasks[dateString].length > 0) {
dayElement.classList.add('has-tasks');
}
if (i === new Date().getDate() && month === new Date().getMonth() && year === new Date().getFullYear()) {
dayElement.classList.add('today');
}
dayElement.onclick = () => showDayTasks(dateString);
calendarGrid.appendChild(dayElement);
}
}
function showDayTasks(dateString) {
const dayTasks = document.getElementById('dayTasks');
dayTasks.innerHTML = `<h3>${dateString} 할일</h3>`;
if (calendarTasks[dateString]) {
calendarTasks[dateString].forEach((task, index) => {
dayTasks.innerHTML += `
<div>
<input type="checkbox" ${task.completed ? 'checked' : ''} onchange="toggleCalendarTask('${dateString}', ${index})">
<span>${task.text}</span>
<button onclick="deleteCalendarTask('${dateString}', ${index})">삭제</button>
</div>
`;
});
}
}
function toggleCalendarTask(dateString, index) {
calendarTasks[dateString][index].completed = !calendarTasks[dateString][index].completed;
showDayTasks(dateString);
}
function deleteCalendarTask(dateString, index) {
calendarTasks[dateString].splice(index, 1);
showDayTasks(dateString);
renderCalendar();
}
function changeMonth(delta) {
currentDate.setMonth(currentDate.getMonth() + delta);
renderCalendar();
}
document.getElementById('saveMemo').addEventListener('click', function() {
const content = tinymce.get('memopad').getContent();
const timestamp = new Date().toLocaleString('ko-KR');
const memoObj = { id: Date.now(), content, timestamp };
let memos = JSON.parse(localStorage.getItem('memos')) || [];
memos.unshift(memoObj);
localStorage.setItem('memos', JSON.stringify(memos));
displayMemos();
tinymce.get('memopad').setContent('');
});
function displayMemos() {
const savedMemosDiv = document.getElementById('savedMemos');
const memos = JSON.parse(localStorage.getItem('memos')) || [];
let memosHTML = '<h3>저장된 메모</h3>';
memos.forEach((memo) => {
memosHTML += `
<div class="saved-memo" id="memo-${memo.id}">
<p><strong>저장 시간:</strong> ${memo.timestamp}</p>
<div>${memo.content}</div>
<div class="memo-actions">
<button onclick="editMemo(${memo.id})">수정</button>
<button onclick="deleteMemo(${memo.id})">삭제</button>
</div>
</div>
`;
});
savedMemosDiv.innerHTML = memosHTML;
}
function editMemo(id) {
const memos = JSON.parse(localStorage.getItem('memos')) || [];
const memo = memos.find(m => m.id === id);
if (memo) {
tinymce.get('memopad').setContent(memo.content);
deleteMemo(id);
}
}
function deleteMemo(id) {
let memos = JSON.parse(localStorage.getItem('memos')) || [];
memos = memos.filter(m => m.id !== id);
localStorage.setItem('memos', JSON.stringify(memos));
displayMemos();
}
window.addEventListener('load', () => {
updateToday();
switchList('주');
switchTab('todo');
displayMemos();
});
</script>
</body>
</html>
'프로젝트' 카테고리의 다른 글
팀 프로젝트) 해당 글만 필터하기 (1) | 2024.09.24 |
---|---|
프로젝트>카풀 _ 보완점 (9) | 2024.09.03 |
프로젝트 > OTT 업데이트 (0) | 2024.08.24 |
간단 게임>비행기 (0) | 2024.08.13 |
프로젝트> ott 로그인버튼 (0) | 2024.08.12 |