feat: add status+tenant filter to Students page, status filter to Rooms page
This commit is contained in:
@@ -45,6 +45,7 @@ const RoomsPage: React.FC = () => {
|
|||||||
const [archivedCount, setArchivedCount] = useState(0);
|
const [archivedCount, setArchivedCount] = useState(0);
|
||||||
const [searchText, setSearchText] = useState('');
|
const [searchText, setSearchText] = useState('');
|
||||||
const [filterBuilding, setFilterBuilding] = useState<string | undefined>(undefined);
|
const [filterBuilding, setFilterBuilding] = useState<string | undefined>(undefined);
|
||||||
|
const [filterStatus, setFilterStatus] = useState<string | undefined>(undefined);
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
|
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
@@ -89,13 +90,12 @@ const RoomsPage: React.FC = () => {
|
|||||||
let result = data;
|
let result = data;
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
const keyword = searchText.toLowerCase();
|
const keyword = searchText.toLowerCase();
|
||||||
result = result.filter((r: any) => r.roomNumber?.toLowerCase().includes(keyword));
|
result = result.filter((r: Record<string, unknown>) => typeof r.roomNumber === 'string' && r.roomNumber.toLowerCase().includes(keyword));
|
||||||
}
|
|
||||||
if (filterBuilding) {
|
|
||||||
result = result.filter((r: any) => r.building === filterBuilding);
|
|
||||||
}
|
}
|
||||||
|
if (filterBuilding) result = result.filter((r: Record<string, unknown>) => r.building === filterBuilding);
|
||||||
|
if (filterStatus) result = result.filter((r: Record<string, unknown>) => r.status === filterStatus);
|
||||||
return result;
|
return result;
|
||||||
}, [data, searchText, filterBuilding]);
|
}, [data, searchText, filterBuilding, filterStatus]);
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
@@ -314,6 +314,8 @@ const RoomsPage: React.FC = () => {
|
|||||||
onChange={(v) => setFilterBuilding(v)}
|
onChange={(v) => setFilterBuilding(v)}
|
||||||
options={buildings.map((b) => ({ value: b, label: b }))}
|
options={buildings.map((b) => ({ value: b, label: b }))}
|
||||||
/>
|
/>
|
||||||
|
<Select placeholder="状态" allowClear style={{ width: 110 }} value={filterStatus} onChange={setFilterStatus}
|
||||||
|
options={[{value:'available',label:'可入住'},{value:'full',label:'已满'},{value:'maintenance',label:'维护中'}]} />
|
||||||
<Button
|
<Button
|
||||||
type={showArchived ? 'primary' : 'default'}
|
type={showArchived ? 'primary' : 'default'}
|
||||||
onClick={() => setShowArchived(!showArchived)}
|
onClick={() => setShowArchived(!showArchived)}
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ const StudentsPage: React.FC = () => {
|
|||||||
const [tenants, setTenants] = useState<any[]>([]);
|
const [tenants, setTenants] = useState<any[]>([]);
|
||||||
const [editing, setEditing] = useState<any>(null);
|
const [editing, setEditing] = useState<any>(null);
|
||||||
const [searchName, setSearchName] = useState('');
|
const [searchName, setSearchName] = useState('');
|
||||||
|
const [filterStatus, setFilterStatus] = useState<string | undefined>(undefined);
|
||||||
|
const [filterTenantId, setFilterTenantId] = useState<number | undefined>(undefined);
|
||||||
const [showArchived, setShowArchived] = useState(false);
|
const [showArchived, setShowArchived] = useState(false);
|
||||||
const [archivedCount, setArchivedCount] = useState(0);
|
const [archivedCount, setArchivedCount] = useState(0);
|
||||||
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
|
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
|
||||||
@@ -117,12 +119,14 @@ const StudentsPage: React.FC = () => {
|
|||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const params: any = { name: searchName || undefined, includeArchived: 'true' };
|
const params: Record<string, unknown> = { name: searchName || undefined, includeArchived: 'true' };
|
||||||
const res: any = await api.get('/students', { params });
|
if (filterStatus) params.status = filterStatus;
|
||||||
const archived = res.filter((r: any) => r.status === 'archived');
|
if (filterTenantId) params.tenantId = filterTenantId;
|
||||||
|
const res = await api.get('/students', { params }) as Array<Record<string, unknown>>;
|
||||||
|
const list = res as Array<Record<string, unknown>>;
|
||||||
|
const archived = list.filter((r) => r.status === 'archived');
|
||||||
setArchivedCount(archived.length);
|
setArchivedCount(archived.length);
|
||||||
const filtered = showArchived ? res : res.filter((r: any) => r.status !== 'archived');
|
setData(showArchived ? list : list.filter((r) => r.status !== 'archived'));
|
||||||
setData(filtered);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
@@ -131,14 +135,13 @@ const StudentsPage: React.FC = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchData();
|
fetchData();
|
||||||
}, [searchName, showArchived]);
|
}, [searchName, showArchived, filterStatus, filterTenantId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
api.get('/tenants', { params: { includeArchived: 'false' } }).then((res: unknown) => {
|
api.get('/tenants', { params: { includeArchived: 'false' } }).then((res: unknown) => {
|
||||||
setTenants(res as Array<{ id: number; name: string }>);
|
setTenants(res as Array<{ id: number; name: string }>);
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
const values = await form.validateFields();
|
const values = await form.validateFields();
|
||||||
try {
|
try {
|
||||||
@@ -331,6 +334,12 @@ const StudentsPage: React.FC = () => {
|
|||||||
allowClear
|
allowClear
|
||||||
style={{ width: 250 }}
|
style={{ width: 250 }}
|
||||||
/>
|
/>
|
||||||
|
<Select placeholder="状态筛选" allowClear style={{ width: 120 }} value={filterStatus} onChange={(v) => { setFilterStatus(v); }}>
|
||||||
|
{Object.entries(statusMap).filter(([k]) => k !== 'archived').map(([k, v]) => <Select.Option key={k} value={k}>{v.text}</Select.Option>)}
|
||||||
|
</Select>
|
||||||
|
<Select placeholder="所属机构" allowClear style={{ width: 140 }} value={filterTenantId} onChange={(v) => { setFilterTenantId(v); }}>
|
||||||
|
{tenants.map((t: { id: number; name: string }) => <Select.Option key={t.id} value={t.id}>{t.name}</Select.Option>)}
|
||||||
|
</Select>
|
||||||
<Button
|
<Button
|
||||||
type={showArchived ? 'primary' : 'default'}
|
type={showArchived ? 'primary' : 'default'}
|
||||||
onClick={() => setShowArchived(!showArchived)}
|
onClick={() => setShowArchived(!showArchived)}
|
||||||
|
|||||||
Reference in New Issue
Block a user