feat: implement useUrlState hook for managing URL-based state in admin pages

- Refactor multiple admin pages (BlogsPage, ClinicsPage, DoctorsPage, etc.) to utilize the new useUrlState hook for managing pagination, search, and filter states via URL.
- Ensure that the state persists in the URL, allowing users to return to the same state when navigating back from detail pages.
- Update relevant components to handle state changes appropriately and maintain clean URLs by removing default values.
- Add SlotPicker component for selecting appointment slots based on availability.
- Create tests for useUrlState to validate its functionality and ensure correct behavior when interacting with the URL.
- Update API documentation to reflect changes in appointment creation and slot selection processes.
This commit is contained in:
hamed
2026-07-29 21:04:40 +03:30
parent e0e8fbd1e4
commit 684cf1f783
20 changed files with 668 additions and 79 deletions
+9 -3
View File
@@ -4,6 +4,7 @@ import { useNavigate } from 'react-router-dom';
import { EyeIcon, CheckIcon, XMarkIcon, MagnifyingGlassIcon } from '@heroicons/react/24/outline';
import { toast } from 'sonner';
import { api } from '../lib/api';
import { useUrlState, pageOf } from '../hooks/useUrlState';
import type { ApiResponse, PaginatedResponse } from '../lib/api';
import type { Settlement } from '../types';
import { formatDate, formatRial } from '../lib/utils';
@@ -24,9 +25,14 @@ const STATUS_FILTERS = [
export default function SettlementsPage() {
const navigate = useNavigate();
const qc = useQueryClient();
const [page, setPage] = useState(1);
const [search, setSearch] = useState('');
const [statusFilter, setStatusFilter] = useState('pending');
// وضعیت لیست در URL می‌ماند تا «بازگشت» از صفحهٔ جزئیات، همین فیلترها و صفحه را برگرداند.
const [urlState, setUrlState] = useUrlState({ page: '1', search: '', status: 'pending' });
const page = pageOf(urlState.page);
const search = urlState.search;
const statusFilter = urlState.status;
const setPage = (p: number) => setUrlState({ page: String(p) });
const setSearch = (v: string) => setUrlState({ search: v, page: '1' });
const setStatusFilter = (v: string) => setUrlState({ status: v, page: '1' });
const [approveTarget, setApproveTarget] = useState<Settlement | null>(null);
const [rejectTarget, setRejectTarget] = useState<Settlement | null>(null);
const [rejectReason, setRejectReason] = useState('');