160 lines
7.0 KiB
HTML
160 lines
7.0 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}{% if entry %}Modifier l'entrée{% else %}Nouvelle journée{% endif %}{% endblock %}
|
||
{% block content %}
|
||
|
||
<div class="mb-5">
|
||
<p class="font-display text-2xl font-semibold" style="color:var(--ink);">
|
||
{% if entry %}Modifier{% else %}Nouvelle journée{% endif %}
|
||
</p>
|
||
</div>
|
||
|
||
<form method="POST" class="space-y-5">
|
||
|
||
<!-- Date -->
|
||
<div>
|
||
<label class="field-label">Date</label>
|
||
<input type="date" name="date"
|
||
value="{{ entry.date.isoformat() if entry else today }}"
|
||
class="field-input" required>
|
||
</div>
|
||
|
||
<!-- Type de journée -->
|
||
<div>
|
||
<label class="field-label">Type de journée</label>
|
||
<div class="grid grid-cols-3 gap-2">
|
||
{% for value, label in day_types %}
|
||
<label class="pill-option">
|
||
<input type="radio" name="day_type" value="{{ value }}"
|
||
{% if entry and entry.day_type == value %}checked{% elif not entry and value == 'WORK' %}checked{% endif %}
|
||
onchange="updateJourneyVisibility(this.value)">
|
||
<span class="pill-inner">{{ label }}</span>
|
||
</label>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Trajet domicile-travail -->
|
||
<div id="journey-section"
|
||
class="{% if entry and entry.day_type in day_types_without_journey %}hidden{% endif %}">
|
||
<label class="field-label">Trajet domicile-travail</label>
|
||
<select name="journey_profile_id" id="journey_profile_id"
|
||
onchange="updateMotorVehicleVisibility(this.value)"
|
||
class="field-input">
|
||
<option value="">— Pas de déplacement —</option>
|
||
{% for jid, jdata in journeys.items() %}
|
||
<option value="{{ jid }}"
|
||
data-has-motor="{{ 'true' if 'moteur' in jdata.distances else 'false' }}"
|
||
{% if entry and entry.journey_profile_id == jid %}selected{% endif %}>
|
||
{{ jdata.name }}
|
||
({% for v, d in jdata.distances.items() %}{{ d }} km {{ v }}{% if not loop.last %} + {% endif %}{% endfor %})
|
||
</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
|
||
<!-- Véhicule à moteur -->
|
||
<div id="motor-vehicle-section" class="{% if not entry or not entry.motor_vehicle_id %}hidden{% endif %}">
|
||
<label class="field-label">Véhicule à moteur utilisé</label>
|
||
<div class="grid grid-cols-2 gap-2">
|
||
{% for vid, vdata in motor_vehicles.items() %}
|
||
<label class="pill-option">
|
||
<input type="radio" name="motor_vehicle_id" value="{{ vid }}"
|
||
{% if entry and entry.motor_vehicle_id == vid %}checked{% endif %}>
|
||
<span class="pill-inner" style="font-size:0.72rem;">{{ vdata.name }}</span>
|
||
</label>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Plages horaires -->
|
||
<div>
|
||
<label class="field-label">Plages horaires</label>
|
||
<div id="time-slots" class="space-y-2">
|
||
{% if entry and entry.time_slots %}
|
||
{% for slot in entry.time_slots %}
|
||
<div class="flex gap-2 items-center time-slot-row">
|
||
<input type="time" name="start_time" value="{{ slot.start_time.strftime('%H:%M') }}"
|
||
class="field-input flex-1" style="padding:0.5rem 0.6rem; font-family:'JetBrains Mono',monospace; font-size:0.9rem;">
|
||
<span style="color:var(--mist); font-size:1rem;">→</span>
|
||
<input type="time" name="end_time" value="{{ slot.end_time.strftime('%H:%M') }}"
|
||
class="field-input flex-1" style="padding:0.5rem 0.6rem; font-family:'JetBrains Mono',monospace; font-size:0.9rem;">
|
||
<button type="button" onclick="this.closest('.time-slot-row').remove()"
|
||
class="text-lg leading-none transition-colors" style="color:var(--mist);"
|
||
onmouseover="this.style.color='var(--rust)'" onmouseout="this.style.color='var(--mist)'">×</button>
|
||
</div>
|
||
{% endfor %}
|
||
{% else %}
|
||
<div class="flex gap-2 items-center time-slot-row">
|
||
<input type="time" name="start_time"
|
||
class="field-input flex-1" style="padding:0.5rem 0.6rem; font-family:'JetBrains Mono',monospace; font-size:0.9rem;">
|
||
<span style="color:var(--mist); font-size:1rem;">→</span>
|
||
<input type="time" name="end_time"
|
||
class="field-input flex-1" style="padding:0.5rem 0.6rem; font-family:'JetBrains Mono',monospace; font-size:0.9rem;">
|
||
<button type="button" onclick="this.closest('.time-slot-row').remove()"
|
||
class="text-lg leading-none" style="color:var(--mist);"
|
||
onmouseover="this.style.color='var(--rust)'" onmouseout="this.style.color='var(--mist)'">×</button>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
<button type="button" onclick="addTimeSlot()"
|
||
class="mt-2 text-xs font-semibold" style="color:var(--amber); letter-spacing:0.05em;">
|
||
+ Ajouter une plage
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Commentaire -->
|
||
<div>
|
||
<label class="field-label">Commentaire</label>
|
||
<textarea name="comment" rows="2" class="field-input"
|
||
placeholder="Formation, déplacement exceptionnel…">{{ entry.comment if entry and entry.comment else '' }}</textarea>
|
||
</div>
|
||
|
||
<!-- Actions -->
|
||
<div class="flex gap-3 pt-1">
|
||
<button type="submit" class="btn-primary flex-1">Enregistrer</button>
|
||
<a href="/" class="btn-ghost flex-1">Annuler</a>
|
||
</div>
|
||
</form>
|
||
|
||
<script>
|
||
const NO_JOURNEY_TYPES = {{ day_types_without_journey | list | tojson }};
|
||
|
||
function updateJourneyVisibility(dayType) {
|
||
const journeySection = document.getElementById('journey-section');
|
||
const hidden = NO_JOURNEY_TYPES.includes(dayType);
|
||
journeySection.classList.toggle('hidden', hidden);
|
||
if (hidden) {
|
||
updateMotorVehicleVisibility('');
|
||
} else {
|
||
const select = document.getElementById('journey_profile_id');
|
||
if (select) updateMotorVehicleVisibility(select.value);
|
||
}
|
||
}
|
||
|
||
function updateMotorVehicleVisibility(journeyId) {
|
||
const section = document.getElementById('motor-vehicle-section');
|
||
const select = document.getElementById('journey_profile_id');
|
||
const selectedOption = select ? select.querySelector(`option[value="${journeyId}"]`) : null;
|
||
const hasMotor = selectedOption && selectedOption.dataset.hasMotor === 'true';
|
||
section.classList.toggle('hidden', !hasMotor);
|
||
}
|
||
|
||
function addTimeSlot() {
|
||
const container = document.getElementById('time-slots');
|
||
const row = document.createElement('div');
|
||
row.className = 'flex gap-2 items-center time-slot-row';
|
||
row.innerHTML = `
|
||
<input type="time" name="start_time"
|
||
class="field-input flex-1" style="padding:0.5rem 0.6rem;font-family:'JetBrains Mono',monospace;font-size:0.9rem;">
|
||
<span style="color:var(--mist);font-size:1rem;">→</span>
|
||
<input type="time" name="end_time"
|
||
class="field-input flex-1" style="padding:0.5rem 0.6rem;font-family:'JetBrains Mono',monospace;font-size:0.9rem;">
|
||
<button type="button" onclick="this.closest('.time-slot-row').remove()"
|
||
class="text-lg leading-none" style="color:var(--mist);"
|
||
onmouseover="this.style.color='var(--rust)'" onmouseout="this.style.color='var(--mist)'">×</button>
|
||
`;
|
||
container.appendChild(row);
|
||
}
|
||
</script>
|
||
{% endblock %}
|