Initial commit
This commit is contained in:
274
templates/schedule_form.html
Normal file
274
templates/schedule_form.html
Normal file
@@ -0,0 +1,274 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}{% if schedule %}Schema Bijwerken{% else %}Schema Toevoegen{% endif %}{% endblock %}
|
||||
{% block content %}
|
||||
<style>
|
||||
.preview-container {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
max-width: 900px;
|
||||
margin: 0 auto 2rem auto;
|
||||
background: white;
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
.preview-wrapper {
|
||||
width: 250px;
|
||||
height: 444px;
|
||||
background: #222;
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
.liturgie-board {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
gap: 0.6vh;
|
||||
padding-left: 5%;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
.liturgie-line {
|
||||
width: 90%;
|
||||
font-size: 28px;
|
||||
line-height: 1.2;
|
||||
text-shadow: 2px 2px 8px #000, 0 0 4px #000;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
outline: none;
|
||||
cursor: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
/* Highlight for drag-over between lines in preview */
|
||||
.liturgie-line.line-over {
|
||||
background: rgba(255,255,255,0.22);
|
||||
border: 2px dashed #fff;
|
||||
box-sizing: border-box;
|
||||
outline: none;
|
||||
transition: background 0.12s, border 0.12s;
|
||||
}
|
||||
|
||||
.liturgie-line.swap-animate {
|
||||
animation: swap-pulse 0.35s;
|
||||
}
|
||||
@keyframes swap-pulse {
|
||||
0% { background: #ffe066; }
|
||||
60% { background: #fff3cd; }
|
||||
100% { background: none; }
|
||||
}
|
||||
.input-section {
|
||||
flex: 1 1 260px;
|
||||
min-width: 260px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
.input-section label {
|
||||
font-weight: 700;
|
||||
color: #374151;
|
||||
display: block;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
.input-section input {
|
||||
width: 100%;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
font-size: 1rem;
|
||||
outline: none;
|
||||
box-shadow: inset 0 1px 2px rgb(0 0 0 / 0.1);
|
||||
transition: border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
|
||||
}
|
||||
.input-section input:focus {
|
||||
border-color: #2563eb;
|
||||
box-shadow: 0 0 5px #93c5fd;
|
||||
}
|
||||
.save-button {
|
||||
padding: 0.75rem 1.25rem;
|
||||
background-color: #16a34a;
|
||||
color: white;
|
||||
border-radius: 0.375rem;
|
||||
font-weight: 700;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
margin-top: auto;
|
||||
}
|
||||
.save-button:hover {
|
||||
background-color: #15803d;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.preview-container {
|
||||
flex-direction: column;
|
||||
max-width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.preview-wrapper {
|
||||
width: 200px;
|
||||
height: 355px;
|
||||
margin: 0 auto 1rem auto;
|
||||
}
|
||||
.input-section {
|
||||
min-width: unset;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<h1 class="text-3xl font-bold mb-6 text-center">{% if schedule %}Schema Bijwerken{% else %}Schema Toevoegen{% endif %}</h1>
|
||||
<form method="post" id="scheduleForm">
|
||||
<div class="preview-container">
|
||||
<!-- Left: Live preview with editable lines -->
|
||||
<div class="preview-wrapper" style="font-family: 'Lora', serif; position: relative; background-image: {% if schedule and schedule.boards_list|length > 0 %}
|
||||
{% set board_bg = schedule.boards_list[0].background_image if schedule.boards_list[0].background_image else None %}
|
||||
{% if board_bg %}
|
||||
url('{% if board_bg.startswith('default_') %}{{ url_for('static', filename=board_bg) }}{% else %}{{ url_for('uploaded_file', filename=board_bg) }}{% endif %}')
|
||||
{% else %}none
|
||||
{% endif %}
|
||||
{% else %}none
|
||||
{% endif %}; background-color:#222; background-size: cover; background-position: center;">
|
||||
<div class="liturgie-bg-overlay" style="
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
"></div>
|
||||
<div class="liturgie-board" contenteditable="false" style="position: relative; z-index: 2; font-family: 'Lora', serif;">
|
||||
{% set lines = schedule.content.split('\n') if schedule and schedule.content else [' ']*10 %}
|
||||
{% for i in range(10) %}
|
||||
<div class="liturgie-line" contenteditable="true" data-line="line{{ i+1 }}" spellcheck="false">{{ lines[i] if i < lines|length else ' ' }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right: Input fields for schedule name, date, time, board assignment, and save button -->
|
||||
<div class="input-section">
|
||||
<label for="name">Naam:</label>
|
||||
<input type="text" id="name" name="name" required value="{{ schedule.name if schedule else '' }}">
|
||||
|
||||
<label for="date">Datum:</label>
|
||||
<input type="date" id="date" name="date" required value="{{ schedule.date.strftime('%Y-%m-%d') if schedule and schedule.date else '' }}">
|
||||
|
||||
<div style="display: flex; gap: 1rem; align-items: center;">
|
||||
<div style="flex: 1;">
|
||||
<label for="start_time">Starttijd:</label>
|
||||
<input type="time" id="start_time" name="start_time" required value="{{ schedule.start_time.strftime('%H:%M') if schedule and schedule.start_time else '' }}">
|
||||
</div>
|
||||
<div style="flex: 1;">
|
||||
<label for="end_time">Eindtijd:</label>
|
||||
<input type="time" id="end_time" name="end_time" required value="{{ schedule.end_time.strftime('%H:%M') if schedule and schedule.end_time else '' }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label>Toegewezen borden:</label>
|
||||
<div class="overflow-hidden rounded-lg max-h-56 overflow-y-auto mb-6 border border-gray-200">
|
||||
<table class="min-w-full divide-y divide-gray-200 border-collapse">
|
||||
<thead class="bg-gray-50">
|
||||
<tr class="divide-x divide-gray-200">
|
||||
<th scope="col" class="py-3.5 pl-4 pr-4 text-left text-sm font-semibold text-gray-900 sm:pl-6">Naam</th>
|
||||
<th scope="col" class="px-4 py-3.5 text-center text-sm font-semibold text-gray-900">Toewijzen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 bg-white">
|
||||
{% for board in boards %}
|
||||
<tr class="divide-x divide-gray-200 hover:bg-gray-50 cursor-pointer">
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-4 text-sm font-semibold text-gray-900 sm:pl-6">{{ board.name }}</td>
|
||||
<td class="whitespace-nowrap px-4 py-4 text-center text-sm font-semibold text-gray-900 flex justify-center items-center">
|
||||
<label class="relative inline-flex items-center cursor-pointer">
|
||||
<input type="checkbox" value="{{ board.id }}" name="boards" class="sr-only peer" {% if schedule and board in schedule.boards_list %}checked{% endif %}>
|
||||
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 rounded-full peer peer-checked:bg-blue-600 transition-all duration-300"></div>
|
||||
<div class="absolute left-1 top-1 bg-white w-4 h-4 rounded-full transition-transform duration-300 peer-checked:translate-x-5"></div>
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="bg-[#f7d91a] text-black px-8 py-3 rounded font-semibold hover:bg-yellow-300 transition">Opslaan</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Hidden inputs to store lines for form submission -->
|
||||
{% for i in range(1, 11) %}
|
||||
<input type="hidden" name="line{{ i }}" id="hidden-line{{ i }}" value="">
|
||||
{% endfor %}
|
||||
</form>
|
||||
|
||||
<script>
|
||||
// --- Line drag-and-swap logic ---
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
let dragSrc = null;
|
||||
const lines = document.querySelectorAll('.liturgie-line[data-line]');
|
||||
lines.forEach(line => {
|
||||
line.addEventListener('dragstart', function (e) {
|
||||
dragSrc = this;
|
||||
this.classList.add('dragging');
|
||||
});
|
||||
line.addEventListener('dragend', function (e) {
|
||||
this.classList.remove('dragging');
|
||||
dragSrc = null;
|
||||
lines.forEach(l => l.classList.remove('line-over'));
|
||||
});
|
||||
line.addEventListener('dragover', function (e) {
|
||||
e.preventDefault();
|
||||
if (this !== dragSrc) this.classList.add('line-over');
|
||||
});
|
||||
line.addEventListener('dragleave', function (e) {
|
||||
this.classList.remove('line-over');
|
||||
});
|
||||
line.addEventListener('drop', function (e) {
|
||||
e.preventDefault();
|
||||
this.classList.remove('line-over');
|
||||
if (dragSrc && dragSrc !== this) {
|
||||
// Only swap textContent, not the whole element
|
||||
const tmp = this.textContent;
|
||||
this.textContent = dragSrc.textContent;
|
||||
dragSrc.textContent = tmp;
|
||||
// animation for both lines
|
||||
this.classList.add('swap-animate');
|
||||
dragSrc.classList.add('swap-animate');
|
||||
setTimeout(() => {
|
||||
this.classList.remove('swap-animate');
|
||||
dragSrc.classList.remove('swap-animate');
|
||||
}, 400);
|
||||
}
|
||||
});
|
||||
// Make lines draggable
|
||||
line.setAttribute('draggable', 'true');
|
||||
});
|
||||
});
|
||||
// --- End drag-and-swap logic ---
|
||||
|
||||
document.getElementById('scheduleForm').addEventListener('submit', function(e) {
|
||||
// Copy content from editable divs to hidden inputs
|
||||
for (let i = 1; i <= 10; i++) {
|
||||
let div = document.querySelector('.liturgie-line[data-line="line' + i + '"]');
|
||||
let hiddenInput = document.getElementById('hidden-line' + i);
|
||||
if (div && hiddenInput) {
|
||||
hiddenInput.value = div.textContent.trim() || ' ';
|
||||
}
|
||||
}
|
||||
});
|
||||
// Optional: keyboard navigation and basic shortcuts could be added here
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user