import 'package:flutter/material.dart'; import '../colors/app_colors.dart'; import '../strings/consultorios_strings.dart'; import '../widgets/tap_bounce.dart'; import 'clinic.dart'; import 'clinic_card.dart'; /// Conteúdo do separador Consultórios, embutido na navegação inferior do /// [LoggedHomeScreen] (sem Scaffold/AppBar próprios). Não busca dados /// sozinho — recebe tudo já carregado do ecrã pai (que mantém o cache vivo /// entre trocas de separador), e só pede um novo carregamento através dos /// callbacks fornecidos. class ConsultoriosTab extends StatelessWidget { const ConsultoriosTab({ super.key, required this.address, required this.loading, required this.error, required this.near, required this.far, required this.favoriteIds, required this.onToggleFavorite, required this.onRefresh, required this.onAddAddress, }); /// Morada guardada, ou vazia/nula se o utilizador ainda não registou uma. final String? address; final bool loading; final String? error; final List near; final List far; final Set favoriteIds; final ValueChanged onToggleFavorite; final Future Function() onRefresh; final VoidCallback onAddAddress; bool get _hasAddress => (address ?? '').trim().isNotEmpty; @override Widget build(BuildContext context) { if (!_hasAddress) { return _EmptyState( icon: Icons.location_on_outlined, title: ConsultoriosStrings.noAddressTitle, message: ConsultoriosStrings.noAddressMessage, actionLabel: ConsultoriosStrings.addAddress, onAction: onAddAddress, ); } if (loading && near.isEmpty && far.isEmpty && error == null) { return const Center( child: Padding( padding: EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(color: AppColors.teal), SizedBox(height: 14), Text( ConsultoriosStrings.loading, textAlign: TextAlign.center, style: TextStyle(fontWeight: FontWeight.w600), ), ], ), ), ); } if (error != null) { return _EmptyState( icon: Icons.wifi_off_rounded, title: ConsultoriosStrings.fetchErrorTitle, message: ConsultoriosStrings.fetchErrorMessage, actionLabel: ConsultoriosStrings.retry, onAction: onRefresh, ); } if (near.isEmpty && far.isEmpty) { return _EmptyState( icon: Icons.search_off_rounded, title: ConsultoriosStrings.noResults, onAction: onRefresh, actionLabel: ConsultoriosStrings.retry, ); } return RefreshIndicator( color: AppColors.teal, onRefresh: onRefresh, child: ListView( padding: const EdgeInsets.fromLTRB(16, 16, 16, 24), children: [ if (near.isNotEmpty) ...[ _SectionLabel(ConsultoriosStrings.sectionNear(near.length)), const SizedBox(height: 10), for (var i = 0; i < near.length; i++) ...[ if (i > 0) const SizedBox(height: 12), ClinicCard( clinic: near[i], isFavorite: favoriteIds.contains(near[i].id), onToggleFavorite: onToggleFavorite, ), ], const SizedBox(height: 20), ], if (far.isNotEmpty) ...[ _SectionLabel(ConsultoriosStrings.sectionFar(far.length)), const SizedBox(height: 10), for (var i = 0; i < far.length; i++) ...[ if (i > 0) const SizedBox(height: 12), ClinicCard( clinic: far[i], isFavorite: favoriteIds.contains(far[i].id), onToggleFavorite: onToggleFavorite, ), ], ], ], ), ); } } class _SectionLabel extends StatelessWidget { const _SectionLabel(this.text); final String text; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(left: 4), child: Text( text, style: const TextStyle( color: AppColors.pink, fontWeight: FontWeight.w900, fontSize: 14, ), ), ); } } class _EmptyState extends StatelessWidget { const _EmptyState({ required this.icon, required this.title, this.message, required this.actionLabel, required this.onAction, }); final IconData icon; final String title; final String? message; final String actionLabel; final VoidCallback onAction; @override Widget build(BuildContext context) { return Center( child: SingleChildScrollView( padding: const EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 76, height: 76, decoration: BoxDecoration( color: AppColors.pinkBackground, shape: BoxShape.circle, ), child: Icon(icon, color: AppColors.pink, size: 36), ), const SizedBox(height: 18), Text( title, textAlign: TextAlign.center, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w900, color: Colors.black87, ), ), if (message != null) ...[ const SizedBox(height: 8), Text( message!, textAlign: TextAlign.center, style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: Colors.black.withValues(alpha: 0.6), height: 1.4, ), ), ], const SizedBox(height: 20), TapBounce( child: FilledButton( style: FilledButton.styleFrom( backgroundColor: AppColors.teal, foregroundColor: Colors.white, shape: const StadiumBorder(), padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 14, ), textStyle: const TextStyle(fontWeight: FontWeight.w800), ), onPressed: onAction, child: Text(actionLabel), ), ), ], ), ), ); } }