c829f78984
- Opprettet Flutter-prosjekt med alle nødvendige avhengigheter - Implementert datamodeller (User, TimeRegistration, TariffProfile, Deviation, AuditLog) - Implementert tjenester (AuthService, TimeService) - Implementert Riverpod providers for state management - Opprettet autentiseringsskjermer (login, signup, reset password) - Opprettet hjemmeskjerm med timer-funksjonalitet - Opprettet placeholder-skjermer for historikk, rapporter og profil - Lagt til norsk dokumentasjon i README
181 lines
4.9 KiB
Dart
181 lines
4.9 KiB
Dart
import 'package:cloud_firestore/cloud_firestore.dart';
|
|
|
|
enum DeviationType {
|
|
dailyMax,
|
|
weeklyMax,
|
|
dailyRest,
|
|
weeklyRest,
|
|
averageExceeded,
|
|
nightWork,
|
|
}
|
|
|
|
enum DeviationSeverity {
|
|
warning,
|
|
violation,
|
|
}
|
|
|
|
class DeviationMetadata {
|
|
final double actualValue;
|
|
final double limitValue;
|
|
final String? period;
|
|
|
|
DeviationMetadata({
|
|
required this.actualValue,
|
|
required this.limitValue,
|
|
this.period,
|
|
});
|
|
|
|
factory DeviationMetadata.fromMap(Map<String, dynamic> map) {
|
|
return DeviationMetadata(
|
|
actualValue: (map['actualValue'] ?? 0).toDouble(),
|
|
limitValue: (map['limitValue'] ?? 0).toDouble(),
|
|
period: map['period'],
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toMap() {
|
|
return {
|
|
'actualValue': actualValue,
|
|
'limitValue': limitValue,
|
|
'period': period,
|
|
};
|
|
}
|
|
}
|
|
|
|
class Deviation {
|
|
final String id;
|
|
final String userId;
|
|
final String organizationId;
|
|
final String timeRegistrationId;
|
|
final DeviationType type;
|
|
final DeviationSeverity severity;
|
|
final String description;
|
|
final DateTime detectedAt;
|
|
final DateTime? acknowledgedAt;
|
|
final String? acknowledgedBy;
|
|
final DeviationMetadata metadata;
|
|
|
|
Deviation({
|
|
required this.id,
|
|
required this.userId,
|
|
required this.organizationId,
|
|
required this.timeRegistrationId,
|
|
required this.type,
|
|
required this.severity,
|
|
required this.description,
|
|
required this.detectedAt,
|
|
this.acknowledgedAt,
|
|
this.acknowledgedBy,
|
|
required this.metadata,
|
|
});
|
|
|
|
factory Deviation.fromFirestore(DocumentSnapshot doc) {
|
|
final data = doc.data() as Map<String, dynamic>;
|
|
return Deviation(
|
|
id: doc.id,
|
|
userId: data['userId'] ?? '',
|
|
organizationId: data['organizationId'] ?? '',
|
|
timeRegistrationId: data['timeRegistrationId'] ?? '',
|
|
type: _parseType(data['type']),
|
|
severity: _parseSeverity(data['severity']),
|
|
description: data['description'] ?? '',
|
|
detectedAt: (data['detectedAt'] as Timestamp).toDate(),
|
|
acknowledgedAt: data['acknowledgedAt'] != null
|
|
? (data['acknowledgedAt'] as Timestamp).toDate()
|
|
: null,
|
|
acknowledgedBy: data['acknowledgedBy'],
|
|
metadata: DeviationMetadata.fromMap(data['metadata'] ?? {}),
|
|
);
|
|
}
|
|
|
|
Map<String, dynamic> toFirestore() {
|
|
return {
|
|
'userId': userId,
|
|
'organizationId': organizationId,
|
|
'timeRegistrationId': timeRegistrationId,
|
|
'type': type.name,
|
|
'severity': severity.name,
|
|
'description': description,
|
|
'detectedAt': Timestamp.fromDate(detectedAt),
|
|
'acknowledgedAt':
|
|
acknowledgedAt != null ? Timestamp.fromDate(acknowledgedAt!) : null,
|
|
'acknowledgedBy': acknowledgedBy,
|
|
'metadata': metadata.toMap(),
|
|
};
|
|
}
|
|
|
|
static DeviationType _parseType(String? typeString) {
|
|
switch (typeString) {
|
|
case 'dailyMax':
|
|
return DeviationType.dailyMax;
|
|
case 'weeklyMax':
|
|
return DeviationType.weeklyMax;
|
|
case 'dailyRest':
|
|
return DeviationType.dailyRest;
|
|
case 'weeklyRest':
|
|
return DeviationType.weeklyRest;
|
|
case 'averageExceeded':
|
|
return DeviationType.averageExceeded;
|
|
case 'nightWork':
|
|
return DeviationType.nightWork;
|
|
default:
|
|
return DeviationType.dailyMax;
|
|
}
|
|
}
|
|
|
|
static DeviationSeverity _parseSeverity(String? severityString) {
|
|
switch (severityString) {
|
|
case 'violation':
|
|
return DeviationSeverity.violation;
|
|
default:
|
|
return DeviationSeverity.warning;
|
|
}
|
|
}
|
|
|
|
String get typeDisplayName {
|
|
switch (type) {
|
|
case DeviationType.dailyMax:
|
|
return 'Maks daglig arbeidstid';
|
|
case DeviationType.weeklyMax:
|
|
return 'Maks ukentlig arbeidstid';
|
|
case DeviationType.dailyRest:
|
|
return 'Daglig hviletid';
|
|
case DeviationType.weeklyRest:
|
|
return 'Ukentlig hviletid';
|
|
case DeviationType.averageExceeded:
|
|
return 'Gjennomsnittsberegning overskredet';
|
|
case DeviationType.nightWork:
|
|
return 'Nattarbeid';
|
|
}
|
|
}
|
|
|
|
bool get isAcknowledged => acknowledgedAt != null;
|
|
|
|
Deviation copyWith({
|
|
String? userId,
|
|
String? organizationId,
|
|
String? timeRegistrationId,
|
|
DeviationType? type,
|
|
DeviationSeverity? severity,
|
|
String? description,
|
|
DateTime? detectedAt,
|
|
DateTime? acknowledgedAt,
|
|
String? acknowledgedBy,
|
|
DeviationMetadata? metadata,
|
|
}) {
|
|
return Deviation(
|
|
id: id,
|
|
userId: userId ?? this.userId,
|
|
organizationId: organizationId ?? this.organizationId,
|
|
timeRegistrationId: timeRegistrationId ?? this.timeRegistrationId,
|
|
type: type ?? this.type,
|
|
severity: severity ?? this.severity,
|
|
description: description ?? this.description,
|
|
detectedAt: detectedAt ?? this.detectedAt,
|
|
acknowledgedAt: acknowledgedAt ?? this.acknowledgedAt,
|
|
acknowledgedBy: acknowledgedBy ?? this.acknowledgedBy,
|
|
metadata: metadata ?? this.metadata,
|
|
);
|
|
}
|
|
}
|