style(admin): improve moderation UI and catalog button alignment
Added dismissed card styling and reorganized error/empty state rendering in moderation. Added fixed width for catalog action buttons.
This commit is contained in:
@@ -444,3 +444,10 @@ const handleDeleteTeam = async () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.text-end .btn {
|
||||||
|
margin: 0 !important;
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ const dismissModal = reactive({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const { data: flagsRes, pending, refresh } = useAsyncData(
|
const { data: flagsRes, pending, refresh } = useAsyncData(
|
||||||
'admin-moderation-flags',
|
'admin-moderation-flags',
|
||||||
() => getModerationFlags({ page: page.value, per_page: perPage.value, status: statusFilter.value || undefined }),
|
() => getModerationFlags({ page: page.value, per_page: perPage.value, status: statusFilter.value || undefined }),
|
||||||
{ watch: [page, statusFilter] }
|
{ watch: [page, statusFilter] }
|
||||||
)
|
)
|
||||||
|
|
||||||
const openResolveModal = (id: number, rejectReport: boolean) => {
|
const openResolveModal = (id: number, rejectReport: boolean) => {
|
||||||
@@ -54,15 +54,14 @@ const handleResolve = async () => {
|
|||||||
actionError.value = ''
|
actionError.value = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await updateModerationFlag(resolveModal.flagId, {
|
await updateModerationFlag(resolveModal.flagId, {
|
||||||
status: 'RESOLVED',
|
status: 'RESOLVED',
|
||||||
reject_report: resolveModal.rejectReport,
|
reject_report: resolveModal.rejectReport,
|
||||||
resolution_note: resolveModal.note || undefined
|
resolution_note: resolveModal.note || undefined
|
||||||
})
|
})
|
||||||
if (res.ok) {
|
|
||||||
await refresh()
|
await refresh()
|
||||||
closeResolveModal()
|
closeResolveModal()
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to resolve flag', err)
|
console.error('Failed to resolve flag', err)
|
||||||
actionError.value = 'Errore durante la risoluzione della segnalazione.'
|
actionError.value = 'Errore durante la risoluzione della segnalazione.'
|
||||||
@@ -89,11 +88,10 @@ const handleDismiss = async () => {
|
|||||||
actionError.value = ''
|
actionError.value = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await updateModerationFlag(dismissModal.flagId, { status: 'DISMISSED' })
|
await updateModerationFlag(dismissModal.flagId, { status: 'DISMISSED' })
|
||||||
if (res.ok) {
|
|
||||||
await refresh()
|
await refresh()
|
||||||
closeDismissModal()
|
closeDismissModal()
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to dismiss flag', err)
|
console.error('Failed to dismiss flag', err)
|
||||||
actionError.value = 'Errore durante l\'aggiornamento.'
|
actionError.value = 'Errore durante l\'aggiornamento.'
|
||||||
@@ -129,21 +127,28 @@ const formatDate = (dateStr: string) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Spostato in modo che non interrompa l'if-else dei caricamenti -->
|
||||||
|
<div v-if="actionError" class="alert alert-danger mb-4">
|
||||||
|
{{ actionError }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="pending" class="text-center py-5">
|
<div v-if="pending" class="text-center py-5">
|
||||||
<div class="spinner-border text-danger" role="status"></div>
|
<div class="spinner-border text-danger" role="status"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="!flagsRes?.flags || flagsRes.flags.length === 0" class="alert alert-success">
|
<div v-else-if="!flagsRes || !flagsRes.flags || flagsRes.flags.length === 0" class="alert alert-success">
|
||||||
Nessun elemento da moderare al momento.
|
Nessun elemento da moderare al momento.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="actionError" class="alert alert-danger">
|
<!-- Questo v-else ora è scatenato in modo pulito solo quando i dati esistono davvero -->
|
||||||
{{ actionError }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div class="card mb-3 shadow-sm border-0" v-for="flag in flagsRes.flags" :key="flag.id">
|
<div
|
||||||
<div class="card-header bg-light d-flex justify-content-between align-items-center">
|
class="card mb-3 border-0"
|
||||||
|
:class="flag.status === 'DISMISSED' ? 'dismissed-card shadow-none' : 'shadow-sm'"
|
||||||
|
v-for="flag in flagsRes.flags"
|
||||||
|
:key="flag.id"
|
||||||
|
>
|
||||||
|
<div class="card-header d-flex justify-content-between align-items-center" :class="flag.status === 'DISMISSED' ? 'bg-transparent' : 'bg-light'">
|
||||||
<div>
|
<div>
|
||||||
<strong>Flag #{{ flag.id }}</strong> -
|
<strong>Flag #{{ flag.id }}</strong> -
|
||||||
<span class="badge" :class="{
|
<span class="badge" :class="{
|
||||||
@@ -162,7 +167,7 @@ const formatDate = (dateStr: string) => {
|
|||||||
{{ flag.details || 'Nessun dettaglio aggiuntivo fornito.' }}
|
{{ flag.details || 'Nessun dettaglio aggiuntivo fornito.' }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-info">
|
||||||
<span class="badge bg-info me-2">{{ flag.content_type }}</span>
|
<span class="badge bg-info me-2">{{ flag.content_type }}</span>
|
||||||
<span v-if="flag.report_id">
|
<span v-if="flag.report_id">
|
||||||
Rif:
|
Rif:
|
||||||
@@ -175,7 +180,7 @@ const formatDate = (dateStr: string) => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 small">
|
<div class="mt-info small text-muted">
|
||||||
Segnalato da: {{ flag.created_by_email }} (ID: {{ flag.created_by_user_id }})
|
Segnalato da: {{ flag.created_by_email }} (ID: {{ flag.created_by_user_id }})
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -203,11 +208,11 @@ const formatDate = (dateStr: string) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Pagination
|
<Pagination
|
||||||
v-if="(flagsRes.total || flagsRes.flags.length) > perPage"
|
v-if="(flagsRes.total || flagsRes.flags.length) > perPage"
|
||||||
:current-page="page"
|
:current-page="page"
|
||||||
:per-page="perPage"
|
:per-page="perPage"
|
||||||
:total-items="flagsRes.total || (page * perPage + 1)"
|
:total-items="flagsRes.total || (page * perPage + 1)"
|
||||||
@page-change="page = $event"
|
@page-change="page = $event"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -235,14 +240,46 @@ const formatDate = (dateStr: string) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
:open="dismissModal.open"
|
:open="dismissModal.open"
|
||||||
title="Ignora flag"
|
title="Ignora flag"
|
||||||
message="Vuoi ignorare questo flag? Azione registrata in moderazione."
|
message="Vuoi ignorare questo flag? Azione registrata in moderazione."
|
||||||
confirm-label="Ignora flag"
|
confirm-label="Ignora flag"
|
||||||
confirm-class="btn-outline-secondary"
|
confirm-class="btn-outline-secondary"
|
||||||
:pending="dismissModal.pending"
|
:pending="dismissModal.pending"
|
||||||
@cancel="closeDismissModal"
|
@cancel="closeDismissModal"
|
||||||
@confirm="handleDismiss"
|
@confirm="handleDismiss"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.dismissed-card {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
opacity: 0.7;
|
||||||
|
border: 1px solid #e9ecef !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dismissed-card .card-header {
|
||||||
|
padding-top: 0.35rem;
|
||||||
|
padding-bottom: 0.35rem;
|
||||||
|
border-bottom: 1px solid rgba(0,0,0,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dismissed-card .card-body {
|
||||||
|
padding-top: 0.6rem;
|
||||||
|
padding-bottom: 0.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dismissed-card h5.card-title {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-info {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dismissed-card .mt-info {
|
||||||
|
margin-top: 0.4rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user