core/app/composables/useGoogleAuth.ts

105 lines
2.9 KiB
TypeScript

interface GoogleCredentialResponse {
credential: string
select_by: string
}
declare global {
interface Window {
google?: {
accounts: {
id: {
initialize: (config: {
client_id: string
callback: (response: GoogleCredentialResponse) => void
auto_select?: boolean
}) => void
prompt: (callback?: (notification: { isNotDisplayed: () => boolean; isSkippedMoment: () => boolean }) => void) => void
renderButton: (parent: HTMLElement, config: Record<string, unknown>) => void
}
}
}
}
}
export function useGoogleAuth() {
const config = useRuntimeConfig()
const googleClientId = config.public.googleClientId as string
const loading = ref(false)
const error = ref<string | null>(null)
function loadGoogleScript(): Promise<void> {
return new Promise((resolve, reject) => {
if (window.google) {
resolve()
return
}
const existingScript = document.querySelector('script[src="https://accounts.google.com/gsi/client"]')
if (existingScript) {
existingScript.addEventListener('load', () => resolve(), { once: true })
return
}
const script = document.createElement('script')
script.src = 'https://accounts.google.com/gsi/client'
script.async = true
script.defer = true
script.onload = () => resolve()
script.onerror = () => reject(new Error('Gagal memuat Google Identity Services'))
document.head.appendChild(script)
})
}
async function signInWithGoogle(onResult?: (result: any) => void, onError?: (msg: string) => void) {
error.value = null
loading.value = true
try {
await loadGoogleScript()
if (!googleClientId) {
throw new Error('Google Client ID tidak dikonfigurasi')
}
window.google!.accounts.id.initialize({
client_id: googleClientId,
callback: async (response: GoogleCredentialResponse) => {
try {
const apiBase = config.public.apiBase
const result = await $fetch(`${apiBase}/auth/google-login`, {
method: 'POST',
body: { credential: response.credential },
})
onResult?.(result)
} catch (e: any) {
const detail = e?.data?.detail
const msg = detail?.message || 'Gagal masuk dengan Google'
error.value = msg
onError?.(msg)
} finally {
loading.value = false
}
},
auto_select: false,
})
window.google!.accounts.id.prompt((notification) => {
if (notification.isNotDisplayed()) {
loading.value = false
onError?.('Popup Google tidak dapat ditampilkan. Silakan coba metode lain.')
}
})
} catch (e: any) {
error.value = e.message
loading.value = false
onError?.(e.message)
}
}
return {
loading,
error,
signInWithGoogle,
}
}