import React, { useState, useEffect } from 'react'; import { useParams, useNavigate, useSearchParams } from 'react-router-dom'; import { useAssetDetails, useAssetMutations } from '../hooks/useAsset'; import { FaArrowLeft, FaSave, FaEdit, FaQrcode } from 'react-icons/fa'; import type { CreateAssetData } from '../services/assetService'; import LinkField from '../components/LinkField'; const AssetDetail: React.FC = () => { const { assetName } = useParams<{ assetName: string }>(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); const duplicateFromAsset = searchParams.get('duplicate'); const isNewAsset = assetName === 'new'; const isDuplicating = isNewAsset && !!duplicateFromAsset; // If duplicating, fetch the source asset const { asset, loading, error } = useAssetDetails( isDuplicating ? duplicateFromAsset : (isNewAsset ? null : assetName || null) ); const { createAsset, updateAsset, loading: saving } = useAssetMutations(); const [isEditing, setIsEditing] = useState(isNewAsset); const [formData, setFormData] = useState({ asset_name: '', company: '', custom_serial_number: '', location: '', custom_manufacturer: '', department: '', custom_asset_type: '', custom_manufacturing_year: '', custom_model: '', custom_class: '', custom_device_status: '', custom_down_time: 0, asset_owner_company: '', custom_up_time: 0, custom_modality: '', custom_attach_image: '', custom_site_contractor: '', custom_total_amount: 0 }); // Load asset data for editing or duplicating useEffect(() => { if (asset) { setFormData({ asset_name: isDuplicating ? `${asset.asset_name} (Copy)` : (asset.asset_name || ''), company: asset.company || '', custom_serial_number: isDuplicating ? '' : (asset.custom_serial_number || ''), // Clear serial number for duplicates location: asset.location || '', custom_manufacturer: asset.custom_manufacturer || '', department: asset.department || '', custom_asset_type: asset.custom_asset_type || '', custom_manufacturing_year: asset.custom_manufacturing_year || '', custom_model: asset.custom_model || '', custom_class: asset.custom_class || '', custom_device_status: asset.custom_device_status || '', custom_down_time: asset.custom_down_time || 0, asset_owner_company: asset.asset_owner_company || '', custom_up_time: asset.custom_up_time || 0, custom_modality: asset.custom_modality || '', custom_attach_image: asset.custom_attach_image || '', custom_site_contractor: asset.custom_site_contractor || '', custom_total_amount: asset.custom_total_amount || 0 }); } }, [asset, isDuplicating]); const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); // Validate required fields if (!formData.asset_name) { alert('Please enter an Asset Name'); return; } if (!formData.custom_asset_type) { alert('Please select a Category'); return; } // Show console log for debugging console.log('Submitting asset data:', formData); try { if (isNewAsset || isDuplicating) { const newAsset = await createAsset(formData); const successMessage = isDuplicating ? 'Asset duplicated successfully!' : 'Asset created successfully!'; alert(successMessage); navigate(`/assets/${newAsset.name}`); } else if (assetName) { await updateAsset(assetName, formData); alert('Asset updated successfully!'); setIsEditing(false); } } catch (err) { console.error('Asset save error:', err); const errorMessage = err instanceof Error ? err.message : 'Unknown error'; // Check if it's an API deployment issue if (errorMessage.includes('404') || errorMessage.includes('not found') || errorMessage.includes('has no attribute') || errorMessage.includes('417')) { alert( '⚠️ Asset API Not Deployed\n\n' + 'The Asset API endpoint (asset_api.py) is not deployed on your Frappe server yet.\n\n' + 'To fix this:\n' + '1. SSH into your Frappe server\n' + '2. Navigate to: frappe-bench/apps/asset_lite/asset_lite/api/\n' + '3. Create the file: asset_api.py\n' + '4. Copy the content from frappe_asset_api.py in this project\n' + '5. Restart Frappe: bench restart\n\n' + 'Error: ' + errorMessage ); } else { alert('Failed to save asset:\n\n' + errorMessage); } } }; if (loading) { return (

Loading asset details...

); } if (error && !isNewAsset && !isDuplicating) { return (

Error: {error}

); } // Show error for duplicate if source asset not found if (error && isDuplicating) { return (

Source Asset Not Found

The asset you're trying to duplicate could not be found. It may have been deleted or you may not have permission to access it.

); } return (
{/* Header */}
{!isNewAsset && !isEditing && ( )} {isEditing && ( <> )}
{/* Left Column - Asset Information & Technical Specs & Location */}
{/* Asset Information */}

Asset Information

{/*
*/} setFormData({ ...formData, custom_asset_type: val })} /> {/*
*/} setFormData({ ...formData, custom_modality: val })} />
{isDuplicating && (

💡 Duplicating from: {duplicateFromAsset}

)}
{/* Technical Specs */}

Technical Specs

{/*
*/} setFormData({ ...formData, manufacturer: val })} />
{/* Location */}

Location

{/*
*/} setFormData({ ...formData, company: val })} /> {/*
*/} setFormData({ ...formData, department: val })} />
{/* Coverage */}

Coverage