import { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { Card } from '../../../shared/ui/Card'; import { Button } from '../../../shared/ui/Button'; import { ArrowLeft, Save, Upload, X, Printer, ZoomIn, Trash2, Plus } from 'lucide-react'; import { assetApi } from '../../../shared/api/assetApi'; import type { Asset } from '../../../shared/api/assetApi'; import { SERVER_URL } from '../../../shared/api/client'; import { createPortal } from 'react-dom'; import { useAuth } from '../../../shared/auth/AuthContext'; interface AssetBasicInfoProps { asset: Asset & { image?: string, accessories?: any[] }; onRefresh: () => void; } export function AssetBasicInfo({ asset, onRefresh }: AssetBasicInfoProps) { const navigate = useNavigate(); const { user } = useAuth(); // User role is now allowed to edit assets const canEdit = user?.role === 'admin' || user?.role === 'supervisor' || user?.role === 'user'; const [isEditing, setIsEditing] = useState(false); const [editData, setEditData] = useState(asset); const [isZoomed, setIsZoomed] = useState(false); const [allAssets, setAllAssets] = useState([]); const [accessories, setAccessories] = useState([]); const [showAccModal, setShowAccModal] = useState(false); const [newAcc, setNewAcc] = useState({ name: '', spec: '', quantity: 1 }); useEffect(() => { loadAccessories(); }, [asset.id]); const loadAccessories = async () => { try { const data = await assetApi.getAccessories(asset.id); setAccessories(data); } catch (err) { console.error("Failed to load accessories", err); } }; useEffect(() => { if (isEditing) { const loadAllAssets = async () => { try { const data = await assetApi.getAll(); setAllAssets(data); } catch (err) { console.error("Failed to load assets", err); } }; loadAllAssets(); } }, [isEditing]); const isFacility = asset.category === '설비'; const handleChange = ( e: React.ChangeEvent ) => { const { name, value } = e.target; setEditData(prev => ({ ...prev, [name]: value })); }; const handleSave = async () => { try { await assetApi.update(asset.id, editData); setIsEditing(false); onRefresh(); // Refresh data from server } catch (error) { console.error("Failed to update asset:", error); alert("저장에 실패했습니다."); } }; const handleImageUpload = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; try { const res = await assetApi.uploadImage(file); setEditData(prev => ({ ...prev, image: res.data.url })); } catch (error) { console.error("Failed to upload image:", error); alert("이미지 업로드에 실패했습니다."); } }; const handleDeleteImage = () => { if (confirm("이미지를 삭제하시겠습니까?")) { setEditData(prev => ({ ...prev, image: '' })); } }; const handleCancel = () => { setEditData(asset); setIsEditing(false); }; const handleAddAccessory = async () => { if (!newAcc.name) return alert('품명을 입력해주세요.'); try { await assetApi.addAccessory(asset.id, newAcc); setNewAcc({ name: '', spec: '', quantity: 1 }); setShowAccModal(false); loadAccessories(); } catch (err) { alert('등록 실패'); } }; const handleDeleteAccessory = async (id: number) => { if (!confirm('삭제하시겠습니까?')) return; try { await assetApi.deleteAccessory(id); loadAccessories(); } catch (err) { alert('삭제 실패'); } }; return ( <>
{isEditing ? ( <> ) : ( canEdit && )}
{/* Left: Image Area */}
!isEditing && editData.image && setIsZoomed(true)} > {editData.image ? ( <> {asset.name} {!isEditing && (
)} ) : (
이미지 없음
)} {isEditing && (
e.stopPropagation()}> {editData.image && ( )}
)}
{/* Right: Info Table */}
{isFacility && ( )}
관리번호
{editData.id}
구입가격 {isEditing ? ( ) : (
{editData.purchasePrice ? `${Number(editData.purchasePrice).toLocaleString()} 원` : '-'}
)}
설비명 {isEditing ? ( ) : (
{editData.name}
)}
S/N {isEditing ? ( ) : (
{editData.serialNumber}
)}
입고일 {isEditing ? ( ) : (
{editData.purchaseDate}
)}
모델명 {isEditing ? ( ) : (
{editData.model}
)}
제작사 {isEditing ? ( ) : (
{editData.manufacturer}
)}
교정주기 {isEditing ? ( ) : (
{editData.calibrationCycle}
)}
스펙/사양 {isEditing ? ( ) : (
{editData.specs}
)}
설치위치 {isEditing ? ( ) : (
{editData.location}
)}
관리책임자 {isEditing ? ( ) : (
{editData.manager}
)}
관리상태 {isEditing ? (
) : (
{editData.status === 'active' ? '정상 가동' : editData.status === 'disposed' ? '폐기 (말소)' : editData.status === 'maintain' ? '점검 중' : '수리 필요'}
)}
상위 설비 {isEditing ? (
) : (
{asset.parentId ? ( [{asset.parentId}] {asset.parentName || '상위 설비'} ) : ( 메인 설비 (상위 설비 없음) )}
)}
{/* Sub-Equipment Section (Only for Facilities) */} {isFacility && (

부속 설비 내역

{canEdit && ( )}
{asset.children && asset.children.length > 0 ? ( asset.children.map(child => ( )) ) : ( )}
관리번호 설비명 위치 상태 관리
{child.id} {child.name} {child.location} {child.status === 'active' ? '정상' : '점검/이동'} 이동
등록된 부속 설비가 없습니다.
)}
{/* Accessories Section (For non-facility or all?) - User said skip hierarchical for others, use simple accessories */} {!isFacility && (

부속품 관리

{canEdit && ( )}
{accessories.length > 0 ? ( accessories.map(item => ( )) ) : ( )}
품명 규격 수량 관리
{item.name} {item.spec || '-'} {item.quantity}개
등록된 부속품이 없습니다.
)}
{/* Accessory Add Modal */} {showAccModal && createPortal(

부속품 추가

setNewAcc({ ...newAcc, name: e.target.value })} />
setNewAcc({ ...newAcc, spec: e.target.value })} />
setNewAcc({ ...newAcc, quantity: Number(e.target.value) })} />
, document.body )} {/* Image Zoom Modal - Moved to Portal */} {isZoomed && editData.image && createPortal(
setIsZoomed(false)} >
e.stopPropagation()} > {/* Modal Header */}

{asset.name} - 이미지 상세

{/* Modal Content */}
{asset.name}
, document.body )} ); }