fix: make log button directly open camera for photo proof and remove unverified test marks
This commit is contained in:
+4
-4
@@ -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
@@ -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
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user