94 lines
2.7 KiB
Dart
94 lines
2.7 KiB
Dart
// @JsonSerializable()
|
|
class Tag {
|
|
final int id;
|
|
final String name;
|
|
|
|
Tag({required this.id, required this.name});
|
|
|
|
factory Tag.fromJson(Map<String, dynamic> json) {
|
|
return Tag(id: json['id'] as int, name: json['name'] as String);
|
|
}
|
|
}
|
|
|
|
// @JsonSerializable()
|
|
class TimeEntry {
|
|
final int id;
|
|
final int? tagId;
|
|
final String? tagName; // Für einfache Anzeige
|
|
final int startTime; // Unix Timestamp (Sekunden)
|
|
final int? endTime; // Unix Timestamp (Sekunden)
|
|
final int? durationSecs; // Berechnet in Rust
|
|
|
|
TimeEntry({
|
|
required this.id,
|
|
this.tagId,
|
|
this.tagName,
|
|
required this.startTime,
|
|
this.endTime,
|
|
this.durationSecs,
|
|
});
|
|
|
|
factory TimeEntry.fromJson(Map<String, dynamic> json) {
|
|
return TimeEntry(
|
|
id: json['id'] as int,
|
|
tagId: json['tag_id'] as int?,
|
|
tagName: json['tag_name'] as String?,
|
|
startTime: json['start_time'] as int,
|
|
endTime: json['end_time'] as int?,
|
|
durationSecs: json['duration_secs'] as int?,
|
|
);
|
|
}
|
|
|
|
bool get isRunning => endTime == null;
|
|
|
|
DateTime get startDateTime =>
|
|
DateTime.fromMillisecondsSinceEpoch(
|
|
startTime * 1000,
|
|
isUtc: true,
|
|
).toLocal();
|
|
DateTime? get endDateTime =>
|
|
endTime == null
|
|
? null
|
|
: DateTime.fromMillisecondsSinceEpoch(
|
|
endTime! * 1000,
|
|
isUtc: true,
|
|
).toLocal();
|
|
|
|
String get durationFormatted {
|
|
if (durationSecs == null || durationSecs! < 0) return '--:--:--';
|
|
final duration = Duration(seconds: durationSecs!);
|
|
String twoDigits(int n) => n.toString().padLeft(2, "0");
|
|
final hours = twoDigits(duration.inHours);
|
|
final minutes = twoDigits(duration.inMinutes.remainder(60));
|
|
final seconds = twoDigits(duration.inSeconds.remainder(60));
|
|
return "$hours:$minutes:$seconds";
|
|
}
|
|
}
|
|
|
|
// @JsonSerializable()
|
|
class ReportData {
|
|
final List<TimeEntry> entries;
|
|
final int totalDurationSecs;
|
|
|
|
ReportData({required this.entries, required this.totalDurationSecs});
|
|
|
|
factory ReportData.fromJson(Map<String, dynamic> json) {
|
|
var entryList = json['entries'] as List;
|
|
List<TimeEntry> entries =
|
|
entryList.map((i) => TimeEntry.fromJson(i)).toList();
|
|
return ReportData(
|
|
entries: entries,
|
|
totalDurationSecs: json['total_duration_secs'] as int,
|
|
);
|
|
}
|
|
|
|
String get totalDurationFormatted {
|
|
if (totalDurationSecs < 0) return '--:--:--';
|
|
final duration = Duration(seconds: totalDurationSecs);
|
|
String twoDigits(int n) => n.toString().padLeft(2, "0");
|
|
final hours = twoDigits(duration.inHours);
|
|
final minutes = twoDigits(duration.inMinutes.remainder(60));
|
|
final seconds = twoDigits(duration.inSeconds.remainder(60));
|
|
return "$hours:$minutes:$seconds";
|
|
}
|
|
}
|