PageSourceSearch

https://tambali.ai/assets/controllers/favoris_controller-8c7518097…2da6b552a5e82621cf7545afecb036b22aee93a2.js

js tambali.ai collected 2026-10-05 14:24:46 UTC 6,243 bytes, 192 lines download raw bytes

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.