feat: Implement the core Anjungan queue display system, including clinic room, entry, and counter queues, along with new stores, pages, and API endpoints.

This commit is contained in:
Fanrouver
2026-02-18 12:00:30 +07:00
parent f78bbea4b0
commit 7d07a4f00d
18 changed files with 38 additions and 38 deletions

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ export const usePermission = () => {
*/ */
const fetchPermission = async (path: string) => { const fetchPermission = async (path: string) => {
const { group, role } = parsePath(path); const { group, role } = parsePath(path);
const url = `http://10.10.150.131:8080/api/permission?roles=${role}&groups=${group}`; const url = `http://10.10.123.140:8089/api/permission?roles=${role}&groups=${group}`;
const { data, error } = await useFetch(url, { const { data, error } = await useFetch(url, {
method: "GET", method: "GET",
+5 -5
View File
@@ -73,16 +73,16 @@ export default defineNuxtConfig({
oauthStateDurationMinutes: parseInt(process.env.OAUTH_STATE_DURATION_MINUTES || '10', 10), oauthStateDurationMinutes: parseInt(process.env.OAUTH_STATE_DURATION_MINUTES || '10', 10),
// External API // External API
externalApiBaseUrl: process.env.EXTERNAL_API_BASE_URL || 'http://10.10.150.100:8084', externalApiBaseUrl: process.env.EXTERNAL_API_BASE_URL || 'http://10.10.123.135:8084',
externalApiTimeout: parseInt(process.env.EXTERNAL_API_TIMEOUT || '10000', 10), externalApiTimeout: parseInt(process.env.EXTERNAL_API_TIMEOUT || '10000', 10),
public: { public: {
authUrl: process.env.AUTH_ORIGIN, authUrl: process.env.AUTH_ORIGIN,
// authUrl: process.env.AUTH_ORIGIN || "http://10.10.150.175:3001", // authUrl: process.env.AUTH_ORIGIN || "http://10.10.150.175:3001",
// authUrl: process.env.AUTH_ORIGIN || "http://localhost:3001", // authUrl: process.env.AUTH_ORIGIN || "http://localhost:3001",
wsBaseUrl: process.env.WS_BASE_URL || 'ws://10.10.150.100:8084/api/v1/ws', wsBaseUrl: process.env.WS_BASE_URL || 'ws://10.10.123.135x:8084/api/v1/ws',
ekstrakExpertiseUrl: process.env.EKSTRAK_EXPERTISE_URL || 'http://10.10.123.218/ekstrakexpertise', ekstrakExpertiseUrl: process.env.EKSTRAK_EXPERTISE_URL || 'http://10.10.123.218/ekstrakexpertise',
verificationApiBaseUrl: process.env.VERIFICATION_API_BASE_URL || 'http://10.10.150.131:8089/api/v1', verificationApiBaseUrl: process.env.VERIFICATION_API_BASE_URL || 'http://10.10.123.140:8089/api/v1',
}, },
}, },
@@ -121,10 +121,10 @@ export default defineNuxtConfig({
routeRules: { routeRules: {
'/stats-api/**': { '/stats-api/**': {
proxy: 'http://10.10.150.100:8084/api/v1/**' proxy: 'http://10.10.123.135:8084/api/v1/**'
}, },
'/visit-api/**': { '/visit-api/**': {
proxy: 'http://10.10.150.100:8084/api/v1/**' proxy: 'http://10.10.123.135:8084/api/v1/**'
}, },
}, },
+2 -2
View File
@@ -485,7 +485,7 @@ const apiQuota = ref(null);
const fetchQuotaFromAPI = async () => { const fetchQuotaFromAPI = async () => {
try { try {
const response = await fetch( const response = await fetch(
"http://10.10.150.131:8089/api/v1/klinik/loket", "http://10.10.123.140:8089/api/v1/klinik/loket",
); );
const data = await response.json(); const data = await response.json();
@@ -1194,7 +1194,7 @@ const buatAntreanKlinikRuang = async (klinikRuang, ruang) => {
console.log("📤 Sending visit ticket to API:", visitTicketBody); console.log("📤 Sending visit ticket to API:", visitTicketBody);
const visitResponse = await fetch( const visitResponse = await fetch(
"http://10.10.150.100:8084/api/v1/visit/ticket/klinik", "http://10.10.123.135:8084/api/v1/visit/ticket/klinik",
{ {
method: "POST", method: "POST",
headers: { headers: {
+1 -1
View File
@@ -490,7 +490,7 @@ const fetchAllData = async () => {
// WebSocket configuration for Anjungan // WebSocket configuration for Anjungan
const config = useRuntimeConfig() const config = useRuntimeConfig()
const wsBaseUrl = config.public?.wsBaseUrl || 'ws://10.10.150.100:8084/api/v1/ws' const wsBaseUrl = config.public?.wsBaseUrl || 'ws://10.10.123.135:8084/api/v1/ws'
// Generate a unique session suffix (random ID) to fulfill "use different id" request // Generate a unique session suffix (random ID) to fulfill "use different id" request
// This ensures that even if the same screen is opened in multiple tabs, they have distinct client IDs // This ensures that even if the same screen is opened in multiple tabs, they have distinct client IDs
@@ -460,7 +460,7 @@ const updateTime = () => {
// WebSocket configuration for Anjungan // WebSocket configuration for Anjungan
const config = useRuntimeConfig() const config = useRuntimeConfig()
const wsBaseUrl = config.public?.wsBaseUrl || 'ws://10.10.150.100:8084/api/v1/ws' const wsBaseUrl = config.public?.wsBaseUrl || 'ws://10.10.123.135:8084/api/v1/ws'
// Generate a unique session suffix (random ID) // Generate a unique session suffix (random ID)
const uniqueSessionSuffix = ref(process.client ? Math.random().toString(36).substring(2, 8) : '') const uniqueSessionSuffix = ref(process.client ? Math.random().toString(36).substring(2, 8) : '')
+1 -1
View File
@@ -858,7 +858,7 @@ const updateTime = () => {
// WebSocket configuration (Placeholder) // WebSocket configuration (Placeholder)
const config = useRuntimeConfig() const config = useRuntimeConfig()
const wsBaseUrl = config.public?.wsBaseUrl || 'ws://10.10.150.100:8084/api/v1/ws' const wsBaseUrl = config.public?.wsBaseUrl || 'ws://10.10.123.135:8084/api/v1/ws'
const anjunganClientId = computed(() => { const anjunganClientId = computed(() => {
if (!loketId.value) return '' if (!loketId.value) return ''
return `anjungan-loket-${loketId.value}-${uniqueSessionSuffix.value}` return `anjungan-loket-${loketId.value}-${uniqueSessionSuffix.value}`
+1 -1
View File
@@ -1683,7 +1683,7 @@ const masterStore = useMasterStore();
const { printTicketFromPatient, isPrinting } = useThermalPrint(); const { printTicketFromPatient, isPrinting } = useThermalPrint();
const config = useRuntimeConfig(); const config = useRuntimeConfig();
const wsBaseUrl = const wsBaseUrl =
config.public?.wsBaseUrl || "ws://10.10.150.100:8084/api/v1/ws"; config.public?.wsBaseUrl || "ws://10.10.123.135:8084/api/v1/ws";
// TypeScript declaration for QRCode // TypeScript declaration for QRCode
declare global { declare global {
+1 -1
View File
@@ -181,7 +181,7 @@ onMounted(async () => {
<p class="text-sm text-gray-600 mb-4"> <p class="text-sm text-gray-600 mb-4">
Test and validate your current access token against the external API endpoint: Test and validate your current access token against the external API endpoint:
<code class="bg-blue-100 px-1 rounded text-blue-800">http://10.10.150.100:8084/api/v1/auth/me</code> <code class="bg-blue-100 px-1 rounded text-blue-800">http://10.10.123.135:8084/api/v1/auth/me</code>
</p> </p>
<!-- Validation Status --> <!-- Validation Status -->
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

+1 -1
View File
@@ -187,7 +187,7 @@ export default defineEventHandler(async (event) => {
if (primaryGroup) params.append('groups', primaryGroup); if (primaryGroup) params.append('groups', primaryGroup);
// Backend API URL - adjust this to match your backend // Backend API URL - adjust this to match your backend
const backendUrl = `http://10.10.150.131:8089/api/v1/permission?${params.toString()}`; const backendUrl = `http://10.10.123.140:8089/api/v1/permission?${params.toString()}`;
try { try {
console.log(`📡 Fetching permissions from: ${backendUrl}`); console.log(`📡 Fetching permissions from: ${backendUrl}`);
+1 -1
View File
@@ -9,7 +9,7 @@ export const useAntreanMasukScreenStore = defineStore('antreanMasukScreen', () =
id: 1, id: 1,
namaScreen: "Layar Antrean Masuk 1", namaScreen: "Layar Antrean Masuk 1",
nomorScreen: "AM-001", nomorScreen: "AM-001",
loket: [1, 2], // Array of loket IDs loket: [1, 2, 12, 14], // Array of loket IDs
}, },
{ {
id: 2, id: 2,
+1 -1
View File
@@ -773,7 +773,7 @@ export const useClinicStore = defineStore('clinic', () => {
try { try {
console.log(`🔄 Fetching clinics from API (Try ${retryCount + 1})...`); console.log(`🔄 Fetching clinics from API (Try ${retryCount + 1})...`);
const response = await fetch('http://10.10.150.131:8089/api/v1/klinik/reguler'); const response = await fetch('http://10.10.123.140:8089/api/v1/klinik/reguler');
if (!response.ok) { if (!response.ok) {
// Handle Rate Limiting with exponential backoff // Handle Rate Limiting with exponential backoff
+1 -1
View File
@@ -67,7 +67,7 @@ export const useDoctorStore = defineStore('doctor', () => {
for (let i = 0; i <= retries; i++) { for (let i = 0; i <= retries; i++) {
try { try {
data = await $fetch( data = await $fetch(
`http://10.10.150.131:8089/api/v1/dokter/${idklinik}`, `http://10.10.123.140:8089/api/v1/dokter/${idklinik}`,
{ timeout: 5000 } { timeout: 5000 }
); );
lastError = null; lastError = null;
+2 -2
View File
@@ -296,7 +296,7 @@ export const useLoketStore = defineStore('loket', () => {
try { try {
console.log(`🔄 [loketStore] Fetching loket configuration (Try ${retryCount + 1})...`); console.log(`🔄 [loketStore] Fetching loket configuration (Try ${retryCount + 1})...`);
const response = await fetch('http://10.10.150.131:8089/api/v1/klinik/loket'); const response = await fetch('http://10.10.123.140:8089/api/v1/klinik/loket');
if (!response.ok) { if (!response.ok) {
if (response.status === 429 && retryCount < 3) { if (response.status === 429 && retryCount < 3) {
@@ -435,7 +435,7 @@ export const useLoketStore = defineStore('loket', () => {
try { try {
console.log(`🔄 [loketStore] Fetching detail for loket ${loketId}...`); console.log(`🔄 [loketStore] Fetching detail for loket ${loketId}...`);
const response = await fetch(`http://10.10.150.131:8089/api/v1/loket/${loketId}`); const response = await fetch(`http://10.10.123.140:8089/api/v1/loket/${loketId}`);
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
+2 -2
View File
@@ -10,7 +10,7 @@ export const usePermissionStore = defineStore("permission", {
const parts = path.split("/").filter(Boolean); const parts = path.split("/").filter(Boolean);
const group = parts[1] || ""; const group = parts[1] || "";
const role = parts.at(-1)?.toLowerCase() || ""; const role = parts.at(-1)?.toLowerCase() || "";
const url = `http://10.10.150.131:8080/api/permission?roles=${role}&groups=${group}`; const url = `http://10.10.123.140:8089/api/permission?roles=${role}&groups=${group}`;
const { data } = await useFetch(url); const { data } = await useFetch(url);
this.data = data.value; this.data = data.value;
}, },
@@ -18,4 +18,4 @@ export const usePermissionStore = defineStore("permission", {
return this.data?.[action] === true; return this.data?.[action] === true;
}, },
}, },
}); });
+15 -15
View File
@@ -350,7 +350,7 @@ export const useQueueStore = defineStore('queue', () => {
}; };
const config = useRuntimeConfig(); const config = useRuntimeConfig();
const wsBaseUrl = config.public?.wsBaseUrl || "ws://10.10.150.100:8084/api/v1/ws"; const wsBaseUrl = config.public?.wsBaseUrl || "ws://10.10.123.135:8084/api/v1/ws";
const { connect, disconnect, sendViaPost, isConnected } = useWebSocket({ const { connect, disconnect, sendViaPost, isConnected } = useWebSocket({
url: wsBaseUrl, url: wsBaseUrl,
@@ -640,7 +640,7 @@ export const useQueueStore = defineStore('queue', () => {
try { try {
console.log(`🔄 [queueStore] Fetching patients for loket ${loketId}...`); console.log(`🔄 [queueStore] Fetching patients for loket ${loketId}...`);
const response = await fetch(`http://10.10.150.131:8089/api/v1/loket/${loketId}`); const response = await fetch(`http://10.10.123.140:8089/api/v1/loket/${loketId}`);
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
@@ -1620,7 +1620,7 @@ export const useQueueStore = defineStore('queue', () => {
// POST to external API when patient is called // POST to external API when patient is called
try { try {
fetch('http://10.10.150.131:8089/api/v1/tiket/update', { fetch('http://10.10.123.140:8089/api/v1/tiket/update', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -1731,7 +1731,7 @@ export const useQueueStore = defineStore('queue', () => {
// POST to external API when patient is called // POST to external API when patient is called
try { try {
const response = await fetch('http://10.10.150.131:8089/api/v1/tiket/update', { const response = await fetch('http://10.10.123.140:8089/api/v1/tiket/update', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -1789,7 +1789,7 @@ export const useQueueStore = defineStore('queue', () => {
// POST to external API when patient finishes at loket // POST to external API when patient finishes at loket
try { try {
fetch('http://10.10.150.131:8089/api/v1/tiket/selesai', { fetch('http://10.10.123.140:8089/api/v1/tiket/selesai', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -1860,7 +1860,7 @@ export const useQueueStore = defineStore('queue', () => {
// POST to external API and WAIT for response // POST to external API and WAIT for response
try { try {
const response = await fetch('http://10.10.150.131:8089/api/v1/tiket/update', { const response = await fetch('http://10.10.123.140:8089/api/v1/tiket/update', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -1952,7 +1952,7 @@ export const useQueueStore = defineStore('queue', () => {
// POST to external API and WAIT for response // POST to external API and WAIT for response
try { try {
const response = await fetch('http://10.10.150.131:8089/api/v1/tiket/update', { const response = await fetch('http://10.10.123.140:8089/api/v1/tiket/update', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -2035,7 +2035,7 @@ export const useQueueStore = defineStore('queue', () => {
// POST to external API to revert status to sedang diproses (status 8) // POST to external API to revert status to sedang diproses (status 8)
try { try {
fetch('http://10.10.150.131:8089/api/v1/tiket/update', { fetch('http://10.10.123.140:8089/api/v1/tiket/update', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -2095,7 +2095,7 @@ export const useQueueStore = defineStore('queue', () => {
// POST to external API when patient is being processed (sedang diproses) // POST to external API when patient is being processed (sedang diproses)
try { try {
fetch('http://10.10.150.131:8089/api/v1/tiket/update', { fetch('http://10.10.123.140:8089/api/v1/tiket/update', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
@@ -2658,7 +2658,7 @@ export const useQueueStore = defineStore('queue', () => {
case "selesai": case "selesai":
// Send API call to finish endpoint // Send API call to finish endpoint
try { try {
const apiUrl = 'http://10.10.150.100:8084/api/v1/visit/status/finish'; const apiUrl = 'http://10.10.123.135:8084/api/v1/visit/status/finish';
const requestBody = { const requestBody = {
patient_visit_healthcare_service_id: patient.healthcareServiceId, patient_visit_healthcare_service_id: patient.healthcareServiceId,
visit_code: patient.barcode || patient.visitCode, visit_code: patient.barcode || patient.visitCode,
@@ -2906,7 +2906,7 @@ export const useQueueStore = defineStore('queue', () => {
/** /**
* Register REGULER patient via API * Register REGULER patient via API
* POST to http://10.10.150.131:8089/api/v1/tiket/generate * POST to http://10.10.123.140:8089/api/v1/tiket/generate
*/ */
const registerRegulerPatientViaApi = async (clinic, paymentType, visitType = 'SEKARANG', isFastTrack = false, fastTrackData = null) => { const registerRegulerPatientViaApi = async (clinic, paymentType, visitType = 'SEKARANG', isFastTrack = false, fastTrackData = null) => {
try { try {
@@ -2988,7 +2988,7 @@ export const useQueueStore = defineStore('queue', () => {
console.log('📤 [queueStore] API Body:', body); console.log('📤 [queueStore] API Body:', body);
// 3. Call API // 3. Call API
const response = await fetch('http://10.10.150.131:8089/api/v1/tiket/generate', { const response = await fetch('http://10.10.123.140:8089/api/v1/tiket/generate', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@@ -3079,7 +3079,7 @@ export const useQueueStore = defineStore('queue', () => {
/** /**
* Check-in patient via API * Check-in patient via API
* POST to http://10.10.150.131:8089/api/v1/tiket/checkin * POST to http://10.10.123.140:8089/api/v1/tiket/checkin
*/ */
const checkInPatientViaApi = async (barcode) => { const checkInPatientViaApi = async (barcode) => {
try { try {
@@ -3095,7 +3095,7 @@ export const useQueueStore = defineStore('queue', () => {
console.log('📤 [queueStore] Check-in API Body:', body); console.log('📤 [queueStore] Check-in API Body:', body);
const response = await fetch('http://10.10.150.131:8089/api/v1/tiket/checkin', { const response = await fetch('http://10.10.123.140:8089/api/v1/tiket/checkin', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
@@ -3368,4 +3368,4 @@ export const useQueueStore = defineStore('queue', () => {
return value; return value;
}, },
}, },
}); });
+1 -1
View File
@@ -336,7 +336,7 @@ export const useRuangStore = defineStore('ruang', () => {
const allClinics = clinicStore.clinics; const allClinics = clinicStore.clinics;
// 2. Fetch room data from new API // 2. Fetch room data from new API
const response = await fetch('http://10.10.150.131:8089/api/v1/loket/ruang'); const response = await fetch('http://10.10.123.140:8089/api/v1/loket/ruang');
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
} }
+1 -1
View File
@@ -16,7 +16,7 @@ export const useVerificationStore = defineStore('verification', () => {
const url = config.public.verificationApiBaseUrl; const url = config.public.verificationApiBaseUrl;
if (!url) { if (!url) {
console.warn('verificationApiBaseUrl is undefined in runtimeConfig, using fallback'); console.warn('verificationApiBaseUrl is undefined in runtimeConfig, using fallback');
return 'http://10.10.150.131:8089/api/v1'; return 'http://10.10.123.140:8089/api/v1';
} }
return url; return url;
}; };