Spaces:
Running
Running
import React, { useState, useEffect } from "react"; | |
import "./App.css"; | |
import Step1 from "./components/Step1"; | |
import Step2 from "./components/Step2"; | |
import Step3 from "./components/Step3"; | |
import Step4 from "./components/Step4"; | |
import { config as appConfig, debugLog } from "./utils/config"; | |
import { ApiService } from "./utils/apiService"; | |
// Make ApiService available globally for debugging | |
if (process.env.NODE_ENV === "development") { | |
window.ApiService = ApiService; | |
} | |
function App() { | |
const [apiKey, setApiKey] = useState(""); | |
const [isApiKeyValid, setIsApiKeyValid] = useState(false); // Explicitly initialized to false | |
const [uploadedFile, setUploadedFile] = useState(null); | |
const [s3Link, setS3Link] = useState(""); | |
const [fileMetadata, setFileMetadata] = useState({ | |
fileSizeBytes: 0, | |
sourceFileRows: 0, | |
}); | |
const [config, setConfig] = useState({ | |
numRows: appConfig.defaultNumRecords, | |
targetColumn: "", | |
}); | |
const [generatedDataLink, setGeneratedDataLink] = useState(""); | |
// Check for previously stored and valid API key on app load | |
useEffect(() => { | |
const checkStoredApiKey = async () => { | |
try { | |
debugLog("Checking for stored API key on app initialization"); | |
const storedKeyStatus = await ApiService.verifyStoredApiKey(); | |
if (storedKeyStatus.valid) { | |
setIsApiKeyValid(true); | |
debugLog("Valid stored API key found", storedKeyStatus); | |
} else { | |
setIsApiKeyValid(false); | |
debugLog("No valid stored API key", storedKeyStatus); | |
} | |
} catch (error) { | |
debugLog("Error checking stored API key", error); | |
setIsApiKeyValid(false); | |
} | |
}; | |
checkStoredApiKey(); | |
}, []); | |
// Log app initialization in debug mode | |
useEffect(() => { | |
debugLog("Syncora app initialized", { | |
defaultNumRecords: appConfig.defaultNumRecords, | |
maxFileSizeMB: appConfig.maxFileSizeMB, | |
apiBaseUrl: appConfig.apiBaseUrl, | |
}); | |
}, []); | |
const steps = [ | |
{ number: 1, title: "API Key Validation", component: Step1, icon: "π" }, | |
{ number: 2, title: "Upload Files", component: Step2, icon: "π" }, | |
{ number: 3, title: "Configuration", component: Step3, icon: "βοΈ" }, | |
{ number: 4, title: "Generate Data", component: Step4, icon: "π" }, | |
]; | |
// Helper function to check if a step should be enabled | |
const isStepEnabled = (stepNumber) => { | |
switch (stepNumber) { | |
case 1: | |
return true; // Step 1 is always enabled | |
case 2: | |
const step2Enabled = isApiKeyValid; | |
debugLog(`Step 2 enabled check: ${step2Enabled}`, { | |
isApiKeyValid, | |
apiKeyLength: apiKey.length, | |
hasApiKey: !!apiKey, | |
}); | |
return step2Enabled; // Step 2 enabled when API key is valid | |
case 3: | |
return isApiKeyValid && uploadedFile && s3Link; // Step 3 enabled when file is uploaded | |
case 4: | |
return isApiKeyValid && uploadedFile && s3Link && config.targetColumn; // Step 4 enabled when config is complete | |
default: | |
return false; | |
} | |
}; | |
const renderStep = (stepNumber) => { | |
const step = steps[stepNumber - 1]; | |
const StepComponent = step.component; | |
const enabled = isStepEnabled(stepNumber); | |
return ( | |
<div className={`step-wrapper ${enabled ? "enabled" : "disabled"}`}> | |
<StepComponent | |
apiKey={apiKey} | |
setApiKey={setApiKey} | |
isApiKeyValid={isApiKeyValid} | |
setIsApiKeyValid={setIsApiKeyValid} | |
uploadedFile={uploadedFile} | |
setUploadedFile={setUploadedFile} | |
s3Link={s3Link} | |
setS3Link={setS3Link} | |
fileMetadata={fileMetadata} | |
setFileMetadata={setFileMetadata} | |
config={config} | |
setConfig={setConfig} | |
generatedDataLink={generatedDataLink} | |
setGeneratedDataLink={setGeneratedDataLink} | |
stepNumber={stepNumber} | |
stepTitle={step.title} | |
stepIcon={step.icon} | |
enabled={enabled} | |
/> | |
</div> | |
); | |
}; | |
return ( | |
<div className="App"> | |
<header className="app-header"> | |
<div className="header-content"> | |
<div> | |
<h1>Syncora</h1> | |
<p>AI-Powered Data Generation Platform</p> | |
</div> | |
<div className="progress-indicator"> | |
{steps.map((step, index) => { | |
const stepNumber = step.number; | |
const isEnabled = isStepEnabled(stepNumber); | |
const isCompleted = | |
stepNumber < steps.length | |
? isStepEnabled(stepNumber + 1) | |
: stepNumber === 4 && generatedDataLink; | |
return ( | |
<div | |
key={step.number} | |
className={`progress-step ${ | |
isCompleted | |
? "completed" | |
: isEnabled | |
? "active" | |
: "disabled" | |
}`} | |
title={`Step ${step.number}: ${step.title}`} | |
/> | |
); | |
})} | |
</div> | |
</div> | |
</header> | |
<div className="main-container"> | |
{/* Left Column */} | |
<div className="steps-column"> | |
{/* Step 1 */} | |
<div className="step-content">{renderStep(1)}</div> | |
{/* Step 2 */} | |
<div className="step-content">{renderStep(2)}</div> | |
</div> | |
{/* Right Column */} | |
<div className="steps-column"> | |
{/* Step 3 */} | |
<div className="step-content">{renderStep(3)}</div> | |
{/* Step 4 */} | |
<div className="step-content">{renderStep(4)}</div> | |
</div> | |
</div> | |
{/* Floating Help Button */} | |
<button | |
className="floating-help" | |
onClick={() => window.open("https://docs.syncora.ai/help", "_blank")} | |
title="Get Help" | |
> | |
? | |
</button> | |
</div> | |
); | |
} | |
export default App; | |