feat: server-side search with debounce for professionals list
- getProfessionals() now accepts optional search param sent to ?search= - updateCity only triggers the initial load (city no longer used as filter) - Search field debounces 450ms before firing API call - TextEditingController added so clear button also resets the field - Client-side filtering removed (API now handles it and returns top 7) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
9da159f287
commit
e0982995e6
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:prosapp_web_app/models/usuario_profesional.dart';
|
||||
import 'package:prosapp_web_app/providers/professionals_provider.dart';
|
||||
@@ -14,19 +15,35 @@ class ProfessionalsView extends StatefulWidget {
|
||||
|
||||
class _ProfessionalsViewState extends State<ProfessionalsView> {
|
||||
String _search = '';
|
||||
Timer? _debounce;
|
||||
final _controller = TextEditingController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_debounce?.cancel();
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onSearchChanged(String value) {
|
||||
setState(() => _search = value);
|
||||
_debounce?.cancel();
|
||||
_debounce = Timer(const Duration(milliseconds: 450), () {
|
||||
context.read<ProfessionalsProvider>().getProfessionals(search: value);
|
||||
});
|
||||
}
|
||||
|
||||
void _clearSearch() {
|
||||
_controller.clear();
|
||||
_onSearchChanged('');
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final provider = context.watch<ProfessionalsProvider>();
|
||||
final isDark = context.watch<ThemeProvider>().isDark;
|
||||
|
||||
final filtered = provider.professionals.where((p) {
|
||||
if (_search.isEmpty) return true;
|
||||
final q = _search.toLowerCase();
|
||||
return p.user.name.toLowerCase().contains(q) ||
|
||||
p.professionalInfo.profession.toLowerCase().contains(q) ||
|
||||
(p.user.city ?? '').toLowerCase().contains(q);
|
||||
}).toList();
|
||||
final filtered = provider.professionals;
|
||||
|
||||
final cardBg = isDark ? const Color(0xFF1E293B) : Colors.white;
|
||||
final border = isDark ? const Color(0xFF334155) : const Color(0xFFE5E7EB);
|
||||
@@ -39,7 +56,8 @@ class _ProfessionalsViewState extends State<ProfessionalsView> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 14),
|
||||
child: TextField(
|
||||
onChanged: (v) => setState(() => _search = v),
|
||||
controller: _controller,
|
||||
onChanged: _onSearchChanged,
|
||||
style: TextStyle(
|
||||
color: isDark ? Colors.white : const Color(0xFF111827),
|
||||
fontSize: 14,
|
||||
@@ -52,7 +70,7 @@ class _ProfessionalsViewState extends State<ProfessionalsView> {
|
||||
suffixIcon: _search.isNotEmpty
|
||||
? IconButton(
|
||||
icon: Icon(Icons.close, size: 18, color: hintColor),
|
||||
onPressed: () => setState(() => _search = ''),
|
||||
onPressed: _clearSearch,
|
||||
)
|
||||
: null,
|
||||
filled: true,
|
||||
|
||||
Reference in New Issue
Block a user