[Sugester V2](https://pomoc.sugester2.pl.md) / [Forum Sugestii](https://pomoc.sugester2.pl/forum-sugestii-1.md)

# [Widget głosowania - osadzanie na zewnętrznych stronach](https://pomoc.sugester2.pl/widget-glosowania-osadzanie-na-zewnetrznych-stronach-Lf3RAMty.md)

## Czym jest widget głosowania?

Widget głosowania pozwala zbierać opinie użytkowników bezpośrednio na stronach marketingowych lub w aplikacjach zewnętrznych. Użytkownicy mogą głosować czy dana funkcja jest dla nich przydatna, a ich głosy trafiają do Forum Sugestii.

## Jak to wygląda?

### Przed głosowaniem

<img src="https://s3.eu-west-1.amazonaws.com/attachments.intum.net/public-files/31076/729234a3a01dfef95ea0fb655e532d70d369c827" alt="widget przed kliknięciem" style="max-width: 100%;" />

### Po głosowaniu

<img src="https://s3.eu-west-1.amazonaws.com/attachments.intum.net/public-files/31076/c6b8699d1a0c0119a70e4342f4762474003176ba" alt="widget po kliknięciu" style="max-width: 100%;" />

## Funkcje widgetu

- **Głosowanie** - przyciski "Tak" / "Nie"
- **Licznik głosów** - po zagłosowaniu pokazuje ile osób głosowało
- **Komentarze** - możliwość dodania opinii tekstowej
- **Link do dyskusji** - przekierowanie do pełnego wątku na forum

---

## Prompt dla LLM (Claude, ChatGPT, itp.)

Jeśli używasz LLM do kodowania strony, możesz użyć tego promptu:

```
Dodaj widget głosowania do mojej strony. Widget powinien:

1. Wyświetlać pytanie "Przydatna funkcja?" z przyciskami "Tak" / "Nie"
2. Po głosowaniu pokazać liczbę głosów i link do dyskusji
3. Wysyłać głos na endpoint: POST {FORUM_URL}/rate?helpful=yes|no
4. Pobierać dane z: GET {FORUM_URL}.json (zwraca rating, comments_count)

Gdzie {FORUM_URL} to ścieżka do wpisu w Forum Sugestii, np.:
/forum/sugestie/nazwa-funkcji-ABC123

Widget powinien być:
- Kompaktowy (max 280px szerokości)
- W ciemnym motywie (slate/purple) lub dopasowany do strony
- Responsywny (fixed na mobile, float-right na desktop)

Mapowanie stron na wpisy forum:
- /funkcje/moja-funkcja → /forum/sugestie/moja-funkcja-TOKEN
```

### Gdzie to działa?

<table>
<tr><th>Środowisko</th><th>Działa?</th><th>Uwagi</th></tr>
<tr><td>Strony w CMS Sugester/Intum</td><td>✅ Tak</td><td>Pełna integracja</td></tr>
<tr><td>Aplikacje NOE</td><td>✅ Tak</td><td>Pełna integracja</td></tr>
<tr><td>Zewnętrzne strony (własny hosting)</td><td>✅ Tak</td><td>Wymaga CORS lub proxy</td></tr>
<tr><td>Inne CMS-y (WordPress, itp.)</td><td>⚠️ Częściowo</td><td>Backend musi być Sugester</td></tr>
</table>
**Wymagania backendu:**
- Forum Sugestii w Sugester/Intum
- Endpoint `/rate` z wyłączonym CSRF (`skip_forgery_protection`)
- Endpoint `.json` zwracający `rating` i `comments_count`

---

## Kod do osadzenia

Aby osadzić widget na swojej stronie, dodaj poniższy kod HTML i JavaScript:

### 1. HTML widgetu

```html
<!-- Widget głosowania -->
<div id="voting-widget" class="hidden">
  <div class="voting-box">
    <p class="voting-question">Przydatna funkcja?</p>
    <div id="vote-buttons" class="voting-buttons">
      <button onclick="vote('yes')" class="voting-btn btn-yes">👍 Tak</button>
      <button onclick="vote('no')" class="voting-btn btn-no">👎 Nie</button>
    </div>
    
    <div id="forum-link" class="hidden">
      <a id="forum-link-href" href="#" target="_blank">
        💬 Dyskusja <span id="comment-count"></span>
      </a>
    </div>
  </div>
</div>
```

### 2. JavaScript

```javascript
(function() {
  // Konfiguracja - zmień na swoje wartości
  const FORUM_BASE = 'https://twoja-domena.pl/forum/sugestie';
  
  const entryMap = {
    '/funkcje/moja-funkcja': { 
      path: FORUM_BASE + '/moja-funkcja-ABC123', 
      id: 123 
    },
    // dodaj więcej mapowań...
  };

  const path = window.location.pathname.replace(/\/$/, '');
  const entry = entryMap[path];
  
  if (entry) {
    document.getElementById('voting-widget').classList.remove('hidden');
    window.currentEntry = entry;

    // Link do forum
    document.getElementById('forum-link-href').href = entry.path;
    document.getElementById('forum-link').classList.remove('hidden');

    // Pobierz liczbę komentarzy
    fetch(entry.path + '.json')
      .then(r => r.json())
      .then(data => {
        if (data.comments_count > 0) {
          document.getElementById('comment-count').textContent = 
            '(' + data.comments_count + ')';
        }
      })
      .catch(() => {});
  }

  window.vote = async function(helpful) {
    const btns = document.querySelectorAll('.voting-btn');
    btns.forEach(b => b.disabled = true);

    try {
      await fetch(window.currentEntry.path + '/rate?helpful=' + helpful, 
        { method: 'POST' });
      
      // Pobierz aktualny rating
      const data = await fetch(window.currentEntry.path + '.json')
        .then(r => r.json());
      const rating = data?.rating || 0;
      
      let msg = '✓ Dziękujemy!';
      if (rating > 0) {
        msg = helpful === 'yes' 
          ? '✓ ' + rating + ' osób chce tę funkcję'
          : '✓ Dziękujemy! (głosów: ' + rating + ')';
      }
      
      document.getElementById('vote-result').textContent = msg;
      document.getElementById('vote-result').classList.remove('hidden');
      document.getElementById('vote-buttons').style.opacity = '0.5';
    } catch(e) {
      document.getElementById('vote-result').textContent = 'Błąd - spróbuj ponownie';
      document.getElementById('vote-result').classList.remove('hidden');
      btns.forEach(b => b.disabled = false);
    }
  };
})();
```

### 3. Style CSS

```css
.voting-box {
  padding: 1rem;
  background: rgba(30, 41, 59, 0.9);
  border-radius: 0.75rem;
  border: 1px solid rgba(168, 85, 247, 0.3);
  max-width: 280px;
}
.voting-question {
  color: #cbd5e1;
  font-size: 0.875rem;
  margin-bottom: 0.75rem;
}
.voting-buttons {
  display: flex;
  gap: 0.5rem;
}
.voting-btn {
  flex: 1;
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  font-weight: 500;
  border-radius: 0.5rem;
  border: none;
  cursor: pointer;
  white-space: nowrap;
}
.btn-yes { background: #059669; color: white; }
.btn-yes:hover { background: #10b981; }
.btn-no { background: #475569; color: white; }
.btn-no:hover { background: #64748b; }
#vote-result { 
  color: #10b981; 
  font-size: 0.875rem; 
  margin-top: 0.75rem; 
}
#forum-link a {
  color: #a78bfa;
  font-size: 0.75rem;
}
.hidden { display: none; }
```

## Wymagania techniczne

- Wpis w Forum Sugestii z włączonym publicznym dostępem
- Endpoint `/rate` z wyłączoną ochroną CSRF (`skip_forgery_protection`)
- Endpoint `.json` zwracający `comments_count` i `rating`
- CORS skonfigurowany jeśli widget na innej domenie