add quick menu, header table

This commit is contained in:
2024-08-29 09:31:49 +07:00
parent b5babbfeac
commit 087bb1dc47
9 changed files with 624 additions and 5 deletions

View File

@@ -7,7 +7,7 @@
</v-list-item>
<!-- LEVEL 0 -->
<template v-for="(lev_0, i) in level_0" :key="lev_0.id" >
<v-list-item v-if="!level_1['p_' + lev_0.id] && lev_0.is_parent === 'N'" @click="goto(lev_0.url)" color="primary" rounded="lg" class="my-2">
<v-list-item v-if="!level_1['p_' + lev_0.id] && lev_0.is_parent === 'N'" @click="goto(lev_0)" color="primary" rounded="lg" class="my-2">
<v-list-item-title >{{ lev_0.name }}</v-list-item-title>
</v-list-item>
<v-list-group v-else :value="lev_0.name" >
@@ -18,7 +18,7 @@
</template>
<!-- LEVEL 1 -->
<template v-for="(lev_1, j) in level_1['p_' + lev_0.id]" :key="lev_1.id">
<v-list-item v-if="!level_2['p_' + lev_1.id] && lev_1.is_parent === 'N'" @click="goto(lev_1.url)" color="primary" rounded="lg" class="{'primary--text': activeItem === lev_2.id}">
<v-list-item v-if="!level_2['p_' + lev_1.id] && lev_1.is_parent === 'N'" @click="goto(lev_1)" color="primary" rounded="lg" class="{'primary--text': activeItem === lev_2.id}">
<v-list-item-title><v-icon>mdi-circle-small</v-icon>{{ lev_1.name }}</v-list-item-title>
</v-list-item>
<v-list-group v-else :value="lev_1.state" v-show="level_2['p_' + lev_1.id]" sub-group no-action >
@@ -29,7 +29,7 @@
</template>
<!-- LEVEL 2 -->
<template v-for="(lev_2, k) in level_2['p_' + lev_1.id]" :key="lev_2.id">
<v-list-item class="" @click="goto(lev_2.url)" color="primary" rounded="lg">
<v-list-item class="" @click="goto(lev_2)" color="primary" rounded="lg">
<v-list-item-title><v-icon>mdi-circle-small</v-icon>{{ lev_2.name }}</v-list-item-title>
</v-list-item>
</template>
@@ -73,10 +73,19 @@ export default {
this.$store.commit("system/update_drawer", val);
},
},
active_menu: {
get() {
return this.$store.state.system.active_menu;
},
set(menu) {
this.$store.commit("system/update_active_menu", menu);
}
}
},
methods: {
goto(url) {
console.log("menuju ke- ", url)
goto(item) {
console.log("menuju ke- ", item.url);
this.active_menu = item;
}
},
};

View File

@@ -0,0 +1,50 @@
<template>
<div class="rounded-xl bg-primary-lighten mx-2 my-2">
<v-container fluid style="overflow-x: auto; white-space: nowrap">
<v-btn
class="mr-2"
size="small"
:variant="active_menu.id === qmenu.id ? 'elevated' : 'outlined'"
rounded="xl"
color="primary-darken"
v-for="qmenu in qmenus"
@click="redirect(qmenu)"
>
{{ qmenu.name }}
</v-btn>
</v-container>
</div>
</template>
<script type="module">
export default {
name: "QuickAccessComponent",
mounted() {
this.$store.dispatch('system/loadQuickMenu');
},
data() {
return {
pressed: false,
}
},
computed: {
qmenus() {
return this.$store.state.system.quick_menu;
},
active_menu: {
get() {
return this.$store.state.system.active_menu;
},
set(menu) {
this.$store.commit("system/update_active_menu", menu);
}
}
},
methods: {
redirect(item) {
this.active_menu = item;
console.log("redirect url ", item.url);
}
},
}
</script>

View File

@@ -8,6 +8,8 @@ const store = {
menu_level_0: [],
menu_level_1: [],
menu_level_2: [],
quick_menu: [],
active_menu: {},
drawer: false,
bread_crumb: "",
search_error_message: "",
@@ -44,6 +46,12 @@ const store = {
update_drawer(state, payload) {
state.drawer = payload;
},
update_quick_menu(state, data) {
state.quick_menu = data;
},
update_active_menu(state, data) {
state.active_menu = data;
}
},
actions: {
async loadMenuData(context) {
@@ -76,6 +84,20 @@ const store = {
console.error('Error loading menu data:', error);
}
},
async loadQuickMenu(context) {
try {
let resp = await axios.get(URL);
if (resp.data.status != "OK") {
console.error('get api failed');
} else {
let item = resp.data.data;
if (item[1])
context.commit("update_quick_menu", item[1]['p_1'])
}
} catch (error) {
console.error('Error load quick menu data', error);
}
}
}
};
export default store

View File

@@ -0,0 +1,116 @@
<template>
<v-container fluid class="bg-white rounded-lg my-5">
<div class="bg-secondary-lighten rounded-lg pa-5 mb-5">
<v-row>
<v-col cols="11">
<h3>{{ $t('message.table.title') }}</h3>
</v-col>
<v-col cols="1" align="end">
<h3>6</h3>
</v-col>
</v-row>
</div>
<v-data-table
:headers="headers"
hide-default-footer
>
<template v-slot:headers="{ columns }">
<tr>
<template v-for="column in columns" :key="column.key">
<td :class="column.class" :style="{ width: column.width, textAlign: column.align }">
<span>{{ column.title }}</span>
</td>
</template>
</tr>
</template>
</v-data-table>
</v-container>
</template>
<script>
export default {
name: "contentcomp",
components: {},
mounted() {},
data() {
return {
menu: false,
visible: false,
headers : [
{
title: this.$t('message.table.h_no'),
align: "start",
sortable: false,
key: "name",
width: "5%",
class: "font-weight-bold",
},
{
title: this.$t('message.table.h_orderr'),
align: "center",
sortable: false,
key: "name",
width: "15%",
class: "font-weight-bold",
},
{
title: this.$t('message.table.h_pasien'),
align: "center",
sortable: false,
key: "name",
width: "20%",
class: "font-weight-bold",
},
{
title: this.$t('message.table.h_status'),
align: "center",
sortable: false,
key: "name",
width: "10%",
class: "font-weight-bold",
},
{
title: this.$t('message.table.h_sample'),
align: "center",
sortable: false,
key: "name",
width: "10%",
class: "font-weight-bold",
},
{
title: this.$t('message.table.h_proces'),
align: "center",
sortable: false,
key: "name",
width: "10%",
class: "font-weight-bold",
},
{
title: this.$t('message.table.h_resver'),
align: "center",
sortable: false,
key: "name",
width: "10%",
class: "font-weight-bold",
},
{
title: this.$t('message.table.h_resval'),
align: "center",
sortable: false,
key: "name",
width: "10%",
class: "font-weight-bold",
},
{
title: this.$t('message.table.h_printt'),
align: "center",
sortable: false,
key: "name",
width: "10%",
class: "font-weight-bold",
},
]
};
},
}
</script>

View File

@@ -0,0 +1,114 @@
<template>
<v-container fluid class="bg-white rounded-lg">
<v-row>
<v-col cols="2">
<v-menu
v-model="menu"
:close-on-content-click="false"
transition="scale-transition"
offset-y
min-width="auto"
max-width="290px"
>
<template v-slot:activator="{ props }">
<v-text-field
:model-value="formatDate()"
:label="$t('message.filter.date')"
prepend-inner-icon="mdi-calendar"
hide-details
readonly
variant="outlined"
v-bind="props"
></v-text-field>
</template>
<v-date-picker
hide-header
show-adjacent-months
rounded="lg"
color="primary"
v-model="date"
@update:modelValue="menu=false"
></v-date-picker>
</v-menu>
</v-col>
<v-col cols="2">
<v-text-field
:label="$t('message.filter.noreg')"
variant="outlined"
hide-details
append-inner-icon="mdi-magnify"
></v-text-field>
</v-col>
<v-col cols="2">
<v-autocomplete
:label="$t('message.filter.group')"
variant="outlined"
hide-details
menu-icon="mdi-chevron-down"
:items="temp_dropdown"
></v-autocomplete>
</v-col>
<v-col cols="5"></v-col>
<v-col cols="1">
<div
style="height: 100%; display: flex; align-items: center; justify-content: center;"
class="rounded-lg bg-primary pa-2 h-100 pointer"
>
<iconify-icon
style="font-size: 2rem;"
icon="fluent:search-20-regular"
></iconify-icon>
</div>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: "filtercomponent",
components: {},
mounted() {
},
data() {
return {
menu: false,
visible: false,
}
},
computed: {
date: {
get() {
return this.$store.state.stored.date;
},
set(val) {
this.$store.commit("setDate", val);
}
},
temp_dropdown: {
get() {
return this.$store.state.stored.temp_dropdown;
}
}
},
methods: {
formatDate() {
if (!this.date) return null;
return moment(this.date).format("DD-MM-YYYY");
},
deFormatedDate(date) {
if (!date) return null;
const [day, month, year] = date.split("-");
return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
}
},
}
</script>
<style scoped>
.pointer {
cursor: pointer;
}
</style>

View File

@@ -0,0 +1,42 @@
<template>
<v-app id="inspire">
<one-navbar></one-navbar>
<v-main>
<quick-menu></quick-menu>
<div class="pa-5 bg-primary-lighten mx-2 rounded-xl" style="height: 100%;">
<one-filter></one-filter>
<one-content></one-content>
</div>
</v-main>
</v-app>
</template>
<script type="module">
import NavbarComponent from "../../globalcomponent/one-navbar.vue";
import QuickMenu from "../../globalcomponent/quick-menu.vue";
import Content from "./content.vue";
import Filter from "./filter.vue";
export default {
name: "Status Pasien",
components: {
"one-navbar": NavbarComponent,
"quick-menu": QuickMenu,
"one-content": Content,
"one-filter": Filter,
},
mounted() {
},
data() {
return {
visible: false
}
},
computed: {
},
methods: {
},
}
</script>

125
status-patient/index.html Normal file
View File

@@ -0,0 +1,125 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Status Pasien</title>
<!-- Vuetify CSS -->
<link href="../css/vuetify.css" rel="stylesheet" />
<!-- Local Stylesheet for Fonts -->
<link rel="stylesheet" href="../css/styles.css" />
<link href="../css/materialdesignicon.css" rel="stylesheet" />
<script src="https://code.iconify.design/iconify-icon/2.1.0/iconify-icon.min.js"></script>
</head>
<body>
<div id="app"></div>
<!-- Moment -->
<script src="../libraries/moment.js"></script>
<!-- Vue.js -->
<!-- DEV -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<!-- PROD -->
<!-- <script src="../libraries/vue3.4.36.global.prod.js"></script> -->
<!-- Vuex -->
<script src="../libraries/vuex.js"></script>
<!-- Vuetify -->
<script src="../libraries/vuetify3.js"></script>
<!-- vue-i18n -->
<script src="../libraries/vue-i18n.global.js"></script>
<!-- Axios -->
<script src="../libraries/axios.js"></script>
<script src="../globalscript/theme.js"></script>
<script src="../globalscript/global.js"></script>
<!-- loader single file component -->
<script src="../libraries/vue3-sfc-loader.js"></script>
<script src="./language.js"></script>
<script type="module">
const { loadModule } = window["vue3-sfc-loader"];
import system from "../globalstore/globalstore.js";
import stored from "./modules/store.js";
// if (one_token()) {
// let usr = JSON.parse(localStorage.getItem("user"));
// location.replace("/" + usr.M_UserGroupDashboard);
// }
const options = {
moduleCache: {
vue: Vue,
},
getFile(url) {
return fetch(url).then((response) =>
response.ok ? response.text() : Promise.reject(response)
);
},
addStyle(textContent) {
const style = document.createElement("style");
style.textContent = textContent;
const ref = document.head.getElementsByTagName("style")[0] || null;
document.head.insertBefore(style, ref);
},
};
const messages = CustomMessages;
const browserLocale = navigator.language || navigator.languages[0];
const i18n = VueI18n.createI18n({
locale: browserLocale.startsWith("id") ? "id" : "en",
fallbackLocale: "en",
messages,
});
window.i18n = i18n;
moment.locale(browserLocale.startsWith("id") ? "id" : "en");
const store = Vuex.createStore({
modules: {
system: system,
stored: stored,
},
});
const app = Vue.createApp({
data() {
return {
visible: false,
bg_src: "",
loading: false,
};
},
template: `
<main-component></main-component>
`,
});
const vuetify = Vuetify.createVuetify({
theme: {
themes: CustomTheme,
},
});
app.use(store);
app.use(vuetify);
app.use(i18n);
const components = {
"main-component": "./components/main.vue",
};
Promise.all(
Object.entries(components).map(([name, path]) => {
return loadModule(path, options).then((component) => {
app.component(name, component);
});
})
)
.then(() => {
app.mount("#app");
})
.catch((error) => {
console.error("Error loading components:", error);
});
</script>
</body>
</html>

View File

@@ -0,0 +1,46 @@
var CustomMessages = {
en: {
message: {
filter: {
date: "Date",
noreg: "No. Reg / Name",
group: "Customer Group",
},
table: {
title: "TOTAL PATIENTS",
h_no: "NO",
h_orderr: "ORDER/JANJI HASIL",
h_pasien: "PATIENT",
h_status: "STATUS ORDER",
h_sample: "SAMP. COLLECT",
h_proces: "PROCESS",
h_resver: "RESULT VERIF",
h_resval: "RESULT VALID",
h_printt: "PRINT",
},
dobage: "Date of Birth and Age",
},
},
id: {
message: {
filter: {
date: "Tanggal",
noreg: "No. Reg / Nama",
group: "Kel. Pelanggan",
},
table: {
title: "TOTAL PASIEN",
h_no: "NO",
h_orderr: "ORDER/JANJI HASIL",
h_pasien: "PASIEN",
h_status: "STATUS ORDER",
h_sample: "SAMP. COLLECT",
h_proces: "PROSES",
h_resver: "RESULT VERIF",
h_resval: "RESULT VALID",
h_printt: "PRINT",
},
dobage: "Tanggal Lahir dan Umur",
},
},
};

View File

@@ -0,0 +1,95 @@
const store = {
state() {
return {
date: new Date(),
temp_dropdown: ["Lorem", "ipsum", "dolor", "sit", "amet"],
data: [
{
"xno": 1,
"xid": "132282",
"order_date": "27-08-2024 19:32",
"no_reg": "05600027LA",
"patient_name": "Ny IMELDA JANICE",
"company_name": "PASIEN KLINISI",
"mou_name": "PASIEN UMUM 2021",
"status_cito": "N",
"order_promise": "28-08-2024 12:00",
"details_order": [
{
"ids": "1626778,1626779",
"group_name": "LAB",
"group_id": "1",
"flag_nonlab": "N",
"status": "N"
}
],
"details_sampling": [
{
"ids": "1626778,1626779",
"group_name": "LAB",
"group_id": "1",
"flag_nonlab": "N",
"status": "N"
}
],
"details_verifications": [
{
"ids": "1626778,1626779",
"group_name": "LAB",
"group_id": "1",
"flag_nonlab": "N",
"status": "N"
}
],
"details_process": [
{
"ids": "1626778,1626779",
"group_name": "LAB",
"group_id": "1",
"flag_nonlab": "N",
"status": "N"
}
],
"details_result_verification": [
{
"ids": "1626778,1626779",
"group_name": "LAB",
"group_id": "1",
"flag_nonlab": "N",
"status": "N"
}
],
"details_result_validation": [
{
"ids": "1626778,1626779",
"group_name": "LAB",
"group_id": "1",
"flag_nonlab": "N",
"status": "N"
}
],
"details_print": [
{
"ids": "1626778,1626779",
"group_name": "LAB",
"group_id": "1",
"flag_nonlab": "N",
"status": "N"
}
],
"no_reg_ext": "056G3C17LA"
}
]
}
},
mutations: {
setDate(state, date) {
state.date = date;
}
},
actions: {
}
}
export default store