feat: back button + reopen for approved/rejected tickets
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ChevronLeft, Clock, User, MessageSquare, Paperclip, Send, CheckCircle2, ArrowRight } from 'lucide-react';
|
||||
import { ChevronLeft, Clock, User, MessageSquare, Paperclip, Send, CheckCircle2, ArrowRight, RotateCcw } from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import ticketService from '@/services/ticketService';
|
||||
import apiClient from '@/services/apiClient';
|
||||
@@ -72,7 +72,10 @@ export default function IssueDetailPage({ params }: { params: Promise<{ id: stri
|
||||
|
||||
const currentIdx = statusFlow.indexOf(status);
|
||||
const canAdvance = currentIdx < statusFlow.length - 1;
|
||||
const canGoBack = currentIdx > 0;
|
||||
const isClosed = status === 'CLOSED';
|
||||
const isApprovalTicket = ['VACATION', 'EXPENSE', 'EQUIPMENT_REQUEST', 'GENERAL'].includes(ticket?.category || '');
|
||||
const isMgmt = user?.roleCode !== 'EMPLOYEE';
|
||||
|
||||
const handleAdvance = async () => {
|
||||
if (!canAdvance) return;
|
||||
@@ -85,6 +88,24 @@ export default function IssueDetailPage({ params }: { params: Promise<{ id: stri
|
||||
}
|
||||
};
|
||||
|
||||
const handleBack = async () => {
|
||||
if (!canGoBack) return;
|
||||
const prevStatus = statusFlow[currentIdx - 1];
|
||||
try {
|
||||
await ticketService.updateStatus(ticketId, prevStatus);
|
||||
setStatus(prevStatus);
|
||||
} catch (err: unknown) {
|
||||
alert((err as { message?: string })?.message || '상태 변경 실패');
|
||||
}
|
||||
};
|
||||
|
||||
const handleReopen = async () => {
|
||||
try {
|
||||
const res: any = await apiClient.post(`/tickets/${ticketId}/reopen`);
|
||||
if (res.success) setTicket(res.data);
|
||||
} catch (err: any) { alert(err.message || '재오픈 실패'); }
|
||||
};
|
||||
|
||||
const handlePostComment = async () => {
|
||||
if (!newComment.trim()) return;
|
||||
try {
|
||||
@@ -124,9 +145,26 @@ export default function IssueDetailPage({ params }: { params: Promise<{ id: stri
|
||||
</Link>
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<span className={`text-xs font-semibold px-3 py-1.5 rounded-full ${statusColor[status]}`}>{statusLabel[status]}</span>
|
||||
{!isClosed && (
|
||||
<button onClick={handleAdvance} disabled={!canAdvance} className="bg-primary hover:bg-primary-hover disabled:opacity-40 disabled:cursor-not-allowed text-white text-xs font-semibold px-4 py-1.5 rounded-lg transition-all flex items-center">
|
||||
{canAdvance ? <>Advance <ArrowRight className="w-3.5 h-3.5 ml-1.5" /></> : 'Completed'}
|
||||
{!isClosed && statusFlow.includes(status) && (
|
||||
<>
|
||||
{canGoBack && (
|
||||
<button onClick={handleBack} className="bg-gray-100 hover:bg-gray-200 text-text-muted text-xs font-semibold px-3 py-1.5 rounded-lg transition-all flex items-center">
|
||||
<ChevronLeft className="w-3.5 h-3.5 mr-1" /> Back
|
||||
</button>
|
||||
)}
|
||||
<button onClick={handleAdvance} disabled={!canAdvance} className="bg-primary hover:bg-primary-hover disabled:opacity-40 disabled:cursor-not-allowed text-white text-xs font-semibold px-4 py-1.5 rounded-lg transition-all flex items-center">
|
||||
{canAdvance ? <>Advance <ArrowRight className="w-3.5 h-3.5 ml-1.5" /></> : 'Completed'}
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
{status === 'APPROVED' && isMgmt && (
|
||||
<button onClick={handleReopen} className="bg-amber-50 hover:bg-amber-100 text-amber-700 border border-amber-200 text-xs font-semibold px-3 py-1.5 rounded-lg transition-all">
|
||||
승인 취소
|
||||
</button>
|
||||
)}
|
||||
{status === 'REJECTED' && (
|
||||
<button onClick={handleReopen} className="bg-blue-50 hover:bg-blue-100 text-blue-700 border border-blue-200 text-xs font-semibold px-3 py-1.5 rounded-lg transition-all">
|
||||
재오픈
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user