Add assigned to filter on work order list

- Dropdown filter next to status chips with All Assignees, Unassigned, and user list
- Filters combine with status filter
- Styled as rounded select matching filter bar aesthetic
This commit is contained in:
Adam Moussa 2026-04-17 12:45:29 -04:00
parent 1ae58e56c3
commit 79f7b4782a
2 changed files with 49 additions and 2 deletions

View file

@ -1,8 +1,9 @@
import { useState } from "react"; import { useState, useEffect } from "react";
import { useNavigate } from "react-router"; import { useNavigate } from "react-router";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import usePaginatedList from "../../../hooks/usePaginatedList"; import usePaginatedList from "../../../hooks/usePaginatedList";
import { fetchWorkOrdersPaged } from "./api"; import { fetchWorkOrdersPaged } from "./api";
import { fetchUsers } from "../api";
import Table from "./Table"; import Table from "./Table";
import DeleteModal from "../../../components/DeleteModal"; import DeleteModal from "../../../components/DeleteModal";
import "./styles.css"; import "./styles.css";
@ -47,8 +48,14 @@ export default function WorkOrdersList() {
}; };
const [statusFilter, setStatusFilter] = useState(""); const [statusFilter, setStatusFilter] = useState("");
const [assigneeFilter, setAssigneeFilter] = useState("");
const [users, setUsers] = useState([]);
const statuses = ["Open", "In Progress", "On Hold", "Done", "Cancelled"]; const statuses = ["Open", "In Progress", "On Hold", "Done", "Cancelled"];
useEffect(() => {
fetchUsers().then(setUsers).catch(() => {});
}, []);
return ( return (
<> <>
<section className="listPage"> <section className="listPage">
@ -86,12 +93,29 @@ export default function WorkOrdersList() {
{s} {s}
</button> </button>
))} ))}
<span className="woFilterDivider" />
<select
className="woFilterSelect"
value={assigneeFilter}
onChange={(e) => setAssigneeFilter(e.target.value)}
>
<option value="">All Assignees</option>
<option value="__unassigned">Unassigned</option>
{users.map((u) => (
<option key={u.id} value={u.name}>{u.name}</option>
))}
</select>
</div> </div>
<Table <Table
loading={loading} loading={loading}
error={err} error={err}
rows={statusFilter ? rows.filter((r) => r.status === statusFilter) : rows} rows={rows.filter((r) => {
if (statusFilter && r.status !== statusFilter) return false;
if (assigneeFilter === "__unassigned" && r.assignedTo) return false;
if (assigneeFilter && assigneeFilter !== "__unassigned" && r.assignedTo !== assigneeFilter) return false;
return true;
})}
onEdit={(item) => navigate(`/workorders/${item.id}`)} onEdit={(item) => navigate(`/workorders/${item.id}`)}
onDelete={handleDeleteClick} onDelete={handleDeleteClick}
page={page} page={page}

View file

@ -418,6 +418,29 @@
border-color: #007bff; border-color: #007bff;
} }
.woFilterDivider {
width: 1px;
height: 20px;
background: #ddd;
margin: 0 4px;
}
.woFilterSelect {
height: 28px;
padding: 0 10px;
border: 1px solid #ddd;
border-radius: 16px;
font-size: 12px;
color: #666;
background: #fff;
cursor: pointer;
outline: none;
}
.woFilterSelect:focus {
border-color: #007bff;
}
/* Table wrapper */ /* Table wrapper */
.tableContainer { .tableContainer {
background: white; background: white;