user profile btn in social nav now only is active for current logged in user, added NSFW tag for admin tagged ones, mod search under a specific game, search term and some filters added to url, filter state is saved locally in cache, user search now works #108

Merged
freakoverse merged 21 commits from staging into master 2024-10-30 16:00:24 +00:00
3 changed files with 49 additions and 107 deletions
Showing only changes of commit 7640bdd53b - Show all commits

View File

@ -9,6 +9,7 @@ import '../styles/styles.css'
import { createSearchParams, useNavigate } from 'react-router-dom' import { createSearchParams, useNavigate } from 'react-router-dom'
import { appRoutes } from 'routes' import { appRoutes } from 'routes'
import { scrollIntoView } from 'utils' import { scrollIntoView } from 'utils'
import { SearchInput } from 'components/SearchInput'
export const GamesPage = () => { export const GamesPage = () => {
const scrollTargetRef = useRef<HTMLDivElement>(null) const scrollTargetRef = useRef<HTMLDivElement>(null)
@ -74,8 +75,8 @@ export const GamesPage = () => {
const value = searchTermRef.current?.value || '' // Access the input value from the ref const value = searchTermRef.current?.value || '' // Access the input value from the ref
if (value !== '') { if (value !== '') {
const searchParams = createSearchParams({ const searchParams = createSearchParams({
searchTerm: value, q: value,
searching: 'Games' kind: 'Games'
}) })
navigate({ pathname: appRoutes.search, search: `?${searchParams}` }) navigate({ pathname: appRoutes.search, search: `?${searchParams}` })
} }
@ -100,34 +101,11 @@ export const GamesPage = () => {
<div className='IBMSMTitleMain'> <div className='IBMSMTitleMain'>
<h2 className='IBMSMTitleMainHeading'>Games</h2> <h2 className='IBMSMTitleMainHeading'>Games</h2>
</div> </div>
<div className='SearchMain'> <SearchInput
<div className='SearchMainInside'> ref={searchTermRef}
<div className='SearchMainInsideWrapper'> handleKeyDown={handleKeyDown}
<input handleSearch={handleSearch}
type='text' />
className='SMIWInput'
ref={searchTermRef}
onKeyDown={handleKeyDown}
placeholder='Enter search term'
/>
<button
className='btn btnMain SMIWButton'
type='button'
onClick={handleSearch}
>
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 512 512'
width='1em'
height='1em'
fill='currentColor'
>
<path d='M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z'></path>
</svg>
</button>
</div>
</div>
</div>
</div> </div>
</div> </div>
<div className='IBMSecMain IBMSMListWrapper'> <div className='IBMSecMain IBMSMListWrapper'>

View File

@ -25,6 +25,7 @@ import {
SortBy SortBy
} from '../types' } from '../types'
import { scrollIntoView } from 'utils' import { scrollIntoView } from 'utils'
import { SearchInput } from 'components/SearchInput'
export const ModsPage = () => { export const ModsPage = () => {
const scrollTargetRef = useRef<HTMLDivElement>(null) const scrollTargetRef = useRef<HTMLDivElement>(null)
@ -146,8 +147,8 @@ const PageTitleRow = React.memo(() => {
const value = searchTermRef.current?.value || '' // Access the input value from the ref const value = searchTermRef.current?.value || '' // Access the input value from the ref
if (value !== '') { if (value !== '') {
const searchParams = createSearchParams({ const searchParams = createSearchParams({
searchTerm: value, q: value,
searching: 'Mods' kind: 'Mods'
}) })
navigate({ pathname: appRoutes.search, search: `?${searchParams}` }) navigate({ pathname: appRoutes.search, search: `?${searchParams}` })
} }
@ -166,35 +167,11 @@ const PageTitleRow = React.memo(() => {
<div className='IBMSMTitleMain'> <div className='IBMSMTitleMain'>
<h2 className='IBMSMTitleMainHeading'>Mods</h2> <h2 className='IBMSMTitleMainHeading'>Mods</h2>
</div> </div>
<div className='SearchMain'> <SearchInput
<div className='SearchMainInside'> ref={searchTermRef}
<div className='SearchMainInsideWrapper'> handleKeyDown={handleKeyDown}
<input handleSearch={handleSearch}
type='text' />
className='SMIWInput'
ref={searchTermRef}
onKeyDown={handleKeyDown}
placeholder='Enter search term'
/>
<button
className='btn btnMain SMIWButton'
type='button'
onClick={handleSearch}
>
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 512 512'
width='1em'
height='1em'
fill='currentColor'
>
<path d='M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z'></path>
</svg>
</button>
</div>
</div>
</div>
</div> </div>
</div> </div>
) )

View File

@ -13,6 +13,7 @@ import { ModCard } from 'components/ModCard'
import { ModFilter } from 'components/ModsFilter' import { ModFilter } from 'components/ModsFilter'
import { Pagination } from 'components/Pagination' import { Pagination } from 'components/Pagination'
import { Profile } from 'components/ProfileSection' import { Profile } from 'components/ProfileSection'
import { SearchInput } from 'components/SearchInput'
import { import {
MAX_GAMES_PER_PAGE, MAX_GAMES_PER_PAGE,
MAX_MODS_PER_PAGE, MAX_MODS_PER_PAGE,
@ -59,15 +60,14 @@ enum SearchKindEnum {
export const SearchPage = () => { export const SearchPage = () => {
const scrollTargetRef = useRef<HTMLDivElement>(null) const scrollTargetRef = useRef<HTMLDivElement>(null)
const [searchParams] = useSearchParams() const [searchParams, setSearchParams] = useSearchParams()
const muteLists = useMuteLists() const muteLists = useMuteLists()
const nsfwList = useNSFWList() const nsfwList = useNSFWList()
const searchTermRef = useRef<HTMLInputElement>(null) const searchTermRef = useRef<HTMLInputElement>(null)
const [searchKind, setSearchKind] = useState( const searchKind =
(searchParams.get('searching') as SearchKindEnum) || SearchKindEnum.Mods (searchParams.get('kind') as SearchKindEnum) || SearchKindEnum.Mods
)
const [filterOptions, setFilterOptions] = useState<FilterOptions>({ const [filterOptions, setFilterOptions] = useState<FilterOptions>({
sort: SortBy.Latest, sort: SortBy.Latest,
@ -76,13 +76,21 @@ export const SearchPage = () => {
moderated: ModeratedFilter.Moderated moderated: ModeratedFilter.Moderated
}) })
const [searchTerm, setSearchTerm] = useState( const [searchTerm, setSearchTerm] = useState(searchParams.get('q') || '')
searchParams.get('searchTerm') || ''
)
const handleSearch = () => { const handleSearch = () => {
const value = searchTermRef.current?.value || '' // Access the input value from the ref const value = searchTermRef.current?.value || '' // Access the input value from the ref
setSearchTerm(value) setSearchTerm(value)
if (value) {
searchParams.set('q', value)
} else {
searchParams.delete('q')
}
setSearchParams(searchParams, {
replace: true
})
} }
// Handle "Enter" key press inside the input // Handle "Enter" key press inside the input
@ -109,41 +117,16 @@ export const SearchPage = () => {
</span> </span>
</h2> </h2>
</div> </div>
<div className='SearchMain'> <SearchInput
<div className='SearchMainInside'> handleKeyDown={handleKeyDown}
<div className='SearchMainInsideWrapper'> handleSearch={handleSearch}
<input ref={searchTermRef}
type='text' />
className='SMIWInput'
ref={searchTermRef}
onKeyDown={handleKeyDown}
placeholder='Enter search term'
/>
<button
className='btn btnMain SMIWButton'
type='button'
onClick={handleSearch}
>
<svg
xmlns='http://www.w3.org/2000/svg'
viewBox='0 0 512 512'
width='1em'
height='1em'
fill='currentColor'
>
<path d='M500.3 443.7l-119.7-119.7c27.22-40.41 40.65-90.9 33.46-144.7C401.8 87.79 326.8 13.32 235.2 1.723C99.01-15.51-15.51 99.01 1.724 235.2c11.6 91.64 86.08 166.7 177.6 178.9c53.8 7.189 104.3-6.236 144.7-33.46l119.7 119.7c15.62 15.62 40.95 15.62 56.57 0C515.9 484.7 515.9 459.3 500.3 443.7zM79.1 208c0-70.58 57.42-128 128-128s128 57.42 128 128c0 70.58-57.42 128-128 128S79.1 278.6 79.1 208z'></path>
</svg>
</button>
</div>
</div>
</div>
</div> </div>
</div> </div>
<Filters <Filters
filterOptions={filterOptions} filterOptions={filterOptions}
setFilterOptions={setFilterOptions} setFilterOptions={setFilterOptions}
searchKind={searchKind}
setSearchKind={setSearchKind}
/> />
{searchKind === SearchKindEnum.Mods && ( {searchKind === SearchKindEnum.Mods && (
<ModsResult <ModsResult
@ -173,18 +156,20 @@ export const SearchPage = () => {
type FiltersProps = { type FiltersProps = {
filterOptions: FilterOptions filterOptions: FilterOptions
setFilterOptions: Dispatch<SetStateAction<FilterOptions>> setFilterOptions: Dispatch<SetStateAction<FilterOptions>>
searchKind: SearchKindEnum
setSearchKind: Dispatch<SetStateAction<SearchKindEnum>>
} }
const Filters = React.memo( const Filters = React.memo(
({ ({ filterOptions, setFilterOptions }: FiltersProps) => {
filterOptions,
setFilterOptions,
searchKind,
setSearchKind
}: FiltersProps) => {
const userState = useAppSelector((state) => state.user) const userState = useAppSelector((state) => state.user)
const [searchParams, setSearchParams] = useSearchParams()
const searchKind =
(searchParams.get('kind') as SearchKindEnum) || SearchKindEnum.Mods
const handleChangeSearchKind = (kind: SearchKindEnum) => {
searchParams.set('kind', kind)
setSearchParams(searchParams, {
replace: true
})
}
return ( return (
<div className='IBMSecMain'> <div className='IBMSecMain'>
@ -252,7 +237,7 @@ const Filters = React.memo(
<div <div
key={`searchingFilterItem-${index}`} key={`searchingFilterItem-${index}`}
className='dropdown-item dropdownMainMenuItem' className='dropdown-item dropdownMainMenuItem'
onClick={() => setSearchKind(item)} onClick={() => handleChangeSearchKind(item)}
> >
{item} {item}
</div> </div>
@ -324,6 +309,7 @@ const ModsResult = ({
}, [searchTerm]) }, [searchTerm])
const filteredMods = useMemo(() => { const filteredMods = useMemo(() => {
// Search page requires search term
if (searchTerm === '') return [] if (searchTerm === '') return []
const lowerCaseSearchTerm = searchTerm.toLowerCase() const lowerCaseSearchTerm = searchTerm.toLowerCase()
@ -338,6 +324,7 @@ const ModsResult = ({
) > -1 ) > -1
const filterSourceFn = (mod: ModDetails) => { const filterSourceFn = (mod: ModDetails) => {
// Filter by source if selected
if (filterOptions.source === window.location.host) { if (filterOptions.source === window.location.host) {
return mod.rTag === filterOptions.source return mod.rTag === filterOptions.source
} }