import React, { useState, useCallback } from 'react'; import { useTranslation } from '@/hooks/useI18n.tsx'; import { useCreateResourceFlow } from '@/hooks/api/useResourcesAPI.ts'; import { useSitesByOrganization } from '@/hooks/api/useSitesAPI.ts'; import Wizard from '@/components/wizard/Wizard.tsx'; import Button from '@/components/ui/Button.tsx'; import { Flex, Stack } from '@/components/ui/layout'; import ErrorMessage from '@/components/ui/ErrorMessage.tsx'; import type { ResourceDirection } from '@/schemas/backend/resource-flow'; interface ResourceFlowWizardProps { isOpen: boolean; onClose: () => void; onSuccess: () => void; organizationId: string; organizationName: string; direction: ResourceDirection; } interface WizardData { siteId: string; type: string; // Step 2: Quality temperature_celsius?: number; pressure_bar?: number; purity_pct?: number; physical_state?: string; // Step 3: Quantity amount: number; unit: string; temporal_unit?: string; // Step 4: Economic cost_in?: number; cost_out?: number; waste_disposal_cost?: number; transportation_cost?: number; // Metadata precision_level: string; source_type: string; } const ResourceFlowWizard: React.FC = ({ isOpen, onClose, onSuccess, organizationId, organizationName, direction, }) => { const { t } = useTranslation(); const createResourceFlowMutation = useCreateResourceFlow(); const { data: sites, isLoading: isLoadingSites } = useSitesByOrganization(organizationId); const [currentStep, setCurrentStep] = useState(1); const [error, setError] = useState(null); const [data, setData] = useState({ siteId: '', type: 'heat', amount: 0, unit: 'MWh', precision_level: 'estimated', source_type: 'declared', }); const totalSteps = 4; const updateData = useCallback((updates: Partial) => { setData(prev => ({ ...prev, ...updates })); }, []); const handleNext = useCallback(() => { if (currentStep < totalSteps) { setCurrentStep(prev => prev + 1); setError(null); } }, [currentStep, totalSteps]); const handlePrevious = useCallback(() => { if (currentStep > 1) { setCurrentStep(prev => prev - 1); setError(null); } }, [currentStep]); const handleSubmit = useCallback(async () => { try { setError(null); const request = { organization_id: organizationId, site_id: data.siteId, direction, type: data.type, quality: { temperature_celsius: data.temperature_celsius, pressure_bar: data.pressure_bar, purity_pct: data.purity_pct, physical_state: data.physical_state, }, quantity: { amount: data.amount, unit: data.unit, temporal_unit: data.temporal_unit, }, economic_data: { cost_in: data.cost_in, cost_out: data.cost_out, waste_disposal_cost: data.waste_disposal_cost, transportation_cost: data.transportation_cost, }, precision_level: data.precision_level, source_type: data.source_type, }; await createResourceFlowMutation.mutateAsync(request); onSuccess(); } catch (err) { setError(err instanceof Error ? err.message : 'An error occurred'); } }, [data, direction, organizationId, createResourceFlowMutation, onSuccess]); const canProceed = useCallback(() => { switch (currentStep) { case 1: return data.siteId && data.type; case 2: return true; // Quality is optional case 3: return data.amount > 0 && data.unit; case 4: return true; // Economic data is optional default: return false; } }, [currentStep, data]); const renderStepContent = () => { switch (currentStep) { case 1: return (
); case 2: return (

{t('resourceFlowWizard.step2.title')}

updateData({ temperature_celsius: parseFloat(e.target.value) || undefined })} className="w-full p-2 border rounded-md" placeholder="°C" />
updateData({ pressure_bar: parseFloat(e.target.value) || undefined })} className="w-full p-2 border rounded-md" placeholder="bar" />
updateData({ purity_pct: parseFloat(e.target.value) || undefined })} className="w-full p-2 border rounded-md" placeholder="%" min="0" max="100" />
); case 3: return (

{t('resourceFlowWizard.step3.title')}

updateData({ amount: parseFloat(e.target.value) || 0 })} className="w-full p-2 border rounded-md" min="0" required />
updateData({ unit: e.target.value })} className="w-full p-2 border rounded-md" placeholder="MWh, kg, m³..." required />
); case 4: return (

{t('resourceFlowWizard.step4.title')}

updateData({ cost_in: parseFloat(e.target.value) || undefined })} className="w-full p-2 border rounded-md" placeholder="€/unit" min="0" />
updateData({ cost_out: parseFloat(e.target.value) || undefined })} className="w-full p-2 border rounded-md" placeholder="€/unit" min="0" />
updateData({ waste_disposal_cost: parseFloat(e.target.value) || undefined })} className="w-full p-2 border rounded-md" placeholder="€/unit" min="0" />
updateData({ transportation_cost: parseFloat(e.target.value) || undefined })} className="w-full p-2 border rounded-md" placeholder="€/km" min="0" />
); default: return null; } }; const wizardTitle = `${direction === 'input' ? t('resourceFlowWizard.titleInput') : t('resourceFlowWizard.titleOutput')} - ${t('resourceFlowWizard.step', { current: currentStep, total: totalSteps })}`; return ( {error && } {renderStepContent()} {currentStep} / {totalSteps} {currentStep < totalSteps ? ( ) : ( )} ); }; export default ResourceFlowWizard;