import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import '../../models/time_registration.dart'; import '../../providers/auth_provider.dart'; import '../../providers/time_provider.dart'; class ManualEntryScreen extends ConsumerStatefulWidget { const ManualEntryScreen({super.key}); @override ConsumerState createState() => _ManualEntryScreenState(); } class _ManualEntryScreenState extends ConsumerState { final _formKey = GlobalKey(); final _commentController = TextEditingController(); final _projectController = TextEditingController(); final _customerController = TextEditingController(); late DateTime _selectedDate; late TimeOfDay _startTime; late TimeOfDay _endTime; RegistrationType _selectedType = RegistrationType.ordinary; bool _isLoading = false; @override void initState() { super.initState(); _selectedDate = DateTime.now(); _startTime = const TimeOfDay(hour: 8, minute: 0); _endTime = const TimeOfDay(hour: 16, minute: 0); } @override void dispose() { _commentController.dispose(); _projectController.dispose(); _customerController.dispose(); super.dispose(); } Future _selectDate(BuildContext context) async { final DateTime? picked = await showDatePicker( context: context, initialDate: _selectedDate, firstDate: DateTime(2020), lastDate: DateTime.now(), locale: const Locale('nb', 'NO'), ); if (picked != null && picked != _selectedDate) { setState(() { _selectedDate = picked; }); } } Future _selectTime(BuildContext context, bool isStart) async { final TimeOfDay? picked = await showTimePicker( context: context, initialTime: isStart ? _startTime : _endTime, builder: (context, child) { return MediaQuery( data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true), child: child!, ); }, ); if (picked != null) { setState(() { if (isStart) { _startTime = picked; } else { _endTime = picked; } }); } } Future _saveRegistration() async { if (!_formKey.currentState!.validate()) return; setState(() => _isLoading = true); try { final user = ref.read(currentUserProvider); final userData = await ref.read(userDataProvider.future); if (user == null || userData == null) { throw Exception('Ingen brukerdata funnet'); } final startDateTime = DateTime( _selectedDate.year, _selectedDate.month, _selectedDate.day, _startTime.hour, _startTime.minute, ); var endDateTime = DateTime( _selectedDate.year, _selectedDate.month, _selectedDate.day, _endTime.hour, _endTime.minute, ); // Håndter nattarbeid (hvis slutt er før start, antar vi neste dag) if (endDateTime.isBefore(startDateTime)) { endDateTime = endDateTime.add(const Duration(days: 1)); } final timeService = ref.read(timeServiceProvider); await timeService.createManualEntry( userId: user.uid, organizationId: userData.organizationId, startTime: startDateTime, endTime: endDateTime, type: _selectedType, projectId: _projectController.text.isNotEmpty ? _projectController.text : null, customerId: _customerController.text.isNotEmpty ? _customerController.text : null, comment: _commentController.text.isNotEmpty ? _commentController.text : null, ); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Timeregistrering lagret')), ); Navigator.pop(context); // Oppdater lister ref.invalidate(todayRegistrationsProvider); } } catch (e) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Feil: $e')), ); } } finally { if (mounted) { setState(() => _isLoading = false); } } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Manuell registrering'), ), body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Dato ListTile( title: const Text('Dato'), subtitle: Text(DateFormat('EEEE d. MMMM yyyy', 'nb_NO').format(_selectedDate)), leading: const Icon(Icons.calendar_today), onTap: () => _selectDate(context), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: Colors.grey.shade300), ), ), const SizedBox(height: 16), // Tidspunkt Row( children: [ Expanded( child: ListTile( title: const Text('Start'), subtitle: Text(_startTime.format(context)), leading: const Icon(Icons.access_time), onTap: () => _selectTime(context, true), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: Colors.grey.shade300), ), ), ), const SizedBox(width: 16), Expanded( child: ListTile( title: const Text('Slutt'), subtitle: Text(_endTime.format(context)), leading: const Icon(Icons.access_time_filled), onTap: () => _selectTime(context, false), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), side: BorderSide(color: Colors.grey.shade300), ), ), ), ], ), const SizedBox(height: 16), // Type arbeid DropdownButtonFormField( value: _selectedType, decoration: const InputDecoration( labelText: 'Type arbeid', prefixIcon: Icon(Icons.category), ), items: RegistrationType.values.map((type) { return DropdownMenuItem( value: type, child: Text(_getTypeDisplayName(type)), ); }).toList(), onChanged: (value) { if (value != null) { setState(() => _selectedType = value); } }, ), const SizedBox(height: 16), // Prosjekt og Kunde TextFormField( controller: _customerController, decoration: const InputDecoration( labelText: 'Kunde (valgfritt)', prefixIcon: Icon(Icons.business), ), ), const SizedBox(height: 16), TextFormField( controller: _projectController, decoration: const InputDecoration( labelText: 'Prosjekt (valgfritt)', prefixIcon: Icon(Icons.folder), ), ), const SizedBox(height: 16), // Kommentar TextFormField( controller: _commentController, decoration: const InputDecoration( labelText: 'Kommentar (valgfritt)', prefixIcon: Icon(Icons.comment), ), maxLines: 3, ), const SizedBox(height: 32), // Lagre knapp FilledButton( onPressed: _isLoading ? null : _saveRegistration, style: FilledButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), ), child: _isLoading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : const Text('Lagre registrering'), ), ], ), ), ), ); } String _getTypeDisplayName(RegistrationType type) { switch (type) { case RegistrationType.ordinary: return 'Ordinær arbeidstid'; case RegistrationType.overtime: return 'Overtid'; case RegistrationType.oncall: return 'Beredskap/Vakt'; case RegistrationType.travel: return 'Reisetid'; } } }