Files
LOGIS/templates/admin/properties/property/upload_photos.html
T
2026-05-28 23:43:20 +02:00

241 lines
6.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block title %}📷 Ajout de photos — {{ property.name_fr }}{% endblock %}
{% block extrahead %}
{{ block.super }}
<style>
.upload-card {
background: #fff;
border: 1px solid #ccc;
border-radius: 6px;
padding: 24px;
max-width: 680px;
margin: 20px 0;
}
.upload-card h2 { margin-top: 0; font-size: 16px; color: #417690; }
.upload-card .form-row { margin-bottom: 16px; }
.upload-card label {
display: block;
font-weight: bold;
margin-bottom: 4px;
font-size: 13px;
}
.upload-card select,
.upload-card input[type=text],
.upload-card input[type=file] {
width: 100%;
padding: 6px 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 13px;
box-sizing: border-box;
}
.upload-card .help { font-size: 11px; color: #888; margin-top: 4px; }
.upload-card .separator {
text-align: center;
color: #999;
font-size: 12px;
margin: 4px 0;
position: relative;
}
.drop-zone {
border: 2px dashed #417690;
border-radius: 6px;
padding: 32px 20px;
text-align: center;
cursor: pointer;
transition: background .2s;
background: #f9fbfc;
}
.drop-zone.dragover { background: #e8f3fa; border-color: #2c6a8e; }
.drop-zone p { margin: 0; color: #417690; font-size: 14px; }
.drop-zone small { color: #888; font-size: 12px; }
#file-preview { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.preview-item {
position: relative;
width: 80px;
height: 80px;
border-radius: 4px;
overflow: hidden;
border: 1px solid #ddd;
}
.preview-item img { width: 100%; height: 100%; object-fit: cover; }
.preview-item span {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,.55);
color: #fff;
font-size: 9px;
padding: 2px 3px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.submit-row { display: flex; gap: 10px; margin-top: 20px; }
.btn-upload {
background: #417690;
color: #fff;
border: none;
padding: 10px 22px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
}
.btn-upload:hover { background: #2c6a8e; }
.btn-again {
background: #f0f0f0;
color: #333;
border: 1px solid #ccc;
padding: 10px 18px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
}
#file-count { font-size: 12px; color: #417690; margin-top: 6px; }
</style>
{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">Accueil</a>
<a href="{% url 'admin:app_list' app_label='properties' %}">Properties</a>
<a href="{% url 'admin:properties_property_changelist' %}">Biens immobiliers</a>
<a href="{% url 'admin:properties_property_change' property.pk %}">{{ property.name_fr }}</a>
Ajout de photos
</div>
{% endblock %}
{% block content %}
<h1>📷 Ajout groupé de photos — <em>{{ property.name_fr }}</em></h1>
{% if messages %}
{% for msg in messages %}
<p class="success">{{ msg }}</p>
{% endfor %}
{% endif %}
<form method="post" enctype="multipart/form-data" id="upload-form">
{% csrf_token %}
<div class="upload-card">
<h2>1. Sélectionner ou créer une pièce</h2>
<div class="form-row">
<label for="id_room">Pièce existante :</label>
<select name="room" id="id_room">
<option value="">— Photos générales (sans pièce) —</option>
{% for room in rooms %}
<option value="{{ room.pk }}">{{ room.name_fr }}</option>
{% endfor %}
</select>
</div>
<div class="separator">— ou créer une nouvelle pièce —</div>
<div class="form-row">
<label for="id_new_room_fr">Nom français de la nouvelle pièce :</label>
<input type="text" name="new_room_fr" id="id_new_room_fr"
placeholder="ex : Cuisine, Salon, Chambre 1…"
autocomplete="off">
<p class="help">Si renseigné, cette pièce est créée et les photos lui sont attribuées (prioritaire sur la sélection ci-dessus).</p>
</div>
<div class="form-row">
<label for="id_new_room_en">Nom anglais (optionnel) :</label>
<input type="text" name="new_room_en" id="id_new_room_en"
placeholder="ex : Kitchen, Living room, Bedroom 1…"
autocomplete="off">
</div>
</div>
<div class="upload-card">
<h2>2. Choisir les photos</h2>
<div class="drop-zone" id="drop-zone">
<p>📂 Glisser-déposer les photos ici</p>
<small>ou cliquer pour sélectionner (sélection multiple possible)</small>
<input type="file" name="images" id="id_images"
multiple accept="image/*"
style="position:absolute;opacity:0;width:0;height:0">
</div>
<div id="file-count"></div>
<div id="file-preview"></div>
</div>
<div class="submit-row">
<button type="submit" name="next" value="change" class="btn-upload">
✓ Télécharger et revenir à la fiche
</button>
<button type="submit" name="next" value="again" class="btn-again">
✓ Télécharger et ajouter une autre pièce
</button>
<a href="{% url 'admin:properties_property_change' property.pk %}"
style="padding:10px 16px;font-size:14px;color:#666">
Annuler
</a>
</div>
</form>
<script>
(function () {
const dropZone = document.getElementById('drop-zone');
const input = document.getElementById('id_images');
const preview = document.getElementById('file-preview');
const fileCount = document.getElementById('file-count');
let dt = new DataTransfer();
// Ouvrir le sélecteur au clic sur la zone
dropZone.addEventListener('click', () => input.click());
// Drag-and-drop
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.classList.add('dragover');
});
dropZone.addEventListener('dragleave', () => dropZone.classList.remove('dragover'));
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.classList.remove('dragover');
addFiles(e.dataTransfer.files);
});
input.addEventListener('change', () => {
addFiles(input.files);
input.value = '';
});
function addFiles(files) {
Array.from(files).forEach(f => {
if (!f.type.startsWith('image/')) return;
dt.items.add(f);
showThumb(f);
});
syncInput();
}
function showThumb(file) {
const reader = new FileReader();
reader.onload = (e) => {
const div = document.createElement('div');
div.className = 'preview-item';
div.innerHTML = `<img src="${e.target.result}" alt="${file.name}">
<span>${file.name}</span>`;
preview.appendChild(div);
};
reader.readAsDataURL(file);
}
function syncInput() {
input.files = dt.files;
const n = dt.files.length;
fileCount.textContent = n > 0 ? `${n} photo(s) sélectionnée(s)` : '';
}
})();
</script>
{% endblock %}