Files
MobilApp/lib/pages/contacts/presentation/views/contact_edit_view.dart
T

188 lines
6.3 KiB
Dart
Raw Normal View History

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../../models/contact.dart';
import '../../../../services/contact_service.dart';
/// Kapcsolat szerkesztő — TELJES OLDAL (Scaffold), nem bottom sheet.
///
/// Miért oldal: a bottom sheet a szoftveres billentyűzettel rosszul
/// viselkedik (a mezőket eltakarja / a lapot feltolja). A Scaffold body
/// automatikusan a billentyűzet fölé görget, a mentés gomb pedig fixen
/// az appbarban van — kesztyűs, terepi használatra is kényelmes.
///
/// Új rekord: `Get.to(() => const ContactEditView())`.
/// Szerkesztés: `Get.to(() => const ContactEditView(), arguments: contact)`.
class ContactEditView extends StatefulWidget {
const ContactEditView({super.key});
@override
State<ContactEditView> createState() => _ContactEditViewState();
}
class _ContactEditViewState extends State<ContactEditView> {
final _formKey = GlobalKey<FormState>();
late final Contact? _original;
late final TextEditingController _name;
late final TextEditingController _address;
late final TextEditingController _phone;
late final TextEditingController _email;
late final TextEditingController _note;
bool _saving = false;
@override
void initState() {
super.initState();
_original = Get.arguments is Contact ? Get.arguments as Contact : null;
_name = TextEditingController(text: _original?.name ?? '');
_address = TextEditingController(text: _original?.address ?? '');
_phone = TextEditingController(text: _original?.phone ?? '');
_email = TextEditingController(text: _original?.email ?? '');
_note = TextEditingController(text: _original?.note ?? '');
}
@override
void dispose() {
_name.dispose();
_address.dispose();
_phone.dispose();
_email.dispose();
_note.dispose();
super.dispose();
}
Future<void> _save() async {
if (!(_formKey.currentState?.validate() ?? false)) return;
setState(() => _saving = true);
try {
final contact = (_original ?? const Contact(name: '')).copyWith(
name: _name.text,
address: _address.text,
phone: _phone.text,
email: _email.text,
note: _note.text,
);
final queued = await ContactService.to.save(contact);
Get.back(result: queued); // a lista frissítéshez visszakapja
Get.snackbar(queued ? 'Elmentve (offline)' : 'Mentve',
queued ? '${contact.name} - feltöltés, amint van net' : contact.name,
snackPosition: SnackPosition.BOTTOM);
} catch (e) {
Get.snackbar('Hiba', _friendly(e),
snackPosition: SnackPosition.BOTTOM,
backgroundColor: const Color(0xFFB71C1C),
colorText: const Color(0xFFFFFFFF));
} finally {
if (mounted) setState(() => _saving = false);
}
}
String _friendly(Object e) {
final s = e.toString();
if (s.contains('permission') ||
s.contains('policy') ||
s.contains('row-level')) {
return 'Nincs jogosultságod a művelethez.';
}
return s;
}
@override
Widget build(BuildContext context) {
final isNew = _original?.id == null;
return Scaffold(
appBar: AppBar(
title: Text(isNew ? 'Új kapcsolat' : 'Kapcsolat szerkesztése'),
actions: [
TextButton.icon(
onPressed: _saving ? null : _save,
icon: _saving
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(strokeWidth: 2))
: const Icon(Icons.check),
label: const Text('Mentés'),
),
],
),
body: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(16),
children: [
TextFormField(
controller: _name,
autofocus: isNew,
textCapitalization: TextCapitalization.words,
decoration: const InputDecoration(
labelText: 'Név *',
prefixIcon: Icon(Icons.person_outline),
),
textInputAction: TextInputAction.next,
validator: (v) => (v == null || v.trim().isEmpty)
? 'A név megadása kötelező.'
: null,
),
const SizedBox(height: 12),
TextFormField(
controller: _address,
textCapitalization: TextCapitalization.sentences,
decoration: const InputDecoration(
labelText: 'Cím',
prefixIcon: Icon(Icons.location_on_outlined),
),
textInputAction: TextInputAction.next,
),
const SizedBox(height: 12),
TextFormField(
controller: _phone,
keyboardType: TextInputType.phone,
decoration: const InputDecoration(
labelText: 'Telefonszám',
prefixIcon: Icon(Icons.phone_outlined),
),
textInputAction: TextInputAction.next,
),
const SizedBox(height: 12),
TextFormField(
controller: _email,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
labelText: 'E-mail',
prefixIcon: Icon(Icons.email_outlined),
),
textInputAction: TextInputAction.next,
validator: (v) {
if (v == null || v.trim().isEmpty) return null;
final ok =
RegExp(r'^[^@\s]+@[^@\s]+\.[^@\s]+$').hasMatch(v.trim());
return ok ? null : 'Érvénytelen e-mail cím.';
},
),
const SizedBox(height: 12),
TextFormField(
controller: _note,
maxLines: 4,
textCapitalization: TextCapitalization.sentences,
decoration: const InputDecoration(
labelText: 'Megjegyzés',
prefixIcon: Icon(Icons.notes_outlined),
alignLabelWithHint: true,
),
),
const SizedBox(height: 24),
FilledButton.icon(
onPressed: _saving ? null : _save,
icon: const Icon(Icons.save_outlined),
label: const Text('Mentés'),
),
],
),
),
);
}
}