import { FormEvent, useEffect, useState } from 'react'
import { ApiError, loginToJellyfin } from '../api/jellyfin'
import { useExternalConfig } from '../hooks/useExternalConfig'
import { Loader } from './Loader'
export const AuthForm = ({
onLogin,
}: {
onLogin: (authData: { serverUrl: string; token: string; userId: string; username: string }) => void
}) => {
const queryParams = new URLSearchParams(window.location.search)
const isDemo = queryParams.get('demo') === '1'
// If the URL is locked, we just use the default
const loadedURL = isDemo ? 'https://demo.jellyfin.org/stable' : localStorage.getItem('lastServerUrl') || ''
const [serverUrl, setServerUrl] = useState(loadedURL)
const { data: config, isPending: loadingConfiguration } = useExternalConfig()
const [username, setUsername] = useState(isDemo ? 'demo' : '')
const [password, setPassword] = useState('')
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
useEffect(() => {
if (!config) return
if (config.lockJellyfinUrl) setServerUrl(config.defaultJellyfinUrl || '')
else if (!serverUrl) setServerUrl(config.defaultJellyfinUrl || '')
}, [serverUrl, loadingConfiguration, config])
const handleSubmit = async (e: FormEvent) => {
e.preventDefault()
setLoading(true)
setError('')
// Pre-validate serverUrl
if (!serverUrl) {
setError('Please enter a server URL.')
setLoading(false)
return
}
let trimmedServerUrl = serverUrl.toLowerCase().replace(new RegExp('/+$'), '')
// Basic URL format check
const urlPattern = /^https?:\/\/.+/
if (!urlPattern.test(trimmedServerUrl)) {
setError('Invalid URL format. Use http:// or https:// followed by a valid address.')
setLoading(false)
return
}
try {
let result
try {
result = await loginToJellyfin(trimmedServerUrl, username, password)
} catch (firstErr) {
const formattedServerUrl = trimmedServerUrl.split('/').slice(0, 3).join('/')
if (trimmedServerUrl !== formattedServerUrl) {
trimmedServerUrl = formattedServerUrl
result = await loginToJellyfin(trimmedServerUrl, username, password)
} else {
throw firstErr
}
}
const { token, userId, username: fetchedUsername } = result!
// Save the serverUrl to localStorage on successful login
localStorage.setItem('lastServerUrl', trimmedServerUrl)
onLogin({ serverUrl: trimmedServerUrl, token, userId, username: fetchedUsername })
} catch (err) {
if (err instanceof ApiError) {
if (err.response) {
// HTTP status errors
if (err.response.status === 401) {
setError('Invalid credentials entered.')
} else if (err.response.status === 404) {
setError('Server not found. Please check the URL.')
} else if (err.response.status === 400) {
setError('Invalid request. Please check your input.')
} else {
setError(`Login failed: Server returned status ${err.response.status}.`)
}
} else {
// Setup errors (e.g., bad config)
setError('Login failed: Request setup error.')
}
} else {
setError('An unexpected error occurred. Please try again.')
}
} finally {
setLoading(false)
}
}
return loadingConfiguration ? (