diff --git a/app/components/team-page/members-table.hbs b/app/components/team-page/members-table.hbs index 8fdf7841be..24de9b21dc 100644 --- a/app/components/team-page/members-table.hbs +++ b/app/components/team-page/members-table.hbs @@ -1,147 +1,154 @@ - - <:headerRight> -
- View activity within -
- - {{#if this.isPeriodDropdownOpen}} -
-
+ <:headerRight> +
+ View activity within +
+ + {{#if this.isPeriodDropdownOpen}} +
+
+ {{#each this.periodOptions as |option|}} + + {{/each}} +
+ {{/if}} +
+
+ + + <:default> +
+ + + + + + + + + + + + + {{#each this.sortedMemberships as |membership|}} + {{/each}} - - {{/if}} + +
Member - {{option.label}} - + + Last Seen + {{#if this.lastSeenSortDirection}} + + + + {{/if}} + + JoinedAttemptsCourses
-
- - <:default> -
- - - - - - - - - - - - - {{#each this.sortedMemberships as |membership|}} - - {{/each}} - -
- - Member - {{#if (eq this.sortColumn "member")}} - - - - {{/if}} - - - - Last Seen - {{#if (eq this.sortColumn "lastSeen")}} - - - - {{/if}} - - - - Joined - {{#if (eq this.sortColumn "joined")}} - - - - {{/if}} - - - - Attempts - {{#if (eq this.sortColumn "attempts")}} - - - - {{/if}} - - - - Courses - {{#if (eq this.sortColumn "courses")}} - - - - {{/if}} - -
-
+
+
+ Invite URL +
-
-
- Invite URL -
+ {{#if this.currentUserIsTeamAdmin}} +
+ To invite new members, send them this invite URL. +
- {{#if this.currentUserIsTeamAdmin}} -
- To invite new members, send them this invite URL. + + {{else}} +
+ To invite new members, ask one of the team admins for an invite URL. +
+ {{/if}}
+ + +{{else}} + +
+ + + + + + + + + + + + + {{#each this.sortedMemberships as |membership|}} + + {{/each}} + +
Member + + Last Seen + {{#if this.lastSeenSortDirection}} + + + + {{/if}} + + JoinedAttemptsCourses
+
- - {{else}} -
- To invite new members, ask one of the team admins for an invite URL. +
+
+ Invite URL
- {{/if}} -
- - + + {{#if this.currentUserIsTeamAdmin}} +
+ To invite new members, send them this invite URL. +
+ + + {{else}} +
+ To invite new members, ask one of the team admins for an invite URL. +
+ {{/if}} +
+
+{{/if}} diff --git a/app/components/team-page/members-table.ts b/app/components/team-page/members-table.ts index 571d46b35b..26b1435298 100644 --- a/app/components/team-page/members-table.ts +++ b/app/components/team-page/members-table.ts @@ -7,7 +7,6 @@ import type TeamModel from 'codecrafters-frontend/models/team'; import type TeamMembershipModel from 'codecrafters-frontend/models/team-membership'; type TimePeriod = 'all' | '3m' | '6m' | '1y'; -type SortColumn = 'member' | 'lastSeen' | 'joined' | 'attempts' | 'courses'; type SortDirection = 'asc' | 'desc'; const PERIOD_OPTIONS: { value: TimePeriod; label: string }[] = [ @@ -22,6 +21,7 @@ interface Signature { Args: { team: TeamModel; + enablePeriodFilter: boolean; }; } @@ -29,8 +29,7 @@ export default class TeamPageMembersTable extends Component { @service declare authenticator: AuthenticatorService; @tracked selectedPeriod: TimePeriod = 'all'; - @tracked sortColumn: SortColumn = 'attempts'; - @tracked sortDirection: SortDirection = 'desc'; + @tracked lastSeenSortDirection: SortDirection | null = null; @tracked isPeriodDropdownOpen = false; periodOptions = PERIOD_OPTIONS; @@ -61,56 +60,48 @@ export default class TeamPageMembersTable extends Component { } } - getCourseCount(membership: TeamMembershipModel): number { - const courses = membership.user.courseParticipations.map((item) => item.course); - const uniqueCourses = new Set(courses.map((c) => c.id)); + get sortedMemberships(): TeamMembershipModel[] { + const memberships = this.args.team.memberships.slice(); - return uniqueCourses.size; - } + // If user clicked Last Seen header, sort by that + if (this.lastSeenSortDirection) { + const dir = this.lastSeenSortDirection === 'asc' ? 1 : -1; - getMemberName(membership: TeamMembershipModel): string { - return (membership.user.githubName || membership.user.username || '').toLowerCase(); - } + return memberships.sort((a, b) => { + const aTime = a.lastAttemptAt ? a.lastAttemptAt.getTime() : 0; + const bTime = b.lastAttemptAt ? b.lastAttemptAt.getTime() : 0; - get sortedMemberships(): TeamMembershipModel[] { - const memberships = this.args.team.memberships.slice(); - const dir = this.sortDirection === 'asc' ? 1 : -1; + return (aTime - bTime) * dir; + }); + } + // Default sort: attempts desc, then last seen desc, then joined desc return memberships.sort((a, b) => { - let comparison = 0; - - switch (this.sortColumn) { - case 'member': - comparison = this.getMemberName(a).localeCompare(this.getMemberName(b)); - break; - case 'lastSeen': { - const aTime = a.lastAttemptAt ? a.lastAttemptAt.getTime() : 0; - const bTime = b.lastAttemptAt ? b.lastAttemptAt.getTime() : 0; - comparison = aTime - bTime; - break; - } - case 'joined': - comparison = a.createdAt.getTime() - b.createdAt.getTime(); - break; - case 'attempts': - comparison = this.getAttempts(a) - this.getAttempts(b); - break; - case 'courses': - comparison = this.getCourseCount(a) - this.getCourseCount(b); - break; + const stagesDiff = (b.numberOfStageAttempts || 0) - (a.numberOfStageAttempts || 0); + + if (stagesDiff !== 0) { + return stagesDiff; + } + + const aLastSeen = a.lastAttemptAt ? a.lastAttemptAt.getTime() : 0; + const bLastSeen = b.lastAttemptAt ? b.lastAttemptAt.getTime() : 0; + + if (aLastSeen !== bLastSeen) { + return bLastSeen - aLastSeen; } - return comparison * dir; + return b.createdAt.getTime() - a.createdAt.getTime(); }); } @action - handleSortClick(column: SortColumn) { - if (this.sortColumn === column) { - this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc'; + handleLastSeenSortClick() { + if (this.lastSeenSortDirection === 'desc') { + this.lastSeenSortDirection = 'asc'; + } else if (this.lastSeenSortDirection === 'asc') { + this.lastSeenSortDirection = null; // back to default } else { - this.sortColumn = column; - this.sortDirection = 'desc'; + this.lastSeenSortDirection = 'desc'; } } diff --git a/app/controllers/team.ts b/app/controllers/team.ts index 8e542712bd..93d7413758 100644 --- a/app/controllers/team.ts +++ b/app/controllers/team.ts @@ -3,4 +3,7 @@ import type { ModelType } from 'codecrafters-frontend/routes/team'; export default class TeamController extends Controller { declare model: ModelType; + + queryParams = ['q']; + q: string | null = null; } diff --git a/app/templates/team.hbs b/app/templates/team.hbs index 99c3ef28dd..b458681051 100644 --- a/app/templates/team.hbs +++ b/app/templates/team.hbs @@ -19,6 +19,6 @@
- +
\ No newline at end of file