feat: show missing requirements on dashboard student hover, fix student grade/sec resolution, and scope teacher stats to assigned sections

This commit is contained in:
ssbg04 committed 2026-08-30 14:05:10 +08:00
1 parent 42d97dd32a
commit f2c259891d
5 files changed
+226 -157

No files matched your search

+5 -2
View File
@@ -431,9 +431,12 @@ Files backup/restore - mirror mode or zip -->
# TEACHERS & ACADEMIC SETUP
- hide or remove from the list all users have deactivated status -->
<!--
# STUDENT SCREEN
- student profile modal -> make the lrn can be copy add icon button to automatically copy
- student profile modal -> make the lrn can be copy add icon button to automatically copy -->
# DASHBOARD SCREEN
- "Top students by documents" and "needs attention" view all -> list of students count of missing documents when hover shows missing requirements separate jhs shs
---
@@ -231,6 +231,7 @@ class StudentDocCount {
final int uploadedCount;
final int totalRequired;
final int missingCount;
final List<String> missingRequirements;
final double percent;
final int? gradeLevel;
final String category;
@@ -242,6 +243,7 @@ class StudentDocCount {
this.uploadedCount = 0,
this.totalRequired = 0,
this.missingCount = 0,
this.missingRequirements = const [],
this.percent = 0.0,
this.gradeLevel,
this.category = 'JHS',
@@ -256,6 +258,11 @@ class StudentDocCount {
final pct = (j['percent'] as num?)?.toDouble() ??
(total == 0 ? (uploaded > 0 ? 1.0 : 0.0) : uploaded / total);
final missingReqs = (j['missingRequirements'] as List<dynamic>?)
?.map((e) => e.toString())
.toList() ??
const [];
return StudentDocCount(
id: (j['id'] as num?)?.toInt() ?? 0,
name: j['name'] as String? ?? '',
@@ -263,6 +270,7 @@ class StudentDocCount {
uploadedCount: uploaded,
totalRequired: total,
missingCount: missing,
missingRequirements: missingReqs,
percent: pct,
gradeLevel: (j['gradeLevel'] as num?)?.toInt(),
category: j['category'] as String? ?? 'JHS',
@@ -1633,16 +1633,49 @@ class _StudentDocCard extends StatelessWidget {
overflow: TextOverflow.ellipsis,
),
),
Text(
'${s.uploadedCount} / ${s.totalRequired} (${s.missingCount} missing)',
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
color: s.missingCount == 0
? (isDark ? const Color(0xFF66BB6A) : AppColors.primaryGreen)
: (isTop
? Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.7)
: Colors.orange.shade700),
Tooltip(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: isDark ? const Color(0xFF1E293B) : const Color(0xFF0F172A),
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.2),
blurRadius: 6,
offset: const Offset(0, 2),
),
],
),
textStyle: const TextStyle(fontSize: 11, color: Colors.white, height: 1.4),
message: s.missingCount == 0
? '[${s.category}] All ${s.totalRequired} required documents submitted! ✅'
: '[${s.category} Missing Requirements (${s.missingCount})]:\n• ${s.missingRequirements.join('\n• ')}',
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
'${s.uploadedCount} / ${s.totalRequired} (${s.missingCount} missing)',
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w600,
color: s.missingCount == 0
? (isDark ? const Color(0xFF66BB6A) : AppColors.primaryGreen)
: (isTop
? Theme.of(context).colorScheme.onSurface.withValues(alpha: 0.7)
: Colors.orange.shade700),
),
),
if (s.missingCount > 0) ...[
const SizedBox(width: 4),
Icon(
Icons.info_outline_rounded,
size: 12,
color: s.missingCount == 0
? AppColors.primaryGreen
: Colors.orange.shade700,
),
],
],
),
),
],
@@ -2060,23 +2093,54 @@ class _StudentDocRankingModalState extends State<_StudentDocRankingModal> {
),
const SizedBox(width: 10),
// Status Pill
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
// Status Pill with hover tooltip showing missing requirements separated by category
Tooltip(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: isComplete
? AppColors.primaryGreen.withValues(alpha: isDark ? 0.25 : 0.12)
: Colors.orange.withValues(alpha: isDark ? 0.25 : 0.12),
borderRadius: BorderRadius.circular(4),
color: isDark ? const Color(0xFF1E293B) : const Color(0xFF0F172A),
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.2),
blurRadius: 6,
offset: const Offset(0, 2),
),
],
),
child: Text(
isComplete ? 'Complete' : '${s.missingCount} Missing',
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
textStyle: const TextStyle(fontSize: 11, color: Colors.white, height: 1.4),
message: isComplete
? '[${s.category}] All ${s.totalRequired} required documents submitted! ✅'
: '[${s.category} Missing Requirements (${s.missingCount})]:\n• ${s.missingRequirements.join('\n• ')}',
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: isComplete
? (isDark ? const Color(0xFF66BB6A) : AppColors.primaryGreen)
: (isDark ? Colors.orange.shade300 : Colors.orange.shade800),
? AppColors.primaryGreen.withValues(alpha: isDark ? 0.25 : 0.12)
: Colors.orange.withValues(alpha: isDark ? 0.25 : 0.12),
borderRadius: BorderRadius.circular(4),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
isComplete ? 'Complete' : '${s.missingCount} Missing',
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: isComplete
? (isDark ? const Color(0xFF66BB6A) : AppColors.primaryGreen)
: (isDark ? Colors.orange.shade300 : Colors.orange.shade800),
),
),
if (!isComplete) ...[
const SizedBox(width: 4),
Icon(
Icons.info_outline_rounded,
size: 11,
color: isDark ? Colors.orange.shade300 : Colors.orange.shade800,
),
],
],
),
),
),