import { useState, useEffect } from 'react' import { Link } from 'react-router-dom' import { api } from '../api' const NETWORK_COLORS = { Amazon: { bg: '#FFF8E1', color: '#B45309' }, ClickBank: { bg: '#ECFDF5', color: '#065F46' }, ShareASale:{ bg: '#EFF6FF', color: '#1D4ED8' }, CJ: { bg: '#F5F3FF', color: '#6D28D9' }, Impact: { bg: '#FFF1F2', color: '#BE123C' }, } export default function AffiliateList() { const [links, setLinks] = useState([]) const [characters, setCharacters] = useState([]) const [loading, setLoading] = useState(true) const [filterCharacter, setFilterCharacter] = useState('') useEffect(() => { loadData() }, []) const loadData = async () => { setLoading(true) try { const [linksData, charsData] = await Promise.all([ api.get('/affiliates/'), api.get('/characters/'), ]) setLinks(linksData) setCharacters(charsData) } catch {} finally { setLoading(false) } } const getCharacterName = (id) => { if (!id) return 'Globale' return characters.find(c => c.id === id)?.name || '—' } const handleToggle = async (link) => { await api.put(`/affiliates/${link.id}`, { is_active: !link.is_active }).catch(() => {}) loadData() } const handleDelete = async (id, name) => { if (!confirm(`Eliminare "${name}"?`)) return await api.delete(`/affiliates/${id}`).catch(() => {}) loadData() } const filtered = links.filter(l => { if (filterCharacter === '') return true if (filterCharacter === 'global') return !l.character_id return String(l.character_id) === filterCharacter }) return (
{/* Header */}
Link Affiliati

Monetizzazione

Gestisci i link affiliati: Leopost li inserisce automaticamente nei contenuti generati.

+ Nuovo Link
{/* Filter */} {characters.length > 0 && (
{filtered.length} link
)} {loading ? ( ) : filtered.length === 0 ? ( ) : (
{['Network','Nome','URL','Personaggio','Stato','Click',''].map(h => ( ))} {filtered.map(link => { const nc = NETWORK_COLORS[link.network] || { bg: 'var(--cream-dark)', color: 'var(--ink-muted)' } return ( e.currentTarget.style.backgroundColor = 'var(--cream)'} onMouseLeave={e => e.currentTarget.style.backgroundColor = 'transparent'} > ) })}
{h}
{link.network || '—'} {link.name} {link.url?.substring(0, 45)}{link.url?.length > 45 ? '…' : ''} {getCharacterName(link.character_id)} {link.click_count ?? 0}
Modifica
)}
) } function EmptyState({ icon, title, description, cta, to }) { return (
{icon}

{title}

{description}

{cta}
) } function Spinner() { return (
) } const btnPrimary = { display: 'inline-block', padding: '0.6rem 1.25rem', backgroundColor: 'var(--ink)', color: 'white', fontFamily: "'DM Sans', sans-serif", fontWeight: 600, fontSize: '0.875rem', textDecoration: 'none', border: 'none', cursor: 'pointer', whiteSpace: 'nowrap', } const btnSmall = { display: 'inline-block', padding: '0.35rem 0.75rem', backgroundColor: 'var(--cream-dark)', color: 'var(--ink-light)', fontFamily: "'DM Sans', sans-serif", fontWeight: 500, fontSize: '0.78rem', textDecoration: 'none', border: 'none', cursor: 'pointer', } const selectStyle = { padding: '0.45rem 0.75rem', border: '1px solid var(--border)', backgroundColor: 'var(--surface)', color: 'var(--ink)', fontSize: '0.85rem', fontFamily: "'DM Sans', sans-serif", outline: 'none', cursor: 'pointer', }