1- import { Component , signal , inject , OnInit } from '@angular/core' ;
2- import { RouterModule , Router , ActivatedRoute } from '@angular/router' ;
1+ import { Component , signal , inject , OnInit , OnDestroy } from '@angular/core' ;
2+ import { RouterModule , Router , ActivatedRoute , NavigationEnd } from '@angular/router' ;
3+ import { filter , Subscription } from 'rxjs' ;
34import { IslamicMonthService , IslamicMonthEntry } from '../services/islamic-month.service' ;
45import { LocationService } from '../services/location.service' ;
56import { LocationDialogService } from '../services/location-dialog.service' ;
67import { LocationDialogComponent } from '../components/location-dialog.component' ;
78import { TopbarComponent } from '../components/topbar.component' ;
89import { HeaderMessageComponent } from '../components/header-message.component' ;
910import { MonthStripComponent } from '../components/month-strip.component' ;
11+ import { YearStripComponent , YearEntry } from '../components/year-strip.component' ;
1012import { FooterComponent } from '../components/footer.component' ;
1113
1214@Component ( {
@@ -17,24 +19,39 @@ import { FooterComponent } from '../components/footer.component';
1719 TopbarComponent ,
1820 HeaderMessageComponent ,
1921 MonthStripComponent ,
22+ YearStripComponent ,
2023 FooterComponent ,
2124 ] ,
2225 templateUrl : './home.component.html' ,
2326 styleUrl : './home.component.scss' ,
2427} )
25- export class HomeComponent implements OnInit {
28+ export class HomeComponent implements OnInit , OnDestroy {
2629 private readonly moonService = inject ( IslamicMonthService ) ;
2730 private readonly router = inject ( Router ) ;
2831 private readonly route = inject ( ActivatedRoute ) ;
2932 private readonly locationService = inject ( LocationService ) ;
3033 readonly locationDialogService = inject ( LocationDialogService ) ;
3134 readonly islamicMonths = signal < IslamicMonthEntry [ ] > ( [ ] ) ;
35+ readonly yearEntries = signal < YearEntry [ ] > ( [ ] ) ;
36+ readonly activeGregorianYear = signal ( new Date ( ) . getFullYear ( ) ) ;
37+
38+ /** Cache of months per Gregorian year to avoid re-computation */
39+ private yearMonthsCache = new Map < number , IslamicMonthEntry [ ] > ( ) ;
40+ private routerSub ! : Subscription ;
3241
3342 constructor ( ) {
34- this . islamicMonths . set ( this . moonService . getUpcomingIslamicMonths ( new Date ( ) , 12 ) ) ;
43+ this . initYears ( ) ;
3544 }
3645
3746 ngOnInit ( ) {
47+ // Detect active year from initial route
48+ this . syncActiveYearFromRoute ( ) ;
49+
50+ // Listen to route changes to update active year
51+ this . routerSub = this . router . events
52+ . pipe ( filter ( ( e ) => e instanceof NavigationEnd ) )
53+ . subscribe ( ( ) => this . syncActiveYearFromRoute ( ) ) ;
54+
3855 if ( ! this . route . firstChild ) {
3956 const defaultRoute = this . moonService . getNearestMonthRoute ( this . islamicMonths ( ) ) ;
4057 this . router . navigateByUrl ( defaultRoute , { replaceUrl : true } ) ;
@@ -46,6 +63,63 @@ export class HomeComponent implements OnInit {
4663 }
4764 }
4865
66+ ngOnDestroy ( ) {
67+ this . routerSub ?. unsubscribe ( ) ;
68+ }
69+
70+ private initYears ( ) {
71+ const currentYear = new Date ( ) . getFullYear ( ) ;
72+ const years : YearEntry [ ] = [ ] ;
73+
74+ for ( let y = currentYear - 5 ; y <= currentYear + 5 ; y ++ ) {
75+ const months = this . getMonthsForYear ( y ) ;
76+ if ( months . length === 0 ) continue ;
77+ const uniqueIslamic = [ ...new Set ( months . map ( ( m ) => m . year ) ) ] . sort ( ) ;
78+ const islamicYearLabel =
79+ uniqueIslamic . length > 1
80+ ? `${ uniqueIslamic [ 0 ] } –${ uniqueIslamic [ uniqueIslamic . length - 1 ] } AH`
81+ : `${ uniqueIslamic [ 0 ] } AH` ;
82+ years . push ( {
83+ gregorianYear : y ,
84+ islamicYearLabel,
85+ firstMonthRoute : `/${ months [ 0 ] . year } AH/${ months [ 0 ] . routeSlug } ` ,
86+ } ) ;
87+ }
88+
89+ this . yearEntries . set ( years ) ;
90+ // Default: load months for current Gregorian year
91+ this . islamicMonths . set ( this . getMonthsForYear ( currentYear ) ) ;
92+ }
93+
94+ private getMonthsForYear ( year : number ) : IslamicMonthEntry [ ] {
95+ if ( ! this . yearMonthsCache . has ( year ) ) {
96+ this . yearMonthsCache . set ( year , this . moonService . getIslamicMonthsForGregorianYear ( year ) ) ;
97+ }
98+ return this . yearMonthsCache . get ( year ) ! ;
99+ }
100+
101+ private syncActiveYearFromRoute ( ) {
102+ const child = this . route . firstChild ;
103+ if ( ! child ) return ;
104+ const yearStr = child . snapshot . params [ 'year' ] ;
105+ const monthSlug = child . snapshot . params [ 'month' ] ;
106+ if ( ! yearStr || ! monthSlug ) return ;
107+
108+ // Find which Gregorian year contains this Islamic month
109+ for ( const ye of this . yearEntries ( ) ) {
110+ const months = this . getMonthsForYear ( ye . gregorianYear ) ;
111+ const match = months . find (
112+ ( m ) =>
113+ `${ m . year } AH` === yearStr && m . routeSlug . toLowerCase ( ) === monthSlug . toLowerCase ( ) ,
114+ ) ;
115+ if ( match ) {
116+ this . activeGregorianYear . set ( ye . gregorianYear ) ;
117+ this . islamicMonths . set ( months ) ;
118+ return ;
119+ }
120+ }
121+ }
122+
49123 closeLocationDialog ( ) {
50124 this . locationDialogService . close ( ) ;
51125 }
0 commit comments