feat(support-tickets): add close action and turn-based reply guidance
Let admins close tickets with confirmation and surface closedBy so consumer reopen rules stay clear.
This commit is contained in:
parent
4c5f4d5983
commit
9254a8b487
@ -7,6 +7,7 @@ import PageNavbar from '@/components/layouts/PageNavbar'
|
||||
import Button from '@/components/formElements/Button'
|
||||
import Input from '@/components/formElements/Input'
|
||||
import { APP_ROUTES } from '@/constants/routes'
|
||||
import useAlertModal from '@/hooks/useAlertModal'
|
||||
import { addToast } from '@/lib/toast'
|
||||
import { formatIranianMobile, formatPersianDate } from '@/lib/formatters'
|
||||
import {
|
||||
@ -21,6 +22,7 @@ import {
|
||||
|
||||
const AdminSupportTicketDetail = () => {
|
||||
const { id } = useParams<{ id: string }>()
|
||||
const { showAlert } = useAlertModal()
|
||||
const [ticket, setTicket] = useState<SupportTicket | null>(null)
|
||||
const [reply, setReply] = useState('')
|
||||
const [pending, setPending] = useState(false)
|
||||
@ -56,6 +58,17 @@ const AdminSupportTicketDetail = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const confirmClose = () => {
|
||||
showAlert(
|
||||
'این تیکت بسته شود؟ کاربر دیگر نمیتواند پیام بفرستد و در صورت بستن توسط ادمین، خودش نمیتواند دوباره باز کند.',
|
||||
() => {
|
||||
void changeStatus('closed')
|
||||
},
|
||||
undefined,
|
||||
{ dangerAccept: true }
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="h-full w-full text-right">
|
||||
<PageNavbar pageTitle={ticket?.subject ?? 'جزئیات تیکت'} />
|
||||
@ -104,6 +117,24 @@ const AdminSupportTicketDetail = () => {
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
{ticket.status !== 'closed' ? (
|
||||
<div className="mt-4 flex justify-end">
|
||||
<Button
|
||||
color="danger"
|
||||
size="sm"
|
||||
variant="flat"
|
||||
onClick={confirmClose}
|
||||
>
|
||||
بستن تیکت
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<p className="mt-4 text-sm text-text-muted">
|
||||
{ticket.closedBy === 'user'
|
||||
? 'این تیکت توسط کاربر بسته شده است.'
|
||||
: 'این تیکت توسط پشتیبانی بسته شده است؛ کاربر نمیتواند دوباره باز کند.'}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="space-y-3 rounded-2xl border border-default-200 bg-white p-5">
|
||||
{ticket.messages.map((message) => (
|
||||
@ -129,7 +160,10 @@ const AdminSupportTicketDetail = () => {
|
||||
setReply(String(value))
|
||||
}}
|
||||
/>
|
||||
<p className="my-3 text-xs text-text-muted">پس از ثبت پاسخ، برای کاربر پیامک اطلاعرسانی ارسال میشود.</p>
|
||||
<p className="my-3 text-xs text-text-muted">
|
||||
میتوانید چند پیام پشتسرهم بفرستید. کاربر فقط بعد از پاسخ شما یک پیام میتواند بفرستد. پس از ثبت پاسخ، برای کاربر پیامک
|
||||
اطلاعرسانی ارسال میشود.
|
||||
</p>
|
||||
<Button
|
||||
isLoading={pending}
|
||||
onClick={() => void send()}
|
||||
|
||||
48
openapi.json
48
openapi.json
@ -16112,6 +16112,7 @@
|
||||
},
|
||||
"/api/v1/support-tickets/{id}/replies": {
|
||||
"post": {
|
||||
"description": "Allowed only while status is waiting_user (after a support reply). One consumer message returns the ticket to waiting_admin.",
|
||||
"operationId": "SupportTicketsController_reply",
|
||||
"parameters": [
|
||||
{
|
||||
@ -16154,6 +16155,41 @@
|
||||
"tags": ["Support Tickets"]
|
||||
}
|
||||
},
|
||||
"/api/v1/support-tickets/{id}/close": {
|
||||
"post": {
|
||||
"description": "Consumers may close their own open tickets. Admin-closed tickets stay closed and cannot be reopened by the consumer.",
|
||||
"operationId": "SupportTicketsController_close",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/SupportTicketSummaryResponseDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"JWT-auth": []
|
||||
}
|
||||
],
|
||||
"summary": "Close my support ticket",
|
||||
"tags": ["Support Tickets"]
|
||||
}
|
||||
},
|
||||
"/api/v1/admin/support-tickets": {
|
||||
"get": {
|
||||
"operationId": "AdminSupportTicketsController_list",
|
||||
@ -28493,6 +28529,12 @@
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"closedBy": {
|
||||
"type": "string",
|
||||
"enum": ["user", "admin"],
|
||||
"nullable": true,
|
||||
"description": "Who closed the ticket. Consumers cannot reopen admin-closed tickets."
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
@ -28544,6 +28586,12 @@
|
||||
"format": "date-time",
|
||||
"nullable": true
|
||||
},
|
||||
"closedBy": {
|
||||
"type": "string",
|
||||
"enum": ["user", "admin"],
|
||||
"nullable": true,
|
||||
"description": "Who closed the ticket. Consumers cannot reopen admin-closed tickets."
|
||||
},
|
||||
"createdAt": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
|
||||
@ -19,6 +19,7 @@ export interface SupportTicket {
|
||||
status: string
|
||||
lastMessageAt: string
|
||||
closedAt: string | null
|
||||
closedBy?: 'user' | 'admin' | null
|
||||
createdAt: string
|
||||
user: { mobile: string; displayName: string | null }
|
||||
messages: SupportTicketMessage[]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user