Skip to content

Commit

Permalink
feat(/user): add basic user lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
Jabster28 committed Jul 11, 2020
1 parent b708a7b commit 70ec916
Show file tree
Hide file tree
Showing 5 changed files with 347 additions and 2 deletions.
53 changes: 51 additions & 2 deletions src/layouts/MainLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,38 @@
<q-drawer v-model="leftDrawerOpen" behavior="mobile" show-if-above bordered>
<q-list>
<q-item-label header class="text-grey-8">
Navigation
Main
</q-item-label>
<EssentialLink
v-for="link in essentialLinks"
:key="link.title"
v-bind="link"
/>
<q-item-label header class="text-grey-8">
Anime
</q-item-label>
<EssentialLink
v-for="link in animeLinks"
:key="link.title"
v-bind="link"
/>
<q-item-label header class="text-grey-8">
Users
</q-item-label>
<EssentialLink
v-for="link in userLinks"
:key="link.title"
v-bind="link"
/>
<q-item-label header class="text-grey-8">
Links
</q-item-label>
<EssentialLink
v-for="link in links"
:key="link.title"
v-bind="link"
external
/>
</q-list>
</q-drawer>

Expand Down Expand Up @@ -66,13 +91,37 @@ export default {
caption: 'Home',
icon: 'home',
link: '/'
},
}
],
animeLinks: [
{
title: 'Search',
caption: 'Search for an anime',
icon: 'search',
link: '/search'
}
],
userLinks: [
{
title: 'Me',
caption: 'Open your MAL page',
icon: 'person',
link: '/me'
},
{
title: 'Set Username',
caption: 'Allows you to see favourited anime etc.',
icon: 'settings',
link: '/setusr'
}
],
links: [
{
title: 'GitHub repo',
caption: 'Source code for this application',
icon: 'code',
link: 'https://github.com/Jabster28/mirai'
}
]
};
},
Expand Down
19 changes: 19 additions & 0 deletions src/pages/Me.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template> </template>

<script lang="ts">
import Vue from 'vue';
export default Vue.extend({
name: 'PageMe',
mounted() {
/* @ts-ignore */
let username = this.$q.localStorage.getItem('username');
/* @ts-ignore */
if (!username) {
this.$router.replace('/setusr/me');
} else {
this.$router.replace('/user/' + encodeURIComponent(username.toString()));
}
}
});
</script>
96 changes: 96 additions & 0 deletions src/pages/SetUsername.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<template>
<q-page class="row items-center justify-evenly">
<q-form @submit="onSubmit" class="col-6 q-gutter-md">
<q-input
filled
v-model="username"
label="Your username"
lazy-rules
:loading="loading"
:rules="[val => (val && val.length > 0) || 'Please type something']"
/>

<div>
<q-btn
label="Submit"
:loading="loading"
:disabled="loading"
type="submit"
color="primary"
/>
</div>
</q-form>
</q-page>
</template>

<script lang="ts">
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import Vue from 'vue';
import axios from 'axios';
export default Vue.extend({
name: 'PageSetUsername',
data() {
return {
username: '',
loading: false
};
},
mounted() {
this.username = this.$q.localStorage.getItem('username') || '';
document.title = 'Set your username | Mirai';
},
methods: {
load() {
this.loading = true;
},
onSubmit() {
if (!navigator.onLine) {
this.$q.notify({
color: 'red',
icon: 'error',
message: "Offline; can't verify username"
});
return;
}
this.loading = true;
axios
.get(`https://api.jikan.moe/v3/user/${this.username}`)
.then(data => {
/* @ts-ignore */
let savedname = this.$q.localStorage.getItem('username');
/* @ts-ignore */
if (!savedname) {
this.$q.localStorage.set('username', '');
savedname = this.$q.localStorage.getItem('username');
}
savedname = this.username;
this.$q.localStorage.set('username', savedname);
this.loading = false;
this.$q.notify({
color: 'green',
icon: 'check',
message: 'Saved'
});
if (this.$route.params.redirect)
this.$router
.replace('/' + decodeURIComponent(this.$route.params.redirect))
.catch(e => console.log(e));
})
.catch(e => {
console.log(e);
this.loading = false;
if (e == 'Error: Request failed with status code 404') {
this.$q.notify({
color: 'red',
icon: 'error',
message: 'User not found.'
});
}
});
}
}
});
</script>
161 changes: 161 additions & 0 deletions src/pages/User.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<template>
<q-page class="items-center justify-evenly">
<div class="post">
<div v-if="error" class="error">
{{ error }}
</div>

<div v-if="user.username" class="content">
<div
:class="[
'q-mx-lg',
'items-center',
'justify-evenly',
$q.screen.width > 800 ? 'row' : 'col'
]"
>
<div class="col-5">
<q-img v-if="user.image_url" :src="user.image_url" />
<q-btn
class="q-ma-lg"
color="primary"
clickable
type="a"
target="_blank"
:href="user.url"
>
Open in MAL</q-btn
>
<q-btn
v-if="isUser()"
class="q-ma-lg"
color="secondary"
clickable
tag="a"
to="/setusr/me"
>
Not you?</q-btn
>
</div>
<div class="col-5">
<h2>{{ user.username }}</h2>

<h6 class="disabled">{{ user.user_id }}</h6>
<!-- <p class="text-justify">{{ anime.synopsis }}</p>
<h5>
<q-icon name="stars" /> {{ anime.score.toPrecision(3) }} / 10
</h5>
<h5><q-icon name="visibility" /> {{ norm(anime.members) }}</h5>
<h5><q-icon name="star" /> {{ norm(anime.favorites) }}</h5>
<h5 v-if="anime.rank"># {{ norm(anime.rank) }}</h5> -->
</div>
</div>
</div>
</div>
</q-page>
</template>

<script lang="ts">
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import axios from 'axios';
import Vue from 'vue';
export default Vue.extend({
name: 'PageUser',
data() {
return {
user: {
username: ''
},
error: ''
};
},
created() {
// fetch the data when the view is created and the data is
// already being observed
this.fetchData();
},
watch: {
// call again the method if the route changes
$route: 'fetchData'
},
methods: {
norm(x: number) {
if (!x) return;
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
},
isUser() {
return this.$q.localStorage.getItem('username') == this.$route.params.id;
},
fetchData() {
this.error = '';
this.$q.loading.show({
delay: 400 // ms
});
const currentUser = this.$route.params.id;
if (!navigator.onLine) {
console.log('checking for cached user data');
let cache = this.$q.localStorage.getItem('cache');
if (!cache) {
this.$q.localStorage.set('cache', {});
cache = this.$q.localStorage.getItem('cache');
}
/* @ts-ignore */
if (!cache.user) cache.user = {};
/* @ts-ignore */
if (cache.user[this.$route.params.id]) {
if (currentUser != this.$route.params.id) return;
/* @ts-ignore */
console.log('found some');
/* @ts-ignore */
this.user = cache.user[this.$route.params.id];
this.$q.loading.hide();
return;
} else {
console.log('none found');
if (currentUser != this.$route.params.id) return;
this.$q.notify(
"This user's data hasn't been cached, so we can't show you anything. Connect to the internet and try again."
);
this.$q.loading.hide();
return;
}
}
// replace `getPost` with your data fetching util / API wrapper
axios
.get(`https://api.jikan.moe/v3/user/${this.$route.params.id}`)
.then(data => {
this.$q.loading.hide();
this.user = data.data;
document.title = `${this.user.username} | Mirai`;
/* @ts-ignore */
let cache = this.$q.localStorage.getItem('cache');
/* @ts-ignore */
if (!cache) {
this.$q.localStorage.set('cache', {});
cache = this.$q.localStorage.getItem('cache');
}
/* @ts-ignore */
if (!cache.user) cache.user = {};
/* @ts-ignore */
cache.user[this.$route.params.id] = this.user;
/* @ts-ignore */
cache.user[this.$route.params.id].date = new Date();
if (currentUser != this.$route.params.id) return;
this.$q.localStorage.set('cache', cache);
})
.catch((e: string) => {
console.log(e);
this.$q.loading.hide();
this.error = e;
});
}
}
});
</script>
20 changes: 20 additions & 0 deletions src/router/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,26 @@ const routes: RouteConfig[] = [
component: () => import('layouts/MainLayout.vue'),
children: [{ path: '', component: () => import('pages/Anime.vue') }]
},
{
path: '/user/:id',
component: () => import('layouts/MainLayout.vue'),
children: [{ path: '', component: () => import('pages/User.vue') }]
},
{
path: '/me',
component: () => import('layouts/MainLayout.vue'),
children: [{ path: '', component: () => import('pages/Me.vue') }]
},
{
path: '/setusr',
component: () => import('layouts/MainLayout.vue'),
children: [{ path: '', component: () => import('pages/SetUsername.vue') }]
},
{
path: '/setusr/:redirect',
component: () => import('layouts/MainLayout.vue'),
children: [{ path: '', component: () => import('pages/SetUsername.vue') }]
},

// Always leave this as last one,
// but you can also remove it
Expand Down

0 comments on commit 70ec916

Please sign in to comment.