davidcr01 / WordlePlus

Repository to store all the documentation, files and structure of my Final Degree Project (TFG in Spanish). The main goal is to develop, as full-stack web developer, a remodel of the Wordle game, including more features and functionalities using Ionic, Django REST Api and PostgreSQL.
1 stars 0 forks source link

Ranking view (S10) #52

Closed davidcr01 closed 1 year ago

davidcr01 commented 1 year ago

Description

As a player, is necessary to implement a new view and logic to display the ranking of the platform. The ranking is an ordered list of players sorted by some player parameter (xp, wins, wins_pvp, wins_tournament)

Tasks

davidcr01 commented 1 year ago

Update Report

Backend

A new method in the Player viewset has been added:

@action(detail=False, methods=['get'])
    def ranking(self, request):
        filter_param = request.GET.get('filter')
        limit = 15
        queryset = Player.objects.all()

        if filter_param:
            queryset = queryset.order_by('-'+filter_param)[:limit]

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

This method gets 15 players ordered by the selected filter in descending order.

image

Frontend

The mockup is the following: image

In the frontend, the tab3 page has been implemented. The HTML is very similar to the tournament page, where the ion-toolbar contains the filter option. In this case, the toolbar contains the wins, wins_pvp, wins_tournament and xp fields. The player info is displayed as a list:

<ion-header>
  <ion-toolbar>
    <ion-segment [scrollable]="true" [(ngModel)]="selectedFilter" (ionChange)="loadPlayers()">
      <ion-segment-button value="wins">
        <ion-label>Wins</ion-label>
      </ion-segment-button>
      <ion-segment-button value="wins_pvp">
        <ion-label>W.PvP</ion-label>
      </ion-segment-button>
      <ion-segment-button value="wins_tournament">
        <ion-label>Tournmts.</ion-label>
      </ion-segment-button>
      <ion-segment-button value="xp">
        <ion-label>xP</ion-label>
      </ion-segment-button>
    </ion-segment>
  </ion-toolbar>
</ion-header>

<ion-content>
  <app-loading *ngIf="isLoading"></app-loading>

  <ion-list *ngIf="players && players.length > 0">
    <ion-item>
      <ion-label>Name</ion-label>
      <ion-label>
        <img src="../../assets/icon/wins-classic.png" alt="Victories Classic" class="icon-img">
      </ion-label>
      <ion-label>
        <img src="../../assets/icon/wins-pvp.png" alt="Victories PvP" class="icon-img">
      </ion-label>
      <ion-label>
        <img src="../../assets/icon/wins-tournaments.png" alt="Victories Tournaments" class="icon-img">
      </ion-label>
      <ion-label>
        <img src="../../assets/icon/experience.png" alt="Experience" class="icon-img">
      </ion-label>
    </ion-item>
    <ion-item class="value" *ngFor="let player of players">
      <ion-label class="username-label">{{ player.user.username }}</ion-label>
      <ion-label class="value-label">{{ player.wins }}</ion-label>
      <ion-label class="value-label">{{ player.wins_pvp }}</ion-label>
      <ion-label class="value-label">{{ player.wins_tournament }}</ion-label>
      <ion-label class="value-label">{{ player.xp }}</ion-label>
    </ion-item>
  </ion-list>

  <ion-card class="ion-padding" *ngIf="players && players.length === 0 && !isLoading">
    <ion-card-content>
      No players found!
    </ion-card-content>
  </ion-card>
</ion-content>

About the logic, is as simple as creating a new method in ApiService to get the players filtered by the parameter, and loading this information every time the ion-toolbar is changed.

export class Tab3Page implements OnInit {
  selectedFilter: string = 'wins';
  players: any[] = [];
  isLoading: boolean = false;

  constructor(private apiService: ApiService, private toastService: ToastService) {}

  ngOnInit() {
    this.loadPlayers();
  }

  async loadPlayers() {
    this.isLoading = true;
    try {
      this.players = await this.apiService.getPlayersRanking(this.selectedFilter) as any;
      console.log(this.players);
      this.isLoading = false;
    } catch (error) {
      console.error('Error loading friend list:', error);
      this.toastService.showToast("Error loading ranking", 2000, 'top', 'danger');
      this.isLoading = false;
    }
  }
}

The result is the following: image image

Notice that #53 is already implemented.