mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 01:40:01 +00:00
Inspections: apply violations new-vs-old cue to the map + list
Match the violations changes on the Inspections map: add a green "New" badge for violations recorded in the last 7 days, both in the map pin popups and the unit list, so new vs old is distinguishable. (Newest-first ordering and auto-advance-to-next-stage on re-recording a property already existed here.) Also fixed a misleading stage fallback that showed "New" as a notice level. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -271,13 +271,20 @@ function InteractiveMap({ units, violationsByUnit, selectedUnit, onSelectUnit, o
|
||||
if (days >= 30) lastColor = "#dc3545";
|
||||
else if (days >= 14) lastColor = "#f59e0b";
|
||||
}
|
||||
// "New" badge for recently-recorded violations (last 7 days) — matches the
|
||||
// violations list, so new vs old is distinguishable on the map too.
|
||||
const createdDays = v.created_at ? Math.floor((Date.now() - new Date(v.created_at).getTime()) / 86400000) : 999;
|
||||
const newBadge = createdDays < 7
|
||||
? `<span style="font-size:9px;color:#047857;background:#d1fae5;border:1px solid #a7f3d0;border-radius:3px;padding:1px 5px;font-weight:700;white-space:nowrap">New</span>`
|
||||
: "";
|
||||
return `<div style="display:flex;align-items:center;gap:6px;padding:4px 0;font-size:12px;color:#343a40;border-bottom:1px solid #f0f0f0">
|
||||
<span>${getIconForCategory(v.category || v.violation_type || "")}</span>
|
||||
<span style="flex:1;display:flex;flex-direction:column;gap:1px">
|
||||
<span>${v.category || v.violation_type || v.title || "Violation"}</span>
|
||||
${lastLabel ? `<span style="font-size:9px;color:${lastColor};font-weight:600">${lastLabel}</span>` : ""}
|
||||
</span>
|
||||
<span style="font-size:9px;color:#6c757d;background:#f0f0f0;border-radius:3px;padding:1px 5px">${v.stage || v.notice_level || "New"}</span>
|
||||
${newBadge}
|
||||
<span style="font-size:9px;color:#6c757d;background:#f0f0f0;border-radius:3px;padding:1px 5px">${v.stage || v.notice_level || "First Notice"}</span>
|
||||
${escalateBtn}
|
||||
<button class="iw-resolve-btn" data-vid="${v.id}" style="background:#198754;color:white;border:none;border-radius:4px;padding:2px 8px;font-size:10px;font-weight:600;cursor:pointer;white-space:nowrap">✓ Resolve</button>
|
||||
</div>`;
|
||||
@@ -1023,6 +1030,7 @@ export default function InspectionsPage() {
|
||||
const viols = violsByUnit[u.id] || [];
|
||||
const open = viols.filter((v: any) => v.status === "open" || v.status === "Open" || v.status === "recommended_for_fining").length;
|
||||
const hasPhotos = viols.some((v: any) => v.photo_url || (Array.isArray(v.photo_urls) && v.photo_urls.length > 0));
|
||||
const hasNew = viols.some((v: any) => v.created_at && (Date.now() - new Date(v.created_at).getTime()) < 7 * 86400000);
|
||||
const sel = selectedUnit?.id === u.id;
|
||||
const isChecked = selectedUnitIds.includes(u.id);
|
||||
|
||||
@@ -1037,6 +1045,7 @@ export default function InspectionsPage() {
|
||||
<div className={`w-5 h-5 rounded-full flex items-center justify-center text-[9px] font-bold text-white shrink-0 ${open && hasPhotos ? "bg-amber-500" : open ? "bg-red-500" : "bg-blue-600"}`}>{i + 1}</div>
|
||||
<div className="text-[13px] font-bold text-slate-800 flex-1 truncate">{u.address || u.unit_number}</div>
|
||||
{hasPhotos && <Camera className="w-3.5 h-3.5 text-amber-500 shrink-0" />}
|
||||
{hasNew && <span className="text-[9px] font-bold text-emerald-700 bg-emerald-100 border border-emerald-200 rounded px-1.5 py-0.5 shrink-0">New</span>}
|
||||
{open > 0 && <InspBadge count={open} color={B.red} />}
|
||||
</div>
|
||||
{u.owner_name && <div className="text-[11px] text-slate-500 pl-7 truncate">{u.owner_name}</div>}
|
||||
|
||||
Reference in New Issue
Block a user