Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
948 changes: 28 additions & 920 deletions lib/main.dart

Large diffs are not rendered by default.

101 changes: 101 additions & 0 deletions lib/models/analytics.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
class Analytics {
final int totalGrievances;
final int resolvedGrievances;
final int pendingGrievances;
final int inProgressGrievances;
final double averageResolutionTime;
final Map<String, int> grievancesByCategory;
final Map<String, int> grievancesByDepartment;
final Map<String, int> grievancesByStatus;
final Map<String, int> grievancesByPriority;
final List<MonthlyStats> monthlyStats;

Analytics({
required this.totalGrievances,
required this.resolvedGrievances,
required this.pendingGrievances,
required this.inProgressGrievances,
required this.averageResolutionTime,
required this.grievancesByCategory,
required this.grievancesByDepartment,
required this.grievancesByStatus,
required this.grievancesByPriority,
required this.monthlyStats,
});

// Computed properties for admin dashboard compatibility
int get pendingCount => pendingGrievances;
int get underReviewCount => grievancesByStatus['underReview'] ?? 0;
int get inProgressCount => inProgressGrievances;
int get resolvedCount => resolvedGrievances;
int get rejectedCount => grievancesByStatus['closed'] ?? 0;
double get resolutionRate =>
totalGrievances > 0 ? resolvedCount / totalGrievances : 0.0;

Map<String, dynamic> toJson() {
return {
'totalGrievances': totalGrievances,
'resolvedGrievances': resolvedGrievances,
'pendingGrievances': pendingGrievances,
'inProgressGrievances': inProgressGrievances,
'averageResolutionTime': averageResolutionTime,
'grievancesByCategory': grievancesByCategory,
'grievancesByDepartment': grievancesByDepartment,
'grievancesByStatus': grievancesByStatus,
'grievancesByPriority': grievancesByPriority,
'monthlyStats': monthlyStats.map((s) => s.toJson()).toList(),
};
}

factory Analytics.fromJson(Map<String, dynamic> json) {
return Analytics(
totalGrievances: json['totalGrievances'],
resolvedGrievances: json['resolvedGrievances'],
pendingGrievances: json['pendingGrievances'],
inProgressGrievances: json['inProgressGrievances'],
averageResolutionTime: json['averageResolutionTime'].toDouble(),
grievancesByCategory: Map<String, int>.from(json['grievancesByCategory']),
grievancesByDepartment: Map<String, int>.from(
json['grievancesByDepartment'],
),
grievancesByStatus: Map<String, int>.from(json['grievancesByStatus']),
grievancesByPriority: Map<String, int>.from(json['grievancesByPriority']),
monthlyStats:
(json['monthlyStats'] as List)
.map((s) => MonthlyStats.fromJson(s))
.toList(),
);
}
}

class MonthlyStats {
final String month;
final int year;
final int totalSubmitted;
final int totalResolved;

MonthlyStats({
required this.month,
required this.year,
required this.totalSubmitted,
required this.totalResolved,
});

Map<String, dynamic> toJson() {
return {
'month': month,
'year': year,
'totalSubmitted': totalSubmitted,
'totalResolved': totalResolved,
};
}

factory MonthlyStats.fromJson(Map<String, dynamic> json) {
return MonthlyStats(
month: json['month'],
year: json['year'],
totalSubmitted: json['totalSubmitted'],
totalResolved: json['totalResolved'],
);
}
}
189 changes: 189 additions & 0 deletions lib/models/grievance.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
enum GrievanceStatus { pending, underReview, inProgress, resolved, closed }

enum Priority { low, medium, high, urgent }

class Grievance {
final String id;
final String title;
final String description;
final String category;
final Priority priority;
final GrievanceStatus status;
final String studentId;
final String studentName;
final String studentEmail;
final String department;
final String year;
final DateTime submittedDate;
final DateTime? lastUpdated;
final DateTime? resolvedDate;
final List<String> attachments;
final List<StatusUpdate> statusHistory;
final String? assignedTo;
final int? rating;
final String? feedback;

Grievance({
required this.id,
required this.title,
required this.description,
required this.category,
required this.priority,
required this.status,
required this.studentId,
required this.studentName,
required this.studentEmail,
required this.department,
required this.year,
required this.submittedDate,
this.lastUpdated,
this.resolvedDate,
this.attachments = const [],
this.statusHistory = const [],
this.assignedTo,
this.rating,
this.feedback,
});

Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'description': description,
'category': category,
'priority': priority.name,
'status': status.name,
'studentId': studentId,
'studentName': studentName,
'studentEmail': studentEmail,
'department': department,
'year': year,
'submittedDate': submittedDate.toIso8601String(),
'lastUpdated': lastUpdated?.toIso8601String(),
'resolvedDate': resolvedDate?.toIso8601String(),
'attachments': attachments,
'statusHistory': statusHistory.map((s) => s.toJson()).toList(),
'assignedTo': assignedTo,
'rating': rating,
'feedback': feedback,
};
}

factory Grievance.fromJson(Map<String, dynamic> json) {
return Grievance(
id: json['id'],
title: json['title'],
description: json['description'],
category: json['category'],
priority: Priority.values.firstWhere((p) => p.name == json['priority']),
status: GrievanceStatus.values.firstWhere(
(s) => s.name == json['status'],
),
studentId: json['studentId'],
studentName: json['studentName'],
studentEmail: json['studentEmail'],
department: json['department'],
year: json['year'],
submittedDate: DateTime.parse(json['submittedDate']),
lastUpdated:
json['lastUpdated'] != null
? DateTime.parse(json['lastUpdated'])
: null,
resolvedDate:
json['resolvedDate'] != null
? DateTime.parse(json['resolvedDate'])
: null,
attachments: List<String>.from(json['attachments'] ?? []),
statusHistory:
(json['statusHistory'] as List?)
?.map((s) => StatusUpdate.fromJson(s))
.toList() ??
[],
assignedTo: json['assignedTo'],
rating: json['rating'],
feedback: json['feedback'],
);
}

Grievance copyWith({
String? id,
String? title,
String? description,
String? category,
Priority? priority,
GrievanceStatus? status,
String? studentId,
String? studentName,
String? studentEmail,
String? department,
String? year,
DateTime? submittedDate,
DateTime? lastUpdated,
DateTime? resolvedDate,
List<String>? attachments,
List<StatusUpdate>? statusHistory,
String? assignedTo,
int? rating,
String? feedback,
}) {
return Grievance(
id: id ?? this.id,
title: title ?? this.title,
description: description ?? this.description,
category: category ?? this.category,
priority: priority ?? this.priority,
status: status ?? this.status,
studentId: studentId ?? this.studentId,
studentName: studentName ?? this.studentName,
studentEmail: studentEmail ?? this.studentEmail,
department: department ?? this.department,
year: year ?? this.year,
submittedDate: submittedDate ?? this.submittedDate,
lastUpdated: lastUpdated ?? this.lastUpdated,
resolvedDate: resolvedDate ?? this.resolvedDate,
attachments: attachments ?? this.attachments,
statusHistory: statusHistory ?? this.statusHistory,
assignedTo: assignedTo ?? this.assignedTo,
rating: rating ?? this.rating,
feedback: feedback ?? this.feedback,
);
}
}

class StatusUpdate {
final String id;
final GrievanceStatus status;
final String comment;
final DateTime timestamp;
final String updatedBy;

StatusUpdate({
required this.id,
required this.status,
required this.comment,
required this.timestamp,
required this.updatedBy,
});

Map<String, dynamic> toJson() {
return {
'id': id,
'status': status.name,
'comment': comment,
'timestamp': timestamp.toIso8601String(),
'updatedBy': updatedBy,
};
}

factory StatusUpdate.fromJson(Map<String, dynamic> json) {
return StatusUpdate(
id: json['id'],
status: GrievanceStatus.values.firstWhere(
(s) => s.name == json['status'],
),
comment: json['comment'],
timestamp: DateTime.parse(json['timestamp']),
updatedBy: json['updatedBy'],
);
}
}
77 changes: 77 additions & 0 deletions lib/models/notification.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
class AppNotification {
final String id;
final String title;
final String message;
final String userId;
final String? grievanceId;
final DateTime timestamp;
final bool isRead;
final NotificationType type;

AppNotification({
required this.id,
required this.title,
required this.message,
required this.userId,
this.grievanceId,
required this.timestamp,
this.isRead = false,
required this.type,
});

Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'message': message,
'userId': userId,
'grievanceId': grievanceId,
'timestamp': timestamp.toIso8601String(),
'isRead': isRead,
'type': type.name,
};
}

factory AppNotification.fromJson(Map<String, dynamic> json) {
return AppNotification(
id: json['id'],
title: json['title'],
message: json['message'],
userId: json['userId'],
grievanceId: json['grievanceId'],
timestamp: DateTime.parse(json['timestamp']),
isRead: json['isRead'] ?? false,
type: NotificationType.values.firstWhere((t) => t.name == json['type']),
);
}

AppNotification copyWith({
String? id,
String? title,
String? message,
String? userId,
String? grievanceId,
DateTime? timestamp,
bool? isRead,
NotificationType? type,
}) {
return AppNotification(
id: id ?? this.id,
title: title ?? this.title,
message: message ?? this.message,
userId: userId ?? this.userId,
grievanceId: grievanceId ?? this.grievanceId,
timestamp: timestamp ?? this.timestamp,
isRead: isRead ?? this.isRead,
type: type ?? this.type,
);
}
}

enum NotificationType {
statusUpdate,
newGrievance,
assignment,
reminder,
general,
}
Loading