151 lines
4.6 KiB
TypeScript
151 lines
4.6 KiB
TypeScript
import type { UploadedFileDto } from '~~/.api-client'
|
|
import { useFileApi } from './useFileApi'
|
|
import { useLogger } from '../useLogger'
|
|
|
|
export interface UploadedFileMetadata {
|
|
fileId: string
|
|
filename: string
|
|
size: number
|
|
mimeType: string
|
|
uploadedAt: string
|
|
}
|
|
|
|
export function useFile() {
|
|
const fileApi = useFileApi()
|
|
const logger = useLogger().withTag('file')
|
|
const { t } = useI18n()
|
|
|
|
async function uploadFile(params: {
|
|
file: File
|
|
applicationFormId?: string
|
|
formElementReference: string
|
|
organizationId?: string
|
|
}): Promise<UploadedFileDto> {
|
|
try {
|
|
logger.debug('Uploading file:', params.file.name)
|
|
return await fileApi.uploadFile(params)
|
|
} catch (e: unknown) {
|
|
logger.error('Failed uploading file:', e)
|
|
|
|
// Enhanced error handling with user-friendly messages
|
|
if (e && typeof e === 'object' && 'status' in e) {
|
|
const error = e as { status: number }
|
|
if (error.status === 413) {
|
|
return Promise.reject(
|
|
new Error(
|
|
t('applicationForms.formElements.fileUpload.fileTooLarge', {
|
|
filename: params.file.name,
|
|
maxSize: '10MB'
|
|
})
|
|
)
|
|
)
|
|
} else if (error.status === 415) {
|
|
return Promise.reject(new Error(t('applicationForms.formElements.fileUpload.unsupportedType')))
|
|
}
|
|
}
|
|
|
|
return Promise.reject(new Error(t('applicationForms.formElements.fileUpload.uploadFailed')))
|
|
}
|
|
}
|
|
|
|
async function downloadFile(id: string, filename: string): Promise<void> {
|
|
try {
|
|
logger.debug('Downloading file:', id)
|
|
const blob = await fileApi.downloadFileContent(id)
|
|
|
|
// Create download link
|
|
const url = window.URL.createObjectURL(blob)
|
|
const link = document.createElement('a')
|
|
link.href = url
|
|
link.download = filename
|
|
document.body.appendChild(link)
|
|
link.click()
|
|
document.body.removeChild(link)
|
|
window.URL.revokeObjectURL(url)
|
|
} catch (e: unknown) {
|
|
logger.error('Failed downloading file:', e)
|
|
return Promise.reject(new Error(t('applicationForms.formElements.fileUpload.downloadFailed')))
|
|
}
|
|
}
|
|
|
|
function isViewableInBrowser(mimeType: string): boolean {
|
|
return mimeType === 'application/pdf' || mimeType.startsWith('image/')
|
|
}
|
|
|
|
function viewFile(id: string): void {
|
|
const url = fileApi.getFileViewUrl(id)
|
|
window.open(url, '_blank')
|
|
}
|
|
|
|
async function deleteFile(id: string): Promise<void> {
|
|
try {
|
|
logger.debug('Deleting file:', id)
|
|
return await fileApi.deleteFile(id)
|
|
} catch (e: unknown) {
|
|
logger.error('Failed deleting file:', e)
|
|
return Promise.reject(new Error(t('applicationForms.formElements.fileUpload.deleteFailed')))
|
|
}
|
|
}
|
|
|
|
async function associateFilesWithApplicationForm(applicationFormId: string, fileIds: string[]): Promise<void> {
|
|
try {
|
|
logger.debug('Associating files with application form:', { applicationFormId, fileIds })
|
|
return await fileApi.associateFilesWithApplicationForm(applicationFormId, fileIds)
|
|
} catch (e: unknown) {
|
|
logger.error('Failed associating files with application form:', e)
|
|
return Promise.reject(e)
|
|
}
|
|
}
|
|
|
|
function parseUploadedFiles(formOptionsValues: string[]): UploadedFileMetadata[] {
|
|
return formOptionsValues
|
|
.map((value) => {
|
|
try {
|
|
return JSON.parse(value) as UploadedFileMetadata
|
|
} catch {
|
|
return null
|
|
}
|
|
})
|
|
.filter((file): file is UploadedFileMetadata => file !== null)
|
|
}
|
|
|
|
function createFileMetadata(response: UploadedFileDto): UploadedFileMetadata {
|
|
return {
|
|
fileId: response.id,
|
|
filename: response.originalFilename,
|
|
size: response.size,
|
|
mimeType: response.mimeType,
|
|
uploadedAt: response.uploadedAt.toISOString()
|
|
}
|
|
}
|
|
|
|
function getFileIcon(mimeType: string): string {
|
|
if (mimeType.startsWith('image/')) return 'i-ph-image'
|
|
if (mimeType === 'application/pdf') return 'i-ph-file-pdf'
|
|
if (mimeType.includes('word')) return 'i-ph-file-doc'
|
|
if (mimeType.includes('zip')) return 'i-ph-file-zip'
|
|
return 'i-ph-file'
|
|
}
|
|
|
|
function formatFileSize(bytes: number): string {
|
|
if (bytes === 0) return '0 B'
|
|
const k = 1024
|
|
const sizes = ['B', 'KB', 'MB', 'GB']
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`
|
|
}
|
|
|
|
return {
|
|
uploadFile,
|
|
downloadFile,
|
|
viewFile,
|
|
deleteFile,
|
|
associateFilesWithApplicationForm,
|
|
parseUploadedFiles,
|
|
createFileMetadata,
|
|
getFileIcon,
|
|
formatFileSize,
|
|
isViewableInBrowser
|
|
}
|
|
}
|