Browse Source

- Move to a 3 colum split for the plan view

pull/1/head
Dan 1 year ago
parent
commit
d866c25fb9
  1. 4
      src/app/app.routes.ts
  2. 1
      src/app/core/models/plan.model.ts
  3. 18
      src/app/features/plan/plan-game/plan-game.component.ts
  4. 227
      src/app/features/plan/plan-pokemon-details/plan-pokemon-details.component.ts
  5. 101
      src/app/features/plan/plan-pokemon/plan-pokemon.component.ts
  6. 325
      src/app/features/plan/plan-pokemon/plan-pokemonV2.component.ts
  7. 189
      src/app/features/plan/planV2.component.ts

4
src/app/app.routes.ts

@ -19,8 +19,8 @@ export const routes: Routes = [
}, },
{ {
path: 'efficiency', path: 'efficiency',
loadComponent: () => import('./features/plan/plan.component') loadComponent: () => import('./features/plan/planV2.component')
.then(m => m.PlanComponent), .then(m => m.PlanV2Component),
canActivate: [AuthGuard] canActivate: [AuthGuard]
}, },
{ {

1
src/app/core/models/plan.model.ts

@ -4,6 +4,7 @@ export interface GamePlan {
} }
export interface PokemonFamilyEntry { export interface PokemonFamilyEntry {
family_pfic?: string;
representative: string; representative: string;
catch_count: number; catch_count: number;
evolve_to: string[]; evolve_to: string[];

18
src/app/features/plan/plan-game/plan-game.component.ts

@ -20,12 +20,6 @@ import { GamePlan } from '../../../core/models/plan.model';
[alt]="game.game_name" [alt]="game.game_name"
class="game-image" class="game-image"
> >
<mat-card-content>
<h3>{{ game.game_name }}</h3>
<p class="catch-count">
Pokémon to catch: {{ getTotalCatchCount() }}
</p>
</mat-card-content>
</mat-card> </mat-card>
`, `,
styles: [` styles: [`
@ -78,12 +72,18 @@ export class PlanGameComponent {
sum += this.game.pokemon[family].catch_count; sum += this.game.pokemon[family].catch_count;
} }
return sum return sum
//return this.game.pokemon.values().reduce((sum, pokemon) => sum + pokemon.catch_count, 0);
} }
getGameBoxArt(): string { getGameBoxArt(): string {
// You'll need to implement this to return the correct box art URL switch(this.game.game_name){
return `/assets/images/games/_${this.game.game_name.replace(' ', '')}.png`; case "Legends: Arceus": {
return `/assets/images/games/_LegendsArceus.png`;
}
default: {
return `/assets/images/games/_${this.game.game_name.replace(' ', '')}.png`;
}
}
} }
onSelect() { onSelect() {

227
src/app/features/plan/plan-pokemon-details/plan-pokemon-details.component.ts

@ -0,0 +1,227 @@
import { Component, Input, Output, EventEmitter, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PokemonFamilyEntry } from '../../../core/models/plan.model';
import { Pokemon } from '../../../core/models/pokemon.model';
import { PokemonService } from '../../../core/services/pokemon.service';
import { MatChipsModule } from '@angular/material/chips';
@Component({
selector: 'app-plan-pokemon-details',
standalone: true,
imports: [
CommonModule,
MatChipsModule
],
template: `
<div class="targets-grid" *ngIf="hasTargets">
<ng-container *ngIf="evolve_to.length > 0">
<div class="target-section">
<h4>Evolution Targets</h4>
<div class="target-cards">
<div
*ngFor="let target of evolve_to"
class="target-card"
[class.completed]="isTargetCompleted(target.PFIC)"
>
<img
lazyImg
[src]="pokemonService.getPokemonImageUrl(target)"
[alt]="target.Name"
class="target-image"
[class.grayscale]="isTargetCompleted(target.PFIC)"
>
<div class="target-details">
<div class="target-name">
{{ target.Name }}
<span *ngIf="target.Form">({{ target.Form }})</span>
</div>
<span *ngIf="target.EvolutionMethod">{{target?.EvolutionMethod}}</span>
</div>
</div>
</div>
</div>
</ng-container>
<ng-container *ngIf="pokemon_family.breed_for.length > 0">
<div class="target-section">
<h4>Breeding Targets</h4>
<div class="target-cards">
<div
*ngFor="let target of breed_for"
class="target-card"
[class.completed]="isTargetCompleted(target.PFIC)"
>
<img
lazyImg
[src]="pokemonService.getPokemonImageUrl(target)"
[alt]="target.Name"
class="target-image"
[class.grayscale]="isTargetCompleted(target.PFIC)"
>
<div class="target-details">
<div class="target-name">
{{ target.Name }}
<span *ngIf="target.Form">({{ target.Form }})</span>
</div>
<mat-chip-listbox>
<mat-chip>Breed</mat-chip>
</mat-chip-listbox>
</div>
</div>
</div>
</div>
</ng-container>
</div>
`,
styles: [`
.targets-grid {
padding: 16px 8px;
display: flex;
flex-direction: column;
gap: 24px;
}
.target-cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 16px;
}
.target-card {
display: flex;
align-items: center;
gap: 12px;
padding: 8px;
border: 1px solid #eee;
border-radius: 8px;
transition: background-color 0.3s ease;
&:hover {
background-color: #f5f5f5;
}
&.completed {
background-color: #f0f0f0;
}
}
.target-image {
width: 64px;
height: 64px;
object-fit: contain;
}
.target-details {
display: flex;
flex-direction: column;
gap: 8px;
}
.target-name {
font-weight: 500;
span {
color: #666;
font-size: 0.9em;
}
}
`]
})
export class PlanPokemonDetailsComponent {
@Input() pokemon_family!: PokemonFamilyEntry;
evolve_to: Pokemon[] = [];
breed_for: Pokemon[] = [];
constructor(
public pokemonService: PokemonService
) {}
ngOnInit() {
this.evolve_to = []
this.breed_for = []
this.loadPokemonFamilyInfo(this.pokemon_family);
}
ngOnChanges(changes: SimpleChanges) {
if (changes['pokemon_family']) {
const currentFamily = changes['pokemon_family'].currentValue;
const previousFamily = changes['pokemon_family'].previousValue;
// Check if there's a meaningful change
if (currentFamily && currentFamily !== previousFamily) {
// Your logic here, e.g., re-fetch data or reset states
this.loadPokemonFamilyInfo(currentFamily);
}
}
}
loadPokemonFamilyInfo(newFamily: PokemonFamilyEntry) {
const evolveToArray: Pokemon[] = [];
newFamily.evolve_to.forEach((target) => {
this.pokemonService.getPokemonFromPFIC(target).subscribe({
next: (pokemon) => {
if (pokemon) {
evolveToArray.push(pokemon);
}
},
complete: () => {
this.customSort(evolveToArray);
this.evolve_to = [...evolveToArray]; // Assign once all have completed
},
error: (error) => {
console.error('Error loading Pokémon:', error);
}
});
});
const breedForArray: Pokemon[] = [];
newFamily.breed_for.forEach((target) => {
this.pokemonService.getPokemonFromPFIC(target).subscribe({
next: (pokemon) => {
if (pokemon) {
breedForArray.push(pokemon);
}
},
complete: () => {
this.customSort(breedForArray);
this.breed_for = [...breedForArray]; // Assign once all have completed
},
error: (error) => {
console.error('Error loading Pokémon:', error);
}
});
});
}
parsePfic(pfic: string): (number | string)[] {
const parts = pfic.split('-');
return parts.map(part => /^\d+$/.test(part) ? parseInt(part) : part);
}
customSort(arr: Pokemon[]): Pokemon[] {
return arr.sort((a, b) => {
const parsedA = this.parsePfic(a.PFIC);
const parsedB = this.parsePfic(b.PFIC);
for (let i = 0; i < Math.min(parsedA.length, parsedB.length); i++) {
if (parsedA[i] !== parsedB[i]) {
if (typeof parsedA[i] === 'number' && typeof parsedB[i] === 'number') {
return (parsedA[i] as number) - (parsedB[i] as number);
}
return (parsedA[i] as string).localeCompare(parsedB[i] as string);
}
}
return parsedA.length - parsedB.length;
});
}
get hasTargets(): boolean {
return this.pokemon_family.evolve_to.length > 0 || this.pokemon_family.breed_for.length > 0;
}
isTargetCompleted(pfic: string): boolean {
return this.pokemonService.isTargetCompleted(pfic);
}
}

101
src/app/features/plan/plan-pokemon/plan-pokemon.component.ts

@ -77,7 +77,7 @@ interface PokemonStatusEvent {
<h4>Evolution Targets</h4> <h4>Evolution Targets</h4>
<div class="target-cards"> <div class="target-cards">
<div <div
*ngFor="let target of evolve_to" *ngFor="let target of evolve_to; trackBy: trackByPfic"
class="target-card" class="target-card"
[class.completed]="isTargetCompleted(target.PFIC)" [class.completed]="isTargetCompleted(target.PFIC)"
> >
@ -275,45 +275,8 @@ export class PlanPokemonComponent {
this.representative_pokemon = null; this.representative_pokemon = null;
this.evolve_to = [] this.evolve_to = []
this.breed_for = [] this.breed_for = []
this.cdr.detectChanges();
this.pokemonService.getPokemonFromPFIC(this.pokemon_family.representative).subscribe({ this.handlePokemonFamilyChange(this.pokemon_family);
next: (pokemon) => {
this.representative_pokemon = pokemon
},
error: (error) => {
console.error('Error loading Pokemon:', error);
this.cdr.markForCheck();
}
});
for(const target of this.pokemon_family.evolve_to) {
this.pokemonService.getPokemonFromPFIC(target).subscribe({
next: (pokemon) => {
if(pokemon) {
this.evolve_to.push(pokemon)
}
},
error: (error) => {
console.error('Error loading Pokemon:', error);
this.cdr.markForCheck();
}
});
}
for(const target of this.pokemon_family.breed_for) {
this.pokemonService.getPokemonFromPFIC(target).subscribe({
next: (pokemon) => {
if(pokemon) {
this.breed_for.push(pokemon)
}
},
error: (error) => {
console.error('Error loading Pokemon:', error);
this.cdr.markForCheck();
}
});
}
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
@ -337,7 +300,6 @@ export class PlanPokemonComponent {
this.representative_pokemon = null; this.representative_pokemon = null;
this.evolve_to = [] this.evolve_to = []
this.breed_for = [] this.breed_for = []
this.cdr.detectChanges();
this.pokemonService.getPokemonFromPFIC(this.pokemon_family.representative).subscribe({ this.pokemonService.getPokemonFromPFIC(this.pokemon_family.representative).subscribe({
next: (pokemon) => { next: (pokemon) => {
@ -349,33 +311,41 @@ export class PlanPokemonComponent {
} }
}); });
for(const target of this.pokemon_family.evolve_to) { const evolveToArray: Pokemon[] = [];
newFamily.evolve_to.forEach((target) => {
this.pokemonService.getPokemonFromPFIC(target).subscribe({ this.pokemonService.getPokemonFromPFIC(target).subscribe({
next: (pokemon) => { next: (pokemon) => {
if(pokemon) { if (pokemon) {
this.evolve_to.push(pokemon) evolveToArray.push(pokemon);
} }
}, },
complete: () => {
this.customSort(evolveToArray);
this.evolve_to = [...evolveToArray]; // Assign once all have completed
},
error: (error) => { error: (error) => {
console.error('Error loading Pokemon:', error); console.error('Error loading Pokémon:', error);
this.cdr.markForCheck();
} }
}); });
} });
for(const target of this.pokemon_family.breed_for) { const breedForArray: Pokemon[] = [];
newFamily.breed_for.forEach((target) => {
this.pokemonService.getPokemonFromPFIC(target).subscribe({ this.pokemonService.getPokemonFromPFIC(target).subscribe({
next: (pokemon) => { next: (pokemon) => {
if(pokemon) { if (pokemon) {
this.breed_for.push(pokemon) breedForArray.push(pokemon);
} }
}, },
complete: () => {
this.customSort(breedForArray);
this.breed_for = [...breedForArray]; // Assign once all have completed
},
error: (error) => { error: (error) => {
console.error('Error loading Pokemon:', error); console.error('Error loading Pokémon:', error);
this.cdr.markForCheck();
} }
}); });
} });
} }
get hasTargets(): boolean { get hasTargets(): boolean {
@ -431,4 +401,31 @@ export class PlanPokemonComponent {
getRepresentativePokemon() { getRepresentativePokemon() {
return this.pokemonService.getPokemonFromPFIC(this.pokemon_family.representative) return this.pokemonService.getPokemonFromPFIC(this.pokemon_family.representative)
} }
trackByPfic(index: number, item: any): string {
return item.PFIC; // Assuming PFIC or another unique identifier is available
}
parsePfic(pfic: string): (number | string)[] {
const parts = pfic.split('-');
return parts.map(part => /^\d+$/.test(part) ? parseInt(part) : part);
}
customSort(arr: Pokemon[]): Pokemon[] {
return arr.sort((a, b) => {
const parsedA = this.parsePfic(a.PFIC);
const parsedB = this.parsePfic(b.PFIC);
for (let i = 0; i < Math.min(parsedA.length, parsedB.length); i++) {
if (parsedA[i] !== parsedB[i]) {
if (typeof parsedA[i] === 'number' && typeof parsedB[i] === 'number') {
return (parsedA[i] as number) - (parsedB[i] as number);
}
return (parsedA[i] as string).localeCompare(parsedB[i] as string);
}
}
return parsedA.length - parsedB.length;
});
}
} }

325
src/app/features/plan/plan-pokemon/plan-pokemonV2.component.ts

@ -0,0 +1,325 @@
import { Component, Input, Output, EventEmitter, ChangeDetectorRef, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatExpansionModule } from '@angular/material/expansion';
import { MatIconModule } from '@angular/material/icon';
import { MatChipsModule } from '@angular/material/chips';
import { MatTooltipModule } from '@angular/material/tooltip';
import { PokemonFamilyEntry } from '../../../core/models/plan.model';
import { LazyImgDirective } from '../../../shared/directives/lazy-img.directive';
import { PokemonService } from '../../../core/services/pokemon.service';
import { Pokemon } from '../../../core/models/pokemon.model';
import { MatCardModule } from '@angular/material/card';
// Define an interface for the status update event
interface PokemonStatusEvent {
pfic: string;
caught: boolean;
completed?: boolean; // Make completed optional
}
@Component({
selector: 'app-plan-pokemonV2',
standalone: true,
imports: [
CommonModule,
MatExpansionModule,
MatIconModule,
MatChipsModule,
MatTooltipModule,
LazyImgDirective,
MatCardModule
],
template: `
<mat-card
class="pokemon-row"
[class.selected]="isSelected"
(click)="onSelect()">
<div class="pokemon-header">
<img
lazyImg
[src]="pokemonService.getPokemonImageUrl(this.representative_pokemon)"
[alt]="this.representative_pokemon?.Name"
class="pokemon-thumbnail"
[class.grayscale]="pokemon_family.catch_count === 0"
>
<div class="pokemon-info">
<div class="pokemon-name">
{{ this.representative_pokemon?.Name }}
<span class="form-name">
<span *ngIf="this.pokemon_family?.Male">
<img src="assets/images/Male_symbol_(fixed_width).svg" >: {{ this.pokemon_family.Male }}
</span>
<span *ngIf="this.pokemon_family?.Female">
<img src="assets/images/Venus_symbol_(fixed_width).svg" >: {{ this.pokemon_family.Female }}
</span>
<span *ngIf="this.pokemon_family?.Any">
<img src="assets/images/Male_and_female_sign.svg" >: {{ this.pokemon_family.Any }}
</span>
</span>
</div>
<div class="catch-info">
<img
src="/assets/images/pokeball_color.png"
[class.grayscale]="pokemon_family.catch_count === 0"
class="pokeball-icon"
[matTooltip]="'Need: ' + pokemon_family.catch_count"
>
<span class="catch-count">{{ pokemon_family.catch_count }}</span>
</div>
</div>
</div>
</mat-card>
`,
styles: [`
.pokemon-panel {
margin-bottom: 8px;
}
.pokemon-row{
margin:5px;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
}
.pokemon-row:hover {
transform: translateY(-4px);
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.pokemon-row.selected {
border: 2px solid #4CAF50;
transform: translateY(-2px);
}
.pokemon-header {
display: flex;
align-items: center;
gap: 16px;
width: 100%;
}
.pokemon-thumbnail {
width: 48px;
height: 48px;
object-fit: contain;
}
.pokemon-info {
display: flex;
justify-content: space-between;
align-items: center;
flex-grow: 1;
}
.pokemon-name {
font-weight: 500;
font-size: 1.1em;
}
.form-name {
color: #666;
font-size: 0.9em;
margin-left: 4px;
}
.catch-info {
display: flex;
align-items: center;
gap: 8px;
min-width: 80px;
}
.pokeball-icon {
width: 24px;
height: 24px;
cursor: pointer;
transition: filter 0.3s ease;
}
.grayscale {
filter: grayscale(100%);
}
.catch-count {
font-weight: 500;
color: #4CAF50;
}
.targets-grid {
padding: 16px 8px;
gap: 24px;
}
.target-section {
h4 {
margin: 0 0 12px 0;
color: #666;
}
}
.target-cards {
gap: 16px;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.target-card {
display: flex;
align-items: center;
gap: 12px;
padding: 8px;
border: 1px solid #eee;
border-radius: 8px;
transition: background-color 0.3s ease;
&:hover {
background-color: #f5f5f5;
}
&.completed {
background-color: #f0f0f0;
}
}
.target-image {
width: 64px;
height: 64px;
object-fit: contain;
}
.target-details {
display: flex;
flex-direction: column;
gap: 8px;
}
.target-name {
font-weight: 500;
span {
color: #666;
font-size: 0.9em;
}
}
mat-chip-list {
display: flex;
gap: 4px;
}
`]
})
export class PlanPokemonV2Component {
@Input() pokemon_family!: PokemonFamilyEntry;
@Input() isSelected = false;
@Output() statusUpdate = new EventEmitter<PokemonStatusEvent>();
@Output() familySelected = new EventEmitter<PokemonFamilyEntry>();
representative_pokemon: Pokemon | null = null;
constructor(
public pokemonService: PokemonService,
private cdr: ChangeDetectorRef
) {}
ngOnInit() {
this.representative_pokemon = null;
this.handlePokemonFamilyChange(this.pokemon_family);
}
ngOnChanges(changes: SimpleChanges) {
if (changes['pokemon_family']) {
const currentFamily = changes['pokemon_family'].currentValue;
const previousFamily = changes['pokemon_family'].previousValue;
// Check if there's a meaningful change
if (currentFamily && currentFamily !== previousFamily) {
// Your logic here, e.g., re-fetch data or reset states
this.handlePokemonFamilyChange(currentFamily);
}
}
}
private handlePokemonFamilyChange(newFamily: PokemonFamilyEntry) {
// This function contains logic to handle the input change.
// For example, resetting component states or fetching additional data.
console.log('Pokemon family has changed:', newFamily);
this.representative_pokemon = null;
this.pokemonService.getPokemonFromPFIC(this.pokemon_family.representative).subscribe({
next: (pokemon) => {
this.representative_pokemon = pokemon
},
error: (error) => {
console.error('Error loading Pokemon:', error);
this.cdr.markForCheck();
}
});
}
get hasTargets(): boolean {
return this.pokemon_family.evolve_to.length > 0 || this.pokemon_family.breed_for.length > 0;
}
isTargetCompleted(pfic: string): boolean {
return this.pokemonService.isTargetCompleted(pfic);
}
calculateTotalNeeded(): number {
let total = 1; // Initial catch
let breedCount = 0;
let evolveCount = 0;
// Calculate breeding needs
if (this.pokemon_family.breed_for.length > 0) {
breedCount = 1; // We only need one for breeding, regardless of how many we breed
}
// Calculate evolution needs
this.pokemon_family.evolve_to.forEach(target => {
if (!this.isTargetCompleted(target)) {
evolveCount += 1;
}
});
return total + breedCount + evolveCount;
}
updateCatchCount() {
const newCount = this.calculateTotalNeeded();
if (newCount !== this.pokemon_family.catch_count) {
this.pokemon_family.catch_count = newCount;
if (newCount === 0) {
// Emit event to move to completed section
this.statusUpdate.emit({
pfic: this.pokemon_family.representative,
caught: true,
completed: true
});
} else if (newCount > 0 && this.pokemon_family.catch_count === 0) {
// Emit event to move back to active section
this.statusUpdate.emit({
pfic: this.pokemon_family.representative,
caught: false,
completed: false
});
}
}
}
getRepresentativePokemon() {
return this.pokemonService.getPokemonFromPFIC(this.pokemon_family.representative)
}
trackByPfic(index: number, item: any): string {
return item.PFIC; // Assuming PFIC or another unique identifier is available
}
onSelect() {
this.familySelected.emit(this.pokemon_family);
}
}

189
src/app/features/plan/planV2.component.ts

@ -0,0 +1,189 @@
import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { FormsModule } from '@angular/forms';
import { PlanGameComponent } from './plan-game/plan-game.component';
import { PlanService } from '../../core/services/plan.service';
import { GamePlan, PokemonFamilyEntry } from '../../core/models/plan.model';
import { PlanPokemonV2Component } from "./plan-pokemon/plan-pokemonV2.component";
import { ScrollingModule, CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { PlanPokemonDetailsComponent } from "./plan-pokemon-details/plan-pokemon-details.component";
@Component({
selector: 'app-planV2',
standalone: true,
imports: [
CommonModule,
MatCardModule,
FormsModule,
PlanGameComponent,
PlanPokemonV2Component,
ScrollingModule,
PlanPokemonDetailsComponent
],
template: `
<div class="plan-container">
<div class="games-section">
<div class="games-scroll">
<div class="games-list">
<app-plan-game
*ngFor="let game of gamePlans"
[game]="game"
[isSelected]="selectedGame?.game_name === game.game_name"
(gameSelect)="selectGame($event)"
></app-plan-game>
</div>
</div>
</div>
<div class="content-section">
<div class="game-stats" *ngIf="selectedGame">
<h2>{{ selectedGame.game_name }} - Game Stats</h2>
<!-- Add game stats here -->
</div>
<div class="middle-section">
<div class="pokemon-section" *ngIf="selectedGame">
<cdk-virtual-scroll-viewport [itemSize]="56" class="pokemon-viewport">
<div *cdkVirtualFor="let pokemon of selectedGame.pokemon | keyvalue; trackBy: trackByPfic">
<app-plan-pokemonV2
[pokemon_family]="pokemon.value"
(statusUpdate)="onPokemonStatusUpdate($event)"
[isSelected]="selectedPokemon?.family_pfic === pokemon.key"
(familySelected)="selectPokemon($event)"
></app-plan-pokemonV2>
</div>
</cdk-virtual-scroll-viewport>
</div>
<div class="details-section">
<h2>{{ selectedPokemon?.representative }} - Details</h2>
<app-plan-pokemon-details
*ngIf="selectedPokemon"
[pokemon_family]="selectedPokemon"
></app-plan-pokemon-details>
</div>
</div>
</div>
</div>
`,
styles: [`
.plan-container {
display: flex;
height: calc(100vh - 64px); /* Adjust based on your header height */
overflow: hidden;
}
.games-section {
width: 11%;
padding: 20px;
overflow-y: auto;
background: #f5f5f5;
border-right: 1px solid #ddd;
}
.games-scroll {
width: 100%;
}
.games-list {
display: flex;
flex-direction: column;
gap: 16px;
}
.content-section {
flex: 1;
display: flex;
flex-direction: column;
padding: 20px;
overflow: hidden;
}
.middle-section {
flex: 2;
display: flex;
flex-direction: row;
margin-right: 20px;
}
.game-stats {
padding-bottom: 16px;
border-bottom: 1px solid #ddd;
margin-bottom: 16px;
}
.pokemon-section {
flex: 1;
min-height: 0; /* Important for Firefox */
display: flex;
flex-direction: row;
margin-right: 15px;
}
.pokemon-viewport {
flex: 1;
overflow-y: auto;
padding: 16px;
background: #f5f5f5;
border-radius: 8px;
margin-bottom: 20px;
}
.details-section {
flex: 1;
padding: 16px;
background: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
width:15%
}
`]
})
export class PlanV2Component implements OnInit {
@ViewChild(CdkVirtualScrollViewport) viewport!: CdkVirtualScrollViewport;
gamePlans: GamePlan[] = [];
selectedGame: GamePlan | null = null;
selectedPokemon: PokemonFamilyEntry | null = null;
constructor(private planService: PlanService, private cdr: ChangeDetectorRef) {}
ngOnInit() {
this.loadPlan();
}
private loadPlan() {
this.planService.getPlan().subscribe(
plan => {
this.gamePlans = plan;
if (!this.selectedGame && plan.length > 0) {
this.selectedGame = plan[0];
}
}
);
}
selectGame(game: GamePlan) {
if (this.viewport) {
this.viewport.scrollToIndex(0); // Reset scroll to top when switching games
}
this.selectedGame = null; // Clear the selected game first to avoid stale data
this.cdr.detectChanges();
this.selectedGame = game;
this.cdr.detectChanges();
}
onPokemonStatusUpdate(event: { pfic: string, caught: boolean }) {
this.loadPlan();
}
selectPokemon(pokemon: any) {
this.selectedPokemon = pokemon;
}
trackByPfic(index: number, item: any): string {
return item.key; // Assuming PFIC or another unique identifier is available
}
}
Loading…
Cancel
Save