I have made a small Vue app which fulfills the following user stories:
Given I make a search for an existing GitHub user, then:
- The user's username is shown
- The user's avatar is shown The user's most commonly used language, if available, in their repositories is shown as a 'favourite language'
- The user's followers, if there are any, are shown alongside their amount
Here is my single file component:
<template>
<div id="app">
<form @submit.prevent="submit">
<input v-model="inputValue" type="text" placeholder="Enter a GitHub username...">
<button>Go!</button>
</form>
<h1 v-text="username"></h1>
<img v-if="avatar" :src="avatar" class="avatar">
<h2 v-if="faveLang">๐ Favourite Language: {{faveLang}} ๐</h2>
<h3 v-if="followers.length > 0">Followers ({{followers.length}}):</h3>
<ul v-if="followers.length > 0">
<li v-for="follower in followers">
{{follower}}
</li>
</ul>
</div>
</template>
<script>
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import _ from 'lodash'
Vue.use(VueAxios, axios)
export default {
name: 'app',
data() {
return {
inputValue: '',
username: '',
avatar: '',
followers: [],
faveLang: '',
urlBase: 'https://api.github.com/users',
}
},
methods: {
submit() {
if (!!this.inputValue) {
const api = `${this.urlBase}/${this.inputValue}`
this.fetchUser(api)
}
},
fetchUser(api) {
Vue.axios.get(api).then((response) => {
const { data } = response
this.inputValue = ''
this.username = data.login
this.avatar = data.avatar_url
this.fetchFollowers()
this.fetchFaveLang()
}).catch(error => {
console.warn('ERROR:', error)
})
},
fetchFollowers() {
Vue.axios.get(`${this.urlBase}/${this.username}/followers`).then(followersResponse => {
this.followers = followersResponse.data.map(follower => {
return follower.login
})
})
},
fetchFaveLang() {
Vue.axios.get(`${this.urlBase}/${this.username}/repos`).then(reposResponse => {
const langs = reposResponse.data.map(repo => {
return repo.language
})
// Get most commonly occurring string from array
const faveLang = _.chain(langs).countBy().toPairs().maxBy(_.last).head().value()
if (faveLang !== 'null') {
this.faveLang = faveLang
}
})
}
}
}
</script>
<style>
body {
background-color: #daa520;
}
#app {
display: flex;
align-items: center;
flex-flow: column;
font-family: Comic Sans MS;
}
input {
width: 320px;
}
input,
button {
font-size: 25px;
}
h1 {
font-size: 44px;
}
.avatar {
height: 200px;
width: 200px;
border-radius: 10%;
}
</style>
My questions:
Is this a good way of managing changing values, ie by mutating the
data
object? Or should this be represented in state?How can I better structure this app? It could be split up into components but should it?
Is there a better way to make API calls like this, and should they go in the
methods
section?Should the API calls be placed inside the
mounted
method?