Files
barber-app/lib/features/services/presentation/pages/services_page.dart
2025-12-19 23:29:24 -03:00

166 lines
6.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:barber_app/core/theme/app_theme.dart';
import 'package:barber_app/features/services/data/models/service_model.dart';
import 'package:barber_app/features/services/data/repositories/service_repository.dart';
import 'package:barber_app/features/services/presentation/pages/add_service_page.dart';
import 'package:intl/intl.dart';
class ServicesPage extends StatefulWidget {
const ServicesPage({super.key});
@override
State<ServicesPage> createState() => _ServicesPageState();
}
class _ServicesPageState extends State<ServicesPage> {
final _repository = ServiceRepository();
List<ServiceModel> _services = [];
final _currencyFormat = NumberFormat.currency(locale: 'pt_BR', symbol: 'R\$');
@override
void initState() {
super.initState();
_loadServices();
}
void _loadServices() {
setState(() {
_services = _repository.getAllServices();
});
}
Future<void> _deleteService(String id) async {
await _repository.deleteService(id);
_loadServices();
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Serviço removido com sucesso!')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Meus Serviços'), centerTitle: true),
body: _services.isEmpty
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.content_cut_outlined,
size: 64,
color: AppColors.textSecondary.withValues(alpha: 0.5),
),
const SizedBox(height: 16),
const Text(
'Nenhum serviço cadastrado',
style: TextStyle(
color: AppColors.textSecondary,
fontSize: 18,
),
),
const SizedBox(height: 8),
TextButton(
onPressed: () => _navigateToAddService(),
child: const Text('Cadastrar Primeiro Serviço'),
),
],
),
)
: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: _services.length,
itemBuilder: (context, index) {
final service = _services[index];
return Dismissible(
key: Key(service.id),
direction: DismissDirection.endToStart,
background: Container(
alignment: Alignment.centerRight,
padding: const EdgeInsets.only(right: 20),
color: AppColors.error,
child: const Icon(Icons.delete, color: Colors.white),
),
confirmDismiss: (direction) async {
return await showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Confirmar exclusão'),
content: Text(
'Deseja remover o serviço "${service.name}"?',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('Cancelar'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text(
'Excluir',
style: TextStyle(color: AppColors.error),
),
),
],
),
);
},
onDismissed: (direction) => _deleteService(service.id),
child: Card(
margin: const EdgeInsets.only(bottom: 12),
child: ListTile(
contentPadding: const EdgeInsets.all(16),
leading: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColors.primaryColor.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(12),
),
child: Icon(Icons.cut, color: AppColors.primaryColor),
),
title: Text(
service.name,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
subtitle: Text(
'Duração média: ${service.durationMinutes} min',
style: const TextStyle(color: AppColors.textSecondary),
),
trailing: Text(
_currencyFormat.format(service.price),
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: AppColors.success,
),
),
onTap: () => _navigateToAddService(service: service),
),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () => _navigateToAddService(),
child: const Icon(Icons.add),
),
);
}
Future<void> _navigateToAddService({ServiceModel? service}) async {
final result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddServicePage(service: service)),
);
if (result == true) {
_loadServices();
}
}
}