Harmonize style between comms and planning panes
This commit is contained in:
parent
b152cf9c36
commit
6797dfa251
5 changed files with 548 additions and 507 deletions
|
|
@ -5,133 +5,136 @@
|
|||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="border-start p-0">
|
||||
<div v-if="loading" class="loading">Loading...</div>
|
||||
<div v-else>
|
||||
<div
|
||||
v-if="!selectedCommunication"
|
||||
class="h-100 d-flex flex-column align-items-center justify-content-center text-muted p-3"
|
||||
>
|
||||
<i class="bi bi-gear fs-1"></i>
|
||||
<p class="mt-2 text-center">
|
||||
Actions will appear here when a report is selected
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="selectedCommunication"
|
||||
class="actions-panel d-flex flex-column"
|
||||
>
|
||||
<div class="p-3 bg-light border-bottom">
|
||||
<h6 class="mb-0"><i class="bi bi-lightning"></i> Quick Actions</h6>
|
||||
<div class="card shadow-sm h-100">
|
||||
<div class="card-header bg-light pane-header">Actions</div>
|
||||
<div class="card-body scroll-pane">
|
||||
<div v-if="loading" class="loading">Loading...</div>
|
||||
<div v-else>
|
||||
<div
|
||||
v-if="!selectedCommunication"
|
||||
class="h-100 d-flex flex-column align-items-center justify-content-center text-muted p-3"
|
||||
>
|
||||
<i class="bi bi-gear fs-1"></i>
|
||||
<p class="mt-2 text-center">
|
||||
Actions will appear here when a report is selected
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="p-3 flex-grow-1">
|
||||
<!-- Create Signal -->
|
||||
<div class="d-grid mb-3">
|
||||
<button class="btn btn-success btn-lg" @click="markSignal()">
|
||||
<i class="bi bi-plus-circle me-2"></i>Mark Signal
|
||||
</button>
|
||||
<small class="text-muted mt-1">This report is useful signal</small>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedCommunication"
|
||||
class="actions-panel d-flex flex-column"
|
||||
>
|
||||
<div class="p-3 flex-grow-1">
|
||||
<!-- Create Signal -->
|
||||
<div class="d-grid mb-3">
|
||||
<button class="btn btn-success btn-lg" @click="markSignal()">
|
||||
<i class="bi bi-plus-circle me-2"></i>Mark Signal
|
||||
</button>
|
||||
<small class="text-muted mt-1"
|
||||
>This report is useful signal</small
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Mark Invalid -->
|
||||
<div class="d-grid mb-3">
|
||||
<button class="btn btn-outline-danger" @click="markInvalid()">
|
||||
<i class="bi bi-x-circle me-2"></i>Mark Invalid
|
||||
</button>
|
||||
<small class="text-muted mt-1">This report isn't useful</small>
|
||||
</div>
|
||||
<!-- Mark Invalid -->
|
||||
<div class="d-grid mb-3">
|
||||
<button class="btn btn-outline-danger" @click="markInvalid()">
|
||||
<i class="bi bi-x-circle me-2"></i>Mark Invalid
|
||||
</button>
|
||||
<small class="text-muted mt-1">This report isn't useful</small>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<hr />
|
||||
|
||||
<!-- Message Reporter -->
|
||||
<div
|
||||
v-if="
|
||||
!(
|
||||
<!-- Message Reporter -->
|
||||
<div
|
||||
v-if="
|
||||
!(
|
||||
selectedCommunication?.public_report.reporter.has_email ||
|
||||
selectedCommunication?.public_report.reporter.has_phone
|
||||
)
|
||||
"
|
||||
class="mb-3"
|
||||
>
|
||||
<h6>
|
||||
<i class="bi bi-chat-dots"></i> No Reporter Communications
|
||||
Available
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
selectedCommunication?.public_report.reporter.has_email ||
|
||||
selectedCommunication?.public_report.reporter.has_phone
|
||||
)
|
||||
"
|
||||
class="mb-3"
|
||||
>
|
||||
<h6>
|
||||
<i class="bi bi-chat-dots"></i> No Reporter Communications
|
||||
Available
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
selectedCommunication?.public_report.reporter.has_email ||
|
||||
selectedCommunication?.public_report.reporter.has_phone
|
||||
"
|
||||
class="mb-3"
|
||||
>
|
||||
<h6><i class="bi bi-chat-dots"></i> Message Reporter</h6>
|
||||
<div class="mb-2">
|
||||
<label class="form-label small text-muted">Quick Templates</label>
|
||||
<select
|
||||
class="form-select form-select-sm"
|
||||
@change="applyMessageTemplate($event.target.value)"
|
||||
>
|
||||
<option value="">Select a template...</option>
|
||||
<option value="received">Report Received</option>
|
||||
<option value="scheduled">Service Scheduled</option>
|
||||
<option value="completed">Service Completed</option>
|
||||
<option value="need_info">Need More Information</option>
|
||||
</select>
|
||||
</div>
|
||||
<textarea
|
||||
class="form-control mb-2"
|
||||
rows="5"
|
||||
v-model="messageText"
|
||||
placeholder="Type your message to the reporter..."
|
||||
></textarea>
|
||||
<div class="d-grid">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
@click="sendMessage()"
|
||||
:disabled="!messageText.trim()"
|
||||
>
|
||||
<i class="bi bi-send me-2"></i>Send Message
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<!-- Report History -->
|
||||
<div>
|
||||
<h6><i class="bi bi-clock-history"></i> Activity Log</h6>
|
||||
<div class="small">
|
||||
<div
|
||||
v-for="entry in selectedCommunication.public_report.log || []"
|
||||
:key="entry.created"
|
||||
class="border-start border-2 ps-2 mb-2"
|
||||
>
|
||||
<div v-if="entry.type === 'created'">
|
||||
<div class="text-muted">Initial Report</div>
|
||||
<small class="text-muted">{{
|
||||
formatDate(entry.created)
|
||||
}}</small>
|
||||
</div>
|
||||
<div v-else-if="entry.type === 'message-text'">
|
||||
<div class="text-muted">Text Message</div>
|
||||
<div>{{ entry.message }}</div>
|
||||
<small class="text-muted">{{
|
||||
formatDate(entry.created)
|
||||
}}</small>
|
||||
</div>
|
||||
<div v-else>{{ entry.type }}</div>
|
||||
"
|
||||
class="mb-3"
|
||||
>
|
||||
<h6><i class="bi bi-chat-dots"></i> Message Reporter</h6>
|
||||
<div class="mb-2">
|
||||
<label class="form-label small text-muted"
|
||||
>Quick Templates</label
|
||||
>
|
||||
<select
|
||||
class="form-select form-select-sm"
|
||||
@change="applyMessageTemplate($event.target.value)"
|
||||
>
|
||||
<option value="">Select a template...</option>
|
||||
<option value="received">Report Received</option>
|
||||
<option value="scheduled">Service Scheduled</option>
|
||||
<option value="completed">Service Completed</option>
|
||||
<option value="need_info">Need More Information</option>
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
!selectedCommunication.public_report.log ||
|
||||
selectedCommunication.public_report.log.length === 0
|
||||
"
|
||||
class="text-muted"
|
||||
>
|
||||
No activity yet
|
||||
<textarea
|
||||
class="form-control mb-2"
|
||||
rows="5"
|
||||
v-model="messageText"
|
||||
placeholder="Type your message to the reporter..."
|
||||
></textarea>
|
||||
<div class="d-grid">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
@click="sendMessage()"
|
||||
:disabled="!messageText.trim()"
|
||||
>
|
||||
<i class="bi bi-send me-2"></i>Send Message
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<!-- Report History -->
|
||||
<div>
|
||||
<h6><i class="bi bi-clock-history"></i> Activity Log</h6>
|
||||
<div class="small">
|
||||
<div
|
||||
v-for="entry in selectedCommunication.public_report.log || []"
|
||||
:key="entry.created"
|
||||
class="border-start border-2 ps-2 mb-2"
|
||||
>
|
||||
<div v-if="entry.type === 'created'">
|
||||
<div class="text-muted">Initial Report</div>
|
||||
<small class="text-muted">{{
|
||||
formatDate(entry.created)
|
||||
}}</small>
|
||||
</div>
|
||||
<div v-else-if="entry.type === 'message-text'">
|
||||
<div class="text-muted">Text Message</div>
|
||||
<div>{{ entry.message }}</div>
|
||||
<small class="text-muted">{{
|
||||
formatDate(entry.created)
|
||||
}}</small>
|
||||
</div>
|
||||
<div v-else>{{ entry.type }}</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
!selectedCommunication.public_report.log ||
|
||||
selectedCommunication.public_report.log.length === 0
|
||||
"
|
||||
class="text-muted"
|
||||
>
|
||||
No activity yet
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -41,336 +41,359 @@
|
|||
</style>
|
||||
|
||||
<template>
|
||||
<div class="p-3">
|
||||
<div class="map-container">
|
||||
<MapMultipoint
|
||||
id="map"
|
||||
ref="mapRef"
|
||||
:organization-id="user.organization.id"
|
||||
:tegola="user.urls.tegola"
|
||||
:xmin="user.organization.service_area?.min.x ?? 0"
|
||||
:ymin="user.organization.service_area?.min.y ?? 0"
|
||||
:xmax="user.organization.service_area?.max.x ?? 0"
|
||||
:ymax="user.organization.service_area?.max.y ?? 0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="loading" class="loading">Loading...</div>
|
||||
<div v-else>
|
||||
<div
|
||||
v-if="!selectedCommunication"
|
||||
class="d-flex flex-column align-items-center justify-content-center text-muted"
|
||||
>
|
||||
<i class="bi bi-hand-index fs-1"></i>
|
||||
<p class="mt-2">Select a report to view details</p>
|
||||
</div>
|
||||
|
||||
<div v-if="selectedCommunication" class="h-100 d-flex flex-column">
|
||||
<!-- Report Details -->
|
||||
<div class="details-section p-3 border-top">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div>
|
||||
<h5 class="mb-1">
|
||||
<span
|
||||
v-if="selectedCommunication.type === 'publicreport.nuisance'"
|
||||
>
|
||||
<i class="bi bi-mosquito icon-nuisance"></i>
|
||||
Nuisance Report
|
||||
</span>
|
||||
<span v-if="selectedCommunication.type === 'publicreport.water'">
|
||||
<i class="bi bi-droplet-fill icon-standing-water"></i>
|
||||
Standing Water Report
|
||||
</span>
|
||||
</h5>
|
||||
<small class="text-muted"
|
||||
>Report ID: #{{ selectedCommunication.id }}</small
|
||||
>
|
||||
</div>
|
||||
<span class="badge bg-secondary">
|
||||
<TimeRelative :time="selectedCommunication.created" />
|
||||
</span>
|
||||
<div class="card shadow-sm mb-3">
|
||||
<div class="card-header bg-white pane-header">Communication Workbench</div>
|
||||
<div class="card-body">
|
||||
<div class="map-container">
|
||||
<MapMultipoint
|
||||
id="map"
|
||||
ref="mapRef"
|
||||
:organization-id="user.organization.id"
|
||||
:tegola="user.urls.tegola"
|
||||
:xmin="user.organization.service_area?.min.x ?? 0"
|
||||
:ymin="user.organization.service_area?.min.y ?? 0"
|
||||
:xmax="user.organization.service_area?.max.x ?? 0"
|
||||
:ymax="user.organization.service_area?.max.y ?? 0"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="loading" class="loading">Loading...</div>
|
||||
<div v-else>
|
||||
<div
|
||||
v-if="!selectedCommunication"
|
||||
class="d-flex flex-column align-items-center justify-content-center text-muted"
|
||||
>
|
||||
<i class="bi bi-hand-index fs-1"></i>
|
||||
<p class="mt-2">Select a report to view details</p>
|
||||
</div>
|
||||
|
||||
<!-- Common Fields -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-geo-alt"></i> Address
|
||||
</label>
|
||||
<div class="fw-medium">
|
||||
{{
|
||||
formatAddress(selectedCommunication.public_report.address)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-person"></i> Reporter Name
|
||||
</label>
|
||||
<div class="fw-medium">
|
||||
{{
|
||||
selectedCommunication.public_report.reporter.name ||
|
||||
"not given"
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label
|
||||
v-if="selectedCommunication.public_report.reporter.has_email"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-envelope"></i>
|
||||
</label>
|
||||
<label
|
||||
v-if="selectedCommunication.public_report.reporter.has_phone"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-phone"></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="water" class="row g-3">
|
||||
<div class="col-12">
|
||||
<ul>
|
||||
<li v-if="water?.is_reporter_owner">
|
||||
Reporter is the owner of the property
|
||||
</li>
|
||||
<li v-if="water?.is_reporter_confidential">
|
||||
Reporter has asked to be kept confidential
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Nuisance-specific Fields -->
|
||||
<div v-if="nuisance" class="card mb-3">
|
||||
<div class="card-header bg-danger bg-opacity-10">
|
||||
<i class="bi bi-exclamation-triangle"></i> Nuisance Details
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-clock"></i> Time of Day Encountered
|
||||
</label>
|
||||
<ul>
|
||||
<li v-if="nuisance?.time_of_day_early">Early</li>
|
||||
<li v-if="nuisance?.time_of_day_day">Daytime</li>
|
||||
<li v-if="nuisance?.time_of_day_evening">Evening</li>
|
||||
<li v-if="nuisance?.time_of_day_night">Night</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-house"></i> Property Area
|
||||
</label>
|
||||
<div>
|
||||
<ul>
|
||||
<li v-if="nuisance?.is_location_backyard">Backyard</li>
|
||||
<li v-if="nuisance?.is_location_frontyard">Frontyard</li>
|
||||
<li v-if="nuisance?.is_location_garden">Garden</li>
|
||||
<li v-if="nuisance?.is_location_other">Other</li>
|
||||
<li v-if="nuisance?.is_location_pool">Pool</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
nuisance?.source_container ||
|
||||
nuisance?.source_gutter ||
|
||||
nuisance?.source_stagnant
|
||||
"
|
||||
class="col-md-6"
|
||||
>
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-droplet"></i> Sources
|
||||
</label>
|
||||
<ul>
|
||||
<li v-if="nuisance?.source_container">Container</li>
|
||||
<li v-if="nuisance?.source_gutter">Gutter</li>
|
||||
<li v-if="nuisance?.source_stagnant">Sprinklers & Gutters</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="nuisance?.source_description" class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-chat-text"></i> Source Description
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ nuisance?.source_description || "none" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label text-mudet small mb-0">
|
||||
<i class="bi bi-clock"></i> Duration
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ nuisance?.duration }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-chat-text"></i> Additional Notes
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ nuisance?.additional_info || "No additional notes" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Standing Water-specific Fields -->
|
||||
<div v-if="water" class="card mb-3">
|
||||
<div class="card-header bg-info bg-opacity-10">
|
||||
<i class="bi bi-droplet"></i> Standing Water Details
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div
|
||||
v-if="
|
||||
water?.access_gate ||
|
||||
water?.access_fence ||
|
||||
water?.access_locked ||
|
||||
water?.access_dog ||
|
||||
water?.access_other
|
||||
"
|
||||
class="col-md-6"
|
||||
>
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-droplet"></i> Access
|
||||
</label>
|
||||
<div v-if="selectedCommunication" class="h-100 d-flex flex-column">
|
||||
<!-- Report Details -->
|
||||
<div class="details-section p-3 border-top">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div>
|
||||
<ul>
|
||||
<li v-if="water?.access_gate">Gate</li>
|
||||
<li v-if="water?.access_fence">Fence</li>
|
||||
<li v-if="water?.access_locked">Locked</li>
|
||||
<li v-if="water?.access_dog">Dog</li>
|
||||
<li v-if="water?.access_other">Other access obstacle</li>
|
||||
</ul>
|
||||
<h5 class="mb-1">
|
||||
<span
|
||||
v-if="
|
||||
selectedCommunication.type === 'publicreport.nuisance'
|
||||
"
|
||||
>
|
||||
<i class="bi bi-mosquito icon-nuisance"></i>
|
||||
Nuisance Report
|
||||
</span>
|
||||
<span
|
||||
v-if="selectedCommunication.type === 'publicreport.water'"
|
||||
>
|
||||
<i class="bi bi-droplet-fill icon-standing-water"></i>
|
||||
Standing Water Report
|
||||
</span>
|
||||
</h5>
|
||||
<small class="text-muted"
|
||||
>Report ID: #{{ selectedCommunication.id }}</small
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="water?.access_comments" class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-chat-text"></i> Access Comments
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ water?.access_comments }}
|
||||
</div>
|
||||
</div>
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-eye"></i> Mosquito Life Stages Observed
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<span
|
||||
class="badge me-2"
|
||||
:class="
|
||||
water?.has_larvae ? 'badge-larvae' : 'bg-light text-muted'
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="bi"
|
||||
:class="water?.has_larvae ? 'bi-check-circle' : 'bi-circle'"
|
||||
></i>
|
||||
Larvae
|
||||
</span>
|
||||
<span
|
||||
class="badge me-2"
|
||||
:class="
|
||||
water?.has_pupae ? 'badge-pupae' : 'bg-light text-muted'
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="bi"
|
||||
:class="water?.has_pupae ? 'bi-check-circle' : 'bi-circle'"
|
||||
></i>
|
||||
Pupae
|
||||
</span>
|
||||
<span
|
||||
class="badge"
|
||||
:class="
|
||||
water?.has_adult ? 'badge-adult' : 'bg-light text-muted'
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="bi"
|
||||
:class="water?.has_adult ? 'bi-check-circle' : 'bi-circle'"
|
||||
></i>
|
||||
Adult Mosquitoes
|
||||
<span class="badge bg-secondary">
|
||||
<TimeRelative :time="selectedCommunication.created" />
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="water?.comments" class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-chat-text"></i> Comments
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ water?.comments }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-person"></i> Owner Name
|
||||
</label>
|
||||
<div class="fw-medium">
|
||||
{{ water?.owner.name || "not given" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label
|
||||
v-if="water?.owner.has_email"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-envelope"></i>
|
||||
</label>
|
||||
<label
|
||||
v-if="water?.owner.has_phone"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-phone"></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Images Section -->
|
||||
<div class="card">
|
||||
<div
|
||||
class="card-header d-flex justify-content-between align-items-center"
|
||||
>
|
||||
<span><i class="bi bi-images"></i> Attached Photos</span>
|
||||
<span class="badge bg-primary">
|
||||
{{ selectedCommunication.public_report.images?.length || 0 }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div
|
||||
v-if="
|
||||
selectedCommunication.public_report.images &&
|
||||
selectedCommunication.public_report.images.length > 0
|
||||
"
|
||||
class="d-flex flex-wrap gap-2"
|
||||
>
|
||||
<img
|
||||
v-for="(photo, index) in selectedCommunication.public_report
|
||||
.images"
|
||||
:key="index"
|
||||
:src="photo.url_content"
|
||||
class="photo-thumbnail"
|
||||
@click="openPhotoViewer(index)"
|
||||
:alt="'Photo ' + (index + 1)"
|
||||
/>
|
||||
<!-- Common Fields -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-geo-alt"></i> Address
|
||||
</label>
|
||||
<div class="fw-medium">
|
||||
{{
|
||||
formatAddress(
|
||||
selectedCommunication.public_report.address,
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-person"></i> Reporter Name
|
||||
</label>
|
||||
<div class="fw-medium">
|
||||
{{
|
||||
selectedCommunication.public_report.reporter.name ||
|
||||
"not given"
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label
|
||||
v-if="
|
||||
selectedCommunication.public_report.reporter.has_email
|
||||
"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-envelope"></i>
|
||||
</label>
|
||||
<label
|
||||
v-if="
|
||||
selectedCommunication.public_report.reporter.has_phone
|
||||
"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-phone"></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="water" class="row g-3">
|
||||
<div class="col-12">
|
||||
<ul>
|
||||
<li v-if="water?.is_reporter_owner">
|
||||
Reporter is the owner of the property
|
||||
</li>
|
||||
<li v-if="water?.is_reporter_confidential">
|
||||
Reporter has asked to be kept confidential
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
!selectedCommunication.public_report.images ||
|
||||
selectedCommunication.public_report.images.length === 0
|
||||
"
|
||||
class="text-muted text-center py-3"
|
||||
>
|
||||
<i class="bi bi-camera-slash fs-4"></i>
|
||||
<p class="mb-0 small">No images attached</p>
|
||||
|
||||
<!-- Nuisance-specific Fields -->
|
||||
<div v-if="nuisance" class="card mb-3">
|
||||
<div class="card-header bg-danger bg-opacity-10">
|
||||
<i class="bi bi-exclamation-triangle"></i> Nuisance Details
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-clock"></i> Time of Day Encountered
|
||||
</label>
|
||||
<ul>
|
||||
<li v-if="nuisance?.time_of_day_early">Early</li>
|
||||
<li v-if="nuisance?.time_of_day_day">Daytime</li>
|
||||
<li v-if="nuisance?.time_of_day_evening">Evening</li>
|
||||
<li v-if="nuisance?.time_of_day_night">Night</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-house"></i> Property Area
|
||||
</label>
|
||||
<div>
|
||||
<ul>
|
||||
<li v-if="nuisance?.is_location_backyard">Backyard</li>
|
||||
<li v-if="nuisance?.is_location_frontyard">
|
||||
Frontyard
|
||||
</li>
|
||||
<li v-if="nuisance?.is_location_garden">Garden</li>
|
||||
<li v-if="nuisance?.is_location_other">Other</li>
|
||||
<li v-if="nuisance?.is_location_pool">Pool</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
nuisance?.source_container ||
|
||||
nuisance?.source_gutter ||
|
||||
nuisance?.source_stagnant
|
||||
"
|
||||
class="col-md-6"
|
||||
>
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-droplet"></i> Sources
|
||||
</label>
|
||||
<ul>
|
||||
<li v-if="nuisance?.source_container">Container</li>
|
||||
<li v-if="nuisance?.source_gutter">Gutter</li>
|
||||
<li v-if="nuisance?.source_stagnant">
|
||||
Sprinklers & Gutters
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="nuisance?.source_description" class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-chat-text"></i> Source Description
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ nuisance?.source_description || "none" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label text-mudet small mb-0">
|
||||
<i class="bi bi-clock"></i> Duration
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ nuisance?.duration }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-chat-text"></i> Additional Notes
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ nuisance?.additional_info || "No additional notes" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Standing Water-specific Fields -->
|
||||
<div v-if="water" class="card mb-3">
|
||||
<div class="card-header bg-info bg-opacity-10">
|
||||
<i class="bi bi-droplet"></i> Standing Water Details
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div
|
||||
v-if="
|
||||
water?.access_gate ||
|
||||
water?.access_fence ||
|
||||
water?.access_locked ||
|
||||
water?.access_dog ||
|
||||
water?.access_other
|
||||
"
|
||||
class="col-md-6"
|
||||
>
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-droplet"></i> Access
|
||||
</label>
|
||||
<div>
|
||||
<ul>
|
||||
<li v-if="water?.access_gate">Gate</li>
|
||||
<li v-if="water?.access_fence">Fence</li>
|
||||
<li v-if="water?.access_locked">Locked</li>
|
||||
<li v-if="water?.access_dog">Dog</li>
|
||||
<li v-if="water?.access_other">Other access obstacle</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="water?.access_comments" class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-chat-text"></i> Access Comments
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ water?.access_comments }}
|
||||
</div>
|
||||
</div>
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-eye"></i> Mosquito Life Stages Observed
|
||||
</label>
|
||||
<div class="mt-2">
|
||||
<span
|
||||
class="badge me-2"
|
||||
:class="
|
||||
water?.has_larvae ? 'badge-larvae' : 'bg-light text-muted'
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="bi"
|
||||
:class="
|
||||
water?.has_larvae ? 'bi-check-circle' : 'bi-circle'
|
||||
"
|
||||
></i>
|
||||
Larvae
|
||||
</span>
|
||||
<span
|
||||
class="badge me-2"
|
||||
:class="
|
||||
water?.has_pupae ? 'badge-pupae' : 'bg-light text-muted'
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="bi"
|
||||
:class="
|
||||
water?.has_pupae ? 'bi-check-circle' : 'bi-circle'
|
||||
"
|
||||
></i>
|
||||
Pupae
|
||||
</span>
|
||||
<span
|
||||
class="badge"
|
||||
:class="
|
||||
water?.has_adult ? 'badge-adult' : 'bg-light text-muted'
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="bi"
|
||||
:class="
|
||||
water?.has_adult ? 'bi-check-circle' : 'bi-circle'
|
||||
"
|
||||
></i>
|
||||
Adult Mosquitoes
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="water?.comments" class="col-12">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-chat-text"></i> Comments
|
||||
</label>
|
||||
<div class="p-2 bg-light rounded">
|
||||
{{ water?.comments }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label text-muted small mb-0">
|
||||
<i class="bi bi-person"></i> Owner Name
|
||||
</label>
|
||||
<div class="fw-medium">
|
||||
{{ water?.owner.name || "not given" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label
|
||||
v-if="water?.owner.has_email"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-envelope"></i>
|
||||
</label>
|
||||
<label
|
||||
v-if="water?.owner.has_phone"
|
||||
class="form-label text-muted small mb-0"
|
||||
>
|
||||
<i class="bi bi-phone"></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Images Section -->
|
||||
<div class="card">
|
||||
<div
|
||||
class="card-header d-flex justify-content-between align-items-center"
|
||||
>
|
||||
<span><i class="bi bi-images"></i> Attached Photos</span>
|
||||
<span class="badge bg-primary">
|
||||
{{ selectedCommunication.public_report.images?.length || 0 }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div
|
||||
v-if="
|
||||
selectedCommunication.public_report.images &&
|
||||
selectedCommunication.public_report.images.length > 0
|
||||
"
|
||||
class="d-flex flex-wrap gap-2"
|
||||
>
|
||||
<img
|
||||
v-for="(photo, index) in selectedCommunication.public_report
|
||||
.images"
|
||||
:key="index"
|
||||
:src="photo.url_content"
|
||||
class="photo-thumbnail"
|
||||
@click="openPhotoViewer(index)"
|
||||
:alt="'Photo ' + (index + 1)"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
!selectedCommunication.public_report.images ||
|
||||
selectedCommunication.public_report.images.length === 0
|
||||
"
|
||||
class="text-muted text-center py-3"
|
||||
>
|
||||
<i class="bi bi-camera-slash fs-4"></i>
|
||||
<p class="mb-0 small">No images attached</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@
|
|||
</style>
|
||||
|
||||
<template>
|
||||
<div class="border-end p-0 reports-list">
|
||||
<div class="p-3 bg-light border-bottom">
|
||||
<div class="card shadow-sm h-100 reports-list">
|
||||
<div class="card-header bg-light pane-header">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text"><i class="bi bi-search"></i></span>
|
||||
<input
|
||||
|
|
@ -30,7 +30,9 @@
|
|||
v-model="searchFilter"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-2 d-flex gap-2">
|
||||
</div>
|
||||
<div class="card-body scroll-pane">
|
||||
<div class="mb-3">
|
||||
<button
|
||||
class="btn btn-sm"
|
||||
:class="
|
||||
|
|
@ -47,7 +49,7 @@
|
|||
"
|
||||
@click="typeFilter = 'nuisance'"
|
||||
>
|
||||
<i class="bi bi-mosquito"></i>Mosquito Nuisance
|
||||
<i class="bi bi-mosquito"></i>Nuisance
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm"
|
||||
|
|
@ -57,70 +59,73 @@
|
|||
<i class="bi bi-droplet"></i> Water
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-group list-group-flush">
|
||||
<div v-if="loading" class="loading">Loading...</div>
|
||||
<div
|
||||
v-else-if="all.length > 0"
|
||||
v-for="comm in filteredCommunications"
|
||||
:key="comm.id"
|
||||
class="list-group-item report-card p-3"
|
||||
:class="{
|
||||
active: selectedId && selectedId === comm.id,
|
||||
}"
|
||||
@click="handleClick(comm.id)"
|
||||
>
|
||||
<!-- First row: icon, type badge, and time -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<div class="d-flex align-items-center">
|
||||
<i
|
||||
v-if="comm.type === 'publicreport.nuisance'"
|
||||
class="bi bi-mosquito icon-nuisance fs-4 me-2"
|
||||
>
|
||||
</i>
|
||||
<i
|
||||
v-if="comm.type === 'publicreport.water'"
|
||||
class="bi bi-droplet-fill icon-standing-water fs-4 me-2"
|
||||
></i>
|
||||
<span
|
||||
class="badge"
|
||||
:class="
|
||||
comm.type === 'publicreport.nuisance' ? 'bg-danger' : 'bg-info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
comm.type === "publicreport.nuisance"
|
||||
? "Nuisance"
|
||||
: "Standing Water"
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<small>
|
||||
<TimeRelative :time="comm.created" />
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Details section: full width -->
|
||||
<div>
|
||||
<div>
|
||||
<i class="bi bi-geo-alt text-muted"></i>
|
||||
<span class="fw-medium">{{
|
||||
comm.public_report.address.postal_code
|
||||
}}</span>
|
||||
</div>
|
||||
<small>{{ formatAddress(comm.public_report.address) }}</small>
|
||||
<div
|
||||
v-if="
|
||||
comm.public_report.images && comm.public_report.images.length > 0
|
||||
"
|
||||
class="mt-1"
|
||||
>
|
||||
<small class="text-muted">
|
||||
<i class="bi bi-camera"></i>
|
||||
{{ comm.public_report.images.length }} photo(s)
|
||||
<div class="list-group list-group-flush">
|
||||
<div v-if="loading" class="loading">Loading...</div>
|
||||
<div
|
||||
v-else-if="all.length > 0"
|
||||
v-for="comm in filteredCommunications"
|
||||
:key="comm.id"
|
||||
class="border rounded list-group-item report-card p-3"
|
||||
:class="{
|
||||
active: selectedId && selectedId === comm.id,
|
||||
}"
|
||||
@click="handleClick(comm.id)"
|
||||
>
|
||||
<!-- First row: icon, type badge, and time -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<div class="d-flex align-items-center">
|
||||
<i
|
||||
v-if="comm.type === 'publicreport.nuisance'"
|
||||
class="bi bi-mosquito icon-nuisance fs-4 me-2"
|
||||
>
|
||||
</i>
|
||||
<i
|
||||
v-if="comm.type === 'publicreport.water'"
|
||||
class="bi bi-droplet-fill icon-standing-water fs-4 me-2"
|
||||
></i>
|
||||
<span
|
||||
class="badge"
|
||||
:class="
|
||||
comm.type === 'publicreport.nuisance'
|
||||
? 'bg-danger'
|
||||
: 'bg-info'
|
||||
"
|
||||
>
|
||||
{{
|
||||
comm.type === "publicreport.nuisance"
|
||||
? "Nuisance"
|
||||
: "Standing Water"
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<small>
|
||||
<TimeRelative :time="comm.created" />
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- Details section: full width -->
|
||||
<div>
|
||||
<div>
|
||||
<i class="bi bi-geo-alt text-muted"></i>
|
||||
<span class="fw-medium">{{
|
||||
comm.public_report.address.postal_code
|
||||
}}</span>
|
||||
</div>
|
||||
<small>{{ formatAddress(comm.public_report.address) }}</small>
|
||||
<div
|
||||
v-if="
|
||||
comm.public_report.images &&
|
||||
comm.public_report.images.length > 0
|
||||
"
|
||||
class="mt-1"
|
||||
>
|
||||
<small class="text-muted">
|
||||
<i class="bi bi-camera"></i>
|
||||
{{ comm.public_report.images.length }} photo(s)
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
</style>
|
||||
<template>
|
||||
<div class="card shadow-sm h-100">
|
||||
<div class="card-header bg-white pane-header">Transformation Tools</div>
|
||||
<div class="card-header bg-light pane-header">Transformation Tools</div>
|
||||
<div class="card-body scroll-pane">
|
||||
<div class="mb-3">
|
||||
<div class="text-muted small mb-2">Signal → Lead</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue