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

171 lines
5.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.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/shared/widgets/custom_text_field.dart';
import 'package:barber_app/shared/widgets/loading_button.dart';
import 'package:intl/intl.dart';
class AddServicePage extends StatefulWidget {
final ServiceModel? service;
const AddServicePage({super.key, this.service});
@override
State<AddServicePage> createState() => _AddServicePageState();
}
class _AddServicePageState extends State<AddServicePage> {
final _formKey = GlobalKey<FormState>();
final _nameController = TextEditingController();
final _priceController = TextEditingController(); // Valor numérico raw
final _displayPriceController = TextEditingController(); // Valor formatado R$
final _durationController = TextEditingController(text: '30');
final _repository = ServiceRepository();
bool _isLoading = false;
final _currencyFormat = NumberFormat.currency(locale: 'pt_BR', symbol: 'R\$');
bool get _isEditing => widget.service != null;
@override
void initState() {
super.initState();
if (_isEditing) {
_nameController.text = widget.service!.name;
_priceController.text = widget.service!.price.toStringAsFixed(2);
_displayPriceController.text = _currencyFormat.format(widget.service!.price);
_durationController.text = widget.service!.durationMinutes.toString();
}
}
void _formatPrice(String value) {
if (value.isEmpty) return;
// Remove tudo que não é número
String numbers = value.replaceAll(RegExp(r'[^0-9]'), '');
if (numbers.isEmpty) return;
double val = double.parse(numbers) / 100;
_priceController.text = val.toStringAsFixed(2);
_displayPriceController.text = _currencyFormat.format(val);
// Mantém cursor no final
_displayPriceController.selection = TextSelection.fromPosition(
TextPosition(offset: _displayPriceController.text.length),
);
}
Future<void> _saveService() async {
if (!_formKey.currentState!.validate()) return;
if (_priceController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Por favor, informe o preço')),
);
return;
}
setState(() => _isLoading = true);
try {
final price = double.parse(_priceController.text);
final duration = int.tryParse(_durationController.text) ?? 30;
if (_isEditing) {
final updatedService = widget.service!.copyWith(
name: _nameController.text.trim(),
price: price,
durationMinutes: duration,
);
await _repository.updateService(updatedService);
} else {
await _repository.createService(
name: _nameController.text.trim(),
price: price,
durationMinutes: duration,
);
}
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(_isEditing
? 'Serviço atualizado com sucesso!'
: 'Serviço criado com sucesso!'
),
backgroundColor: AppColors.success,
),
);
Navigator.pop(context, true);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Erro ao salvar: $e'),
backgroundColor: AppColors.error,
),
);
}
} finally {
if (mounted) setState(() => _isLoading = false);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_isEditing ? 'Editar Serviço' : 'Novo Serviço'),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
CustomTextField(
label: 'Nome do Serviço',
controller: _nameController,
hint: 'Ex: Corte Degradê, Barba Terapia...',
validator: (v) => v?.isEmpty == true ? 'Informe o nome' : null,
),
const SizedBox(height: 16),
CustomTextField(
label: 'Preço',
controller: _displayPriceController,
hint: 'R\$ 0,00',
keyboardType: TextInputType.number,
onChanged: _formatPrice,
validator: (v) => v?.isEmpty == true ? 'Informe o preço' : null,
),
const SizedBox(height: 16),
CustomTextField(
label: 'Duração Média (minutos)',
controller: _durationController,
keyboardType: TextInputType.number,
hint: '30',
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
),
const SizedBox(height: 32),
LoadingButton(
text: 'Salvar Serviço',
onPressed: _saveService,
isLoading: _isLoading,
),
],
),
),
),
);
}
}