-
- Show
-
- entries
+
+
+
+
-
-
-
-
-
- Hapus Data
- Apakah Anda yakin ingin menghapus data ini?
-
- Batal
- Hapus
-
+
+
+
+
+
+ {{ item.kodeKlinik }}
+
+ {{ item.namaKlinik }}
+
+
+
+
+ mdi-pencil
+ Edit
+
+
+ mdi-delete
+ Delete
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.raw.kode }}
+
+ {{ item.raw.nama }}
+
+
+
+ Masukan Kode Ruang 2 Huruf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mdi-numeric-{{ index + 1 }}-circle
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Masukan Nomor Screen Ruang
+
+
+
+
+ mdi-delete
+
+
+
+
+
+
+ mdi-information
+ Klik "Add Ruang" untuk menambahkan ruangan
+
+
+
+
+
+
+
+
+
+
+
+
+ mdi-close
+ Cancel
+
+
+ mdi-content-save
+ Submit
+
+
+
+
+
+
+.ruang-list {
+ background: #f8f9fa;
+ border: 2px solid #e8f5e9;
+ border-radius: 12px;
+ padding: 16px;
+}
+
+.ruang-item {
+ background: white;
+ padding: 16px;
+ border-radius: 8px;
+ margin-bottom: 12px;
+ border: 1px solid #e0e0e0;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.05);
+}
+
+.ruang-item:last-child {
+ margin-bottom: 0;
+}
+
+.ruang-number {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: linear-gradient(135deg, #4caf50 0%, #388e3c 100%);
+ color: white;
+ padding: 8px;
+ border-radius: 8px;
+ font-weight: 600;
+ font-size: 14px;
+}
+
\ No newline at end of file
diff --git a/pages/Setting/MasterLoket.vue b/pages/Setting/MasterLoket.vue
new file mode 100644
index 0000000..a5e1d26
--- /dev/null
+++ b/pages/Setting/MasterLoket.vue
@@ -0,0 +1,176 @@
+
+
+
+
+
+
+
+ Edit
+
+
+ Delete
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pages/Setting/TambahLoket.vue b/pages/Setting/TambahLoket.vue
new file mode 100644
index 0000000..6d85098
--- /dev/null
+++ b/pages/Setting/TambahLoket.vue
@@ -0,0 +1,310 @@
+
+
+
+
+
+
+
+
+
+
+
+
Informasi Loket
+
+
+
+
+
+
+
+
+
+
+
+
+
Konfigurasi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mdi-content-save
+ Simpan Loket
+
+
+ mdi-close
+ Batal
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/server/api/auth/session.get.ts b/server/api/auth/session.get.ts
index b809c6c..0d6d81b 100644
--- a/server/api/auth/session.get.ts
+++ b/server/api/auth/session.get.ts
@@ -2,94 +2,93 @@
// Helper function to safely decode the JWT payload (Access Token or ID Token)
const decodeTokenPayload = (token: string | undefined): any | null => {
- if (!token) return null;
- try {
- // Tokens are base64 encoded and separated by '.'
- const parts = token.split('.');
- if (parts.length < 2) return null; // Not a valid JWT format
-
- const payloadBase64 = parts[1];
-
- // Decode from base64 and parse the JSON
- // Note: Using Buffer.from is standard in Node.js server environments (like Nitro/H3)
- return JSON.parse(Buffer.from(payloadBase64, 'base64').toString());
- } catch (e) {
- console.error('โ Failed to decode token payload:', e);
- return null;
- }
+ if (!token) return null;
+ try {
+ // Tokens are base64 encoded and separated by '.'
+ const parts = token.split(".");
+ if (parts.length < 2) return null; // Not a valid JWT format
+
+ const payloadBase64 = parts[1];
+
+ // Decode from base64 and parse the JSON
+ // Note: Using Buffer.from is standard in Node.js server environments (like Nitro/H3)
+ return JSON.parse(Buffer.from(payloadBase64, "base64").toString());
+ } catch (e) {
+ console.error("โ Failed to decode token payload:", e);
+ return null;
+ }
};
// --- START OF THE SINGLE EXPORT DEFAULT HANDLER ---
export default defineEventHandler(async (event) => {
- console.log('๐ Session endpoint called');
+ console.log("๐ Session endpoint called");
- const sessionCookie = getCookie(event, 'user_session');
- console.log('๐ช Session cookie exists:', !!sessionCookie);
+ const sessionCookie = getCookie(event, "user_session");
+ console.log("๐ช Session cookie exists:", !!sessionCookie);
- if (!sessionCookie) {
- console.log('โ No session cookie found');
- throw createError({
- statusCode: 401,
- statusMessage: 'No session cookie found'
- });
+ if (!sessionCookie) {
+ console.log("โ No session cookie found");
+ throw createError({
+ statusCode: 401,
+ statusMessage: "No session cookie found",
+ });
+ }
+
+ try {
+ const session = JSON.parse(sessionCookie);
+ console.log("๐ Session parsed successfully");
+
+ const isExpired = Date.now() > session.expiresAt;
+ console.log(" ย Is Expired:", isExpired);
+
+ // Check if the token has expired
+ if (isExpired) {
+ console.log("โฐ Session has expired, clearing cookie");
+ deleteCookie(event, "user_session");
+ throw createError({
+ statusCode: 401,
+ statusMessage: "Session expired",
+ });
}
- try {
- const session = JSON.parse(sessionCookie);
- console.log('๐ Session parsed successfully');
-
- const isExpired = Date.now() > session.expiresAt;
- console.log(' ย Is Expired:', isExpired);
+ // Decode tokens and prepare the enhanced response data
+ const idTokenPayload = decodeTokenPayload(session.idToken);
+ const accessTokenPayload = decodeTokenPayload(session.accessToken);
- // Check if the token has expired
- if (isExpired) {
- console.log('โฐ Session has expired, clearing cookie');
- deleteCookie(event, 'user_session');
- throw createError({
- statusCode: 401,
- statusMessage: 'Session expired'
- });
- }
+ // Final response object for the frontend debug page
+ const sessionResponse = {
+ // Basic User Info
+ user: session.user,
- // Decode tokens and prepare the enhanced response data
- const idTokenPayload = decodeTokenPayload(session.idToken);
- const accessTokenPayload = decodeTokenPayload(session.accessToken);
-
- // Final response object for the frontend debug page
- const sessionResponse = {
- // Basic User Info
- user: session.user,
-
- // Raw Tokens
- idToken: session.idToken,
- accessToken: session.accessToken,
- refreshToken: session.refreshToken,
-
- // Session Timestamps
- expiresAt: session.expiresAt,
- createdAt: session.createdAt,
+ // Raw Tokens
+ idToken: session.idToken,
+ accessToken: session.accessToken,
+ refreshToken: session.refreshToken,
- // Parsed Payloads
- idTokenPayload: idTokenPayload,
- accessTokenPayload: accessTokenPayload,
+ // Session Timestamps
+ expiresAt: session.expiresAt,
+ createdAt: session.createdAt,
- // Raw Session Data (for Debug section)
- fullSessionObject: session,
-
- status: 'authenticated',
- };
+ // Parsed Payloads
+ idTokenPayload: idTokenPayload,
+ accessTokenPayload: accessTokenPayload,
- console.log('โ
Session is valid, returning full session data');
- return sessionResponse;
+ // Raw Session Data (for Debug section)
+ fullSessionObject: session,
- } catch (parseError) {
- console.error('โ Failed to parse session cookie:', parseError);
- // If JSON parsing fails or any other error occurs, the session is invalid
- deleteCookie(event, 'user_session');
- throw createError({
- statusCode: 401,
- statusMessage: 'Invalid session data'
- });
- }
+ status: "authenticated",
+ };
+
+ console.log("โ
Session is valid, returning full session data");
+ return sessionResponse;
+ } catch (parseError) {
+ console.error("โ Failed to parse session cookie:", parseError);
+ // If JSON parsing fails or any other error occurs, the session is invalid
+ deleteCookie(event, "user_session");
+ throw createError({
+ statusCode: 401,
+ statusMessage: "Invalid session data",
+ });
+ }
});
-// --- END OF THE SINGLE EXPORT DEFAULT HANDLER ---
\ No newline at end of file
+// --- END OF THE SINGLE EXPORT DEFAULT HANDLER ---
diff --git a/stores/navItems.ts b/stores/navItems.ts
index 09092b2..069fbae 100644
--- a/stores/navItems.ts
+++ b/stores/navItems.ts
@@ -1,59 +1,55 @@
// stores/navItems.ts
import { defineStore } from 'pinia';
import { useLocalStorage } from '@vueuse/core';
+import { computed } from 'vue'; // Import computed dari Vue
interface NavItem {
id: number;
- name: string;
- path: string;
+ name: string; // Menggantikan 'title'
+ path: string; // Menggantikan 'to'
icon: string;
children?: NavItem[];
+ badge?: string; // Tambahkan properti badge
}
// Initial default navigation items
const defaultNavItems: NavItem[] = [
{ id: 1, name: "Dashboard", icon: "mdi-view-dashboard", path: "/dashboard" },
- // Add other main menu items
- { id: 2, name: "Loket Admin", icon: "mdi-account-supervisor", path: "/LoketAdmin" },
- { id: 3, name: "Ranap Admin", icon: "mdi-bed", path: "/RanapAdmin" },
- { id: 4, name: "Klinik Admin", icon: "mdi-hospital-box", path: "/KlinikAdmin" },
- { id: 5, name: "Klinik Ruang Admin", icon: "mdi-hospital-marker", path: "/KlinikRuangAdmin" },
+ { id: 2, name: "Verifikasi Akun", icon: "mdi-account-check-outline", path:"/VerifikasiAkun" },
+ {
+ id: 3,
+ name: "Check In",
+ icon: "mdi-file-document-edit-outline",
+ path: "/CheckIn"
+ // badge: "3",
+ },
+ { id: 4, name: "Admin Loket", icon: "mdi-account-supervisor-outline", path: "/AdminLoket" },
+ { id: 5, name: "Admin Klinik", icon: "mdi-text-box-plus-outline", path: "/AdminKlinik" },
+ { id: 6, name: "Admin Penunjang", icon: "mdi-plus-box-outline", path: "/AdminPenunjang" },
+ { id: 7, name: "Buat Antrean", icon: "mdi-account-multiple-plus-outline", path: "/BuatAntrean" },
+ { id: 8, name: "Monitoring Pasien", icon: "mdi-account-group-outline", path: "/data-pasien" },
{
- id: 6,
- name: "Anjungan",
- icon: "mdi-account-box-multiple",
+ id: 9,
+ name: "Layar Informasi",
+ icon: "mdi-monitor-multiple",
path: "",
children: [
- { id: 7, name: "Anjungan", path: "/Anjungan/Anjungan", icon: "mdi-account-box" },
- { id: 8, name: "Admin Anjungan", path: "/Anjungan/AdminAnjungan", icon: "mdi-account-cog" },
+ { id: 10, name: "Anjungan", path: "/anjungan/anjungan", icon: "mdi-circle-small" },
+ { id: 11, name: "Klinik Ruang", path: "/anjungan/AntrianKlinik", icon: "mdi-circle-small" },
],
},
- { id: 9, name: "Fast Track", icon: "mdi-clock-fast", path: "/FastTrack" },
- { id: 10, name: "Data Pasien", icon: "mdi-account-multiple", path: "/DataPasien" },
- {
- id: 11,
- name: "Screen",
- icon: "mdi-monitor",
+ {
+ id: 12,
+ name: "Master Data",
+ icon: "mdi-cog-outline",
path: "",
children: [
- { id: 12, name: "Antrian Masuk 1", path: "/Screen/Antrian Masuk 1", icon: "mdi-monitor" },
- { id: 13, name: "Antrian Masuk 2", path: "/Screen/Antrian Masuk 2", icon: "mdi-monitor" },
- // ... more screen pages
- ],
- },
- { id: 14, name: "List Pasien", icon: "mdi-format-list-bulleted", path: "/ListPasien" },
- {
- id: 15 ,
- name: "Setting",
- icon: "mdi-cog",
- path: "",
- children: [
- { id: 16, name: "Hak Akses", path: "/setting/HakAkses", icon: "mdi-shield-lock-outline" },
- { id: 17, name: "User Login", path: "/setting/UserLogin", icon: "mdi-account-circle" },
- { id: 18, name: "Master Loket", path: "/setting/MasterLoket", icon: "mdi-counter" },
- { id: 19, name: "Master Klinik", path: "/setting/MasterKlinik", icon: "mdi-hospital" },
- { id: 20, name: "Master Klinik Ruang", path: "/setting/MasterKlinikRuang", icon: "mdi-hospital-box" },
- { id: 21, name: "Screen", path: "/setting/Screen", icon: "mdi-monitor" },
+ { id: 13, name: "Hak Akses", path: "/setting/hak-akses", icon: "mdi-circle-small" },
+ { id: 14, name: "User Login", path: "/setting/user-login", icon: "mdi-circle-small" },
+ { id: 15, name: "Master Loket", path: "/setting/masterloket", icon: "mdi-circle-small" },
+ { id: 16, name: "Master Klinik", path: "/setting/masterklinik", icon: "mdi-circle-small" },
+ { id: 17, name: "Master Klinik Ruang", path: "/setting/masterklinikruang", icon: "mdi-circle-small" },
+ { id: 18, name: "Screen", path: "/setting/screen", icon: "mdi-circle-small" },
],
},
];
@@ -61,8 +57,18 @@ const defaultNavItems: NavItem[] = [
export const useNavItemsStore = defineStore('navItems', () => {
const navItems = useLocalStorage
('navItems', defaultNavItems);
+ // === GETTER PENTING UNTUK MENGATASI MASALAH 'NULL' DI AWAL ===
+ const getNavItems = computed(() => {
+ // Jika navItems.value null, undefined, atau bukan array yang valid,
+ // kembalikan array default.
+ if (!Array.isArray(navItems.value) || navItems.value === null || navItems.value === undefined) {
+ return defaultNavItems;
+ }
+ return navItems.value;
+ });
+ // =============================================================
+
function updateNavItems(newItems: NavItem[]) {
- // This will update the local storage and the state
navItems.value = newItems.map((item, index) => ({
...item,
id: index + 1
@@ -76,6 +82,7 @@ export const useNavItemsStore = defineStore('navItems', () => {
return {
navItems,
+ getNavItems, // Diekspor untuk digunakan di Sidebar
updateNavItems,
addNavItem,
};