Files
Inventory_frontend/app/composables/useSiteManagement.ts
2025-09-25 15:14:00 +02:00

317 lines
8.4 KiB
TypeScript

import { computed, onMounted, reactive, ref, watch } from 'vue'
import { navigateTo, useRoute } from '#imports'
import { useSites } from '~/composables/useSites'
import { useToast } from '~/composables/useToast'
import { useDocuments } from '~/composables/useDocuments'
import { getFileIcon } from '~/utils/fileIcons'
import { canPreviewDocument } from '~/utils/documentPreview'
type SiteForm = {
name: string
contactName: string
contactPhone: string
contactAddress: string
contactPostalCode: string
contactCity: string
}
type SiteDocument = {
id: string
name?: string
filename?: string
mimeType?: string
size?: number
path?: string
}
type SiteWithDocuments = {
id: string
name?: string
contactName?: string
contactPhone?: string
contactAddress?: string
contactPostalCode?: string
contactCity?: string
documents?: SiteDocument[]
machines?: Array<unknown>
}
export function useSiteManagement() {
const route = useRoute()
const { showError, showSuccess } = useToast()
const { sites, loading, loadSites, createSite, updateSite, deleteSite } = useSites()
const { uploadDocuments, deleteDocument, loadDocumentsBySite } = useDocuments()
const showAddSiteModal = ref(false)
const showEditSiteModal = ref(false)
const siteBeingEdited = ref<SiteWithDocuments | null>(null)
const newSite = reactive<SiteForm>({
name: '',
contactName: '',
contactPhone: '',
contactAddress: '',
contactPostalCode: '',
contactCity: ''
})
const editSiteForm = reactive<SiteForm>({
name: '',
contactName: '',
contactPhone: '',
contactAddress: '',
contactPostalCode: '',
contactCity: ''
})
const selectedFiles = ref<File[]>([])
const uploadingDocuments = ref(false)
const previewDocument = ref<SiteDocument | null>(null)
const previewVisible = ref(false)
const siteDocuments = computed(() => siteBeingEdited.value?.documents || [])
const documentIcon = (doc: SiteDocument) =>
getFileIcon({ name: doc.filename || doc.name, mime: doc.mimeType })
const resetNewSite = () => {
newSite.name = ''
newSite.contactName = ''
newSite.contactPhone = ''
newSite.contactAddress = ''
newSite.contactPostalCode = ''
newSite.contactCity = ''
}
const closeCreateModal = () => {
showAddSiteModal.value = false
resetNewSite()
}
const openCreateSiteModal = () => {
resetNewSite()
showAddSiteModal.value = true
}
const handleCreateSite = async () => {
const result = await createSite({
name: newSite.name,
contactName: newSite.contactName,
contactPhone: newSite.contactPhone,
contactAddress: newSite.contactAddress,
contactPostalCode: newSite.contactPostalCode,
contactCity: newSite.contactCity
})
if (result.success) {
closeCreateModal()
}
}
const editSite = (site: SiteWithDocuments) => {
siteBeingEdited.value = site
editSiteForm.name = site.name || ''
editSiteForm.contactName = site.contactName || ''
editSiteForm.contactPhone = site.contactPhone || ''
editSiteForm.contactAddress = site.contactAddress || ''
editSiteForm.contactPostalCode = site.contactPostalCode || ''
editSiteForm.contactCity = site.contactCity || ''
selectedFiles.value = []
refreshSiteDocuments(site.id)
showEditSiteModal.value = true
}
const closeEditModal = () => {
showEditSiteModal.value = false
siteBeingEdited.value = null
selectedFiles.value = []
}
const updateSiteInCollection = (id: string, updated: Partial<SiteWithDocuments>) => {
const index = sites.value.findIndex(site => site.id === id)
if (index !== -1) {
sites.value[index] = {
...sites.value[index],
...updated
}
}
}
const handleUpdateSite = async () => {
if (!siteBeingEdited.value) return
const baseUpdate = {
name: editSiteForm.name,
contactName: editSiteForm.contactName,
contactPhone: editSiteForm.contactPhone,
contactAddress: editSiteForm.contactAddress,
contactPostalCode: editSiteForm.contactPostalCode,
contactCity: editSiteForm.contactCity
}
const result = await updateSite(siteBeingEdited.value.id, baseUpdate)
if (!result.success) return
let uploadedDocuments: SiteDocument[] = []
const existingDocuments = siteBeingEdited.value?.documents || []
if (selectedFiles.value.length) {
uploadingDocuments.value = true
const uploadResult = await uploadDocuments(
{
files: selectedFiles.value,
context: { siteId: siteBeingEdited.value.id }
},
{ updateStore: false }
)
uploadingDocuments.value = false
if (uploadResult.success) {
uploadedDocuments = uploadResult.data || []
selectedFiles.value = []
}
}
if (uploadedDocuments.length) {
const mergedDocuments = [...uploadedDocuments, ...existingDocuments]
if (siteBeingEdited.value) {
siteBeingEdited.value.documents = mergedDocuments
}
updateSiteInCollection(siteBeingEdited.value.id, {
...baseUpdate,
documents: mergedDocuments
})
} else {
updateSiteInCollection(siteBeingEdited.value.id, baseUpdate)
}
closeEditModal()
}
const handleRemoveSiteDocument = async (documentId: string) => {
if (!documentId) return
const result = await deleteDocument(documentId, { updateStore: false })
if (!result.success) return
if (siteBeingEdited.value) {
siteBeingEdited.value.documents = (siteBeingEdited.value.documents || []).filter(
doc => doc.id !== documentId
)
updateSiteInCollection(siteBeingEdited.value.id, {
documents: siteBeingEdited.value.documents
})
}
}
const downloadDocument = (doc: SiteDocument) => {
if (!doc?.path) return
if (doc.path.startsWith('data:')) {
const link = document.createElement('a')
link.href = doc.path
link.download = doc.filename || doc.name || 'document'
link.click()
return
}
window.open(doc.path, '_blank')
}
const openPreview = (doc: SiteDocument) => {
if (!canPreviewDocument(doc)) return
previewDocument.value = doc
previewVisible.value = true
}
const closePreview = () => {
previewVisible.value = false
previewDocument.value = null
}
const refreshSiteDocuments = async (siteId: string) => {
if (!siteId) return
const result = await loadDocumentsBySite(siteId, { updateStore: false })
if (result.success && siteBeingEdited.value && siteBeingEdited.value.id === siteId) {
const cloned = Array.isArray(result.data) ? [...result.data] : []
siteBeingEdited.value.documents = cloned
updateSiteInCollection(siteId, { documents: cloned })
}
}
const formatSize = (size?: number | null) => {
if (size === undefined || size === null) return '—'
if (size === 0) return '0 B'
const units = ['B', 'KB', 'MB', 'GB']
const index = Math.min(units.length - 1, Math.floor(Math.log(size) / Math.log(1024)))
const formatted = size / Math.pow(1024, index)
return `${formatted.toFixed(1)} ${units[index]}`
}
const confirmDeleteSite = async (site: SiteWithDocuments) => {
if (
!confirm(
`Êtes-vous sûr de vouloir supprimer le site "${site.name}" ? Cette action est irréversible.`
)
) {
return
}
try {
const result = await deleteSite(site.id)
if (result.success) {
showSuccess(`Site "${site.name}" supprimé avec succès`)
} else {
showError(`Erreur lors de la suppression: ${result.error}`)
}
} catch (error: any) {
showError(`Erreur lors de la suppression: ${error.message}`)
}
}
onMounted(async () => {
await loadSites()
})
watch(
() => route.query.add,
async (shouldOpen) => {
if (shouldOpen === 'true') {
openCreateSiteModal()
await navigateTo('/sites', { replace: true })
}
},
{ immediate: true }
)
return {
sites,
loading,
showAddSiteModal,
showEditSiteModal,
siteBeingEdited,
newSite,
editSiteForm,
selectedFiles,
uploadingDocuments,
previewDocument,
previewVisible,
siteDocuments,
documentIcon,
openCreateSiteModal,
closeCreateModal,
handleCreateSite,
editSite,
handleUpdateSite,
closeEditModal,
handleRemoveSiteDocument,
downloadDocument,
openPreview,
closePreview,
refreshSiteDocuments,
formatSize,
confirmDeleteSite,
canPreviewDocument
}
}