Initial commit: TimeReg Flutter app med Firebase backend
- 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
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user