feat: unified sort overview with n.i.O./i.O. badges, sortable by filename

This commit is contained in:
Ferdinand
2026-04-08 13:06:08 +02:00
parent 35dccd4f1b
commit 3057538642

View File

@@ -133,8 +133,8 @@
<!-- Review -->
<div id="view-review" class="view card">
<h2 style="margin-bottom: 0.5rem;">Vorschau aussortierter Fotos</h2>
<p style="color: #888; font-size: 0.85rem; margin-bottom: 1rem;">Klicke "Behalten", um ein Foto von der Liste zu entfernen.</p>
<h2 style="margin-bottom: 0.5rem;">Sortierübersicht</h2>
<p style="color: #888; font-size: 0.85rem; margin-bottom: 1rem;">Alle Fotos auf einen Blick — klicke auf ein Vorschaubild zum Vergrößern oder ändere die Entscheidung per Button.</p>
<div id="review-list"></div>
<button class="primary" id="confirm-btn">Alle bestaetigen &amp; verschieben</button>
</div>
@@ -264,20 +264,20 @@
const list = el("review-list");
list.textContent = "";
// --- Aussortierte Fotos ---
if (analysisResults.length > 0) {
const div = document.createElement("div");
div.className = "section-divider";
div.textContent = "Aussortieren (" + analysisResults.length + ")";
list.appendChild(div);
}
// Alle Fotos zusammenführen und nach Dateiname sortieren
const flaggedMap = {};
analysisResults.forEach((item, idx) => { flaggedMap[item.path] = { item, idx }; });
analysisResults.forEach((item, idx) => {
const name = item.path.split("/").pop();
const allEntries = [
...analysisResults.map((item, idx) => ({ path: item.path, flagged: true, reasons: item.reasons, idx })),
...okPaths.map(path => ({ path, flagged: false, reasons: [], idx: null })),
].sort((a, b) => a.path.split("/").pop().localeCompare(b.path.split("/").pop()));
allEntries.forEach(entry => {
const name = entry.path.split("/").pop();
const row = document.createElement("div");
row.className = "photo-item";
row.id = "item-" + idx;
if (entry.idx !== null) row.id = "item-" + entry.idx;
const info = document.createElement("div");
info.className = "photo-info";
@@ -287,76 +287,57 @@
nameEl.textContent = name;
const badge = document.createElement("span");
badge.className = "badge-reject";
badge.textContent = "aussortieren";
badge.className = entry.flagged ? "badge-reject" : "badge-ok";
badge.textContent = entry.flagged ? "n.i.O." : "i.O.";
nameEl.appendChild(badge);
info.appendChild(nameEl);
if (entry.reasons.length > 0) {
const reasonsEl = document.createElement("div");
reasonsEl.className = "photo-reasons";
reasonsEl.textContent = item.reasons.join(", ");
info.appendChild(nameEl);
reasonsEl.textContent = entry.reasons.join(", ");
info.appendChild(reasonsEl);
}
const btn = document.createElement("button");
btn.className = "keep-btn";
btn.textContent = "Behalten";
btn.textContent = entry.flagged ? "Behalten" : "Aussortieren";
btn.addEventListener("click", () => {
row.classList.toggle("kept");
const isKept = row.classList.contains("kept");
btn.textContent = isKept ? "Aussortieren" : "Behalten";
badge.textContent = isKept ? "i.O." : "aussortieren";
badge.className = isKept ? "badge-ok" : "badge-reject";
entry.flagged = !entry.flagged;
badge.className = entry.flagged ? "badge-reject" : "badge-ok";
badge.textContent = entry.flagged ? "n.i.O." : "i.O.";
btn.textContent = entry.flagged ? "Behalten" : "Aussortieren";
// Sync mit analysisResults für doMove
if (entry.idx !== null) {
row.classList.toggle("kept", !entry.flagged);
} else {
// Manuell zum Aussortieren markiert
row.id = "manual-" + entry.path;
}
});
row.appendChild(makeThumb(item.path, name));
row.appendChild(makeThumb(entry.path, name));
row.appendChild(info);
row.appendChild(btn);
list.appendChild(row);
});
// --- i.O. Fotos ---
if (okPaths.length > 0) {
const div = document.createElement("div");
div.className = "section-divider";
div.textContent = "Behalten i.O. (" + okPaths.length + ")";
list.appendChild(div);
okPaths.forEach(path => {
const name = path.split("/").pop();
const row = document.createElement("div");
row.className = "photo-item";
const info = document.createElement("div");
info.className = "photo-info";
const nameEl = document.createElement("div");
nameEl.className = "photo-name";
nameEl.textContent = name;
const badge = document.createElement("span");
badge.className = "badge-ok";
badge.textContent = "i.O.";
nameEl.appendChild(badge);
info.appendChild(nameEl);
row.appendChild(makeThumb(path, name));
row.appendChild(info);
list.appendChild(row);
});
}
// Für doMove: manuelle Auswahl über allEntries tracken
list._allEntries = allEntries;
}
// --- Confirm & Move ---
el("confirm-btn").addEventListener("click", () => doMove(false));
async function doMove(skipReview = true) {
const toMove = skipReview
? analysisResults.map(r => r.path)
: analysisResults.filter((_, idx) => {
const row = el("item-" + idx);
return row && !row.classList.contains("kept");
}).map(r => r.path);
let toMove;
if (skipReview) {
toMove = analysisResults.map(r => r.path);
} else {
const entries = el("review-list")._allEntries || [];
toMove = entries.filter(e => e.flagged).map(e => e.path);
}
if (toMove.length === 0) {
renderResult(0);