Skip to content

Commit

Permalink
Merge pull request #54 from alpaca-tc/filter-source-by-name
Browse files Browse the repository at this point in the history
Filter sources by sourceName
  • Loading branch information
alpaca-tc authored May 31, 2024
2 parents 696cd3d + 3c6c7f7 commit 98c8cb6
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 3 deletions.
21 changes: 21 additions & 0 deletions frontend/hooks/useDebounce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { DependencyList, useCallback, useEffect, useRef } from 'react'

export const useDebounce = (callback: () => void, delay: number, dependencies: DependencyList): void => {
const timer = useRef<NodeJS.Timeout>()

const clearDebounce = useCallback(() => {
if (timer.current) {
clearTimeout(timer.current)
timer.current = undefined
}
}, [])

const debounce = useCallback(() => {
clearDebounce()
timer.current = setTimeout(() => {
callback()
}, delay)
}, [callback, clearDebounce, delay])

useEffect(debounce, dependencies)
}
58 changes: 55 additions & 3 deletions frontend/pages/Sources/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,21 @@ import styled from 'styled-components'

import { Link } from '@/components/Link'
import { Loading } from '@/components/Loading'
import { Button, Cluster, EmptyTableBody, FaPencilIcon, Heading, Section, Stack, Table, Td, Text, Th } from '@/components/ui'
import {
Button,
Cluster,
EmptyTableBody,
FaPencilIcon,
FormControl,
Heading,
Input,
Section,
Stack,
Table,
Td,
Text,
Th,
} from '@/components/ui'
import { path } from '@/constants/path'
import { spacing } from '@/constants/theme'
import { useSources } from '@/repositories/sourceRepository'
Expand All @@ -12,6 +26,7 @@ import { Module } from '@/models/module'
import { SourceModulesComboBox } from '@/components/SourceModulesComboBox'
import { UpdateSourceModulesButton } from '@/components/UpdateSourceModulesButton'
import { SourceMemoInput } from '@/components/SourceMemoInput'
import { useDebounce } from '@/hooks/useDebounce'

const sortTypes = ['asc', 'desc', 'none'] as const

Expand Down Expand Up @@ -109,6 +124,23 @@ export const List: FC = () => {
const { data, mutate, isLoading } = useSources()
const [sortState, setSortState] = useState<SortState>({ key: 'sourceName', sort: 'asc' })
const [recentModules, setRecentModules] = useState<Module[]>([])
const [inputSourceName, setInputSourceName] = useState<string>('')
const [filteredSourceName, setFilteredSourceName] = useState<string>('')

const handleInputSourceName = useCallback(
(event: React.ChangeEvent<HTMLInputElement>) => {
setInputSourceName(event.target.value)
},
[setInputSourceName],
)

useDebounce(
() => {
setFilteredSourceName(inputSourceName)
},
200,
[inputSourceName],
)

const setNextSortType = useCallback(
(key: SortState['key']) => {
Expand All @@ -127,12 +159,28 @@ export const List: FC = () => {
)

const sources: Sources['sources'] = useMemo(() => {
console.log(`changed filteredSourceName ${filteredSourceName}`)

if (!data) {
return []
}

return sortSources(data.sources, sortState.key, sortState.sort)
}, [data?.sources, sortState])
let sources = data.sources

if (!/^\s*$/.test(inputSourceName)) {
const words = filteredSourceName
.split(/\s+/)
.map((s) => s.trim().toLowerCase())
.filter((s) => s !== '')

sources = sources.filter((source) => {
const sourceName = source.sourceName.toLowerCase()
return words.every((word) => sourceName.includes(word))
})
}

return sortSources(sources, sortState.key, sortState.sort)
}, [data?.sources, sortState, filteredSourceName])

return (
<StyledSection>
Expand All @@ -144,6 +192,10 @@ export const List: FC = () => {
: null}
</Heading>

<FormControl title="Filtering Sources" helpMessage="Refine the source with a source name">
<Input name="title" type="text" onChange={handleInputSourceName} value={inputSourceName} />
</FormControl>

<div style={{ overflow: 'clip' }}>
<Table fixedHead>
<thead>
Expand Down

0 comments on commit 98c8cb6

Please sign in to comment.