Source: Wiki/Partnership/partners.js

/* eslint-disable no-unused-vars */
/* eslint-disable no-undef */

/**
 * Lista de parceiros com informações detalhadas.
 * @type {Array<Object>}
 */
const partners = [
    {
        name: 'Akanano',
        description: 'Um streamer legal, faz diversas atividades como lives de jogos e edits, em sua maioria de animes e gachas, como Genshin Impact. Prefere ser chamado por Aka, Akashi ou Akanano.',
        url: 'https://m.twitch.tv/akanano0299',
        image: 'https://static-cdn.jtvnw.net/jtv_user_pictures/2deccd13-6c5f-4c10-a68d-69782c5450c8-profile_image-150x150.png',
        added: '2024-12-14',
        type: 'Streamer',
    },
    {
        name: 'Baileys',
        description: 'Projeto que deu vida a Íris, já que é o kernel funcional dela para operar no WhatsApp.',
        url: 'https://github.com/WhiskeySockets/Baileys',
        image: 'https://avatars.githubusercontent.com/u/131354555?s=200&v=4',
        added: '2024-12-14',
        type: 'Project',
    },
    {
        name: 'xtgmpx',
        description: "Criador de contéudo que posta em sua maioria 'Tipografia de músicas Paraenses', mas também cria contéudo, como gameplays e edits de animes.",
        url: 'https://www.tiktok.com/@xtgmpx',
        image: 'https://p16-amd-va.tiktokcdn.com/tos-maliva-avt-0068/fc3999af8870e6e2bdf4e7b750bad4c8~tplv-tiktokx-cropcenter-q:1080:1080:q75.jpeg',
        added: '2024-12-14',
        type: 'Tiktoker',
    },
];

/**
 * Variável que controla o estado de exibição da lista de parceiros.
 * @type {boolean}
 */
let isListView = false;

/**
 * Objeto que armazena a coluna e a direção de ordenação atual.
 * @type {Object}
 * @property {string|null} column - Nome da coluna atualmente sendo ordenada.
 * @property {boolean} ascending - Se a ordenação é crescente.
 */
let currentSort = { column: null, ascending: true };

/**
 * Alterna o menu de navegação em dispositivos móveis.
 */
document.getElementById('hamburgerMenu').onclick = function changeView() {
    const menuList = document.getElementById('menuList');
    menuList.style.display = (menuList.style.display === 'flex') ? 'none' : 'flex';
};

/**
 * Ajusta a visibilidade do menu de navegação com base no tamanho da tela.
 */
window.addEventListener('resize', () => {
    const menuList = document.getElementById('menuList');
    menuList.style.display = (window.innerWidth > 768) ? 'flex' : 'none';
});

/**
 * Cria um cartão de exibição para um parceiro.
 * @param {Object} partner - O objeto do parceiro.
 * @param {number} index - Índice do parceiro na lista.
 * @returns {HTMLElement} - O elemento do cartão.
 */
function createCard(partner, index) {
    const cardDiv = document.createElement('div');
    cardDiv.classList.add('col-lg-3', 'col-md-4', 'col-sm-6', 'mb-4');
    cardDiv.innerHTML = `
        <div class="card">
            <img src="${partner.image}" class="card-img-top" alt="${partner.name}">
            <div class="card-body text-center">
                <p class="name">${partner.name}</p>
                <p class="type">${partner.type}</p>
                <p class="added-date">Adicionado em: ${partner.added}</p>
                <p class="description-text" id="card-description-${index}">
                    ${partner.description.substring(0, 60)}...<br>
                    <button class="btn btn-link" onclick="toggleDescription(${index})" style="color: red;">
                        <i class="fa-solid fa-plus"></i>
                    </button>
                    <a href="${partner.url}" class="btn btn-link" style="color: red;" target="_blank">
                        <i class="fa-solid fa-link"></i>
                    </a>
                </p>
            </div>
        </div>
    `;
    return cardDiv;
}

/**
 * Cria uma linha de lista para um parceiro.
 * @param {Object} partner - O objeto do parceiro.
 * @param {number} index - Índice do parceiro na lista.
 * @returns {HTMLElement} - O elemento da linha da lista.
 */
function createListRow(partner, index) {
    const listRow = document.createElement('tr');
    listRow.innerHTML = `
        <td>${index + 1}</td>
        <td><img src="${partner.image}" alt="${partner.name}" style="width: 50px;"></td>
        <td>${partner.name}</td>
        <td>
            <span class="description-text" id="list-description-${index}">
                ${partner.description.substring(0, 30)}...
                <button class="btn btn-link" onclick="toggleDescription(${index}, true)" style="color: red;">
                    <i class="fa-solid fa-plus"></i>
                </button>
            </span>
        </td>
        <td>${partner.added}</td>
        <td>${partner.type} <a href="${partner.url}" class="btn btn-link" style="color: red;" target="_blank"><i class="fa-solid fa-link"></i></a></td>
    `;
    return listRow;
}

/**
 * Gera o conteúdo da lista de parceiros e exibe conforme o modo (cartão ou lista).
 */
function generateContent() {
    const cardsContainer = document.getElementById('cards');
    const listBody = document.getElementById('listBody');
    cardsContainer.innerHTML = '';
    listBody.innerHTML = '';

    partners.forEach((partner, index) => {
        const cardDiv = createCard(partner, index);
        cardsContainer.appendChild(cardDiv);

        const listRow = createListRow(partner, index);
        listBody.appendChild(listRow);
    });
}

/**
 * Alterna entre o modo de exibição de lista e cartão.
 */
function toggleListView() {
    isListView = !isListView;
    document.getElementById('cards').style.display = isListView ? 'none' : 'flex';
    document.getElementById('listView').style.display = isListView ? 'block' : 'none';
    this.innerHTML = isListView ? '<i class="fa-solid fa-id-card"></i> Modo Card' : '<i class="fa-solid fa-list"></i> Modo Lista';
    generateContent();
}
document.getElementById('toggleViewBtn').onclick = toggleListView;

/**
 * Redireciona para a URL de um parceiro.
 * @param {number} index - Índice do parceiro na lista.
 */
function urlGo(index) {
    const partner = partners[index];
    if (!partner?.url) {
        console.error(`URL não encontrada para o parceiro no índice ${index}`);
        return;
    }
    window.location.href = partner.url;
}

/**
 * Alterna entre exibir a descrição completa ou resumida de um parceiro.
 * @param {number} index - Índice do parceiro na lista.
 * @param {boolean} [isList=false] - Se a exibição é no modo lista.
 */
function toggleDescription(index, isList = false) {
    const descriptionId = isList ? `list-description-${index}` : `card-description-${index}`;
    const descriptionText = document.getElementById(descriptionId);
    const isExpanded = descriptionText.innerText.includes('...');
    const fullDescription = partners[index].description;
    const truncatedDescription = (isList
        ? fullDescription.substring(0, 30)
        : fullDescription.substring(0, 60)
    );

    descriptionText.innerHTML = isExpanded
        ? `${fullDescription}<br><button class="btn btn-link" onclick="toggleDescription(${index}, ${isList})" style="color: red;"><i class="fa-solid fa-minus"></i></button><button class="btn btn-link" onclick="urlGo(${index})" style="color: red;"><i class="fa-solid fa-link"></i></button>`
        : `${truncatedDescription}...<br><button class="btn btn-link" onclick="toggleDescription(${index}, ${isList})" style="color: red;"><i class="fa-solid fa-plus"></i></button><button class="btn btn-link" onclick="urlGo(${index})" style="color: red;"><i class="fa-solid fa-link"></i></button>`;
}

/**
 * Atualiza os ícones de ordenação de acordo com a coluna e a direção.
 * @param {string} column - A coluna que está sendo ordenada.
 * @param {boolean} ascending - Se a ordenação é crescente.
 */
function updateSortIcons(column, ascending) {
    document.querySelectorAll('.sort-icon i').forEach((icon) => {
        icon.classList.remove('fa-arrow-up', 'fa-arrow-down');
        icon.classList.add('fa-arrow-down');
    });

    const activeIcon = document.querySelector(`.sort-icon[data-sort="${column}"] i`);
    activeIcon.classList.remove('fa-arrow-down', 'fa-arrow-up');
    activeIcon.classList.add(ascending ? 'fa-arrow-up' : 'fa-arrow-down');
}

/**
 * Ordena a lista de parceiros pela coluna especificada.
 * @param {string} column - A coluna a ser ordenada.
 * @param {boolean} ascending - Se a ordenação é crescente.
 */
function sortByColumn(column, ascending) {
    const sortFunctions = {
        name: (a, b) => a.name.localeCompare(b.name),
        type: (a, b) => a.type.localeCompare(b.type),
        date: (a, b) => new Date(a.added) - new Date(b.added),
        number: (a, b) => partners.indexOf(a) - partners.indexOf(b),
    };

    partners.sort(
        (a, b) => (ascending ? sortFunctions[column](a, b) : sortFunctions[column](b, a)),
    );
    currentSort = { column, ascending };
    updateSortIcons(column, ascending);
    generateContent();
}
document.querySelectorAll('.sort-icon').forEach((button) => {
    button.addEventListener('click', function sortView() {
        const column = this.dataset.sort;
        const ascending = currentSort.column !== column || !currentSort.ascending;
        sortByColumn(column, ascending);
    });
});

/**
 * Exporte os dados dos parceiros para um arquivo JSON.
 */
document.getElementById('exportJSON').onclick = function exportJSON() {
    const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(partners))}`;
    const downloadAnchorNode = document.createElement('a');
    downloadAnchorNode.setAttribute('href', dataStr);
    downloadAnchorNode.setAttribute('download', 'partners.json');
    document.body.appendChild(downloadAnchorNode);
    downloadAnchorNode.click();
    downloadAnchorNode.remove();
};

/* Inicia */
generateContent();