# Building a serverless Web app on AWS with Amplify, CDK(python) and Nuxt(Part 3)

Hi, Welcome to Part 3 of this post series. 
In [Part 1](https://phatrabbitapps.com/building-a-serverless-web-app-on-aws-with-amplify-cdkpython-and-nuxtpart-1), we covered the steps to get started in deploying an Amplify Application using AWS CDK. 
</br>
In [Part 2](https://phatrabbitapps.com/building-a-serverless-web-app-on-aws-with-amplify-cdkpython-and-nuxtpart-2), we added a backend to the application with Amplify tools and Amplify CLI. We added categories such as authentication, API, and Storage. 

</br>
In this part, we will start building the application from the login page.

<h2> Login Page </h2>
We will be using **Amplify UI Components** to quickly build a Sign Up/Login page/ reset password etc. 
</br>
Amplify UI Components is an open-source UI toolkit that encapsulates cloud-connected workflows inside of cross-framework UI components.

</br>
Install these 2 modules before proceeding </br>

```
npm install @aws-amplify/ui-components

@aws-amplify/ui-vue
``` 

Create a file called loginpage.vue inside the pages directory and type in this code

```
<template>
    <div class="container">
      <div class="content">
           <div class="left">
           <h2 class="article-title article-title--large">
					<a href="#" class="article-link">The Newspaper for <mark class="mark mark--primary">Those</mark> who can <mark class="mark mark--secondary">Read</mark></a>
				</h2>
          </div>
        <div class="right">
         <amplify-authenticator v-if="authState !== 'signedin'" class="signIn" />
          <div class="authenticated" v-if="authState === 'signedin' && user">
          <update-profile :email="user.attributes.email"
          :userId="user.attributes.sub" :username="user.username" />
     <button @click="signOut">Sign Out</button>
    </div>
      </div>
    </div>
    </div>
</template>

<script>
import { onAuthUIStateChange } from '@aws-amplify/ui-components'
import { Auth }  from 'aws-amplify';
import UpdateProfile from '../components/UpdateProfile.vue';
    export default {
components:{UpdateProfile},
       created() {
    onAuthUIStateChange((authState, authData) => {
      this.authState = authState;
      this.user = authData;
      console.log(this.user);
    })
  },
  data() {
    return { user: undefined, authState: undefined }
  },
  methods: {
    signOut(){
      console.log("clicked sign out");
       Auth.signOut();
       this.authState = undefined;
    } 
  },
   beforeDestroy() {
    return onAuthUIStateChange;
  }
        
    }
</script>

``` 
**amplify-authenticator** provides ready-made UI components for building the authentication pages of our application faster. </br>
We first verify if the user is signed in, by checking the authState.
</br>
If the user is signed in, grab the user details and send them as props to another page called updateprofile.vue. </br>

If not, display the login screen.
Here's how the login page looks like. 


![Screen Shot 2021-05-24 at 12.31.56.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1621972005036/R411euAYD.png)

<h2> Update Page </h2>
In the **components** folder, create a file called UpdateProfile.vue and typing this code

```
<template>
    <div class="update-profile">

  
 <input type="file" @change="onFileChange" />
  
      <div id="preview">
    <img class= "profilepic" v-if="url" :src="url" />
  </div>

      <div class="sub-load">
         
      <Loading v-if="loading"/>
     
    
<input v-else type="submit" value="Upload Image" class="btn" @click="upload">
  
        
      </div>

        
    
   </div>
</template>

<script>
import { API } from 'aws-amplify';
import { Storage }  from 'aws-amplify';
import { v4 as uuidv4 } from 'uuid';
import profile_icon from '@/assets/profile.png';
import {createUser} from '../src/graphql/mutations';

    export default {
        
        mounted(){
            this.first_name = this.username;
            this.email = this.email;
            this.userId = this.userId;
            console.log(this.email);
         
            
        },
    
       props:{
           username:String,
           email:String,
           userId:String,
       },
       data(){
           return{
           first_name:String,
           url:profile_icon,
           filename:String,
           loading:false,
           filePath:String
         
           }
       },
       methods:{
           
           
 async addUserToDb(){
                const uuid = uuidv4();
               const {username,email,filename,userId} = this;
               const signedURL = await Storage.get(filename); 
               const user = {id:userId,username,email,profilePicUrl:signedURL,userType:"ADMIN"};
               
               console.log("signed url"+signedURL);
               await API.graphql({
                   query:createUser,
                   variables:{input:user},
               }).then((result) =>{
                   this.loading = false;
                   console.log("result is"+result);
               })
               this.loading = false;
               console.log("successfully uploaded");
               this.$router.push({name:'index',params:{id: uuid}});
           },
          
           onFileChange(e) {
      const file = e.target.files[0];
      console.log(file);
      this.filename =file.name;
      this.filePath = file; 
      
      this.url = URL.createObjectURL(file);
    },
    upload(e) {
        console.log(this.filename);
        this.loading = true;
       const result = Storage.put(this.filename, this.filePath, {
          
           contentType:this.filePath.type,
    progressCallback(progress) {
        if(`${progress.loaded}` === `${progress.total}` ){
          
         
      
        }
        console.log(`Uploaded: ${progress.loaded}/${progress.total}`);
  },
}).then((result) =>{
    this.addUserToDb();
})
    }
         
       }
      
    }
</script>

``` 
Here's what's happening. Firstly, we get the passed-in user data(username, email and userId) as props. Then we give the user the possibility to select an image as a profile picture. When the upload button is clicked, the image is uploaded to an s3 bucket, the pre-signed URL is gotten and saved to the user table through the **createUser** mutation of our GraphQl API.

</br>

![Screen Shot 2021-05-24 at 12.32.21.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1621973613726/b6DNTQ316.png)

<h2> Create post </h2>
In the **pages** folder, create e file called createArticle.vue and type in this code

```
<template>
    <div class="container">
      <div class="content">
           <div class="left">
           <h2 class="article-title article-title--large">
					<a href="#" class="article-link">Talk <mark class="mark mark--tertiary">That</mark> Talk</a>
				</h2>
          </div>
        <div class="right">
        
   
        <div v-if="image" class="img-container">
            <input class="pickImage" type="file" @change="onFileChange" />
  
      <div id="preview-pic">
    <img class= "postpic" v-if="url" :src="url" />
  </div>
        </div>
  <div class="checkbox">
     
  <input type="checkbox" name="noImage" id="noImage" class="noImageCheck" @click="showImagePicker">
   <label for="noImage" class="noImage"> No Image</label>
  </div>
  <input type="text" class="postTitle" placeholder= "Post title" v-model="postTitle" name="postTitle" id="postTitle">
        <textarea placeholder="What's new ?" v-model="postText" class="article__post" rows="4" cols="10"/><br>
       
       <Loading v-if="loading" />
        <input type="submit" v-else-if="image" value="Create Article" class="article__btn" @click="addPostWithImage">
        <input type="submit" v-else value="Create Article" class="article__btn" @click="addPostWithoutImage">

        
      </div>
    </div>
    
    </div>
   
</template>

<script>
import { onAuthUIStateChange } from '@aws-amplify/ui-components'
import { Auth,API,Storage }  from 'aws-amplify';
import add_image from '@/assets/add_pic.svg';

import { v4 as uuidv4 } from 'uuid';
import {createPost} from '../src/graphql/mutations';
    export default {
mounted() {
    console.log('Params: ', this.$route.params);
    this.userId = this.$route.params.userId;
    console.log("user id is"+this.userId);
   
       
},

    
        data(){
            return {
                postTitle:"",
               postText:'',
               loading:false,
               image:true,
              url:add_image,
               filename:String,
           filePath:String,
            }
        },
         methods:{
             showImagePicker(){
               this.image = !this.image;
             },
           async addPostToDb(){
                const uuid = uuidv4();
               const {userId,postText,filename,postTitle,image} = this;
               const signedURL = await Storage.get(filename); 
               const post = {id:uuid,userId:userId,postText,title:postTitle,postType:"BUSINESS",postStatus:"CREATED",postImageUrl:signedURL,image};
               
               console.log("signed url"+signedURL);
               await API.graphql({
                   query:createPost,
                   variables:{input:post},
               }).then((result) =>{
                   console.log("result is"+result);
                   this.loading = false;
               })
               console.log("successfully uploaded");
               this.postText = "";
               this.loading = false;
             //this.$emit('close');
           },
              
           onFileChange(e) {
      const file = e.target.files[0];
      console.log(file);
      this.filename =file.name;
      this.filePath = file; 
      
      this.url = URL.createObjectURL(file);
    },
     addPostWithImage(e) {
        console.log("clicked");
        this.loading = true;
        
       const result = Storage.put(this.filename, this.filePath, {
          
           contentType:this.filePath.type,
    progressCallback(progress) {
        if(`${progress.loaded}` === `${progress.total}` ){
          
         
      
        }
        console.log(`Uploaded: ${progress.loaded}/${progress.total}`);
  },
}).then((result) =>{
    this.addPostToDb();
})
    },
   async addPostWithoutImage(e){
         const uuid = uuidv4();
               const {userId,postText,postTitle,image} = this;
              
               const post = {id:uuid,userId:userId,postText,title:postTitle,postType:"BUSINESS",postStatus:"CREATED",image};
               
               await API.graphql({
                   query:createPost,
                   variables:{input:post},
               }).then((result) =>{
                   console.log("result is"+result);
                   this.loading = false;
               })
               console.log("successfully uploaded");
               this.postText = "";
               this.loading = false;
    }

         }
        
    }
</script>


``` 
This piece of code is similar to the updateprofile code. </br>
You give the user the possibility to upload a post with or without an image. You save the post in the post table using **createPost** mutation .


![Screen Shot 2021-05-24 at 12.34.42.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1621973877222/P8aDogo89.png)

</h2>Index page</h2>
In the pages folder, open up the index.vue file and type in the following code

```
<template>
    <div>
<header class="header responsive-wrapper">
	<div class="header-left">
		<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="233.445" height="52.805" viewBox="0 0 233.445 52.805">
			<defs>
				<clipPath id="clip-fox-news-logo">
					<rect width="233.445" height="52.805" />
				</clipPath>
			</defs>
			<g id="fox-news-logo" clip-path="url(#clip-fox-news-logo)">
				<g id="Group_1" data-name="Group 1" transform="translate(-2179.585 601.093)">
					<path id="Path_5" data-name="Path 5" d="M4.185-29.205H22.59v4.59H9.5v7.7h11.97v4.545H9.5V0H4.185Zm27.675,6.75a12.117,12.117,0,0,1,4.14.7,8.656,8.656,0,0,1,3.33,2.138q3.105,3.15,3.105,8.73,0,5.49-3.105,8.64A9.921,9.921,0,0,1,31.86.63,10.222,10.222,0,0,1,24.3-2.25Q21.2-5.355,21.2-10.89q0-5.625,3.105-8.73A10.217,10.217,0,0,1,31.86-22.455Zm5.265,11.52a8.372,8.372,0,0,0-1.35-5.2,4.5,4.5,0,0,0-3.757-1.733,5.013,5.013,0,0,0-3.937,1.733,7.654,7.654,0,0,0-1.53,5.2,8.27,8.27,0,0,0,1.372,5.2A4.534,4.534,0,0,0,31.68-4.005,4.989,4.989,0,0,0,35.6-5.738,7.654,7.654,0,0,0,37.125-10.935ZM64.62,0H58.14l-5.4-7.02L47.7,0H41.175l8.5-10.89-8.5-11.025H47.7l5.355,7.02,5.085-7.02h6.48L56.16-10.89ZM78.48-29.205l12.87,20.7v-20.7h5.31V0h-5.4L77.985-21.42V0h-5.31V-29.205Zm37.71,9.945a9.966,9.966,0,0,1,1.688,3.33,12.23,12.23,0,0,1,.563,3.465,20.182,20.182,0,0,1-.18,2.835H104.13a7.606,7.606,0,0,0,1.305,4.32,4.268,4.268,0,0,0,3.69,1.665q3.285,0,3.915-2.88H118.4A7.849,7.849,0,0,1,115.38-1.35,9.93,9.93,0,0,1,109.125.63a9.489,9.489,0,0,1-7.245-3.15,11.96,11.96,0,0,1-3.015-8.415,11.822,11.822,0,0,1,3.015-8.46,9.529,9.529,0,0,1,7.245-3.06A8.486,8.486,0,0,1,116.19-19.26Zm-7.02,1.035a4.385,4.385,0,0,0-3.51,1.463,6.578,6.578,0,0,0-1.485,3.758h9.315q0-3.555-2.25-4.77A4.4,4.4,0,0,0,109.17-18.225Zm13.455-3.645,4.41,15.615,4.185-14.4h4.815L140.22-6.21l4.455-15.66h5.31L142.785,0h-5.22l-4.05-13.1L129.555,0H124.29l-7.245-21.87Zm31.05,15.21q.09,3.105,4.545,3.1a4.934,4.934,0,0,0,2.813-.743,2.1,2.1,0,0,0,1.1-1.733,1.847,1.847,0,0,0-.675-1.53,6.639,6.639,0,0,0-2.115-.99l-4.77-1.71q-5.31-1.845-5.31-6.03a5.172,5.172,0,0,1,2.5-4.477,11.8,11.8,0,0,1,6.7-1.687,10.044,10.044,0,0,1,6.48,1.845,6,6,0,0,1,2.362,4.635h-4.995a2.191,2.191,0,0,0-1.035-1.71,4.856,4.856,0,0,0-2.7-.63,4.6,4.6,0,0,0-2.723.7,1.974,1.974,0,0,0-.967,1.6q0,1.575,2.655,2.34l5.175,1.935a10.264,10.264,0,0,1,3.938,2.182A4.576,4.576,0,0,1,168.03-6.12a5.8,5.8,0,0,1-2.565,4.68,11.1,11.1,0,0,1-7.02,2.07,11.753,11.753,0,0,1-7.02-1.913,6.353,6.353,0,0,1-2.7-5.377Z" transform="translate(2245 -561)" />
					<path id="Path_1" data-name="Path 1" d="M2207.653-46.775c-.029,5.98,9.656-7.959,11.9-8.762a45.226,45.226,0,0,1,9.4-2.275,19.066,19.066,0,0,1,2.663-.116c4.366.13-3.9-18.154-3.9-18.154l-8.853.386s-6.824,3.109-7.306,9.208,1.265,4.691-.822,10.951c-1.45,4.351-2.432,3.276-3.084,5.217A25.988,25.988,0,0,0,2207.653-46.775Z" transform="translate(-0.475 -503)" />
					<path id="Path_2" data-name="Path 2" d="M2232.822-46.775c.029,5.98-9.656-7.959-11.9-8.762a45.226,45.226,0,0,0-9.4-2.275,19.066,19.066,0,0,0-2.663-.116c-4.366.13,3.9-18.154,3.9-18.154l8.853.386s6.824,3.109,7.306,9.208-1.265,4.691.822,10.951c1.45,4.351,2.432,3.276,3.084,5.217A25.988,25.988,0,0,1,2232.822-46.775Z" transform="translate(-28 -503)" />
					<circle id="Ellipse_1" data-name="Ellipse 1" cx="1" cy="1" r="1" transform="translate(2205 -559)" />
					<path id="Path_3" data-name="Path 3" d="M2216.209-91.186c.2,1.456,9.045,4.389,11.518,8.66s3.761-15.174,2.68-16.427S2216.012-92.642,2216.209-91.186Z" transform="translate(0 -502)" />
					<path id="Path_4" data-name="Path 4" d="M2230.791-91.186c-.2,1.456-9.045,4.389-11.518,8.66s-3.761-15.174-2.68-16.427S2230.988-92.642,2230.791-91.186Z" transform="translate(-34 -502)" />
				</g>
			</g>
		</svg>
	</div>
	<div class="header-middle">
		<a href="#" class="header-link">Call Us (237) 678 323 387</a>
		<span>/</span>
		<a href="#" class="header-link">rosius@ghost.com</a>
	</div>
	<div class="header-right">
	<nav class="header-nav">

 
		<a href="#" class="header-link" v-if="signedIn" @click="signUserOut">Logout</a>
       <NuxtLink  to="/loginpage" class="header-link" v-else> Login </NuxtLink>
       
        
	
   
		<nuxt-link :to="{name:'createArticle',params:{userId:user.id}}" class="header-link header-link--button">Write Article</nuxt-link>
	</nav>
 
       <img class="article-author-img" :src="user.profilePicUrl" alt="Profile Picture">
    
	
		</div>
</header>
<main class="responsive-wrapper">
	<div class="page-title">
		<h1>Latest Updates</h1>
	</div>
	<div class="magazine-layout">
		<div class="magazine-column">
			
            <article class="article">
				<h2 class="article-title article-title--large">
					<a href="#" class="article-link">The First Signs of <mark class="mark mark--primary">Alcoholic Liver</mark> Damage Are Not in the Liver</a>
				</h2>
				<div class="article-excerpt">
					<p>The combination of my father's death and my personal back ground lit a fire in me to know more</p>
					<p>He was admitted to the hospital on June 24, 2016.</p>
				</div>
				<div class="article-author">
					<div class="article-author-img">
						<img src="https://assets.codepen.io/285131/author-3.png" />
					</div>
					<div class="article-author-info">
						<dl>
							<dt>David Sherof</dt>
							<dd>Reporter</dd>
						</dl>
					</div>
				</div>
			</article>
		
		</div>
		<div class="magazine-column"  v-for="post in posts" :key="post.id">
			<article v-if="post.image" class="article">
				<figure class="article-img">
					<img :src="post.postImageUrl" />
				</figure>
                <mark class="mark mark--secondary article-title">{{post.postType}}</mark>
				<h2 class="article-title article-title--medium">
					<a href="#" class="article-link">{{post.title}}</a>
				</h2>
				<div class="article-excerpt">
					<p>{{post.postText}}</p>
				</div>
				<div class="article-author">
					<div class="article-author-img">
						<img :src="post.user.profilePicUrl" />
					</div>
					<div class="article-author-info">
						<dl>
							<dt>{{post.user.username}}</dt>
							<dd>{{post.user.userType}}</dd>
						</dl>
					</div>
				</div>
			</article>
            <article v-else class="article">
				<h2 class="article-title article-title--large">
					<a href="#" class="article-link"> <mark class="mark mark--primary">{{post.title}}</mark> </a>
				</h2>
				<div class="article-excerpt">
					{{post.postText}}
				</div>
				<div class="article-author">
					<div class="article-author-img">
						<img :src="post.user.profilePicUrl" />
					</div>
					<div class="article-author-info">
						<dl>
							<dt>{{post.user.username}}</dt>
							<dd>{{post.user.userType}}</dd>
						</dl>
					</div>
				</div>
			</article>
            
		</div>
		<div class="magazine-column">
			<article class="article">
				<figure class="article-img">
					<img src="https://images.unsplash.com/photo-1512521743077-a42eeaaa963c?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1351&q=80" />
				</figure>
				<h2 class="article-title article-title--small">
					<a href="#" class="article-link">To Become <mark class="mark mark--secondary">Happier</mark>, Ask Yourself These Two Questions Every Night</a>
				</h2>
				<div class="article-creditation">
					<p>By Jonathan O'Connell</p>
				</div>
			</article>
			<article class="article">
				<figure class="article-img">
					<img src="https://images.unsplash.com/photo-1569234817121-a2552baf4fd4?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80" />
				</figure>
				<h2 class="article-title article-title--small">
					<a href="#" class="article-link">10 Things I Stole From People Smarter Than Me</a>
				</h2>
				<div class="article-creditation">
					<p>By Jonathan O'Connell</p>
				</div>
			</article>
		</div>
		<div class="magazine-column">
			<article class="article">
				<h2 class="article-title article-title--medium">
					<a href="#" class="article-link">Traveller Visiting Ice Cave With Amazing Eye-Catching Scenes</a>
				</h2>
				<div class="article-excerpt">
					<p>Slack has become indispensible for many businesses operation remotely during the pandemic. Here's what the acquisition could mean for users...</p>
				</div>
				<div class="article-author">
					<div class="article-author-img">
						<img src="https://assets.codepen.io/285131/author-2.png" />
					</div>
					<div class="article-author-info">
						<dl>
							<dt>James Robert</dt>
							<dd>Editor</dd>
						</dl>
					</div>
				</div>
			</article>
			<article class="article">
				<small class="article-category">
					<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="28" height="22" viewBox="0 0 28 22">
  <defs>
    <clipPath id="clip-headphones">
      <rect width="28" height="22"/>
    </clipPath>
  </defs>
  <g id="headphones" clip-path="url(#clip-headphones)">
    <g id="Group_2" data-name="Group 2" transform="translate(-3680 -609)">
      <path id="Subtraction_1" data-name="Subtraction 1" d="M5,12H5A5.274,5.274,0,0,1,0,6.5,5.274,5.274,0,0,1,5,1V12Z" transform="translate(3680 619)"/>
      <rect id="Rectangle_18" data-name="Rectangle 18" width="2" height="11" transform="translate(3686 620)"/>
      <path id="Subtraction_5" data-name="Subtraction 5" d="M1.243,12H.045C.015,11.67,0,11.334,0,11A11,11,0,0,1,18.778,3.222,10.925,10.925,0,0,1,22,11c0,.331-.015.667-.045,1h-1.2a14.108,14.108,0,0,0-2.685-6.241A8.982,8.982,0,0,0,11,2,8.982,8.982,0,0,0,3.929,5.759,14.109,14.109,0,0,0,1.243,12Z" transform="translate(3683 609)"/>
      <path id="Subtraction_6" data-name="Subtraction 6" d="M5,0H5A5.274,5.274,0,0,0,0,5.5,5.274,5.274,0,0,0,5,11V0Z" transform="translate(3708 631) rotate(180)"/>
      <rect id="Rectangle_23" data-name="Rectangle 23" width="2" height="11" transform="translate(3700 620)"/>
      <path id="Path_8" data-name="Path 8" d="M.156-.031,2.125-1.687,2,2H0Z" transform="translate(3683 619)"/>
      <path id="Path_9" data-name="Path 9" d="M1.969-.031,0-1.687.125,2h2Z" transform="translate(3702.875 619)"/>
    </g>
  </g>
</svg>
					<span>Post Reports / Podcast</span>
				</small>
				<h2 class="article-title article-title--medium">
					<a href="#" class="article-link">Things to Do After 6 P.M Will Enrich <mark class="mark mark--tertiary">Your Life</mark></a>
				</h2>
				<div class="article-podcast-player">
					<button class="podcast-play-button">
						<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" fill="#000000" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"></rect><path d="M232.3125,114.34375,88.34375,26.35937A15.99781,15.99781,0,0,0,64,40.00781V215.99219a16.00521,16.00521,0,0,0,24.34375,13.64843L232.3125,141.65625a16.00727,16.00727,0,0,0,0-27.3125Z"></path></svg>
					</button>
					<div class="podcast-progression">
						
					</div>
					<span class="podcast-time">23:45</span>
				</div>
				<div class="article-podcast-info">
					Apple Podcasts, Google Podcasts, Stitcher
				</div>
				<div class="article-author">
					<div class="article-author-img">
						<img src="https://assets.codepen.io/285131/author-3.png" />
					</div>
					<div class="article-author-info">
						<dl>
							<dt>David Sherof</dt>
							<dd>Reporter</dd>
						</dl>
					</div>
				</div>
			</article>
		</div>
	</div>
</main>
    </div>
</template>

<script>
import { onAuthUIStateChange } from '@aws-amplify/ui-components'
import { Auth,API }  from 'aws-amplify';
import {onCreatePost} from '../src/graphql/subscriptions';
import {getUser,listPosts} from '../src/graphql/queries';

    export default {
         data() {
    return { user: Object, 
    posts:[],
    authState: undefined,
     signedIn:false }
  },
 async beforeCreate() {
     
    try {
      const user = await Auth.currentAuthenticatedUser();
      console.log(user.attributes.sub);
      this.getUserDetails(user.attributes.sub);

      this.signedIn = true
    } catch (err) {
      this.signedIn = false
    }
    
 },

  created() {
   
  this.getPosts();
  //this.subscribe();

  },

   methods: {
        async getUserDetails(userId){
         const userData =  await API.graphql({
         query:getUser,
         variables:{id: userId}
       });
       this.user =userData.data.getUser;
console.log(this.user);
    },
    signUserOut(){
      console.log("clicked sign out");
       Auth.signOut();
       
       this.$router.push({name:'loginpage'});
    } ,
    async getPosts(){
       
       const posts = await API.graphql({
         query:listPosts
         
       
       });
       this.posts = posts.data.listPosts.items;
       console.log(posts.data.listPosts);
     },
 

  },
  


       
    }
</script>

<style lang="scss" scoped>
.profile-pic{
    object-fit: cover;
    width: 40px;
    height: 40px;
}
</style>
``` 
Firstly, we determine the authentication state of the application. We check to see if any user is currectly signed in . 

```
  try {
      const user = await Auth.currentAuthenticatedUser();
      console.log(user.attributes.sub);
      this.getUserDetails(user.attributes.sub);

      this.signedIn = true
    } catch (err) {
      this.signedIn = false
    }
    
 },
``` 
If true, we display the logout button while getting the user details. If false, we display the login button.

</br>
We also retrieve and display the list of posts in our posts table from the dynamoDB.

```
 async getPosts(){
       
       const posts = await API.graphql({
         query:listPosts
         
       
       });
       this.posts = posts.data.listPosts.items;
       console.log(posts.data.listPosts);
     },
 

  },
``` 
<h2> Github </h2>
Get the complete code [here](https://github.com/trey-rosius/newspaper-app)

<h2> What Next </h2>
There's still a ton of things to be done with the application. I wrote the app on a weekend, and I know there are a lot of bugs in it. </br>
Challenge yourself to add more features and resolve any bugs you find within the app.
</br>

Thanks for taking out the time to check this out. I really appreciate it. 
</br>
I'll love to know what you think about this piece. 
</br>
Stay Safe ❤️






