Get a callback to fire on click.
This commit is contained in:
parent
ac6cd878af
commit
5f54cfa6ed
2 changed files with 113 additions and 93 deletions
|
|
@ -1,3 +1,19 @@
|
|||
<style scoped>
|
||||
.report-card {
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.report-card:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.report-card.active {
|
||||
background-color: #0d6efd;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div class="col-md-3 border-end p-0 reports-list">
|
||||
<div class="p-3 bg-light border-bottom">
|
||||
|
|
@ -49,7 +65,7 @@
|
|||
:class="{
|
||||
active: selectedCommunication && selectedCommunication.id === comm.id,
|
||||
}"
|
||||
@click="selectCommunication(comm)"
|
||||
@click="handleClick(comm.id)"
|
||||
>
|
||||
<!-- First row: icon, type badge, and time -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
|
|
@ -118,16 +134,38 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref } from "vue";
|
||||
import TimeRelative from "../components/TimeRelative.vue";
|
||||
import { Communication } from "../types";
|
||||
|
||||
interface Props {
|
||||
all: string[] | null;
|
||||
all: Communication[] | null;
|
||||
loading: boolean;
|
||||
selectedId?: string | null;
|
||||
}
|
||||
interface Emits {
|
||||
(e: "select", id: string): void;
|
||||
}
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
selectedIndex: null,
|
||||
});
|
||||
|
||||
const emit = defineEmits<Emits>();
|
||||
const handleClick = (id: string) => {
|
||||
emit("select", id);
|
||||
};
|
||||
const searchFilter = ref("");
|
||||
const typeFilter = ref("all");
|
||||
|
||||
function selectCommunication(communication: Communication) {
|
||||
// Emit both events - one for general use, one for v-model
|
||||
console.log("selected", communication);
|
||||
emit("select-item", communication);
|
||||
emit("update:selectedItem", communication);
|
||||
//selectedCommunication.value = comm;
|
||||
//messageText.value = "";
|
||||
//updateMap();
|
||||
}
|
||||
|
||||
// Computed properties
|
||||
const filteredCommunications = computed(() => {
|
||||
if (props.all == null) {
|
||||
|
|
@ -148,6 +186,6 @@ function formatAddress(a) {
|
|||
if (a.number === "" && a.street === "") {
|
||||
return "no address provided";
|
||||
}
|
||||
return `$${a.number} $${a.street}, ${a.locality}`;
|
||||
return `${a.number} ${a.street}, ${a.locality}`;
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,75 @@
|
|||
<style scoped>
|
||||
/* Add your component-specific styles here */
|
||||
.reports-list {
|
||||
overflow-y: auto;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.map-container {
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.photo-thumbnail {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
object-fit: cover;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.photo-thumbnail:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.details-section {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.actions-panel {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.badge-larvae {
|
||||
background-color: #ffc107;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.badge-pupae {
|
||||
background-color: #fd7e14;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.badge-adult {
|
||||
background-color: #dc3545;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.icon-standing-water {
|
||||
color: #0dcaf0;
|
||||
}
|
||||
|
||||
.icon-nuisance {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.modal.show {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="h-100">
|
||||
<div class="container-fluid h-100">
|
||||
<div class="row h-100">
|
||||
<!-- Left Column - Communications List -->
|
||||
<CommunicationColumnList :all="communication.all" :loading="loading" />
|
||||
<CommunicationColumnList
|
||||
:all="communication.all"
|
||||
:loading="loading"
|
||||
:selected-id="selectedId"
|
||||
@select="handleSelect"
|
||||
/>
|
||||
|
||||
<!-- Middle Column - Report Details -->
|
||||
<div class="col-md-6 p-0">
|
||||
|
|
@ -672,6 +738,7 @@ const apiBase = ref("/api");
|
|||
const selectedCommunication = ref(null);
|
||||
const messageText = ref("");
|
||||
const showPhotoModal = ref(false);
|
||||
const selectedId = ref<string | null>(null);
|
||||
const currentPhotoIndex = ref(0);
|
||||
const showToast = ref(false);
|
||||
const toastTitle = ref("");
|
||||
|
|
@ -688,6 +755,9 @@ const water = computed(() => {
|
|||
return selectedCommunication.value?.public_report?.water || null;
|
||||
});
|
||||
|
||||
const handleSelect = (id: string) => {
|
||||
selectedId.value = id;
|
||||
};
|
||||
async function fetchCommunications() {
|
||||
await communication.fetchAll();
|
||||
// if we already had something selected, reset it using the new data
|
||||
|
|
@ -700,12 +770,6 @@ async function fetchCommunications() {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Methods
|
||||
function filterMatches(filter, comm) {
|
||||
// Implement your filter logic here
|
||||
return true;
|
||||
}
|
||||
|
||||
function formatAddress(a) {
|
||||
if (a.number === "" && a.street === "") {
|
||||
return "no address provided";
|
||||
|
|
@ -746,12 +810,6 @@ async function loadFromAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
function selectCommunication(comm) {
|
||||
selectedCommunication.value = comm;
|
||||
messageText.value = "";
|
||||
updateMap();
|
||||
}
|
||||
|
||||
function openPhotoViewer(index) {
|
||||
currentPhotoIndex.value = index;
|
||||
showPhotoModal.value = true;
|
||||
|
|
@ -961,79 +1019,3 @@ onMounted(async () => {
|
|||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Add your component-specific styles here */
|
||||
.reports-list {
|
||||
overflow-y: auto;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.report-card {
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.report-card:hover {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.report-card.active {
|
||||
background-color: #0d6efd;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.map-container {
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.photo-thumbnail {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
object-fit: cover;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.photo-thumbnail:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.details-section {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.actions-panel {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.badge-larvae {
|
||||
background-color: #ffc107;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.badge-pupae {
|
||||
background-color: #fd7e14;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.badge-adult {
|
||||
background-color: #dc3545;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.icon-standing-water {
|
||||
color: #0dcaf0;
|
||||
}
|
||||
|
||||
.icon-nuisance {
|
||||
color: #dc3545;
|
||||
}
|
||||
|
||||
.modal.show {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue