## index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PWA Calendar</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<div class="left-panel">
<input type="file" id="photo-upload" accept="image/*">
<label for="photo-upload" class="upload-button">Upload</label>
<img id="photo-preview" src="" alt="Uploaded photo">
</div>
<div class="right-panel">
<div class="calendar">
<div class="month">
<select id="year-select"></select>
<select id="month-select">
<option value="0">January</option>
<option value="1">February</option>
<option value="2">March</option>
<option value="3">April</option>
<option value="4">May</option>
<option value="5">June</option>
<option value="6">July</option>
<option value="7">August</option>
<option value="8">September</option>
<option value="9">October</option>
<option value="10">November</option>
<option value="11">December</option>
</select>
</div>
<div class="weekdays">
<div class="sunday">S</div>
<div>M</div>
<div>T</div>
<div>W</div>
<div>T</div>
<div>F</div>
<div>S</div>
</div>
<div class="days" id="days-container"></div>
</div>
<div class="todo-list">
<h3>TO DO LIST:</h3>
<ul class="todo-lines">
<li class="todo-line"><input type="text"></li>
<li class="todo-line"><input type="text"></li>
<li class="todo-line"><input type="text"></li>
<li class="todo-line"><input type="text"></li>
<li class="todo-line"><input type="text"></li>
</ul>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
## styles.css
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #B4A391;
color: #2E292A;
}
.container {
display: flex;
width: 80%;
max-width: 1200px;
background-color: #B4A391;
}
.left-panel, .right-panel {
padding: 20px;
flex: 1;
}
.left-panel {
display: flex;
justify-content: center;
align-items: center;
}
#photo-upload {
display: none;
}
.upload-button {
background-color: white;
color: #2E292A;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
}
#photo-preview {
width: 100%;
height: 100%;
object-fit: cover;
display: none;
}
.right-panel {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.calendar {
text-align: center;
}
.month {
margin-bottom: 20px;
}
.weekdays, .days {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 5px;
}
.weekdays div, .days div {
padding: 10px;
}
.sunday {
color: red; /* 일요일 글자 색상 */
}
/* 6주 고정 */
.days {
grid-template-rows: repeat(6, 1fr);
height: 240px; /* 각 줄의 높이를 설정하여 6줄로 고정 */
}
.todo-list {
margin-top: 20px;
}
.todo-lines {
list-style-type: none;
padding: 0;
}
.todo-line {
margin-bottom: 10px;
padding-bottom: 5px;
border-bottom: 1px solid #fff; /* To Do List 밑줄 */
}
.todo-line input {
width: 100%;
background: transparent;
border: none;
color: #2E292A;
font-size: 16px;
}
.todo-line input:focus {
outline: none;
}
## script.js
document.getElementById('photo-upload').addEventListener('change', function(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const preview = document.getElementById('photo-preview');
preview.src = e.target.result;
preview.style.display = 'block';
document.querySelector('.upload-button').style.display = 'none';
}
reader.readAsDataURL(file);
}
});
const yearSelect = document.getElementById('year-select');
const monthSelect = document.getElementById('month-select');
const daysContainer = document.getElementById('days-container');
function populateYears() {
const currentYear = new Date().getFullYear();
for (let i = currentYear - 10; i <= currentYear + 10; i++) {
const option = document.createElement('option');
option.value = i;
option.textContent = i;
yearSelect.appendChild(option);
}
}
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
}
function getLastDateOfMonth(year, month) {
const lastDate = [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
return lastDate[month];
}
function populateDays(year, month) {
daysContainer.innerHTML = '';
const firstDay = new Date(year, month, 1).getDay();
const lastDate = getLastDateOfMonth(year, month);
// 빈 칸 추가
for (let i = 0; i < firstDay; i++) {
const emptyDiv = document.createElement('div');
daysContainer.appendChild(emptyDiv);
}
// 날짜 추가
for (let i = 1; i <= lastDate; i++) {
const dayDiv = document.createElement('div');
dayDiv.textContent = i;
if ((firstDay + i - 1) % 7 === 0) { // 일요일에 해당하는 경우
dayDiv.style.color = 'red'; // 일요일 숫자를 빨간색으로 표시
}
daysContainer.appendChild(dayDiv);
}
// 6주 고정: 빈 칸 추가
const totalDays = firstDay + lastDate;
const emptyDaysNeeded = (6 * 7) - totalDays; // 6주를 맞추기 위해 필요한 빈 칸 수
for (let i = 0; i < emptyDaysNeeded; i++) {
const emptyDiv = document.createElement('div');
daysContainer.appendChild(emptyDiv);
}
}
yearSelect.addEventListener('change', function() {
populateDays(yearSelect.value, monthSelect.value);
});
monthSelect.addEventListener('change', function() {
populateDays(yearSelect.value, monthSelect.value);
});
populateYears();
populateDays(new Date().getFullYear(), new Date().getMonth());
'1인 프로젝트 > 나만의 달력' 카테고리의 다른 글
백업...또 백업 (0) | 2024.08.09 |
---|---|
PostgreSQL (0) | 2024.08.07 |
Perplexity 사용하기 어렵다... (0) | 2024.08.06 |
3차 백업 (0) | 2024.08.05 |
2차 백업 (0) | 2024.08.05 |