Initial commit: SIBU 2.0 MISSION
This commit is contained in:
265
old/lib/presentation/taxi_screen/taxi_screen.dart
Normal file
265
old/lib/presentation/taxi_screen/taxi_screen.dart
Normal file
@ -0,0 +1,265 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../models/taxi_model.dart';
|
||||
import '../../services/taxi_service.dart';
|
||||
import '../../widgets/custom_app_bar.dart';
|
||||
import '../../widgets/custom_bottom_bar.dart';
|
||||
import './widgets/taxi_card_widget.dart';
|
||||
import './widgets/taxi_empty_state_widget.dart';
|
||||
import './widgets/taxi_filters_widget.dart';
|
||||
|
||||
/// Main taxi screen with filtering, search, and favorites functionality
|
||||
class TaxiScreen extends StatefulWidget {
|
||||
const TaxiScreen({super.key});
|
||||
|
||||
@override
|
||||
State<TaxiScreen> createState() => _TaxiScreenState();
|
||||
}
|
||||
|
||||
class _TaxiScreenState extends State<TaxiScreen> {
|
||||
final TaxiService _taxiService = TaxiService.instance;
|
||||
Timer? _searchDebouncer;
|
||||
|
||||
// State variables
|
||||
List<String> _corregimientos = [];
|
||||
List<String> _shifts = [];
|
||||
List<TaxiModel> _taxis = [];
|
||||
Set<String> _favoriteTaxiIds = {};
|
||||
String? _selectedCorregimiento;
|
||||
String? _selectedShift;
|
||||
String _searchText = '';
|
||||
bool _isLoading = true;
|
||||
String? _error;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_searchDebouncer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// Load corregimientos, shifts and initial taxi data
|
||||
Future<void> _loadInitialData() async {
|
||||
try {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
});
|
||||
|
||||
// Load corregimientos, shifts and favorites
|
||||
final results = await Future.wait([
|
||||
_taxiService.getCorregimientos(),
|
||||
_taxiService.getFavoriteTaxiIds(),
|
||||
]);
|
||||
|
||||
final corregimientos = results[0];
|
||||
final favoriteIds = results[1];
|
||||
|
||||
setState(() {
|
||||
_corregimientos = corregimientos;
|
||||
_shifts = _taxiService.getShifts();
|
||||
_favoriteTaxiIds = favoriteIds.toSet();
|
||||
_isLoading = false;
|
||||
});
|
||||
|
||||
// Load taxis for all corregimientos initially
|
||||
await _searchTaxis();
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_error = e.toString();
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Search taxis with current filters
|
||||
Future<void> _searchTaxis() async {
|
||||
try {
|
||||
final taxis = await _taxiService.searchTaxis(
|
||||
selectedCorregimiento: _selectedCorregimiento,
|
||||
selectedShift: _selectedShift,
|
||||
searchText: _searchText.isEmpty ? null : _searchText,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_taxis = taxis;
|
||||
_error = null;
|
||||
});
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_error = e.toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle corregimiento selection change
|
||||
void _onCorregimientoChanged(String? corregimiento) {
|
||||
setState(() {
|
||||
_selectedCorregimiento = corregimiento;
|
||||
});
|
||||
_searchTaxis();
|
||||
}
|
||||
|
||||
/// Handle shift selection change
|
||||
void _onShiftChanged(String? shift) {
|
||||
setState(() {
|
||||
_selectedShift = shift;
|
||||
});
|
||||
_searchTaxis();
|
||||
}
|
||||
|
||||
/// Handle search text change with debouncing
|
||||
void _onSearchChanged(String text) {
|
||||
setState(() {
|
||||
_searchText = text;
|
||||
});
|
||||
|
||||
// Cancel previous timer
|
||||
_searchDebouncer?.cancel();
|
||||
|
||||
// Start new timer for debounced search
|
||||
_searchDebouncer = Timer(const Duration(milliseconds: 300), () {
|
||||
_searchTaxis();
|
||||
});
|
||||
}
|
||||
|
||||
/// Clear all filters
|
||||
void _onClearFilters() {
|
||||
setState(() {
|
||||
_selectedCorregimiento = null;
|
||||
_selectedShift = null;
|
||||
_searchText = '';
|
||||
});
|
||||
_searchTaxis();
|
||||
}
|
||||
|
||||
/// Toggle favorite status for a taxi
|
||||
Future<void> _onFavoriteToggle(String taxiId) async {
|
||||
try {
|
||||
final isFavorite = await _taxiService.toggleFavorite(taxiId);
|
||||
|
||||
setState(() {
|
||||
if (isFavorite) {
|
||||
_favoriteTaxiIds.add(taxiId);
|
||||
} else {
|
||||
_favoriteTaxiIds.remove(taxiId);
|
||||
}
|
||||
});
|
||||
|
||||
// Show feedback
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
isFavorite
|
||||
? 'Taxi agregado a favoritos'
|
||||
: 'Taxi removido de favoritos',
|
||||
),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: isFavorite ? Colors.green : Colors.orange,
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Error al actualizar favoritos: $e'),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle pull to refresh
|
||||
Future<void> _onRefresh() async {
|
||||
await _loadInitialData();
|
||||
}
|
||||
|
||||
/// Get current empty state widget based on context
|
||||
Widget _getEmptyStateWidget() {
|
||||
if (_error != null) {
|
||||
return TaxiEmptyStateWidget.error(
|
||||
error: _error!,
|
||||
onRetry: _loadInitialData,
|
||||
);
|
||||
}
|
||||
|
||||
if (_selectedCorregimiento == null &&
|
||||
_selectedShift == null &&
|
||||
_searchText.isEmpty) {
|
||||
return TaxiEmptyStateWidget.noFiltersSelected();
|
||||
}
|
||||
|
||||
return TaxiEmptyStateWidget.noResultsFound(onClearFilters: _onClearFilters);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.colorScheme.surface,
|
||||
appBar: const CustomAppBar(
|
||||
title: 'Taxi Directory',
|
||||
backgroundColor: Color(0xFF101820),
|
||||
foregroundColor: Color(0xFFFEE715),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
// Filters Section
|
||||
TaxiFiltersWidget(
|
||||
corregimientos: _corregimientos,
|
||||
shifts: _shifts,
|
||||
selectedCorregimiento: _selectedCorregimiento,
|
||||
selectedShift: _selectedShift,
|
||||
searchText: _searchText,
|
||||
onCorregimientoChanged: _onCorregimientoChanged,
|
||||
onShiftChanged: _onShiftChanged,
|
||||
onSearchChanged: _onSearchChanged,
|
||||
onClearFilters: _onClearFilters,
|
||||
),
|
||||
// Results Section
|
||||
Expanded(
|
||||
child:
|
||||
_isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: _taxis.isEmpty
|
||||
? _getEmptyStateWidget()
|
||||
: RefreshIndicator(
|
||||
onRefresh: _onRefresh,
|
||||
child: ListView.builder(
|
||||
itemCount: _taxis.length,
|
||||
itemBuilder: (context, index) {
|
||||
final taxi = _taxis[index];
|
||||
return TaxiCardWidget(
|
||||
taxi: taxi,
|
||||
isFavorite: _favoriteTaxiIds.contains(taxi.id),
|
||||
onFavoriteToggle: _onFavoriteToggle,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: CustomBottomBar(
|
||||
currentIndex: 3, // Taxi tab index
|
||||
onTap: _onBottomNavTap,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Handle bottom navigation tap
|
||||
void _onBottomNavTap(int index) {
|
||||
// Navigation is handled by CustomBottomBar
|
||||
}
|
||||
}
|
||||
159
old/lib/presentation/taxi_screen/widgets/taxi_card_widget.dart
Normal file
159
old/lib/presentation/taxi_screen/widgets/taxi_card_widget.dart
Normal file
@ -0,0 +1,159 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import '../../../models/taxi_model.dart';
|
||||
|
||||
/// Individual taxi card widget displaying taxi information with call and favorite functionality
|
||||
class TaxiCardWidget extends StatelessWidget {
|
||||
final TaxiModel taxi;
|
||||
final bool isFavorite;
|
||||
final Function(String) onFavoriteToggle;
|
||||
|
||||
const TaxiCardWidget({
|
||||
super.key,
|
||||
required this.taxi,
|
||||
required this.isFavorite,
|
||||
required this.onFavoriteToggle,
|
||||
});
|
||||
|
||||
/// Launch phone call
|
||||
Future<void> _makePhoneCall(String phoneNumber) async {
|
||||
final Uri launchUri = Uri(scheme: 'tel', path: phoneNumber);
|
||||
try {
|
||||
if (await canLaunchUrl(launchUri)) {
|
||||
await launchUrl(launchUri);
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle error silently or show user feedback
|
||||
}
|
||||
}
|
||||
|
||||
/// Capitalize first letter of shift for display
|
||||
String _formatShift(String shift) {
|
||||
if (shift.isEmpty) return '';
|
||||
return shift[0].toUpperCase() + shift.substring(1);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
elevation: 2,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header Row: Name and Favorite Button
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
taxi.name,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: const Color(0xFF101820),
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => onFavoriteToggle(taxi.id),
|
||||
icon: Icon(
|
||||
isFavorite ? Icons.favorite : Icons.favorite_border,
|
||||
color:
|
||||
isFavorite
|
||||
? const Color(0xFFFEE715)
|
||||
: theme.iconTheme.color,
|
||||
),
|
||||
tooltip:
|
||||
isFavorite ? 'Remove from favorites' : 'Add to favorites',
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
// Phone Row with Call Button
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.phone, size: 20, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
taxi.phone,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: const Color(0xFF101820),
|
||||
),
|
||||
),
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => _makePhoneCall(taxi.phone),
|
||||
icon: const Icon(Icons.call, size: 18),
|
||||
label: const Text('Call'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFFEE715),
|
||||
foregroundColor: const Color(0xFF101820),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 8,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
|
||||
// Location and Shift Info
|
||||
Row(
|
||||
children: [
|
||||
// Corregimiento
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.location_on,
|
||||
size: 16,
|
||||
color: theme.iconTheme.color?.withAlpha(153),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
taxi.corregimiento,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.textTheme.bodySmall?.color?.withAlpha(
|
||||
153,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Shift
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.schedule,
|
||||
size: 16,
|
||||
color: theme.iconTheme.color?.withAlpha(153),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
_formatShift(taxi.shift),
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.textTheme.bodySmall?.color?.withAlpha(153),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Widget for displaying various empty states in the taxi screen
|
||||
class TaxiEmptyStateWidget extends StatelessWidget {
|
||||
final String title;
|
||||
final String message;
|
||||
final IconData icon;
|
||||
final String? buttonText;
|
||||
final VoidCallback? onButtonPressed;
|
||||
|
||||
const TaxiEmptyStateWidget({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.message,
|
||||
required this.icon,
|
||||
this.buttonText,
|
||||
this.onButtonPressed,
|
||||
});
|
||||
|
||||
/// Empty state when no filters are selected
|
||||
factory TaxiEmptyStateWidget.noFiltersSelected() {
|
||||
return const TaxiEmptyStateWidget(
|
||||
title: 'Select Filters',
|
||||
message: 'Choose a corregimiento and/or shift to see available taxis.',
|
||||
icon: Icons.filter_list,
|
||||
);
|
||||
}
|
||||
|
||||
/// Empty state when no results match the current filters
|
||||
factory TaxiEmptyStateWidget.noResultsFound({
|
||||
required VoidCallback onClearFilters,
|
||||
}) {
|
||||
return TaxiEmptyStateWidget(
|
||||
title: 'No taxis available for this selection.',
|
||||
message: 'Try adjusting your filters or search terms.',
|
||||
icon: Icons.search_off,
|
||||
buttonText: 'Clear Filters',
|
||||
onButtonPressed: onClearFilters,
|
||||
);
|
||||
}
|
||||
|
||||
/// Empty state when there's no data at all
|
||||
factory TaxiEmptyStateWidget.noData() {
|
||||
return const TaxiEmptyStateWidget(
|
||||
title: 'No taxis registered yet.',
|
||||
message: 'There are no taxi services available at the moment.',
|
||||
icon: Icons.local_taxi,
|
||||
);
|
||||
}
|
||||
|
||||
/// Empty state for error conditions
|
||||
factory TaxiEmptyStateWidget.error({
|
||||
required String error,
|
||||
required VoidCallback onRetry,
|
||||
}) {
|
||||
return TaxiEmptyStateWidget(
|
||||
title: 'Error Loading Taxis',
|
||||
message: error,
|
||||
icon: Icons.error_outline,
|
||||
buttonText: 'Retry',
|
||||
onButtonPressed: onRetry,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(32),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(icon, size: 80, color: theme.iconTheme.color?.withAlpha(128)),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
title,
|
||||
style: theme.textTheme.headlineSmall?.copyWith(
|
||||
color: const Color(0xFF101820),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
message,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.textTheme.bodyMedium?.color?.withAlpha(153),
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
if (buttonText != null && onButtonPressed != null) ...[
|
||||
const SizedBox(height: 24),
|
||||
ElevatedButton(
|
||||
onPressed: onButtonPressed,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFFEE715),
|
||||
foregroundColor: const Color(0xFF101820),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 24,
|
||||
vertical: 12,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text(buttonText!),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,189 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Widget for taxi search filters including corregimiento dropdown, shift dropdown and search input
|
||||
class TaxiFiltersWidget extends StatefulWidget {
|
||||
final List<String> corregimientos; // Changed from districts
|
||||
final List<String> shifts; // Added shifts list
|
||||
final String? selectedCorregimiento; // Changed from selectedDistrict
|
||||
final String? selectedShift; // Added shift selection
|
||||
final String searchText;
|
||||
final Function(String?)
|
||||
onCorregimientoChanged; // Changed from onDistrictChanged
|
||||
final Function(String?) onShiftChanged; // Added shift handler
|
||||
final Function(String) onSearchChanged;
|
||||
final VoidCallback onClearFilters;
|
||||
|
||||
const TaxiFiltersWidget({
|
||||
super.key,
|
||||
required this.corregimientos, // Changed from districts
|
||||
required this.shifts, // Added shifts
|
||||
required this.selectedCorregimiento, // Changed from selectedDistrict
|
||||
required this.selectedShift, // Added shift selection
|
||||
required this.searchText,
|
||||
required this.onCorregimientoChanged, // Changed from onDistrictChanged
|
||||
required this.onShiftChanged, // Added shift handler
|
||||
required this.onSearchChanged,
|
||||
required this.onClearFilters,
|
||||
});
|
||||
|
||||
@override
|
||||
State<TaxiFiltersWidget> createState() => _TaxiFiltersWidgetState();
|
||||
}
|
||||
|
||||
class _TaxiFiltersWidgetState extends State<TaxiFiltersWidget> {
|
||||
late TextEditingController _searchController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_searchController = TextEditingController(text: widget.searchText);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_searchController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.surface,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: theme.shadowColor.withAlpha(26),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Filter Dropdowns Row
|
||||
Row(
|
||||
children: [
|
||||
// Corregimiento Dropdown
|
||||
Expanded(
|
||||
child: DropdownButtonFormField<String?>(
|
||||
value:
|
||||
widget
|
||||
.selectedCorregimiento, // Changed from selectedDistrict
|
||||
hint: const Text(
|
||||
'Seleccionar Corregimiento',
|
||||
), // Updated hint text
|
||||
decoration: InputDecoration(
|
||||
labelText:
|
||||
'Filter by Corregimiento', // Updated label as requested
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 8,
|
||||
),
|
||||
),
|
||||
items: [
|
||||
const DropdownMenuItem<String?>(
|
||||
value: null,
|
||||
child: Text('Todos los corregimientos'), // Updated text
|
||||
),
|
||||
...widget.corregimientos.map(
|
||||
// Changed from districts
|
||||
(corregimiento) => DropdownMenuItem<String?>(
|
||||
value: corregimiento,
|
||||
child: Text(corregimiento),
|
||||
),
|
||||
),
|
||||
],
|
||||
onChanged:
|
||||
widget
|
||||
.onCorregimientoChanged, // Changed from onDistrictChanged
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
// Shift Dropdown
|
||||
Expanded(
|
||||
child: DropdownButtonFormField<String?>(
|
||||
value: widget.selectedShift,
|
||||
hint: const Text('Seleccionar Turno'),
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Filter by Shift', // Label as requested
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 8,
|
||||
),
|
||||
),
|
||||
items: [
|
||||
const DropdownMenuItem<String?>(
|
||||
value: null,
|
||||
child: Text('Todos los turnos'),
|
||||
),
|
||||
...widget.shifts.map(
|
||||
(shift) => DropdownMenuItem<String?>(
|
||||
value: shift,
|
||||
child: Text(shift),
|
||||
),
|
||||
),
|
||||
],
|
||||
onChanged: widget.onShiftChanged,
|
||||
),
|
||||
),
|
||||
if (widget.selectedCorregimiento !=
|
||||
null || // Changed from selectedDistrict
|
||||
widget.selectedShift != null || // Added shift condition
|
||||
widget.searchText.isNotEmpty) ...[
|
||||
const SizedBox(width: 8),
|
||||
IconButton(
|
||||
onPressed: widget.onClearFilters,
|
||||
icon: const Icon(Icons.clear),
|
||||
tooltip: 'Clear Filters', // Updated tooltip text as requested
|
||||
style: IconButton.styleFrom(
|
||||
backgroundColor: theme.colorScheme.errorContainer,
|
||||
foregroundColor: theme.colorScheme.onErrorContainer,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// Search Input
|
||||
TextField(
|
||||
controller: _searchController,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Buscar taxi o teléfono',
|
||||
hintText: 'Escribe el nombre o número...',
|
||||
prefixIcon: const Icon(Icons.search),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 8,
|
||||
),
|
||||
suffixIcon:
|
||||
widget.searchText.isNotEmpty
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
_searchController.clear();
|
||||
widget.onSearchChanged('');
|
||||
},
|
||||
icon: const Icon(Icons.clear),
|
||||
tooltip: 'Limpiar búsqueda',
|
||||
)
|
||||
: null,
|
||||
),
|
||||
onChanged: widget.onSearchChanged,
|
||||
textInputAction: TextInputAction.search,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user