삭제 후엔 부서 선택 해제
This commit is contained in:
parent
6b53cb414c
commit
c50c8d01df
|
|
@ -250,25 +250,19 @@ export async function deleteDepartment(req: AuthenticatedRequest, res: Response)
|
||||||
if (parseInt(hasChildren?.count || "0") > 0) {
|
if (parseInt(hasChildren?.count || "0") > 0) {
|
||||||
res.status(400).json({
|
res.status(400).json({
|
||||||
success: false,
|
success: false,
|
||||||
message: "하위 부서가 있는 부서는 삭제할 수 없습니다.",
|
message: "하위 부서가 있는 부서는 삭제할 수 없습니다. 먼저 하위 부서를 삭제해주세요.",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 부서원 확인
|
// 부서원 삭제 (부서 삭제 전에 먼저 삭제)
|
||||||
const hasMembers = await queryOne<any>(`
|
const deletedMembers = await query<any>(`
|
||||||
SELECT COUNT(*) as count
|
DELETE FROM user_dept
|
||||||
FROM user_dept
|
|
||||||
WHERE dept_code = $1
|
WHERE dept_code = $1
|
||||||
|
RETURNING user_id
|
||||||
`, [deptCode]);
|
`, [deptCode]);
|
||||||
|
|
||||||
if (parseInt(hasMembers?.count || "0") > 0) {
|
const memberCount = deletedMembers.length;
|
||||||
res.status(400).json({
|
|
||||||
success: false,
|
|
||||||
message: "부서원이 있는 부서는 삭제할 수 없습니다.",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 부서 삭제
|
// 부서 삭제
|
||||||
const result = await query<any>(`
|
const result = await query<any>(`
|
||||||
|
|
@ -285,11 +279,17 @@ export async function deleteDepartment(req: AuthenticatedRequest, res: Response)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("부서 삭제 성공", { deptCode });
|
logger.info("부서 삭제 성공", {
|
||||||
|
deptCode,
|
||||||
|
deptName: result[0].dept_name,
|
||||||
|
deletedMemberCount: memberCount
|
||||||
|
});
|
||||||
|
|
||||||
res.status(200).json({
|
res.status(200).json({
|
||||||
success: true,
|
success: true,
|
||||||
message: "부서가 삭제되었습니다.",
|
message: memberCount > 0
|
||||||
|
? `부서가 삭제되었습니다. (부서원 ${memberCount}명 제외됨)`
|
||||||
|
: "부서가 삭제되었습니다.",
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("부서 삭제 실패", error);
|
logger.error("부서 삭제 실패", error);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import {
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import type { Department, DepartmentMember } from "@/types/department";
|
import type { Department, DepartmentMember } from "@/types/department";
|
||||||
import * as departmentAPI from "@/lib/api/department";
|
import * as departmentAPI from "@/lib/api/department";
|
||||||
|
|
||||||
|
|
@ -30,6 +31,7 @@ export function DepartmentMembers({
|
||||||
selectedDepartment,
|
selectedDepartment,
|
||||||
onMemberChange,
|
onMemberChange,
|
||||||
}: DepartmentMembersProps) {
|
}: DepartmentMembersProps) {
|
||||||
|
const { toast } = useToast();
|
||||||
const [members, setMembers] = useState<DepartmentMember[]>([]);
|
const [members, setMembers] = useState<DepartmentMember[]>([]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
|
const [isAddModalOpen, setIsAddModalOpen] = useState(false);
|
||||||
|
|
@ -108,16 +110,31 @@ export function DepartmentMembers({
|
||||||
setSearchResults([]);
|
setSearchResults([]);
|
||||||
loadMembers();
|
loadMembers();
|
||||||
onMemberChange?.(); // 부서 구조 새로고침
|
onMemberChange?.(); // 부서 구조 새로고침
|
||||||
|
|
||||||
|
// 성공 Toast 표시
|
||||||
|
toast({
|
||||||
|
title: "부서원 추가 완료",
|
||||||
|
description: "부서원이 추가되었습니다.",
|
||||||
|
variant: "default",
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if ((response as any).isDuplicate) {
|
if ((response as any).isDuplicate) {
|
||||||
setDuplicateMessage(response.error || "이미 해당 부서의 부서원입니다.");
|
setDuplicateMessage(response.error || "이미 해당 부서의 부서원입니다.");
|
||||||
} else {
|
} else {
|
||||||
alert(response.error || "부서원 추가에 실패했습니다.");
|
toast({
|
||||||
|
title: "부서원 추가 실패",
|
||||||
|
description: response.error || "부서원 추가에 실패했습니다.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("부서원 추가 실패:", error);
|
console.error("부서원 추가 실패:", error);
|
||||||
alert("부서원 추가 중 오류가 발생했습니다.");
|
toast({
|
||||||
|
title: "부서원 추가 실패",
|
||||||
|
description: "부서원 추가 중 오류가 발생했습니다.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -142,12 +159,27 @@ export function DepartmentMembers({
|
||||||
setMemberToRemove(null);
|
setMemberToRemove(null);
|
||||||
loadMembers();
|
loadMembers();
|
||||||
onMemberChange?.(); // 부서 구조 새로고침
|
onMemberChange?.(); // 부서 구조 새로고침
|
||||||
|
|
||||||
|
// 성공 Toast 표시
|
||||||
|
toast({
|
||||||
|
title: "부서원 제거 완료",
|
||||||
|
description: `${memberToRemove.name} 님이 부서에서 제외되었습니다.`,
|
||||||
|
variant: "default",
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
alert(response.error || "부서원 제거에 실패했습니다.");
|
toast({
|
||||||
|
title: "부서원 제거 실패",
|
||||||
|
description: response.error || "부서원 제거에 실패했습니다.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("부서원 제거 실패:", error);
|
console.error("부서원 제거 실패:", error);
|
||||||
alert("부서원 제거 중 오류가 발생했습니다.");
|
toast({
|
||||||
|
title: "부서원 제거 실패",
|
||||||
|
description: "부서원 제거 중 오류가 발생했습니다.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -163,12 +195,27 @@ export function DepartmentMembers({
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
loadMembers();
|
loadMembers();
|
||||||
|
|
||||||
|
// 성공 Toast 표시
|
||||||
|
toast({
|
||||||
|
title: "주 부서 설정 완료",
|
||||||
|
description: "주 부서가 변경되었습니다.",
|
||||||
|
variant: "default",
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
alert(response.error || "주 부서 설정에 실패했습니다.");
|
toast({
|
||||||
|
title: "주 부서 설정 실패",
|
||||||
|
description: response.error || "주 부서 설정에 실패했습니다.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("주 부서 설정 실패:", error);
|
console.error("주 부서 설정 실패:", error);
|
||||||
alert("주 부서 설정 중 오류가 발생했습니다.");
|
toast({
|
||||||
|
title: "주 부서 설정 실패",
|
||||||
|
description: "주 부서 설정 중 오류가 발생했습니다.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,11 @@
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { Plus, ChevronDown, ChevronRight, Users, Trash2 } from "lucide-react";
|
import { Plus, ChevronDown, ChevronRight, Users, Trash2 } from "lucide-react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
DialogFooter,
|
|
||||||
} from "@/components/ui/dialog";
|
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import type { Department, DepartmentFormData } from "@/types/department";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
|
import type { Department } from "@/types/department";
|
||||||
import * as departmentAPI from "@/lib/api/department";
|
import * as departmentAPI from "@/lib/api/department";
|
||||||
|
|
||||||
interface DepartmentStructureProps {
|
interface DepartmentStructureProps {
|
||||||
|
|
@ -31,6 +26,7 @@ export function DepartmentStructure({
|
||||||
onSelectDepartment,
|
onSelectDepartment,
|
||||||
refreshTrigger,
|
refreshTrigger,
|
||||||
}: DepartmentStructureProps) {
|
}: DepartmentStructureProps) {
|
||||||
|
const { toast } = useToast();
|
||||||
const [departments, setDepartments] = useState<Department[]>([]);
|
const [departments, setDepartments] = useState<Department[]>([]);
|
||||||
const [expandedDepts, setExpandedDepts] = useState<Set<string>>(new Set());
|
const [expandedDepts, setExpandedDepts] = useState<Set<string>>(new Set());
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
@ -40,10 +36,11 @@ export function DepartmentStructure({
|
||||||
const [parentDeptForAdd, setParentDeptForAdd] = useState<string | null>(null);
|
const [parentDeptForAdd, setParentDeptForAdd] = useState<string | null>(null);
|
||||||
const [newDeptName, setNewDeptName] = useState("");
|
const [newDeptName, setNewDeptName] = useState("");
|
||||||
const [duplicateMessage, setDuplicateMessage] = useState<string | null>(null);
|
const [duplicateMessage, setDuplicateMessage] = useState<string | null>(null);
|
||||||
|
|
||||||
// 부서 삭제 확인 모달
|
// 부서 삭제 확인 모달
|
||||||
const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
|
const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false);
|
||||||
const [deptToDelete, setDeptToDelete] = useState<{ code: string; name: string } | null>(null);
|
const [deptToDelete, setDeptToDelete] = useState<{ code: string; name: string } | null>(null);
|
||||||
|
const [deleteErrorMessage, setDeleteErrorMessage] = useState<string | null>(null);
|
||||||
|
|
||||||
// 부서 목록 로드
|
// 부서 목록 로드
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -97,16 +94,31 @@ export function DepartmentStructure({
|
||||||
setNewDeptName("");
|
setNewDeptName("");
|
||||||
setParentDeptForAdd(null);
|
setParentDeptForAdd(null);
|
||||||
loadDepartments();
|
loadDepartments();
|
||||||
|
|
||||||
|
// 성공 Toast 표시
|
||||||
|
toast({
|
||||||
|
title: "부서 생성 완료",
|
||||||
|
description: `"${newDeptName}" 부서가 생성되었습니다.`,
|
||||||
|
variant: "default",
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if ((response as any).isDuplicate) {
|
if ((response as any).isDuplicate) {
|
||||||
setDuplicateMessage(response.error || "이미 존재하는 부서명입니다.");
|
setDuplicateMessage(response.error || "이미 존재하는 부서명입니다.");
|
||||||
} else {
|
} else {
|
||||||
alert(response.error || "부서 추가에 실패했습니다.");
|
toast({
|
||||||
|
title: "부서 생성 실패",
|
||||||
|
description: response.error || "부서 추가에 실패했습니다.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("부서 추가 실패:", error);
|
console.error("부서 추가 실패:", error);
|
||||||
alert("부서 추가 중 오류가 발생했습니다.");
|
toast({
|
||||||
|
title: "부서 생성 실패",
|
||||||
|
description: "부서 추가 중 오류가 발생했습니다.",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -124,15 +136,32 @@ export function DepartmentStructure({
|
||||||
const response = await departmentAPI.deleteDepartment(deptToDelete.code);
|
const response = await departmentAPI.deleteDepartment(deptToDelete.code);
|
||||||
|
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
|
// 삭제된 부서가 선택되어 있었다면 선택 해제
|
||||||
|
if (selectedDepartment?.dept_code === deptToDelete.code) {
|
||||||
|
onSelectDepartment(null);
|
||||||
|
}
|
||||||
|
|
||||||
setDeleteConfirmOpen(false);
|
setDeleteConfirmOpen(false);
|
||||||
setDeptToDelete(null);
|
setDeptToDelete(null);
|
||||||
loadDepartments();
|
loadDepartments();
|
||||||
|
|
||||||
|
// 성공 메시지 Toast로 표시 (부서원 수 포함)
|
||||||
|
toast({
|
||||||
|
title: "부서 삭제 완료",
|
||||||
|
description: response.message || "부서가 삭제되었습니다.",
|
||||||
|
variant: "default",
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
alert(response.error || "부서 삭제에 실패했습니다.");
|
// 삭제 확인 모달을 닫고 에러 모달을 표시
|
||||||
|
setDeleteConfirmOpen(false);
|
||||||
|
setDeptToDelete(null);
|
||||||
|
setDeleteErrorMessage(response.error || "부서 삭제에 실패했습니다.");
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("부서 삭제 실패:", error);
|
console.error("부서 삭제 실패:", error);
|
||||||
alert("부서 삭제 중 오류가 발생했습니다.");
|
setDeleteConfirmOpen(false);
|
||||||
|
setDeptToDelete(null);
|
||||||
|
setDeleteErrorMessage("부서 삭제 중 오류가 발생했습니다.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -160,15 +189,12 @@ export function DepartmentStructure({
|
||||||
<div key={dept.dept_code}>
|
<div key={dept.dept_code}>
|
||||||
{/* 부서 항목 */}
|
{/* 부서 항목 */}
|
||||||
<div
|
<div
|
||||||
className={`flex cursor-pointer items-center justify-between rounded-lg p-2 text-sm transition-colors hover:bg-muted ${
|
className={`hover:bg-muted flex cursor-pointer items-center justify-between rounded-lg p-2 text-sm transition-colors ${
|
||||||
isSelected ? "bg-primary/10 text-primary" : ""
|
isSelected ? "bg-primary/10 text-primary" : ""
|
||||||
}`}
|
}`}
|
||||||
style={{ marginLeft: `${level * 16}px` }}
|
style={{ marginLeft: `${level * 16}px` }}
|
||||||
>
|
>
|
||||||
<div
|
<div className="flex flex-1 items-center gap-2" onClick={() => onSelectDepartment(dept)}>
|
||||||
className="flex flex-1 items-center gap-2"
|
|
||||||
onClick={() => onSelectDepartment(dept)}
|
|
||||||
>
|
|
||||||
{/* 확장/축소 아이콘 */}
|
{/* 확장/축소 아이콘 */}
|
||||||
{hasChildren ? (
|
{hasChildren ? (
|
||||||
<button
|
<button
|
||||||
|
|
@ -178,11 +204,7 @@ export function DepartmentStructure({
|
||||||
}}
|
}}
|
||||||
className="h-4 w-4"
|
className="h-4 w-4"
|
||||||
>
|
>
|
||||||
{isExpanded ? (
|
{isExpanded ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
|
||||||
<ChevronDown className="h-4 w-4" />
|
|
||||||
) : (
|
|
||||||
<ChevronRight className="h-4 w-4" />
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<div className="h-4 w-4" />
|
<div className="h-4 w-4" />
|
||||||
|
|
@ -192,7 +214,7 @@ export function DepartmentStructure({
|
||||||
<span className="font-medium">{dept.dept_name}</span>
|
<span className="font-medium">{dept.dept_name}</span>
|
||||||
|
|
||||||
{/* 인원수 */}
|
{/* 인원수 */}
|
||||||
<div className="flex items-center gap-1 text-xs text-muted-foreground">
|
<div className="text-muted-foreground flex items-center gap-1 text-xs">
|
||||||
<Users className="h-3 w-3" />
|
<Users className="h-3 w-3" />
|
||||||
<span>{dept.memberCount || 0}</span>
|
<span>{dept.memberCount || 0}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -214,7 +236,7 @@ export function DepartmentStructure({
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="h-6 w-6 text-destructive"
|
className="text-destructive h-6 w-6"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
handleDeleteDepartmentRequest(dept.dept_code, dept.dept_name);
|
handleDeleteDepartmentRequest(dept.dept_code, dept.dept_name);
|
||||||
|
|
@ -244,11 +266,11 @@ export function DepartmentStructure({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 부서 트리 */}
|
{/* 부서 트리 */}
|
||||||
<div className="space-y-1 rounded-lg border bg-card p-4 shadow-sm">
|
<div className="bg-card space-y-1 rounded-lg border p-4 shadow-sm">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<div className="py-8 text-center text-sm text-muted-foreground">로딩 중...</div>
|
<div className="text-muted-foreground py-8 text-center text-sm">로딩 중...</div>
|
||||||
) : departments.length === 0 ? (
|
) : departments.length === 0 ? (
|
||||||
<div className="py-8 text-center text-sm text-muted-foreground">
|
<div className="text-muted-foreground py-8 text-center text-sm">
|
||||||
부서가 없습니다. 최상위 부서를 추가해주세요.
|
부서가 없습니다. 최상위 부서를 추가해주세요.
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -260,9 +282,7 @@ export function DepartmentStructure({
|
||||||
<Dialog open={isAddModalOpen} onOpenChange={setIsAddModalOpen}>
|
<Dialog open={isAddModalOpen} onOpenChange={setIsAddModalOpen}>
|
||||||
<DialogContent className="sm:max-w-[425px]">
|
<DialogContent className="sm:max-w-[425px]">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>
|
<DialogTitle>{parentDeptForAdd ? "하위 부서 추가" : "최상위 부서 추가"}</DialogTitle>
|
||||||
{parentDeptForAdd ? "하위 부서 추가" : "최상위 부서 추가"}
|
|
||||||
</DialogTitle>
|
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
<div className="space-y-4 py-4">
|
<div className="space-y-4 py-4">
|
||||||
|
|
@ -301,10 +321,7 @@ export function DepartmentStructure({
|
||||||
<p className="text-sm">{duplicateMessage}</p>
|
<p className="text-sm">{duplicateMessage}</p>
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button
|
<Button onClick={() => setDuplicateMessage(null)} className="h-8 text-xs sm:h-10 sm:text-sm">
|
||||||
onClick={() => setDuplicateMessage(null)}
|
|
||||||
className="h-8 text-xs sm:h-10 sm:text-sm"
|
|
||||||
>
|
|
||||||
확인
|
확인
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
|
|
@ -321,9 +338,7 @@ export function DepartmentStructure({
|
||||||
<p className="text-sm">
|
<p className="text-sm">
|
||||||
<span className="font-semibold">{deptToDelete?.name}</span> 부서를 삭제하시겠습니까?
|
<span className="font-semibold">{deptToDelete?.name}</span> 부서를 삭제하시겠습니까?
|
||||||
</p>
|
</p>
|
||||||
<p className="mt-2 text-xs text-muted-foreground">
|
<p className="text-muted-foreground mt-2 text-xs">이 작업은 되돌릴 수 없습니다.</p>
|
||||||
이 작업은 되돌릴 수 없습니다.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<DialogFooter className="gap-2 sm:gap-0">
|
<DialogFooter className="gap-2 sm:gap-0">
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -346,7 +361,23 @@ export function DepartmentStructure({
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
|
{/* 부서 삭제 에러 모달 */}
|
||||||
|
<Dialog open={!!deleteErrorMessage} onOpenChange={() => setDeleteErrorMessage(null)}>
|
||||||
|
<DialogContent className="max-w-[95vw] sm:max-w-[400px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle className="text-base sm:text-lg">삭제 불가</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="py-4">
|
||||||
|
<p className="text-sm">{deleteErrorMessage}</p>
|
||||||
|
</div>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button onClick={() => setDeleteErrorMessage(null)} className="h-8 text-xs sm:h-10 sm:text-sm">
|
||||||
|
확인
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue