import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:fikoyt_soyagaci/models/soy_agaci_models.dart'; import 'package:fikoyt_soyagaci/services/soy_agaci_service.dart'; import 'package:fikoyt_soyagaci/dialogs/akrabalik_turu_sec_dialog.dart'; // --- Renkler --- const _erkekRenk = Color(0xFF3b82f6); const _kadinRenk = Color(0xFFec4899); const _vurguRenk = Color(0xFFf59e0b); const _kenarCizgi = Color(0xFFe2e8f0); const _metinBirincil = Color(0xFF1e293b); const _metinIkincil = Color(0xFF64748b); /// Wizard adimi enum _AkrabaEkleAdim { secim, elle, mevcut, turSec, onay } /// Akraba Ekle Dialog Controller class AkrabaEkleController extends GetxController { final String? hedefKisiId; final String hedefKisiIsim; AkrabaEkleController({this.hedefKisiId, this.hedefKisiIsim = ''}); final service = Get.find(); // Wizard state final adim = _AkrabaEkleAdim.secim.obs; // Form alanlari final isimController = TextEditingController(); final soyIsimController = TextEditingController(); final meslekController = TextEditingController(); final dogumYeriController = TextEditingController(); final notlarController = TextEditingController(); final cinsiyet = 'E'.obs; final dogumTarihi = Rxn(); final resimYolu = ''.obs; // Secili kisi (mevcut modunda) final seciliMevcutKisi = Rxn(); // Secili akrabalik turu final seciliAkrabalikTuru = Rxn(); // Arama final aramaController = TextEditingController(); final aramaMetni = ''.obs; final filtrelenmisKisiler = [].obs; // Durum final kaydediliyor = false.obs; @override void onInit() { super.onInit(); debounce(aramaMetni, (_) => _kisileriFiltrele(), time: const Duration(milliseconds: 300)); } @override void onClose() { isimController.dispose(); soyIsimController.dispose(); meslekController.dispose(); dogumYeriController.dispose(); notlarController.dispose(); aramaController.dispose(); super.onClose(); } // --- Mod Gecisleri --- void tiklandiElleModu() { isimController.clear(); soyIsimController.clear(); meslekController.clear(); dogumYeriController.clear(); cinsiyet.value = 'E'; dogumTarihi.value = null; resimYolu.value = ''; seciliMevcutKisi.value = null; adim.value = _AkrabaEkleAdim.elle; } void tiklandiMevcutModu() { seciliMevcutKisi.value = null; aramaController.clear(); aramaMetni.value = ''; _kisileriFiltrele(); adim.value = _AkrabaEkleAdim.mevcut; } void tiklandiGeri() { switch (adim.value) { case _AkrabaEkleAdim.elle: case _AkrabaEkleAdim.mevcut: adim.value = _AkrabaEkleAdim.secim; break; case _AkrabaEkleAdim.turSec: adim.value = seciliMevcutKisi.value != null ? _AkrabaEkleAdim.mevcut : _AkrabaEkleAdim.elle; break; case _AkrabaEkleAdim.onay: adim.value = _AkrabaEkleAdim.turSec; break; default: break; } } void elleIleri() { if (isimController.text.trim().isEmpty || soyIsimController.text.trim().isEmpty) return; seciliMevcutKisi.value = null; adim.value = _AkrabaEkleAdim.turSec; } void mevcutKisiSecildi(FamilyChartDugum kisi) { seciliMevcutKisi.value = kisi; adim.value = _AkrabaEkleAdim.turSec; } void turSecildi(AkrabalikTuru tur) { seciliAkrabalikTuru.value = tur; adim.value = _AkrabaEkleAdim.onay; } // --- Arama --- void _kisileriFiltrele() { final aranan = aramaMetni.value.toLowerCase(); final tumKisiler = service.chartVerileriMap.values.toList(); if (aranan.isEmpty) { filtrelenmisKisiler.value = tumKisiler; } else { filtrelenmisKisiler.value = tumKisiler .where((k) => k.isim.toLowerCase().contains(aranan) || k.soyIsim.toLowerCase().contains(aranan)) .toList(); } } // --- Resim --- void resimSil() { resimYolu.value = ''; } // --- Dogum Tarihi --- Future dogumTarihiSec(BuildContext context) async { final secilen = await showDatePicker( context: context, initialDate: dogumTarihi.value ?? DateTime(1990), firstDate: DateTime(1800), lastDate: DateTime.now(), locale: const Locale('tr', 'TR'), ); if (secilen != null) { dogumTarihi.value = secilen; } } // --- Yardimci --- String get eklenecekKisiIsim { if (seciliMevcutKisi.value != null) { return seciliMevcutKisi.value!.tamAd; } return '${isimController.text} ${soyIsimController.text}'.trim(); } String get eklenecekKisiCinsiyet { if (seciliMevcutKisi.value != null) { return seciliMevcutKisi.value!.cinsiyet == 'F' ? 'K' : 'E'; } return cinsiyet.value; } Color avatarRenk(String? c) => c == 'K' ? _kadinRenk : _erkekRenk; // --- Kaydet --- Future kaydet() async { if (seciliAkrabalikTuru.value == null) return; kaydediliyor.value = true; try { final hedefId = hedefKisiId ?? service.chartVerileriMap.values.firstOrNull?.id; if (hedefId == null) { Get.snackbar('Hata', 'Hedef kisi bulunamadi', backgroundColor: Colors.red.shade100); kaydediliyor.value = false; return; } String? mevcutKisiId; SoyAgaciKisiVeri? yeniKisiVeri; if (seciliMevcutKisi.value != null) { mevcutKisiId = seciliMevcutKisi.value!.id; } else { // Yeni kisi verisi olustur yeniKisiVeri = SoyAgaciKisiVeri( isim: isimController.text.trim(), soyIsim: soyIsimController.text.trim(), cinsiyet: cinsiyet.value, // 'E' | 'K' dogumTarihi: dogumTarihi.value != null ? dogumTarihi.value!.toIso8601String() : null, meslek: meslekController.text.trim().isNotEmpty ? meslekController.text.trim() : null, dogumYeri: dogumYeriController.text.trim().isNotEmpty ? dogumYeriController.text.trim() : null, resimUrl: resimYolu.value.isNotEmpty ? resimYolu.value : null, ); } final basarili = await service.akrabaEkle( kisi1Id: hedefId, kisi2Id: mevcutKisiId ?? '', // bos ise service yeni kisi olusturacak akrabalikTuru: seciliAkrabalikTuru.value!, yeniKisiVeri: yeniKisiVeri, ); if (basarili) { Get.snackbar('Basarili', 'Akrabalik bagi eklendi', backgroundColor: Colors.green.shade100); Get.back(result: true); } else { Get.snackbar('Hata', 'Akrabalik bagi eklenemedi', backgroundColor: Colors.red.shade100); } } catch (e) { Get.snackbar('Hata', 'Akrabalik bagi eklenemedi: $e', backgroundColor: Colors.red.shade100); } kaydediliyor.value = false; } } /// Akraba Ekle Dialog -- Angular DialogAkrabaEkleComponent karsiligi Future showAkrabaEkleDialog({ String? hedefKisiId, String hedefKisiIsim = '', }) async { final controller = Get.put( AkrabaEkleController( hedefKisiId: hedefKisiId, hedefKisiIsim: hedefKisiIsim), tag: 'akraba_ekle_${DateTime.now().millisecondsSinceEpoch}', ); final result = await Get.dialog( Dialog( insetPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 40), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), child: _AkrabaEkleDialogBody(controller: controller), ), barrierDismissible: false, ); Get.delete( tag: 'akraba_ekle_${DateTime.now().millisecondsSinceEpoch}', force: true); return result; } class _AkrabaEkleDialogBody extends StatelessWidget { final AkrabaEkleController controller; const _AkrabaEkleDialogBody({required this.controller}); @override Widget build(BuildContext context) { return Container( width: 480, constraints: BoxConstraints( maxHeight: MediaQuery.of(context).size.height * 0.85, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // Baslik _buildBaslik(), const Divider(height: 1, color: _kenarCizgi), // Icerik Flexible( child: Obx(() => AnimatedSwitcher( duration: const Duration(milliseconds: 200), child: _buildAdimIcerik(context), )), ), ], ), ); } Widget _buildBaslik() { return Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), child: Row( children: [ const Icon(Icons.person_add_alt_1, color: _erkekRenk, size: 22), const SizedBox(width: 10), Expanded( child: Obx(() { String baslik = 'Akraba Ekle'; if (controller.hedefKisiIsim.isNotEmpty) { baslik = '${controller.hedefKisiIsim} icin Akraba Ekle'; } final adimNo = controller.adim.value.index + 1; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(baslik, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: _metinBirincil)), Text('Adim $adimNo / 5', style: const TextStyle( fontSize: 11, color: _metinIkincil)), ], ); }), ), IconButton( icon: const Icon(Icons.close, size: 20, color: _metinIkincil), onPressed: () => Get.back(), ), ], ), ); } Widget _buildAdimIcerik(BuildContext context) { switch (controller.adim.value) { case _AkrabaEkleAdim.secim: return _buildSecimAdimi(); case _AkrabaEkleAdim.elle: return _buildElleAdimi(context); case _AkrabaEkleAdim.mevcut: return _buildMevcutAdimi(); case _AkrabaEkleAdim.turSec: return _buildTurSecAdimi(); case _AkrabaEkleAdim.onay: return _buildOnayAdimi(); } } // ---- ADIM 1: Secim ---- Widget _buildSecimAdimi() { return Padding( key: const ValueKey('secim'), padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text('Nasil eklemek istersiniz?', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: _metinBirincil)), const SizedBox(height: 16), Row( children: [ Expanded(child: _secimKart( ikon: Icons.edit_note, baslik: 'Elle Yeni Kisi Ekle', aciklama: 'Isim, dogum tarihi ve diger bilgileri girin', onTap: controller.tiklandiElleModu, )), const SizedBox(width: 12), Expanded(child: _secimKart( ikon: Icons.people_outline, baslik: 'Mevcut Kisiden Sec', aciklama: 'Agacta kayitli bir kisiyle baglanti kurun', onTap: controller.tiklandiMevcutModu, )), ], ), ], ), ); } Widget _secimKart({ required IconData ikon, required String baslik, required String aciklama, required VoidCallback onTap, }) { return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(12), child: Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( border: Border.all(color: _kenarCizgi), borderRadius: BorderRadius.circular(12), ), child: Column( children: [ Icon(ikon, size: 32, color: _erkekRenk), const SizedBox(height: 8), Text(baslik, textAlign: TextAlign.center, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: _metinBirincil)), const SizedBox(height: 4), Text(aciklama, textAlign: TextAlign.center, style: const TextStyle(fontSize: 11, color: _metinIkincil)), ], ), ), ); } // ---- ADIM 2: Elle Gir ---- Widget _buildElleAdimi(BuildContext context) { return Padding( key: const ValueKey('elle'), padding: const EdgeInsets.all(20), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text('Yeni kisi bilgilerini girin', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: _metinBirincil)), const SizedBox(height: 16), // Profil Resmi Center( child: Obx(() => Stack( children: [ CircleAvatar( radius: 36, backgroundColor: _kenarCizgi, backgroundImage: controller.resimYolu.value.isNotEmpty ? NetworkImage(controller.resimYolu.value) as ImageProvider : null, child: controller.resimYolu.value.isEmpty ? const Icon(Icons.person, size: 28, color: _metinIkincil) : null, ), if (controller.resimYolu.value.isNotEmpty) Positioned( top: 0, right: 0, child: GestureDetector( onTap: controller.resimSil, child: Container( padding: const EdgeInsets.all(2), decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), child: const Icon(Icons.close, size: 12, color: Colors.white), ), ), ), ], )), ), const SizedBox(height: 16), // Isim - Soyisim Row( children: [ Expanded( child: _buildTextField( controller: controller.isimController, label: 'Isim *', hint: 'Isim', ), ), const SizedBox(width: 12), Expanded( child: _buildTextField( controller: controller.soyIsimController, label: 'Soyisim *', hint: 'Soyisim', ), ), ], ), const SizedBox(height: 12), // Cinsiyet Row( children: [ const Text('Cinsiyet:', style: TextStyle( fontSize: 12, color: _metinIkincil)), const SizedBox(width: 12), _cinsiyetButon('E', 'Erkek', Icons.male, _erkekRenk), const SizedBox(width: 8), _cinsiyetButon('K', 'Kadin', Icons.female, _kadinRenk), ], ), const SizedBox(height: 12), // Dogum Tarihi Obx(() => InkWell( onTap: () => controller.dogumTarihiSec(context), borderRadius: BorderRadius.circular(8), child: Container( padding: const EdgeInsets.symmetric( horizontal: 12, vertical: 12), decoration: BoxDecoration( border: Border.all(color: _kenarCizgi), borderRadius: BorderRadius.circular(8), ), child: Row( children: [ const Icon(Icons.calendar_today, size: 16, color: _metinIkincil), const SizedBox(width: 8), Text( controller.dogumTarihi.value != null ? '${controller.dogumTarihi.value!.day.toString().padLeft(2, '0')}.${controller.dogumTarihi.value!.month.toString().padLeft(2, '0')}.${controller.dogumTarihi.value!.year}' : 'Dogum Tarihi (istege bagli)', style: TextStyle( fontSize: 13, color: controller.dogumTarihi.value != null ? _metinBirincil : _metinIkincil, ), ), ], ), ), )), const SizedBox(height: 12), // Meslek _buildTextField( controller: controller.meslekController, label: 'Meslek', hint: 'Meslek (istege bagli)', ), const SizedBox(height: 12), // Dogum Yeri _buildTextField( controller: controller.dogumYeriController, label: 'Dogum Yeri', hint: 'Dogum Yeri (istege bagli)', ), const SizedBox(height: 20), // Footer Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton.icon( onPressed: controller.tiklandiGeri, icon: const Icon(Icons.arrow_back, size: 16), label: const Text('Geri'), style: TextButton.styleFrom(foregroundColor: _metinIkincil), ), FilledButton.icon( onPressed: controller.elleIleri, icon: const Text('Ileri'), label: const Icon(Icons.arrow_forward, size: 16), style: FilledButton.styleFrom(backgroundColor: _erkekRenk), ), ], ), ], ), ), ); } Widget _cinsiyetButon(String deger, String etiket, IconData ikon, Color renk) { return Obx(() { final secili = controller.cinsiyet.value == deger; return InkWell( onTap: () => controller.cinsiyet.value = deger, borderRadius: BorderRadius.circular(8), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: secili ? renk.withOpacity(0.1) : Colors.transparent, border: Border.all(color: secili ? renk : _kenarCizgi), borderRadius: BorderRadius.circular(8), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon(ikon, size: 16, color: secili ? renk : _metinIkincil), const SizedBox(width: 4), Text(etiket, style: TextStyle( fontSize: 12, color: secili ? renk : _metinIkincil, fontWeight: secili ? FontWeight.w600 : FontWeight.normal)), ], ), ), ); }); } // ---- ADIM 3: Mevcut Kisiden Sec ---- Widget _buildMevcutAdimi() { return Padding( key: const ValueKey('mevcut'), padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text('Mevcut kisiden secin', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: _metinBirincil)), const SizedBox(height: 12), // Arama TextField( controller: controller.aramaController, onChanged: (v) => controller.aramaMetni.value = v, decoration: InputDecoration( hintText: 'Isim veya soyisim ile ara...', hintStyle: const TextStyle(fontSize: 13, color: _metinIkincil), prefixIcon: const Icon(Icons.search, size: 18, color: _metinIkincil), contentPadding: const EdgeInsets.symmetric( horizontal: 12, vertical: 10), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide(color: _kenarCizgi), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide(color: _kenarCizgi), ), ), ), const SizedBox(height: 12), // Liste Flexible( child: Obx(() { final kisiler = controller.filtrelenmisKisiler; if (kisiler.isEmpty) { return const Center( child: Padding( padding: EdgeInsets.all(24), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.inbox, size: 32, color: _metinIkincil), SizedBox(height: 8), Text('Kisi bulunamadi', style: TextStyle( fontSize: 13, color: _metinIkincil)), ], ), ), ); } return ListView.separated( shrinkWrap: true, itemCount: kisiler.length, separatorBuilder: (_, __) => const Divider(height: 1, color: _kenarCizgi), itemBuilder: (context, index) { final kisi = kisiler[index]; return _mevcutKisiKart(kisi); }, ); }), ), const SizedBox(height: 12), // Geri Align( alignment: Alignment.centerLeft, child: TextButton.icon( onPressed: controller.tiklandiGeri, icon: const Icon(Icons.arrow_back, size: 16), label: const Text('Geri'), style: TextButton.styleFrom(foregroundColor: _metinIkincil), ), ), ], ), ); } Widget _mevcutKisiKart(FamilyChartDugum kisi) { final renk = kisi.cinsiyet == 'F' ? _kadinRenk : _erkekRenk; return ListTile( dense: true, contentPadding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), leading: CircleAvatar( radius: 18, backgroundColor: renk, child: Text(kisi.basHarf, style: const TextStyle( color: Colors.white, fontSize: 11, fontWeight: FontWeight.w600)), ), title: Text(kisi.tamAd, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w500, color: _metinBirincil)), subtitle: Text( [ kisi.cinsiyet == 'F' ? '\u2640' : '\u2642', if (kisi.dogumTarihi != null && kisi.dogumTarihi!.isNotEmpty) kisi.dogumTarihi!, if (kisi.meslek != null && kisi.meslek!.isNotEmpty) kisi.meslek!, ].join(' \u00B7 '), style: const TextStyle(fontSize: 11, color: _metinIkincil), ), trailing: FilledButton( onPressed: () => controller.mevcutKisiSecildi(kisi), style: FilledButton.styleFrom( backgroundColor: _erkekRenk, padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), minimumSize: Size.zero, textStyle: const TextStyle(fontSize: 12), ), child: const Text('Sec'), ), ); } // ---- ADIM 4: Tur Sec ---- Widget _buildTurSecAdimi() { final hedef = controller.hedefKisiIsim.isNotEmpty ? controller.hedefKisiIsim : 'Ben'; final eklenen = controller.eklenecekKisiIsim; return Padding( key: const ValueKey('turSec'), padding: const EdgeInsets.all(20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ RichText( text: TextSpan( style: const TextStyle(fontSize: 13, color: _metinBirincil), children: [ TextSpan( text: hedef, style: const TextStyle(fontWeight: FontWeight.w700)), const TextSpan(text: ' ile '), TextSpan( text: eklenen, style: const TextStyle(fontWeight: FontWeight.w700)), const TextSpan(text: ' arasindaki akrabalik turunu secin'), ], ), ), const SizedBox(height: 12), Flexible( child: AkrabalikTuruSecWidget( onSecildi: controller.turSecildi, ), ), const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton.icon( onPressed: controller.tiklandiGeri, icon: const Icon(Icons.arrow_back, size: 16), label: const Text('Geri'), style: TextButton.styleFrom(foregroundColor: _metinIkincil), ), const Text('Bir tur secerek devam edin', style: TextStyle(fontSize: 11, color: _metinIkincil)), ], ), ], ), ); } // ---- ADIM 5: Onay ---- Widget _buildOnayAdimi() { return Padding( key: const ValueKey('onay'), padding: const EdgeInsets.all(20), child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Text('Ozeti onaylayin', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: _metinBirincil)), const SizedBox(height: 16), // Ozet karti Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.grey.shade50, borderRadius: BorderRadius.circular(12), border: Border.all(color: _kenarCizgi), ), child: Obx(() { final tur = controller.seciliAkrabalikTuru.value; final bilgi = tur != null ? akrabalikBilgi[tur] : null; final tersBilgi = bilgi?.tersi != null ? akrabalikBilgi[bilgi!.tersi!] : null; final hedef = controller.hedefKisiIsim.isNotEmpty ? controller.hedefKisiIsim : 'Ben'; final eklenen = controller.eklenecekKisiIsim; final eklenenCinsiyet = controller.eklenecekKisiCinsiyet; return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ // Hedef kisi Column( children: [ CircleAvatar( radius: 24, backgroundColor: _erkekRenk, child: Text( hedef.isNotEmpty ? hedef[0].toUpperCase() : 'B', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.w600), ), ), const SizedBox(height: 4), Text(hedef, style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: _metinBirincil)), ], ), // Ok ve tur if (bilgi != null) Column( children: [ Text(bilgi.simge, style: const TextStyle(fontSize: 20)), const SizedBox(height: 2), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 2), decoration: BoxDecoration( color: Color(bilgi.renk).withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: Text(bilgi.isim, style: TextStyle( fontSize: 11, color: Color(bilgi.renk), fontWeight: FontWeight.w600)), ), ], ), // Eklenen kisi Column( children: [ CircleAvatar( radius: 24, backgroundColor: eklenenCinsiyet == 'K' ? _kadinRenk : _erkekRenk, child: Text( eklenen.isNotEmpty ? eklenen[0].toUpperCase() : '?', style: const TextStyle( color: Colors.white, fontWeight: FontWeight.w600), ), ), const SizedBox(height: 4), Text(eklenen, style: const TextStyle( fontSize: 12, fontWeight: FontWeight.w500, color: _metinBirincil)), if (controller.seciliMevcutKisi.value == null) Container( margin: const EdgeInsets.only(top: 2), padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 1), decoration: BoxDecoration( color: _erkekRenk.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: const Text('Yeni Kisi', style: TextStyle( fontSize: 10, color: _erkekRenk)), ), ], ), ], ), if (tersBilgi != null) ...[ const SizedBox(height: 12), Text('Ters iliski: ${tersBilgi.isim}', style: const TextStyle( fontSize: 11, color: _metinIkincil)), ], ], ); }), ), const SizedBox(height: 12), // Not _buildTextField( controller: controller.notlarController, label: 'Not (istege bagli)', hint: 'Bu akrabalik hakkinda not ekleyin...', maxLines: 2, ), const SizedBox(height: 20), // Footer Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ TextButton.icon( onPressed: () => controller.kaydediliyor.value ? null : controller.tiklandiGeri(), icon: const Icon(Icons.arrow_back, size: 16), label: const Text('Geri'), style: TextButton.styleFrom(foregroundColor: _metinIkincil), ), Obx(() => FilledButton.icon( onPressed: controller.kaydediliyor.value ? null : controller.kaydet, icon: controller.kaydediliyor.value ? const SizedBox( width: 14, height: 14, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white), ) : const Icon(Icons.save, size: 16), label: const Text('Kaydet'), style: FilledButton.styleFrom( backgroundColor: _erkekRenk), )), ], ), ], ), ), ); } // ---- Ortak Widgetlar ---- Widget _buildTextField({ required TextEditingController controller, required String label, required String hint, int maxLines = 1, }) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: const TextStyle(fontSize: 12, color: _metinIkincil)), const SizedBox(height: 4), TextField( controller: controller, maxLines: maxLines, style: const TextStyle(fontSize: 13, color: _metinBirincil), decoration: InputDecoration( hintText: hint, hintStyle: const TextStyle(fontSize: 12, color: _metinIkincil), contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide(color: _kenarCizgi), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide(color: _kenarCizgi), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: const BorderSide(color: _erkekRenk), ), ), ), ], ); } }