feat: add optional student nickname for informal display

Keep legal first and last names for formal lists; show DisplayFirstName on teams, calendars, and import matching so two Josiahs can be told apart.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-12 00:06:33 -04:00
co-authored by Cursor
parent c03ffc0833
commit 29101e2ead
35 changed files with 516 additions and 41 deletions
@@ -0,0 +1,88 @@
using Core.Utility;
using Tests.Builders;
namespace Tests.Utility;
[TestFixture]
public class StudentNameFormatter_Tests
{
[Test]
public void FormatStudentName_UsesDisplayFirstNameAndSuffixes()
{
var student = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
var formatted = StudentNameFormatter.FormatStudentName(student, new StudentNameFormatter.FormatOptions
{
HasOverlap = true,
IsAbsent = true
});
Assert.That(formatted, Is.EqualTo("Jo* (absent)"));
}
}
[TestFixture]
public class TeamStudentNameFormatter_Tests
{
[Test]
public void FormatStudentName_KeepsCaptainAndOverlapMarkersOnNickname()
{
var captain = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
var teammate = StudentBuilder.Create("Aria", "Cole").Build();
var evt = EventDefinitionBuilder.Team("Flight Endurance", 2, 2).Build();
var team = TeamBuilder.Create(evt)
.WithStudent(captain, isCaptain: true)
.WithStudent(teammate)
.Build();
var formatted = TeamStudentNameFormatter.FormatStudentName(
captain,
team,
new TeamStudentNameFormatter.FormatOptions
{
CaptainIndicator = TeamStudentNameFormatter.CaptainIndicatorStyle.Captain,
MarkOverlaps = true,
HasOverlaps = _ => true
});
Assert.That(formatted, Is.EqualTo("Jo(Cpt)*"));
}
[Test]
public void FormatStudentList_AlphabeticalUsesDisplayFirstName()
{
var jo = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build();
var josiahB = StudentBuilder.Create("Josiah", "Green").WithNickname("Josiah B").Build();
var aria = StudentBuilder.Create("Aria", "Cole").Build();
var evt = EventDefinitionBuilder.Team("Flight Endurance", 3, 3).Build();
var team = TeamBuilder.Create(evt)
.WithStudent(josiahB)
.WithStudent(aria)
.WithStudent(jo, isCaptain: true)
.Build();
var list = TeamStudentNameFormatter.FormatStudentList(
team,
new TeamStudentNameFormatter.FormatOptions
{
Ordering = TeamStudentNameFormatter.OrderingStyle.Alphabetical
});
Assert.That(list, Is.EqualTo("Aria, Jo, Josiah B"));
}
[Test]
public void FormatStudentName_FallsBackToFirstName()
{
var student = StudentBuilder.Create("Josiah", "Green").Build();
var evt = EventDefinitionBuilder.Team("Flight Endurance", 2, 2).Build();
var team = TeamBuilder.Create(evt).WithStudent(student).Build();
var formatted = TeamStudentNameFormatter.FormatStudentName(
student,
team,
new TeamStudentNameFormatter.FormatOptions());
Assert.That(formatted, Is.EqualTo("Josiah"));
}
}