Browse Source

Allow athlete adopting by providing ID

main
Haris Razis 4 years ago
parent
commit
37b120d2bd
  1. 5
      client/services/socket.js
  2. 10
      server/routes/athletes.js
  3. 2
      web/src/store/modules/athletes.ts
  4. 68
      web/src/views/Athlete.vue
  5. 174
      web/src/views/Athletes.vue

5
client/services/socket.js

@ -6,6 +6,11 @@ const getMAC = require('getmac').default
const socket = io(server_url); const socket = io(server_url);
const mac = getMAC(); const mac = getMAC();
console.log(chalk.green(`
ID: ${mac}
Use this ID, to adopt the athlete on the user dashboard.
`))
socket.on('connect', () => { socket.on('connect', () => {
console.log(chalk.green('Connected to server!')); console.log(chalk.green('Connected to server!'));

10
server/routes/athletes.js

@ -39,7 +39,15 @@ router.put('/api/athletes/:id',
const {name, _trainer} = req.body const {name, _trainer} = req.body
const updateAthlete = {name, _trainer} const updateAthlete = {name, _trainer}
if (name || _trainer) if (_trainer === '') {
updateAthlete._trainer = undefined
await Athlete.findByIdAndUpdate(req.params.id, updateAthlete, {}, (err, athlete) => {
if (err)
return res.status(400).json({errors: 'Something went wrong!'});
return res.send(athlete)
})
} else if (name || _trainer)
await Athlete.findByIdAndUpdate(req.params.id, updateAthlete, {}, (err, athlete) => { await Athlete.findByIdAndUpdate(req.params.id, updateAthlete, {}, (err, athlete) => {
if (err) if (err)
return res.status(400).json({errors: 'Something went wrong!'}); return res.status(400).json({errors: 'Something went wrong!'});

2
web/src/store/modules/athletes.ts

@ -8,7 +8,7 @@ export interface AthleteInterface {
id: string, id: string,
socketID: string, socketID: string,
name: string, name: string,
_trainer: UserInterface _trainer: string
} }
@Module @Module

68
web/src/views/Athlete.vue

@ -1,5 +1,30 @@
<template> <template>
<h1 class="title is-2">/athletes/{{ athlete.name }}</h1> <h1 class="title is-2">/athletes/{{ athlete.name }}</h1>
<div class="tile mb-5">
<article class="tile is-child box">
<nav class="level">
<div class="level-left">
<div class="level-item ">
<div class="title">Actions</div>
</div>
</div>
<div class="level-right">
<div class="level-item has-text-centered">
<router-link :to="{ name: 'Table', params: { id: athlete._id }}" @click="saveAthlete(athlete)">
<span class="icon is-medium has-background-primary has-text-white mr-1">
<i class="fa fa-lg fa-table"></i>
</span>
</router-link>
<router-link :to="{ name: 'Chart', params: { id: athlete._id }}" @click="saveAthlete(athlete)">
<span class="icon is-medium has-background-primary has-text-white mr-1">
<i class="fa fa-lg fa-chart-area"></i>
</span>
</router-link>
</div>
</div>
</nav>
</article>
</div>
<div class="tile is-ancestor"> <div class="tile is-ancestor">
<div class="tile is-6 is-vertical is-parent"> <div class="tile is-6 is-vertical is-parent">
<form @submit="update"> <form @submit="update">
@ -11,10 +36,6 @@
<input v-model="athlete.name" class="input" type="text"> <input v-model="athlete.name" class="input" type="text">
</div> </div>
</div> </div>
<div class="field">
<label class="label">ID</label>
<p>{{ athlete.id }}</p>
</div>
<div class="field"> <div class="field">
<label class="label">Client Status</label> <label class="label">Client Status</label>
<p v-if="athlete.socketID">Online</p> <p v-if="athlete.socketID">Online</p>
@ -50,12 +71,25 @@
<div class="tile is-parent"> <div class="tile is-parent">
<div class="tile is-child box"> <div class="tile is-child box">
<p class="title">Trainer Status</p> <p class="title">Trainer Status</p>
<div v-if="!athlete._trainer" class="notification is-warning is-light mt-5"> <div v-if="!athlete._trainer">
<ul> <div class="notification is-primary is-light mt-5">
<p>It seems that this athlete has no trainer attached to him!</p> <ul>
<p>By adopting an athlete you can edit his personal details and view his performance stats.</p> <p>It seems that this athlete has no trainer attached to him!</p>
</ul> <p>By adopting an athlete you can edit his personal details and view his performance stats.</p>
<button class="button is-large is-rounded is-primary is-light" @click="update">Adopt</button> <p>Enter the client id displayed in the clients terminal to adopt him!</p>
</ul>
</div>
<div class="field">
<label class="label">Athlete ID</label>
<div class="control">
<input v-model="clientID" class="input" type="text">
</div>
</div>
<div class="field">
<p class="control">
<button class="button is-medium is-rounded is-primary" @click="update('adopt')">Adopt</button>
</p>
</div>
</div> </div>
<div v-else> <div v-else>
<div class="field"> <div class="field">
@ -88,6 +122,7 @@ export default class Athlete extends Vue {
private trainerLogin = ''; private trainerLogin = '';
private msgError = '' private msgError = ''
private msgSuccess = '' private msgSuccess = ''
private clientID = ''
mounted() { mounted() {
this.athlete = this.$store.getters.currentAthlete this.athlete = this.$store.getters.currentAthlete
@ -106,9 +141,20 @@ export default class Athlete extends Vue {
} }
} }
private update() { private update(action: string) {
if (action === 'adopt' && this.clientID === '') {
this.msgError = 'Please give a valid athlete ID!';
return;
}
if (this.clientID != '' && this.clientID != this.athlete.id) {
this.msgError = 'Athlete ID does not match with current athlete!';
return;
}
const user = {_trainer: this.$store.getters.currentUser._id} const user = {_trainer: this.$store.getters.currentUser._id}
Object.assign(this.athlete, user) Object.assign(this.athlete, user)
this.$store.dispatch('updateAthlete', this.athlete) this.$store.dispatch('updateAthlete', this.athlete)
.then((res: any) => { .then((res: any) => {
this.msgSuccess = 'Athlete updated' this.msgSuccess = 'Athlete updated'

174
web/src/views/Athletes.vue

@ -1,73 +1,156 @@
<template> <template>
<h1 class="title is-2">/athletes</h1> <h1 class="title is-2">/athletes</h1>
<div class="tile">
<table <div class="notification is-link is-light">
class="table Your adopted athletes are displayed on this table. Choose an athlete and view his details, data.
</div>
<div class="section ">
<div class="table-container">
<table
class="table
is-striped is-striped
is-large is-large
is-hoverable is-hoverable
is-fullwidth is-fullwidth
has-text-left" has-text-centered">
> <thead>
<thead> <tr>
<tr> <th><span class="icon mr-1"><i class="fa fa-plug"></i></span>
<th><span class="icon mr-1"><i class="fa fa-id-card"></i></span> Athlete status
Athlete id </th>
</th> <th><span class="icon mr-1"><i class="fas fa-running"></i></span>
<th><span class="icon mr-1"><i class="fas fa-running"></i></span> Name
Name </th>
</th> <th><span class="icon mr-1"><i class="fas fa-id-badge"></i></span>
<th>Trainer</th> ID
<th>Actions</th> </th>
</tr> <th>Actions</th>
</thead> </tr>
<tr v-for="(athlete, index) in athletes" :key="index"> </thead>
<td class="is-family-monospace"> <tr v-for="(athlete, index) in myAthletes" :key="index">
<span>{{ athlete.id }}</span> <td class="is-family-monospace" v-if="athlete.name">
</td> <span v-if="athlete.socketID">Online</span>
<td> <span v-else>Offline</span>
<span>{{ athlete.name }}</span> </td>
</td> <td v-if="athlete.name">
<td v-if="athlete._trainer"> <span>{{ athlete.name }}</span>
<span class="icon mr-1"><i class="fa fa-check"></i></span> </td>
</td> <td v-if="athlete.name">
<td v-else> <span>{{ athlete.id }}</span>
<span class="icon mr-1"><i class="fa fa-times"></i></span> </td>
</td> <td v-if="athlete.name">
<td> <router-link :to="{ name: 'Table', params: { id: athlete._id }}" @click="saveAthlete(athlete)">
<router-link :to="{ name: 'Athlete', params: { id: athlete._id }}" @click="saveAthlete(athlete)"> <span class="icon is-medium has-background-primary has-text-white mr-1">
<i class="fa fa-lg fa-table"></i>
</span>
</router-link>
<router-link :to="{ name: 'Chart', params: { id: athlete._id }}" @click="saveAthlete(athlete)">
<span class="icon is-medium has-background-primary has-text-white mr-1">
<i class="fa fa-lg fa-chart-area"></i>
</span>
</router-link>
<router-link :to="{ name: 'Athlete', params: { id: athlete._id }}" @click="saveAthlete(athlete)">
<span class="icon is-medium has-background-warning has-text-white mr-1"> <span class="icon is-medium has-background-warning has-text-white mr-1">
<i class="fa fa-lg fa-user-edit"></i> <i class="fa fa-lg fa-user-edit"></i>
</span> </span>
</router-link> </router-link>
<router-link :to="{ name: 'Table', params: { id: athlete._id }}" @click="saveAthlete(athlete)"> <a @click="removeMyAthlete(athlete, index)">
<span class="icon is-medium has-background-danger has-text-white mr-1">
<i class="fa fa-lg fa-user-times"></i>
</span>
</a>
</td>
</tr>
</table>
</div>
</div>
<div class="section is-medium">
<div class="container">
<h3 class="title is-4">Search all athletes</h3>
<p class="subtitle">All athletes are displayed on this table.</p>
<div class="control">
<input class="input is-focused" placeholder="Search Athletes" type="text">
</div>
</div>
<div class="table-container">
<table
class="table
is-striped
is-large
is-hoverable
is-fullwidth
has-text-centered">
<thead>
<tr>
<th><span class="icon mr-1"><i class="fa fa-plug"></i></span>
Athlete status
</th>
<th><span class="icon mr-1"><i class="fas fa-running"></i></span>
Name
</th>
<th>Trainer</th>
<th>Actions</th>
</tr>
</thead>
<tr v-for="(athlete, index) in athletes" :key="index">
<td class="is-family-monospace">
<span v-if="athlete.socketID">Online</span>
<span v-else>Offline</span>
</td>
<td>
<span>{{ athlete.name }}</span>
</td>
<td v-if="athlete._trainer">
<span class="icon mr-1"><i class="fa fa-check"></i></span>
</td>
<td v-else>
<span class="icon mr-1"><i class="fa fa-times"></i></span>
</td>
<td>
<router-link :to="{ name: 'Table', params: { id: athlete._id }}" @click="saveAthlete(athlete)">
<span class="icon is-medium has-background-primary has-text-white mr-1"> <span class="icon is-medium has-background-primary has-text-white mr-1">
<i class="fa fa-lg fa-table"></i> <i class="fa fa-lg fa-table"></i>
</span> </span>
</router-link> </router-link>
<router-link :to="{ name: 'Chart', params: { id: athlete._id }}" @click="saveAthlete(athlete)"> <router-link :to="{ name: 'Chart', params: { id: athlete._id }}" @click="saveAthlete(athlete)">
<span class="icon is-medium has-background-primary has-text-white mr-1"> <span class="icon is-medium has-background-primary has-text-white mr-1">
<i class="fa fa-lg fa-chart-area"></i> <i class="fa fa-lg fa-chart-area"></i>
</span> </span>
</router-link> </router-link>
<router-link :to="{ name: 'Athlete', params: { id: athlete._id }}" @click="saveAthlete(athlete)">
</td> <span class="icon is-medium has-background-warning has-text-white mr-1">
</tr> <i class="fa fa-lg fa-user-edit"></i>
</table> </span>
</router-link>
</td>
</tr>
</table>
</div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import {Vue} from "vue-class-component"; import {Vue} from "vue-class-component";
import {AthleteInterface} from "@/store/modules/athletes"; import {AthleteInterface} from "@/store/modules/athletes";
import {UserInterface} from "@/store/modules/user";
export default class Athletes extends Vue { export default class Athletes extends Vue {
private athletes = [<AthleteInterface>{}] private athletes = [<AthleteInterface>{}]
private myAthletes = [<AthleteInterface>{}]
private user = <UserInterface>{}
private msg = '' private msg = ''
mounted() { mounted() {
this.myAthletes = [<AthleteInterface>{}]
this.$store.dispatch('getAthletes') this.$store.dispatch('getAthletes')
.then((res: any) => this.athletes = res.data) .then((res: any) => {
this.athletes = res.data;
this.user = this.$store.getters.currentUser
for (const athlete of this.athletes) {
if (athlete._trainer === this.user._id)
this.myAthletes.push(athlete)
}
})
.catch((err: any) => this.msg = err.response.data.errors.message || err.message || 'Something went wrong!') .catch((err: any) => this.msg = err.response.data.errors.message || err.message || 'Something went wrong!')
} }
@ -75,6 +158,13 @@ export default class Athletes extends Vue {
this.$store.dispatch('saveAthlete', athlete) this.$store.dispatch('saveAthlete', athlete)
} }
private removeMyAthlete(athlete: AthleteInterface, index: number) {
athlete._trainer = ''
this.$store.dispatch('updateAthlete', athlete)
.then(() => this.myAthletes.splice(index, 1))
}
} }
</script> </script>

Loading…
Cancel
Save