Skip to content

Commit 88ecefa

Browse files
user settings page
Signed-off-by: Arnav Gupta <[email protected]>
1 parent 99490ac commit 88ecefa

File tree

9 files changed

+535
-433
lines changed

9 files changed

+535
-433
lines changed

src/components/AppNavbar.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
<a class="nav-link active" href="">Home</a>
99
</li>
1010
<li v-if="username" class="nav-item">
11-
<a class="nav-link" href="">
12-
<i class="ion-compose"></i>&nbsp;New Post
13-
</a>
11+
<router-link class="nav-link" to="/editor">
12+
<i class="ion-compose"></i>&nbsp;New Article
13+
</router-link>
1414
</li>
1515
<li v-if="username" class="nav-item">
16-
<a class="nav-link" href="">
16+
<router-link class="nav-link" to="/settings">
1717
<i class="ion-gear-a"></i>&nbsp;Settings
18-
</a>
18+
</router-link>
1919
</li>
2020
<li v-if="username" class="nav-item">
2121
<router-link class="nav-link" :to="'/@' + username">

src/router.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ export default new Router({
2626
name: 'settings',
2727
component: () => import('@/views/Settings.vue'),
2828
},
29+
{
30+
path: '/editor',
31+
name: 'editor',
32+
component: () => import('@/views/Editor.vue'),
33+
},
2934
{
3035
path: '/@:username',
3136
name: 'profile',

src/store/api.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
ArticlesResponse,
77
Profile,
88
ProfileResponse,
9+
UserForUpdate,
910
} from './models';
1011

1112
export const conduitApi = axios.create({
@@ -32,7 +33,18 @@ export async function fetchProfile(username: string): Promise<Profile> {
3233
return (response.data as ProfileResponse).profile;
3334
}
3435

36+
export async function fetchUser(): Promise<User> {
37+
const response = await conduitApi.get('/user')
38+
return (response.data as UserResponse).user
39+
}
40+
3541
export async function getGlobalFeed() {
3642
const response = await conduitApi.get('/articles');
3743
return response.data as ArticlesResponse;
3844
}
45+
46+
47+
export async function updateUser(user: UserForUpdate): Promise<User> {
48+
const response = await conduitApi.put('/user', user)
49+
return (response.data as UserResponse).user
50+
}

src/store/models.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ export interface User {
1313
image?: string;
1414
}
1515

16+
export interface UserForUpdate {
17+
email?: string
18+
username?: string
19+
bio?: string
20+
password?: string
21+
image?: string
22+
}
23+
1624
export interface Article {
1725
slug: string;
1826
title: string;

src/store/modules/articles.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import {
33
VuexModule,
44
getModule,
55
Mutation,
6-
Action, MutationAction,
6+
Action,
7+
MutationAction,
78
} from 'vuex-module-decorators';
89
import store from '@/store';
910
import { Article } from '../models';
1011
import * as api from '@/store/api';
11-
type FeedType = 'global' | 'user'
12+
type FeedType = 'global' | 'user';
1213

1314
@Module({
1415
dynamic: true,
@@ -23,7 +24,7 @@ class ArticlesModule extends VuexModule {
2324
async refreshFeed(feedType: FeedType) {
2425
const globalFeed = await api.getGlobalFeed();
2526
return {
26-
feed: globalFeed.articles
27+
feed: globalFeed.articles,
2728
};
2829
}
2930
}

src/store/modules/users.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
import { getModule, Module, MutationAction, VuexModule } from 'vuex-module-decorators';
1+
import {
2+
getModule,
3+
Module,
4+
MutationAction,
5+
VuexModule,
6+
} from 'vuex-module-decorators';
27
import store from '@/store';
3-
import { Profile, User, UserSubmit } from '../models';
4-
import { fetchProfile, loginUser } from '../api';
8+
import { Profile, User, UserSubmit, UserForUpdate } from '../models';
9+
import { fetchProfile, fetchUser, loginUser, updateUser, setJWT } from '../api';
510

611
@Module({
712
namespaced: true,
@@ -13,14 +18,14 @@ class UsersModule extends VuexModule {
1318
user: User | null = null;
1419
profile: Profile | null = null;
1520

16-
1721
get username() {
1822
return (this.user && this.user.username) || null;
1923
}
2024

2125
@MutationAction
2226
async login(userSubmit: UserSubmit) {
2327
const user = await loginUser(userSubmit);
28+
setJWT(user.token)
2429
return { user };
2530
}
2631

@@ -29,6 +34,18 @@ class UsersModule extends VuexModule {
2934
const profile = await fetchProfile(username);
3035
return { profile };
3136
}
37+
38+
@MutationAction
39+
async loadUser() {
40+
const user = await fetchUser()
41+
return { user }
42+
}
43+
44+
@MutationAction
45+
async updateSelfProfile(userUpdateFields: UserForUpdate) {
46+
const user = await updateUser(userUpdateFields)
47+
return { user }
48+
}
3249
}
3350

3451
export default getModule(UsersModule);

src/views/Home.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,13 @@ import articles from '@/store/modules/articles';
5959
ArticlePreview,
6060
},
6161
})
62-
export default class extends Vue {
63-
get feed() { return articles.feed }
62+
export default class Home extends Vue {
63+
get feed() {
64+
return articles.feed;
65+
}
6466
6567
async created() {
66-
await articles.refreshFeed('global')
68+
await articles.refreshFeed('global');
6769
}
6870
}
6971
</script>

src/views/Settings.vue

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,31 @@
99
<fieldset>
1010
<fieldset class="form-group">
1111
<input
12+
v-model="user.image"
1213
class="form-control"
1314
type="text"
1415
placeholder="URL of profile picture"
1516
/>
1617
</fieldset>
1718
<fieldset class="form-group">
1819
<input
20+
v-model="user.username"
1921
class="form-control form-control-lg"
2022
type="text"
2123
placeholder="Your Name"
2224
/>
2325
</fieldset>
2426
<fieldset class="form-group">
2527
<textarea
28+
v-model="user.bio"
2629
class="form-control form-control-lg"
2730
rows="8"
2831
placeholder="Short bio about you"
2932
></textarea>
3033
</fieldset>
3134
<fieldset class="form-group">
3235
<input
36+
v-model="user.email"
3337
class="form-control form-control-lg"
3438
type="text"
3539
placeholder="Email"
@@ -42,7 +46,7 @@
4246
placeholder="Password"
4347
/>
4448
</fieldset>
45-
<button class="btn btn-lg btn-primary pull-xs-right">
49+
<button @click="updateProfile()" class="btn btn-lg btn-primary pull-xs-right">
4650
Update Settings
4751
</button>
4852
</fieldset>
@@ -52,3 +56,28 @@
5256
</div>
5357
</div>
5458
</template>
59+
60+
<script lang="ts">
61+
import { Vue, Component } from 'vue-property-decorator';
62+
import { User } from '@/store/models'
63+
import users from '@/store/modules/users';
64+
65+
@Component
66+
export default class Settings extends Vue {
67+
user: Partial<User> = {}
68+
69+
async created() {
70+
await users.loadUser()
71+
this.user = users.user || {}
72+
}
73+
74+
75+
async updateProfile() {
76+
await users.updateSelfProfile({
77+
email: this.user.email,
78+
bio: this.user.bio
79+
})
80+
this.user = users.user || {}
81+
}
82+
}
83+
</script>

0 commit comments

Comments
 (0)