import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../core/providers/auth_provider.dart'; import '../../core/theme/app_theme.dart'; import '../shared/location_picker_sheet.dart'; import '../shared/tenant_location_data.dart'; import 'onboarding_repository.dart'; class OnboardingScreen extends ConsumerStatefulWidget { const OnboardingScreen({super.key}); @override ConsumerState createState() => _OnboardingScreenState(); } class _OnboardingScreenState extends ConsumerState with SingleTickerProviderStateMixin { final _formKey = GlobalKey(); final _nameCtrl = TextEditingController(); String _selectedKind = 'clinic'; TenantLocationData? _location; bool _loading = false; String? _error; late AnimationController _animCtrl; late Animation _fadeAnim; late Animation _slideAnim; @override void initState() { super.initState(); _animCtrl = AnimationController( vsync: this, duration: const Duration(milliseconds: 600), ); _fadeAnim = CurvedAnimation(parent: _animCtrl, curve: Curves.easeOut); _slideAnim = Tween( begin: const Offset(0, 0.08), end: Offset.zero, ).animate(CurvedAnimation(parent: _animCtrl, curve: Curves.easeOutCubic)); _animCtrl.forward(); } @override void dispose() { _animCtrl.dispose(); _nameCtrl.dispose(); super.dispose(); } Future _create() async { if (!_formKey.currentState!.validate()) return; setState(() { _loading = true; _error = null; }); try { final result = await OnboardingRepository.instance.createTenantAndJoin( kind: _selectedKind, companyName: _nameCtrl.text.trim(), companyAddress: _location?.address, city: _location?.city, district: _location?.district, latitude: _location?.latitude, longitude: _location?.longitude, ); if (!mounted) return; ref.read(authProvider.notifier).setActiveTenant(result.tenants.first); } catch (e) { setState(() { _error = 'Hesap oluşturulamadı. Lütfen tekrar deneyin.'; _loading = false; }); } } @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; final size = MediaQuery.sizeOf(context); return Scaffold( backgroundColor: const Color(0xFF4F46E5), body: Stack( children: [ // ── Gradient background ────────────────────────────────────────── Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomCenter, colors: [Color(0xFF3730A3), Color(0xFF6366F1)], ), ), ), // ── Decorative circles ─────────────────────────────────────────── Positioned( top: -40, right: -60, child: Container( width: 220, height: 220, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withValues(alpha: 0.06), ), ), ), Positioned( top: 80, left: -70, child: Container( width: 200, height: 200, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withValues(alpha: 0.04), ), ), ), // ── Content ────────────────────────────────────────────────────── Column( children: [ // Header SafeArea( bottom: false, child: SizedBox( height: size.height * 0.26, child: Stack( children: [ // Sign out Positioned( right: 8, top: 4, child: TextButton.icon( onPressed: () => ref.read(authProvider.notifier).signOut(), icon: const Icon(Icons.logout_rounded, color: Colors.white70, size: 18), label: const Text( 'Çıkış', style: TextStyle(color: Colors.white70), ), ), ), Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 68, height: 68, decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.15), borderRadius: BorderRadius.circular(20), border: Border.all( color: Colors.white.withValues(alpha: 0.3), width: 1.5, ), ), child: const Icon( Icons.domain_add_rounded, size: 32, color: Colors.white, ), ), const SizedBox(height: 14), const Text( 'Kurumunuzu Oluşturun', style: TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.w700, letterSpacing: 0.3, ), ), const SizedBox(height: 4), Text( 'Klinik veya laboratuvar olarak kayıt olun', style: TextStyle( color: Colors.white.withValues(alpha: 0.70), fontSize: 13, ), ), ], ), ), ], ), ), ), // Form card Expanded( child: FadeTransition( opacity: _fadeAnim, child: SlideTransition( position: _slideAnim, child: Container( decoration: BoxDecoration( color: cs.surface, borderRadius: const BorderRadius.vertical( top: Radius.circular(32), ), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.15), blurRadius: 24, offset: const Offset(0, -4), ), ], ), child: SingleChildScrollView( padding: const EdgeInsets.fromLTRB(28, 32, 28, 24), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( 'Kurum Türünü Seçin', style: Theme.of(context) .textTheme .titleMedium ?.copyWith(fontWeight: FontWeight.w600), ), const SizedBox(height: 14), // Kind cards Row( children: [ Expanded( child: _KindCard( icon: Icons.local_hospital_outlined, label: 'Klinik', description: 'Diş kliniği', value: 'clinic', selected: _selectedKind == 'clinic', onTap: () => setState( () => _selectedKind = 'clinic'), ), ), const SizedBox(width: 12), Expanded( child: _KindCard( icon: Icons.science_outlined, label: 'Laboratuvar', description: 'Diş laboratuvarı', value: 'lab', selected: _selectedKind == 'lab', onTap: () => setState(() => _selectedKind = 'lab'), ), ), ], ), const SizedBox(height: 24), Text( 'Konum', style: Theme.of(context) .textTheme .titleMedium ?.copyWith(fontWeight: FontWeight.w600), ), const SizedBox(height: 10), Container( padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(14), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _location?.fullLabel.isNotEmpty == true ? _location!.fullLabel : 'Konumu haritadan seçin. Laboratuvar aramalarında bu veri kullanılacak.', style: TextStyle( fontSize: 13, color: _location == null ? cs.onSurfaceVariant : cs.onSurface, ), ), if (_location?.hasCoordinates == true) ...[ const SizedBox(height: 8), Text( '${_location!.latitude!.toStringAsFixed(6)}, ${_location!.longitude!.toStringAsFixed(6)}', style: const TextStyle( fontSize: 12, color: AppColors.textMuted, ), ), ], const SizedBox(height: 12), OutlinedButton.icon( onPressed: () async { final picked = await showLocationPickerSheet( context, initialLocation: _location, title: _selectedKind == 'lab' ? 'Laboratuvar Konumu' : 'Klinik Konumu', ); if (picked != null) { setState(() => _location = picked); } }, icon: const Icon(Icons.map_outlined), label: Text(_location == null ? 'Haritadan Seç' : 'Konumu Güncelle'), ), ], ), ), const SizedBox(height: 24), // Company name Text( 'Kurum Adı', style: Theme.of(context) .textTheme .titleMedium ?.copyWith(fontWeight: FontWeight.w600), ), const SizedBox(height: 10), TextFormField( controller: _nameCtrl, textInputAction: TextInputAction.done, textCapitalization: TextCapitalization.words, onFieldSubmitted: (_) => _create(), decoration: InputDecoration( labelText: _selectedKind == 'clinic' ? 'Klinik Adı' : 'Laboratuvar Adı', prefixIcon: const Icon( Icons.business_outlined, size: 20), filled: true, fillColor: cs.surfaceContainerHighest, border: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: BorderSide.none, ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: BorderSide.none, ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: const BorderSide( color: Color(0xFF4F46E5), width: 2), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: BorderSide(color: cs.error, width: 1.5), ), focusedErrorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(14), borderSide: BorderSide(color: cs.error, width: 2), ), contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 16), ), validator: (v) { if (v == null || v.trim().isEmpty) { return 'Kurum adı gereklidir'; } if (v.trim().length < 3) { return 'En az 3 karakter olmalıdır'; } return null; }, ), // Error banner if (_error != null) ...[ const SizedBox(height: 14), Container( padding: const EdgeInsets.symmetric( horizontal: 14, vertical: 10), decoration: BoxDecoration( color: cs.errorContainer, borderRadius: BorderRadius.circular(12), ), child: Row( children: [ Icon(Icons.error_outline_rounded, color: cs.onErrorContainer, size: 18), const SizedBox(width: 8), Expanded( child: Text( _error!, style: TextStyle( color: cs.onErrorContainer, fontSize: 13), ), ), ], ), ), ], const SizedBox(height: 28), FilledButton( onPressed: _loading || _location == null ? null : _create, style: FilledButton.styleFrom( minimumSize: const Size.fromHeight(52), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(14), ), backgroundColor: const Color(0xFF4F46E5), ), child: _loading ? const SizedBox( height: 22, width: 22, child: CircularProgressIndicator( strokeWidth: 2.5, color: Colors.white, ), ) : const Text( 'Devam Et', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ), ], ), ), ), ), ), ), ), ], ), ], ), ); } } class _KindCard extends StatelessWidget { const _KindCard({ required this.icon, required this.label, required this.description, required this.value, required this.selected, required this.onTap, }); final IconData icon; final String label; final String description; final String value; final bool selected; final VoidCallback onTap; @override Widget build(BuildContext context) { final cs = Theme.of(context).colorScheme; return InkWell( onTap: onTap, borderRadius: BorderRadius.circular(16), child: AnimatedContainer( duration: const Duration(milliseconds: 180), padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 12), decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), border: Border.all( color: selected ? const Color(0xFF4F46E5) : cs.outlineVariant, width: selected ? 2 : 1, ), color: selected ? const Color(0xFF4F46E5).withValues(alpha: 0.08) : cs.surfaceContainerLow, ), child: Column( children: [ Container( width: 48, height: 48, decoration: BoxDecoration( color: selected ? const Color(0xFF4F46E5).withValues(alpha: 0.12) : cs.surfaceContainerHighest, borderRadius: BorderRadius.circular(12), ), child: Icon( icon, size: 26, color: selected ? const Color(0xFF4F46E5) : cs.onSurfaceVariant, ), ), const SizedBox(height: 10), Text( label, style: TextStyle( fontWeight: FontWeight.w600, fontSize: 14, color: selected ? const Color(0xFF4F46E5) : cs.onSurface, ), ), const SizedBox(height: 2), Text( description, style: TextStyle( fontSize: 11, color: cs.onSurfaceVariant, ), ), ], ), ), ); } }