Files
ShooterHub/frontend/photos.html
2026-04-02 11:24:30 +02:00

140 lines
6.7 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.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Photos ShooterHub</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="/css/app.css">
<style>
.photo-card { position:relative; border-radius:8px; overflow:hidden; background:#f8f9fa; }
.photo-card img { width:100%; aspect-ratio:4/3; object-fit:cover; display:block; cursor:pointer; transition:opacity .15s; }
.photo-card img:hover { opacity:.88; }
.photo-card .overlay { position:absolute; inset:0; background:linear-gradient(to top,rgba(0,0,0,.55) 0%,transparent 55%); pointer-events:none; }
.photo-card .footer { position:absolute; bottom:0; left:0; right:0; padding:.45rem .6rem; color:#fff; font-size:.75rem; }
.photo-card .actions { position:absolute; top:.4rem; right:.4rem; display:flex; gap:.3rem; opacity:0; transition:opacity .15s; }
.photo-card:hover .actions { opacity:1; }
.photo-card .badge-es { position:absolute; top:.4rem; left:.4rem; font-size:.65rem; }
.btn-icon { padding:.25rem .4rem; line-height:1; font-size:.8rem; }
#loadMoreBtn { display:none; }
</style>
</head>
<body>
<div id="navbar"></div>
<div class="container py-4">
<div class="d-flex align-items-center justify-content-between flex-wrap gap-2 mb-4">
<div>
<h2 class="fw-bold mb-0"><i class="bi bi-images me-2"></i>Photos</h2>
<p class="text-muted small mb-0">Group photos, annotations and group-size measurements.</p>
</div>
<button class="btn btn-primary" id="uploadBtn">
<i class="bi bi-upload me-1"></i>Upload photo
</button>
</div>
<!-- Filters -->
<div class="d-flex flex-wrap gap-2 align-items-center mb-3">
<select class="form-select form-select-sm" id="filterMeasured" style="width:auto">
<option value="">All photos</option>
<option value="measured">Measured only</option>
<option value="unmeasured">Unmeasured only</option>
</select>
<span class="text-muted small ms-auto" id="photoCount"></span>
</div>
<!-- Grid -->
<div class="row g-3" id="photoGrid"></div>
<div class="text-center mt-4">
<div id="gridSpinner" class="text-center py-5 d-none">
<div class="spinner-border text-primary"></div>
</div>
<button class="btn btn-outline-secondary" id="loadMoreBtn">Load more</button>
</div>
<p id="emptyMsg" class="text-center text-muted py-5 d-none">No photos yet. Upload one to get started.</p>
</div>
<!-- ── Lightbox modal ─────────────────────────────────────────────────────── -->
<div class="modal fade" id="lightboxModal" tabindex="-1">
<div class="modal-dialog modal-xl modal-dialog-centered">
<div class="modal-content bg-dark border-0">
<div class="modal-header border-0 py-2 px-3">
<div class="d-flex align-items-center gap-2 flex-wrap">
<span class="text-white fw-semibold" id="lbTitle"></span>
<span id="lbBadge" class="badge bg-success d-none"></span>
</div>
<div class="d-flex gap-2 ms-auto me-2">
<button class="btn btn-sm btn-outline-light" id="lbTogglePublicBtn" title="Make public/private">
<i class="bi bi-lock me-1" id="lbTogglePublicIcon"></i><span id="lbTogglePublicLabel">Private</span>
</button>
<a id="lbMeasureBtn" href="#" class="btn btn-sm btn-outline-light">
<i class="bi bi-crosshair2 me-1"></i>Measure
</a>
<button class="btn btn-sm btn-outline-light" id="lbComputeBtn">
<i class="bi bi-calculator me-1"></i>Compute
</button>
<a id="lbOpenBtn" href="#" target="_blank" class="btn btn-sm btn-outline-light">
<i class="bi bi-box-arrow-up-right"></i>
</a>
</div>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<!-- Stats bar + unit switch -->
<div class="px-3 py-2 border-top border-secondary d-flex flex-wrap align-items-center gap-2">
<div id="lbStats" class="small text-white-50 d-flex flex-wrap gap-3 flex-grow-1"></div>
<div class="btn-group btn-group-sm ms-auto flex-shrink-0" id="lbUnitBtns">
<button class="btn btn-outline-light" data-dist-unit="mm">mm</button>
<button class="btn btn-outline-light" data-dist-unit="moa">MOA</button>
<button class="btn btn-outline-light" data-dist-unit="mrad">MRAD</button>
</div>
</div>
<div class="text-center" style="max-height:75vh;overflow:hidden;background:#111">
<img id="lbImg" src="" alt="" style="max-width:100%;max-height:75vh;object-fit:contain">
</div>
</div>
</div>
</div>
<!-- ── Upload modal ───────────────────────────────────────────────────────── -->
<div class="modal fade" id="uploadModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="bi bi-upload me-2"></i>Upload photo</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="form-label fw-semibold">Photo <span class="text-danger">*</span></label>
<input type="file" class="form-control" id="upFile" accept="image/jpeg,image/png,image/webp">
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Caption <span class="text-muted fw-normal">(optional)</span></label>
<input type="text" class="form-control" id="upCaption" placeholder="e.g. 100m cold bore">
</div>
<div id="upAlert" class="alert alert-danger d-none small"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="upSubmitBtn">
<span id="upSpinner" class="spinner-border spinner-border-sm me-1 d-none"></span>
Upload
</button>
</div>
</div>
</div>
</div>
<div id="toastContainer"></div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="/js/api.js"></script>
<script src="/js/utils.js"></script>
<script src="/js/i18n.js"></script>
<script src="/js/nav.js"></script>
<script src="/js/photos.js"></script>
</body>
</html>