Remade frontend dashboard as flutter dashboard, still WIP
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'achievement.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class Achievement {
|
||||
final int id;
|
||||
final String name;
|
||||
final String description;
|
||||
@JsonKey(name: 'xp_reward')
|
||||
final int xpReward;
|
||||
@JsonKey(name: 'achieved_at')
|
||||
final String? achievedAt;
|
||||
@JsonKey(name: 'level_at_achievement')
|
||||
final int? levelAtAchievement;
|
||||
|
||||
Achievement({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.description,
|
||||
required this.xpReward,
|
||||
this.achievedAt,
|
||||
this.levelAtAchievement,
|
||||
});
|
||||
|
||||
factory Achievement.fromJson(Map<String, dynamic> json) =>
|
||||
_$AchievementFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$AchievementToJson(this);
|
||||
|
||||
bool get isAchieved => achievedAt != null;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'achievement.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Achievement _$AchievementFromJson(Map<String, dynamic> json) => Achievement(
|
||||
id: (json['id'] as num).toInt(),
|
||||
name: json['name'] as String,
|
||||
description: json['description'] as String,
|
||||
xpReward: (json['xp_reward'] as num).toInt(),
|
||||
achievedAt: json['achieved_at'] as String?,
|
||||
levelAtAchievement: (json['level_at_achievement'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AchievementToJson(Achievement instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'name': instance.name,
|
||||
'description': instance.description,
|
||||
'xp_reward': instance.xpReward,
|
||||
'achieved_at': instance.achievedAt,
|
||||
'level_at_achievement': instance.levelAtAchievement,
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'activity.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class Activity {
|
||||
final int id;
|
||||
final String type;
|
||||
final String application;
|
||||
final Map<String, dynamic>? metadata;
|
||||
final String timestamp;
|
||||
@JsonKey(name: 'duration_seconds')
|
||||
final int durationSeconds;
|
||||
|
||||
Activity({
|
||||
required this.id,
|
||||
required this.type,
|
||||
required this.application,
|
||||
this.metadata,
|
||||
required this.timestamp,
|
||||
required this.durationSeconds,
|
||||
});
|
||||
|
||||
factory Activity.fromJson(Map<String, dynamic> json) =>
|
||||
_$ActivityFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ActivityToJson(this);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'activity.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Activity _$ActivityFromJson(Map<String, dynamic> json) => Activity(
|
||||
id: (json['id'] as num).toInt(),
|
||||
type: json['type'] as String,
|
||||
application: json['application'] as String,
|
||||
metadata: json['metadata'] as Map<String, dynamic>?,
|
||||
timestamp: json['timestamp'] as String,
|
||||
durationSeconds: (json['duration_seconds'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ActivityToJson(Activity instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'type': instance.type,
|
||||
'application': instance.application,
|
||||
'metadata': instance.metadata,
|
||||
'timestamp': instance.timestamp,
|
||||
'duration_seconds': instance.durationSeconds,
|
||||
};
|
||||
@@ -0,0 +1,170 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'activity_event.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class ActivityEvent {
|
||||
final ActivityEventType type;
|
||||
final String application;
|
||||
final String? metadata;
|
||||
final DateTime timestamp;
|
||||
|
||||
ActivityEvent({
|
||||
required this.type,
|
||||
required this.application,
|
||||
this.metadata,
|
||||
required this.timestamp,
|
||||
});
|
||||
|
||||
factory ActivityEvent.fromJson(Map<String, dynamic> json) =>
|
||||
_$ActivityEventFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ActivityEventToJson(this);
|
||||
}
|
||||
|
||||
enum ActivityEventType {
|
||||
@JsonValue('coding')
|
||||
coding,
|
||||
@JsonValue('focused_browsing')
|
||||
focusedBrowsing,
|
||||
@JsonValue('collaboration')
|
||||
collaboration,
|
||||
@JsonValue('meetings')
|
||||
meetings,
|
||||
@JsonValue('misc')
|
||||
misc,
|
||||
@JsonValue('uncategorized')
|
||||
uncategorized;
|
||||
|
||||
String get id {
|
||||
switch (this) {
|
||||
case ActivityEventType.coding:
|
||||
return 'coding';
|
||||
case ActivityEventType.focusedBrowsing:
|
||||
return 'focused_browsing';
|
||||
case ActivityEventType.collaboration:
|
||||
return 'collaboration';
|
||||
case ActivityEventType.meetings:
|
||||
return 'meetings';
|
||||
case ActivityEventType.misc:
|
||||
return 'misc';
|
||||
case ActivityEventType.uncategorized:
|
||||
return 'uncategorized';
|
||||
}
|
||||
}
|
||||
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case ActivityEventType.coding:
|
||||
return 'Coding';
|
||||
case ActivityEventType.focusedBrowsing:
|
||||
return 'Focused Browsing';
|
||||
case ActivityEventType.collaboration:
|
||||
return 'Collaboration';
|
||||
case ActivityEventType.meetings:
|
||||
return 'Meetings';
|
||||
case ActivityEventType.misc:
|
||||
return 'Miscellaneous';
|
||||
case ActivityEventType.uncategorized:
|
||||
return 'Uncategorized';
|
||||
}
|
||||
}
|
||||
|
||||
String get icon {
|
||||
switch (this) {
|
||||
case ActivityEventType.coding:
|
||||
return '💻';
|
||||
case ActivityEventType.focusedBrowsing:
|
||||
return '🔍';
|
||||
case ActivityEventType.collaboration:
|
||||
return '🤝';
|
||||
case ActivityEventType.meetings:
|
||||
return '📅';
|
||||
case ActivityEventType.misc:
|
||||
return '📝';
|
||||
case ActivityEventType.uncategorized:
|
||||
return '❓';
|
||||
}
|
||||
}
|
||||
|
||||
static ActivityEventType categorize({
|
||||
String? eventId,
|
||||
String? applicationId,
|
||||
String? applicationTitle,
|
||||
}) {
|
||||
// Direct type mappings
|
||||
if (eventId != null) {
|
||||
final matchType = ActivityEventType.values
|
||||
.where((e) => e.id == eventId)
|
||||
.firstOrNull;
|
||||
if (matchType != null) {
|
||||
return matchType;
|
||||
}
|
||||
}
|
||||
|
||||
if (applicationId != null) {
|
||||
// Fallback to application-based categorization for 'other' type
|
||||
switch (applicationId.toLowerCase()) {
|
||||
case 'codium':
|
||||
case 'code':
|
||||
case 'vscode':
|
||||
case 'nvim':
|
||||
case 'vim':
|
||||
case 'emacs':
|
||||
return coding;
|
||||
case 'com.slack.slack':
|
||||
case 'slack':
|
||||
case 'discord':
|
||||
case 'teams':
|
||||
case 'mattermost':
|
||||
return collaboration;
|
||||
// terminals
|
||||
case 'com.mitchellh.ghostty':
|
||||
case 'alacritty':
|
||||
case 'kitty':
|
||||
case 'gnome-terminal':
|
||||
case 'konsole':
|
||||
case 'foot':
|
||||
switch (applicationTitle) {
|
||||
case String s when s.contains('git'):
|
||||
case String s when s == 'hx' || s == 'helix':
|
||||
return coding;
|
||||
case null:
|
||||
default:
|
||||
return misc;
|
||||
}
|
||||
case 'org.keepassxc.keepassxc':
|
||||
case 'keepassxc':
|
||||
case 'bitwarden':
|
||||
case '1password':
|
||||
return misc; // security tools now categorized as misc
|
||||
case 'firefox':
|
||||
case 'chrome':
|
||||
case 'safari':
|
||||
case 'edge':
|
||||
return focusedBrowsing;
|
||||
case 'zoom':
|
||||
case 'zoom.us':
|
||||
case 'us.zoom.xos':
|
||||
return meetings;
|
||||
default:
|
||||
return uncategorized;
|
||||
}
|
||||
}
|
||||
|
||||
return uncategorized;
|
||||
}
|
||||
}
|
||||
|
||||
enum ZoomStatus {
|
||||
@JsonValue('none')
|
||||
none,
|
||||
@JsonValue('zoom_focused')
|
||||
zoomFocused, // Zoom window active, no media
|
||||
@JsonValue('zoom_background')
|
||||
zoomBackground, // Zoom running, not focused, no media
|
||||
@JsonValue('background_meeting')
|
||||
backgroundMeeting, // Meeting active but Zoom not focused
|
||||
@JsonValue('active_meeting')
|
||||
activeMeeting, // Meeting active and Zoom focused
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'activity_event.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ActivityEvent _$ActivityEventFromJson(Map<String, dynamic> json) =>
|
||||
ActivityEvent(
|
||||
type: $enumDecode(_$ActivityEventTypeEnumMap, json['type']),
|
||||
application: json['application'] as String,
|
||||
metadata: json['metadata'] as String?,
|
||||
timestamp: DateTime.parse(json['timestamp'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ActivityEventToJson(ActivityEvent instance) =>
|
||||
<String, dynamic>{
|
||||
'type': _$ActivityEventTypeEnumMap[instance.type]!,
|
||||
'application': instance.application,
|
||||
'metadata': instance.metadata,
|
||||
'timestamp': instance.timestamp.toIso8601String(),
|
||||
};
|
||||
|
||||
const _$ActivityEventTypeEnumMap = {
|
||||
ActivityEventType.coding: 'coding',
|
||||
ActivityEventType.focusedBrowsing: 'focused_browsing',
|
||||
ActivityEventType.collaboration: 'collaboration',
|
||||
ActivityEventType.meetings: 'meetings',
|
||||
ActivityEventType.misc: 'misc',
|
||||
ActivityEventType.uncategorized: 'uncategorized',
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'classification.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class ApplicationClassification {
|
||||
final int id;
|
||||
@JsonKey(name: 'application_name')
|
||||
final String applicationName;
|
||||
@JsonKey(name: 'category_id')
|
||||
final String categoryId;
|
||||
@JsonKey(name: 'created_at')
|
||||
final String createdAt;
|
||||
@JsonKey(name: 'updated_at')
|
||||
final String updatedAt;
|
||||
|
||||
ApplicationClassification({
|
||||
required this.id,
|
||||
required this.applicationName,
|
||||
required this.categoryId,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
factory ApplicationClassification.fromJson(Map<String, dynamic> json) =>
|
||||
_$ApplicationClassificationFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ApplicationClassificationToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class UnclassifiedApplication {
|
||||
final int id;
|
||||
@JsonKey(name: 'application_name')
|
||||
final String applicationName;
|
||||
@JsonKey(name: 'first_seen')
|
||||
final String firstSeen;
|
||||
@JsonKey(name: 'last_seen')
|
||||
final String lastSeen;
|
||||
@JsonKey(name: 'occurrence_count')
|
||||
final int occurrenceCount;
|
||||
|
||||
UnclassifiedApplication({
|
||||
required this.id,
|
||||
required this.applicationName,
|
||||
required this.firstSeen,
|
||||
required this.lastSeen,
|
||||
required this.occurrenceCount,
|
||||
});
|
||||
|
||||
factory UnclassifiedApplication.fromJson(Map<String, dynamic> json) =>
|
||||
_$UnclassifiedApplicationFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$UnclassifiedApplicationToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ClassificationRequest {
|
||||
@JsonKey(name: 'application_name')
|
||||
final String applicationName;
|
||||
@JsonKey(name: 'category_id')
|
||||
final String categoryId;
|
||||
|
||||
ClassificationRequest({
|
||||
required this.applicationName,
|
||||
required this.categoryId,
|
||||
});
|
||||
|
||||
factory ClassificationRequest.fromJson(Map<String, dynamic> json) =>
|
||||
_$ClassificationRequestFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ClassificationRequestToJson(this);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'classification.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
ApplicationClassification _$ApplicationClassificationFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => ApplicationClassification(
|
||||
id: (json['id'] as num).toInt(),
|
||||
applicationName: json['application_name'] as String,
|
||||
categoryId: json['category_id'] as String,
|
||||
createdAt: json['created_at'] as String,
|
||||
updatedAt: json['updated_at'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ApplicationClassificationToJson(
|
||||
ApplicationClassification instance,
|
||||
) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'application_name': instance.applicationName,
|
||||
'category_id': instance.categoryId,
|
||||
'created_at': instance.createdAt,
|
||||
'updated_at': instance.updatedAt,
|
||||
};
|
||||
|
||||
UnclassifiedApplication _$UnclassifiedApplicationFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => UnclassifiedApplication(
|
||||
id: (json['id'] as num).toInt(),
|
||||
applicationName: json['application_name'] as String,
|
||||
firstSeen: json['first_seen'] as String,
|
||||
lastSeen: json['last_seen'] as String,
|
||||
occurrenceCount: (json['occurrence_count'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$UnclassifiedApplicationToJson(
|
||||
UnclassifiedApplication instance,
|
||||
) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'application_name': instance.applicationName,
|
||||
'first_seen': instance.firstSeen,
|
||||
'last_seen': instance.lastSeen,
|
||||
'occurrence_count': instance.occurrenceCount,
|
||||
};
|
||||
|
||||
ClassificationRequest _$ClassificationRequestFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => ClassificationRequest(
|
||||
applicationName: json['application_name'] as String,
|
||||
categoryId: json['category_id'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$ClassificationRequestToJson(
|
||||
ClassificationRequest instance,
|
||||
) => <String, dynamic>{
|
||||
'application_name': instance.applicationName,
|
||||
'category_id': instance.categoryId,
|
||||
};
|
||||
@@ -0,0 +1,112 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'dashboard_stats.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class DashboardStats {
|
||||
final TodayStats today;
|
||||
final StreakStats streaks;
|
||||
@JsonKey(name: 'recent_activity')
|
||||
final List<RecentActivity> recentActivity;
|
||||
final int timestamp;
|
||||
|
||||
DashboardStats({
|
||||
required this.today,
|
||||
required this.streaks,
|
||||
required this.recentActivity,
|
||||
required this.timestamp,
|
||||
});
|
||||
|
||||
factory DashboardStats.fromJson(Map<String, dynamic> json) =>
|
||||
_$DashboardStatsFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$DashboardStatsToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class TodayStats {
|
||||
final int level;
|
||||
final int xp;
|
||||
@JsonKey(name: 'focus_time')
|
||||
final int focusTime;
|
||||
@JsonKey(name: 'meeting_time')
|
||||
final int meetingTime;
|
||||
@JsonKey(name: 'focus_sessions')
|
||||
final int focusSessions;
|
||||
|
||||
TodayStats({
|
||||
required this.level,
|
||||
required this.xp,
|
||||
required this.focusTime,
|
||||
required this.meetingTime,
|
||||
required this.focusSessions,
|
||||
});
|
||||
|
||||
factory TodayStats.fromJson(Map<String, dynamic> json) =>
|
||||
_$TodayStatsFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$TodayStatsToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class StreakStats {
|
||||
@JsonKey(name: 'current_streak')
|
||||
final int currentStreak;
|
||||
@JsonKey(name: 'longest_streak')
|
||||
final int longestStreak;
|
||||
|
||||
StreakStats({
|
||||
required this.currentStreak,
|
||||
required this.longestStreak,
|
||||
});
|
||||
|
||||
factory StreakStats.fromJson(Map<String, dynamic> json) =>
|
||||
_$StreakStatsFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$StreakStatsToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class RecentActivity {
|
||||
final String type;
|
||||
final String application;
|
||||
final String timestamp;
|
||||
@JsonKey(name: 'duration_seconds')
|
||||
final int durationSeconds;
|
||||
|
||||
RecentActivity({
|
||||
required this.type,
|
||||
required this.application,
|
||||
required this.timestamp,
|
||||
required this.durationSeconds,
|
||||
});
|
||||
|
||||
factory RecentActivity.fromJson(Map<String, dynamic> json) =>
|
||||
_$RecentActivityFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$RecentActivityToJson(this);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class StatsHistory {
|
||||
final String date;
|
||||
final int level;
|
||||
final int xp;
|
||||
@JsonKey(name: 'focus_time')
|
||||
final int focusTime;
|
||||
@JsonKey(name: 'meeting_time')
|
||||
final int meetingTime;
|
||||
|
||||
StatsHistory({
|
||||
required this.date,
|
||||
required this.level,
|
||||
required this.xp,
|
||||
required this.focusTime,
|
||||
required this.meetingTime,
|
||||
});
|
||||
|
||||
factory StatsHistory.fromJson(Map<String, dynamic> json) =>
|
||||
_$StatsHistoryFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$StatsHistoryToJson(this);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'dashboard_stats.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
DashboardStats _$DashboardStatsFromJson(Map<String, dynamic> json) =>
|
||||
DashboardStats(
|
||||
today: TodayStats.fromJson(json['today'] as Map<String, dynamic>),
|
||||
streaks: StreakStats.fromJson(json['streaks'] as Map<String, dynamic>),
|
||||
recentActivity: (json['recent_activity'] as List<dynamic>)
|
||||
.map((e) => RecentActivity.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
timestamp: (json['timestamp'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$DashboardStatsToJson(DashboardStats instance) =>
|
||||
<String, dynamic>{
|
||||
'today': instance.today,
|
||||
'streaks': instance.streaks,
|
||||
'recent_activity': instance.recentActivity,
|
||||
'timestamp': instance.timestamp,
|
||||
};
|
||||
|
||||
TodayStats _$TodayStatsFromJson(Map<String, dynamic> json) => TodayStats(
|
||||
level: (json['level'] as num).toInt(),
|
||||
xp: (json['xp'] as num).toInt(),
|
||||
focusTime: (json['focus_time'] as num).toInt(),
|
||||
meetingTime: (json['meeting_time'] as num).toInt(),
|
||||
focusSessions: (json['focus_sessions'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$TodayStatsToJson(TodayStats instance) =>
|
||||
<String, dynamic>{
|
||||
'level': instance.level,
|
||||
'xp': instance.xp,
|
||||
'focus_time': instance.focusTime,
|
||||
'meeting_time': instance.meetingTime,
|
||||
'focus_sessions': instance.focusSessions,
|
||||
};
|
||||
|
||||
StreakStats _$StreakStatsFromJson(Map<String, dynamic> json) => StreakStats(
|
||||
currentStreak: (json['current_streak'] as num).toInt(),
|
||||
longestStreak: (json['longest_streak'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$StreakStatsToJson(StreakStats instance) =>
|
||||
<String, dynamic>{
|
||||
'current_streak': instance.currentStreak,
|
||||
'longest_streak': instance.longestStreak,
|
||||
};
|
||||
|
||||
RecentActivity _$RecentActivityFromJson(Map<String, dynamic> json) =>
|
||||
RecentActivity(
|
||||
type: json['type'] as String,
|
||||
application: json['application'] as String,
|
||||
timestamp: json['timestamp'] as String,
|
||||
durationSeconds: (json['duration_seconds'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$RecentActivityToJson(RecentActivity instance) =>
|
||||
<String, dynamic>{
|
||||
'type': instance.type,
|
||||
'application': instance.application,
|
||||
'timestamp': instance.timestamp,
|
||||
'duration_seconds': instance.durationSeconds,
|
||||
};
|
||||
|
||||
StatsHistory _$StatsHistoryFromJson(Map<String, dynamic> json) => StatsHistory(
|
||||
date: json['date'] as String,
|
||||
level: (json['level'] as num).toInt(),
|
||||
xp: (json['xp'] as num).toInt(),
|
||||
focusTime: (json['focus_time'] as num).toInt(),
|
||||
meetingTime: (json['meeting_time'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$StatsHistoryToJson(StatsHistory instance) =>
|
||||
<String, dynamic>{
|
||||
'date': instance.date,
|
||||
'level': instance.level,
|
||||
'xp': instance.xp,
|
||||
'focus_time': instance.focusTime,
|
||||
'meeting_time': instance.meetingTime,
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'focus_session.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class FocusSession {
|
||||
final int id;
|
||||
@JsonKey(name: 'start_time')
|
||||
final String startTime;
|
||||
@JsonKey(name: 'end_time')
|
||||
final String? endTime;
|
||||
@JsonKey(name: 'duration_seconds')
|
||||
final int? durationSeconds;
|
||||
@JsonKey(name: 'xp_earned')
|
||||
final int xpEarned;
|
||||
final String status;
|
||||
@JsonKey(name: 'created_at')
|
||||
final String createdAt;
|
||||
@JsonKey(name: 'updated_at')
|
||||
final String updatedAt;
|
||||
|
||||
FocusSession({
|
||||
required this.id,
|
||||
required this.startTime,
|
||||
this.endTime,
|
||||
this.durationSeconds,
|
||||
required this.xpEarned,
|
||||
required this.status,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
});
|
||||
|
||||
factory FocusSession.fromJson(Map<String, dynamic> json) =>
|
||||
_$FocusSessionFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$FocusSessionToJson(this);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'focus_session.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
FocusSession _$FocusSessionFromJson(Map<String, dynamic> json) => FocusSession(
|
||||
id: (json['id'] as num).toInt(),
|
||||
startTime: json['start_time'] as String,
|
||||
endTime: json['end_time'] as String?,
|
||||
durationSeconds: (json['duration_seconds'] as num?)?.toInt(),
|
||||
xpEarned: (json['xp_earned'] as num).toInt(),
|
||||
status: json['status'] as String,
|
||||
createdAt: json['created_at'] as String,
|
||||
updatedAt: json['updated_at'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$FocusSessionToJson(FocusSession instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'start_time': instance.startTime,
|
||||
'end_time': instance.endTime,
|
||||
'duration_seconds': instance.durationSeconds,
|
||||
'xp_earned': instance.xpEarned,
|
||||
'status': instance.status,
|
||||
'created_at': instance.createdAt,
|
||||
'updated_at': instance.updatedAt,
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
part 'system_log.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class SystemLogResponse {
|
||||
final List<String> logs;
|
||||
|
||||
SystemLogResponse({
|
||||
required this.logs,
|
||||
});
|
||||
|
||||
factory SystemLogResponse.fromJson(Map<String, dynamic> json) =>
|
||||
_$SystemLogResponseFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$SystemLogResponseToJson(this);
|
||||
}
|
||||
|
||||
enum LogLevel {
|
||||
@JsonValue('debug')
|
||||
debug,
|
||||
@JsonValue('info')
|
||||
info,
|
||||
@JsonValue('warn')
|
||||
warn,
|
||||
@JsonValue('error')
|
||||
error;
|
||||
|
||||
String get name {
|
||||
switch (this) {
|
||||
case LogLevel.debug:
|
||||
return 'debug';
|
||||
case LogLevel.info:
|
||||
return 'info';
|
||||
case LogLevel.warn:
|
||||
return 'warn';
|
||||
case LogLevel.error:
|
||||
return 'error';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'system_log.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
SystemLogResponse _$SystemLogResponseFromJson(Map<String, dynamic> json) =>
|
||||
SystemLogResponse(
|
||||
logs: (json['logs'] as List<dynamic>).map((e) => e as String).toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SystemLogResponseToJson(SystemLogResponse instance) =>
|
||||
<String, dynamic>{'logs': instance.logs};
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'dashboard_stats.dart';
|
||||
|
||||
part 'websocket_message.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class WebSocketMessage {
|
||||
final WebSocketMessageType type;
|
||||
final Map<String, dynamic>? data;
|
||||
final int timestamp;
|
||||
|
||||
WebSocketMessage({required this.type, this.data, required this.timestamp});
|
||||
|
||||
factory WebSocketMessage.fromJson(Map<String, dynamic> json) => _$WebSocketMessageFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$WebSocketMessageToJson(this);
|
||||
|
||||
// Factory constructors for specific message types
|
||||
factory WebSocketMessage.statsUpdate(DashboardStats stats) {
|
||||
return WebSocketMessage(
|
||||
type: WebSocketMessageType.statsUpdate,
|
||||
data: stats.toJson(),
|
||||
timestamp: DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
|
||||
factory WebSocketMessage.xpBreakdownUpdate(Map<String, int> breakdown) {
|
||||
return WebSocketMessage(
|
||||
type: WebSocketMessageType.xpBreakdownUpdate,
|
||||
data: breakdown,
|
||||
timestamp: DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
|
||||
factory WebSocketMessage.achievementUnlocked(Map<String, dynamic> achievement) {
|
||||
return WebSocketMessage(
|
||||
type: WebSocketMessageType.achievementUnlocked,
|
||||
data: achievement,
|
||||
timestamp: DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
|
||||
factory WebSocketMessage.levelUp(int newLevel) {
|
||||
return WebSocketMessage(
|
||||
type: WebSocketMessageType.levelUp,
|
||||
data: {'level': newLevel},
|
||||
timestamp: DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
|
||||
factory WebSocketMessage.focusSessionComplete(Map<String, dynamic> session) {
|
||||
return WebSocketMessage(
|
||||
type: WebSocketMessageType.focusSessionComplete,
|
||||
data: session,
|
||||
timestamp: DateTime.now().millisecondsSinceEpoch,
|
||||
);
|
||||
}
|
||||
|
||||
factory WebSocketMessage.ping() {
|
||||
return WebSocketMessage(type: WebSocketMessageType.ping, timestamp: DateTime.now().millisecondsSinceEpoch);
|
||||
}
|
||||
|
||||
factory WebSocketMessage.pong() {
|
||||
return WebSocketMessage(type: WebSocketMessageType.pong, timestamp: DateTime.now().millisecondsSinceEpoch);
|
||||
}
|
||||
}
|
||||
|
||||
enum WebSocketMessageType {
|
||||
statsUpdate('stats_update'),
|
||||
xpBreakdownUpdate('xp_breakdown_update'),
|
||||
achievementUnlocked('achievement_unlocked'),
|
||||
levelUp('level_up'),
|
||||
focusSessionComplete('focus_session_complete'),
|
||||
ping('ping'),
|
||||
pong('pong');
|
||||
|
||||
const WebSocketMessageType(this.value);
|
||||
final String value;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'websocket_message.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
WebSocketMessage _$WebSocketMessageFromJson(Map<String, dynamic> json) =>
|
||||
WebSocketMessage(
|
||||
type: $enumDecode(_$WebSocketMessageTypeEnumMap, json['type']),
|
||||
data: json['data'] as Map<String, dynamic>?,
|
||||
timestamp: (json['timestamp'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$WebSocketMessageToJson(WebSocketMessage instance) =>
|
||||
<String, dynamic>{
|
||||
'type': _$WebSocketMessageTypeEnumMap[instance.type]!,
|
||||
'data': instance.data,
|
||||
'timestamp': instance.timestamp,
|
||||
};
|
||||
|
||||
const _$WebSocketMessageTypeEnumMap = {
|
||||
WebSocketMessageType.statsUpdate: 'statsUpdate',
|
||||
WebSocketMessageType.xpBreakdownUpdate: 'xpBreakdownUpdate',
|
||||
WebSocketMessageType.achievementUnlocked: 'achievementUnlocked',
|
||||
WebSocketMessageType.levelUp: 'levelUp',
|
||||
WebSocketMessageType.focusSessionComplete: 'focusSessionComplete',
|
||||
WebSocketMessageType.ping: 'ping',
|
||||
WebSocketMessageType.pong: 'pong',
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
library xp_models;
|
||||
|
||||
// Models
|
||||
export 'src/models/activity_event.dart';
|
||||
export 'src/models/dashboard_stats.dart';
|
||||
export 'src/models/achievement.dart';
|
||||
export 'src/models/activity.dart';
|
||||
export 'src/models/classification.dart';
|
||||
export 'src/models/focus_session.dart';
|
||||
export 'src/models/system_log.dart';
|
||||
export 'src/models/websocket_message.dart';
|
||||
Reference in New Issue
Block a user