Files
qotnews/webclient/src/Results.js
T
2025-12-16 17:06:53 -07:00

96 lines
2.3 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { Link, useLocation, useHistory } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import queryString from 'query-string';
import { sourceLink, infoLine, logos } from './utils.js';
import AbortController from 'abort-controller';
function Results() {
const [stories, setStories] = useState(false);
const [error, setError] = useState(false);
const location = useLocation();
const history = useHistory();
const handleFilterChange = e => {
const isChecked = e.target.checked;
const currentQuery = queryString.parse(location.search);
if (isChecked) {
currentQuery.article = 'true';
} else {
delete currentQuery.article;
}
history.push('/search?' + queryString.stringify(currentQuery));
};
useEffect(() => {
const controller = new AbortController();
const signal = controller.signal;
const search = location.search;
fetch('/api/search' + search, { method: 'get', signal: signal })
.then(res => res.json())
.then(
(result) => {
setStories(result.hits);
},
(error) => {
if (error.message !== 'The operation was aborted. ') {
setError(true);
}
}
);
return () => {
controller.abort();
};
}, [location.search]);
const searchInArticle = queryString.parse(location.search).article === 'true';
return (
<div className='container'>
<Helmet>
<title>Search Results | QotNews</title>
</Helmet>
<div style={{marginBottom: '1rem'}}>
<input type="checkbox" id="search-in-article" className="checkbox" checked={searchInArticle} onChange={handleFilterChange} />
<label htmlFor="search-in-article">Search in article</label>
</div>
{error && <p>Connection error?</p>}
{stories ?
<>
<p>Search results:</p>
<div className='comment lined'>
{stories.length ?
stories.map(x =>
<div className='item' key={x.id}>
<div className='title'>
<Link className='link' to={'/' + x.id}>
<img className='source-logo' src={logos[x.source]} alt='source logo' /> {x.title}
</Link>
<span className='source'>
({sourceLink(x)})
</span>
</div>
{infoLine(x)}
</div>
)
:
<p>none</p>
}
</div>
</>
:
<p>loading...</p>
}
</div>
);
}
export default Results;