useApi.ts
3.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import type { Ref } from 'vue'
import { useKeycloakStore } from '@/@core/stores/keycloakStore'
import { useAuthFetch } from '@/composables/useAuthFetch'
import keycloakInstance from '@/keycloak'
const BASE_URL = 'https://api.ui.ac.id'
const keycloakStore = useKeycloakStore()
// --- Interface Definitions ---
interface PasswordPayload {
oldPassword: string
newPassword: string
}
interface ApiErrorDetail {
message: string
details?: any
}
interface ApiErrorResponse {
success: false
code: number
error: ApiErrorDetail
message?: string
}
export function useCivitasApi() {
const loading = ref(false)
const error: Ref<string | null> = ref(null)
const errorResponse: Ref<ApiErrorResponse | null> = ref(null)
const fetchWithAuth = async <T = any>(
endpoint: string,
options: Record<string, any> = {},
) => {
loading.value = true
error.value = null
errorResponse.value = null
const url = `${BASE_URL}${
endpoint.startsWith('/') ? endpoint : `/${endpoint}`
}`
const responseData: Ref<T | null> = ref(null)
const errorRef: Ref<any | null> = ref(null)
const currentTime = Math.floor(Date.now() / 1000) // Current time in seconds
const tokenExp = keycloakInstance.tokenParsed?.exp ?? 0 // Token expiration time in seconds
const timeRemaining = tokenExp - currentTime // Time remaining in seconds
if (timeRemaining < 5) {
console.log('Token hampir expired, mencoba refresh...')
await keycloakStore.updateToken() // Refresh the token if it's about to expire
}
try {
const { data, error: fetchError } = await useAuthFetch<
T | ApiErrorResponse
>(url, options)
responseData.value = data as Ref<T | null>
errorRef.value = fetchError
// so up until this is work
if (fetchError.value) {
const errorData = fetchError.value.data as ApiErrorResponse
errorResponse.value = errorData
if (errorData?.error?.message) {
error.value = errorData.error.message
}
else if (errorData?.message) {
error.value = errorData.message
}
else {
error.value
= fetchError.value.message || 'An error occurred during fetch'
}
console.error('API call error details:', fetchError.value)
}
}
catch (err: any) {
error.value
= err.message || 'An unexpected network or setup error occurred'
console.error('API call exception:', err)
errorResponse.value = {
success: false,
code: 0,
error: { message: error.value || 'Unknown error' },
}
errorRef.value = { message: error.value }
}
finally {
loading.value = false
}
return {
response: responseData,
error: errorRef,
fetchError: error,
errorResponse,
}
}
// Grouped API endpoints
const api = {
staf: {
getStafData: (stafNIP: number) =>
fetchWithAuth(`/staf/${stafNIP}`),
},
dosen: {
getListDosen: () =>
fetchWithAuth('/listdosen'),
},
user: {
getRiwayatAkademik: () => fetchWithAuth('/my/ac'),
getProfile: () => fetchWithAuth('/me'),
getParkirAktif: () => fetchWithAuth('/my/parkir/aktif'),
getAttendance: () => fetchWithAuth('/my/hr/attendance'),
getLib: () => fetchWithAuth('/my/lib'),
changePassword: (payload: PasswordPayload) =>
fetchWithAuth('/my/pw', {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json',
},
}),
// getPublicPhoto: (kodeIdentitas: number) =>
// fetchWithAuth(`/public/photo/${kodeIdentitas}.jpg`),
},
}
return {
api,
loading,
error,
errorResponse,
}
}