fix: ticket

This commit is contained in:
sajjadtalkhabi
2026-06-05 18:43:02 +03:30
parent 1c665830b0
commit ea562aeefa
53 changed files with 2475 additions and 859 deletions
@@ -0,0 +1,145 @@
<template>
<BasicModal width="95%" max-width="58rem" min-width="auto" :show-close-button="true">
<template #default>
<div class="sdm">
<header class="sdm__header">
<LineTitleBlock title="جزئیات درخواست" title-en="Request details" />
</header>
<SkeletonLoaderBlock v-if="isLoading && !service" :rows="2" :cols-per-row="1" />
<template v-else-if="service">
<div class="sdm__top">
<Badge :variant="statusVariant" size="sm" dot :value="statusLabel" />
<span class="sdm__date">{{ requestDate }}</span>
</div>
<div v-if="messages.length > 0" class="sdm__messages">
<div v-for="message in messages" :key="message.id" class="sdm__bubble">
<p class="sdm__text">{{ message.message }}</p>
<span class="sdm__time">{{ messageTime(message) }}</span>
</div>
</div>
<NoItems v-else title="پیامی نیست" desc="هنوز پیامی برای این درخواست ثبت نشده است." />
</template>
</div>
</template>
</BasicModal>
</template>
<script setup>
import { computed } from 'vue'
import { TICKET_STATUS } from '@/enums'
import Badge from '@/components/Badge.vue'
import useModal from '@/composables/useModal'
import BasicModal from '@/components/BasicModal.vue'
import NoItems from '@/components/blocks/NoItems.vue'
import { formatJalaaliDate } from '@/utils/date-utils'
import LineTitleBlock from '@/components/LineTitleBlock.vue'
import { useStudentTicketQuery } from '@/services/query/student-tickets'
import SkeletonLoaderBlock from '@/components/blocks/SkeletonLoaderBlock.vue'
defineOptions({ name: 'ServiceDetailsModal' })
const STATUS_VARIANT = {
open: 'neutral',
answered: 'success',
closed: 'info',
approved: 'success',
rejected: 'danger',
pending: 'neutral',
}
const { getModal } = useModal()
const modalData = computed(() => getModal('ServiceDetailsModal')?.data ?? {})
const ticketId = computed(() => modalData.value.id ?? null)
const { data: service, isLoading } = useStudentTicketQuery(ticketId, {
enabled: () => !!ticketId.value,
})
const messages = computed(() => service.value?.messages ?? [])
const statusLabel = computed(() => TICKET_STATUS[service.value?.status] || '—')
const statusVariant = computed(() => STATUS_VARIANT[service.value?.status] || 'neutral')
const requestDate = computed(() => formatJalaaliDate(service.value?.createdAt) || '—')
const messageTime = (message) => {
if (!message.createdAt) return ''
const d = new Date(message.createdAt)
if (Number.isNaN(d.getTime())) return ''
return d.toLocaleTimeString('fa-IR', { hour: '2-digit', minute: '2-digit' })
}
</script>
<style lang="scss" scoped>
.sdm {
display: flex;
flex-direction: column;
gap: 1rem;
padding-block: 0.25rem 0.5rem;
text-align: start;
&__header {
display: flex;
align-items: center;
justify-content: flex-start;
}
&__top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75rem;
flex-wrap: wrap;
}
&__date {
background: #f5f5f5;
color: #a3a3a3;
border-radius: 9999px;
padding: 0.3rem 0.875rem;
font-family: var(--font-family-fa);
font-size: 0.7rem;
line-height: 1.45;
white-space: nowrap;
}
&__messages {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
&__bubble {
position: relative;
background: #f6f6f6;
padding: 1rem 1rem 1.5rem;
border-radius: 0.75rem 0.75rem 0 0.75rem;
color: #454545;
}
&__text {
font-family: var(--font-family-fa);
font-weight: 300;
font-size: 0.8rem;
line-height: 1.7;
margin: 0;
text-align: justify;
white-space: pre-wrap;
}
&__time {
position: absolute;
inset-inline-end: 1rem;
inset-block-end: 0.5rem;
font-family: var(--font-family-fa);
font-size: 0.65rem;
color: #a7a7a7;
line-height: 1.45;
}
}
</style>