11import { ChangeDetectionStrategy , Component , Input , OnDestroy , OnInit } from '@angular/core' ;
22import { MatTabChangeEvent } from '@angular/material/tabs' ;
3- import { ActivatedRoute , Router } from '@angular/router' ;
3+ import { ActivatedRoute , ParamMap , Router } from '@angular/router' ;
44import { BehaviorSubject , Observable , Subscription , first , of } from 'rxjs' ;
55import { Project } from 'src/app/api/models/project' ;
66import { Unit } from 'src/app/api/models/unit' ;
77import { ProjectService } from 'src/app/api/services/project.service' ;
88import { UserService } from 'src/app/api/services/user.service' ;
99import { AlertService } from 'src/app/common/services/alert.service' ;
10+ import {
11+ DEFAULT_PORTFOLIO_LIST_FILTERS ,
12+ PortfolioListFilters ,
13+ } from './directives/portfolios-list/portfolios-list.component' ;
1014
1115type PortfolioTabKey = 'select' | 'progress' | 'student-notes' | 'portfolio' | 'assessment' ;
1216
@@ -39,6 +43,7 @@ export class PortfoliosComponent implements OnInit, OnDestroy {
3943 public selectedProject$ : BehaviorSubject < Project | null > = new BehaviorSubject ( null ) ;
4044 public loadingStudents = true ;
4145 public currentTab : PortfolioTab = this . tabs [ 0 ] ;
46+ public portfolioListFilters : PortfolioListFilters = { ...DEFAULT_PORTFOLIO_LIST_FILTERS } ;
4247
4348 private subscriptions : Subscription [ ] = [ ] ;
4449 private selectedProjectId : number | null = null ;
@@ -70,6 +75,9 @@ export class PortfoliosComponent implements OnInit, OnDestroy {
7075 this . route . paramMap . subscribe ( ( params ) => {
7176 this . updateCurrentTabFromState ( params . get ( 'tab' ) , params . get ( 'projectId' ) ) ;
7277 } ) ,
78+ this . route . queryParamMap . subscribe ( ( params ) => {
79+ this . updatePortfolioListFiltersFromQueryParams ( params ) ;
80+ } ) ,
7381 ) ;
7482 } ,
7583 error : ( error ) => {
@@ -101,12 +109,27 @@ export class PortfoliosComponent implements OnInit, OnDestroy {
101109 this . navigateToProject ( project . id , 'progress' ) ;
102110 }
103111
112+ public portfolioListFiltersChange ( filters : PortfolioListFilters ) : void {
113+ this . portfolioListFilters = { ...filters } ;
114+
115+ if ( this . currentTab . routeSegment === 'select' ) {
116+ this . router . navigate ( [ ] , {
117+ relativeTo : this . route ,
118+ queryParams : this . portfolioListFilterQueryParams ( ) ,
119+ replaceUrl : true ,
120+ } ) ;
121+ }
122+ }
123+
104124 public onTabChange ( event : MatTabChangeEvent ) : void {
105125 const nextTab = this . tabs [ event . index ] ?? this . tabs [ 0 ] ;
106126 this . currentTab = nextTab ;
107127
108128 if ( nextTab . routeSegment === 'select' || ! this . selectedProject ) {
109- this . router . navigate ( [ '/units' , this . unit . id , 'students' , 'portfolios' ] , { replaceUrl : true } ) ;
129+ this . router . navigate ( [ '/units' , this . unit . id , 'students' , 'portfolios' ] , {
130+ queryParams : this . portfolioListFilterQueryParams ( ) ,
131+ replaceUrl : true ,
132+ } ) ;
110133 return ;
111134 }
112135
@@ -125,6 +148,52 @@ export class PortfoliosComponent implements OnInit, OnDestroy {
125148 } ) ;
126149 }
127150
151+ private updatePortfolioListFiltersFromQueryParams ( params : ParamMap ) : void {
152+ const filters : PortfolioListFilters = {
153+ portfolioFilter : params . get ( 'portfolio' ) === 'all' ? 'all' : 'submitted_only' ,
154+ tutorialFilter : params . get ( 'tutorial' ) === 'mine' ? 'mine' : 'all' ,
155+ gradeFilter : this . gradeFilterFromQueryParam ( params . get ( 'grade' ) ) ,
156+ filterText : params . get ( 'search' ) ?? '' ,
157+ } ;
158+
159+ if ( ! this . portfolioListFiltersEqual ( filters , this . portfolioListFilters ) ) {
160+ this . portfolioListFilters = filters ;
161+ }
162+ }
163+
164+ private gradeFilterFromQueryParam ( grade : string | null ) : number | null {
165+ if ( grade === null ) {
166+ return null ;
167+ }
168+
169+ const gradeValue = Number ( grade ) ;
170+ return Number . isFinite ( gradeValue ) ? gradeValue : null ;
171+ }
172+
173+ private portfolioListFilterQueryParams ( ) : Record < string , string | number | null > {
174+ return {
175+ portfolio :
176+ this . portfolioListFilters . portfolioFilter === DEFAULT_PORTFOLIO_LIST_FILTERS . portfolioFilter
177+ ? null
178+ : this . portfolioListFilters . portfolioFilter ,
179+ tutorial :
180+ this . portfolioListFilters . tutorialFilter === DEFAULT_PORTFOLIO_LIST_FILTERS . tutorialFilter
181+ ? null
182+ : this . portfolioListFilters . tutorialFilter ,
183+ grade : this . portfolioListFilters . gradeFilter ,
184+ search : this . portfolioListFilters . filterText . trim ( ) || null ,
185+ } ;
186+ }
187+
188+ private portfolioListFiltersEqual ( a : PortfolioListFilters , b : PortfolioListFilters ) : boolean {
189+ return (
190+ a . portfolioFilter === b . portfolioFilter &&
191+ a . tutorialFilter === b . tutorialFilter &&
192+ a . gradeFilter === b . gradeFilter &&
193+ a . filterText === b . filterText
194+ ) ;
195+ }
196+
128197 private updateCurrentTabFromState (
129198 tabParam ?: string | null ,
130199 projectIdParam ?: string | null ,
@@ -184,6 +253,7 @@ export class PortfoliosComponent implements OnInit, OnDestroy {
184253
185254 private navigateToProject ( projectId : number , tab : PortfolioTabKey ) : void {
186255 this . router . navigate ( [ '/units' , this . unit . id , 'students' , 'portfolios' , projectId , tab ] , {
256+ queryParams : this . portfolioListFilterQueryParams ( ) ,
187257 replaceUrl : true ,
188258 } ) ;
189259 }
0 commit comments