import { Component, computed, effect, inject, input, signal } from '@angular/core'; import { Router } from '@angular/router'; import { Article, ArticleService } from '../../core/data/article.service'; import { BookmarksStore } from '../../shared/state/bookmarks.store'; import { BookmarkIconComponent } from '../../shared/ui/bookmark-icon.component'; import { ChevronIconComponent } from '../../shared/ui/chevron-icon.component'; import { bodyReadouts } from './body-readouts'; import { BodyDetailViewModel } from './body-detail.model'; import { ReadoutSectionsComponent } from './readout-sections.component'; /** * Displays the real NASA data for the currently selected body/exoplanet: kind, physical * size/mass, orbital elements, and (for exoplanets) discovery year. Presentational only — * `BodyDetailSceneComponent` supplies the view model and owns navigation state. * * The rows come from `bodyReadouts` via `ReadoutSectionsComponent`, both shared with the system * view's object card so the same body cannot read differently in the two places it can be * inspected. */ @Component({ selector: 'app-info-panel', imports: [BookmarkIconComponent, ChevronIconComponent, ReadoutSectionsComponent], template: `

{{ body().name }}

{{ readouts().kindLabel }} · {{ body().hostStarName }}

@if (article(); as found) {

{{ found.extract }}

Wikipedia · {{ found.language }}
} @else if (aboutState() !== 'idle') {

@switch (aboutState()) { @case ('loading') { Asking Wikipedia… } @case ('none') { Wikipedia has no article on {{ body().name }}. } @case ('unavailable') { Wikipedia could not be reached. } }

} @else { }
` }) export class InfoPanelComponent { readonly body = input.required(); readonly bookmarks = inject(BookmarksStore); private readonly articles = inject(ArticleService); readonly article = signal
(null); readonly aboutState = signal<'idle' | 'loading' | 'none' | 'unavailable'>('idle'); constructor(private readonly router: Router) { // The panel is reused as the route's parameter changes, so what was asked about one body // must not still be showing under the next one's name. effect(() => { this.body(); this.article.set(null); this.aboutState.set('idle'); }); } /** * Fetches the article, on the press and not before. The kind goes with the name because * Wikipedia disambiguates by it — "Titan" alone is a list of everything called Titan. */ async loadArticle(): Promise { this.aboutState.set('loading'); const result = await this.articles.lookup(this.body().name, this.readouts().kindLabel.toLowerCase()); if (result.status === 'found') { this.article.set(result.article); this.aboutState.set('idle'); return; } this.article.set(null); this.aboutState.set(result.status); } readonly readouts = computed(() => bodyReadouts(this.body())); goBack(): void { void this.router.navigate(['/']); } }