@@ -248,193 +248,61 @@ const ScannerUI = () => {
248248
249249 return (
250250 < div className = "p-8 bg-white min-h-screen" >
251- { /* Main Input Section */ }
252- < div className = "max-w-3xl mx-auto mb-8" >
253- < h1 className = "text-3xl font-bold text-gray-900 mb-4 flex items-center" >
254- < Shield className = "h-8 w-8 mr-2" />
255- SecurityLens
256- </ h1 >
257- < p className = "text-gray-600 mb-6 max-w-2xl" >
258- Scans code for security vulnerabilities including code injection, authentication bypass,
259- SQL injection, XSS, buffer issues, sensitive data exposure, and more. Supports JavaScript,
260- TypeScript, Python, and other languages.
261- </ p >
262-
263- { /* URL Input Section */ }
264- < div className = "bg-gray-50 p-6 rounded-lg shadow-sm mb-4" >
265- < h2 className = "text-lg font-semibold text-gray-700 mb-4" > Scan Repository</ h2 >
266- < div className = "flex gap-4" >
267- < input
268- type = "text"
269- value = { urlInput }
270- onChange = { ( e ) => setUrlInput ( e . target . value ) }
271- placeholder = "Enter GitHub repository URL"
272- className = "flex-1 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
273- />
274- < button
275- onClick = { handleUrlScan }
276- disabled = { scanning || ! urlInput }
277- className = { `px-6 py-2 rounded-md text-white font-medium ${
278- scanning || ! urlInput
279- ? 'bg-gray-400 cursor-not-allowed'
280- : 'bg-blue-600 hover:bg-blue-700'
281- } `}
282- >
283- { scanning ? 'Scanning...' : 'Scan Repository' }
284- </ button >
285- </ div >
286- </ div >
287-
288- { /* File Upload Section */ }
289- < div className = "bg-gray-50 p-6 rounded-lg shadow-sm" >
290- < h2 className = "text-lg font-semibold text-gray-700 mb-4" > Scan Local Files</ h2 >
291- < div className = "flex justify-center" >
251+ < div className = "flex flex-col gap-8 p-8" >
252+ < div className = "flex flex-col gap-4" >
253+ { /* File Upload Section */ }
254+ < div className = "border-2 border-dashed border-gray-300 rounded-lg p-8 text-center" >
292255 < input
293256 type = "file"
294- id = "fileInput"
295257 multiple
296258 onChange = { handleFileUpload }
297259 className = "hidden"
260+ id = "file-upload"
298261 />
299262 < label
300- htmlFor = "fileInput "
301- className = "inline-flex flex-col items-center justify-center px-4 py-6 bg-gray-50 rounded-lg border-2 border-dashed border-gray-300 cursor-pointer hover:bg -gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 "
263+ htmlFor = "file-upload "
264+ className = "cursor-pointer text -gray-600 "
302265 >
303- < div className = "mb-2" >
304- < svg className = "w-12 h-12 text-gray-400" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
305- < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = "2"
306- d = "M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12"
307- />
308- </ svg >
266+ Drag and drop files here, or click to select files
267+ < div className = "text-sm text-gray-500 mt-2" >
268+ Supported files: js, jsx, ts, tsx, py, java, and more
309269 </ div >
310- < p className = "text-gray-600" >
311- Drag and drop files here, or click to select files
312- </ p >
313- < p className = "text-sm text-gray-500 mt-1" >
314- Supported files: .js, .jsx, .ts, .tsx, .py, and more
315- </ p >
316270 </ label >
317271 </ div >
318- </ div >
319272
320- { /* Progress Bar */ }
321- { scanning && progress . total > 0 && (
322- < div className = "mb-6" >
323- < div className = "w-full bg-gray-300 rounded-full h-3" >
324- < div
325- className = "bg-blue-600 h-3 rounded-full transition-all duration-300"
326- style = { { width : `${ ( progress . current / progress . total ) * 100 } %` } }
327- > </ div >
328- </ div >
329- < div className = "text-sm text-gray-700 mt-2 text-center" >
330- { progress . current === progress . total
331- ? 'Processing results...'
332- : `Scanning file ${ progress . current } of ${ progress . total } `
333- }
273+ { /* Progress and Status */ }
274+ { scanning && (
275+ < div className = "text-center" >
276+ < div className = "animate-pulse text-blue-600" >
277+ Scanning... { progress . current } of { progress . total } files
278+ </ div >
334279 </ div >
335- </ div >
336- ) }
280+ ) }
337281
338- { /* Success Message */ }
339- { successMessage && (
340- < Alert className = "mb-4" variant = "default" >
341- < AlertDescription > { successMessage } </ AlertDescription >
342- </ Alert >
343- ) }
344-
345- { /* Error Message */ }
346- { error && (
347- < Alert className = "mb-4" variant = "error" >
348- < AlertDescription >
349- < AlertTriangle className = "h-4 w-4 inline-block mr-2" />
282+ { error && (
283+ < div className = "text-red-600 text-center" >
350284 { error }
351- </ AlertDescription >
352- </ Alert >
353- ) }
285+ </ div >
286+ ) }
354287
355- { /* Rate Limit Info */ }
356- { rateLimitInfo && rateLimitInfo . remaining < 10 && (
357- < Alert className = "mb-4" variant = "warning" >
358- < AlertDescription >
359- Rate limit: { rateLimitInfo . remaining } requests remaining.
360- Resets at { new Date ( rateLimitInfo . reset * 1000 ) . toLocaleTimeString ( ) }
361- </ AlertDescription >
362- </ Alert >
363- ) }
288+ { successMessage && (
289+ < div className = "text-green-600 text-center" >
290+ { successMessage }
291+ </ div >
292+ ) }
293+ </ div >
364294
365295 { /* Scan Results */ }
366- { scanResults && (
367- < ScanResults
368- data = { scanResults }
369- usedCache = { usedCache }
370- onRefreshRequest = { handleUrlScan }
371- scanning = { scanning }
296+ { scanResults && ! scanning && (
297+ < ScanResults
298+ scanResults = { scanResults }
299+ onRefreshRequest = { ( ) => {
300+ setScanResults ( null ) ;
301+ setSuccessMessage ( '' ) ;
302+ } }
372303 />
373304 ) }
374-
375- { /* If user has no token, show a quick form to set one */ }
376- { ! githubToken && (
377- < div className = "bg-gray-50 p-6 rounded-lg shadow-sm mb-4" >
378- < h2 className = "text-lg font-semibold text-gray-700 mb-4" > GitHub Access Token</ h2 >
379- < p className = "text-sm text-gray-600 mb-4" >
380- To scan repositories, you'll need a GitHub personal access token.
381- This stays in your browser and is never sent to any server.
382- </ p >
383- < input
384- type = "password"
385- placeholder = "GitHub token"
386- onChange = { ( e ) => handleTokenSubmit ( e . target . value ) }
387- className = "w-full px-4 py-2 border rounded"
388- />
389- < a
390- href = "https://github.com/settings/tokens/new"
391- target = "_blank"
392- className = "text-sm text-blue-600 hover:underline mt-2 inline-block"
393- >
394- Generate a token
395- </ a >
396- </ div >
397- ) }
398305 </ div >
399-
400- { /* Token Dialog */ }
401- < AlertDialog open = { showTokenDialog } onClose = { ( ) => setShowTokenDialog ( false ) } >
402- < AlertDialogContent >
403- < AlertDialogHeader >
404- < h2 className = "text-lg font-semibold" > GitHub Token Required</ h2 >
405- </ AlertDialogHeader >
406- < div className = "space-y-4" >
407- < div className = "bg-blue-50 border border-blue-200 rounded p-3 text-sm" >
408- < strong > 🔒 Security Note:</ strong > Your token is stored only in your browser's local storage.
409- It never leaves your device and is not sent to any external servers.
410- </ div >
411- < p className = "text-sm text-gray-600" >
412- To scan GitHub repositories, you'll need a Personal Access Token. Here's how to get one:
413- </ p >
414- < ol className = "list-decimal list-inside space-y-2 text-sm" >
415- < li >
416- Go to < a
417- href = "https://github.com/settings/tokens/new"
418- target = "_blank"
419- rel = "noopener noreferrer"
420- className = "text-blue-600 hover:underline"
421- >
422- GitHub Token Settings
423- </ a >
424- </ li >
425- < li > Select either "Classic" or "Fine-grained" token</ li >
426- < li > Enable "repo" access permissions</ li >
427- < li > Generate and copy the token</ li >
428- </ ol >
429- < input
430- type = "password"
431- placeholder = "Paste your GitHub token here"
432- className = "w-full px-4 py-2 border rounded"
433- onChange = { ( e ) => handleTokenSubmit ( e . target . value ) }
434- />
435- </ div >
436- </ AlertDialogContent >
437- </ AlertDialog >
438306 </ div >
439307 ) ;
440308} ;
0 commit comments