diff --git a/backend/server.js b/backend/server.js index b7f07b9..f1cbfda 100644 --- a/backend/server.js +++ b/backend/server.js @@ -126,6 +126,23 @@ app.post('/api/asns', async (req, res) => { } }); +// Новый эндпоинт для получения дат последнего изменения файлов S3 +app.get('/api/s3/last-modified', async (req, res) => { + try { + const [domainsHead, asnsHead] = await Promise.all([ + s3.headObject({ Bucket: BUCKET_NAME, Key: 'domains.txt' }).promise(), + s3.headObject({ Bucket: BUCKET_NAME, Key: 'asns.txt' }).promise() + ]); + res.json({ + domainsLastModified: domainsHead.LastModified ? domainsHead.LastModified.toISOString() : null, + asnsLastModified: asnsHead.LastModified ? asnsHead.LastModified.toISOString() : null + }); + } catch (error) { + console.error(error); + res.status(500).send('Error fetching last modified dates from S3'); + } +}); + // The "catchall" handler: for any request that doesn't // match one above, send back React's index.html file. app.get('*', (req, res) => { diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index ebb3c2e..088af32 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { Container } from 'react-bootstrap'; import { IconBrandTabler, @@ -19,6 +19,7 @@ import { } from '@tabler/icons-react'; import DataManager from './DataManager'; import './App.css'; +import axios from 'axios'; function App() { const [activeTab, setActiveTab] = useState('dashboard'); @@ -171,34 +172,60 @@ function StatCard({ icon: Icon, color, value, title, subtitle }) { } function Dashboard() { + const [stats, setStats] = useState({ domainsCount: null, asnsCount: null, lastModified: null }); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function fetchStats() { + setLoading(true); + try { + const [domainsRes, asnsRes, s3Res] = await Promise.all([ + axios.get('/api/domains'), + axios.get('/api/asns'), + axios.get('/api/s3/last-modified') + ]); + setStats({ + domainsCount: domainsRes.data.length, + asnsCount: asnsRes.data.length, + lastModified: s3Res.data.domainsLastModified + }); + } catch (e) { + setStats({ domainsCount: null, asnsCount: null, lastModified: null }); + } finally { + setLoading(false); + } + } + fetchStats(); + }, []); + return (