Commit 7b82a25d authored by Kemm23's avatar Kemm23

Merge branch 'feature/UI-vuetify' of...

Merge branch 'feature/UI-vuetify' of https://gitlab.kiaisoft.com/kiaisoft.anh.tran2/kiaisoft_tuananh_nuxt into feature/UI-vuetify
parents fb0853d5 39666ecf
<!-- eslint-disable vue/multi-word-component-names -->
<template> <template>
<div> <div>
<v-toolbar <v-toolbar
...@@ -10,56 +11,106 @@ ...@@ -10,56 +11,106 @@
<v-toolbar-title> <v-toolbar-title>
<v-btn href="/users"> <v-btn href="/users">
<span>USER</span> <span>USER</span>
<v-icon dense>mdi-account</v-icon> <v-icon dense>
mdi-account
</v-icon>
</v-btn> </v-btn>
<v-btn href="/categories"> <v-btn href="/categories">
<span>CATEGORY</span> <span>CATEGORY</span>
<v-icon dense>mdi-heart</v-icon> <v-icon dense>
mdi-heart
</v-icon>
</v-btn> </v-btn>
<v-btn href="/products"> <v-btn href="/products">
<span>PRODUCT</span> <span>PRODUCT</span>
<v-icon dense> mdi-briefcase</v-icon> <v-icon dense>
mdi-briefcase
</v-icon>
</v-btn> </v-btn>
<v-btn href="/posts"> <v-btn href="/posts">
<span>POST</span> <span>POST</span>
<v-icon dense>mdi-newspaper</v-icon> <v-icon dense>
mdi-newspaper
</v-icon>
</v-btn> </v-btn>
</v-toolbar-title> </v-toolbar-title>
<v-spacer /> <v-spacer />
<v-toolbar-title>{{ $auth.$storage.getUniversal("userName") }}</v-toolbar-title> <v-toolbar-title class="profile">
{{ $auth.$storage.getUniversal("userName") }}
<v-btn icon @click="logout"> </v-toolbar-title>
<v-icon>mdi-export</v-icon> <div class="text-center">
</v-btn> <v-menu offset-y>
<template #activator="{ on, attrs }">
<v-btn
icon
dark
v-bind="attrs"
v-on="on"
>
<v-icon>mdi-menu-down</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item-group
color="primary"
>
<v-list-item
@click="logout()"
>
<v-list-item-icon>
<v-icon>
mdi-logout
</v-icon>
</v-list-item-icon>
<v-list-item-title>
Logout
</v-list-item-title>
</v-list-item>
</v-list-item-group>
</v-list>
</v-menu>
</div>
</v-toolbar> </v-toolbar>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
methods: { methods: {
logout () { async logout () {
fetch('http://127.0.0.1:8000/api/logout', { try {
method: 'POST', const resp = await this.$axios.post('/logout', {
headers: {
'Content-Type': 'application/json',
accept: 'application/json'
},
body: JSON.stringify({
token: this.$auth.$storage.getUniversal('token') token: this.$auth.$storage.getUniversal('token')
}) })
}) if (resp.status === '200') {
localStorage.setItem('token', '') this.$toast.success('Logout!', {
this.$auth.$storage.setUniversal('loggedIn', 'false') duration: 2000
this.$auth.$storage.setUniversal('token', '') })
this.$auth.$storage.setUniversal('userName', '') this.$router.push('/login')
this.$router.push('/login') localStorage.setItem('token', '')
this.$auth.$storage.setUniversal('loggedIn', 'false')
this.$auth.$storage.setUniversal('token', '')
this.$auth.$storage.setUniversal('userName', '')
}
} catch (e) {
this.$toast.error('ERR !', {
duration: 2000
})
}
} }
} }
} }
</script> </script>
<style scoped>
.v-toolbar--prominent:not(.v-toolbar--bottom) .v-toolbar__title.profile {
align-self: baseline;
padding-top: 5px;
}
.v-application--is-ltr .v-list-item__action:first-child, .v-application--is-ltr .v-list-item__icon:first-child {
margin-right: 15px;
}
</style>
export default function(context) { export default function (context) {
console.log('[LOG]: middleware is running ...') console.log('[LOG]: middleware is running ...')
} }
\ No newline at end of file
export default ({ redirect }) => { export default ({ redirect, store }) => {
if (typeof localStorage !== 'undefined' && !localStorage.getItem('token')) { if (typeof localStorage !== 'undefined' && !localStorage.getItem('token')) {
return redirect('/login') return redirect('/login')
} }
......
...@@ -82,6 +82,7 @@ ...@@ -82,6 +82,7 @@
<v-text-field <v-text-field
v-model="eName" v-model="eName"
label="Name" label="Name"
:rules="nameRules"
required required
/> />
</v-col> </v-col>
...@@ -90,6 +91,7 @@ ...@@ -90,6 +91,7 @@
v-model="eOrdering" v-model="eOrdering"
label="Ordering" label="Ordering"
type="number" type="number"
:rules="requiredRules"
required required
/> />
</v-col> </v-col>
...@@ -146,7 +148,7 @@ ...@@ -146,7 +148,7 @@
v-model="dialog1" v-model="dialog1"
persistent persistent
max-width="600px" max-width="600px"
@submit.prevent="createUser" lazy-validation
> >
<template #activator="{ on, attrs }"> <template #activator="{ on, attrs }">
<v-btn <v-btn
...@@ -173,6 +175,8 @@ ...@@ -173,6 +175,8 @@
<v-text-field <v-text-field
v-model="name" v-model="name"
label="Name" label="Name"
:rules="nameRules"
lazy-validation
required required
/> />
</v-col> </v-col>
...@@ -181,6 +185,7 @@ ...@@ -181,6 +185,7 @@
v-model="ordering" v-model="ordering"
label="Ordering" label="Ordering"
type="number" type="number"
:rules="numberRules"
required required
/> />
</v-col> </v-col>
...@@ -191,12 +196,12 @@ ...@@ -191,12 +196,12 @@
item-text="name" item-text="name"
item-value="id" item-value="id"
label="Parent*" label="Parent*"
:rules="requiredRules"
/> />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-file-input <v-file-input
v-model="image" v-model="image"
accept="image/*"
label="Image" label="Image"
prepend-icon="mdi-camera" prepend-icon="mdi-camera"
/> />
...@@ -282,17 +287,20 @@ ...@@ -282,17 +287,20 @@
</v-dialog> </v-dialog>
</v-toolbar> </v-toolbar>
</template> </template>
<template #item.created_at="{ item }"> <template #[`item.index`]="{ index }">
{{ index + 1 }}
</template>
<template #[`item.created_at`]="{ item }">
<span>{{ formatDate(item.created_at) }}</span> <span>{{ formatDate(item.created_at) }}</span>
</template> </template>
<template #item.updated_at="{ item }"> <template #[`item.updated_at`]="{ item }">
<span>{{ formatDate(item.updated_at) }}</span> <span>{{ formatDate(item.updated_at) }}</span>
</template> </template>
<template #item.actions="{ item }"> <template #[`item.actions`]="{ item }">
<v-icon :id="item.id" small @click="dialog2 = true; editCategory(item)"> <v-icon :id="item.id" small @click="dialog2 = true; editCategory(item)">
mdi-pencil mdi-pencil
</v-icon> </v-icon>
<v-icon :id="item.id" small @click="dialogDelete = true;getID(item)"> <v-icon :id="item.id" small @click="dialogDelete = true; getID(item)">
mdi-delete mdi-delete
</v-icon> </v-icon>
<v-icon :id="item.id" small @click="dialog3 = true; showCategory(item)"> <v-icon :id="item.id" small @click="dialog3 = true; showCategory(item)">
...@@ -328,11 +336,12 @@ export default { ...@@ -328,11 +336,12 @@ export default {
options: [], options: [],
headers: [ headers: [
{ {
text: 'Name', text: '#',
align: 'start', align: 'start',
value: 'name', value: 'index',
groupable: false groupable: false
}, },
{ text: 'Name', value: 'name', groupable: false },
{ text: 'Odering', value: 'ordering', groupable: false }, { text: 'Odering', value: 'ordering', groupable: false },
{ text: 'Created', value: 'created_at', groupable: false }, { text: 'Created', value: 'created_at', groupable: false },
{ text: 'Updated', value: 'updated_at', groupable: false }, { text: 'Updated', value: 'updated_at', groupable: false },
...@@ -374,6 +383,17 @@ export default { ...@@ -374,6 +383,17 @@ export default {
disabled: false, disabled: false,
href: '/categories' href: '/categories'
} }
],
nameRules: [
v => !!v || 'Name is required',
v => (v && v.length <= 255) || 'Name must be less than 255 characters'
],
requiredRules: [
v => !!v || 'This field is required'
],
numberRules: [
v => !!v || 'This field is required',
v => v > 0 || 'value must be a positive integer'
] ]
} }
}, },
...@@ -442,13 +462,11 @@ export default { ...@@ -442,13 +462,11 @@ export default {
this.$axios this.$axios
.get('/categories/', { .get('/categories/', {
headers: { headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
}) })
.then((response) => { .then((response) => {
this.categories = response.data.data this.categories = response.data.data
console.log(this.categories)
}) })
.catch(function (error) { .catch(function (error) {
console.log(error) console.log(error)
...@@ -460,13 +478,14 @@ export default { ...@@ -460,13 +478,14 @@ export default {
fd.append('name', this.name) fd.append('name', this.name)
fd.append('ordering', this.ordering) fd.append('ordering', this.ordering)
fd.append('parent_id', this.parent_id) fd.append('parent_id', this.parent_id)
fd.append('image', this.image) if (this.image != null) {
fd.append('image', this.image)
}
this.$axios this.$axios
.post('/categories/', .post('/categories/',
fd, fd,
{ {
headers: { headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
} }
...@@ -485,6 +504,8 @@ export default { ...@@ -485,6 +504,8 @@ export default {
duration: 3000 duration: 3000
}) })
}) })
this.getCategories()
this.clearData()
}, },
deleteCategory () { deleteCategory () {
const self = this const self = this
...@@ -494,7 +515,6 @@ export default { ...@@ -494,7 +515,6 @@ export default {
.delete(`/categories/${this.eID}`, .delete(`/categories/${this.eID}`,
{ {
headers: { headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
}) })
...@@ -519,7 +539,7 @@ export default { ...@@ -519,7 +539,7 @@ export default {
this.eName = item.name this.eName = item.name
this.eOrdering = item.ordering this.eOrdering = item.ordering
this.eParentId = item.parent_id this.eParentId = item.parent_id
this.eImage = item.images this.eImage = item.image
this.editedIndex = this.categories.indexOf(item) this.editedIndex = this.categories.indexOf(item)
console.log(this.eID) console.log(this.eID)
console.log(this.eImage) console.log(this.eImage)
...@@ -528,7 +548,7 @@ export default { ...@@ -528,7 +548,7 @@ export default {
this.eName = item.name this.eName = item.name
this.eOrdering = item.ordering this.eOrdering = item.ordering
this.eParentId = item.parent_id this.eParentId = item.parent_id
this.eImage = item.images this.eImage = item.image
}, },
updateCategory (userID) { updateCategory (userID) {
const self = this const self = this
...@@ -540,7 +560,7 @@ export default { ...@@ -540,7 +560,7 @@ export default {
} }
fd.append('name', this.eName) fd.append('name', this.eName)
fd.append('ordering', this.eOrdering) fd.append('ordering', this.eOrdering)
if (typeof this.eImage !== 'string') { if (typeof this.eImage !== 'string' && this.eImage != null) {
fd.append('image', this.eImage) fd.append('image', this.eImage)
} }
try { try {
...@@ -549,7 +569,6 @@ export default { ...@@ -549,7 +569,6 @@ export default {
fd, fd,
{ {
headers: { headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
} }
...@@ -564,6 +583,13 @@ export default { ...@@ -564,6 +583,13 @@ export default {
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }
},
clearData () {
// eslint-disable-next-line no-unused-expressions, no-sequences
this.parent_id = '',
this.name = '',
this.ordering = '',
this.image = null
} }
} }
} }
...@@ -577,19 +603,19 @@ export default { ...@@ -577,19 +603,19 @@ export default {
padding-left: 30px !important; padding-left: 30px !important;
background-color: rgba(211, 211, 211, 0.133); background-color: rgba(211, 211, 211, 0.133);
} }
.depth-1 > td:first-child { .depth-1 > td:nth-child(2) {
padding-left: 30px !important; padding-left: 30px !important;
} }
.depth-2 > td:first-child { .depth-2 > td:nth-child(2) {
padding-left: 45px !important;
}
.depth-3 > td:first-child {
padding-left: 60px !important; padding-left: 60px !important;
} }
.depth-4 > td:first-child { .depth-3 > td:nth-child(2) {
padding-left: 75px !important;
}
.depth-5 > td:first-child {
padding-left: 90px !important; padding-left: 90px !important;
} }
.depth-4 > td:nth-child(2) {
padding-left: 120px !important;
}
.depth-5 > td:nth-child(2) {
padding-left: 150px !important;
}
</style> </style>
...@@ -126,8 +126,8 @@ export default { ...@@ -126,8 +126,8 @@ export default {
return response.json() return response.json()
}) })
console.log(resp.status) console.log(resp.status)
localStorage.setItem('token', 'Bearer ' + resp.data.bearer_token) localStorage.setItem('token', resp.data.bearer_token)
this.$auth.$storage.setUniversal('token', 'Bearer ' + resp.data.bearer_token) this.$auth.$storage.setUniversal('token', resp.data.bearer_token)
this.$auth.$storage.setUniversal('userName', resp.data.name) this.$auth.$storage.setUniversal('userName', resp.data.name)
this.$auth.$storage.setUniversal('loggedIn', 'true') this.$auth.$storage.setUniversal('loggedIn', 'true')
if (resp.status == 'success') { if (resp.status == 'success') {
......
<!-- eslint-disable vue/valid-v-slot -->
<!-- eslint-disable no-sequences -->
<!-- eslint-disable no-unused-expressions -->
<!-- eslint-disable no-unused-expressions -->
<!-- eslint-disable vue/require-v-for-key --> <!-- eslint-disable vue/require-v-for-key -->
<template> <template>
<div> <div>
...@@ -12,106 +9,7 @@ ...@@ -12,106 +9,7 @@
</template> </template>
</v-breadcrumbs> </v-breadcrumbs>
</div> </div>
<div style="float: right"> <div style="float: right" />
<v-dialog
v-model="dialog1"
persistent
max-width="600px"
enctype="multipart/form-data"
>
<template #activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
>
New Post
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">CREAT POST</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="title"
label="Title*"
required
/>
</v-col>
<v-col
cols="12"
>
<v-select
v-model="category_id"
:items="categories"
item-text="name"
item-value="id"
label="Category"
/>
</v-col>
<v-col cols="12">
<v-text-field
v-model="content"
label="Content"
required
/>
</v-col>
<v-col
cols="12"
>
<v-select
v-model="status"
:items="statusDefaul"
item-text="name"
item-value="id"
label="Status"
/>
</v-col>
<v-col cols="12">
<v-file-input
v-model="images"
label="File input"
small-chips
dense
accept="image/*"
prepend-icon="mdi-camera"
@change="fileSelected"
/>
</v-col>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
color="blue darken-1"
text
@click="dialog1 = false"
>
Close
</v-btn>
<v-btn
color="blue darken-1"
text
type="submit"
@click="dialog1 = false; createPost()"
>
Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
<!-- modal-show --> <!-- modal-show -->
<v-dialog <v-dialog
v-model="dialog2" v-model="dialog2"
...@@ -133,7 +31,7 @@ ...@@ -133,7 +31,7 @@
<v-text-field <v-text-field
v-model="sTitle" v-model="sTitle"
label="Title" label="Title"
disabled readonly
/> />
</v-col> </v-col>
<v-col <v-col
...@@ -145,14 +43,15 @@ ...@@ -145,14 +43,15 @@
item-text="name" item-text="name"
item-value="id" item-value="id"
label="Category" label="Category"
disabled readonly
/> />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field <v-textarea
v-model="sContent" v-model="sContent"
label="Content" label="Content"
disabled word-break="break-word"
readonly
/> />
</v-col> </v-col>
<v-col <v-col
...@@ -163,14 +62,17 @@ ...@@ -163,14 +62,17 @@
:items="statusDefaul" :items="statusDefaul"
item-text="name" item-text="name"
item-value="id" item-value="id"
label="Category" label="Status"
disabled readonly
/> />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-col v-for="(image, index) in sImages" :key="index" cols="12"> <!-- <v-col v-for="(image, index) in sImages" :key="index" cols="12">
<v-img :src="image" contain /> <v-img :src="image"/> </v-col> -->
</v-col> <v-img
v-if="typeof sImages == 'string'"
:src="sImages"
/>
</v-col> </v-col>
</v-row> </v-row>
</v-container> </v-container>
...@@ -185,14 +87,6 @@ ...@@ -185,14 +87,6 @@
> >
Close Close
</v-btn> </v-btn>
<v-btn
color="blue darken-1"
text
type="submit"
@click="dialog2 = false;"
>
Save
</v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>
...@@ -201,6 +95,7 @@ ...@@ -201,6 +95,7 @@
v-model="dialog" v-model="dialog"
persistent persistent
max-width="600px" max-width="600px"
lazy-validation
> >
<v-card> <v-card>
<v-card-title> <v-card-title>
...@@ -217,6 +112,7 @@ ...@@ -217,6 +112,7 @@
<v-text-field <v-text-field
v-model="eTitle" v-model="eTitle"
label="Title*" label="Title*"
:rules="requiredRules"
required required
/> />
</v-col> </v-col>
...@@ -229,13 +125,15 @@ ...@@ -229,13 +125,15 @@
item-text="name" item-text="name"
item-value="id" item-value="id"
label="Category" label="Category"
:rules="requiredRules"
/> />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field <v-textarea
v-model="eContent" v-model="eContent"
label="Content" label="Content"
required required
:rules="requiredRules"
/> />
</v-col> </v-col>
<v-col <v-col
...@@ -246,7 +144,8 @@ ...@@ -246,7 +144,8 @@
:items="statusDefaul" :items="statusDefaul"
item-text="name" item-text="name"
item-value="id" item-value="id"
label="Category" label="Status"
:rules="requiredRules"
/> />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
...@@ -283,155 +182,24 @@ ...@@ -283,155 +182,24 @@
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>
<!-- <div style="float: right"> <!-- modal-delete -->
<b-button class="text-white" v-b-modal.modal-create>New Post</b-button> <v-dialog v-model="dialogDelete" max-width="500px">
</div> <v-card>
<b-modal id="modal-create" title="create Post" class="modal fade"> <v-card-title class="text-h5">
<div class="w-full mt-4 p-10"> Are you sure you want to delete this item?
<form> </v-card-title>
<label for="input-live">Title :</label> <v-card-actions>
<b-form-input <v-spacer />
id="input-live" <v-btn color="blue darken-1" text @click="closeDelete">
v-model="title" Cancel
type="text" </v-btn>
class="form-control mb-2" <v-btn color="blue darken-1" text @click="deletePost(); dialogDelete = false">
placeholder="name" OK
aria-describedby="input-live-help input-live-feedback" </v-btn>
max="255" <v-spacer />
min="1" </v-card-actions>
trim </v-card>
/> </v-dialog>
<label>Category ID :</label>
<b-form-select v-model="category_id">
<option v-for="item in categories" :value="item.id">
{{ item.name }}
</option>
</b-form-select>
<label>Content :</label>
<input
v-model="content"
type="text"
class="form-control mb-2"
placeholder="Ordering"
size="sm"
required
>
<label>Author :</label>
<input
v-model="user_id"
type="text"
class="form-control mb-2"
placeholder="Description"
size="sm"
required
>
<label>Status :</label>
<b-form-select v-model="status" :options="options" />
<label>Image :</label>
<b-form-file
v-model="images"
multiple
:state="Boolean(images)"
placeholder="Choose a image or drop it here..."
drop-placeholder="Drop file here..."
/>
</form>
</div>
<template #modal-footer>
<button v-b-modal.modal-close_visit class="btn btn-danger btn-sm m-1" @click="$bvModal.hide('modal-create')">
Close
</button>
<button v-b-modal.modal-close_visit class="btn btn-success btn-sm m-1" @click="createPost()">
Submit
</button>
</template>
</b-modal> -->
<!-- modal-show -->
<!-- <b-modal id="modal-show" title="POST" class="modal fade">
<div class="w-full mt-4 p-10">
<form>
<label>Title :</label>
<input v-model="sTitle" type="text" class="form-control mb-2" size="sm" disabled>
<label>Category ID :</label>
<input v-model="sCategoryId" type="text" class="form-control mb-2" size="sm" disabled>
<label>Content :</label>
<input v-model="sContent" type="text" class="form-control mb-2" size="sm" disabled>
<label>Author :</label>
<input
v-model="sUserId"
type="text"
class="form-control mb-2"
placeholder="Description"
size="sm"
disabled
>
<label>Status :</label>
<b-form-select v-model="sStatus" :options="options" disabled />
<label>Image :</label>
<div v-for="(image, index) in sImages" :key="index">
<b-img :src="image" fluid alt="Fluid image" />
</div>
</form>
</div>
<template #modal-footer>
<button v-b-modal.modal-close_visit class="btn btn-danger btn-sm m-1" @click="$bvModal.hide('modal-show')">
Close
</button>
</template>
</b-modal> -->
<!-- modal-edit -->
<!-- <b-modal id="modal-edit" title="Edit Post " class="modal fade">
<div class="w-full mt-4 p-10">
<form>
<label>Title :</label>
<input
v-model="eTitle"
type="text"
class="form-control mb-2"
placeholder="name"
max="255"
min="1"
size="sm"
required
>
<label>Category ID :</label>
<b-form-select v-model="eCategoryId">
<option v-for="item in categories" :value="item.id">
{{ item.name }}
</option>
</b-form-select>
<label>Content :</label>
<input
v-model="eContent"
type="text"
class="form-control mb-2"
placeholder="Ordering"
size="sm"
required
>
<label>Author :</label>
<input v-model="eUserId" type="text" class="form-control mb-2" placeholder="Description" size="sm">
<label>Status :</label>
<b-form-select v-model="eStatus" :options="options" />
<label>Image :</label>
<b-form-file
v-model="eImages"
multiple
:state="Boolean(eImages)"
placeholder="Choose a image or drop it here..."
drop-placeholder="Drop file here..."
/>
</form>
</div>
<template #modal-footer>
<button v-b-modal.modal-close_visit class="btn btn-danger btn-sm m-1" @click="$bvModal.hide('modal-edit')">
Close
</button>
<button v-b-modal.modal-close_visit class="btn btn-success btn-sm m-1" @click="updatePost()">
Submit
</button>
</template>
</b-modal> -->
<!-- table --> <!-- table -->
<div> <div>
<v-data-table :headers="headers" :items="posts" sort-by="calories" class="elevation-1"> <v-data-table :headers="headers" :items="posts" sort-by="calories" class="elevation-1">
...@@ -440,13 +208,132 @@ ...@@ -440,13 +208,132 @@
<v-toolbar-title>Post Manage</v-toolbar-title> <v-toolbar-title>Post Manage</v-toolbar-title>
<v-divider class="mx-4" inset vertical /> <v-divider class="mx-4" inset vertical />
<v-spacer /> <v-spacer />
<v-toolbar-title>
<!-- modal-create -->
<v-dialog
v-model="dialog1"
persistent
max-width="600px"
enctype="multipart/form-data"
lazy-validation
>
<template #activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
>
New Post
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">CREAT POST</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="title"
label="Title*"
:rules="requiredRules"
required
/>
</v-col>
<v-col
cols="12"
>
<v-select
v-model="category_id"
:items="categories"
item-text="name"
item-value="id"
label="Category"
:rules="requiredRules"
/>
</v-col>
<v-col cols="12">
<v-textarea
v-model="content"
label="Content"
:rules="requiredRules"
required
/>
</v-col>
<v-col
cols="12"
>
<v-select
v-model="status"
:items="statusDefaul"
item-text="name"
item-value="id"
label="Status"
:rules="requiredRules"
/>
</v-col>
<v-col cols="12">
<v-file-input
v-model="images"
label="File input"
small-chips
dense
accept="image/*"
prepend-icon="mdi-camera"
:rules="requiredRules"
@change="fileSelected"
/>
</v-col>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
color="blue darken-1"
text
@click="dialog1 = false"
>
Close
</v-btn>
<v-btn
color="blue darken-1"
text
type="submit"
@click="dialog1 = false; createPost()"
>
Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar-title>
</v-toolbar> </v-toolbar>
</template> </template>
<template #[`item.index`]="{ index }">
{{ index + 1 }}
</template>
<template #[`item.category_id`]="{ item }">
{{ categories.find(x => x.id === item.category_id)?.name }}
</template>
<template #[`item.status`]="{ item }">
{{ statusDefaul.find(x => x.id == item.status)?.name }}
</template>
<template #[`item.user_id`]="{ item }">
{{ users.find(x => x.id === item.user_id)?.name }}
</template>
<template #[`item.actions`]="{ item }"> <template #[`item.actions`]="{ item }">
<v-icon :id="item.id" small @click="editPost(item)"> <v-icon :id="item.id" small @click="editPost(item)">
mdi-pencil mdi-pencil
</v-icon> </v-icon>
<v-icon :id="item.id" small @click="deletePost(item.id, item)"> <v-icon :id="item.id" small @click="dialogDelete = true; getID(item)">
mdi-delete mdi-delete
</v-icon> </v-icon>
<v-icon :id="item.id" small @click="showPost(item)"> <v-icon :id="item.id" small @click="showPost(item)">
...@@ -484,15 +371,14 @@ export default { ...@@ -484,15 +371,14 @@ export default {
dialogDelete: false, dialogDelete: false,
headers: [ headers: [
{ {
text: 'Title', text: '#',
align: 'start', align: 'start',
sortable: false, value: 'index'
value: 'title'
}, },
{ text: 'Category ID', value: 'category_id' }, { text: 'Title', value: 'title' },
{ text: 'content', value: 'content', sortable: false }, { text: 'Category', value: 'category_id' },
{ text: 'author', value: 'user_id' }, { text: 'Author', value: 'user_id' },
{ text: 'status', value: 'status' }, { text: 'Status', value: 'status' },
{ text: 'Actions', value: 'actions', sortable: false } { text: 'Actions', value: 'actions', sortable: false }
], ],
items: [ items: [
...@@ -518,18 +404,19 @@ export default { ...@@ -518,18 +404,19 @@ export default {
id: '2' id: '2'
}, },
{ {
name: 'UnPublish', name: 'Unpublish',
id: '3' id: '3'
} }
], ],
posts: [], posts: [],
categories: [], categories: [],
users: [],
sTitle: '', sTitle: '',
sCategoryId: '', sCategoryId: '',
sContent: '', sContent: '',
sUserId: '', sUserId: '',
sStatus: null, sStatus: [],
sImages: null, sImages: [],
eId: '', eId: '',
eTitle: '', eTitle: '',
eCategoryId: [], eCategoryId: [],
...@@ -553,7 +440,18 @@ export default { ...@@ -553,7 +440,18 @@ export default {
status: '', status: '',
created_at: '', created_at: '',
updated_at: '' updated_at: ''
} },
requiredRules: [
v => !!v || 'This field is required'
],
numberRules: [
v => !!v || 'This field is required',
v => v > 0 || 'value must be a positive integer'
],
imageRules: [
v => !!v || 'Images is required',
v => (v && v.length > 0) || 'Images is required'
]
} }
}, },
computed: { computed: {
...@@ -574,8 +472,9 @@ export default { ...@@ -574,8 +472,9 @@ export default {
}, },
created () { created () {
this.initialize() this.initialize()
this.getposts() this.getPosts()
this.getCategories() this.getCategories()
this.getUsers()
}, },
methods: { methods: {
initialize () { initialize () {
...@@ -586,8 +485,8 @@ export default { ...@@ -586,8 +485,8 @@ export default {
this.sCategoryId = '' this.sCategoryId = ''
this.sContent = '' this.sContent = ''
this.sUserId = '' this.sUserId = ''
this.sStatus = '' this.sStatus = []
this.sImages = null this.sImages = []
}, },
editItem (item) { editItem (item) {
this.editedIndex = this.posts.indexOf(item) this.editedIndex = this.posts.indexOf(item)
...@@ -625,11 +524,22 @@ export default { ...@@ -625,11 +524,22 @@ export default {
} }
this.close() this.close()
}, },
getUsers () {
this.$axios
.get('/users/', {
headers: {
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
}
})
.then(response => (this.users = response.data.data.data))
.catch(function (error) {
console.log(error)
})
},
getCategories () { getCategories () {
this.$axios this.$axios
.get('/categories/', { .get('/categories/', {
headers: { headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
}) })
...@@ -638,11 +548,10 @@ export default { ...@@ -638,11 +548,10 @@ export default {
console.log(error) console.log(error)
}) })
}, },
getposts () { getPosts () {
this.$axios this.$axios
.get('/posts/', { .get('/posts/', {
headers: { headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
}) })
...@@ -664,7 +573,6 @@ export default { ...@@ -664,7 +573,6 @@ export default {
fd, fd,
{ {
headers: { headers: {
'Content-Type': 'multipart/form-data; application/json',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
} }
...@@ -683,42 +591,40 @@ export default { ...@@ -683,42 +591,40 @@ export default {
}) })
}) })
}, },
deletePost (ID, index) { getID (item) {
this.eID = item.id
this.editedIndex = this.categories.indexOf(item)
},
deletePost () {
const self = this const self = this
this.editedIndex = this.posts.indexOf(index) const currentPostIndex = this.editedIndex
if (confirm('Do you really want to delete?')) { this.$axios
this.$axios .delete(`/posts/${this.eID}`, {
.delete(`/posts/${ID}`, { headers: {
headers: { Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
'Content-Type': 'application/json', }
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` })
} .then((response) => {
}) this.posts.splice(currentPostIndex, 1)
.then((response) => { self.$toast.success('Post deleted successfully!', {
this.posts.splice(this.editedIndex, 1) duration: 3000
self.$toast.success('Post deleted successfully!', {
duration: 3000
})
}) })
.catch((error) => { })
console.log(error) .catch((error) => {
self.$toast.error('Error!', { console.log(error)
duration: 3000 self.$toast.error('Error!', {
}) duration: 3000
}) })
} })
}, },
async showPost (item) { async showPost (item) {
const ID = item.id const ID = item.id
try { try {
const resp = await this.$axios.get(`/posts/${ID}`, { const resp = await this.$axios.get(`/posts/${ID}`, {
method: 'GET',
headers: { headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
}) })
console.log(resp.data)
this.sTitle = resp.data.data.title this.sTitle = resp.data.data.title
this.sContent = resp.data.data.content this.sContent = resp.data.data.content
this.sCategoryId = resp.data.data.category_id this.sCategoryId = resp.data.data.category_id
...@@ -735,6 +641,7 @@ export default { ...@@ -735,6 +641,7 @@ export default {
this.eCategoryId = item.category_id this.eCategoryId = item.category_id
this.eContent = item.content this.eContent = item.content
this.eStatus = item.status this.eStatus = item.status
this.eImages = []
this.editedIndex = this.posts.indexOf(item) this.editedIndex = this.posts.indexOf(item)
console.log(this.editedIndex) console.log(this.editedIndex)
this.dialog = true this.dialog = true
...@@ -745,9 +652,10 @@ export default { ...@@ -745,9 +652,10 @@ export default {
fd.append('title', this.eTitle) fd.append('title', this.eTitle)
fd.append('category_id', this.eCategoryId) fd.append('category_id', this.eCategoryId)
fd.append('content', this.eContent) fd.append('content', this.eContent)
fd.append('images', this.eImages)
fd.append('status', this.eStatus) fd.append('status', this.eStatus)
if (typeof this.eImages !== 'string' && this.eImages != null) {
fd.append('images', this.eImages)
}
const currentPostIndex = this.editedIndex const currentPostIndex = this.editedIndex
this.$axios this.$axios
.post( .post(
...@@ -755,9 +663,7 @@ export default { ...@@ -755,9 +663,7 @@ export default {
fd, fd,
{ {
headers: { headers: {
'Content-Type': 'multipart/form-data', Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`,
Accept: 'application/json, text/plain, */*'
} }
} }
) )
......
<!-- eslint-disable vue/require-v-for-key -->
<!-- eslint-disable vue/valid-v-slot -->
<template> <template>
<div> <div>
<div> <div>
...@@ -9,162 +7,6 @@ ...@@ -9,162 +7,6 @@
</template> </template>
</v-breadcrumbs> </v-breadcrumbs>
</div> </div>
<div style="float: right">
<v-dialog
v-model="dialog1"
persistent
max-width="600px"
>
<template #activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
>
New Product
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">CREAT PRODUCT</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="name"
label="Name*"
required
/>
</v-col>
<v-col
cols="12"
>
<v-select
v-model="category_id"
:items="categories"
item-text="name"
item-value="id"
label="Category"
/>
</v-col>
<v-col cols="12">
<v-text-field
v-model="price"
label="Price*"
required
/>
</v-col>
<v-col cols="12">
<v-text-field
v-model="description"
label="Description"
/>
</v-col>
<v-col cols="12">
<v-file-input
v-model="images"
label="File input"
small-chips
dense
multiple
/>
</v-col>
<v-col cols="12">
<v-btn
class="mx-2"
fab
dark
small
color="indigo"
@click="addMore()"
>
<v-icon dark>
mdi-plus
</v-icon>
</v-btn>
</v-col>
<v-row v-for="(variant, index) in variants" :key=" 'B' +index">
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="variant.color"
label="Color*"
required
/>
</v-col>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="variant.size"
label="Size*"
required
/>
</v-col>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="variant.quantity"
label="Quantity*"
required
/>
</v-col>
<v-col>
<v-btn
v-show="index != 0"
class=""
fab
dark
x-small
color="red"
@click="remove(index)"
>
<v-icon dark>
mdi-minus
</v-icon>
</v-btn>
</v-col>
</v-row>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
color="blue darken-1"
text
@click="dialog1 = false; seeVariant()"
>
Close
</v-btn>
<v-btn
color="blue darken-1"
text
type="submit"
@click="dialog1 = false; createProduct();"
>
Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
<!-- show-modal --> <!-- show-modal -->
<v-dialog <v-dialog
v-model="dialog2" v-model="dialog2"
...@@ -186,7 +28,7 @@ ...@@ -186,7 +28,7 @@
<v-text-field <v-text-field
v-model="sName" v-model="sName"
label="Name" label="Name"
disabled readonly
/> />
</v-col> </v-col>
<v-col <v-col
...@@ -198,20 +40,21 @@ ...@@ -198,20 +40,21 @@
item-text="name" item-text="name"
item-value="id" item-value="id"
label="Category" label="Category"
disabled readonly
/> />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field <v-text-field
v-model="sPrice" v-model="sPrice"
label="Price" label="Price"
disabled readonly
/> />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field <v-text-field
v-model="sDescription" v-model="sDescription"
label="Description" label="Description"
readonly
/> />
</v-col> </v-col>
<v-col v-for="(image, index) in sImages" :key="index" cols="12"> <v-col v-for="(image, index) in sImages" :key="index" cols="12">
...@@ -227,7 +70,7 @@ ...@@ -227,7 +70,7 @@
<v-text-field <v-text-field
v-model="variant.color" v-model="variant.color"
label="Color" label="Color"
disabled readonly
/> />
</v-col> </v-col>
<v-col <v-col
...@@ -238,7 +81,7 @@ ...@@ -238,7 +81,7 @@
<v-text-field <v-text-field
v-model="variant.size" v-model="variant.size"
label="Size" label="Size"
disabled readonly
/> />
</v-col> </v-col>
<v-col <v-col
...@@ -249,7 +92,7 @@ ...@@ -249,7 +92,7 @@
<v-text-field <v-text-field
v-model="variant.quantity" v-model="variant.quantity"
label="Quantity" label="Quantity"
disabled readonly
/> />
</v-col> </v-col>
<v-col /> <v-col />
...@@ -291,6 +134,7 @@ ...@@ -291,6 +134,7 @@
<v-text-field <v-text-field
v-model="eName" v-model="eName"
label="Name*" label="Name*"
:rules="requiredRules"
required required
/> />
</v-col> </v-col>
...@@ -303,12 +147,14 @@ ...@@ -303,12 +147,14 @@
item-text="name" item-text="name"
item-value="id" item-value="id"
label="Category" label="Category"
:rules="requiredRules"
/> />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field <v-text-field
v-model="ePrice" v-model="ePrice"
label="Price*" label="Price*"
:rules="requiredRules"
required required
/> />
</v-col> </v-col>
...@@ -316,6 +162,7 @@ ...@@ -316,6 +162,7 @@
<v-text-field <v-text-field
v-model="eDescription" v-model="eDescription"
label="Description" label="Description"
:rules="requiredRules"
/> />
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
...@@ -327,7 +174,7 @@ ...@@ -327,7 +174,7 @@
multiple multiple
/> />
</v-col> </v-col>
<!-- <v-img v-if="typeof eImage === 'string'" :src="eImages" /> --> <v-img v-if="typeof eImages === 'string'" :src="eImages" />
<v-col cols="12"> <v-col cols="12">
<v-btn <v-btn
class="mx-2" class="mx-2"
...@@ -351,6 +198,7 @@ ...@@ -351,6 +198,7 @@
<v-text-field <v-text-field
v-model="variant.color" v-model="variant.color"
label="Color*" label="Color*"
:rules="requiredRules"
required required
/> />
</v-col> </v-col>
...@@ -362,6 +210,7 @@ ...@@ -362,6 +210,7 @@
<v-text-field <v-text-field
v-model="variant.size" v-model="variant.size"
label="Size*" label="Size*"
:rules="requiredRules"
required required
/> />
</v-col> </v-col>
...@@ -373,6 +222,7 @@ ...@@ -373,6 +222,7 @@
<v-text-field <v-text-field
v-model="variant.quantity" v-model="variant.quantity"
label="Quantity*" label="Quantity*"
:rules="numberRules"
required required
/> />
</v-col> </v-col>
...@@ -384,7 +234,7 @@ ...@@ -384,7 +234,7 @@
dark dark
x-small x-small
color="red" color="red"
@click="removeVariant(index)" @click="getVariant(index, variant); dialogDeleteVariant = true"
> >
<v-icon dark> <v-icon dark>
mdi-minus mdi-minus
...@@ -416,6 +266,41 @@ ...@@ -416,6 +266,41 @@
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>
<!-- delete-modal -->
<v-dialog v-model="dialogDelete" max-width="500px">
<v-card>
<v-card-title class="text-h5">
Are you sure you want to delete this item?
</v-card-title>
<v-card-actions>
<v-spacer />
<v-btn color="blue darken-1" text @click="closeDelete">
Cancel
</v-btn>
<v-btn color="blue darken-1" text @click="deleteProduct(); dialogDelete = false">
OK
</v-btn>
<v-spacer />
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogDeleteVariant" max-width="500px">
<v-card>
<v-card-title class="text-h5">
Are you sure you want to delete this item?
</v-card-title>
<v-card-actions>
<v-spacer />
<v-btn color="blue darken-1" text @click="closeDelete">
Cancel
</v-btn>
<v-btn color="blue darken-1" text @click="removeVariant(); dialogDeleteVariant=false">
OK
</v-btn>
<v-spacer />
</v-card-actions>
</v-card>
</v-dialog>
<!-- table --> <!-- table -->
<div> <div>
<v-data-table <v-data-table
...@@ -429,13 +314,184 @@ ...@@ -429,13 +314,184 @@
<v-toolbar-title>Product Manage</v-toolbar-title> <v-toolbar-title>Product Manage</v-toolbar-title>
<v-divider class="mx-4" inset vertical /> <v-divider class="mx-4" inset vertical />
<v-spacer /> <v-spacer />
<v-toolbar-title>
<v-dialog
v-model="dialog1"
persistent
max-width="600px"
lazy-validation
>
<template #activator="{ on, attrs }">
<v-btn
color="primary"
dark
v-bind="attrs"
v-on="on"
>
New Product
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">CREAT PRODUCT</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="name"
label="Name*"
:rules="requiredRules"
required
lazy-validation
/>
</v-col>
<v-col
cols="12"
>
<v-select
v-model="category_id"
:items="categories"
item-text="name"
item-value="id"
label="Category"
:rules="requiredRules"
/>
</v-col>
<v-col cols="12">
<v-text-field
v-model="price"
label="Price*"
:rules="requiredRules"
required
/>
</v-col>
<v-col cols="12">
<v-text-field
v-model="description"
label="Description"
:rules="requiredRules"
/>
</v-col>
<v-col cols="12">
<v-file-input
v-model="images"
label="File input"
small-chips
dense
multiple
:rules="imageRules"
lazy-validation
prepend-icon="mdi-camera"
/>
</v-col>
<v-col cols="12">
<v-btn
class="mx-2"
fab
dark
small
color="indigo"
@click="addMore()"
>
<v-icon dark>
mdi-plus
</v-icon>
</v-btn>
</v-col>
<v-row v-for="(variant, index) in variants" :key=" 'B' +index">
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="variant.color"
label="Color*"
:rules="requiredRules"
required
/>
</v-col>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="variant.size"
label="Size*"
:rules="requiredRules"
required
/>
</v-col>
<v-col
cols="12"
sm="6"
md="4"
>
<v-text-field
v-model="variant.quantity"
label="Quantity*"
:rules="numberRules"
required
/>
</v-col>
<v-col>
<v-btn
v-show="index != 0"
class=""
fab
dark
x-small
color="red"
@click="remove(index)"
>
<v-icon dark>
mdi-minus
</v-icon>
</v-btn>
</v-col>
</v-row>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
color="blue darken-1"
text
@click="dialog1 = false"
>
Close
</v-btn>
<v-btn
color="blue darken-1"
text
type="submit"
@click="dialog1 = false; createProduct();"
>
Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar-title>
</v-toolbar> </v-toolbar>
</template> </template>
<template #[`item.index`]="{ index }">
{{ index + 1 }}
</template>
<template #[`item.actions`]="{ item }"> <template #[`item.actions`]="{ item }">
<v-icon :id="item.id" small @click="editProduct(item)"> <v-icon :id="item.id" small @click="editProduct(item)">
mdi-pencil mdi-pencil
</v-icon> </v-icon>
<v-icon :id="item.id" small @click="deleteProduct(item.id,item)"> <v-icon :id="item.id" small @click="dialogDelete = true; getID(item)">
mdi-delete mdi-delete
</v-icon> </v-icon>
<v-icon :id="item.id" small @click="showProduct(item)"> <v-icon :id="item.id" small @click="showProduct(item)">
...@@ -460,7 +516,7 @@ export default { ...@@ -460,7 +516,7 @@ export default {
return { return {
name: '', name: '',
id: '', id: '',
category_id: null, category_id: '',
price: '', price: '',
stock: '', stock: '',
description: '', description: '',
...@@ -480,19 +536,19 @@ export default { ...@@ -480,19 +536,19 @@ export default {
dialog2: false, dialog2: false,
dialog3: false, dialog3: false,
dialogDelete: false, dialogDelete: false,
dialogDeleteVariant: false,
options: [], options: [],
headers: [ headers: [
{ {
text: 'Name', text: '#',
align: 'start', align: 'start',
sortable: false, sortable: false,
value: 'name' value: 'index'
}, },
{ text: 'id', value: 'id' }, { text: 'Name', value: 'name' },
{ text: 'category ID', value: 'category_id' }, { text: 'Category', value: 'category.name' },
{ text: 'price', value: 'price', sortable: false }, { text: 'Price', value: 'price' },
{ text: 'description', value: 'description' }, { text: 'Stock', value: 'stock' },
{ text: 'stock', value: 'stock' },
{ text: 'Actions', value: 'actions', sortable: false } { text: 'Actions', value: 'actions', sortable: false }
], ],
items: [ items: [
...@@ -517,7 +573,7 @@ export default { ...@@ -517,7 +573,7 @@ export default {
sPrice: '', sPrice: '',
sDescription: '', sDescription: '',
sStock: '', sStock: '',
sImages: null, sImages: [],
sVariants: [ sVariants: [
{ {
color: '', color: '',
...@@ -525,6 +581,8 @@ export default { ...@@ -525,6 +581,8 @@ export default {
quantity: '' quantity: ''
} }
], ],
idVariant: '',
editedVariantIndex: '',
eId: '', eId: '',
eName: '', eName: '',
eCategoryId: '', eCategoryId: '',
...@@ -555,7 +613,18 @@ export default { ...@@ -555,7 +613,18 @@ export default {
status: '', status: '',
created_at: '', created_at: '',
updated_at: '' updated_at: ''
} },
requiredRules: [
v => !!v || 'This field is required'
],
numberRules: [
v => !!v || 'This field is required',
v => v > 0 || 'value must be a positive integer'
],
imageRules: [
v => !!v || 'Images is required',
v => (v && v.length > 0) || 'Images is required'
]
} }
}, },
computed: { computed: {
...@@ -584,7 +653,7 @@ export default { ...@@ -584,7 +653,7 @@ export default {
this.images = [] this.images = []
this.products = [] this.products = []
this.product = [] this.product = []
this.categories = [] this.categories = ''
this.sName = '' this.sName = ''
this.sCategoryId = '' this.sCategoryId = ''
this.sPrice = '' this.sPrice = ''
...@@ -596,7 +665,6 @@ export default { ...@@ -596,7 +665,6 @@ export default {
color: '', color: '',
size: '', size: '',
quantity: '' quantity: ''
} }
] ]
}, },
...@@ -640,7 +708,6 @@ export default { ...@@ -640,7 +708,6 @@ export default {
this.$axios this.$axios
.get('/categories/', { .get('/categories/', {
headers: { headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
}) })
...@@ -653,7 +720,6 @@ export default { ...@@ -653,7 +720,6 @@ export default {
this.$axios this.$axios
.get('/products/', { .get('/products/', {
headers: { headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
}) })
...@@ -683,9 +749,7 @@ export default { ...@@ -683,9 +749,7 @@ export default {
, ,
{ {
headers: { headers: {
'Content-Type': 'multipart/form-data ', Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`,
Accept: 'application/json; multipart/form-data'
} }
}) })
.then((response) => { .then((response) => {
...@@ -704,27 +768,28 @@ export default { ...@@ -704,27 +768,28 @@ export default {
}) })
}) })
}, },
deleteProduct (ID, index) { getID (item) {
this.eID = item.id
this.editedIndex = this.products.indexOf(item)
},
deleteProduct () {
const self = this const self = this
this.editedIndex = this.products.indexOf(index) const currentPostIndex = this.editedIndex
if (confirm('Do you really want to delete?')) { try {
try { this.$axios
this.$axios .delete(`/products/${this.eID}`, {
.delete(`/products/${ID}`, { headers: {
headers: { Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
'Content-Type': 'application/json', }
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` })
} .then((response) => {
}) this.products.splice(currentPostIndex, 1)
.then((response) => { self.$toast.success('Category deleted successfully!', {
this.products.splice(this.editedIndex, 1) duration: 3000
self.$toast.success('Category deleted successfully!', {
duration: 3000
})
}) })
} catch (error) { })
console.log(error) } catch (error) {
} console.log(error)
} }
}, },
async showProduct (item) { async showProduct (item) {
...@@ -733,7 +798,6 @@ export default { ...@@ -733,7 +798,6 @@ export default {
const resp = await this.$axios.get(`/products/${ID}`, { const resp = await this.$axios.get(`/products/${ID}`, {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
}) })
...@@ -768,16 +832,18 @@ export default { ...@@ -768,16 +832,18 @@ export default {
fd.append('price', this.ePrice) fd.append('price', this.ePrice)
fd.append('category_id', this.eCategoryId) fd.append('category_id', this.eCategoryId)
fd.append('description', this.eDescription) fd.append('description', this.eDescription)
if (this.eVariants) { for (let i = 0; i < this.eVariants.length; i++) {
for (let i = 0; i < this.eVariants.length; i++) { if (typeof this.eVariants[i].id !== 'undefined') {
fd.append(`variants[${i}][id]`, this.eVariants[i].id) fd.append(`variants[${i}][id]`, this.eVariants[i].id)
fd.append(`variants[${i}][color]`, this.eVariants[i].color)
fd.append(`variants[${i}][quantity]`, this.eVariants[i].quantity)
fd.append(`variants[${i}][size]`, this.eVariants[i].size)
} }
fd.append(`variants[${i}][color]`, this.eVariants[i].color)
fd.append(`variants[${i}][quantity]`, this.eVariants[i].quantity)
fd.append(`variants[${i}][size]`, this.eVariants[i].size)
} }
for (let j = 0; j < this.eImages.length; j++) { if (this.eImages) {
fd.append(`images[${j}]`, this.eImages[j]) for (let j = 0; j < this.eImages.length; j++) {
fd.append(`images[${j}]`, this.eImages[j])
}
} }
const currentPostIndex = this.editedIndex const currentPostIndex = this.editedIndex
try { try {
...@@ -785,7 +851,6 @@ export default { ...@@ -785,7 +851,6 @@ export default {
.post(`/products/update/${this?.eId}`, .post(`/products/update/${this?.eId}`,
fd, { fd, {
headers: { headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
} }
} }
...@@ -819,11 +884,32 @@ export default { ...@@ -819,11 +884,32 @@ export default {
remove (index) { remove (index) {
this.variants.splice(index, 1) this.variants.splice(index, 1)
}, },
removeVariant (index) { getVariant (index, item) {
this.eVariants.splice(index, 1) this.editedVariantIndex = index
this.idVariant = item.id
}, },
seeVariant () { removeVariant () {
console.log(this.variants) const self = this
const currentVariantIndex = this.editedVariantIndex
if (this.idVariant !== null) {
try {
this.$axios.delete(`/products/delete-variant/${this.idVariant}`,
{
headers: {
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
}
}
).then((response) => {
self.$toast.success('Remove variant successfully!', {
duration: 3000
})
})
this.getProducts()
} catch (error) {
console.log(error)
}
this.eVariants.splice(currentVariantIndex, 1)
}
} }
} }
} }
......
...@@ -11,11 +11,7 @@ ...@@ -11,11 +11,7 @@
</v-breadcrumbs> </v-breadcrumbs>
</div> </div>
<!-- modal-create --> <!-- modal-create -->
<v-dialog <v-dialog v-model="dialog2" persistent max-width="600px" lazy-validation>
v-model="dialog2"
persistent
max-width="600px"
>
<v-card> <v-card>
<v-card-title> <v-card-title>
<span class="text-h5">User Edit</span> <span class="text-h5">User Edit</span>
...@@ -23,29 +19,18 @@ ...@@ -23,29 +19,18 @@
<v-card-text> <v-card-text>
<v-container> <v-container>
<v-row> <v-row>
<v-col <v-col cols="12" sm="6" md="4">
cols="12" <v-text-field v-model="eName" label="Legal name*" :rules="nameRules" required />
sm="6"
md="4"
>
<v-text-field
v-model="eName"
label="Legal name*"
required
/>
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field <v-text-field v-model="eEmail" label="Email*" :rules="emailRules" required />
v-model="eEmail"
label="Email*"
required
/>
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
<v-text-field <v-text-field
v-model="ePassword" v-model="ePassword"
label="Password*" label="Password*"
type="password" type="password"
:rules="passwordRules"
required required
/> />
</v-col> </v-col>
...@@ -55,39 +40,69 @@ ...@@ -55,39 +40,69 @@
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-spacer /> <v-spacer />
<v-btn color="blue darken-1" text @click="dialog2 = false">
Close
</v-btn>
<v-btn <v-btn
color="blue darken-1" color="blue darken-1"
text text
@click="dialog2 = false" type="submit"
@click="
dialog2 = false;
updateUser();
"
> >
Close Save
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<!-- modal-delete -->
<v-dialog v-model="dialogDelete" max-width="500px">
<v-card>
<v-card-title class="text-h5">
Are you sure you want to delete this item?
</v-card-title>
<v-card-actions>
<v-spacer />
<v-btn color="blue darken-1" text @click="closeDelete">
Cancel
</v-btn> </v-btn>
<v-btn <v-btn
color="blue darken-1" color="blue darken-1"
text text
type="submit" @click="
@click="dialog2 = false; updateUser();" deleteUser();
dialogDelete = false;
"
> >
Save OK
</v-btn> </v-btn>
<v-spacer />
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>
<v-data-table :headers="headers" :items="users" sort-by="calories" class="elevation-1"> <v-data-table
:headers="headers"
:items="users"
sort-by="calories"
class="elevation-1"
>
<template #top> <template #top>
<v-toolbar flat> <v-toolbar flat>
<v-toolbar-title>User Manage</v-toolbar-title> <v-toolbar-title>User Manage</v-toolbar-title>
<v-divider class="mx-4" inset vertical /> <v-divider class="mx-4" inset vertical />
<v-spacer /> <v-spacer />
<v-toolbar-title style="float: right"> <v-toolbar-title style="float: right">
<v-dialog v-model="dialog1" persistent max-width="600px" @submit.prevent="createUser"> <v-dialog
v-model="dialog1"
persistent
max-width="600px"
@submit.prevent="createUser"
lazy-validation
>
<template #activator="{ on, attrs }"> <template #activator="{ on, attrs }">
<v-btn <v-btn color="primary" dark v-bind="attrs" v-on="on">
color="primary"
dark
v-bind="attrs"
v-on="on"
>
New USER New USER
</v-btn> </v-btn>
</template> </template>
...@@ -98,14 +113,11 @@ ...@@ -98,14 +113,11 @@
<v-card-text> <v-card-text>
<v-container> <v-container>
<v-row> <v-row>
<v-col <v-col cols="12" sm="6" md="4">
cols="12"
sm="6"
md="4"
>
<v-text-field <v-text-field
v-model="name" v-model="name"
label="Legal name*" label="Legal name*"
:rules="nameRules"
required required
/> />
</v-col> </v-col>
...@@ -113,6 +125,7 @@ ...@@ -113,6 +125,7 @@
<v-text-field <v-text-field
v-model="email" v-model="email"
label="Email*" label="Email*"
:rules="emailRules"
required required
/> />
</v-col> </v-col>
...@@ -121,6 +134,7 @@ ...@@ -121,6 +134,7 @@
v-model="password" v-model="password"
label="Password*" label="Password*"
type="password" type="password"
:rules="passwordRules"
required required
/> />
</v-col> </v-col>
...@@ -130,18 +144,17 @@ ...@@ -130,18 +144,17 @@
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-spacer /> <v-spacer />
<v-btn <v-btn color="blue darken-1" text @click="dialog1 = false">
color="blue darken-1"
text
@click="dialog1 = false"
>
Close Close
</v-btn> </v-btn>
<v-btn <v-btn
color="blue darken-1" color="blue darken-1"
text text
type="submit" type="submit"
@click="dialog1 = false; createUser();" @click="
dialog1 = false;
createUser();
"
> >
Save Save
</v-btn> </v-btn>
...@@ -151,17 +164,35 @@ ...@@ -151,17 +164,35 @@
</v-toolbar-title> </v-toolbar-title>
</v-toolbar> </v-toolbar>
</template> </template>
<template #item.created_at="{ item }"> <template #[`item.index`]="{ index }">
{{ index + 1 }}
</template>
<template #[`item.created_at`]="{ item }">
<span>{{ formatDate(item.created_at) }}</span> <span>{{ formatDate(item.created_at) }}</span>
</template> </template>
<template #item.updated_at="{ item }"> <template #[`item.updated_at`]="{ item }">
<span>{{ formatDate(item.updated_at) }}</span> <span>{{ formatDate(item.updated_at) }}</span>
</template> </template>
<template #[`item.actions`]="{ item }"> <template #[`item.actions`]="{ item }">
<v-icon :id="item.id" small class="mr-2" @click="dialog2 = true; editUser(item);"> <v-icon
:id="item.id"
small
class="mr-2"
@click="
dialog2 = true;
editUser(item)
"
>
mdi-pencil mdi-pencil
</v-icon> </v-icon>
<v-icon :id="item.id" small @click="deleteUser(item.id, item)"> <v-icon
:id="item.id"
small
@click="
dialogDelete = true;
getID(item)
"
>
mdi-delete mdi-delete
</v-icon> </v-icon>
</template> </template>
...@@ -189,12 +220,11 @@ export default { ...@@ -189,12 +220,11 @@ export default {
dialogDelete: false, dialogDelete: false,
headers: [ headers: [
{ {
text: 'Name', text: '#',
align: 'start', align: 'start',
sortable: false, value: 'index'
value: 'name'
}, },
{ text: 'id', value: 'id' }, { text: 'Name', value: 'name' },
{ text: 'email', value: 'email' }, { text: 'email', value: 'email' },
{ text: 'status', value: 'id', sortable: false }, { text: 'status', value: 'id', sortable: false },
{ text: 'created', value: 'created_at' }, { text: 'created', value: 'created_at' },
...@@ -236,7 +266,20 @@ export default { ...@@ -236,7 +266,20 @@ export default {
status: '', status: '',
created_at: '', created_at: '',
updated_at: '' updated_at: ''
} },
nameRules: [
v => !!v || 'Name is required',
v => (v && v.length <= 255) || 'Name must be less than 255 characters'
],
emailRules: [
v => !!v || 'E-mail is required',
v => /.+@.+\..+/.test(v) || 'E-mail must be valid'
],
passwordRules: [
v => !!v || 'Password is required',
v => (v && v.length >= 6) || 'Password must be more than 6 characters',
v => (v && v.length <= 255) || 'Password must be less than 255 characters'
]
} }
}, },
computed: { computed: {
...@@ -256,6 +299,9 @@ export default { ...@@ -256,6 +299,9 @@ export default {
this.initialize() this.initialize()
this.getUsers() this.getUsers()
}, },
beforeCreate () {
// this.keepToken()
},
methods: { methods: {
initialize () { initialize () {
this.users = [] this.users = []
...@@ -302,7 +348,9 @@ export default { ...@@ -302,7 +348,9 @@ export default {
.get('/users/', { .get('/users/', {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal(
'token'
)}`
} }
}) })
.then(response => (this.users = response.data.data.data)) .then(response => (this.users = response.data.data.data))
...@@ -313,16 +361,21 @@ export default { ...@@ -313,16 +361,21 @@ export default {
createUser () { createUser () {
const self = this const self = this
this.$axios this.$axios
.post('/users/', { .post(
email: this.email, '/users/',
password: this.password, {
name: this.name email: this.email,
}, { password: this.password,
headers: { name: this.name
'Content-Type': 'application/json', },
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.$auth.$storage.getUniversal(
'token'
)}`
}
} }
}
) )
.then((response) => { .then((response) => {
self.$toast.success('User created successfully!', { self.$toast.success('User created successfully!', {
...@@ -334,7 +387,6 @@ export default { ...@@ -334,7 +387,6 @@ export default {
this.users.push(this.editedItem) this.users.push(this.editedItem)
}) })
.catch((errors) => { .catch((errors) => {
this.$bvModal.hide('modal-login')
console.log(errors.response.data.message) console.log(errors.response.data.message)
this.message = errors.response.data.message this.message = errors.response.data.message
self.$toast.error('something went wrong while trying create!', { self.$toast.error('something went wrong while trying create!', {
...@@ -342,23 +394,23 @@ export default { ...@@ -342,23 +394,23 @@ export default {
}) })
}) })
}, },
deleteUser (userID, index) { deleteUser () {
const self = this const self = this
this.editedIndex = this.users.indexOf(index) const currentPostIndex = this.editedIndex
if (confirm('Do you really want to delete?')) { try {
try { this.$axios.delete(`/users/${this.eID}`, {
this.$axios headers: {
.delete(`/users/${userID}`) Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}`
.then((response) => { }
console.log(response.data) }).then((response) => {
this.users.splice(this.editedIndex, 1) console.log(response.data)
self.$toast.success('User deleted successfully!', { this.users.splice(currentPostIndex, 1)
duration: 3000 self.$toast.success('User deleted successfully!', {
}) duration: 3000
}) })
} catch (error) { })
console.log(error) } catch (error) {
} console.log(error)
} }
}, },
editUser (user) { editUser (user) {
...@@ -374,7 +426,8 @@ export default { ...@@ -374,7 +426,8 @@ export default {
console.log(this.eEmail) console.log(this.eEmail)
console.log(this?.eID) console.log(this?.eID)
this.$axios this.$axios
.put(`/users/${this?.eID}`, .put(
`/users/${this?.eID}`,
{ {
email: this.eEmail, email: this.eEmail,
password: this.ePassword, password: this.ePassword,
...@@ -383,7 +436,9 @@ export default { ...@@ -383,7 +436,9 @@ export default {
{ {
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
Authorization: `Bearer ${this.$auth.$storage.getUniversal('token')}` Authorization: `Bearer ${this.$auth.$storage.getUniversal(
'token'
)}`
} }
} }
) )
...@@ -401,6 +456,10 @@ export default { ...@@ -401,6 +456,10 @@ export default {
duration: 3000 duration: 3000
}) })
}) })
},
getID (item) {
this.eID = item.id
this.editedIndex = this.users.indexOf(item)
} }
} }
} }
......
...@@ -15,7 +15,8 @@ export default function ({ $axios }, inject, redirect) { ...@@ -15,7 +15,8 @@ export default function ({ $axios }, inject, redirect) {
const api = $axios.create({ const api = $axios.create({
headers: { headers: {
common: { common: {
Accept: 'application/json, text/plain, */*' Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json, text/plain, */*'
} }
} }
}) })
......
import Vue from 'vue' import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
Vue.mixin({ Vue.mixin({
methods: { methods: {
...@@ -12,6 +14,11 @@ Vue.mixin({ ...@@ -12,6 +14,11 @@ Vue.mixin({
if (day.length < 2) { day = '0' + day } if (day.length < 2) { day = '0' + day }
return [year, month, day].join('-') return [year, month, day].join('-')
},
keepToken () {
const TOKEN = localStorage.getItem('token')
this.$auth.$storage.setUniversal('token', TOKEN)
} }
} }
}) })
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
modules: {
}
})
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment