Advertisement
Guest User

Validator

a guest
Jan 27th, 2025
13
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.21 KB | None | 0 0
  1. import React, { useState, useCallback } from 'react';
  2. import { Upload, File, AlertCircle, CheckCircle, Download } from 'lucide-react';
  3. import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
  4.  
  5. // Simple ID generator
  6. const generateId = () => Math.random().toString(36).substr(2, 9);
  7.  
  8. const MedicalFormValidator = () => {
  9. const [files, setFiles] = useState([]);
  10. const [validationResults, setValidationResults] = useState([]);
  11. const [isProcessing, setIsProcessing] = useState(false);
  12. const [error, setError] = useState(null);
  13. const [progress, setProgress] = useState(0);
  14.  
  15. // File handling functions
  16. const handleFileDrop = useCallback((e) => {
  17. e.preventDefault();
  18. e.stopPropagation();
  19. const droppedFiles = Array.from(e.dataTransfer?.files || [])
  20. .filter(file => file.type === 'application/pdf');
  21. setFiles(prevFiles => [...prevFiles, ...droppedFiles]);
  22. }, []);
  23.  
  24. const handleFileSelect = useCallback((e) => {
  25. const selectedFiles = Array.from(e.target.files || [])
  26. .filter(file => file.type === 'application/pdf');
  27. setFiles(prevFiles => [...prevFiles, ...selectedFiles]);
  28. }, []);
  29.  
  30. // Mock validation function - replace with actual PDF processing
  31. const validateForms = async () => {
  32. setIsProcessing(true);
  33. setError(null);
  34. setProgress(0);
  35.  
  36. try {
  37. const results = [];
  38.  
  39. for (let i = 0; i < files.length; i++) {
  40. const file = files[i];
  41. setProgress((i / files.length) * 100);
  42.  
  43. // Simulate processing time
  44. await new Promise(resolve => setTimeout(resolve, 1000));
  45.  
  46. // Mock validation results
  47. const mockIssues = [
  48. {
  49. type: 'SIDE_MISMATCH',
  50. description: 'Left shoulder pain indicated but right shoulder treatment selected',
  51. page: 1,
  52. severity: 'high',
  53. suggestions: [
  54. 'Review side selection',
  55. 'Ensure treatment matches affected side'
  56. ]
  57. },
  58. {
  59. type: 'MISSING_TREATMENT',
  60. description: 'No treatment specified for indicated knee pain',
  61. page: 1,
  62. severity: 'medium',
  63. suggestions: [
  64. 'Add treatment plan',
  65. 'Remove if not relevant'
  66. ]
  67. }
  68. ];
  69.  
  70. const report = generateReport(mockIssues);
  71.  
  72. results.push({
  73. fileName: file.name,
  74. status: 'processed',
  75. issues: mockIssues,
  76. report
  77. });
  78. }
  79.  
  80. setValidationResults(results);
  81. } catch (err) {
  82. setError('Error processing files: ' + err.message);
  83. } finally {
  84. setIsProcessing(false);
  85. setProgress(100);
  86. }
  87. };
  88.  
  89. // Generate markdown report
  90. const generateReport = (issues) => {
  91. let report = '# Medical Form Validation Report\n\n';
  92.  
  93. if (issues.length === 0) {
  94. report += '✅ No validation issues found\n';
  95. return report;
  96. }
  97.  
  98. const groupedByType = {};
  99. issues.forEach(issue => {
  100. if (!groupedByType[issue.type]) {
  101. groupedByType[issue.type] = [];
  102. }
  103. groupedByType[issue.type].push(issue);
  104. });
  105.  
  106. Object.entries(groupedByType).forEach(([type, typeIssues]) => {
  107. report += `## ${type}\n\n`;
  108. typeIssues.forEach(issue => {
  109. report += `- ${issue.description}\n`;
  110. if (issue.suggestions?.length) {
  111. report += ' Suggestions:\n';
  112. issue.suggestions.forEach(suggestion => {
  113. report += ` * ${suggestion}\n`;
  114. });
  115. }
  116. report += '\n';
  117. });
  118. });
  119.  
  120. return report;
  121. };
  122.  
  123. // Download report function
  124. const downloadReport = useCallback((result) => {
  125. const blob = new Blob([result.report], { type: 'text/markdown' });
  126. const url = URL.createObjectURL(blob);
  127. const a = document.createElement('a');
  128. a.href = url;
  129. a.download = `validation-report-${result.fileName}.md`;
  130. document.body.appendChild(a);
  131. a.click();
  132. document.body.removeChild(a);
  133. URL.revokeObjectURL(url);
  134. }, []);
  135.  
  136. return (
  137. <div className="w-full max-w-4xl mx-auto p-6">
  138. <div className="mb-8">
  139. <h1 className="text-2xl font-bold mb-2">Medical Form Validator</h1>
  140. <p className="text-gray-600">
  141. Upload medical forms to validate consistency between marked body parts and treatments
  142. </p>
  143. </div>
  144.  
  145. {/* File Upload Area */}
  146. <div
  147. className="border-2 border-dashed border-gray-300 rounded-lg p-8 mb-6 text-center"
  148. onDragOver={(e) => e.preventDefault()}
  149. onDrop={handleFileDrop}
  150. >
  151. <Upload className="mx-auto h-12 w-12 text-gray-400 mb-4" />
  152. <p className="mb-2">Drag and drop PDF files here, or</p>
  153. <label className="inline-block">
  154. <span className="bg-blue-500 text-white px-4 py-2 rounded cursor-pointer hover:bg-blue-600">
  155. Browse Files
  156. </span>
  157. <input
  158. type="file"
  159. className="hidden"
  160. multiple
  161. accept=".pdf"
  162. onChange={handleFileSelect}
  163. />
  164. </label>
  165. </div>
  166.  
  167. {/* Progress Bar */}
  168. {isProcessing && (
  169. <div className="mb-6">
  170. <div className="w-full bg-gray-200 rounded-full h-2">
  171. <div
  172. className="bg-blue-600 h-2 rounded-full transition-all duration-300"
  173. style={{ width: `${progress}%` }}
  174. />
  175. </div>
  176. <p className="text-sm text-gray-600 mt-2">
  177. Processing files... {Math.round(progress)}%
  178. </p>
  179. </div>
  180. )}
  181.  
  182. {/* File List */}
  183. {files.length > 0 && (
  184. <div className="mb-6">
  185. <h2 className="text-lg font-semibold mb-2">Selected Files</h2>
  186. <div className="space-y-2">
  187. {files.map((file, index) => (
  188. <div
  189. key={index}
  190. className="flex items-center p-3 bg-gray-50 rounded"
  191. >
  192. <File className="h-5 w-5 text-gray-500 mr-2" />
  193. <span className="flex-1">{file.name}</span>
  194. <span className="text-sm text-gray-500">
  195. {(file.size / 1024).toFixed(1)} KB
  196. </span>
  197. </div>
  198. ))}
  199. </div>
  200.  
  201. <button
  202. className="mt-4 bg-green-500 text-white px-6 py-2 rounded hover:bg-green-600 disabled:opacity-50"
  203. onClick={validateForms}
  204. disabled={isProcessing}
  205. >
  206. {isProcessing ? 'Processing...' : 'Validate Forms'}
  207. </button>
  208. </div>
  209. )}
  210.  
  211. {/* Error Display */}
  212. {error && (
  213. <Alert variant="destructive" className="mb-6">
  214. <AlertCircle className="h-4 w-4" />
  215. <AlertTitle>Error</AlertTitle>
  216. <AlertDescription>{error}</AlertDescription>
  217. </Alert>
  218. )}
  219.  
  220. {/* Validation Results */}
  221. {validationResults.length > 0 && (
  222. <div className="space-y-4">
  223. <h2 className="text-lg font-semibold">Validation Results</h2>
  224.  
  225. {validationResults.map((result, index) => (
  226. <div key={index} className="border rounded-lg p-4">
  227. <div className="flex items-center justify-between mb-2">
  228. <div className="flex items-center">
  229. <h3 className="text-lg font-medium">{result.fileName}</h3>
  230. {result.issues.length === 0 ? (
  231. <CheckCircle className="h-5 w-5 text-green-500 ml-2" />
  232. ) : (
  233. <AlertCircle className="h-5 w-5 text-red-500 ml-2" />
  234. )}
  235. </div>
  236. <button
  237. onClick={() => downloadReport(result)}
  238. className="flex items-center text-blue-500 hover:text-blue-600"
  239. >
  240. <Download className="h-4 w-4 mr-1" />
  241. Download Report
  242. </button>
  243. </div>
  244.  
  245. {result.issues.length > 0 ? (
  246. <div className="space-y-2">
  247. {result.issues.map((issue, issueIndex) => (
  248. <div
  249. key={issueIndex}
  250. className="bg-red-50 border-l-4 border-red-500 p-3"
  251. >
  252. <p className="text-red-700">{issue.description}</p>
  253. <p className="text-sm text-red-600">
  254. Page {issue.page} - Severity: {issue.severity}
  255. </p>
  256. {issue.suggestions && (
  257. <ul className="mt-2 text-sm text-red-600">
  258. {issue.suggestions.map((suggestion, i) => (
  259. <li key={i}>• {suggestion}</li>
  260. ))}
  261. </ul>
  262. )}
  263. </div>
  264. ))}
  265. </div>
  266. ) : (
  267. <p className="text-green-600">No issues found</p>
  268. )}
  269. </div>
  270. ))}
  271. </div>
  272. )}
  273. </div>
  274. );
  275. };
  276.  
  277. export default MedicalFormValidator;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement