UI
This commit is contained in:
+43
-1
@@ -32,6 +32,48 @@ export default [
|
|||||||
text: 'NEW',
|
text: 'NEW',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: 'CNavTitle',
|
||||||
|
name: 'Ticketing',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'CNavGroup',
|
||||||
|
name: 'Ticketing',
|
||||||
|
to: '/ticket',
|
||||||
|
icon: 'cil-layers',
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
component: 'CNavItem',
|
||||||
|
name: 'Ticket',
|
||||||
|
to: '/tickets/ticket',
|
||||||
|
icon: 'cil-notes',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'CNavItem',
|
||||||
|
name: 'Ticket Type',
|
||||||
|
to: '/tickets/ticket-type',
|
||||||
|
icon: 'cil-list',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'CNavItem',
|
||||||
|
name: 'Ticket Materials',
|
||||||
|
to: '/tickets/ticket-materials',
|
||||||
|
icon: 'cil-file',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'CNavItem',
|
||||||
|
name: 'Approved',
|
||||||
|
to: '/tickets/approved',
|
||||||
|
icon: 'cil-check',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: 'CNavItem',
|
||||||
|
name: 'Rejected',
|
||||||
|
to: '/tickets/rejected',
|
||||||
|
icon: 'cil-ban',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: 'CNavTitle',
|
component: 'CNavTitle',
|
||||||
name: 'Theme',
|
name: 'Theme',
|
||||||
@@ -176,7 +218,7 @@ export default [
|
|||||||
color: 'danger',
|
color: 'danger',
|
||||||
text: 'PRO',
|
text: 'PRO',
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 129 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
@@ -1,7 +1,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { RouterLink } from 'vue-router'
|
import { RouterLink } from 'vue-router'
|
||||||
|
|
||||||
import { logo } from '@/assets/brand/logo'
|
// import { logo } from '@/assets/brand/logo'
|
||||||
|
import logo from '@/assets/images/Logo_big.png'
|
||||||
import { sygnet } from '@/assets/brand/sygnet'
|
import { sygnet } from '@/assets/brand/sygnet'
|
||||||
import { AppSidebarNav } from '@/components/AppSidebarNav.js'
|
import { AppSidebarNav } from '@/components/AppSidebarNav.js'
|
||||||
import { useSidebarStore } from '@/stores/sidebar.js'
|
import { useSidebarStore } from '@/stores/sidebar.js'
|
||||||
@@ -20,9 +21,27 @@ const sidebar = useSidebarStore()
|
|||||||
>
|
>
|
||||||
<CSidebarHeader class="border-bottom">
|
<CSidebarHeader class="border-bottom">
|
||||||
<RouterLink custom to="/" v-slot="{ href, navigate }">
|
<RouterLink custom to="/" v-slot="{ href, navigate }">
|
||||||
<CSidebarBrand v-bind="$attrs" as="a" :href="href" @click="navigate">
|
<!-- <CSidebarBrand v-bind="$attrs" as="a" :href="href" @click="navigate">
|
||||||
<CIcon custom-class-name="sidebar-brand-full" :icon="logo" :height="32" />
|
<CIcon custom-class-name="sidebar-brand-full" :icon="logo" :height="32" />
|
||||||
<CIcon custom-class-name="sidebar-brand-narrow" :icon="sygnet" :height="32" />
|
<CIcon custom-class-name="sidebar-brand-narrow" :icon="sygnet" :height="32" />
|
||||||
|
</CSidebarBrand> -->
|
||||||
|
<CSidebarBrand
|
||||||
|
v-bind="$attrs"
|
||||||
|
as="a"
|
||||||
|
:href="href"
|
||||||
|
@click="navigate"
|
||||||
|
class="d-flex align-items-center text-decoration-none"
|
||||||
|
>
|
||||||
|
<!-- Logo -->
|
||||||
|
<img :src="logo" alt="Logo" style="height: 60px; width: auto" />
|
||||||
|
|
||||||
|
<!-- Teks -->
|
||||||
|
<div class="ms-2 text-start">
|
||||||
|
<div class="fw-bold" style="font-size: 30px; line-height: 1; color: #ff8c00">
|
||||||
|
ManjaPro
|
||||||
|
</div>
|
||||||
|
<small class="fw-bold" style="font-size: 11px"> PT. Rhadika Data Nusantara </small>
|
||||||
|
</div>
|
||||||
</CSidebarBrand>
|
</CSidebarBrand>
|
||||||
</RouterLink>
|
</RouterLink>
|
||||||
<CCloseButton class="d-lg-none" dark @click="sidebar.toggleVisible()" />
|
<CCloseButton class="d-lg-none" dark @click="sidebar.toggleVisible()" />
|
||||||
|
|||||||
@@ -49,6 +49,43 @@ const routes = [
|
|||||||
/* webpackChunkName: "dashboard" */ '@/views/dashboard/Dashboard.vue'
|
/* webpackChunkName: "dashboard" */ '@/views/dashboard/Dashboard.vue'
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/tickets',
|
||||||
|
name: 'Tickets',
|
||||||
|
component: {
|
||||||
|
render() {
|
||||||
|
return h(resolveComponent('router-view'))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
redirect: '/tickets/ticket',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/tickets/ticket',
|
||||||
|
name: 'Ticket',
|
||||||
|
component: () => import('@/views/tickets/Ticket.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/tickets/ticket-type',
|
||||||
|
name: 'Ticket Type',
|
||||||
|
component: () => import('@/views/tickets/TicketType.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/tickets/ticket-materials',
|
||||||
|
name: 'Ticket Materials',
|
||||||
|
component: () => import('@/views/tickets/TicketMaterials.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/tickets/approved',
|
||||||
|
name: 'Approved',
|
||||||
|
component: () => import('@/views/tickets/Approved.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/tickets/rejected',
|
||||||
|
name: 'Rejected',
|
||||||
|
component: () => import('@/views/tickets/Rejected.vue'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/theme',
|
path: '/theme',
|
||||||
name: 'Theme',
|
name: 'Theme',
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import { ref } from 'vue'
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
export const useTicketStore = defineStore('ticket', () => {
|
||||||
|
const tickets = ref([
|
||||||
|
{
|
||||||
|
ticket_no: 'TKT-001',
|
||||||
|
tenant_id: 'tenant-01',
|
||||||
|
customer_id: 'CUST-1001',
|
||||||
|
deskripsi: 'Modem Merah',
|
||||||
|
kode_tiket: 'GGN',
|
||||||
|
status: 'Open',
|
||||||
|
prioritas: 'Low',
|
||||||
|
sla_minutes: '480',
|
||||||
|
ditugaskan_untuk: 'Joko',
|
||||||
|
created_by: 'admin@company.com',
|
||||||
|
approved_by: 'manager@company.com',
|
||||||
|
approved_at: '2026-06-20 09:00',
|
||||||
|
rejected_by: '-',
|
||||||
|
rejected_at: '-',
|
||||||
|
rejection_reason: '-',
|
||||||
|
assigned_at: '2026-06-20 09:30',
|
||||||
|
resolved_at: '-',
|
||||||
|
closed_at: '-',
|
||||||
|
created_at: '2026-06-20 08:00',
|
||||||
|
updated_at: '2026-06-20 09:30',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ticket_no: 'TKT-002',
|
||||||
|
tenant_id: 'tenant-01',
|
||||||
|
customer_id: 'CUST-1002',
|
||||||
|
deskripsi: 'Ganti Perangkat',
|
||||||
|
kode_tiket: 'ONU',
|
||||||
|
status: 'Open',
|
||||||
|
prioritas: 'Medium',
|
||||||
|
sla_minutes: '240',
|
||||||
|
ditugaskan_untuk: 'Bowo',
|
||||||
|
created_by: 'user@company.com',
|
||||||
|
approved_by: '-',
|
||||||
|
approved_at: '-',
|
||||||
|
rejected_by: 'supervisor@company.com',
|
||||||
|
rejected_at: '2026-06-22 10:00',
|
||||||
|
rejection_reason: 'Duplicate request',
|
||||||
|
assigned_at: '-',
|
||||||
|
resolved_at: '-',
|
||||||
|
closed_at: '-',
|
||||||
|
created_at: '2026-06-22 09:00',
|
||||||
|
updated_at: '2026-06-22 10:00',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ticket_no: 'TKT-003',
|
||||||
|
tenant_id: 'tenant-02',
|
||||||
|
customer_id: 'CUST-1003',
|
||||||
|
deskripsi: 'Perawatan Perangkat',
|
||||||
|
kode_tiket: 'MNT',
|
||||||
|
status: 'Closed',
|
||||||
|
prioritas: 'High',
|
||||||
|
sla_minutes: '720',
|
||||||
|
ditugaskan_untuk: 'Bahlil',
|
||||||
|
created_by: 'client@domain.com',
|
||||||
|
approved_by: 'manager@company.com',
|
||||||
|
approved_at: '2026-06-23 08:00',
|
||||||
|
rejected_by: '-',
|
||||||
|
rejected_at: '-',
|
||||||
|
rejection_reason: '-',
|
||||||
|
assigned_at: '2026-06-23 08:30',
|
||||||
|
resolved_at: '2026-06-24 15:00',
|
||||||
|
closed_at: '2026-06-24 16:00',
|
||||||
|
created_at: '2026-06-23 07:00',
|
||||||
|
updated_at: '2026-06-24 16:00',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const approvedTickets = ref([])
|
||||||
|
const rejectedTickets = ref([])
|
||||||
|
|
||||||
|
function addTicket(ticket) {
|
||||||
|
tickets.value.push({ ...ticket })
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTicket(index, ticket) {
|
||||||
|
tickets.value[index] = { ...ticket }
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteTicket(index) {
|
||||||
|
tickets.value.splice(index, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function approveTicket(index, approver) {
|
||||||
|
const now = new Date().toISOString().slice(0, 16).replace('T', ' ')
|
||||||
|
tickets.value[index].approved_by = approver
|
||||||
|
tickets.value[index].approved_at = now
|
||||||
|
tickets.value[index].status = 'Approved'
|
||||||
|
}
|
||||||
|
|
||||||
|
function rejectTicket(index, rejector, reason) {
|
||||||
|
const now = new Date().toISOString().slice(0, 16).replace('T', ' ')
|
||||||
|
tickets.value[index].rejected_by = rejector
|
||||||
|
tickets.value[index].rejected_at = now
|
||||||
|
tickets.value[index].rejection_reason = reason
|
||||||
|
tickets.value[index].status = 'Rejected'
|
||||||
|
}
|
||||||
|
|
||||||
|
return { tickets, addTicket, updateTicket, deleteTicket, approveTicket, rejectTicket }
|
||||||
|
})
|
||||||
+69
-5
@@ -1,8 +1,8 @@
|
|||||||
@use "@coreui/coreui/scss/coreui" as * with (
|
@use '@coreui/coreui/scss/coreui' as * with (
|
||||||
$enable-deprecation-messages: false
|
$enable-deprecation-messages: false
|
||||||
);
|
);
|
||||||
@use "@coreui/chartjs/scss/coreui-chartjs";
|
@use '@coreui/chartjs/scss/coreui-chartjs';
|
||||||
@use "vendors/simplebar";
|
@use 'vendors/simplebar';
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: var(--cui-tertiary-bg);
|
background-color: var(--cui-tertiary-bg);
|
||||||
@@ -12,7 +12,7 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
padding-inline: var(--cui-sidebar-occupy-start, 0) var(--cui-sidebar-occupy-end, 0);
|
padding-inline: var(--cui-sidebar-occupy-start, 0) var(--cui-sidebar-occupy-end, 0);
|
||||||
will-change: auto;
|
will-change: auto;
|
||||||
@include transition(padding .15s);
|
@include transition(padding 0.15s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header > .container-fluid,
|
.header > .container-fluid,
|
||||||
@@ -48,6 +48,37 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-nav .nav-link {
|
||||||
|
&.active {
|
||||||
|
color: #ff8c00;
|
||||||
|
background: rgba(255, 140, 0, 0.1);
|
||||||
|
|
||||||
|
.nav-icon {
|
||||||
|
color: #ff8c00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #ff8c00;
|
||||||
|
background: rgba(255, 140, 0, 0.08);
|
||||||
|
|
||||||
|
.nav-icon {
|
||||||
|
color: #ff8c00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-nav .nav-link {
|
||||||
|
&.active {
|
||||||
|
color: #ff8c00;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
color: #ff8c00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.header > .container-fluid + .container-fluid {
|
.header > .container-fluid + .container-fluid {
|
||||||
min-height: 3rem;
|
min-height: 3rem;
|
||||||
}
|
}
|
||||||
@@ -57,11 +88,44 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@include color-mode(dark) {
|
@include color-mode(dark) {
|
||||||
|
--cui-body-bg: #0d0e12;
|
||||||
|
--cui-body-bg-rgb: 13, 14, 18;
|
||||||
|
--cui-secondary-bg: #121318;
|
||||||
|
--cui-secondary-bg-rgb: 18, 19, 24;
|
||||||
|
--cui-tertiary-bg: #16171d;
|
||||||
|
--cui-tertiary-bg-rgb: 22, 23, 29;
|
||||||
|
--cui-sidebar-bg: #0d0e12;
|
||||||
|
--cui-sidebar-nav-link-active-bg: rgba(242, 133, 0, 0.1);
|
||||||
|
--cui-card-bg: #16171d;
|
||||||
|
--cui-card-cap-bg: #16171d;
|
||||||
|
--cui-card-border-color: #22242d;
|
||||||
|
--cui-border-color: #22242d;
|
||||||
|
--cui-border-color-translucent: rgba(34, 36, 45, 0.8);
|
||||||
|
--cui-dark-bg-subtle: #0d0e12;
|
||||||
|
--cui-primary: #f28500;
|
||||||
|
--cui-primary-rgb: 242, 133, 0;
|
||||||
|
--cui-link-color: #f28500;
|
||||||
|
--cui-link-color-rgb: 242, 133, 0;
|
||||||
|
--cui-table-bg: #16171d;
|
||||||
|
--cui-table-color: rgba(255, 255, 255, 0.87);
|
||||||
|
--cui-input-bg: #16171d;
|
||||||
|
--cui-input-color: rgba(255, 255, 255, 0.87);
|
||||||
|
--cui-input-border-color: #22242d;
|
||||||
|
--cui-list-group-bg: #16171d;
|
||||||
|
--cui-list-group-border-color: #22242d;
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: var(--cui-dark-bg-subtle);
|
background-color: var(--cui-body-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
--cui-footer-bg: var(--cui-body-bg);
|
--cui-footer-bg: var(--cui-body-bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-dark {
|
||||||
|
--cui-body-bg: #0d0e12;
|
||||||
|
--cui-secondary-bg: #121318;
|
||||||
|
--cui-tertiary-bg: #16171d;
|
||||||
|
--cui-border-color: #22242d;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useTicketStore } from '@/stores/ticket.js'
|
||||||
|
|
||||||
|
const store = useTicketStore()
|
||||||
|
|
||||||
|
const approvedTickets = computed(() =>
|
||||||
|
store.tickets.filter((t) => t.approved_by && t.approved_by !== '-')
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CRow>
|
||||||
|
<CCol :xs="12">
|
||||||
|
<CCard class="mb-4">
|
||||||
|
<CCardHeader>
|
||||||
|
<strong>Approved Tickets</strong>
|
||||||
|
</CCardHeader>
|
||||||
|
<CCardBody>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<CTable striped hover small>
|
||||||
|
<CTableHead>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="col">No</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Ticket No</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Kode Tiket</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Deskripsi</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Approved By</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Approved At</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Status</CTableHeaderCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableHead>
|
||||||
|
<CTableBody>
|
||||||
|
<CTableRow v-for="(item, index) in approvedTickets" :key="item.ticket_no">
|
||||||
|
<CTableHeaderCell scope="row">{{ index + 1 }}</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ item.ticket_no }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.kode_tiket }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.deskripsi }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.approved_by }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.approved_at }}</CTableDataCell>
|
||||||
|
<CTableDataCell>
|
||||||
|
<CBadge color="success">Approved</CBadge>
|
||||||
|
</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow v-if="approvedTickets.length === 0">
|
||||||
|
<CTableDataCell colspan="7" class="text-center">Tidak ada data approved tickets</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableBody>
|
||||||
|
</CTable>
|
||||||
|
</div>
|
||||||
|
</CCardBody>
|
||||||
|
</CCard>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useTicketStore } from '@/stores/ticket.js'
|
||||||
|
|
||||||
|
const store = useTicketStore()
|
||||||
|
|
||||||
|
const rejectedTickets = computed(() =>
|
||||||
|
store.tickets.filter((t) => t.rejected_by && t.rejected_by !== '-')
|
||||||
|
)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CRow>
|
||||||
|
<CCol :xs="12">
|
||||||
|
<CCard class="mb-4">
|
||||||
|
<CCardHeader>
|
||||||
|
<strong>Rejected Tickets</strong>
|
||||||
|
</CCardHeader>
|
||||||
|
<CCardBody>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<CTable striped hover small>
|
||||||
|
<CTableHead>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="col">No</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Ticket No</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Kode Tiket</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Deskripsi</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Rejected By</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Rejected At</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Alasan</CTableHeaderCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableHead>
|
||||||
|
<CTableBody>
|
||||||
|
<CTableRow v-for="(item, index) in rejectedTickets" :key="item.ticket_no">
|
||||||
|
<CTableHeaderCell scope="row">{{ index + 1 }}</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ item.ticket_no }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.kode_tiket }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.deskripsi }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.rejected_by }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.rejected_at }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.rejection_reason }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow v-if="rejectedTickets.length === 0">
|
||||||
|
<CTableDataCell colspan="7" class="text-center">Tidak ada data rejected tickets</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableBody>
|
||||||
|
</CTable>
|
||||||
|
</div>
|
||||||
|
</CCardBody>
|
||||||
|
</CCard>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,479 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
import { useTicketStore } from '@/stores/ticket.js'
|
||||||
|
|
||||||
|
const store = useTicketStore()
|
||||||
|
|
||||||
|
const ticketModal = ref(false)
|
||||||
|
const detailModal = ref(false)
|
||||||
|
const approveModal = ref(false)
|
||||||
|
const rejectModal = ref(false)
|
||||||
|
const editingIndex = ref(-1)
|
||||||
|
const isEdit = ref(false)
|
||||||
|
const form = reactive({
|
||||||
|
ticket_no: '',
|
||||||
|
tenant_id: '',
|
||||||
|
customer_id: '',
|
||||||
|
deskripsi: '',
|
||||||
|
kode_tiket: '',
|
||||||
|
status: 'Open',
|
||||||
|
prioritas: 'Low',
|
||||||
|
sla_minutes: '',
|
||||||
|
ditugaskan_untuk: '',
|
||||||
|
created_by: '',
|
||||||
|
approved_by: '',
|
||||||
|
approved_at: '',
|
||||||
|
rejected_by: '',
|
||||||
|
rejected_at: '',
|
||||||
|
rejection_reason: '',
|
||||||
|
assigned_at: '',
|
||||||
|
resolved_at: '',
|
||||||
|
closed_at: '',
|
||||||
|
created_at: '',
|
||||||
|
updated_at: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const emptyForm = () => ({
|
||||||
|
ticket_no: '',
|
||||||
|
tenant_id: '',
|
||||||
|
customer_id: '',
|
||||||
|
deskripsi: '',
|
||||||
|
kode_tiket: '',
|
||||||
|
status: 'Open',
|
||||||
|
prioritas: 'Low',
|
||||||
|
sla_minutes: '',
|
||||||
|
ditugaskan_untuk: '',
|
||||||
|
created_by: '',
|
||||||
|
approved_by: '',
|
||||||
|
approved_at: '',
|
||||||
|
rejected_by: '',
|
||||||
|
rejected_at: '',
|
||||||
|
rejection_reason: '',
|
||||||
|
assigned_at: '',
|
||||||
|
resolved_at: '',
|
||||||
|
closed_at: '',
|
||||||
|
created_at: '',
|
||||||
|
updated_at: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const detailItem = ref(null)
|
||||||
|
const approveIndex = ref(-1)
|
||||||
|
const rejectIndex = ref(-1)
|
||||||
|
const approverName = ref('')
|
||||||
|
const rejectorName = ref('')
|
||||||
|
const rejectReason = ref('')
|
||||||
|
|
||||||
|
function openAddModal() {
|
||||||
|
isEdit.value = false
|
||||||
|
editingIndex.value = -1
|
||||||
|
Object.assign(form, emptyForm())
|
||||||
|
ticketModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function openEditModal(index) {
|
||||||
|
isEdit.value = true
|
||||||
|
editingIndex.value = index
|
||||||
|
Object.assign(form, store.tickets[index])
|
||||||
|
ticketModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function openDetail(item) {
|
||||||
|
detailItem.value = item
|
||||||
|
detailModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveTicket() {
|
||||||
|
if (isEdit.value && editingIndex.value >= 0) {
|
||||||
|
store.updateTicket(editingIndex.value, form)
|
||||||
|
} else {
|
||||||
|
store.addTicket(form)
|
||||||
|
}
|
||||||
|
ticketModal.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteTicket(index) {
|
||||||
|
store.deleteTicket(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
function openApproveModal(index) {
|
||||||
|
approveIndex.value = index
|
||||||
|
approverName.value = ''
|
||||||
|
approveModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmApprove() {
|
||||||
|
if (approverName.value.trim()) {
|
||||||
|
store.approveTicket(approveIndex.value, approverName.value.trim())
|
||||||
|
approveModal.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openRejectModal(index) {
|
||||||
|
rejectIndex.value = index
|
||||||
|
rejectorName.value = ''
|
||||||
|
rejectReason.value = ''
|
||||||
|
rejectModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function confirmReject() {
|
||||||
|
if (rejectorName.value.trim() && rejectReason.value.trim()) {
|
||||||
|
store.rejectTicket(rejectIndex.value, rejectorName.value.trim(), rejectReason.value.trim())
|
||||||
|
rejectModal.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPending(item) {
|
||||||
|
return (
|
||||||
|
(item.approved_by === '-' || !item.approved_by) &&
|
||||||
|
(item.rejected_by === '-' || !item.rejected_by)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<CRow>
|
||||||
|
<CCol :xs="12">
|
||||||
|
<CCard class="mb-4">
|
||||||
|
<CCardHeader>
|
||||||
|
<strong>Ticket</strong>
|
||||||
|
<CButton color="primary" size="sm" class="float-end" @click="openAddModal">
|
||||||
|
+ Tambah Ticket
|
||||||
|
</CButton>
|
||||||
|
</CCardHeader>
|
||||||
|
<CCardBody>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<CTable striped hover small>
|
||||||
|
<CTableHead>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="col">No</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col" class="text-center">Ticket No</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col" class="text-center w-25"
|
||||||
|
>Kode Tiket</CTableHeaderCell
|
||||||
|
>
|
||||||
|
<CTableHeaderCell scope="col">Deskripsi</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Status</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Prioritas</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col" class="text-center"
|
||||||
|
>Ditugaskan Untuk</CTableHeaderCell
|
||||||
|
>
|
||||||
|
<CTableHeaderCell scope="col" class="text-center">Aksi</CTableHeaderCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableHead>
|
||||||
|
<CTableBody>
|
||||||
|
<CTableRow v-for="(item, index) in store.tickets" :key="item.ticket_no">
|
||||||
|
<CTableHeaderCell scope="row">{{ index + 1 }}</CTableHeaderCell>
|
||||||
|
<CTableDataCell class="text-center">{{ item.ticket_no }}</CTableDataCell>
|
||||||
|
<CTableDataCell class="text-center w-25">{{ item.kode_tiket }}</CTableDataCell>
|
||||||
|
<CTableDataCell>{{ item.deskripsi }}</CTableDataCell>
|
||||||
|
<CTableDataCell>
|
||||||
|
<CBadge
|
||||||
|
:color="
|
||||||
|
item.status === 'Closed'
|
||||||
|
? 'success'
|
||||||
|
: item.status === 'Approved'
|
||||||
|
? 'info'
|
||||||
|
: item.status === 'Rejected'
|
||||||
|
? 'dark'
|
||||||
|
: 'primary'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ item.status }}
|
||||||
|
</CBadge>
|
||||||
|
</CTableDataCell>
|
||||||
|
<CTableDataCell>
|
||||||
|
<CBadge
|
||||||
|
:color="
|
||||||
|
item.prioritas === 'High'
|
||||||
|
? 'danger'
|
||||||
|
: item.prioritas === 'Medium'
|
||||||
|
? 'warning'
|
||||||
|
: 'secondary'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ item.prioritas }}
|
||||||
|
</CBadge>
|
||||||
|
</CTableDataCell>
|
||||||
|
<CTableDataCell class="text-center">{{ item.ditugaskan_untuk }}</CTableDataCell>
|
||||||
|
<CTableDataCell class="text-center">
|
||||||
|
<CButton color="info" size="sm" class="me-1" @click="openDetail(item)"
|
||||||
|
>Detail</CButton
|
||||||
|
>
|
||||||
|
<CButton
|
||||||
|
v-if="isPending(item)"
|
||||||
|
color="success"
|
||||||
|
size="sm"
|
||||||
|
class="me-1"
|
||||||
|
@click="openApproveModal(index)"
|
||||||
|
>Setujui</CButton
|
||||||
|
>
|
||||||
|
<CButton
|
||||||
|
v-if="isPending(item)"
|
||||||
|
color="warning"
|
||||||
|
size="sm"
|
||||||
|
class="me-1"
|
||||||
|
@click="openRejectModal(index)"
|
||||||
|
>Tolak</CButton
|
||||||
|
>
|
||||||
|
<CButton color="warning" size="sm" class="me-1" @click="openEditModal(index)"
|
||||||
|
>Edit</CButton
|
||||||
|
>
|
||||||
|
<CButton color="danger" size="sm" @click="deleteTicket(index)">Hapus</CButton>
|
||||||
|
</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableBody>
|
||||||
|
</CTable>
|
||||||
|
</div>
|
||||||
|
</CCardBody>
|
||||||
|
</CCard>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
|
||||||
|
<!-- Form Modal (Add / Edit) -->
|
||||||
|
<CModal :visible="ticketModal" @close="ticketModal = false" size="lg" alignment="center">
|
||||||
|
<CModalHeader dismiss @close="ticketModal = false">
|
||||||
|
<CModalTitle>{{ isEdit ? 'Edit Ticket' : 'Tambah Ticket' }}</CModalTitle>
|
||||||
|
</CModalHeader>
|
||||||
|
<CModalBody>
|
||||||
|
<CForm>
|
||||||
|
<CRow class="mb-3">
|
||||||
|
<CCol :md="6">
|
||||||
|
<CFormLabel>Ticket No</CFormLabel>
|
||||||
|
<CFormInput v-model="form.ticket_no" />
|
||||||
|
</CCol>
|
||||||
|
<CCol :md="6">
|
||||||
|
<CFormLabel>Tenant ID</CFormLabel>
|
||||||
|
<CFormInput v-model="form.tenant_id" />
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow class="mb-3">
|
||||||
|
<CCol :md="6">
|
||||||
|
<CFormLabel>Customer ID</CFormLabel>
|
||||||
|
<CFormInput v-model="form.customer_id" />
|
||||||
|
</CCol>
|
||||||
|
<CCol :md="6">
|
||||||
|
<CFormLabel>Kode Tiket</CFormLabel>
|
||||||
|
<CFormInput v-model="form.kode_tiket" />
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow class="mb-3">
|
||||||
|
<CCol :md="12">
|
||||||
|
<CFormLabel>Deskripsi</CFormLabel>
|
||||||
|
<CFormTextarea v-model="form.deskripsi" rows="2"></CFormTextarea>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow class="mb-3">
|
||||||
|
<CCol :md="4">
|
||||||
|
<CFormLabel>Status</CFormLabel>
|
||||||
|
<CFormSelect v-model="form.status">
|
||||||
|
<option value="Open">Open</option>
|
||||||
|
<option value="In Progress">In Progress</option>
|
||||||
|
<option value="Closed">Closed</option>
|
||||||
|
</CFormSelect>
|
||||||
|
</CCol>
|
||||||
|
<CCol :md="4">
|
||||||
|
<CFormLabel>Prioritas</CFormLabel>
|
||||||
|
<CFormSelect v-model="form.prioritas">
|
||||||
|
<option value="Low">Low</option>
|
||||||
|
<option value="Medium">Medium</option>
|
||||||
|
<option value="High">High</option>
|
||||||
|
<option value="Critical">Critical</option>
|
||||||
|
</CFormSelect>
|
||||||
|
</CCol>
|
||||||
|
<CCol :md="4">
|
||||||
|
<CFormLabel>SLA (menit)</CFormLabel>
|
||||||
|
<CFormInput v-model="form.sla_minutes" type="number" />
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow class="mb-3">
|
||||||
|
<CCol :md="6">
|
||||||
|
<CFormLabel>Ditugaskan Untuk</CFormLabel>
|
||||||
|
<CFormInput v-model="form.ditugaskan_untuk" />
|
||||||
|
</CCol>
|
||||||
|
<CCol :md="6">
|
||||||
|
<CFormLabel>Created By</CFormLabel>
|
||||||
|
<CFormInput v-model="form.created_by" />
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
</CForm>
|
||||||
|
</CModalBody>
|
||||||
|
<CModalFooter>
|
||||||
|
<CButton color="secondary" @click="ticketModal = false">Batal</CButton>
|
||||||
|
<CButton color="primary" @click="saveTicket">Simpan</CButton>
|
||||||
|
</CModalFooter>
|
||||||
|
</CModal>
|
||||||
|
|
||||||
|
<!-- Approve Modal -->
|
||||||
|
<CModal :visible="approveModal" @close="approveModal = false" alignment="center">
|
||||||
|
<CModalHeader dismiss @close="approveModal = false">
|
||||||
|
<CModalTitle>Setujui Ticket</CModalTitle>
|
||||||
|
</CModalHeader>
|
||||||
|
<CModalBody>
|
||||||
|
<CForm>
|
||||||
|
<div class="mb-3">
|
||||||
|
<CFormLabel>Nama Leader / SPV</CFormLabel>
|
||||||
|
<CFormInput v-model="approverName" placeholder="Masukkan nama" />
|
||||||
|
</div>
|
||||||
|
</CForm>
|
||||||
|
</CModalBody>
|
||||||
|
<CModalFooter>
|
||||||
|
<CButton color="secondary" @click="approveModal = false">Batal</CButton>
|
||||||
|
<CButton color="success" @click="confirmApprove" :disabled="!approverName.trim()"
|
||||||
|
>Setujui</CButton
|
||||||
|
>
|
||||||
|
</CModalFooter>
|
||||||
|
</CModal>
|
||||||
|
|
||||||
|
<!-- Reject Modal -->
|
||||||
|
<CModal :visible="rejectModal" @close="rejectModal = false" alignment="center">
|
||||||
|
<CModalHeader dismiss @close="rejectModal = false">
|
||||||
|
<CModalTitle>Tolak Ticket</CModalTitle>
|
||||||
|
</CModalHeader>
|
||||||
|
<CModalBody>
|
||||||
|
<CForm>
|
||||||
|
<div class="mb-3">
|
||||||
|
<CFormLabel>Nama Leader / SPV</CFormLabel>
|
||||||
|
<CFormInput v-model="rejectorName" placeholder="Masukkan nama" />
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<CFormLabel>Alasan Penolakan</CFormLabel>
|
||||||
|
<CFormTextarea
|
||||||
|
v-model="rejectReason"
|
||||||
|
rows="3"
|
||||||
|
placeholder="Masukkan alasan"
|
||||||
|
></CFormTextarea>
|
||||||
|
</div>
|
||||||
|
</CForm>
|
||||||
|
</CModalBody>
|
||||||
|
<CModalFooter>
|
||||||
|
<CButton color="secondary" @click="rejectModal = false">Batal</CButton>
|
||||||
|
<CButton
|
||||||
|
color="warning"
|
||||||
|
@click="confirmReject"
|
||||||
|
:disabled="!rejectorName.trim() || !rejectReason.trim()"
|
||||||
|
>Tolak</CButton
|
||||||
|
>
|
||||||
|
</CModalFooter>
|
||||||
|
</CModal>
|
||||||
|
|
||||||
|
<!-- Detail Modal -->
|
||||||
|
<CModal :visible="detailModal" @close="detailModal = false" size="lg" alignment="center">
|
||||||
|
<CModalHeader dismiss @close="detailModal = false">
|
||||||
|
<CModalTitle>Detail Ticket</CModalTitle>
|
||||||
|
</CModalHeader>
|
||||||
|
<CModalBody>
|
||||||
|
<CTable bordered small v-if="detailItem">
|
||||||
|
<CTableBody>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell style="width: 30%">Ticket No</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.ticket_no }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Tenant ID</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.tenant_id }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Customer ID</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.customer_id }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Kode Tiket</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.kode_tiket }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Deskripsi</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.deskripsi }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Status</CTableHeaderCell>
|
||||||
|
<CTableDataCell>
|
||||||
|
<CBadge
|
||||||
|
:color="
|
||||||
|
detailItem.status === 'Closed'
|
||||||
|
? 'success'
|
||||||
|
: detailItem.status === 'Approved'
|
||||||
|
? 'info'
|
||||||
|
: detailItem.status === 'Rejected'
|
||||||
|
? 'dark'
|
||||||
|
: 'primary'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ detailItem.status }}
|
||||||
|
</CBadge>
|
||||||
|
</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Prioritas</CTableHeaderCell>
|
||||||
|
<CTableDataCell>
|
||||||
|
<CBadge
|
||||||
|
:color="
|
||||||
|
detailItem.prioritas === 'High'
|
||||||
|
? 'danger'
|
||||||
|
: detailItem.prioritas === 'Medium'
|
||||||
|
? 'warning'
|
||||||
|
: 'secondary'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ detailItem.prioritas }}
|
||||||
|
</CBadge>
|
||||||
|
</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>SLA (menit)</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.sla_minutes }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Ditugaskan Untuk</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.ditugaskan_untuk }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Created By</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.created_by }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Approved By</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.approved_by || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Approved At</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.approved_at || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Rejected By</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.rejected_by || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Rejected At</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.rejected_at || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Rejection Reason</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.rejection_reason || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Assigned At</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.assigned_at || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Resolved At</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.resolved_at || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Closed At</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.closed_at || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Created At</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.created_at || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell>Updated At</CTableHeaderCell>
|
||||||
|
<CTableDataCell>{{ detailItem.updated_at || '-' }}</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableBody>
|
||||||
|
</CTable>
|
||||||
|
</CModalBody>
|
||||||
|
<CModalFooter>
|
||||||
|
<CButton color="secondary" @click="detailModal = false">Tutup</CButton>
|
||||||
|
</CModalFooter>
|
||||||
|
</CModal>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<CRow>
|
||||||
|
<CCol :xs="12">
|
||||||
|
<CCard class="mb-4">
|
||||||
|
<CCardHeader> <strong>Ticket Materials</strong> </CCardHeader>
|
||||||
|
<CCardBody>
|
||||||
|
<CTable striped hover>
|
||||||
|
<CTableHead>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="col">#</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Material Name</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Ticket</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Quantity</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Unit</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Cost</CTableHeaderCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableHead>
|
||||||
|
<CTableBody>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="row">1</CTableHeaderCell>
|
||||||
|
<CTableDataCell>Cable CAT6</CTableDataCell>
|
||||||
|
<CTableDataCell>Network setup</CTableDataCell>
|
||||||
|
<CTableDataCell>100</CTableDataCell>
|
||||||
|
<CTableDataCell>Meters</CTableDataCell>
|
||||||
|
<CTableDataCell>$150.00</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="row">2</CTableHeaderCell>
|
||||||
|
<CTableDataCell>RJ45 Connector</CTableDataCell>
|
||||||
|
<CTableDataCell>Network setup</CTableDataCell>
|
||||||
|
<CTableDataCell>50</CTableDataCell>
|
||||||
|
<CTableDataCell>Pcs</CTableDataCell>
|
||||||
|
<CTableDataCell>$25.00</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="row">3</CTableHeaderCell>
|
||||||
|
<CTableDataCell>SSD 512GB</CTableDataCell>
|
||||||
|
<CTableDataCell>Hardware upgrade</CTableDataCell>
|
||||||
|
<CTableDataCell>2</CTableDataCell>
|
||||||
|
<CTableDataCell>Pcs</CTableDataCell>
|
||||||
|
<CTableDataCell>$200.00</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="row">4</CTableHeaderCell>
|
||||||
|
<CTableDataCell>RAM 16GB</CTableDataCell>
|
||||||
|
<CTableDataCell>Hardware upgrade</CTableDataCell>
|
||||||
|
<CTableDataCell>2</CTableDataCell>
|
||||||
|
<CTableDataCell>Pcs</CTableDataCell>
|
||||||
|
<CTableDataCell>$180.00</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableBody>
|
||||||
|
</CTable>
|
||||||
|
</CCardBody>
|
||||||
|
</CCard>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<CRow>
|
||||||
|
<CCol :xs="12">
|
||||||
|
<CCard class="mb-4">
|
||||||
|
<CCardHeader>
|
||||||
|
<strong>Ticket Type</strong>
|
||||||
|
</CCardHeader>
|
||||||
|
<CCardBody>
|
||||||
|
<CTable striped hover>
|
||||||
|
<CTableHead>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="col">#</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Name</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Description</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Color</CTableHeaderCell>
|
||||||
|
<CTableHeaderCell scope="col">Status</CTableHeaderCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableHead>
|
||||||
|
<CTableBody>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="row">1</CTableHeaderCell>
|
||||||
|
<CTableDataCell>Bug</CTableDataCell>
|
||||||
|
<CTableDataCell>Error or issue in the system</CTableDataCell>
|
||||||
|
<CTableDataCell>Red</CTableDataCell>
|
||||||
|
<CTableDataCell>Active</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="row">2</CTableHeaderCell>
|
||||||
|
<CTableDataCell>Enhancement</CTableDataCell>
|
||||||
|
<CTableDataCell>Request for new feature</CTableDataCell>
|
||||||
|
<CTableDataCell>Blue</CTableDataCell>
|
||||||
|
<CTableDataCell>Active</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="row">3</CTableHeaderCell>
|
||||||
|
<CTableDataCell>Support</CTableDataCell>
|
||||||
|
<CTableDataCell>General support request</CTableDataCell>
|
||||||
|
<CTableDataCell>Green</CTableDataCell>
|
||||||
|
<CTableDataCell>Active</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
<CTableRow>
|
||||||
|
<CTableHeaderCell scope="row">4</CTableHeaderCell>
|
||||||
|
<CTableDataCell>Question</CTableDataCell>
|
||||||
|
<CTableDataCell>General inquiry</CTableDataCell>
|
||||||
|
<CTableDataCell>Yellow</CTableDataCell>
|
||||||
|
<CTableDataCell>Inactive</CTableDataCell>
|
||||||
|
</CTableRow>
|
||||||
|
</CTableBody>
|
||||||
|
</CTable>
|
||||||
|
</CCardBody>
|
||||||
|
</CCard>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
</template>
|
||||||
Reference in New Issue
Block a user