Spaces:
Running
Running
import React, { useState, useEffect } from 'react'; | |
import { useParams, useNavigate } from 'react-router-dom'; | |
import { ArrowLeft, Brain, Cpu, Loader2 } from 'lucide-react'; | |
import ReactMarkdown from 'react-markdown'; | |
// Import markdown content | |
import linearRegressionMd from '../docs/linear_regression.md?raw'; | |
import cnnMd from '../docs/cnn.md?raw'; | |
const AlgorithmDetail: React.FC = () => { | |
const { algorithmId } = useParams<{ algorithmId: string }>(); | |
const navigate = useNavigate(); | |
const [markdownContent, setMarkdownContent] = useState<string>(''); | |
const [loading, setLoading] = useState(true); | |
const [error, setError] = useState<string | null>(null); | |
useEffect(() => { | |
loadMarkdownContent(); | |
}, [algorithmId]); | |
const loadMarkdownContent = async () => { | |
try { | |
setLoading(true); | |
setError(null); | |
let content = ''; | |
switch (algorithmId) { | |
case 'linear_regression': | |
content = linearRegressionMd; | |
break; | |
case 'cnn': | |
content = cnnMd; | |
break; | |
default: | |
setError('Algorithm documentation not found'); | |
setLoading(false); | |
return; | |
} | |
setMarkdownContent(content); | |
} catch (err) { | |
setError('Failed to load algorithm documentation'); | |
} finally { | |
setLoading(false); | |
} | |
}; | |
const getAlgorithmInfo = () => { | |
switch (algorithmId) { | |
case 'linear_regression': | |
return { | |
name: 'Linear Regression', | |
category: 'Classical ML', | |
icon: <Brain className="h-8 w-8 text-blue-600" />, | |
categoryColor: 'bg-blue-100 text-blue-800' | |
}; | |
case 'cnn': | |
return { | |
name: 'Convolutional Neural Network', | |
category: 'Deep Learning', | |
icon: <Cpu className="h-8 w-8 text-purple-600" />, | |
categoryColor: 'bg-purple-100 text-purple-800' | |
}; | |
default: | |
return { | |
name: 'Unknown Algorithm', | |
category: 'Unknown', | |
icon: <Brain className="h-8 w-8 text-gray-600" />, | |
categoryColor: 'bg-gray-100 text-gray-800' | |
}; | |
} | |
}; | |
const algorithmInfo = getAlgorithmInfo(); | |
if (loading) { | |
return ( | |
<div className="max-w-4xl mx-auto"> | |
<button | |
onClick={() => navigate(-1)} | |
className="mb-6 flex items-center text-blue-600 hover:text-blue-800 transition-colors" | |
> | |
<ArrowLeft className="h-4 w-4 mr-2" /> | |
Back | |
</button> | |
<div className="flex justify-center items-center h-64"> | |
<Loader2 className="h-8 w-8 animate-spin text-blue-600" /> | |
<span className="ml-2 text-gray-600">Loading documentation...</span> | |
</div> | |
</div> | |
); | |
} | |
if (error) { | |
return ( | |
<div className="max-w-4xl mx-auto"> | |
<button | |
onClick={() => navigate(-1)} | |
className="mb-6 flex items-center text-blue-600 hover:text-blue-800 transition-colors" | |
> | |
<ArrowLeft className="h-4 w-4 mr-2" /> | |
Back | |
</button> | |
<div className="bg-white rounded-lg shadow-md p-8 text-center"> | |
<h1 className="text-2xl font-bold text-gray-900 mb-4">Documentation Not Available</h1> | |
<p className="text-gray-600 mb-4">{error}</p> | |
<button | |
onClick={loadMarkdownContent} | |
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors" | |
> | |
Try Again | |
</button> | |
</div> | |
</div> | |
); | |
} | |
return ( | |
<div className="max-w-4xl mx-auto"> | |
<button | |
onClick={() => navigate(-1)} | |
className="mb-6 flex items-center text-blue-600 hover:text-blue-800 transition-colors" | |
> | |
<ArrowLeft className="h-4 w-4 mr-2" /> | |
Back | |
</button> | |
{/* Algorithm Header */} | |
<div className="bg-white rounded-lg shadow-md p-6 mb-6"> | |
<div className="flex items-center justify-between"> | |
<div className="flex items-center"> | |
{algorithmInfo.icon} | |
<div className="ml-4"> | |
<h1 className="text-2xl font-bold text-gray-900">{algorithmInfo.name}</h1> | |
</div> | |
</div> | |
<span className={`px-3 py-1 rounded-full text-sm font-semibold ${algorithmInfo.categoryColor}`}> | |
{algorithmInfo.category} | |
</span> | |
</div> | |
</div> | |
{/* Markdown Content */} | |
<div className="bg-white rounded-lg shadow-md p-8"> | |
<div className="prose prose-lg max-w-none"> | |
<ReactMarkdown | |
components={{ | |
h1: ({ children }) => ( | |
<h1 className="text-3xl font-bold text-gray-900 mb-6 border-b-2 border-gray-200 pb-2"> | |
{children} | |
</h1> | |
), | |
h2: ({ children }) => ( | |
<h2 className="text-2xl font-semibold text-gray-900 mt-8 mb-4 border-b border-gray-200 pb-2"> | |
{children} | |
</h2> | |
), | |
h3: ({ children }) => ( | |
<h3 className="text-xl font-semibold text-gray-900 mt-6 mb-3"> | |
{children} | |
</h3> | |
), | |
h4: ({ children }) => ( | |
<h4 className="text-lg font-semibold text-gray-900 mt-4 mb-2"> | |
{children} | |
</h4> | |
), | |
p: ({ children }) => ( | |
<p className="text-gray-700 leading-relaxed mb-4"> | |
{children} | |
</p> | |
), | |
ul: ({ children }) => ( | |
<ul className="list-disc list-outside text-gray-700 mb-4 space-y-2 ml-6"> | |
{children} | |
</ul> | |
), | |
ol: ({ children }) => ( | |
<ol className="list-decimal list-outside text-gray-700 mb-4 space-y-2 ml-6"> | |
{children} | |
</ol> | |
), | |
li: ({ children }) => ( | |
<li className="pl-2"> | |
{children} | |
</li> | |
), | |
code: ({ children, className }) => { | |
const isBlock = className?.includes('language-'); | |
if (isBlock) { | |
return ( | |
<pre className="bg-gray-50 border border-gray-200 rounded-lg p-4 mb-4 overflow-x-auto"> | |
<code className="text-sm font-mono text-gray-800"> | |
{children} | |
</code> | |
</pre> | |
); | |
} | |
return ( | |
<code className="bg-gray-100 px-2 py-1 rounded text-sm font-mono text-gray-800"> | |
{children} | |
</code> | |
); | |
}, | |
blockquote: ({ children }) => ( | |
<blockquote className="border-l-4 border-blue-500 pl-4 italic text-gray-600 mb-4"> | |
{children} | |
</blockquote> | |
), | |
strong: ({ children }) => ( | |
<strong className="font-semibold text-gray-900"> | |
{children} | |
</strong> | |
), | |
em: ({ children }) => ( | |
<em className="italic text-gray-700"> | |
{children} | |
</em> | |
), | |
table: ({ children }) => ( | |
<div className="overflow-x-auto mb-4"> | |
<table className="min-w-full divide-y divide-gray-200"> | |
{children} | |
</table> | |
</div> | |
), | |
thead: ({ children }) => ( | |
<thead className="bg-gray-50"> | |
{children} | |
</thead> | |
), | |
tbody: ({ children }) => ( | |
<tbody className="bg-white divide-y divide-gray-200"> | |
{children} | |
</tbody> | |
), | |
tr: ({ children }) => ( | |
<tr> | |
{children} | |
</tr> | |
), | |
th: ({ children }) => ( | |
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"> | |
{children} | |
</th> | |
), | |
td: ({ children }) => ( | |
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900"> | |
{children} | |
</td> | |
) | |
}} | |
> | |
{markdownContent} | |
</ReactMarkdown> | |
</div> | |
</div> | |
</div> | |
); | |
}; | |
export default AlgorithmDetail; |