49 lines
2.1 KiB
TypeScript
49 lines
2.1 KiB
TypeScript
|
|
import type { FormEvent } from 'react'
|
||
|
|
import { Search } from 'lucide-react'
|
||
|
|
|
||
|
|
import { ROLE_OPTIONS, roleLabel, STATUS_OPTIONS } from '../../../../constants/user'
|
||
|
|
import type { Role, Status } from '../../../../interfaces/user/model'
|
||
|
|
import styles from './index.module.scss'
|
||
|
|
|
||
|
|
interface DirectoryToolbarProps {
|
||
|
|
keyword: string
|
||
|
|
roleFilter: Role | ''
|
||
|
|
statusFilter: Status | ''
|
||
|
|
hasFilters: boolean
|
||
|
|
onKeywordChange: (value: string) => void
|
||
|
|
onSearch: (event: FormEvent<HTMLFormElement>) => void
|
||
|
|
onRoleChange: (value: Role | '') => void
|
||
|
|
onStatusChange: (value: Status | '') => void
|
||
|
|
onClear: () => void
|
||
|
|
}
|
||
|
|
|
||
|
|
export default function DirectoryToolbar(props: DirectoryToolbarProps) {
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<div className={`filter-toolbar ${styles.root}`}>
|
||
|
|
<form className="search-form" onSubmit={props.onSearch}>
|
||
|
|
<label className="sr-only" htmlFor="user-search">搜索用户</label>
|
||
|
|
<Search className="search-icon" aria-hidden="true" size={18} />
|
||
|
|
<input id="user-search" value={props.keyword} onChange={(event) => props.onKeywordChange(event.target.value)} placeholder="搜索姓名或邮箱" />
|
||
|
|
<button type="submit" className="secondary-button">搜索</button>
|
||
|
|
</form>
|
||
|
|
<div className="filter-group">
|
||
|
|
<label className="sr-only" htmlFor="role-filter">按角色筛选</label>
|
||
|
|
<select id="role-filter" value={props.roleFilter} onChange={(event) => props.onRoleChange(event.target.value as Role | '')}>
|
||
|
|
<option value="">全部角色</option>
|
||
|
|
{ROLE_OPTIONS.map((role) => <option value={role} key={role}>{roleLabel(role)}</option>)}
|
||
|
|
</select>
|
||
|
|
{props.hasFilters && <button className="clear-button" type="button" onClick={props.onClear}>清除筛选</button>}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
<div className="status-tabs" role="group" aria-label="按状态筛选">
|
||
|
|
{STATUS_OPTIONS.map((option) => (
|
||
|
|
<button className={props.statusFilter === option.value ? 'active' : ''} type="button" key={option.value} onClick={() => props.onStatusChange(option.value)}>
|
||
|
|
{option.label}
|
||
|
|
</button>
|
||
|
|
))}
|
||
|
|
</div>
|
||
|
|
</>
|
||
|
|
)
|
||
|
|
}
|