feat(ui): replace all emojis with professional vector SVG icons suite

This commit is contained in:
2026-09-12 09:59:23 -07:00
parent ef36bfb050
commit 19a1108384
6 changed files with 724 additions and 167 deletions
+38 -17
View File
@@ -428,22 +428,30 @@
const crossStreets = cam.crossStreets || (cam.name ? cam.name.split('(')[0].replace(/^.*?-\s*/, '').trim() : 'Intersection Camera');
const badgeHtml = meta.isContested
? `<span class="dir-cam-badge unverified">🟠 CONTESTED</span>`
: (hasPhoto ? `<span class="dir-cam-badge verified">🟢 HARDWARE PHOTO VERIFIED</span>` : `<span class="dir-cam-badge unverified">⚠️ SIGHTING RECORDED</span>`);
? `<span class="dir-cam-badge unverified">${window.FlockIcons ? window.FlockIcons.alertTriangle('flock-svg-sm') : ''} CONTESTED</span>`
: (hasPhoto
? `<span class="dir-cam-badge verified">${window.FlockIcons ? window.FlockIcons.checkCircle('flock-svg-sm') : ''} PHOTO VERIFIED</span>`
: `<span class="dir-cam-badge unverified">${window.FlockIcons ? window.FlockIcons.camera('flock-svg-sm') : ''} SIGHTING RECORDED</span>`);
const imageContainerHtml = hasPhoto
? `<div class="dir-cam-image-container">
<img src="${photoUrl}" class="dir-cam-img" alt="Camera at ${escapeHtml(crossStreets)}" onclick="window.open('${photoUrl}', '_blank')" title="Click to view full photo proof in high resolution">
${badgeHtml}
<div class="dir-cam-img-hover-hint">🔍 Tap to inspect photo proof</div>
<div class="dir-cam-img-hover-hint">
${window.FlockIcons ? window.FlockIcons.search('flock-svg-sm') : ''}
<span>Tap to inspect photo proof</span>
</div>
</div>`
: `<div class="dir-cam-image-container pending">
<div class="dir-cam-placeholder">
<span class="dir-cam-placeholder-icon">📸</span>
<div class="dir-cam-placeholder-icon">
${window.FlockIcons ? window.FlockIcons.camera('flock-svg-lg') : ''}
</div>
<strong style="font-size: 0.84rem; color: #cbd5e1;">Hardware Photo Pending</strong>
<span style="font-size: 0.72rem; color: #94a3b8;">Mounted on utility / signal pole</span>
<button type="button" class="btn-dir-cam-upload-trigger" onclick="window.openCameraHardwareProof('${escapeHtml(cam.id)}')">
<span>+ Upload Photo Proof</span>
${window.FlockIcons ? window.FlockIcons.cameraPlus('flock-svg-sm') : ''}
<span>Upload Photo Proof</span>
</button>
</div>
${badgeHtml}
@@ -456,7 +464,9 @@
<div>
<!-- Cross Streets Prominent Box -->
<div class="dir-cam-cross-box">
<span class="dir-cam-cross-icon">📍</span>
<span class="dir-cam-cross-icon">
${window.FlockIcons ? window.FlockIcons.mapPin('flock-svg-md') : ''}
</span>
<div class="dir-cam-cross-content">
<span class="dir-cam-cross-label">CROSS STREETS</span>
<strong class="dir-cam-cross-value">${escapeHtml(crossStreets)}</strong>
@@ -465,8 +475,8 @@
<h4 class="dir-cam-intersection">${escapeHtml(cam.name)}</h4>
<div class="dir-cam-agency-meta">
<span>🏛️ ${escapeHtml(cam.agency || 'Local Law Enforcement')}</span>
${cam.city ? `<span class="dir-cam-city-tag">🗺️ ${escapeHtml(cam.city)}, ${escapeHtml(cam.state || 'CA')}</span>` : ''}
<span>${window.FlockIcons ? window.FlockIcons.building('flock-svg-sm') : ''} ${escapeHtml(cam.agency || 'Local Law Enforcement')}</span>
${cam.city ? `<span class="dir-cam-city-tag">${window.FlockIcons ? window.FlockIcons.map('flock-svg-sm') : ''} ${escapeHtml(cam.city)}, ${escapeHtml(cam.state || 'CA')}</span>` : ''}
</div>
<div class="dir-cam-specs-row">
@@ -484,18 +494,20 @@
</div>
<div class="dir-cam-spec-item">
<span class="dir-cam-spec-label">CONSENSUS</span>
<span class="dir-cam-spec-val" style="color: #38bdf8;">👍 ${meta.confirmations || 1} Confirmed</span>
<span class="dir-cam-spec-val" style="color: #38bdf8; display: inline-flex; align-items: center; gap: 4px;">
${window.FlockIcons ? window.FlockIcons.thumbUp('flock-svg-sm') : ''} ${meta.confirmations || 1} Confirmed
</span>
</div>
</div>
</div>
<div class="dir-cam-actions">
<button type="button" class="btn-dir-cam-jump" onclick="window.jumpToRadarCamera('${escapeHtml(cam.id)}')">
<span>🗺️</span>
${window.FlockIcons ? window.FlockIcons.radar('flock-svg-sm') : ''}
<span>View on Live Radar</span>
</button>
<button type="button" class="btn-dir-cam-details" onclick="window.openCameraHardwareProof('${escapeHtml(cam.id)}')">
<span>📸</span>
${window.FlockIcons ? window.FlockIcons.camera('flock-svg-sm') : ''}
<span>Camera Info</span>
</button>
</div>
@@ -910,13 +922,22 @@
const toast = document.createElement('div');
toast.className = 'toast';
let icon = '';
if (type === 'success') icon = '✓';
if (type === 'error') icon = '⚠️';
if (type === 'warning') icon = '⚡';
let iconSvg = window.FlockIcons ? FlockIcons.alertTriangle('flock-svg-sm') : '';
if (type === 'success') {
iconSvg = window.FlockIcons ? FlockIcons.checkCircle('flock-svg-sm') : '';
} else if (type === 'error') {
iconSvg = window.FlockIcons ? FlockIcons.alertTriangle('flock-svg-sm') : '';
} else if (type === 'warning') {
iconSvg = window.FlockIcons ? FlockIcons.zap('flock-svg-sm') : '';
} else {
iconSvg = window.FlockIcons ? FlockIcons.radar('flock-svg-sm') : '';
}
toast.innerHTML = `<span>${icon}</span><span>${escapeHtml(message)}</span>`;
el.toastContainer.appendChild(toast);
// Clean any leading emoji characters from message
const cleanMsg = String(message).replace(/^[\u{1F300}-\u{1FAFF}\u{2600}-\u{27BF}\u{2300}-\u{23FF}\s]+/u, '').trim();
toast.innerHTML = `<span class="toast-icon">${iconSvg}</span><span>${escapeHtml(cleanMsg || message)}</span>`;
if (el.toastContainer) el.toastContainer.appendChild(toast);
setTimeout(() => {
toast.style.opacity = '0';