diff --git a/mobile/coach_views.py b/mobile/coach_views.py index 343bf3f..fe0c5cc 100644 --- a/mobile/coach_views.py +++ b/mobile/coach_views.py @@ -169,8 +169,9 @@ class CoachAttendanceView(CoachScopeMixin, LoginRequiredMixin, TemplateView): #: param) means "Responded" (IN_STATUSES: present/selected/maybe), the #: default view. A coach doesn't need to check in someone silent or #: declined -- neither is expected to show up -- so those are left out of - #: the default rather than needing to be filtered away each time. - FILTERS = {"silent"} + #: the default rather than needing to be filtered away each time; each + #: still gets its own chip to review who's in either bucket. + FILTERS = {"silent", "declined"} def get_event(self): if self.active_team is None: @@ -195,6 +196,8 @@ class CoachAttendanceView(CoachScopeMixin, LoginRequiredMixin, TemplateView): filter_param = "" if filter_param == "silent": rows = [row for row in attendances if row.is_silent] + elif filter_param == "declined": + rows = [row for row in attendances if row.status in OUT_STATUSES] else: rows = [row for row in attendances if row.status in IN_STATUSES] @@ -204,6 +207,7 @@ class CoachAttendanceView(CoachScopeMixin, LoginRequiredMixin, TemplateView): total_count=len(attendances), responded_count=sum(1 for row in attendances if row.status in IN_STATUSES), silent_count=sum(1 for row in attendances if row.is_silent), + declined_count=sum(1 for row in attendances if row.status in OUT_STATUSES), checked_in_count=sum(1 for row in attendances if row.showed_up is not None), filter_param=filter_param, **kwargs, diff --git a/mobile/templates/mobile/coach/attendance.html b/mobile/templates/mobile/coach/attendance.html index b918d92..972e86e 100644 --- a/mobile/templates/mobile/coach/attendance.html +++ b/mobile/templates/mobile/coach/attendance.html @@ -31,13 +31,16 @@ {% trans "Silent" %} {{ silent_count }} + + {% trans "Declined" %} {{ declined_count }} +
{% csrf_token %}
{% for row in rows %} -
+
{{ row.membership.jersey_number|default:"—" }}
{{ row.member.get_full_name }}
diff --git a/mobile/tests.py b/mobile/tests.py index 7336223..3c54cbe 100644 --- a/mobile/tests.py +++ b/mobile/tests.py @@ -3113,6 +3113,18 @@ class CoachAttendanceViewTests(TestCase): self.assertEqual([row.member for row in rows], [self.player]) self.assertEqual(response.context["responded_count"], 1) + def test_declined_filter_narrows_to_declined_rows(self): + declined_member = Member.objects.create(first_name="Cara", last_name="Declined") + TeamMembership.objects.create(team=self.team, member=declined_member, season=self.season) + Attendance.objects.update_or_create(event=self.event, member=declined_member, defaults={"status": Attendance.AttendanceStatus.ABSENT}) + self.client.force_login(self.user) + + response = self._get(filter="declined") + + rows = response.context["rows"] + self.assertEqual([row.member for row in rows], [declined_member]) + self.assertEqual(response.context["declined_count"], 1) + def test_the_goalies_chip_is_gone(self): self.client.force_login(self.user) @@ -3120,6 +3132,17 @@ class CoachAttendanceViewTests(TestCase): self.assertNotContains(response, "Goalies") self.assertContains(response, "Responded") + self.assertContains(response, "Declined") + + def test_silent_rows_have_no_special_background(self): + silent_member = Member.objects.create(first_name="Ben", last_name="Silent") + TeamMembership.objects.create(team=self.team, member=silent_member, season=self.season) + Attendance.objects.update_or_create(event=self.event, member=silent_member, defaults={"status": Attendance.AttendanceStatus.NO_RESPONSE}) + self.client.force_login(self.user) + + response = self._get(filter="silent") + + self.assertNotContains(response, "bg-warn-bg") def test_event_from_another_team_is_not_reachable(self): other_team = Team.objects.create(club=self.club, name="U14", short_name="U14")