1import { Controller } from "@hotwired/stimulus" 2 3export default class extends Controller { 4 static targets = ["card"] 5 6 connect() { 7 this.currentTab = "fiches" 8 } 9 10 switchTab(event) { 11 const clickedTab = event.currentTarget 12 const tabName = clickedTab.dataset.tab 13 14 const tabs = this.element.querySelectorAll('.favoris-tab') 15 tabs.forEach(tab => tab.classList.remove('active')) 16 clickedTab.classList.add('active') 17 18 const tabContents = this.element.querySelectorAll('[data-tab-content]') 19 tabContents.forEach(content => { 20 content.style.display = content.dataset.tabContent === tabName ? 'block' : 'none' 21 }) 22 23 const url = new URL(window.location) 24 url.searchParams.set('tab', tabName) 25 window.history.pushState({}, '', url) 26 27 this.currentTab = tabName 28 } 29 30 async unsaveFiche(event) { 31 event.preventDefault() 32 event.stopPropagation() 33 34 const button = event.currentTarget 35 const ficheId = button.dataset.ficheId 36 const card = button.closest('.favoris-card') 37 38 try { 39 const response = await fetch(`/fiches-idees/${ficheId}/unsave`, { 40 method: 'DELETE', 41 headers: { 42 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content, 43 'Accept': 'application/json' 44 } 45 }) 46 47 const data = await response.json() 48 49 if (data.status === 'success') { 50 this.removeCard(card, 'fiches', "Fiches d'idées", "fa-solid fa-lightbulb", "Aucune fiche d'idée sauvegardée", "Explorez les fiches d'idées et sauvegardez celles qui vous inspirent.") 51 } 52 } catch (error) { 53 alert('Erreur lors de la suppression du favori. Veuillez réessayer.') 54 } 55 } 56 57 async unsaveRecherche(event) { 58 event.preventDefault() 59 event.stopPropagation() 60 61 const button = event.currentTarget 62 const rechercheId = button.dataset.rechercheId 63 const card = button.closest('.favoris-card') 64 65 try { 66 const response = await fetch(`/r-d-recherches/${rechercheId}/unsave`, { 67 method: 'DELETE', 68 headers: { 69 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content, 70 'Accept': 'application/json' 71 } 72 }) 73 74 const data = await response.json() 75 76 if (data.status === 'success') { 77 this.removeCard(card, 'recherches', "Recherches R&D", "fa-solid fa-flask", "Aucune recherche R&D sauvegardée", "Explorez les recherches R&D et sauvegardez celles qui vous intéressent.") 78 } 79 } catch (error) { 80 alert('Erreur lors de la suppression du favori. Veuillez réessayer.') 81 } 82 } 83 84 async unsaveIdeeDuJour(event) { 85 event.preventDefault() 86 event.stopPropagation() 87 88 const button = event.currentTarget 89 const ideeId = button.dataset.ideeId 90 const card = button.closest('.favoris-card') 91 92 try { 93 const response = await fetch(`/idee-du-jour/${ideeId}/unsave`, { 94 method: 'DELETE', 95 headers: { 96 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content, 97 'Accept': 'application/json' 98 } 99 }) 100 101 const data = await response.json() 102 103 if (data.status === 'success') { 104 this.removeCard(card, 'idee-jour', "Idée du jour", "fa-solid fa-calendar-star", "Aucune idée du jour sauvegardée", "Consultez l'idée du jour et sauvegardez celles qui vous intéressent.") 105 } 106 } catch (error) { 107 alert('Erreur lors de la suppression du favori. Veuillez réessayer.') 108 } 109 } 110 111 async unsaveOpportunity(event) { 112 event.preventDefault() 113 event.stopPropagation() 114 115 const button = event.currentTarget 116 const opportunityId = button.dataset.opportunityId 117 const card = button.closest('.favoris-card') 118 119 try { 120 const response = await fetch(`/market-opportunity/${opportunityId}/unsave`, { 121 method: 'DELETE', 122 headers: { 123 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content, 124 'Accept': 'application/json' 125 } 126 }) 127 128 const data = await response.json() 129 130 if (data.status === 'success') { 131 this.removeCard(card, 'opportunites', "Opportunités", "fa-solid fa-map-location-dot", "Aucune opportunité sauvegardée", "Explorez la cartographie et sauvegardez les opportunités qui vous intéressent.") 132 } 133 } catch (error) { 134 alert('Erreur lors de la suppression du favori. Veuillez réessayer.') 135 } 136 } 137 138 async unsaveTendance(event) { 139 event.preventDefault() 140 event.stopPropagation() 141 142 const button = event.currentTarget 143 const tendanceId = button.dataset.tendanceId 144 const card = button.closest('.favoris-card') 145 146 try { 147 const response = await fetch(`/tendances/${tendanceId}/unsave`, { 148 method: 'DELETE', 149 headers: { 150 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content, 151 'Accept': 'application/json' 152 } 153 }) 154 155 const data = await response.json() 156 157 if (data.status === 'success') { 158 this.removeCard(card, 'tendances', "Tendances", "fa-solid fa-arrow-trend-up", "Aucune tendance sauvegardée", "Explorez les tendances et sauvegardez celles qui vous intéressent.") 159 } 160 } catch (error) { 161 alert('Erreur lors de la suppression du favori. Veuillez réessayer.') 162 } 163 } 164 165 removeCard(card, tabName, tabLabel, iconClass, emptyTitle, emptyDescription) { 166 card.style.transition = 'opacity 0.3s ease, transform 0.3s ease' 167 card.style.opacity = '0' 168 card.style.transform = 'translateY(-10px)' 169 170 setTimeout(() => { 171 card.remove() 172 173 const count = this.element.querySelectorAll(`[data-tab-content="${tabName}"] .favoris-card`).length 174 const tab = this.element.querySelector(`[data-tab="${tabName}"]`) 175 if (tab) { 176 const countEl = tab.querySelector('.favoris-tab-count') 177 if (countEl) countEl.textContent = count 178 } 179 180 if (count === 0) { 181 const tabContent = this.element.querySelector(`[data-tab-content="${tabName}"]`) 182 tabContent.innerHTML = ` 183 <div class="favoris-empty-state"> 184 <i class="${iconClass}"></i> 185 <h3>${emptyTitle}</h3> 186 <p>${emptyDescription}</p> 187 </div> 188 ` 189 } 190 }, 300) 191 } 192};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.