// ========================================
// Paraguay LLC & SRL — Main JS
// ========================================
const API_URL = 'https://n8n.odoo4projects.com/webhook/paraguay/login';
const NEWSLETTER_URL = 'https://n8n.odoo4projects.com/webhook/paraguay/newsletter';
const USER_URL = 'https://n8n.odoo4projects.com/webhook/paraguay/user';
const PROFILE_URL = 'https://n8n.odoo4projects.com/webhook/paraguay/profile';
const WIKI_URL = 'https://n8n.odoo4projects.com/webhook/paraguay/wiki';
let currentLang = 'de';
document.addEventListener('DOMContentLoaded', () => {
currentLang = document.body.dataset.lang || 'de';
checkSession();
// Smooth scroll nav links
document.querySelectorAll('.nav-link').forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const target = document.querySelector(link.getAttribute('href'));
if (target) {
target.scrollIntoView({ behavior: 'smooth' });
}
// Close mobile nav
document.getElementById('nav-menu').classList.remove('open');
});
});
// Mobile nav toggle
const navToggle = document.getElementById('nav-toggle');
const navMenu = document.getElementById('nav-menu');
if (navToggle) {
navToggle.addEventListener('click', () => {
navMenu.classList.toggle('open');
});
}
// Navbar scroll effect
window.addEventListener('scroll', () => {
const nav = document.getElementById('main-nav');
if (nav) {
nav.classList.toggle('scrolled', window.scrollY > 20);
}
});
// Language toggle
document.querySelectorAll('.lang-btn').forEach(btn => {
btn.addEventListener('click', () => {
const lang = btn.dataset.lang;
setLanguage(lang);
// Reload content in new language
if (isLoggedIn) {
if (document.querySelector('.notebook') || document.getElementById('members-list')) loadUsers();
if (document.getElementById('wiki-grid')) loadWiki();
}
});
});
// Member search
const memberSearch = document.getElementById('member-search');
if (memberSearch) {
memberSearch.addEventListener('input', (e) => {
filterMembers(e.target.value);
});
}
// Wiki search
const wikiSearch = document.getElementById('wiki-search');
if (wikiSearch) {
wikiSearch.addEventListener('input', (e) => {
searchWiki(e.target.value);
});
}
// Close modals on overlay click
document.querySelectorAll('.modal-overlay').forEach(overlay => {
overlay.addEventListener('click', (e) => {
if (e.target === overlay) {
overlay.classList.remove('active');
}
});
});
// Close modals on Escape
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
document.querySelectorAll('.modal-overlay.active').forEach(m => m.classList.remove('active'));
}
});
// Login button
const loginBtn = document.getElementById('login-btn');
if (loginBtn) {
loginBtn.addEventListener('click', () => {
openLoginModal();
});
}
});
// ========================================
// LANGUAGE
// ========================================
function setLanguage(lang) {
currentLang = lang;
document.body.dataset.lang = lang;
document.querySelectorAll('.lang-btn').forEach(b => {
b.classList.toggle('active', b.dataset.lang === lang);
});
}
function isDE() {
return currentLang !== 'en';
}
// ========================================
// AUTH / SESSION
// ========================================
let isLoggedIn = false;
function isSessionValid() {
const sid = getCookie('sessionid');
return sid.length > 0;
}
function checkSession() {
isLoggedIn = isSessionValid();
if (isLoggedIn) {
document.body.dataset.loggedIn = 'true';
document.getElementById('login-btn').style.display = 'none';
document.getElementById('logout-btn').style.display = 'inline-flex';
document.getElementById('profile-btn').style.display = 'inline-flex';
document.getElementById('telegram-banner').style.display = 'none';
document.getElementById('main-content').style.display = 'block';
document.getElementById('newsletter-section').style.display = 'block';
loadUsers();
loadWiki();
} else {
document.body.dataset.loggedIn = 'false';
document.getElementById('login-btn').style.display = 'inline-flex';
document.getElementById('logout-btn').style.display = 'none';
document.getElementById('profile-btn').style.display = 'none';
document.getElementById('telegram-banner').style.display = 'block';
document.getElementById('main-content').style.display = 'none';
document.getElementById('newsletter-section').style.display = 'none';
}
}
// ========================================
// LOGIN MODAL
// ========================================
function openLoginModal() {
document.getElementById('login-modal-overlay').classList.add('active');
// Reset to step 1
document.querySelectorAll('.login-step').forEach(s => s.classList.remove('active'));
document.getElementById('login-step-1').classList.add('active');
document.getElementById('telegram-user').value = '';
document.getElementById('verification-code').value = '';
}
function closeLoginModal() {
document.getElementById('login-modal-overlay').classList.remove('active');
}
// ========================================
// PROFILE MODAL
// ========================================
function openProfileModal() {
const sid = getCookie('sessionid');
if (!sid) { alert('Bitte anmelden.'); return; }
fetch(PROFILE_URL + '?sessionid=' + encodeURIComponent(sid))
.then(r => r.json())
.then(user => {
document.getElementById('profile-username-display').textContent = user.username || '';
const rank = getRank(user.posts || 0);
const badge = document.getElementById('profile-rank-badge');
badge.innerHTML = `${rank.emoji} ${rank.title}`;
document.getElementById('profile-company').value = user.company || '';
document.getElementById('profile-email').value = user.email || '';
document.getElementById('profile-homepage').value = user.homepage || '';
document.getElementById('profile-image').value = user.image || '';
document.getElementById('profile-location').value = user.location || '';
document.getElementById('profile-description').value = user.Description || '';
document.getElementById('profile-publish').checked = true;
document.getElementById('profile-modal-overlay').classList.add('active');
})
.catch(() => alert('Fehler beim Laden des Profils.'));
}
function closeProfileModal() {
document.getElementById('profile-modal-overlay').classList.remove('active');
}
function saveProfile() {
const sid = getCookie('sessionid');
fetch(PROFILE_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: document.getElementById('profile-username-display').textContent,
company: document.getElementById('profile-company').value.trim(),
email: document.getElementById('profile-email').value,
homepage: document.getElementById('profile-homepage').value,
image: document.getElementById('profile-image').value,
location: document.getElementById('profile-location').value,
Description: document.getElementById('profile-description').value,
sessionid: sid,
publish: document.getElementById('profile-publish').checked
})
})
.then(r => r.ok ? alert('Profil gespeichert!') : alert('Fehler beim Speichern.'))
.catch(() => alert('Fehler bei der Verbindung.'));
}
// ========================================
// USER DETAIL MODAL
// ========================================
function openUserDetailModal(user) {
const avatar = document.getElementById('user-detail-avatar');
if (user.image) {
avatar.innerHTML = ``;
} else {
avatar.innerHTML = `${(user.username || '?').charAt(0).toUpperCase()}`;
}
document.getElementById('user-detail-initial').textContent = '';
document.getElementById('user-detail-username').textContent = '@' + (user.username || 'Unknown');
const rank = getRank(user.posts || 0);
document.getElementById('user-detail-rank-badge').className = `rank-badge rank-${rank.level}`;
document.getElementById('user-detail-rank-badge').textContent = rank.emoji + ' ' + rank.title;
document.getElementById('user-detail-company').textContent = user.company || '';
const emailEl = document.getElementById('user-detail-email');
emailEl.innerHTML = user.email ? `${user.email}` : '-';
const hpEl = document.getElementById('user-detail-homepage');
const hp = user.homepage || '';
hpEl.innerHTML = hp ? `${hp}` : '-';
document.getElementById('user-detail-location').textContent = user.location || '-';
document.getElementById('user-detail-description').innerHTML = (user.Description || '-').replace(/\n/g, '
');
document.getElementById('user-detail-modal-overlay').classList.add('active');
}
function closeUserDetailModal() {
document.getElementById('user-detail-modal-overlay').classList.remove('active');
}
// ========================================
// LOGIN FLOW
// ========================================
function sendTelegramUser() {
const user = document.getElementById('telegram-user').value.trim();
if (!user) { alert('Bitte geben Sie einen Telegram-Nutzernamen ein.'); return; }
const btn = event.target;
btn.disabled = true;
btn.textContent = isDE() ? 'Sende...' : 'Sending...';
fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: user })
})
.then(r => r.json())
.then(data => {
if (data.sessionid) {
setCookie('sessionid', data.sessionid, 1);
document.getElementById('login-step-1').classList.remove('active');
document.getElementById('login-step-3').classList.add('active');
} else if (data.status === 'code send') {
document.getElementById('login-step-1').classList.remove('active');
document.getElementById('login-step-2').classList.add('active');
} else {
alert(isDE() ? 'Benutzername nicht gefunden. Bitte über Telegram Bot anmelden.' : 'Username not found. Please sign up via Telegram bot.');
}
})
.catch(() => {
btn.disabled = false;
alert(isDE() ? 'Verbindungsfehler' : 'Connection error');
});
}
function verifyCode() {
const code = document.getElementById('verification-code').value.trim();
if (!code) { alert('Bitte geben Sie den Code ein.'); return; }
fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: document.getElementById('telegram-user').value,
code: code,
sessionid: getCookie('sessionid')
})
})
.then(r => r.json())
.then(data => {
if (data.sessionid) {
setCookie('sessionid', data.sessionid, 1);
checkSession();
closeLoginModal();
} else {
alert(isDE() ? 'Ungültiger Code' : 'Invalid code');
}
})
.catch(() => alert(isDE() ? 'Verbindungsfehler' : 'Connection error'));
}
function submitLoginData() {
const name = document.getElementById('full-name').value.trim();
const llc = document.getElementById('llc-name').value.trim();
if (!name || !llc) { alert(isDE() ? 'Bitte Name und LLC eintragen' : 'Please enter name and LLC'); return; }
fetch(API_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: document.getElementById('telegram-user').value,
name: name,
llc: llc
})
})
.then(r => r.json())
.then(data => {
if (data.sessionid) {
setCookie('sessionid', data.sessionid, 1);
checkSession();
closeLoginModal();
} else {
alert(isDE() ? 'Registrierung fehlgeschlagen' : 'Registration failed');
}
})
.catch(() => alert(isDE() ? 'Verbindungsfehler' : 'Connection error'));
}
function logout() {
setCookie('sessionid', '', -1);
checkSession();
}
// ========================================
// NEWSLETTER
// ========================================
function subscribeNewsletter() {
const email = document.getElementById('newsletter-email').value.trim();
if (!email) { alert(isDE() ? 'Bitte E-Mail eingeben' : 'Please enter email'); return; }
fetch(NEWSLETTER_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: email })
})
.then(r => {
if (r.ok) {
document.getElementById('newsletter-form').classList.add('hidden');
document.getElementById('newsletter-success').classList.remove('hidden');
} else {
alert(isDE() ? 'Fehler beim Abonnieren' : 'Error subscribing');
}
})
.catch(() => alert(isDE() ? 'Verbindungsfehler' : 'Connection error'));
}
// ========================================
// USERS / MEMBERS
// ========================================
async function loadUsers() {
try {
const response = await fetch(USER_URL);
if (!response.ok) throw new Error('Failed to fetch');
const data = await response.json();
const container = document.getElementById('members-list');
if (data.data && Array.isArray(data.data)) {
container.innerHTML = '';
container.style.display = 'grid';
data.data.forEach(user => {
const card = createMemberCard(user);
container.appendChild(card);
});
// Update stats
document.getElementById('stat-members').textContent = data.data.length;
const totalPosts = data.data.reduce((sum, u) => sum + (u.posts || 0), 0);
document.getElementById('stat-posts').textContent = totalPosts;
} else {
container.innerHTML = '
' + (isDE() ? 'Keine Mitglieder gefunden' : 'No members found') + '
'; } } catch (error) { const container = document.getElementById('members-list'); container.innerHTML = '' + (isDE() ? 'Fehler beim Laden' : 'Error loading') + '
'; } } function createMemberCard(user) { const card = document.createElement('div'); card.className = 'member-card'; const rank = getRank(user.posts || 0); const avatarContent = user.image ? `${user.company || ''}
${user.location ? `📍 ${user.location}
` : ''} ${user.posts ? `${user.posts} ${isDE() ? 'Beiträge' : 'posts'}
` : ''} ${rank.emoji} ${rank.title}' + (isDE() ? 'Keine Wiki-Daten' : 'No wiki data') + '
'; } } catch (error) { document.getElementById('wiki-grid').innerHTML = '' + (isDE() ? 'Fehler beim Laden' : 'Error loading') + '
'; } } function renderWikiCards(data) { const grid = document.getElementById('wiki-grid'); grid.innerHTML = ''; if (data.length === 0) { grid.innerHTML = '' + (isDE() ? 'Keine Ergebnisse gefunden' : 'No results found') + '
'; return; } // Group by topic const topics = {}; data.forEach(item => { const topicKey = (item.topic_en && currentLang === 'en') ? item.topic_en : (item.topic || 'Unknown'); if (!topics[topicKey]) topics[topicKey] = []; topics[topicKey].push(item); }); const colors = ['blue', 'teal', 'green', 'orange', 'purple', 'pink', 'yellow']; Object.entries(topics).forEach(([topicName, subtopics], idx) => { const card = document.createElement('div'); card.className = 'wiki-card'; card.dataset.color = colors[idx % colors.length]; // Get excerpt from first subtopic const firstSub = subtopics[0]; const excerpt = currentLang === 'en' && firstSub.wiki_en ? firstSub.wiki_en : (firstSub.wiki || ''); const subtopicTitle = currentLang === 'en' && firstSub.subtopic_en ? firstSub.subtopic_en : (firstSub.subtopic || ''); card.innerHTML = `