Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ module.exports = {
'vue/singleline-html-element-content-newline': 0,
'vue/html-self-closing': 0,
'vue/html-closing-bracket-newline': 0,
'prettier/prettier': [
'error',
{
endOfLine: 'auto',
},
],
},
parserOptions: {
parser: '@typescript-eslint/parser',
Expand Down
29 changes: 29 additions & 0 deletions components/addTask.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<aside class="mx-auto flex justify-between mt-24 px-4">
<label for="add task" class="flex-1">
<input
v-model="newTask"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no .trim on data

type="text"
name="add task"
class="
Expand Down Expand Up @@ -47,14 +48,42 @@ import { defineComponent } from '@nuxtjs/composition-api'

export default defineComponent({
emits: ['newTask'],
data() {
return {
newTask: '',
}
},
methods: {
addTask() {
// console.log(this.$emit('newTask'))
/**
* @todo Complete this function.
* @todo 1. Send the request to add the task to the backend server.
* @todo 2. Add the task in the dom.
* @hint use emit to make a event that parent can observe
*/
if (this.newTask === '') {
this.$toast.error('Task cannot be empty')
} else {
this.$axios({
headers: {
Authorization: 'Token ' + this.$store.getters.token,
},
url: 'todo/create/',
method: 'post',
data: {
title: this.newTask,
},
})
.then(() => {
this.$emit('newTask')
this.$toast.success('Successfully added task')
this.newTask = ''
})
.catch(() => {
this.$toast.error('Error in updating the todos')
})
}
},
},
})
Expand Down
1 change: 1 addition & 0 deletions components/navbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export default defineComponent({
logout() {
this.$store.commit('setToken', null)
this.$router.replace('/login')
this.$toast.success('Logged Out Successfully')
},
},
})
Expand Down
7 changes: 7 additions & 0 deletions middleware/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,11 @@ export default defineNuxtMiddleware((context) => {
* @todo Redirect the user to main page if token is present in store
* @hints check what propeties context has
*/
const path = context.route.fullPath
const token = context.store.getters.token
if (token == null && path === '/') {
return context.redirect('login/')
} else if (token != null && path !== '/') {
return context.redirect('/')
}
})
89 changes: 71 additions & 18 deletions pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<main class="max-w-lg mx-auto px-6">
<add-task @newTask="getTasks" />
<transition>
<transition name="fade">
<span v-if="loading">Fetching Tasks....</span>
<ul v-else class="flex-col mt-9 mx-auto">
<li
Expand All @@ -21,19 +21,21 @@
>
<label :for="todo.id">
<input
v-show="todo.editing"
:id="todo.id"
v-model="todo.title"
type="text"
:class="[
'hideme appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring todo-edit-task-input',
'appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:ring todo-edit-task-input',
]"
:name="todo.title"
placeholder="Edit The Task"
/>
</label>
<div class="">
<button
v-show="todo.editing"
class="
hideme
bg-transparent
hover:bg-gray-500
text-gray-700 text-sm
Expand All @@ -51,11 +53,12 @@
Done
</button>
</div>
<div :class="['todo-task text-gray-600']">
<div v-show="!todo.editing" :class="['todo-task text-gray-600']">
{{ todo.title }}
</div>
<span class="">
<button
v-show="!todo.editing"
style="margin-right: 5px"
type="button"
class="
Expand All @@ -77,6 +80,7 @@
/>
</button>
<button
v-show="!todo.editing"
type="button"
class="
bg-transparent
Expand Down Expand Up @@ -109,25 +113,17 @@ import addTask from '~/components/addTask.vue'

export default defineComponent({
components: { addTask },
middleware: 'auth',

data() {
return {
hello: 'hello world!',
todos: [
{
title: 'Henlo',
id: 1,
editing: false,
},
{
title: 'Frens',
id: 2,
editing: false,
},
],
todos: [],
loading: false,
}
},
mounted() {
this.loading = true
this.getTasks()
},
methods: {
Expand All @@ -138,6 +134,25 @@ export default defineComponent({
* @hints use store and set loading true
* @caution you have to assign new value to todos for it to update
*/
await this.$axios({
headers: {
Authorization: 'Token ' + this.$store.getters.token,
},
url: 'todo/',
method: 'get',
})
.then(({ data }) => {
this.loading = false
this.todos = data.map((todo) => {
return {
...todo,
editing: false,
}
})
})
.catch(() => {
this.$toast.error('Error in fetching the todos')
})
},
/**
* Function to update a single todo
Expand All @@ -147,7 +162,30 @@ export default defineComponent({
* @todo 1. Send the request to update the task to the backend server.
* @todo 2. Update the task in the dom.
*/
updateTask(_index, _id) {},
updateTask(_index, _id) {
// console.log(this.todos[_index].title)
if (this.todos[_index].title === '') {
this.$toast.error('Task cannot be empty!!')
} else {
this.$axios({
headers: {
Authorization: 'Token ' + this.$store.getters.token,
},
url: 'todo/' + _id + '/',
method: 'patch',
data: {
title: this.todos[_index].title,
},
})
.then(() => {
this.todos[_index].editing = false
this.$toast.success('Task updated successfully')
})
.catch(() => {
this.$toast.error('Error in updating the todos')
})
}
},
/**
* toggle visibility of input and buttons for a single todo
* @argument {number} index - index of element to toggle
Expand All @@ -165,7 +203,22 @@ export default defineComponent({
* @todo 1. Send the request to delete the task to the backend server.
* @todo 2. Remove the task from the dom.
*/
deleteTask(_index, _id) {},
deleteTask(_index, _id) {
this.$axios({
headers: {
Authorization: 'Token ' + this.$store.getters.token,
},
url: 'todo/' + _id + '/',
method: 'delete',
})
.then(() => {
this.$toast.success('Todo deleted successfully')
this.todos = this.todos.filter((todo) => todo.id !== _id)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could have used splice

})
.catch(() => {
this.$toast.error('Error in deleting the todos')
})
},
},
})
</script>
30 changes: 27 additions & 3 deletions pages/login/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<label for="inputUsername">
<input
id="inputUsername"
v-model.trim="username"
type="text"
class="block border border-grey-light w-full p-3 rounded mb-4"
name="inputUsername"
Expand All @@ -15,6 +16,7 @@
<label for="password">
<input
id="inputPassword"
v-model.trim="password"
type="password"
class="block border border-grey-light w-full p-3 rounded mb-4"
name="inputPassword"
Expand Down Expand Up @@ -47,23 +49,45 @@

<script>
import { useContext } from '@nuxtjs/composition-api'
import { defineComponent } from '@vue/composition-api'
import { defineComponent, reactive, toRefs } from '@vue/composition-api'

export default defineComponent({
middleware: 'auth',
setup() {
const { $toast } = useContext()
const { $toast, $axios, store, redirect, route } = useContext()

const state = reactive({
username: '',
password: '',
})
function login() {
$toast.info('Complete Me!')
/***
* @todo Complete this function.
* @todo 1. Write code for form validation.
* @todo 2. Fetch the auth token from backend and login the user.
* @todo 3. Commit token to Vuex Store
* @hints checkout register/index.vue
*/
const data = {
username: state.username,
password: state.password,
}

$axios
.$post('auth/login/', data)
.then(({ token }) => {
store.commit('setToken', token)
// console.log(token)
if (route.path !== '/') redirect('/')
$toast.success('Logged In successfully')
})
.catch(() => {
$toast.error('Invalid Credentials')
})
}

return {
...toRefs(state),
login,
}
},
Expand Down
7 changes: 4 additions & 3 deletions pages/register/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
</main>
</template>

<script lang="ts">
<script>
import {
defineComponent,
reactive,
Expand All @@ -88,6 +88,7 @@ import {
} from '@nuxtjs/composition-api'

export default defineComponent({
middleware: 'auth',
setup() {
const state = reactive({
firstName: '',
Expand All @@ -97,7 +98,7 @@ export default defineComponent({
password: '',
})

const { redirect, $axios, store, $toast } = useContext()
const { $toast, $axios, store, redirect, route } = useContext()

const validateField = () => {
if (
Expand Down Expand Up @@ -133,7 +134,7 @@ export default defineComponent({
.$post('auth/register/', data)
.then(({ token }) => {
store.commit('setToken', token)
redirect('/')
if (route.path !== '/') redirect('/')
})
.catch(() => {
$toast.error(
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"compilerOptions": {
"target": "ES2018",
"module": "ESNext",
"jsx": "react",
"importHelpers": true,
"moduleResolution": "Node",
"lib": [
Expand Down