feat: add "Mostrar apenas as minhas" checkbox to task filters

Adds a pre-checked checkbox next to the employee filter that
automatically filters tasks to the logged-in user on page load.
Unchecking restores the free-select dropdown behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gabriel Santana de Menezes 2026-05-20 15:51:40 -04:00
parent f01d72c2bb
commit 119d896a59
3 changed files with 79 additions and 16 deletions

View file

@ -22,6 +22,7 @@ interface TaskFilterBarProps {
projects: Project[]
categories: Category[]
assignees: TaskAssignee[]
currentUserId?: number
isLoading?: boolean
onRefresh?: () => void
}
@ -32,6 +33,7 @@ export function TaskFilterBar({
projects,
categories,
assignees,
currentUserId,
isLoading,
onRefresh,
}: TaskFilterBarProps) {
@ -98,7 +100,22 @@ export function TaskFilterBar({
</div>
{assignees.length > 0 && (
<div className="grid gap-3">
<div className="grid gap-2">
{currentUserId !== undefined && (
<label className="flex cursor-pointer items-center gap-2 self-start">
<input
type="checkbox"
checked={filters.userIds.length === 1 && filters.userIds[0] === currentUserId}
onChange={(e) =>
update({ userIds: e.target.checked ? [currentUserId] : [] })
}
className="h-4 w-4 accent-brand"
/>
<span className="text-xs font-semibold text-text-muted">
Mostrar apenas as minhas
</span>
</label>
)}
<MultiSelectDropdown
label="Funcionario"
allLabel="Todos os funcionarios"

View file

@ -16,6 +16,7 @@ import { Link, useNavigate } from 'react-router-dom'
import { taskService } from '../services/taskService'
import type { Project } from '../services/projectService'
import { categoryService } from '../services/categoryService'
import { organizationService } from '../services/organizationService'
import type { Category } from '../types/category'
import { cn } from '../lib/utils'
import type { TaskAssignee, TaskResponse, TaskStatus } from '../types/task'
@ -63,6 +64,7 @@ export function TaskBoardPage() {
const [categories, setCategories] = useState<Category[]>([])
const [assignees, setAssignees] = useState<TaskAssignee[]>([])
const [filters, setFilters] = useState<TaskFilters>(DEFAULT_TASK_FILTERS)
const [currentUserAssigneeId, setCurrentUserAssigneeId] = useState<number | null>(null)
const navigate = useNavigate()
const { activeOrg, user } = useAuth()
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)
@ -95,12 +97,38 @@ export function TaskBoardPage() {
useEffect(() => {
if (!activeOrg) return
setFilters(DEFAULT_TASK_FILTERS)
setProjects([])
setAssignees([])
setCategories([])
void loadTasks(DEFAULT_TASK_FILTERS)
categoryService.listByOrganization(activeOrg.id).then(setCategories).catch(() => {})
const init = async () => {
setFilters(DEFAULT_TASK_FILTERS)
setProjects([])
setAssignees([])
setCategories([])
const [members] = await Promise.all([
organizationService.listMembers(activeOrg.id),
categoryService.listByOrganization(activeOrg.id).then(setCategories).catch(() => {}),
])
const assigneesData = members.map((m) => ({
id: m.userId,
name: m.userName,
email: m.userEmail,
photo: m.userPhoto ?? null,
}))
setAssignees(assigneesData)
const currentMember = members.find((m) => m.userEmail === user?.email)
const userId = currentMember?.userId ?? null
setCurrentUserAssigneeId(userId)
const initialFilters = userId
? { ...DEFAULT_TASK_FILTERS, userIds: [userId] }
: DEFAULT_TASK_FILTERS
setFilters(initialFilters)
void loadTasks(initialFilters)
}
void init()
}, [activeOrg])
const handleFiltersChange = (newFilters: TaskFilters) => {
@ -182,6 +210,7 @@ export function TaskBoardPage() {
projects={projects}
categories={categories}
assignees={assignees}
currentUserId={currentUserAssigneeId ?? undefined}
isLoading={isLoading}
onRefresh={() => void loadTasks(filters)}
/>

View file

@ -94,6 +94,7 @@ export function TaskListPage() {
const [categories, setCategories] = useState<Category[]>([])
const [assignees, setAssignees] = useState<TaskAssignee[]>([])
const [filters, setFilters] = useState<TaskFilters>(DEFAULT_TASK_FILTERS)
const [currentUserAssigneeId, setCurrentUserAssigneeId] = useState<number | null>(null)
const navigate = useNavigate()
const { activeOrg, user } = useAuth()
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)
@ -126,22 +127,37 @@ export function TaskListPage() {
useEffect(() => {
if (!activeOrg) return
setFilters(DEFAULT_TASK_FILTERS)
setCategories([])
void loadTasks(DEFAULT_TASK_FILTERS)
categoryService.listByOrganization(activeOrg.id).then(setCategories).catch(() => {})
const init = async () => {
setFilters(DEFAULT_TASK_FILTERS)
setCategories([])
projectService.listByOrganization(activeOrg.id).then(setProjects).catch(() => {})
const [members] = await Promise.all([
organizationService.listMembers(activeOrg.id),
categoryService.listByOrganization(activeOrg.id).then(setCategories).catch(() => {}),
projectService.listByOrganization(activeOrg.id).then(setProjects).catch(() => {}),
])
organizationService.listMembers(activeOrg.id).then((members) => {
setAssignees(members.map((m) => ({
const assigneesData = members.map((m) => ({
id: m.userId,
name: m.userName,
email: m.userEmail,
photo: m.userPhoto ?? null,
})))
}).catch(() => {})
}))
setAssignees(assigneesData)
const currentMember = members.find((m) => m.userEmail === user?.email)
const userId = currentMember?.userId ?? null
setCurrentUserAssigneeId(userId)
const initialFilters = userId
? { ...DEFAULT_TASK_FILTERS, userIds: [userId] }
: DEFAULT_TASK_FILTERS
setFilters(initialFilters)
void loadTasks(initialFilters)
}
void init()
}, [activeOrg])
const handleFiltersChange = (newFilters: TaskFilters) => {
@ -193,6 +209,7 @@ export function TaskListPage() {
projects={projects}
categories={categories}
assignees={assignees}
currentUserId={currentUserAssigneeId ?? undefined}
isLoading={isLoading}
onRefresh={() => void loadTasks(filters)}
/>