Files
elink-test-master/TestMasterUI/src/components/users/UserEditDialog.jsx
T
2025-02-05 22:32:28 +09:00

312 lines
11 KiB
React

import React, { useState, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { useAPI } from '@/providers/APIProvider';
import { ScrollArea } from '@/components/ui/scroll-area';
// User status enum mapped to descriptions
const USER_STATUS = {
WAITING: '가입승인 대기',
ACTIVE: '활성화',
RESET_PASSWORD: '비밀번호 초기화',
INACTIVE: '비활성화',
LOCKED: '잠김',
DELETED: '삭제'
};
const DEFAULT_USER = {
esntlId: null,
userId: '',
password: '',
password2: '',
username: '',
userSecurity: 'ROLE_USER',
mobilePhone: '',
status: 'WAITING', // Changed default to WAITING as per business logic
lockAt: 'N',
lockCnt: 0,
createdAt: null,
lastLockDate: null,
lastPasswordChangeDate: null
};
const UserEditDialog = ({ open, onOpenChange, item }) => {
const { createUser, updateUser, error } = useAPI();
const [user, setUser] = useState(DEFAULT_USER);
const [validationErrors, setValidationErrors] = useState({});
useEffect(() => {
if (item) {
setUser(item);
} else {
setUser(DEFAULT_USER);
}
}, [item]);
const validateForm = () => {
const errors = {};
if (!user.userId) errors.userId = '사용자 ID는 필수입니다.';
if (!user.username) errors.username = '이름은 필수입니다.';
if (!user.mobilePhone) errors.mobilePhone = '연락처는 필수입니다.';
if (!user.esntlId) { // Only validate passwords for new users
if (!user.password) errors.password = '비밀번호는 필수입니다.';
if (user.password && user.password.length < 8) {
errors.password = '비밀번호는 8자 이상이어야 합니다.';
}
if (user.password !== user.password2) {
errors.password2 = '비밀번호가 일치하지 않습니다.';
}
}
setValidationErrors(errors);
return Object.keys(errors).length === 0;
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!validateForm()) {
return;
}
try {
// Create a clean copy of the user data for API submission
const userData = {
...user,
createdAt: user.createdAt || undefined,
lastLockDate: user.lastLockDate || undefined,
lastPasswordChangeDate: user.lastPasswordChangeDate || undefined
};
if (user.esntlId) {
await updateUser(user.esntlId, userData);
} else {
await createUser(userData);
}
onOpenChange(false);
} catch (error) {
console.error('Failed to save user:', error);
}
};
const handleChange = (field, value) => {
setUser(prev => ({ ...prev, [field]: value }));
// Clear validation error when field is modified
if (validationErrors[field]) {
setValidationErrors(prev => ({ ...prev, [field]: undefined }));
}
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-3xl max-h-[90vh]">
<DialogHeader>
<DialogTitle>
{user.esntlId == null ? '내부 사용자 등록' : '내부 사용자 수정'}
</DialogTitle>
<DialogDescription>
사용자 정보를 입력하거나 수정할 있습니다. 필수 항목을 모두 입력해주세요.
</DialogDescription>
{error && (
<div className="text-red-500 text-sm">
{error}
</div>
)}
</DialogHeader>
<ScrollArea className="max-h-[calc(90vh-200px)]">
<form onSubmit={handleSubmit} className="space-y-4 p-1">
{user.esntlId && (
<div className="space-y-2">
<Label>고유ID</Label>
<Input value={user.esntlId} disabled />
</div>
)}
<div className="space-y-2">
<Label htmlFor="userId" className="must">사용자 ID</Label>
<Input
id="userId"
value={user.userId}
onChange={(e) => handleChange('userId', e.target.value)}
disabled={!!user.esntlId}
required
className={validationErrors.userId ? 'border-red-500' : ''}
/>
{validationErrors.userId && (
<div className="text-red-500 text-sm">{validationErrors.userId}</div>
)}
</div>
{!user.esntlId && (
<>
<div className="space-y-2">
<Label htmlFor="password" className="must">비밀번호</Label>
<Input
id="password"
type="password"
value={user.password}
onChange={(e) => handleChange('password', e.target.value)}
required
className={validationErrors.password ? 'border-red-500' : ''}
/>
{validationErrors.password && (
<div className="text-red-500 text-sm">{validationErrors.password}</div>
)}
</div>
<div className="space-y-2">
<Label htmlFor="password2" className="must">비밀번호 확인</Label>
<Input
id="password2"
type="password"
value={user.password2}
onChange={(e) => handleChange('password2', e.target.value)}
required
className={validationErrors.password2 ? 'border-red-500' : ''}
/>
{validationErrors.password2 && (
<div className="text-red-500 text-sm">{validationErrors.password2}</div>
)}
</div>
</>
)}
<div className="space-y-2">
<Label htmlFor="username" className="must">이름</Label>
<Input
id="username"
value={user.username}
onChange={(e) => handleChange('username', e.target.value)}
required
className={validationErrors.username ? 'border-red-500' : ''}
/>
{validationErrors.username && (
<div className="text-red-500 text-sm">{validationErrors.username}</div>
)}
</div>
<div className="space-y-2">
<Label className="must">권한</Label>
<Select
value={user.userSecurity}
onValueChange={(value) => handleChange('userSecurity', value)}
>
<SelectTrigger>
<SelectValue placeholder="권한 선택" />
</SelectTrigger>
<SelectContent>
<SelectItem value="ROLE_ADMIN">관리자</SelectItem>
<SelectItem value="ROLE_USER">사용자</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="mobilePhone" className="must">연락처</Label>
<Input
id="mobilePhone"
value={user.mobilePhone}
onChange={(e) => handleChange('mobilePhone', e.target.value)}
required
className={validationErrors.mobilePhone ? 'border-red-500' : ''}
/>
{validationErrors.mobilePhone && (
<div className="text-red-500 text-sm">{validationErrors.mobilePhone}</div>
)}
</div>
{user.esntlId && (
<>
<div className="space-y-2">
<Label className="must">상태</Label>
<Select
value={user.status}
onValueChange={(value) => handleChange('status', value)}
>
<SelectTrigger>
<SelectValue placeholder="상태 선택" />
</SelectTrigger>
<SelectContent>
{Object.entries(USER_STATUS).map(([value, label]) => (
<SelectItem key={value} value={value}>
{label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label className="must">잠금여부</Label>
<Select
value={user.lockAt}
onValueChange={(value) => handleChange('lockAt', value)}
>
<SelectTrigger>
<SelectValue placeholder="잠금여부 선택" />
</SelectTrigger>
<SelectContent>
<SelectItem value="N">해제</SelectItem>
<SelectItem value="Y">잠금</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label>잠금 횟수</Label>
<Input value={user.lockCnt} disabled />
</div>
{user.createdAt && (
<div className="space-y-2">
<Label>등록 일시</Label>
<Input value={user.createdAt} disabled />
</div>
)}
{user.lastLockDate && (
<div className="space-y-2">
<Label>잠금최종시점</Label>
<Input value={user.lastLockDate} disabled />
</div>
)}
{user.lastPasswordChangeDate && (
<div className="space-y-2">
<Label>비밀번호 변경일자</Label>
<Input value={user.lastPasswordChangeDate} disabled />
</div>
)}
</>
)}
</form>
</ScrollArea>
<DialogFooter className="flex justify-end space-x-2">
<Button variant="secondary" onClick={() => onOpenChange(false)}>
닫기
</Button>
<Button type="submit" onClick={handleSubmit}>
저장
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};
export default UserEditDialog;