import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { Card } from '../../../shared/ui/Card'; import { Button } from '../../../shared/ui/Button'; import { Input } from '../../../shared/ui/Input'; import { Select } from '../../../shared/ui/Select'; import { ArrowLeft, Save, Upload } from 'lucide-react'; import { getCategories, getLocations, getIDRule } from './AssetSettingsPage'; import { assetApi, type Asset } from '../../../shared/api/assetApi'; import './AssetRegisterPage.css'; export function AssetRegisterPage() { const navigate = useNavigate(); // Load Settings Data const categories = getCategories(); const locations = getLocations(); const idRule = getIDRule(); const [formData, setFormData] = useState({ id: '', // Asset ID (Auto-generated) name: '', categoryId: '', // Use ID for selection model: '', serialNo: '', locationId: '', // Use ID for selection manager: '', status: 'active', purchaseDate: new Date().toISOString().split('T')[0], // Default to today purchasePrice: '', image: null as File | null, imagePreview: '' as string, manufacturer: '' }); // Auto-generate Asset ID useEffect(() => { // If category is required by rule but not selected, can't generate fully const hasCategoryRule = idRule.some(r => r.type === 'category'); if (hasCategoryRule && !formData.categoryId) { setFormData(prev => ({ ...prev, id: '' })); return; } const category = categories.find(c => c.id === formData.categoryId); const year = formData.purchaseDate ? new Date(formData.purchaseDate).getFullYear().toString() : new Date().getFullYear().toString(); // Build ID string based on Rule const generatedId = idRule.map(part => { if (part.type === 'company') return part.value; // e.g. HK if (part.type === 'custom') return part.value; if (part.type === 'separator') return part.value; if (part.type === 'year') return year; if (part.type === 'category') return category ? category.code : 'UNKNOWN'; if (part.type === 'sequence') return part.value; return ''; }).join(''); const finalId = generatedId.replace('001', '001'); setFormData(prev => ({ ...prev, id: finalId })); }, [formData.categoryId, formData.purchaseDate, idRule, categories]); const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleImageChange = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { const reader = new FileReader(); reader.onloadend = () => { setFormData(prev => ({ ...prev, image: file, imagePreview: reader.result as string })); }; reader.readAsDataURL(file); } }; const handleSubmit = async (e: React.FormEvent) => { if (e) e.preventDefault(); // Validation if (!formData.categoryId || !formData.name || !formData.locationId) { alert('필수 항목(카테고리, 자산명, 설치위치)을 입력해주세요.'); return; } try { const selectedCategory = categories.find(c => c.id === formData.categoryId); const selectedLocation = locations.find(l => l.id === formData.locationId); let imageUrl = ''; if (formData.image) { const uploadRes = await assetApi.uploadImage(formData.image); imageUrl = uploadRes.data.url; } const payload: Partial = { id: formData.id, name: formData.name, category: selectedCategory ? selectedCategory.name : '미지정', model: formData.model, serialNumber: formData.serialNo, location: selectedLocation ? selectedLocation.name : '미지정', manager: formData.manager, status: formData.status as Asset['status'], purchaseDate: formData.purchaseDate, purchasePrice: formData.purchasePrice ? Number(formData.purchasePrice) : 0, manufacturer: formData.manufacturer, image: imageUrl }; await assetApi.create(payload); alert(`자산이 성공적으로 등록되었습니다.\n자산번호: ${formData.id}`); navigate('/asset/list'); } catch (error) { console.error('Failed to register asset:', error); alert('자산 등록에 실패했습니다. 서버 상태를 확인해주세요.'); } }; return (

자산 등록

새로운 자산을 시스템에 등록합니다.

{/* Basic Info Section */}

기본 정보

{/* Image Upload Field */}
{formData.imagePreview ? ( Preview ) : (
)}
{formData.image ? formData.image.name : '선택된 파일 없음'} 지원 형식: JPG, PNG, GIF (최대 5MB)
{/* Management Info Section */}

관리 정보

{/* Bottom Action Buttons */}
); }