fedisearch/application/src/pages/feeds.tsx

155 wiersze
5.3 KiB
TypeScript
Czysty Zwykły widok Historia

2022-01-01 19:37:33 +00:00
import Head from 'next/head'
2022-11-03 18:38:01 +00:00
import React, { ReactElement, useEffect, useState } from 'react'
2022-01-01 19:37:33 +00:00
import Loader from '../components/Loader'
import FeedResults from '../components/FeedResults'
2022-01-01 19:37:33 +00:00
import Layout, { siteTitle } from '../components/Layout'
import { matomoConfig } from '../lib/matomoConfig'
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
2022-09-14 19:16:00 +00:00
import { faSearch, faAngleDoubleDown, faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'
import { useRouter } from 'next/router'
2022-09-14 19:16:00 +00:00
import { useQuery } from '@apollo/client'
import {
ListFeedsQuery, ListFeedsResult
} from '../graphql/client/queries/ListFeedsQuery'
import getMatomo from '../lib/getMatomo'
import { feedQueryInputSchema, FeedQueryInputType } from '../graphql/common/types/FeedQueryInput'
import { ListFeedsVariables } from '../graphql/common/queries/listFeeds'
2022-01-01 19:37:33 +00:00
2022-11-03 18:38:01 +00:00
const Feeds: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> = ({ matomoConfig }): ReactElement => {
const router = useRouter()
2022-09-14 19:16:00 +00:00
const routerQuery = feedQueryInputSchema.parse(router.query)
const [page, setPage] = useState<number>(0)
2022-09-14 19:16:00 +00:00
const [query, setQuery] = useState<FeedQueryInputType>(routerQuery)
const [pageLoading, setPageLoading] = useState<boolean>(false)
const { loading, data, error, fetchMore, refetch } = useQuery<ListFeedsResult, ListFeedsVariables>(ListFeedsQuery, {
variables: {
paging: { page: 0 },
query
2022-01-01 19:37:33 +00:00
}
2022-09-14 19:16:00 +00:00
})
2022-11-03 18:38:01 +00:00
useEffect((): void => {
router.push({ query })
2022-11-03 18:38:01 +00:00
.catch((error) => console.error(error))
getMatomo(matomoConfig).trackEvent({
2022-01-01 19:37:33 +00:00
category: 'feeds',
action: 'new-search'
})
2022-09-14 19:16:00 +00:00
}, [query])
useEffect(() => {
getMatomo(matomoConfig).trackEvent({
2022-01-01 19:37:33 +00:00
category: 'feeds',
action: 'next-page',
customDimensions: [
{
value: page.toString(),
id: 1
}
]
})
2022-09-14 19:16:00 +00:00
}, [page])
2022-01-01 19:37:33 +00:00
2022-11-03 18:38:01 +00:00
const handleQueryChange = (event): void => {
const inputElement = event.target
const value = inputElement.value
const name = inputElement.name
const newQuery = {
...query
}
newQuery[name] = value
setQuery(newQuery)
2022-01-01 19:37:33 +00:00
setPage(0)
}
2022-11-03 18:38:01 +00:00
const handleSearchSubmit = async (event): Promise<void> => {
2022-01-01 19:37:33 +00:00
event.preventDefault()
2022-09-14 19:16:00 +00:00
setPageLoading(true)
2022-01-01 19:37:33 +00:00
setPage(0)
2022-09-14 19:16:00 +00:00
await refetch({ paging: { page: 0 } })
setPageLoading(false)
2022-01-01 19:37:33 +00:00
}
2022-11-03 18:38:01 +00:00
const handleLoadMore = async (event): Promise<void> => {
2022-01-01 19:37:33 +00:00
event.preventDefault()
2022-09-14 19:16:00 +00:00
setPageLoading(true)
await fetchMore({
variables: {
paging: { page: page + 1 }
},
updateQuery: (previousData, { fetchMoreResult }) => {
fetchMoreResult.listFeeds.items = [
...previousData.listFeeds.items,
...fetchMoreResult.listFeeds.items
]
return fetchMoreResult
}
})
setPageLoading(false)
2022-01-01 19:37:33 +00:00
setPage(page + 1)
}
return (
<Layout matomoConfig={matomoConfig}>
2022-01-01 19:37:33 +00:00
<Head>
<title>{siteTitle}</title>
</Head>
<h1>People</h1>
2022-01-15 00:59:06 +00:00
<form onSubmit={handleSearchSubmit}>
<div className="input-group mb-3">
<input
name={'search'}
id={'search'}
type={'search'}
onChange={handleQueryChange}
onBlur={handleQueryChange}
value={query.search ?? ''}
placeholder={'Search people on Fediverse'}
className="form-control"
autoFocus={true}
aria-label="Search people on Fediverse"
aria-describedby="search-button"
/>
<button type={'submit'} id={'search-button'} className={'btn btn-primary'}>
<FontAwesomeIcon icon={faSearch} className={'margin-right'}/>
<span>Search</span>
</button>
</div>
2022-01-15 00:59:06 +00:00
</form>
2022-09-14 19:16:00 +00:00
<Loader loading={loading || pageLoading} showBottom={true}>
2022-01-01 19:37:33 +00:00
{
2022-11-03 18:38:01 +00:00
(data != null) && query.search.length > 0
? <FeedResults feeds={data.listFeeds.items}/>
: ''
2022-01-01 19:37:33 +00:00
}
</Loader>
2022-11-03 18:38:01 +00:00
{!loading && !pageLoading && data?.listFeeds?.paging?.hasNext !== undefined && data?.listFeeds?.paging?.hasNext
2022-01-01 19:37:33 +00:00
? (
<div className={'d-flex justify-content-center'}>
<button className={'btn btn-secondary'} onClick={handleLoadMore}>
<FontAwesomeIcon icon={faAngleDoubleDown} className={'margin-right'}/>
<span>Load more</span>
</button>
</div>
2022-01-01 19:37:33 +00:00
)
: ''}
2022-11-03 18:38:01 +00:00
{(error != null)
2022-09-14 19:16:00 +00:00
? (<div className={'d-flex justify-content-center'}>
2022-11-03 18:38:01 +00:00
<FontAwesomeIcon icon={faExclamationTriangle} className={'margin-right'}/>
<span>{error.message}</span>
2022-09-14 19:16:00 +00:00
</div>)
: ''}
2022-01-01 19:37:33 +00:00
</Layout>
)
}
export const getServerSideProps: GetServerSideProps = async () => {
return {
props: {
matomoConfig
}
}
}
2022-02-01 20:54:48 +00:00
export default Feeds