292 lines
11 KiB
JavaScript
292 lines
11 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import useProjectStore from '../../store/projectStore';
|
|
|
|
export default function BusinessQuestionsScreen() {
|
|
const [businessQuestions, setBusinessQuestions] = useState([]);
|
|
const [businessAnswers, setBusinessAnswers] = useState({});
|
|
const [isLoadingQuestions, setIsLoadingQuestions] = useState(true);
|
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
const [error, setError] = useState(null);
|
|
|
|
const { selectedFeatures, setCurrentStep, projectName, projectType } = useProjectStore();
|
|
|
|
// Load business questions when component mounts
|
|
useEffect(() => {
|
|
loadBusinessQuestions();
|
|
}, []);
|
|
|
|
const loadBusinessQuestions = async () => {
|
|
try {
|
|
setIsLoadingQuestions(true);
|
|
setError(null);
|
|
|
|
if (selectedFeatures.length === 0) {
|
|
setError('No features found to generate business questions');
|
|
return;
|
|
}
|
|
|
|
console.log('🚀 Generating comprehensive business questions for integrated system:', selectedFeatures);
|
|
|
|
// Call the new comprehensive endpoint
|
|
// Prefer an environment-provided backend URL for frontend builds (REACT_APP_BACKEND_URL or NEXT_PUBLIC_BACKEND_URL).
|
|
const backendBase = (process.env.REACT_APP_BACKEND_URL || process.env.NEXT_PUBLIC_BACKEND_URL || '').replace(/\/$/, '') || '';
|
|
const getApiUrl = (endpoint) => {
|
|
const clean = endpoint.startsWith('/') ? endpoint.slice(1) : endpoint;
|
|
if (backendBase) return `${backendBase}/${clean}`;
|
|
// Fallback to relative path (assumes frontend is served with proxy to backend)
|
|
return `/${clean}`;
|
|
};
|
|
|
|
const response = await fetch(getApiUrl('api/v1/generate-comprehensive-business-questions'), {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
allFeatures: selectedFeatures, // Send ALL features with their logic rules
|
|
projectName: projectName,
|
|
projectType: projectType,
|
|
totalFeatures: selectedFeatures.length
|
|
}),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
console.log('✅ Comprehensive business questions response:', data);
|
|
|
|
if (data.success && data.data.businessQuestions) {
|
|
setBusinessQuestions(data.data.businessQuestions);
|
|
|
|
// Initialize answers object
|
|
const initialAnswers = {};
|
|
data.data.businessQuestions.forEach((question, index) => {
|
|
initialAnswers[index] = '';
|
|
});
|
|
setBusinessAnswers(initialAnswers);
|
|
|
|
console.log(`🎯 Generated ${data.data.businessQuestions.length} comprehensive questions for integrated system`);
|
|
} else {
|
|
setError('Failed to generate comprehensive business questions');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error loading comprehensive business questions:', error);
|
|
setError(`Failed to load business questions: ${error.message}`);
|
|
} finally {
|
|
setIsLoadingQuestions(false);
|
|
}
|
|
};
|
|
|
|
const handleAnswerChange = (questionIndex, answer) => {
|
|
setBusinessAnswers(prev => ({
|
|
...prev,
|
|
[questionIndex]: answer
|
|
}));
|
|
};
|
|
|
|
const handleSubmit = async () => {
|
|
try {
|
|
setIsSubmitting(true);
|
|
|
|
// Validate that at least some questions are answered
|
|
const answeredQuestions = Object.values(businessAnswers).filter(answer => answer.trim()).length;
|
|
|
|
if (answeredQuestions === 0) {
|
|
alert('Please answer at least one question before proceeding.');
|
|
return;
|
|
}
|
|
|
|
// Prepare complete data for tech stack selector - use ALL features data
|
|
const completeData = {
|
|
// System-wide information
|
|
projectName: projectName,
|
|
projectType: projectType,
|
|
allFeatures: selectedFeatures, // Include ALL features
|
|
businessQuestions: businessQuestions,
|
|
businessAnswers: businessAnswers,
|
|
timestamp: new Date().toISOString(),
|
|
|
|
// For backward compatibility with tech-stack-selector
|
|
featureName: `${projectName} - Integrated System`,
|
|
description: `Complete ${projectType} system with ${selectedFeatures.length} integrated features`,
|
|
requirements: selectedFeatures.flatMap(f => f.requirements || []),
|
|
complexity: selectedFeatures.some(f => f.complexity === 'high') ? 'high' :
|
|
selectedFeatures.some(f => f.complexity === 'medium') ? 'medium' : 'low',
|
|
logicRules: selectedFeatures.flatMap(f => f.logicRules || [])
|
|
};
|
|
|
|
console.log('🚀 Sending comprehensive system data to tech stack selector:', completeData);
|
|
|
|
// Call enhanced tech stack selector directly
|
|
const response = await fetch('https://backend.codenuk.com/api/v1/select', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify(completeData),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
const techRecommendations = await response.json();
|
|
console.log('✅ Tech stack recommendations received:', techRecommendations);
|
|
|
|
// Store results in project store
|
|
useProjectStore.setState({
|
|
finalProjectData: completeData,
|
|
techStackRecommendations: techRecommendations,
|
|
businessQuestionsCompleted: true
|
|
});
|
|
|
|
// Move to summary step to show recommendations
|
|
setCurrentStep('summary');
|
|
|
|
} catch (error) {
|
|
console.error('❌ Error calling tech stack selector:', error);
|
|
alert(`Failed to get technology recommendations: ${error.message}`);
|
|
} finally {
|
|
setIsSubmitting(false);
|
|
}
|
|
};
|
|
|
|
const handleBack = () => {
|
|
setCurrentStep('features');
|
|
};
|
|
|
|
if (isLoadingQuestions) {
|
|
return (
|
|
<div className="flex items-center justify-center min-h-96">
|
|
<div className="text-center">
|
|
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
|
|
<p className="text-gray-600">🧠 AI is generating comprehensive business questions...</p>
|
|
<p className="text-gray-500 text-sm mt-2">Analyzing {selectedFeatures.length} features as integrated system</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="text-center py-12">
|
|
<div className="bg-red-50 border border-red-200 rounded-lg p-6 max-w-md mx-auto">
|
|
<h3 className="text-red-900 font-semibold mb-2">Error Loading Questions</h3>
|
|
<p className="text-red-700 text-sm mb-4">{error}</p>
|
|
<div className="space-x-3">
|
|
<button
|
|
onClick={loadBusinessQuestions}
|
|
className="bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700 transition-colors"
|
|
>
|
|
Try Again
|
|
</button>
|
|
<button
|
|
onClick={handleBack}
|
|
className="bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 transition-colors"
|
|
>
|
|
Go Back
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="text-center">
|
|
<h2 className="text-2xl font-semibold text-gray-900 mb-2">
|
|
📋 Business Context Questions
|
|
</h2>
|
|
<p className="text-gray-600">
|
|
Help us recommend the best technology stack by answering these questions
|
|
</p>
|
|
<p className="text-sm text-blue-600 mt-1">
|
|
Analyzing your complete {projectType} system with {selectedFeatures.length} integrated features
|
|
</p>
|
|
</div>
|
|
|
|
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
|
<div className="flex items-start space-x-2">
|
|
<span className="text-blue-600 text-lg">💡</span>
|
|
<div>
|
|
<p className="text-blue-800 text-sm">
|
|
<strong>Tip:</strong> Answer as many questions as possible for better technology recommendations.
|
|
You can skip questions you're unsure about. These questions consider your entire system, not individual features.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-6">
|
|
{businessQuestions.map((question, index) => (
|
|
<div key={index} className="bg-white border border-gray-200 rounded-lg p-6">
|
|
<label className="block text-sm font-medium text-gray-900 mb-3">
|
|
<span className="inline-flex items-center space-x-2">
|
|
<span className="bg-blue-100 text-blue-600 rounded-full w-6 h-6 flex items-center justify-center text-sm font-medium">
|
|
{index + 1}
|
|
</span>
|
|
<span>{question}</span>
|
|
</span>
|
|
</label>
|
|
|
|
<textarea
|
|
value={businessAnswers[index] || ''}
|
|
onChange={(e) => handleAnswerChange(index, e.target.value)}
|
|
placeholder="Your answer..."
|
|
rows={3}
|
|
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
/>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Progress Summary */}
|
|
<div className="bg-gray-50 border border-gray-200 rounded-lg p-4">
|
|
<h4 className="font-medium text-gray-900 mb-2">Progress Summary</h4>
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-sm text-gray-600">
|
|
<div>
|
|
<p><strong>Questions answered:</strong> {Object.values(businessAnswers).filter(answer => answer.trim()).length} of {businessQuestions.length}</p>
|
|
</div>
|
|
<div>
|
|
<p><strong>Completion:</strong> {Math.round((Object.values(businessAnswers).filter(answer => answer.trim()).length / businessQuestions.length) * 100)}%</p>
|
|
</div>
|
|
<div>
|
|
<p><strong>Features analyzing:</strong> {selectedFeatures.length} integrated features</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Action Buttons */}
|
|
<div className="flex justify-between pt-6 border-t border-gray-200">
|
|
<button
|
|
onClick={handleBack}
|
|
className="px-6 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors"
|
|
>
|
|
← Back to Features
|
|
</button>
|
|
|
|
<button
|
|
onClick={handleSubmit}
|
|
disabled={isSubmitting || Object.values(businessAnswers).filter(answer => answer.trim()).length === 0}
|
|
className={`px-6 py-2 rounded-md font-medium transition-colors ${isSubmitting || Object.values(businessAnswers).filter(answer => answer.trim()).length === 0
|
|
? 'bg-gray-300 text-gray-500 cursor-not-allowed'
|
|
: 'bg-green-600 text-white hover:bg-green-700'
|
|
}`}
|
|
>
|
|
{isSubmitting ? (
|
|
<div className="flex items-center space-x-2">
|
|
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-white"></div>
|
|
<span>Getting System Recommendations...</span>
|
|
</div>
|
|
) : (
|
|
'Generate Technology Recommendations →'
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |