diff --git a/package-lock.json b/package-lock.json index 04c92c27d158a40a07d11c091b4f5b0af4e93b56..da35d07e4b05a2bef59b5901a8f9fd84961ac744 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11944,6 +11944,11 @@ "setimmediate": "^1.0.4" } }, + "tiny-cookie": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tiny-cookie/-/tiny-cookie-1.0.1.tgz", + "integrity": "sha1-dTeGB5xkKjw9CyrMrWAPjeEZrCo=" + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", @@ -12456,6 +12461,14 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.10.tgz", "integrity": "sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==" }, + "vue-cookie": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/vue-cookie/-/vue-cookie-1.1.4.tgz", + "integrity": "sha1-uLRtESvan5Oi9HAXwu1SgtIGT9o=", + "requires": { + "tiny-cookie": "^1.0" + } + }, "vue-functional-data-merge": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-2.0.7.tgz", diff --git a/package.json b/package.json index e5a3e9fe861c29905ba1ecca04f1d946b77debcc..c3aebd5ea1cab5070a40af3fb867fba5963ca77b 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "bootstrap-vue": "^2.0.0-rc.15", "d3": "^5.9.2", "vue": "^2.6.10", + "vue-cookie": "^1.1.4", "vue-router": "^3.0.1", "vuex": "^3.1.0" }, diff --git a/src/App.vue b/src/App.vue index 59d58953655dfcfe93318f114bfe64e1a9d82d9a..63bc9bf1a37c6eb767caf827e11cc85bd191b7e6 100644 --- a/src/App.vue +++ b/src/App.vue @@ -17,6 +17,31 @@ export default { components: { 'app-navbar': navbar, }, + mounted() { + if(this.$cookie.get('token')) { + let fetchData = { + method: 'POST', + headers: { + "Authorization": this.$cookie.get('token'), + } + } + + fetch(`${this.$store.state.baseUrl}/api/get-user`, fetchData) + .then(response => response.json()) + .then(response => { + if(response.status === 200) { + let data = { + 'token': this.$cookie.get('token'), + 'id': response.data._id, + 'name': response.data.name, + 'role': response.data.role, + 'pageList': response.data.page_list + } + this.$store.commit('setUser', data) + } + }) + } + } } </script> diff --git a/src/components/pages/LoginPage.vue b/src/components/pages/LoginPage.vue index 2d16827da9a70bf8421b7fa725c5a8ff8c613368..778a6ed3aaf8c79e6459ea42f3a0c73a21399513 100644 --- a/src/components/pages/LoginPage.vue +++ b/src/components/pages/LoginPage.vue @@ -4,6 +4,15 @@ <b-card no-body> <b-tabs card> <b-tab title="Masuk" active> + <b-alert + :show="dismissCountDown" + dismissible + variant="warning" + @dismissed="dismissCountDown=0" + @dismiss-count-down="countdownCallback" + > + {{ errorMessage }} + </b-alert> <b-form @submit.prevent="submitLogin"> <b-form-group label="Nama Pengguna:"> <b-form-input @@ -25,6 +34,15 @@ </b-form> </b-tab> <b-tab title="Daftar"> + <b-alert + :show="dismissCountDown" + dismissible + variant="warning" + @dismissed="dismissCountDown=0" + @dismiss-count-down="countdownCallback" + > + {{ errorMessage }} + </b-alert> <b-form> <b-form-group label="NIK/NIP:"> <b-form-input @@ -93,23 +111,135 @@ export default { username: '', password: '', confirmPassword: '' - } + }, + errorMessage: '', + dismissSecs: 5, + dismissCountDown: 0 } }, created : function() { this.$store.commit('changed','Jenis Anggaran') }, methods: { - submitLogin: function(event) { - // TODO: Create function to log in the user - var data = {token: 'ABCD', id: 1, name: this.login.username} - this.$store.commit('setUser', data) - this.$router.push('/') + submitLogin() { + if (this.login.username.length == 0 || this.login.password.length == 0) { + this.setErrorMessage("Kata pengguna/sandi wajib diisi") + return + } + + let fetchData = { + method: 'POST', + body: JSON.stringify( + { + username: this.login.username, + password: this.login.password, + } + ), + headers: { + "Content-Type": "application/json", + } + } + + fetch(`${this.$store.state.baseUrl}/api/login`, fetchData) + .then(response => response.json()) + .then(response => { + if(response.status === 200) { + this.$cookie.set('token', response.data.token) + let data = { + 'token': response.data.token, + 'id': response.data.user._id, + 'name': response.data.user.name, + 'role': response.data.user.role, + 'pageList': response.data.user.page_list + } + this.$store.commit('setUser', data) + this.$router.push({name: 'LandingPage'}) + } else if(response.status === 404) { + this.setErrorMessage('Kata pengguna/sandi salah.') + } else { + this.setErrorMessage('Tidak dapat masuk. Silakan coba lagi.') + } + }) + .catch(error => { + this.setErrorMessage('Tidak dapat terhubung dengan server. Mohon periksa koneksi internet dan cobalah beberapa saat lagi.') + }) + }, + submitRegister() { + if (this.register.username.length === 0) { + this.setErrorMessage("Kata pengguna wajib diisi") + return + } + if (this.register.nik.length === 0) { + this.setErrorMessage("NIK wajib diisi") + return + } + if (this.register.name.length === 0) { + this.setErrorMessage("Nama lengkap wajib diisi") + return + } + if (this.register.password.length === 0) { + this.setErrorMessage("Kata sandi wajib diisi") + return + } + if (this.register.password !== this.register.confirmPassword) { + this.setErrorMessage("Kata sandi tidak cocok") + return + } + if (this.register.password !== this.register.confirmPassword) { + this.setErrorMessage("Kata sandi tidak cocok") + return + } + + let role = 0 + if (this.register.nik.length === 18) + role = 1 + + let fetchData = { + method: 'POST', + body: JSON.stringify( + { + username: this.register.username, + password: this.register.password, + user_id: this.register.nik, + name: this.register.name, + role: role + } + ), + headers: { + "Content-Type": "application/json", + } + }; + + fetch(`${this.$store.state.baseUrl}/api/register`, fetchData) + .then(response => response.json()) + .then(response => { + if(response.status === 200) { + this.$cookie.set('token', response.data.token) + let data = { + 'token': response.data.token, + 'id': this.register.nik, + 'name': this.register.name, + 'role': role, + 'pageList': [] + } + this.$store.commit('setUser', data) + this.$router.push({name: 'LandingPage'}) + } else if (response.status === 500) { + this.setErrorMessage('Akun dengan NIK ini sudah dibuat.') + } else { + this.setErrorMessage('Terjadi kesalahan. Kesalahan: ' + response.message) + } + }) + .catch(error => { + this.setErrorMessage('Tidak dapat terhubung dengan server. Mohon periksa koneksi internet dan cobalah beberapa saat lagi.') + }) + }, + countdownCallback(dismissCountDown) { + this.dismissCountDown = dismissCountDown }, - submitRegister: function(event) { - // TODO: Create function to register new user - this.$store.commit('setUser', 'ABCD', 1, this.register.username) - this.$router.push('/') + setErrorMessage(message) { + this.errorMessage = message + this.dismissCountDown = this.dismissSecs } } } diff --git a/src/components/pages/PanelAdministrator.vue b/src/components/pages/PanelAdministrator.vue new file mode 100644 index 0000000000000000000000000000000000000000..19984f0bb6c5d1122509b923a4ec87dd13f8f43a --- /dev/null +++ b/src/components/pages/PanelAdministrator.vue @@ -0,0 +1,277 @@ +<template> + <div id="placeholder"> + <div id="container"> + <b-card no-body> + <b-tabs card> + <b-tab title="Komentar" active> + <b-card no-body> + <b-tabs pills vertical card> + <b-tab title="Entri Komentar" disabled/> + <b-tab + v-for="item in urusan" + :key=item.judul + v-bind:title="item.judul"> + <b-tabs content-class="mt-3"> + <b-tab title="Belum dibalas" active> + <comments replyable/> + </b-tab> + <b-tab title="Semua"> + <comments replyable/> + </b-tab> + </b-tabs> + </b-tab> + </b-tabs> + </b-card> + </b-tab> + <b-tab v-if="this.$store.state.user.role == 2" title="Pengaturan Admin"> + <!-- Table Pagination + Filter --> + <b-pagination + v-model="currentPage" + :total-rows="totalRows" + :per-page="perPage" + align="center" + /> + <b-form-input + v-model="filter" + placeholder="Ketik untuk menyaring urusan/admin..." + /> + <div class="mb-3"> + <small class="text-muted font-italic"> + Menampilkan {{ totalRows }} baris urusan + </small> + </div> + <b-table + show-empty + striped + hover + stacked="sm" + :items="items" + :fields="fields" + :current-page="currentPage" + :per-page="perPage" + :filter="filter" + @filtered="filterTrigger" + > + <template slot="aksi" slot-scope="row"> + <div v-if="row.item.admin === '-'"> + <div class="px-1 col-md-6 col-12"> + <b-button + @click="switchToggleDetails(row)" + variant="success" + size="sm" + class="w-100" + > + Pasang + </b-button> + </div> + </div> + <b-row class="mx-0" v-else> + <div class="px-1 col-md-6 col-12"> + <b-button + @click="switchToggleDetails(row)" + variant="primary" + size="sm" + class="w-100" + > + Ubah + </b-button> + </div> + <div class="px-1 col-md-6 col-12"> + <b-button + @click="clearButtonHandler(row)" + variant="danger" + size="sm" + class="w-100" + > + Kosongkan + </b-button> + </div> + </b-row> + </template> + <template slot="row-details" slot-scope="row"> + <b-card + bg-variant="light" + > + <small><b>Mohon pilih Admin dari daftar di bawah ini:</b></small> + <b-form-select + v-model="selected" + :options="options" + size="sm" + /> + <b-button + @click="assignAdmin(row)" + variant="primary" + size="sm" + class="float-right mt-2 ml-2" + > + Pilih Admin + </b-button> + <b-button + @click="switchToggleDetails(null)" + size="sm" + class="float-right mt-2" + > + Batalkan + </b-button> + </b-card> + </template> + <template slot="empty"> + <div align="center">Tidak ada data untuk ditampilkan</div> + </template> + <template slot="emptyfiltered"> + <div align="center">Data tidak ditemukan</div> + </template> + </b-table> + <b-pagination + v-model="currentPage" + :total-rows="totalRows" + :per-page="perPage" + align="center" + /> + + <!-- Modal Component --> + <b-modal + id="confirmation-modal" + centered + title="Konfirmasi" + v-model="modalVisibility" + ok-title="Kosongkan" + cancel-title="Batal" + ok-variant="danger" + @ok="clearAdminHandler" + > + <p align="center" class="my-4"> + Apakah Anda yakin ingin mengosongkan Admin?<br> + <b>Tindakan ini tidak dapat diurungkan.</b> + </p> + </b-modal> + </b-tab> + </b-tabs> + </b-card> + </div> + </div> +</template> + +<script> +import Comments from '@/components/partials/Comments' + +export default { + name: 'PanelAdministrator', + components: { + 'comments' : Comments, + }, + data() { + return { + currentRow: null, + clearedRowPointer: null, + modalVisibility: false, + totalRows: 1, + currentPage: 1, + perPage: 15, + filter: null, + selected: 'urusan', + fields: ['urusan', 'admin', 'aksi'], + urusan : [ + { judul: "Pendapatan", url: "" }, + { judul: "Pembiayaan", url: "" }, + { judul: "Biaya Langsung", url: "" }, + { judul: "Biaya Tidak Langsung", url: "" }, + ], + items : [ + { urusan: 'Biaya Langsung', admin: 'Rifo Ahmad Genadi'}, + { urusan: 'Biaya Tak Langsung', admin: 'David Timothy Panjaitan'}, + { urusan: 'Pembiayaan', admin: '-'}, + { urusan: 'Pendapatan', admin: '-'}, + { urusan: 'A', admin: 'Rifo Ahmad Genadi'}, + { urusan: 'B', admin: 'David Timothy Panjaitan'}, + { urusan: 'C', admin: '-'}, + { urusan: 'D', admin: '-'}, + { urusan: 'E', admin: 'Rifo Ahmad Genadi'}, + { urusan: 'F', admin: 'David Timothy Panjaitan'}, + { urusan: 'G', admin: '-'}, + { urusan: 'H', admin: '-'}, + { urusan: 'I', admin: 'Rifo Ahmad Genadi'}, + { urusan: 'J', admin: 'David Timothy Panjaitan'}, + { urusan: 'K', admin: '-'}, + { urusan: 'L', admin: '-'}, + { urusan: 'M', admin: 'Rifo Ahmad Genadi'}, + { urusan: 'N', admin: 'David Timothy Panjaitan'}, + { urusan: 'O', admin: '-'}, + { urusan: 'P', admin: '-'}, + { urusan: 'Q', admin: 'Rifo Ahmad Genadi'}, + { urusan: 'R', admin: 'David Timothy Panjaitan'}, + { urusan: 'S', admin: '-'}, + { urusan: 'T', admin: '-'}, + { urusan: 'U', admin: 'Rifo Ahmad Genadi'}, + { urusan: 'V', admin: 'David Timothy Panjaitan'}, + { urusan: 'W', admin: '-'}, + { urusan: 'X', admin: '-'}, + { urusan: 'Y', admin: 'Rifo Ahmad Genadi'}, + { urusan: 'Z', admin: 'David Timothy Panjaitan'}, + ], + options: [ + { value: '0', text: 'Rifo Ahmad Genadi' }, + { value: '1', text: 'David Timothy Panjaitan' }, + { value: '2', text: 'William Rukmansa' }, + { value: '3', text: 'Ricky Kennedy' } + ], + } + }, + created : function() { + if (this.$store.state.user.role <= 0) { + this.$router.push({name: 'LandingPage'}); + return + } + + this.totalRows = this.items.length + this.$store.commit('changed','Jenis Anggaran') + }, + methods: { + assignAdmin : function(row) { + row.item.admin = this.options[this.selected].text + this.switchToggleDetails(null) + }, + clearButtonHandler : function(row) { + this.modalVisibility = true + this.clearedRowPointer = row + }, + clearAdminHandler : function() { + this.clearedRowPointer.item.admin = "-" + this.switchToggleDetails(null) + }, + switchToggleDetails : function(newRow) { + if (this.currentRow) { + this.currentRow.toggleDetails() + } + if (newRow) { + newRow.toggleDetails() + } + this.currentRow = newRow + this.selected = null + }, + filterTrigger(item) { + this.totalRows = item.length + this.currentPage = 1 + } + } +} +</script> + + +<style lang="scss" scoped> +@import 'src/assets/css/style.scss'; + +#placeholder { + padding: 30px 20px; + + #container { + height: auto; + width: 100%; + min-width: 250px; + max-width: 1000px; + margin: auto; + border-radius: 5px; + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.25); + } +} +</style> \ No newline at end of file diff --git a/src/components/pages/SemuaAnggaran.vue b/src/components/pages/SemuaAnggaran.vue index c39a833e5908041f7c5c1538ac65091959c231b8..c8d9613131f31c2a3ef37ef73f5f9d8f855b05f6 100644 --- a/src/components/pages/SemuaAnggaran.vue +++ b/src/components/pages/SemuaAnggaran.vue @@ -13,7 +13,7 @@ </b-col> </b-row> <div id="comments-container"> - <comments/> + <comments commentable/> </div> </b-container> </template> diff --git a/src/components/partials/Comments.vue b/src/components/partials/Comments.vue index ff1026194419745414f5a7c6744a7915ed1f4e26..854dedcdb544c5837e7e92ae67f56d7d68a9ea82 100644 --- a/src/components/partials/Comments.vue +++ b/src/components/partials/Comments.vue @@ -1,6 +1,10 @@ <template> +<<<<<<< HEAD <div id="placeholder"> <h4 class="font-weight-bold">Komentar ({{rows}})</h4> +======= + <div id="comments-placeholder"> +>>>>>>> 8b073dd0b310f4ac1bcf4d8a7bdf1fc0952755b4 <div id="comments-container"> <b-card bg-variant="light" @@ -21,6 +25,23 @@ {{comment.reply.content}} <div><small class="text-muted font-italic">{{comment.reply.timestamp}}</small></div> </b-card> + <div v-else> + <b-card + v-if="replyable" + bg-variant="dark" + text-variant="white" + class="reply-box float-right" + > + <b-form-textarea + id="textarea" + class="reply-textarea" + v-model="replyText[comment.id]" + placeholder="Masukkan balasan..." + no-resize + /> + <b-button variant="primary" class="float-right mt-2" @click="replyComment(comment.id)">Kirim</b-button> + </b-card> + </div> </b-card> </div> <div id="comment-box"> @@ -30,22 +51,24 @@ :per-page="perPage" align="center" /> - <div v-if="this.$store.state.user.token != ''" id="comment-section"> - <b-form-textarea - id="textarea" - v-model="text" - placeholder="Masukkan komentar..." - no-resize - /> - <b-button variant="primary" class="float-right mt-2" @click="addComment">Kirim</b-button> - </div> - <div v-else> - Anda harus <router-link :to="{ name:'LoginPage' }">masuk</router-link> terlebih dahulu sebelum memberikan komentar. - </div> - <div> - <small class="text-muted font-italic"> - Dengan mengirim komentar, Anda tunduk terhadap UU ITE yang berlaku. - </small> + <div v-if="commentable"> + <div v-if="this.$store.state.user.token != ''" id="comment-section"> + <b-form-textarea + id="textarea" + v-model="text" + placeholder="Masukkan komentar..." + no-resize + /> + <b-button variant="primary" class="float-right mt-2" @click="addComment">Kirim</b-button> + </div> + <div v-else> + Anda harus <router-link :to="{ name:'LoginPage' }">masuk</router-link> terlebih dahulu sebelum memberikan komentar. + </div> + <div> + <small class="text-muted font-italic"> + Dengan mengirim komentar, Anda tunduk terhadap UU ITE yang berlaku. + </small> + </div> </div> </div> </div> @@ -54,14 +77,19 @@ <script> export default { name: 'Comments', + props: { + commentable : Boolean, + replyable : Boolean, + }, components: { - + }, data() { return { perPage: 5, currentPage: 1, - text: '', + text: "", + replyText: [], items: [ { id: 6, @@ -133,14 +161,27 @@ export default { }, }, methods: { - addComment: function(event) { + addComment: function() { this.items.unshift({ "id" : (this.rows+1), "userid": 0, "name": "Rifo Ahmad Genadi", "content": this.text, "timestamp": "29 Maret 2019, 02.48 WIB", - }); + }) + }, + replyComment: function(id) { + this.items[this.rows-id-1].reply = { + "name": "Administrator", + "content": this.replyText[id], + "timestamp": "29 Maret 2019, 02.48 WIB", + } + this.refreshContent(); + }, + refreshContent: function() { + let temp = this.items + this.items = null + this.items = temp } } } @@ -150,10 +191,9 @@ export default { <style lang="scss" scoped> @import 'src/assets/css/style.scss'; -#placeholder { +#comments-placeholder { width: 100%; height: 100%; - padding: 20px; #comments-container { height: 60%; @@ -169,7 +209,7 @@ export default { margin-bottom: 5px; } - .item-reply { + .item-reply, .reply-box { width: 100%; margin-top: 5px; } @@ -177,6 +217,16 @@ export default { .item-reply>.card-body { padding: 5px 15px !important; } + + .reply-box>.card-body { + padding: 5px !important; + } + + .reply-textarea { + background-color: #212529; + border: 1px solid #212529; + color: white; + } } #comment-box { diff --git a/src/components/partials/Navbar.vue b/src/components/partials/Navbar.vue index 97942b30c1e1f50c1c6981e92ac06dee4f13b4c4..45bd28a16993f6378fb1eeb9c3d117bff404812d 100644 --- a/src/components/partials/Navbar.vue +++ b/src/components/partials/Navbar.vue @@ -12,7 +12,7 @@ <b-collapse is-nav id="nav_collapse"> <!-- Right aligned nav items --> <b-navbar-nav> - <b-nav-item-dropdown v-bind:text=pilihan left> + <b-nav-item-dropdown v-bind:text=state left> <b-dropdown-item v-on:click="gotoPage('semua-anggaran')"> Semua Anggaran </b-dropdown-item> @@ -38,18 +38,22 @@ </b-nav-item> </div> <div v-else> - <b-nav-item-dropdown v-bind:text=nama right> + <b-nav-item-dropdown v-bind:text=name right> + <b-dropdown-item + v-if="this.$store.state.user.role > 0" + v-on:click="gotoPage('panel-administrator')" + > + Panel Admin + </b-dropdown-item> <b-dropdown-item v-on:click="gotoPage('semua-anggaran')"> Pengaturan </b-dropdown-item> - <b-dropdown-item v-on:click="gotoPage('pendapatan')"> + <b-dropdown-item v-on:click="logOut()"> Keluar </b-dropdown-item> </b-nav-item-dropdown> </div> </b-navbar-nav> - - </b-collapse> </b-container> </b-navbar> @@ -61,29 +65,27 @@ export default { name: 'Navbar', data () { return { - pilihan : this.$store.state.pilihan, - nama : this.$store.state.user.name, + } }, computed : { - state_watcher () { + state() { return this.$store.state.pilihan + }, + name() { + return this.$store.state.user.name } }, methods : { - gotoPage : function(page) { + gotoPage(page) { this.$router.push(page) + }, + logOut() { + this.$cookie.set('token', ""); + this.$store.commit('clearUser') + this.$router.push({name: 'LandingPage'}); } }, - created : function() { - this.pilihan = this.$store.state.pilihan - }, - watch : { - state_watcher(newPilihan, oldPilihan) { - // console.log("lama : " + oldPilihan + ", baru :" +newPilihan) - this.pilihan = newPilihan - } - } } </script> diff --git a/src/components/store/Store.js b/src/components/store/Store.js index 968e617040b987fed2319979519755646f4532ed..47416af30db77b1a775b6b3a15f5a624f3f75986 100644 --- a/src/components/store/Store.js +++ b/src/components/store/Store.js @@ -9,10 +9,13 @@ export const store = new Vuex.Store({ count : 0, year : '', user : { - token : '', - id : -1, - name : 'dummy' - } + token: '', + id: -1, + name: '', + role: -1, + pageList: [] + }, + baseUrl: 'http://localhost:5000' }, computed: { pilihan() { @@ -30,7 +33,16 @@ export const store = new Vuex.Store({ state.user.token = data.token state.user.id = data.id state.user.name = data.name + state.user.role = data.role + state.user.pageList = data.pageList }, + clearUser(state) { + state.user.token = '', + state.user.id = -1, + state.user.name = '', + state.user.role = -1, + state.user.pageList = [] + } }, getters : { pilihan : (state) => { diff --git a/src/main.js b/src/main.js index 9d4ab8846d9f4d49fae15007603ed7f9b7ec9d6f..44488f4ae3b2fc2fa48abc7526cd69167af0f869 100644 --- a/src/main.js +++ b/src/main.js @@ -5,6 +5,7 @@ import Vuex from 'vuex' import App from './App' import router from './router' import BootstrapVue from 'bootstrap-vue' +import VueCookie from 'vue-cookie' import {store} from './components/store/store' import 'bootstrap/dist/css/bootstrap.css' @@ -13,6 +14,8 @@ import 'bootstrap-vue/dist/bootstrap-vue.css' Vue.config.productionTip = false Vue.use(BootstrapVue) Vue.use(Vuex) +Vue.use(VueCookie) + /* eslint-disable no-new */ new Vue({ el: '#app', diff --git a/src/router/index.js b/src/router/index.js index 4bc1dde5d09c3115ccdaa06c44c3e0847c2703be..eae9fb458f3ce402a0a6a7253a3eb9bd1b8d8c64 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -8,6 +8,7 @@ import BiayaTidakLangsung from '@/components/pages/BiayaTidakLangsungPage' import BiayaLangsung from '@/components/pages/BiayaLangsungPage' import SemuaAnggaran from '@/components/pages/SemuaAnggaran' import SimpleCardContainer from '@/components/partials/SimpleCardContainer' +import PanelAdministrator from '@/components/pages/PanelAdministrator' Vue.use(Router) export default new Router({ @@ -52,7 +53,11 @@ export default new Router({ name: 'SimpleCardContainer', component: SimpleCardContainer }, - + { + path: '/panel-administrator', + name: 'PanelAdministrator', + component: PanelAdministrator + }, ], mode: 'history', })