244 lines
6.6 KiB
Dart
Raw Permalink Normal View History

2025-07-23 15:02:40 +04:00
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:my_attendance/models/attendance_entry.dart';
import 'package:my_attendance/utils/database_helper.dart';
class AttendanceService with ChangeNotifier {
final DatabaseHelper _dbHelper = DatabaseHelper();
AttendanceEntry? _todayEntry;
AttendanceEntry? get todayEntry => _todayEntry;
List<AttendanceEntry> _history = [];
List<AttendanceEntry> get history => _history;
Map<String, int> _monthlyStats = {};
Map<String, int> get monthlyStats => _monthlyStats;
Map<String, int> _yearlyStats = {};
Map<String, int> get yearlyStats => _yearlyStats;
bool _isLoading = true;
bool get isLoading => _isLoading;
AttendanceService() {
loadTodayEntry();
}
Future<void> logIn() async {
_isLoading = true;
notifyListeners();
try {
final now = DateTime.now();
final date = DateTime(now.year, now.month, now.day);
final entry = AttendanceEntry(
date: date,
loginTime: now,
entryType: EntryType.work,
);
final id = await _dbHelper.insertAttendance(entry);
_todayEntry = entry.copyWith(id: id);
} catch (e) {
debugPrint("Error logging in: $e");
} finally {
_isLoading = false;
notifyListeners();
}
}
Future<void> logOut() async {
if (_todayEntry == null || _todayEntry!.logoutTime != null) return;
_isLoading = true;
notifyListeners();
try {
final now = DateTime.now();
final updatedEntry = _todayEntry!.copyWith(logoutTime: now);
await _dbHelper.updateAttendance(updatedEntry);
_todayEntry = updatedEntry;
} catch (e) {
debugPrint("Error logging out: $e");
} finally {
_isLoading = false;
notifyListeners();
}
}
Future<void> loadTodayEntry() async {
_isLoading = true;
notifyListeners();
try {
final now = DateTime.now();
final date = DateTime(now.year, now.month, now.day);
_todayEntry = await _dbHelper.getAttendanceForDate(date);
} catch (e) {
debugPrint("Error loading today's entry: $e");
} finally {
_isLoading = false;
notifyListeners();
}
}
Future<void> loadHistory({int limit = 10}) async {
_isLoading = true;
notifyListeners();
try {
_history = await _dbHelper.getAttendanceHistory(limit: limit);
} catch (e) {
debugPrint("Error loading history: $e");
} finally {
_isLoading = false;
notifyListeners();
}
}
Future<void> updateNotes(int entryId, String notes) async {
try {
AttendanceEntry? entryToUpdate;
if (_todayEntry?.id == entryId) {
entryToUpdate = _todayEntry;
} else {
entryToUpdate = _history.firstWhere((e) => e.id == entryId);
}
if (entryToUpdate != null) {
final updated = entryToUpdate.copyWith(notes: notes);
await _dbHelper.updateAttendance(updated);
await loadTodayEntry();
await loadHistory();
await calculateStats();
}
} catch (e) {
debugPrint("Error updating notes: $e");
}
}
Future<void> markAsWfh() async {
_isLoading = true;
notifyListeners();
try {
final now = DateTime.now();
final date = DateTime(now.year, now.month, now.day);
final entry = AttendanceEntry(date: date, entryType: EntryType.wfh);
final id = await _dbHelper.insertAttendance(entry);
_todayEntry = entry.copyWith(id: id);
await calculateStats();
} catch (e) {
debugPrint("Error marking as WFH: $e");
} finally {
_isLoading = false;
notifyListeners();
}
}
Future<void> markAsLeave(LeaveType leaveType) async {
_isLoading = true;
notifyListeners();
try {
final now = DateTime.now();
final date = DateTime(now.year, now.month, now.day);
final entry = AttendanceEntry(
date: date,
entryType: EntryType.leave,
leaveType: leaveType,
);
final id = await _dbHelper.insertAttendance(entry);
_todayEntry = entry.copyWith(id: id);
await calculateStats();
} catch (e) {
debugPrint("Error marking as leave: $e");
} finally {
_isLoading = false;
notifyListeners();
}
}
Future<void> resetData() async {
_isLoading = true;
notifyListeners();
try {
await _dbHelper.resetDatabase();
_todayEntry = null;
_history = [];
await calculateStats();
} catch (e) {
debugPrint("Error resetting data: $e");
} finally {
_isLoading = false;
notifyListeners();
}
}
Future<void> updateOrCreateEntry(AttendanceEntry entry) async {
final existingEntry = await _dbHelper.getAttendanceForDate(entry.date);
if (existingEntry != null) {
// Preserve the original ID when updating
await _dbHelper.updateAttendance(entry.copyWith(id: existingEntry.id));
} else {
await _dbHelper.insertAttendance(entry);
}
// Refresh data to reflect changes
await loadTodayEntry();
await loadHistory();
await calculateStats();
}
Future<AttendanceEntry?> getEntryForDate(DateTime date) async {
return await _dbHelper.getAttendanceForDate(date);
}
Future<void> calculateStats() async {
final now = DateTime.now();
// Monthly stats
final monthStart = DateTime(now.year, now.month, 1);
final monthEnd = DateTime(now.year, now.month + 1, 0);
final monthlyEntries = await _dbHelper.getAttendanceInRange(
monthStart,
monthEnd,
);
_monthlyStats = _calculateCounts(monthlyEntries);
// Yearly stats
final yearStart = DateTime(now.year, 1, 1);
final yearEnd = DateTime(now.year, 12, 31);
final yearlyEntries = await _dbHelper.getAttendanceInRange(
yearStart,
yearEnd,
);
_yearlyStats = _calculateCounts(yearlyEntries);
notifyListeners();
}
Map<String, int> _calculateCounts(List<AttendanceEntry> entries) {
final counts = <String, int>{};
for (final entry in entries) {
if (entry.entryType == EntryType.wfh) {
counts['Work From Home'] = (counts['Work From Home'] ?? 0) + 1;
} else if (entry.entryType == EntryType.leave) {
final leaveName = _getLeaveTypeName(entry.leaveType);
counts[leaveName] = (counts[leaveName] ?? 0) + 1;
}
}
return counts;
}
String _getLeaveTypeName(LeaveType? type) {
switch (type) {
case LeaveType.sick:
return 'Sick Leave';
case LeaveType.annual:
return 'Annual Leave';
case LeaveType.nationalHoliday:
return 'National Holiday';
case LeaveType.companyWfh:
return 'Company WFH';
default:
return 'On Leave';
}
}
}