summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-09-03 12:46:37 +0000
committerjoonhoekim <26rote@gmail.com>2025-09-03 12:46:37 +0000
commit07c9bfd5860e27165c255a03f51e95d0187459fe (patch)
treef40c994a81b4317e7cd86e10f6c4b5f4dd6762e1 /components
parent688d9884ca98b50d04ac78fc1f6e28e034a519c0 (diff)
(김준회) 결재 API 응답 처리 오류 수정, 자재마스터 상세보기 누락컬럼 추가
Diffstat (limited to 'components')
-rw-r--r--components/knox/approval/ApprovalCancel.tsx127
-rw-r--r--components/knox/approval/ApprovalDetail.tsx2
-rw-r--r--components/knox/approval/ApprovalList.tsx2
3 files changed, 83 insertions, 48 deletions
diff --git a/components/knox/approval/ApprovalCancel.tsx b/components/knox/approval/ApprovalCancel.tsx
index b40b43df..62afce94 100644
--- a/components/knox/approval/ApprovalCancel.tsx
+++ b/components/knox/approval/ApprovalCancel.tsx
@@ -7,6 +7,7 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Badge } from '@/components/ui/badge';
import { Separator } from '@/components/ui/separator';
+import { Textarea } from '@/components/ui/textarea';
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog';
import { toast } from 'sonner';
import { Loader2, XCircle, AlertTriangle, CheckCircle } from 'lucide-react';
@@ -47,6 +48,7 @@ export default function ApprovalCancel({
const [isCancelling, setIsCancelling] = useState(false);
const [error, setError] = useState<string | null>(null);
const [cancelResult, setCancelResult] = useState<{ apInfId: string } | null>(null);
+ const [cancelOpinion, setCancelOpinion] = useState('');
const fetchApprovalDetail = async () => {
if (!apInfId.trim()) {
@@ -58,11 +60,12 @@ export default function ApprovalCancel({
setError(null);
setApprovalDetail(null);
setCancelResult(null);
+ setCancelOpinion('');
try {
const response = await getApprovalDetail(apInfId);
- if (response.result === 'SUCCESS') {
+ if (response.result === 'success') {
setApprovalDetail(response.data);
} else {
setError('결재 정보를 가져오는데 실패했습니다.');
@@ -80,12 +83,17 @@ export default function ApprovalCancel({
const handleCancelApproval = async () => {
if (!approvalDetail) return;
+ if (!cancelOpinion.trim()) {
+ toast.error('상신취소 의견을 입력해주세요.');
+ return;
+ }
+
setIsCancelling(true);
try {
- const response = await cancelApproval(approvalDetail.apInfId);
+ const response = await cancelApproval(approvalDetail.apInfId, cancelOpinion);
- if (response.result === 'SUCCESS') {
+ if (response.result === 'success') {
setCancelResult({ apInfId: response.data.apInfId });
toast.success('결재가 성공적으로 취소되었습니다.');
onCancelSuccess?.(response.data.apInfId);
@@ -95,6 +103,9 @@ export default function ApprovalCancel({
...approvalDetail,
status: '4' // 상신취소
});
+
+ // 의견 초기화
+ setCancelOpinion('');
} else {
toast.error('결재 취소에 실패했습니다.');
}
@@ -288,54 +299,78 @@ export default function ApprovalCancel({
</div>
</div>
- {/* 취소 버튼 */}
+ {/* 취소 의견 및 버튼 */}
{canCancelApproval(approvalDetail.status) && (
<>
<Separator />
- <div className="flex justify-end">
- <AlertDialog>
- <AlertDialogTrigger asChild>
- <Button variant="destructive" disabled={isCancelling}>
- {isCancelling ? (
- <>
- <Loader2 className="w-4 h-4 mr-2 animate-spin" />
- 취소 중...
- </>
- ) : (
- <>
- <XCircle className="w-4 h-4 mr-2" />
- 결재 취소
- </>
- )}
- </Button>
- </AlertDialogTrigger>
- <AlertDialogContent>
- <AlertDialogHeader>
- <AlertDialogTitle>결재 취소 확인</AlertDialogTitle>
- <AlertDialogDescription>
- 정말로 이 결재를 취소하시겠습니까?
- <br />
- <br />
- <strong>결재 ID:</strong> {approvalDetail.apInfId}
- <br />
- <strong>제목:</strong> {approvalDetail.subject}
- <br />
- <br />
- 이 작업은 되돌릴 수 없습니다.
- </AlertDialogDescription>
- </AlertDialogHeader>
- <AlertDialogFooter>
- <AlertDialogCancel>취소</AlertDialogCancel>
- <AlertDialogAction
- onClick={handleCancelApproval}
- className="bg-red-600 hover:bg-red-700"
+ <div className="space-y-4">
+ <div>
+ <Label htmlFor="cancelOpinion" className="text-sm font-medium">
+ 상신취소 의견 <span className="text-red-500">*</span>
+ </Label>
+ <Textarea
+ id="cancelOpinion"
+ placeholder="상신취소 사유를 입력해주세요"
+ value={cancelOpinion}
+ onChange={(e) => setCancelOpinion(e.target.value)}
+ className="mt-1"
+ rows={3}
+ />
+ <p className="text-xs text-gray-500 mt-1">
+ 상신취소 의견은 필수 입력 항목입니다.
+ </p>
+ </div>
+
+ <div className="flex justify-end">
+ <AlertDialog>
+ <AlertDialogTrigger asChild>
+ <Button
+ variant="destructive"
+ disabled={isCancelling || !cancelOpinion.trim()}
>
- 결재 취소
- </AlertDialogAction>
- </AlertDialogFooter>
- </AlertDialogContent>
- </AlertDialog>
+ {isCancelling ? (
+ <>
+ <Loader2 className="w-4 h-4 mr-2 animate-spin" />
+ 취소 중...
+ </>
+ ) : (
+ <>
+ <XCircle className="w-4 h-4 mr-2" />
+ 결재 취소
+ </>
+ )}
+ </Button>
+ </AlertDialogTrigger>
+ <AlertDialogContent>
+ <AlertDialogHeader>
+ <AlertDialogTitle>결재 취소 확인</AlertDialogTitle>
+ <AlertDialogDescription>
+ 정말로 이 결재를 취소하시겠습니까?
+ <br />
+ <br />
+ <strong>결재 ID:</strong> {approvalDetail.apInfId}
+ <br />
+ <strong>제목:</strong> {approvalDetail.subject}
+ <br />
+ <strong>취소 의견:</strong> {cancelOpinion}
+ <br />
+ <br />
+ 이 작업은 되돌릴 수 없습니다.
+ </AlertDialogDescription>
+ </AlertDialogHeader>
+ <AlertDialogFooter>
+ <AlertDialogCancel>취소</AlertDialogCancel>
+ <AlertDialogAction
+ onClick={handleCancelApproval}
+ className="bg-red-600 hover:bg-red-700"
+ >
+ 결재 취소
+ </AlertDialogAction>
+ </AlertDialogFooter>
+ </AlertDialogContent>
+ </AlertDialog>
+ </div>
</div>
</>
)}
diff --git a/components/knox/approval/ApprovalDetail.tsx b/components/knox/approval/ApprovalDetail.tsx
index d6c883cb..c36137b4 100644
--- a/components/knox/approval/ApprovalDetail.tsx
+++ b/components/knox/approval/ApprovalDetail.tsx
@@ -86,7 +86,7 @@ export default function ApprovalDetail({
getApprovalContent(id)
]);
- if (detailResponse.result === 'SUCCESS' && contentResponse.result === 'SUCCESS') {
+ if (detailResponse.result.toLowerCase() === 'success' && contentResponse.result.toLowerCase() === 'success') {
setApprovalData({
detail: detailResponse.data,
content: contentResponse.data
diff --git a/components/knox/approval/ApprovalList.tsx b/components/knox/approval/ApprovalList.tsx
index 3a766901..13a13936 100644
--- a/components/knox/approval/ApprovalList.tsx
+++ b/components/knox/approval/ApprovalList.tsx
@@ -67,7 +67,7 @@ export default function ApprovalList({
response = await getApprovalHistory();
}
- if (response.result === 'SUCCESS') {
+ if (response.result === 'success') {
setListData(response.data as unknown as ListItem[]);
} else {
setError('목록을 가져오는데 실패했습니다.');