feat: implement citizen report creation, detail view, and chat system
- Create report creation page with step-by-step media uploads and categories loading - Create report details view page with history events log and messaging section - Implement MessageComposer and MessageList components for chat workflow - Implement MediaUploader with drag-and-drop support, file type, and size validation - Implement Pagination component with dynamic buttons and ellipsis support - Implement user profile settings summary page and notifications listing page
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
<script setup lang="ts">
|
||||
import type { Message } from '~/types/api'
|
||||
|
||||
interface Props {
|
||||
messages: Message[]
|
||||
isLoading?: boolean
|
||||
}
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
isLoading: false
|
||||
})
|
||||
|
||||
const formatDate = (dateString: string): string => {
|
||||
const date = new Date(dateString)
|
||||
const today = new Date()
|
||||
const yesterday = new Date(today)
|
||||
yesterday.setDate(yesterday.getDate() - 1)
|
||||
|
||||
if (date.toDateString() === today.toDateString()) {
|
||||
return date.toLocaleTimeString('it-IT', { hour: '2-digit', minute: '2-digit' })
|
||||
} else if (date.toDateString() === yesterday.toDateString()) {
|
||||
return 'Ieri'
|
||||
} else {
|
||||
return date.toLocaleDateString('it-IT', { day: '2-digit', month: '2-digit', year: '2-digit' })
|
||||
}
|
||||
}
|
||||
|
||||
const auth = useAuth()
|
||||
|
||||
const isCurrentUser = (userId: number): boolean => auth.user.value?.id === userId
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="message-list">
|
||||
<div v-if="isLoading" class="text-center py-5">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Caricamento...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="messages.length === 0" class="alert alert-info text-center" role="alert">
|
||||
Nessun messaggio disponibile. Sii il primo a scrivere!
|
||||
</div>
|
||||
|
||||
<div v-else class="messages-container">
|
||||
<div v-for="msg in messages" :key="msg.id" class="message-bubble mb-3">
|
||||
<div
|
||||
class="message-bubble-content p-3 rounded-3"
|
||||
:class="{
|
||||
'bg-primary text-white': isCurrentUser(msg.user_id),
|
||||
'bg-light border': !isCurrentUser(msg.user_id)
|
||||
}"
|
||||
>
|
||||
<!-- Nome mittente (solo per messaggi non miei) -->
|
||||
<div v-if="!isCurrentUser(msg.user_id)" class="small font-weight-bold mb-2 text-primary">
|
||||
{{ msg.first_name }} {{ msg.last_name }}
|
||||
</div>
|
||||
|
||||
<!-- Corpo messaggio -->
|
||||
<div class="message-body" :class="{ 'text-break': true }">
|
||||
{{ msg.body }}
|
||||
</div>
|
||||
|
||||
<!-- Timestamp -->
|
||||
<div class="small mt-2" :class="{ 'text-white-50': isCurrentUser(msg.user_id), 'text-muted': !isCurrentUser(msg.user_id) }">
|
||||
{{ formatDate(msg.created_at) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.message-list {
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
padding: 1rem;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 0.5rem;
|
||||
border: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.messages-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.message-bubble {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.message-bubble-content {
|
||||
max-width: 75%;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.message-body {
|
||||
white-space: pre-wrap;
|
||||
line-height: 1.4;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user