140 lines
6.7 KiB
HTML
140 lines
6.7 KiB
HTML
<!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>
|