actualizaciones varias
This commit is contained in:
parent
a1270096d1
commit
76ceaab343
|
|
@ -0,0 +1,82 @@
|
|||
.calendar-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
gap: 0.75rem;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.weekday-header,
|
||||
.day {
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
background: var(--bg-alt);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.weekday-header {
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
text-transform: uppercase;
|
||||
font-size: 0.78rem;
|
||||
letter-spacing: 0.08em;
|
||||
background: linear-gradient(180deg, rgba(255,255,255,0.02), transparent);
|
||||
}
|
||||
|
||||
.day {
|
||||
min-height: 5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.day.empty {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.day-number {
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.5rem;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.day.today {
|
||||
border: 2px solid var(--accent);
|
||||
background: rgba(0,0,0,0.12);
|
||||
}
|
||||
|
||||
.day.other-month {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.day-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.topic {
|
||||
display: block;
|
||||
padding: 0.4rem 0.6rem;
|
||||
margin-bottom: 0.4rem;
|
||||
background: var(--bg);
|
||||
border-left: 3px solid var(--accent);
|
||||
color: var(--text);
|
||||
font-size: 0.85rem;
|
||||
border-radius: 4px;
|
||||
box-shadow: inset 0 -1px 0 rgba(255,255,255,0.02);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.calendar-grid {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.weekday-header,
|
||||
.day {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const calendarGrid = document.getElementById('calendarGrid');
|
||||
const monthTitle = document.getElementById('monthTitle');
|
||||
const prevMonthBtn = document.getElementById('prevMonth');
|
||||
const nextMonthBtn = document.getElementById('nextMonth');
|
||||
const autoScheduleBtn = document.getElementById('autoScheduleBtn');
|
||||
|
||||
const monthNames = [
|
||||
'enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio',
|
||||
'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'
|
||||
];
|
||||
|
||||
const weekdayNames = ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'];
|
||||
const today = new Date();
|
||||
let currentYear = today.getFullYear();
|
||||
let currentMonth = today.getMonth();
|
||||
const STORAGE_KEY = 'tatvil_scheduled_topics_v1';
|
||||
|
||||
function renderCalendar(year, month) {
|
||||
calendarGrid.innerHTML = '';
|
||||
|
||||
weekdayNames.forEach(name => {
|
||||
const headerCell = document.createElement('div');
|
||||
headerCell.className = 'weekday-header';
|
||||
headerCell.textContent = name;
|
||||
calendarGrid.appendChild(headerCell);
|
||||
});
|
||||
|
||||
const firstDay = new Date(year, month, 1);
|
||||
const startWeekday = (firstDay.getDay() + 6) % 7; // Lunes = 0
|
||||
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
||||
const isCurrentMonth = year === today.getFullYear() && month === today.getMonth();
|
||||
|
||||
for (let i = 0; i < startWeekday; i += 1) {
|
||||
const emptyCell = document.createElement('div');
|
||||
emptyCell.className = 'day empty';
|
||||
calendarGrid.appendChild(emptyCell);
|
||||
}
|
||||
|
||||
for (let day = 1; day <= daysInMonth; day += 1) {
|
||||
const dayCell = document.createElement('div');
|
||||
dayCell.className = 'day';
|
||||
if (isCurrentMonth && day === today.getDate()) {
|
||||
dayCell.classList.add('today');
|
||||
}
|
||||
|
||||
const dateStr = `${year}-${pad(month+1)}-${pad(day)}`;
|
||||
dayCell.dataset.date = dateStr;
|
||||
|
||||
const dayNumber = document.createElement('div');
|
||||
dayNumber.className = 'day-number';
|
||||
dayNumber.textContent = day;
|
||||
dayCell.appendChild(dayNumber);
|
||||
|
||||
const content = document.createElement('div');
|
||||
content.className = 'day-content';
|
||||
// populate scheduled topic if exists
|
||||
const scheduled = loadScheduledTopics();
|
||||
if (scheduled[dateStr]) {
|
||||
const t = document.createElement('div');
|
||||
t.className = 'topic';
|
||||
t.textContent = scheduled[dateStr];
|
||||
content.appendChild(t);
|
||||
}
|
||||
|
||||
dayCell.appendChild(content);
|
||||
calendarGrid.appendChild(dayCell);
|
||||
}
|
||||
|
||||
const totalCells = startWeekday + daysInMonth;
|
||||
const remaining = totalCells % 7;
|
||||
if (remaining !== 0) {
|
||||
const fillers = 7 - remaining;
|
||||
for (let i = 0; i < fillers; i += 1) {
|
||||
const emptyCell = document.createElement('div');
|
||||
emptyCell.className = 'day empty';
|
||||
calendarGrid.appendChild(emptyCell);
|
||||
}
|
||||
}
|
||||
|
||||
const title = `${monthNames[month].charAt(0).toUpperCase() + monthNames[month].slice(1)} ${year}`;
|
||||
monthTitle.textContent = title;
|
||||
}
|
||||
|
||||
function pad(n) { return String(n).padStart(2, '0'); }
|
||||
|
||||
function loadScheduledTopics() {
|
||||
try { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}'); } catch (e) { return {}; }
|
||||
}
|
||||
|
||||
function saveScheduledTopics(obj) { localStorage.setItem(STORAGE_KEY, JSON.stringify(obj)); }
|
||||
|
||||
function generateTopics() {
|
||||
const blocks = [9,5,9,10];
|
||||
const topics = [];
|
||||
blocks.forEach((count, idx) => {
|
||||
for (let i = 1; i <= count; i++) topics.push(`Bloque ${idx+1} — Tema ${i}`);
|
||||
});
|
||||
return topics;
|
||||
}
|
||||
|
||||
function getNextMonday(fromDate) {
|
||||
const d = new Date(fromDate);
|
||||
const day = d.getDay(); // 0 Sun, 1 Mon
|
||||
let diff = (1 + 7 - day) % 7;
|
||||
if (diff === 0) diff = 7;
|
||||
d.setDate(d.getDate() + diff);
|
||||
return d;
|
||||
}
|
||||
|
||||
function scheduleOnePerWeek(topics) {
|
||||
const scheduled = loadScheduledTopics();
|
||||
let date = getNextMonday(new Date());
|
||||
for (let i = 0; i < topics.length; i++) {
|
||||
const ds = date.toISOString().slice(0,10);
|
||||
scheduled[ds] = topics[i];
|
||||
date.setDate(date.getDate() + 7);
|
||||
}
|
||||
saveScheduledTopics(scheduled);
|
||||
}
|
||||
|
||||
autoScheduleBtn?.addEventListener('click', () => {
|
||||
if (!confirm('Programar 1 tema por semana empezando el próximo lunes?')) return;
|
||||
const topics = generateTopics();
|
||||
scheduleOnePerWeek(topics);
|
||||
renderCalendar(currentYear, currentMonth);
|
||||
alert('Temas programados. Navega meses para verlos.');
|
||||
});
|
||||
|
||||
function goToPreviousMonth() {
|
||||
currentMonth -= 1;
|
||||
if (currentMonth < 0) {
|
||||
currentMonth = 11;
|
||||
currentYear -= 1;
|
||||
}
|
||||
renderCalendar(currentYear, currentMonth);
|
||||
}
|
||||
|
||||
function goToNextMonth() {
|
||||
currentMonth += 1;
|
||||
if (currentMonth > 11) {
|
||||
currentMonth = 0;
|
||||
currentYear += 1;
|
||||
}
|
||||
renderCalendar(currentYear, currentMonth);
|
||||
}
|
||||
|
||||
prevMonthBtn.addEventListener('click', goToPreviousMonth);
|
||||
nextMonthBtn.addEventListener('click', goToNextMonth);
|
||||
|
||||
// If there is no scheduling stored yet, auto-schedule topics once
|
||||
if (Object.keys(loadScheduledTopics()).length === 0) {
|
||||
scheduleOnePerWeek(generateTopics());
|
||||
}
|
||||
|
||||
renderCalendar(currentYear, currentMonth);
|
||||
});
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security" lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Planning TAI — Agenda</title>
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
<link rel="stylesheet" href="css/planning.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="planning-container">
|
||||
<h1><i class="fas fa-calendar-alt"></i> Mi Planning 2026</h1>
|
||||
|
||||
<!-- Header con navegación -->
|
||||
<div class="planning-header">
|
||||
<div class="month-nav">
|
||||
<button class="nav-btn" id="prevMonth" title="Mes anterior"><i class="fas fa-chevron-left"></i></button>
|
||||
<div class="month-title" id="monthTitle"></div>
|
||||
<button class="nav-btn" id="nextMonth" title="Próximo mes"><i class="fas fa-chevron-right"></i></button>
|
||||
</div>
|
||||
<button class="reset-btn" id="resetBtn" title="Limpiar todo"><i class="fas fa-trash"></i> Limpiar todo</button>
|
||||
<button class="btn btn-outline" id="autoScheduleBtn" title="Programar 1 tema por semana">Programar 1 tema/semana</button>
|
||||
</div>
|
||||
|
||||
<!-- Formulario para agregar tareas -->
|
||||
<form class="add-task-form" id="addTaskForm">
|
||||
<input
|
||||
type="text"
|
||||
id="taskInput"
|
||||
placeholder="Escribe una tarea..."
|
||||
maxlength="80"
|
||||
autocomplete="off"
|
||||
>
|
||||
<button type="submit"><i class="fas fa-plus"></i> Agregar</button>
|
||||
</form>
|
||||
|
||||
<!-- Calendario -->
|
||||
<div class="calendar-grid" id="calendarGrid"></div>
|
||||
</div>
|
||||
|
||||
<script src="js/planning.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue