diff --git a/src/components/table-2.vue b/src/components/table-2.vue new file mode 100644 index 0000000000000000000000000000000000000000..2742b764d021033973c122343427927ccf85ac36 --- /dev/null +++ b/src/components/table-2.vue @@ -0,0 +1,206 @@ +<template> + <div class="table-responsive"> + <table class="table table-bordered"> + <thead> + <tr> + <template v-for="c in columns" :key="c"> + <th + v-if="!c.hidden" + @click="sort(c.data)" + class="text-blue clickable" + > + {{ c.name}} + </th> + </template> + <th v-if="this.edit || this.delete" class="text-blue">Aksi</th> + </tr> + </thead> + <tbody> + + <tr + v-for="e in this.entries.slice( + (this.page - 1) * this.entry_per_page, + this.page * this.entry_per_page + )" + :key="e.id" + > + <template v-for="c in columns" :key="c"> + <template v-if="!c.hidden"> + <td v-if="c.clickable" @click="this.$emit('detail-entry', e[columns.Id.data])" class="clickable"> + {{ e[c.data] }} + </td> + <td v-else > + {{ e[c.data]}} + </td> + </template> + </template> + + <td v-if="this.edit || this.delete" style="text-align: center"> + <button v-if="this.edit" @click="this.$emit('edit-entry', e[columns.Id.data])" class="btn btn-blue"> <i class="icon ion-android-create" style="font-size: 20px"></i> Edit </button> + <button v-if="this.delete" @click="this.$emit('delete-entry', e[columns.Id.data])" class="btn-red"> <i class="icon ion-ios-trash-outline" style="font-size: 23px"></i> </button> + </td> + </tr> + </tbody> + </table> + <nav aria-label="Page navigation"> + <ul class="pagination justify-content-end"> + <li v-if="this.page > 1" class="page-item"> + <div class="page-link" @click="prevPage()">Previous</div> + </li> + <li v-else class="page-item disabled"> + <div class="page-link">Previous</div> + </li> + <template v-for="p in this.pagination" :key="p"> + <li v-if="this.page == p" class="page-item disabled"> + <div class="page-link">{{ p }}</div> + </li> + <li v-else class="page-item"> + <div class="page-link" @click="goPage(p)">{{ p }}</div> + </li> + </template> + <li v-if="this.page < this.page_num" class="page-item"> + <div class="page-link" @click="nextPage()">Next</div> + </li> + <li v-else class="page-item disabled"> + <div class="page-link">Next</div> + </li> + </ul> + </nav> + </div> +</template> + +<script> + +import { HTTP } from '../http-common' +// import axios from 'axios'; + +export default { + name: "Table2", + props: { + //map nama kolom ke data + columns: Object, + endpoint: String, + filter: String, + filter_column: String, + edit: { + type: Boolean, + default: true + }, + delete: { + type: Boolean, + default: true + }, + + + }, + data() { + return { + pagination: [], + sorted: { + column: this.columns.Id.data, + asc: true, + }, + entries: [], + entry_per_page: 10, + page: 1, + page_num: 0, + }; + }, + mounted() { + this.getData() + }, + watch: { + filter() { + this.page = 1 + this.getData() + } + }, + methods: { + getData(){ + let sortCol = this.sorted.column + if (!this.sorted.asc){ + sortCol = `-${sortCol}` + } + HTTP.get(`${this.endpoint}?page=${this.page}&sort=${sortCol}&filter[${this.filter_column}]=${this.filter}`).then((res)=>{ + if (res.status == 200){ + console.log(res.data) + this.entries = res.data.data.data + this.page = res.data.data.current_page + this.entry_per_page = res.data.data.per_page + this.page_num = res.data.data.last_page + this.updatePagination(); + } + }) + }, + sort(column) { + console.log("sort "+ column) + if (column === this.sorted.column) { + this.sorted.asc = !this.sorted.asc; + } else { + this.sorted.column = column; + this.sorted.asc = true + } + this.page = 1 + this.getData() + }, + nextPage() { + if (this.page < this.page_num) { + this.page += 1; + this.getData() + } + }, + prevPage() { + if (this.page > 1) { + this.page -= 1; + this.getData() + } + }, + goPage(i) { + this.page = i; + this.getData() + }, + updatePagination() { + this.pagination = []; + for (let i = this.page - 2; i <= this.page + 2; i++) { + if (i <= this.page_num && i > 0) { + this.pagination.push(i); + } + } + }, + }, +}; +</script> + +<style scoped> +li { + padding: 0; +} + +.table-bordered td, +.table-bordered th, +.table-bordered thead { + border: 1px solid #6992b4 !important; +} + +.btn-blue { + background-color: #6992b4; + color: #f1f7fc; + border-radius: 15px; + padding: 5px; + margin-right: 5px; + vertical-align:middle +} + +.btn-red { + background-color: #f4476b; + color: #f1f7fc; + border-radius: 8px; + padding-left: 5px; + padding-right: 5px; + vertical-align:middle +} + +th{ + text-align: center; +} +</style> diff --git a/src/components/table.vue b/src/components/table.vue index 7f79403a52ce752a11963907a76e90f20943a919..bd7c946e3f70d5a06fd3d2e7f7f0b40b248f8e28 100644 --- a/src/components/table.vue +++ b/src/components/table.vue @@ -43,7 +43,7 @@ </tbody> </table> <nav aria-label="Page navigation"> - <ul class="pagination justify-content-end"> + <ul class="pagination justify-content-end clickable"> <li v-if="this.page > 1" class="page-item"> <div class="page-link" @click="prevPage()">Previous</div> </li> @@ -88,7 +88,6 @@ export default { }, data() { return { - // entries: [], pagination: [], sorted: { column: "", @@ -112,7 +111,6 @@ export default { return entries; }, - }, methods: { changes(entries) { diff --git a/src/http-common.js b/src/http-common.js index 79a652db6c05881d51273c7944758e302983e845..44da233e4de33f0432230b95f20d831af1822761 100644 --- a/src/http-common.js +++ b/src/http-common.js @@ -1,8 +1,12 @@ import axios from 'axios'; +const token = localStorage.getItem('token') + export const HTTP = axios.create({ baseURL: `https://simkpi-backend.herokuapp.com/api`, -// headers: { -// Authorization: 'Bearer {token}' -// } + // baseURL: 'localhost:8000/api/', + headers: { + Accept: 'application/json', + Authorization: `Bearer ${token}` + } }) diff --git a/src/router/index.js b/src/router/index.js index 7bc9277e022dbded363f52defd9648707924a087..73232584641d938abe454eb53b241191cfde718d 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -13,6 +13,10 @@ import AdminEdit from "../views/AdminEdit.vue"; import KpiIndex from "../views/KpiIndex.vue"; import KpiCreate from "../views/KpiCreate.vue"; import KpiManagerDetail from "../views/KpiManagerDetail.vue"; +import Test from "../views/Test.vue"; +import ManagerKpiIndex from "../views/ManagerKpiIndex.vue"; +import ManagerKaryawanIndex from "../views/ManagerKaryawanIndex.vue"; +import ManagerKaryawanDetail from "../views/ManagerKaryawanDetail.vue"; const routes = [ { @@ -85,6 +89,26 @@ const routes = [ name: "KpiManagerDetail", component: KpiManagerDetail, }, + { + path: "/manager/kpi", + name: "ManagerkpiIndex", + component: ManagerKpiIndex, + }, + { + path: "/manager/employees", + name: "ManagerkaryawanIndex", + component: ManagerKaryawanIndex, + }, + { + path: "/manager/employees/:id", + name: "ManagerKaryawanDetail", + component: ManagerKaryawanDetail, + }, + { + path: "/test", + name: "test", + component: Test, + }, ]; const router = createRouter({ diff --git a/src/views/ManagerKaryawanDetail.vue b/src/views/ManagerKaryawanDetail.vue new file mode 100644 index 0000000000000000000000000000000000000000..5a42511101a7a7650476f10eeba75bb59c7b93ed --- /dev/null +++ b/src/views/ManagerKaryawanDetail.vue @@ -0,0 +1,162 @@ +<template> + <div class="container-fluid"> + <div class="row flex-nowrap"> + <Sidebar current_page = "About"></Sidebar> + <div class="col ps-md-2 pt-2"> + <Header></Header> + <div class="row p-3"> + <router-link :to="{ path: '/manager/employees' }" style="text-decoration: none"> + <div class="d-flex flex-row justify-content-start align-items-center illustration" id="back"> + <i class="icon ion-chevron-left text-blue" style="font-size: 20px"></i> + <p class="text-blue ms-1">kembali</p> + </div> + </router-link> + </div> + <div class="row p-2"> + <div class="col"> + <h1 class="text-blue">NAMA</h1> + </div> + </div> + <form @submit="report" autocomplete="off" id="formReport"> + <div class="row p-2"> + + <div class="col p-2"> + <label for="startReport" class="text-blue"> Tanggal awal </label> + <input v-model="startReport" type="date" id="startReport" class="form-control" required> + </div> + <div class="col p-2"> + <label for="endReport" class="text-blue"> Tanggal akhir </label> + <input v-model="endReport" type="date" id="endReport" class="form-control" required> + </div> + <div class="col p-2"> + <button type="submit" class="btn-blue p-1 mt-3" >Buat Report</button> + </div> + </div> + </form> + <hr class="m-2"> + <div class="row p-2"> + <h2 class="text-blue">Daftar KPI</h2> + </div> + <div class="row p-2"> + <div class="col-6 p-2"> + <select + v-model="filter" + class="form-select" + aria-label="Default select example" + > + <option selected value="">Semua</option> + <option v-for="p in periods" :key="p" :value="p.data">{{p.name}}</option> + </select> + </div> + </div> + <div class="row p-2"> + <!-- Ganti endpoint --> + <Table2 + :endpoint="'kpis'" + :columns="columns" + :filter="filter" + :filter_column="'period_type'" + :edit = "false" + :delete = "false" + @detail-entry="openResponses" + ></Table2> + </div> + </div> + </div> + </div> +</template> + +<script> + +import Table2 from "../components/table-2"; +import Header from "../components/header"; +import Sidebar from "../components/sidebar"; +// import { HTTP } from "../http-common"; + + +export default { + name: "ManagerKaryawanDetail", + components: { + Header, + Sidebar, + Table2 + }, + data(){ + return{ + filter: "", + columns: { + Id: { + name : "Id", + data : "id", + hidden : true, + clickable : false + }, + Nama: { + name : "Nama", + data : "name", + hidden : false, + clickable : true + }, + Periode: { + name : "Periode", + data : "period_type", + hidden : false, + clickable : false + }, + }, + periods: [ + {name: "Harian", + data: "daily"}, + {name: "Mingguan", + data: "weekly"}, + {name: "Bulanan", + data: "monthly"}, + {name: "Tahunan", + data: "yearly"}, + {name: "Custom", + data: "custom"}, + ], + id: -1, + emp: { + name : "Nama Karyawan" + }, + } + }, + mounted(){ + this.id = this.$route.params.id + }, + methods: { + openResponses(idKpi){ + //routing ke halaman response + console.log(idKpi) + }, + report(){ + //download report + } + } + +} +</script> + +<style scoped> +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + min-height: 100vh; + background-color: #fff; +} + +.btn-blue { + background-color: #6992b4; + color: #f1f7fc; + border-radius: 8px; + margin-right: 5px; +} + + + +</style> \ No newline at end of file diff --git a/src/views/ManagerKaryawanIndex.vue b/src/views/ManagerKaryawanIndex.vue new file mode 100644 index 0000000000000000000000000000000000000000..fcc8ee07cb70bb56c8782d6dfd29e2fdc7b18bda --- /dev/null +++ b/src/views/ManagerKaryawanIndex.vue @@ -0,0 +1,98 @@ +<template> + <div class="container-fluid"> + <div class="row flex-nowrap"> + <Sidebar current_page = "About"></Sidebar> + <div class="col ps-md-2 pt-2"> + <Header></Header> + <div class="row p-2"> + <div class="col"> + <h1 class="text-blue">Daftar Karyawan</h1> + </div> + </div> + <div class="row p-2"> + <Table2 + :endpoint="'kpis'" + :columns="columns" + :filter="filter" + :filter_column="'period_type'" + :edit = "false" + :delete = "false" + @detail-entry="detailKaryawan" + ></Table2> + </div> + </div> + </div> + </div> +</template> + +<script> + +import Table2 from "../components/table-2"; +import Header from "../components/header"; +import Sidebar from "../components/sidebar"; +// import { HTTP } from "../http-common"; + + +export default { + name: "ManagerKaryawanIndex", + components: { + Header, + Sidebar, + Table2 + }, + data(){ + return{ + filter: "", + columns: { + Id: { + name : "Id", + data : "id", + hidden : true, + clickable : false + }, + Nama: { + name : "Nama", + data : "name", + hidden : false, + clickable : true + }, + Periode: { + name : "Periode", + data : "period_type", + hidden : false, + clickable : false + }, + } + } + }, + methods: { + detailKaryawan(id){ + //routing page detail + console.log(id) + } + } + +} +</script> + +<style scoped> +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + min-height: 100vh; + background-color: #fff; +} + +.btn { + background-color: #6992b4; + color: #f1f7fc; + border-radius: 15px; + padding: 7px; +} + + +</style> \ No newline at end of file diff --git a/src/views/ManagerKpiIndex.vue b/src/views/ManagerKpiIndex.vue new file mode 100644 index 0000000000000000000000000000000000000000..5daa7a35cb6d48f957ab500aaef05ab44f6679ce --- /dev/null +++ b/src/views/ManagerKpiIndex.vue @@ -0,0 +1,139 @@ +<template> + <div class="container-fluid"> + <div class="row flex-nowrap"> + <Sidebar current_page = "About"></Sidebar> + <div class="col ps-md-2 pt-2"> + <Header></Header> + <div class="row p-2"> + <div class="col"> + <h1 class="text-blue">Daftar KPI</h1> + </div> + <div class="col"> + <!-- Ganti Path --> + <router-link :to="{ path: '/user/insert' }" style="text-decoration: none"> + <button class="btn float-end">Buat KPI</button> + </router-link> + </div> + </div> + <div class="row p-2"> + <div class="col-6 p-2"> + <select + v-model="filter" + class="form-select" + aria-label="Default select example" + > + <option selected value="">Semua</option> + <option v-for="p in periods" :key="p" :value="p.data">{{p.name}}</option> + </select> + </div> + </div> + <div class="row p-2"> + <Table2 + :endpoint="'kpis'" + :columns="columns" + :filter="filter" + :filter_column="'period_type'" + @edit-entry="editKpi" + @delete-entry="deleteKpi" + @detail-entry="detailKpi" + ></Table2> + </div> + </div> + </div> + </div> +</template> + +<script> + +import Table2 from "../components/table-2"; +import Header from "../components/header"; +import Sidebar from "../components/sidebar"; +import { HTTP } from "../http-common"; + + +export default { + name: "ManagerKpiIndex", + components: { + Header, + Sidebar, + Table2 + }, + data(){ + return{ + filter: "", + columns: { + Id: { + name : "Id", + data : "id", + hidden : true, + clickable : false + }, + Nama: { + name : "Nama", + data : "name", + hidden : false, + clickable : true + }, + Periode: { + name : "Periode", + data : "period_type", + hidden : false, + clickable : false + }, + }, + periods: [ + {name: "Harian", + data: "daily"}, + {name: "Mingguan", + data: "weekly"}, + {name: "Bulanan", + data: "monthly"}, + {name: "Tahunan", + data: "yearly"}, + {name: "Custom", + data: "custom"}, + ] + } + }, + methods: { + deleteKpi(id){ + if (confirm("Yakin akan menghapus KPI?")){ + HTTP.delete(`kpis/${id}`).catch(()=>{ + alert("Gagal Menghapus KPI") + }) + } + }, + editKpi(id){ + //routing page edit + console.log(id) + }, + detailKpi(id){ + //routing page detail + console.log(id) + } + } + +} +</script> + +<style scoped> +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + min-height: 100vh; + background-color: #fff; +} + +.btn { + background-color: #6992b4; + color: #f1f7fc; + border-radius: 15px; + padding: 7px; +} + + +</style> \ No newline at end of file diff --git a/src/views/Test.vue b/src/views/Test.vue new file mode 100644 index 0000000000000000000000000000000000000000..0c051c15e566227d5a3d0f81c2c9002f42a8ac4d --- /dev/null +++ b/src/views/Test.vue @@ -0,0 +1,68 @@ +<template> + <div class="container-fluid"> + <div class="row flex-nowrap"> + <Sidebar current_page = "About"></Sidebar> + <div class="col ps-md-2 pt-2"> + <Header></Header> + <input v-model="filter" type="text"> + <Table2 :endpoint="'kpis'" :columns="columns" :filter="filter" :filter_column="'name'" @edit-entry="print" @delete-entry="print" @detail-entry="print" ></Table2> + </div> + </div> + </div> +</template> + +<script> + +import Header from "../components/header" +import Sidebar from "../components/sidebar" +import Table2 from "../components/table-2"; + + +export default { + name: "Template", + components: { + Header, + Sidebar, + Table2 + }, + data(){ + return{ + filter: "", + columns: { + Id: { + name : "Id", + data : "id", + hidden : true, + clickable : false + }, + Nama: { + name : "Nama", + data : "name", + hidden : false, + clickable : true + }, + }, + } + }, + methods: { + print(id){ + console.log(id) + } + } +} +</script> + +<style scoped> +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + min-height: 100vh; + background-color: #fff; +} + + +</style> \ No newline at end of file