Skip to content
This repository was archived by the owner on Nov 5, 2025. It is now read-only.

Commit c42dc14

Browse files
chore: add button to download python script for verification
1 parent 12de12e commit c42dc14

1 file changed

Lines changed: 86 additions & 6 deletions

File tree

frontend/src/routes/history.$id.tsx

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createFileRoute, Link } from '@tanstack/react-router'
2-
import { CheckCircle2, History, ArrowLeft, Calendar, Hash, Settings, Palette, ExternalLink, Globe } from 'lucide-react'
2+
import { CheckCircle2, History, ArrowLeft, Calendar, Hash, Settings, Palette, ExternalLink, Globe, FileCode, Loader2 } from 'lucide-react'
3+
import { useCallback, useRef, useState, useEffect } from 'react'
34

45
import { Badge } from '@/components/ui/badge'
56
import { Button } from '@/components/ui/button'
@@ -15,6 +16,64 @@ export const Route = createFileRoute('/history/$id')({
1516
params: { path: { id } },
1617
})
1718

19+
const [pythonDownloadStatus, setPythonDownloadStatus] = useState<'idle' | 'loading' | 'success' | 'failed'>('idle')
20+
const pythonDownloadTimeoutRef = useRef<number | null>(null)
21+
22+
const clearPythonStatusTimeout = useCallback(() => {
23+
if (pythonDownloadTimeoutRef.current !== null) {
24+
window.clearTimeout(pythonDownloadTimeoutRef.current)
25+
pythonDownloadTimeoutRef.current = null
26+
}
27+
}, [])
28+
29+
const schedulePythonStatusReset = useCallback(() => {
30+
clearPythonStatusTimeout()
31+
pythonDownloadTimeoutRef.current = window.setTimeout(() => {
32+
setPythonDownloadStatus('idle')
33+
pythonDownloadTimeoutRef.current = null
34+
}, 2000)
35+
}, [clearPythonStatusTimeout])
36+
37+
const handleDownloadPythonScript = useCallback(async () => {
38+
if (!data?.result?.length) return
39+
try {
40+
setPythonDownloadStatus('loading')
41+
clearPythonStatusTimeout()
42+
const searchParams = new URLSearchParams()
43+
if (data.footprint) {
44+
searchParams.set('footprint', data.footprint)
45+
}
46+
data.result.forEach((value: number) => {
47+
searchParams.append('numbers', String(value))
48+
})
49+
const response = await fetch(`/api/random-generator/verify-python-code?${searchParams.toString()}`, {
50+
credentials: 'include',
51+
})
52+
if (!response.ok) {
53+
throw new Error('Failed to download script')
54+
}
55+
const blob = await response.blob()
56+
const url = URL.createObjectURL(blob)
57+
const anchor = document.createElement('a')
58+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
59+
anchor.href = url
60+
anchor.download = `check_${timestamp}.py`
61+
anchor.click()
62+
URL.revokeObjectURL(url)
63+
setPythonDownloadStatus('success')
64+
} catch (error) {
65+
setPythonDownloadStatus('failed')
66+
} finally {
67+
schedulePythonStatusReset()
68+
}
69+
}, [data, clearPythonStatusTimeout, schedulePythonStatusReset])
70+
71+
useEffect(() => {
72+
return () => {
73+
clearPythonStatusTimeout()
74+
}
75+
}, [clearPythonStatusTimeout])
76+
1877

1978
if (isServerPending) {
2079
return (
@@ -140,15 +199,36 @@ export const Route = createFileRoute('/history/$id')({
140199
<CheckCircle2 className="h-4 w-4 text-primary" />
141200
<span className="font-medium text-foreground">Криптографическая подпись</span>
142201
</div>
143-
<Button asChild variant="outline" size="sm">
144-
<Link to="/verify" search={{ footprint: data.footprint, numbers: data.result.join(',') }}>
145-
Проверить подпись
146-
</Link>
147-
</Button>
202+
<div className="flex gap-2">
203+
<Button asChild variant="outline" size="sm">
204+
<Link to="/verify" search={{ footprint: data.footprint, numbers: data.result.join(',') }}>
205+
Проверить подпись
206+
</Link>
207+
</Button>
208+
<Button
209+
variant="outline"
210+
size="sm"
211+
onClick={handleDownloadPythonScript}
212+
disabled={pythonDownloadStatus === 'loading'}
213+
>
214+
{pythonDownloadStatus === 'loading' ? (
215+
<Loader2 className="mr-2 h-4 w-4 animate-spin" aria-hidden />
216+
) : (
217+
<FileCode className="mr-2 h-4 w-4" aria-hidden />
218+
)}
219+
Python-скрипт
220+
</Button>
221+
</div>
148222
</div>
149223
<code className="block rounded-md border border-border/60 bg-background px-3 py-2 text-xs break-all">
150224
{data.footprint}
151225
</code>
226+
{pythonDownloadStatus === 'success' && (
227+
<p className="text-xs text-green-600">Скрипт check.py сохранён.</p>
228+
)}
229+
{pythonDownloadStatus === 'failed' && (
230+
<p className="text-xs text-red-600">Не удалось скачать скрипт. Попробуйте ещё раз.</p>
231+
)}
152232
</div>
153233
)}
154234
</CardContent>

0 commit comments

Comments
 (0)