fix: make log button directly open camera for photo proof and remove unverified test marks

This commit is contained in:
2026-09-12 09:08:36 -07:00
parent ad6b99260e
commit b10b6e0f2f
3 changed files with 76 additions and 64 deletions
+4 -4
View File
@@ -274,13 +274,13 @@
<span>Recenter on Vehicle</span> <span>Recenter on Vehicle</span>
</button> </button>
<!-- Giant 1-Tap Floating Action Button: Log Flock Camera (Bottom-Right) --> <!-- Giant 1-Tap Floating Action Button: Snap & Log Flock Camera (Bottom-Right) -->
<div class="driver-fab-container"> <div class="driver-fab-container">
<button id="btn-quick-log-cam" class="btn-driver-fab" title="1-Tap: Log a Flock camera at your exact current GPS location"> <button id="btn-quick-log-cam" class="btn-driver-fab" title="Snap camera photo on pole & log at GPS location">
<div class="fab-icon-glow">📸</div> <div class="fab-icon-glow">📸</div>
<div class="fab-text-group"> <div class="fab-text-group">
<span class="fab-main-title">+ LOG FLOCK CAMERA</span> <span class="fab-main-title">+ SNAP & LOG CAMERA</span>
<span class="fab-sub-title">1-Tap Pin at GPS Location</span> <span class="fab-sub-title">Opens Camera for Photo Proof</span>
</div> </div>
</button> </button>
</div> </div>
+31
View File
@@ -122,6 +122,12 @@
const stored = localStorage.getItem(STORAGE_KEY_REPORTS); const stored = localStorage.getItem(STORAGE_KEY_REPORTS);
if (stored) { if (stored) {
communityReports = JSON.parse(stored); communityReports = JSON.parse(stored);
// Automatically prune any unverified test marks or pins without photo proof
const beforeCount = communityReports.length;
communityReports = communityReports.filter(r => r && r.photoUrl && !r.id.startsWith('usr-pin-'));
if (communityReports.length !== beforeCount) {
localStorage.setItem(STORAGE_KEY_REPORTS, JSON.stringify(communityReports));
}
} else { } else {
communityReports = []; communityReports = [];
} }
@@ -130,6 +136,29 @@
} }
} }
function clearUnverifiedReports() {
try {
communityReports = communityReports.filter(r => r && r.photoUrl && !r.id.startsWith('usr-pin-'));
localStorage.setItem(STORAGE_KEY_REPORTS, JSON.stringify(communityReports));
Object.keys(cameraMetadata).forEach(id => {
if (id.startsWith('usr-pin-') || !cameraMetadata[id].photoUrl) {
delete cameraMetadata[id];
}
});
localStorage.setItem(STORAGE_KEY_METADATA, JSON.stringify(cameraMetadata));
window.dispatchEvent(new CustomEvent('flock_reports_updated', { detail: communityReports }));
} catch (e) {
console.warn('Could not clear unverified reports', e);
}
}
function removeReport(reportId) {
communityReports = communityReports.filter(r => r.id !== reportId);
if (cameraMetadata[reportId]) delete cameraMetadata[reportId];
saveReports();
saveMetadata();
}
function saveReports() { function saveReports() {
try { try {
localStorage.setItem(STORAGE_KEY_REPORTS, JSON.stringify(communityReports)); localStorage.setItem(STORAGE_KEY_REPORTS, JSON.stringify(communityReports));
@@ -339,6 +368,8 @@
saveUser, saveUser,
getReports, getReports,
addReport, addReport,
removeReport,
clearUnverifiedReports,
getCameraMeta, getCameraMeta,
confirmCamera, confirmCamera,
addPhotoProof, addPhotoProof,
+41 -60
View File
@@ -286,24 +286,33 @@
}); });
} }
// --- LOAD CAMERA DATA (DEFAULTS + COMMUNITY + MUNICIPAL HUBS) --- // --- LOAD CAMERA DATA (DEFAULTS + VERIFIED COMMUNITY + MUNICIPAL HUBS) ---
function loadAllCameraData() { function loadAllCameraData() {
allCameras = [...DEFAULT_CAMERAS]; // Purge any unverified test marks or pins without photo proof
if (window.FlockAuth && typeof window.FlockAuth.clearUnverifiedReports === 'function') {
window.FlockAuth.clearUnverifiedReports();
}
// Load crowdsourced reports from auth store // Filter out any unverified user pins
allCameras = [...DEFAULT_CAMERAS].filter(c => !c.id.startsWith('usr-pin-'));
// Load crowdsourced reports from auth store (ONLY if photo verified!)
if (window.FlockAuth) { if (window.FlockAuth) {
const reports = window.FlockAuth.getReports(); const reports = window.FlockAuth.getReports();
reports.forEach(r => { reports.forEach(r => {
// Strict verification rule: Sighting MUST have verified photo proof!
if (!r || !r.photoUrl || r.id.startsWith('usr-pin-')) return;
allCameras.push({ allCameras.push({
id: r.id, id: r.id,
name: `Community Report: ${r.type}`, name: `Verified Sighting: ${r.type || 'Solar Pole Mount'}`,
lat: r.lat, lat: r.lat,
lng: r.lng, lng: r.lng,
radius: 280, radius: 280,
agency: 'Crowdsourced Report', agency: 'Community Verified ALPR',
slug: '', slug: '',
cameras: 1, cameras: 1,
captures30d: 'Active Surveillance Zone', captures30d: 'Photo Verified Hardware',
isCommunity: true, isCommunity: true,
reportedBy: r.reportedBy, reportedBy: r.reportedBy,
notes: r.notes notes: r.notes
@@ -629,61 +638,13 @@
} }
} }
// --- 1-TAP DRIVER QUICK-LOG CAMERA --- // --- 1-TAP DRIVER QUICK-LOG CAMERA (IMMEDIATELY OPENS CAMERA FOR PHOTO PROOF) ---
function quickLogFlockCameraAtCurrentLocation() { function quickLogFlockCameraAtCurrentLocation() {
const lat = currentPosition.lat; photoUploadTarget = 'quicklog';
const lng = currentPosition.lng; if (el.cameraPhotoFileInput) {
const timeStr = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); el.cameraPhotoFileInput.value = '';
const camId = 'usr-pin-' + Date.now(); el.cameraPhotoFileInput.click();
const newCam = {
id: camId,
name: `Driver Pinned Camera (${timeStr})`,
lat: lat,
lng: lng,
radius: 280,
agency: 'Driver Crowdsourced ALPR',
slug: '',
cameras: 1,
captures30d: 'Verified Mobile Sighting',
isCommunity: true,
reportedBy: 'Active Driver',
notes: 'Logged via 1-Tap Dashboard Button'
};
allCameras.unshift(newCam);
// Save to persistence store
if (window.FlockAuth) {
const reports = window.FlockAuth.getReports();
reports.unshift({
id: camId,
type: 'Fixed ALPR Camera',
lat: lat,
lng: lng,
reportedBy: 'Active Driver',
timestamp: new Date().toISOString(),
notes: '1-Tap Mobile Driver Pin'
});
localStorage.setItem('flock_community_reports', JSON.stringify(reports));
} }
// Immediately draw the new red perimeter circle
renderCameraZones();
// Positive audio feedback + voice announcement
playLogConfirmationChirp();
speakVoiceAlert("Camera logged at current location. Radar grid updated.");
// Animate the button briefly
if (el.btnQuickLogCam) {
el.btnQuickLogCam.style.transform = 'scale(1.1)';
setTimeout(() => {
if (el.btnQuickLogCam) el.btnQuickLogCam.style.transform = '';
}, 300);
}
showToast("📸 Camera logged at current location & synced to radar!");
} }
// --- AUTO-CENTER / FOLLOW CAR HANDLER --- // --- AUTO-CENTER / FOLLOW CAR HANDLER ---
@@ -1506,7 +1467,27 @@
showToast("📸 Processing & compressing photo proof..."); showToast("📸 Processing & compressing photo proof...");
const compressedDataUrl = await window.FlockAuth.compressImage(file, 1000, 0.72); const compressedDataUrl = await window.FlockAuth.compressImage(file, 1000, 0.72);
if (photoUploadTarget === 'detail' && activeModalCamera) { if (photoUploadTarget === 'quicklog') {
const timeStr = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
const newRpt = window.FlockAuth.addReport({
lat: currentPosition.lat,
lng: currentPosition.lng,
type: 'Solar Pole Mount (Falcon)',
intersection: `Driver Sighting (${timeStr})`,
notes: 'Physical photo evidence captured by scout on pole',
photoUrl: compressedDataUrl
});
loadAllCameraData();
renderCameraZones();
updateProfileDisplay();
playLogConfirmationChirp();
speakVoiceAlert("Camera photo proof verified and logged to radar grid. +150 Scout Points!");
showToast("📸 Camera photo proof verified & logged! +150 Scout Points!");
const cam = allCameras.find(c => c.id === newRpt.id);
if (cam) openCameraDetailModal(cam);
} else if (photoUploadTarget === 'detail' && activeModalCamera) {
window.FlockAuth.addPhotoProof(activeModalCamera.id, compressedDataUrl, 'Physical pole photo uploaded by scout'); window.FlockAuth.addPhotoProof(activeModalCamera.id, compressedDataUrl, 'Physical pole photo uploaded by scout');
openCameraDetailModal(activeModalCamera); openCameraDetailModal(activeModalCamera);
renderCameraZones(); renderCameraZones();