import { computed, onMounted, reactive, ref, watch } from 'vue' import { navigateTo, useRoute } from '#imports' import { useSites } from '~/composables/useSites' import { useToast } from '~/composables/useToast' import { humanizeError } from '~/shared/utils/errorMessages' import { useDocuments } from '~/composables/useDocuments' import { useConfirm } from '~/composables/useConfirm' import { getFileIcon } from '~/utils/fileIcons' import { canPreviewDocument } from '~/utils/documentPreview' type SiteForm = { name: string color: 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 fileUrl?: string downloadUrl?: string } type SiteWithDocuments = { id: string name?: string color?: string contactName?: string contactPhone?: string contactAddress?: string contactPostalCode?: string contactCity?: string documents?: SiteDocument[] machines?: Array } export function useSiteManagement() { const route = useRoute() const { showError, showSuccess } = useToast() const { sites, loading, loadSites, createSite, updateSite, deleteSite } = useSites() const { uploadDocuments, deleteDocument, loadDocumentsBySite } = useDocuments() const { confirm: confirmDialog } = useConfirm() const showAddSiteModal = ref(false) const showEditSiteModal = ref(false) const siteBeingEdited = ref(null) const newSite = reactive({ name: '', color: '', contactName: '', contactPhone: '', contactAddress: '', contactPostalCode: '', contactCity: '' }) const editSiteForm = reactive({ name: '', color: '', contactName: '', contactPhone: '', contactAddress: '', contactPostalCode: '', contactCity: '' }) const selectedFiles = ref([]) const uploadingDocuments = ref(false) const previewDocument = ref(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.color = '' 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, color: newSite.color, 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.color = site.color || '' 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) => { const index = sites.value.findIndex(site => site.id === id) if (index !== -1) { sites.value[index] = { ...sites.value[index], ...updated, id, } } } const handleUpdateSite = async () => { if (!siteBeingEdited.value) return const baseUpdate = { name: editSiteForm.name, color: editSiteForm.color, 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 && uploadResult.data) { const data = uploadResult.data uploadedDocuments = (Array.isArray(data) ? data : [data]) as SiteDocument[] 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?.downloadUrl) { window.open(doc.downloadUrl, '_blank') return } const url = doc?.fileUrl || doc?.path if (!url) return if (url.startsWith('data:')) { const link = document.createElement('a') link.href = url link.download = doc.filename || doc.name || 'document' link.click() return } window.open(url, '_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 ( !await confirmDialog({ message: `Ê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(`Impossible de supprimer le site : ${humanizeError(result.error)}`) } } catch (error: any) { showError(`Impossible de supprimer le site : ${humanizeError(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 } }