feat: solution for 'Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily)'
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
}
|
||||
+4
-2
@@ -1,10 +1,12 @@
|
||||
import React from 'react';
|
||||
import Comparison from './components/Comparison';
|
||||
import ComparisonTable from './components/ComparisonTable';
|
||||
import './App.css';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<Comparison />
|
||||
<h1>Entity Comparison</h1>
|
||||
<ComparisonTable />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
.comparison-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.comparison-table th,
|
||||
.comparison-table td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.comparison-table th {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.comparison-table tr:nth-child(even) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
.comparison-table tr:hover {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTable } from 'react-table';
|
||||
import { TavilyClient } from '@tavily/tavily-api';
|
||||
import './ComparisonTable.css';
|
||||
|
||||
const ComparisonTable = () => {
|
||||
const [data, setData] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const entities = ['Apple', 'Samsung', 'Google'];
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const client = new TavilyClient({
|
||||
apiKey: process.env.REACT_APP_TAVILY_API_KEY,
|
||||
});
|
||||
|
||||
const results = await Promise.all(
|
||||
entities.map(async (entity) => {
|
||||
const response = await client.search({
|
||||
query: entity,
|
||||
search_type: 'search',
|
||||
});
|
||||
|
||||
// Extract a concise summary from the response
|
||||
const summary =
|
||||
response?.response?.text ||
|
||||
response?.results?.[0]?.text ||
|
||||
'No summary available';
|
||||
|
||||
return { entity, summary };
|
||||
})
|
||||
);
|
||||
|
||||
setData(results);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
setError('Failed to fetch data from Tavily API.');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const columns = React.useMemo(
|
||||
() => [
|
||||
{
|
||||
Header: 'Entity',
|
||||
accessor: 'entity',
|
||||
},
|
||||
{
|
||||
Header: 'Summary',
|
||||
accessor: 'summary',
|
||||
},
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
const {
|
||||
getTableProps,
|
||||
getTableBodyProps,
|
||||
headerGroups,
|
||||
rows,
|
||||
prepareRow,
|
||||
} = useTable({ columns, data });
|
||||
|
||||
if (loading) {
|
||||
return <p>Loading comparison data...</p>;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <p className="error">{error}</p>;
|
||||
}
|
||||
|
||||
return (
|
||||
<table {...getTableProps()} className="comparison-table">
|
||||
<thead>
|
||||
{headerGroups.map((headerGroup) => (
|
||||
<tr {...headerGroup.getHeaderGroupProps()}>
|
||||
{headerGroup.headers.map((column) => (
|
||||
<th {...column.getHeaderProps()}>{column.render('Header')}</th>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</thead>
|
||||
<tbody {...getTableBodyProps()}>
|
||||
{rows.map((row) => {
|
||||
prepareRow(row);
|
||||
return (
|
||||
<tr {...row.getRowProps()}>
|
||||
{row.cells.map((cell) => (
|
||||
<td {...cell.getCellProps()}>{cell.render('Cell')}</td>
|
||||
))}
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
};
|
||||
|
||||
export default ComparisonTable;
|
||||
+3
-2
@@ -1,5 +1,6 @@
|
||||
/* Basic global styles */
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #fafafa;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
+4
-2
@@ -1,9 +1,11 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import App from './App';
|
||||
import './index.css';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
const container = document.getElementById('root');
|
||||
const root = createRoot(container);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
|
||||
Reference in New Issue
Block a user