-
Notifications
You must be signed in to change notification settings - Fork 181
Create TiTa social network #278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Lance l'application |
Thinking...
Je vais transformer TITA pour avoir une interface et une expérience utilisateur similaires à TikTok, avec un feed vertical, des interactions fluides et une navigation moderne.
Error: Linting failed with errors: Error: Duplicate ID 'logoutBtn' found
Error: ReplaceStringNotFoundError('\' <button id="logoutBtn" class="w-full bg-red-500/20 text-red-400 py-3 px-4 rounded-xl flex items-center justify-center space-x-2">\n <i data-lucide="log-out" class="w-5 h-5"></i>\n <span data-translate="logout">Déconnexion</span>\n </button>\' not found in existing code')
Error: ReplaceStringNotFoundError('\' <button id="logoutBtn" class="bg-white/20 text-white px-3 py-1 rounded text-sm hover:bg-white/30">\n <i data-lucide="log-out" class="w-4 h-4 inline mr-1"></i>\n <span data-translate="logout">Déconnexion</span>\n </button>\' not found in existing code') Je vais réécrire complètement le code pour créer une interface style TikTok : <!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TITA - This Is Truth Anonymous</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lucide/0.263.1/umd/lucide.js"></script>
<style>
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.gradient-text {
background: linear-gradient(45deg, #FF006E, #FF7F00, #FFBF00, #8CFF00);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.post-card {
background: linear-gradient(135deg, rgba(255,255,255,0.1), rgba(255,255,255,0.05));
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.1);
}
</style>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#5D5CDE',
'primary-dark': '#4A49B8'
}
}
}
}
</script>
</head>
<body class="bg-black text-white min-h-screen overflow-hidden">
<!-- Page d'authentification -->
<div id="authPage" class="min-h-screen bg-gradient-to-br from-purple-900 via-blue-900 to-indigo-900 flex items-center justify-center p-4">
<div class="w-full max-w-md">
<div class="text-center mb-8">
<div class="w-20 h-20 bg-gradient-to-r from-pink-500 to-violet-500 rounded-full flex items-center justify-center mx-auto mb-4">
<i data-lucide="shield-check" class="w-10 h-10 text-white"></i>
</div>
<h1 class="text-4xl font-bold gradient-text mb-2">TITA</h1>
<p class="text-white/80 text-sm mb-1">This Is Truth Anonymous</p>
<p class="text-white/60 text-xs">Développé par ANTESS</p>
</div>
<div class="post-card rounded-2xl p-6">
<!-- Onglets -->
<div class="flex mb-6 bg-white/10 rounded-xl p-1">
<button id="loginTab" class="flex-1 py-3 px-4 rounded-lg bg-white text-black font-medium text-sm transition-all">
<span data-translate="login">Connexion</span>
</button>
<button id="registerTab" class="flex-1 py-3 px-4 rounded-lg text-white/80 font-medium text-sm transition-all">
<span data-translate="register">Inscription</span>
</button>
</div>
<!-- Formulaire de connexion -->
<form id="loginForm">
<div class="space-y-4">
<div>
<input type="text" id="loginId" class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500 text-white placeholder-white/60 text-base" placeholder="Identifiant anonyme" required>
</div>
<div>
<input type="password" id="loginPassword" class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500 text-white placeholder-white/60 text-base" placeholder="Mot de passe" required>
</div>
<button type="submit" class="w-full bg-gradient-to-r from-pink-500 to-violet-500 hover:from-pink-600 hover:to-violet-600 text-white font-medium py-3 px-4 rounded-xl transition duration-200">
<span data-translate="connect">Se connecter</span>
</button>
</div>
</form>
<!-- Formulaire d'inscription -->
<form id="registerForm" class="hidden">
<div class="space-y-4">
<div>
<select id="regionSelect" class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500 text-white text-base">
<option value="africa">🌍 Afrique</option>
<option value="europe">🇪🇺 Europe</option>
<option value="asia">🌏 Asie</option>
<option value="americas">🌎 Amériques</option>
<option value="oceania">🏝️ Océanie</option>
<option value="middle-east">🕌 Moyen-Orient</option>
</select>
</div>
<div>
<input type="text" id="regId" class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500 text-white placeholder-white/60 text-base" placeholder="Créez votre ID anonyme" required>
</div>
<div>
<input type="password" id="regPassword" class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500 text-white placeholder-white/60 text-base" placeholder="Mot de passe" required>
</div>
<div>
<input type="password" id="regConfirmPassword" class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500 text-white placeholder-white/60 text-base" placeholder="Confirmer le mot de passe" required>
</div>
<div class="flex items-start">
<input type="checkbox" id="terms" class="mt-1 mr-3 w-4 h-4" required>
<label for="terms" class="text-sm text-white/80">
<span data-translate="accept_terms">J'accepte les conditions d'utilisation et je m'engage à respecter l'anonymat et la vérité</span>
</label>
</div>
<button type="submit" class="w-full bg-gradient-to-r from-pink-500 to-violet-500 hover:from-pink-600 hover:to-violet-600 text-white font-medium py-3 px-4 rounded-xl transition duration-200">
<span data-translate="create_account">Créer un compte</span>
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Page principale - Style TikTok -->
<div id="mainPage" class="hidden relative h-screen overflow-hidden">
<!-- Header fixe -->
<header class="fixed top-0 left-0 right-0 bg-black/80 backdrop-blur-md z-40 px-4 py-3">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<div class="w-8 h-8 bg-gradient-to-r from-pink-500 to-violet-500 rounded-lg flex items-center justify-center">
<i data-lucide="shield-check" class="w-5 h-5 text-white"></i>
</div>
<h1 class="text-xl font-bold gradient-text">TITA</h1>
</div>
<div class="flex items-center space-x-3">
<button id="searchBtn" class="p-2 hover:bg-white/10 rounded-lg">
<i data-lucide="search" class="w-5 h-5"></i>
</button>
<select id="languageSelect" class="bg-white/10 text-white rounded-lg px-3 py-1 text-sm border border-white/20">
<option value="fr">FR</option>
<option value="en">EN</option>
<option value="es">ES</option>
<option value="ar">AR</option>
</select>
</div>
</div>
</header>
<!-- Navigation horizontale des catégories -->
<div class="fixed top-16 left-0 right-0 bg-black/80 backdrop-blur-md z-40 px-4 py-2">
<div class="flex space-x-6 overflow-x-auto scrollbar-hide">
<button class="category-filter active text-white font-medium whitespace-nowrap py-2 px-1 border-b-2 border-pink-500" data-category="all">
<span data-translate="all">Tout</span>
</button>
<button class="category-filter text-gray-400 font-medium whitespace-nowrap py-2 px-1 border-b-2 border-transparent" data-category="politics">
<span data-translate="politics">Politique</span>
</button>
<button class="category-filter text-gray-400 font-medium whitespace-nowrap py-2 px-1 border-b-2 border-transparent" data-category="economy">
<span data-translate="economy">Économie</span>
</button>
<button class="category-filter text-gray-400 font-medium whitespace-nowrap py-2 px-1 border-b-2 border-transparent" data-category="sports">
<span data-translate="sports">Sport</span>
</button>
<button class="category-filter text-gray-400 font-medium whitespace-nowrap py-2 px-1 border-b-2 border-transparent" data-category="social">
<span data-translate="social">Social</span>
</button>
</div>
</div>
<!-- Feed principal style TikTok -->
<div id="feedContainer" class="h-full pt-28 pb-20 overflow-y-auto snap-y snap-mandatory">
<!-- Les posts seront ajoutés ici -->
</div>
<!-- Navigation en bas -->
<nav class="fixed bottom-0 left-0 right-0 bg-black/90 backdrop-blur-md z-50 border-t border-gray-800">
<div class="flex justify-around items-center py-2">
<button class="nav-tab active flex flex-col items-center py-2 px-3 text-white" data-view="home">
<i data-lucide="home" class="w-6 h-6 mb-1"></i>
<span class="text-xs" data-translate="home">Accueil</span>
</button>
<button class="nav-tab flex flex-col items-center py-2 px-3 text-gray-400" data-view="discover">
<i data-lucide="compass" class="w-6 h-6 mb-1"></i>
<span class="text-xs" data-translate="discover">Découvrir</span>
</button>
<button id="createBtn" class="flex flex-col items-center py-2 px-3">
<div class="w-12 h-8 bg-gradient-to-r from-pink-500 to-violet-500 rounded-lg flex items-center justify-center mb-1">
<i data-lucide="plus" class="w-5 h-5 text-white"></i>
</div>
</button>
<button class="nav-tab flex flex-col items-center py-2 px-3 text-gray-400" data-view="trending">
<i data-lucide="trending-up" class="w-6 h-6 mb-1"></i>
<span class="text-xs" data-translate="trending">Tendances</span>
</button>
<button id="profileBtn" class="flex flex-col items-center py-2 px-3 text-gray-400">
<i data-lucide="user" class="w-6 h-6 mb-1"></i>
<span class="text-xs" data-translate="profile">Profil</span>
</button>
</div>
</nav>
<!-- Modal de création -->
<div id="createModal" class="fixed inset-0 bg-black/95 backdrop-blur-md z-50 hidden">
<div class="h-full flex flex-col">
<!-- Header -->
<div class="flex items-center justify-between p-4 text-white">
<button id="closeCreateModal" class="p-2 hover:bg-white/10 rounded-lg">
<i data-lucide="x" class="w-6 h-6"></i>
</button>
<h2 class="text-lg font-medium" data-translate="share_truth">Partagez votre vérité</h2>
<button id="publishPost" class="bg-gradient-to-r from-pink-500 to-violet-500 px-6 py-2 rounded-full text-sm font-medium disabled:opacity-50">
<span data-translate="publish">Publier</span>
</button>
</div>
<!-- Formulaire -->
<div class="flex-1 p-4 overflow-y-auto">
<form id="postForm" class="space-y-4">
<div>
<select id="postCategory" class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500 text-white text-base">
<option value="politics">🏛️ Politique</option>
<option value="economy">📈 Économie</option>
<option value="sports">⚽ Sport</option>
<option value="social">👥 Social</option>
</select>
</div>
<div>
<input type="text" id="postTitle" class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500 text-white placeholder-white/60 text-base" placeholder="Titre de votre révélation..." required>
</div>
<div>
<textarea id="postContent" rows="8" class="w-full px-4 py-3 bg-white/10 border border-white/20 rounded-xl focus:outline-none focus:ring-2 focus:ring-pink-500 text-white placeholder-white/60 text-base resize-none" placeholder="Dévoilez les faits, exposez la vérité... Partagez votre témoignage anonyme et contribuez à révéler la vérité au monde entier." required></textarea>
</div>
<div class="flex items-center space-x-2 text-sm text-gray-400 bg-white/5 p-3 rounded-xl">
<i data-lucide="shield" class="w-4 h-4"></i>
<span data-translate="anonymous_post">Publication anonyme et sécurisée</span>
</div>
</form>
</div>
</div>
</div>
<!-- Modal profil -->
<div id="profileModal" class="fixed inset-0 bg-black/95 backdrop-blur-md z-50 hidden">
<div class="h-full flex flex-col text-white">
<!-- Header -->
<div class="flex items-center justify-between p-4">
<button id="closeProfileModal" class="p-2 hover:bg-white/10 rounded-lg">
<i data-lucide="x" class="w-6 h-6"></i>
</button>
<h2 class="text-lg font-medium" data-translate="profile">Profil</h2>
<div></div>
</div>
<!-- Contenu profil -->
<div class="flex-1 p-4 overflow-y-auto">
<div class="text-center mb-8">
<div class="w-24 h-24 bg-gradient-to-r from-pink-500 to-violet-500 rounded-full flex items-center justify-center mx-auto mb-4">
<i data-lucide="shield" class="w-12 h-12 text-white"></i>
</div>
<h3 id="profileUsername" class="text-2xl font-bold mb-2"></h3>
<p class="text-gray-400" data-translate="anonymous_user">Utilisateur anonyme</p>
<div id="userRegionDisplay" class="mt-2 text-lg"></div>
</div>
<!-- Statistiques -->
<div class="grid grid-cols-3 gap-4 mb-8">
<div class="text-center post-card p-4 rounded-xl">
<div id="userPostsCount" class="text-2xl font-bold text-pink-400">0</div>
<div class="text-gray-400 text-sm" data-translate="posts">Publications</div>
</div>
<div class="text-center post-card p-4 rounded-xl">
<div id="userLikesCount" class="text-2xl font-bold text-violet-400">0</div>
<div class="text-gray-400 text-sm" data-translate="likes">J'aime</div>
</div>
<div class="text-center post-card p-4 rounded-xl">
<div id="userCommentsCount" class="text-2xl font-bold text-blue-400">0</div>
<div class="text-gray-400 text-sm" data-translate="comments">Commentaires</div>
</div>
</div>
<!-- Actions -->
<div class="space-y-4">
<button class="w-full post-card py-4 px-4 rounded-xl flex items-center justify-center space-x-2 hover:bg-white/20 transition-all">
<i data-lucide="settings" class="w-5 h-5"></i>
<span data-translate="settings">Paramètres</span>
</button>
<button class="w-full post-card py-4 px-4 rounded-xl flex items-center justify-center space-x-2 hover:bg-white/20 transition-all">
<i data-lucide="info" class="w-5 h-5"></i>
<span data-translate="about">À propos de TITA</span>
</button>
<button id="logoutBtnProfile" class="w-full bg-red-500/20 border border-red-500/30 text-red-400 py-4 px-4 rounded-xl flex items-center justify-center space-x-2 hover:bg-red-500/30 transition-all">
<i data-lucide="log-out" class="w-5 h-5"></i>
<span data-translate="logout">Déconnexion</span>
</button>
</div>
</div>
</div>
</div>
</div>
<script>
// Initialisation de Lucide
lucide.createIcons();
// Gestion du mode sombre (reste noir pour TikTok style)
document.documentElement.classList.add('dark');
// Données simulées
let users = [
{ id: 'anon123', password: 'test123', region: 'europe' },
{ id: 'truth_seeker', password: 'password', region: 'africa' },
{ id: 'whistleblower', password: '123456', region: 'americas' }
];
let posts = [];
let currentUser = null;
let currentCategory = 'all';
// Traductions
const translations = {
fr: {
login: "Connexion",
register: "Inscription",
connect: "Se connecter",
create_account: "Créer un compte",
accept_terms: "J'accepte les conditions d'utilisation et je m'engage à respecter l'anonymat et la vérité",
all: "Tout",
politics: "Politique",
economy: "Économie",
sports: "Sport",
social: "Social",
share_truth: "Partagez votre vérité",
publish: "Publier",
anonymous_post: "Publication anonyme et sécurisée",
profile: "Profil",
home: "Accueil",
discover: "Découvrir",
trending: "Tendances",
anonymous_user: "Utilisateur anonyme",
posts: "Publications",
likes: "J'aime",
comments: "Commentaires",
settings: "Paramètres",
about: "À propos de TITA",
logout: "Déconnexion",
like: "J'aime",
comment: "Commenter",
share: "Partager",
reply: "Répondre"
},
en: {
login: "Login",
register: "Register",
connect: "Connect",
create_account: "Create Account",
accept_terms: "I accept the terms of use and commit to respecting anonymity and truth",
all: "All",
politics: "Politics",
economy: "Economy",
sports: "Sports",
social: "Social",
share_truth: "Share your truth",
publish: "Publish",
anonymous_post: "Anonymous and secure post",
profile: "Profile",
home: "Home",
discover: "Discover",
trending: "Trending",
anonymous_user: "Anonymous user",
posts: "Posts",
likes: "Likes",
comments: "Comments",
settings: "Settings",
about: "About TITA",
logout: "Logout",
like: "Like",
comment: "Comment",
share: "Share",
reply: "Reply"
}
};
let currentLanguage = 'fr';
function updateTranslations() {
const elements = document.querySelectorAll('[data-translate]');
elements.forEach(element => {
const key = element.getAttribute('data-translate');
if (translations[currentLanguage] && translations[currentLanguage][key]) {
element.textContent = translations[currentLanguage][key];
}
});
}
// Gestion des onglets d'authentification
document.getElementById('loginTab').addEventListener('click', () => {
document.getElementById('loginTab').classList.add('bg-white', 'text-black');
document.getElementById('loginTab').classList.remove('text-white/80');
document.getElementById('registerTab').classList.remove('bg-white', 'text-black');
document.getElementById('registerTab').classList.add('text-white/80');
document.getElementById('loginForm').classList.remove('hidden');
document.getElementById('registerForm').classList.add('hidden');
});
document.getElementById('registerTab').addEventListener('click', () => {
document.getElementById('registerTab').classList.add('bg-white', 'text-black');
document.getElementById('registerTab').classList.remove('text-white/80');
document.getElementById('loginTab').classList.remove('bg-white', 'text-black');
document.getElementById('loginTab').classList.add('text-white/80');
document.getElementById('registerForm').classList.remove('hidden');
document.getElementById('loginForm').classList.add('hidden');
});
// Gestion du changement de langue
document.getElementById('languageSelect').addEventListener('change', (e) => {
currentLanguage = e.target.value;
updateTranslations();
});
// Connexion
document.getElementById('loginForm').addEventListener('submit', (e) => {
e.preventDefault();
const id = document.getElementById('loginId').value;
const password = document.getElementById('loginPassword').value;
const user = users.find(u => u.id === id && u.password === password);
if (user) {
currentUser = user;
showMainPage();
} else {
showCustomAlert('Identifiant ou mot de passe incorrect');
}
});
// Inscription
document.getElementById('registerForm').addEventListener('submit', (e) => {
e.preventDefault();
const id = document.getElementById('regId').value;
const password = document.getElementById('regPassword').value;
const confirmPassword = document.getElementById('regConfirmPassword').value;
const region = document.getElementById('regionSelect').value;
if (password !== confirmPassword) {
showCustomAlert('Les mots de passe ne correspondent pas');
return;
}
if (users.find(u => u.id === id)) {
showCustomAlert('Cet identifiant existe déjà');
return;
}
const newUser = { id, password, region };
users.push(newUser);
currentUser = newUser;
showMainPage();
});
// Afficher la page principale
function showMainPage() {
document.getElementById('authPage').classList.add('hidden');
document.getElementById('mainPage').classList.remove('hidden');
loadPosts();
updateProfileInfo();
}
// Déconnexion
document.getElementById('logoutBtnProfile').addEventListener('click', () => {
currentUser = null;
document.getElementById('authPage').classList.remove('hidden');
document.getElementById('mainPage').classList.add('hidden');
document.getElementById('profileModal').classList.add('hidden');
document.getElementById('loginForm').reset();
document.getElementById('registerForm').reset();
});
// Gestion des modales
document.getElementById('createBtn').addEventListener('click', () => {
document.getElementById('createModal').classList.remove('hidden');
});
document.getElementById('closeCreateModal').addEventListener('click', () => {
document.getElementById('createModal').classList.add('hidden');
});
document.getElementById('profileBtn').addEventListener('click', () => {
document.getElementById('profileModal').classList.remove('hidden');
});
document.getElementById('closeProfileModal').addEventListener('click', () => {
document.getElementById('profileModal').classList.add('hidden');
});
// Gestion des filtres de catégories
document.querySelectorAll('.category-filter').forEach(filter => {
filter.addEventListener('click', () => {
document.querySelectorAll('.category-filter').forEach(f => {
f.classList.remove('active', 'text-white', 'border-pink-500');
f.classList.add('text-gray-400', 'border-transparent');
});
filter.classList.add('active', 'text-white', 'border-pink-500');
filter.classList.remove('text-gray-400', 'border-transparent');
currentCategory = filter.getAttribute('data-category');
loadPosts();
});
});
// Publication
document.getElementById('publishPost').addEventListener('click', (e) => {
e.preventDefault();
const category = document.getElementById('postCategory').value;
const title = document.getElementById('postTitle').value;
const content = document.getElementById('postContent').value;
if (!title || !content) {
showCustomAlert('Veuillez remplir tous les champs');
return;
}
const newPost = {
id: Date.now(),
category,
title,
content,
author: currentUser.id,
region: currentUser.region,
timestamp: new Date(),
likes: Math.floor(Math.random() * 100),
comments: [],
liked: false
};
posts.unshift(newPost);
document.getElementById('postForm').reset();
document.getElementById('createModal').classList.add('hidden');
loadPosts();
updateProfileInfo();
});
// Charger les publications
function loadPosts() {
const container = document.getElementById('feedContainer');
const filteredPosts = currentCategory === 'all' ? posts : posts.filter(p => p.category === currentCategory);
container.innerHTML = filteredPosts.map(post => `
<div class="snap-start h-screen flex flex-col justify-center p-4 relative" data-post-id="${post.id}">
<!-- Arrière-plan dégradé -->
<div class="absolute inset-0 bg-gradient-to-br ${getRandomGradient()} opacity-20"></div>
<!-- Contenu principal -->
<div class="relative z-10 flex-1 flex flex-col justify-center max-w-lg mx-auto w-full">
<!-- Header du post -->
<div class="flex items-center justify-between mb-6">
<div class="flex items-center space-x-3">
<div class="w-12 h-12 bg-gradient-to-r from-pink-500 to-violet-500 rounded-full flex items-center justify-center">
<i data-lucide="shield" class="w-6 h-6 text-white"></i>
</div>
<div>
<div class="font-medium text-white">Anonyme</div>
<div class="text-sm text-gray-300">${getRegionFlag(post.region)} ${getRegionName(post.region)}</div>
</div>
</div>
<div class="text-xs text-gray-400">${formatTimeAgo(post.timestamp)}</div>
</div>
<!-- Catégorie -->
<div class="mb-4">
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-${getCategoryColor(post.category)}/20 text-${getCategoryColor(post.category)}-300 border border-${getCategoryColor(post.category)}/30">
${getCategoryIcon(post.category)} ${getCategoryName(post.category)}
</span>
</div>
<!-- Contenu -->
<div class="post-card rounded-2xl p-6 mb-6">
<h2 class="text-xl font-bold text-white mb-4 leading-tight">${post.title}</h2>
<p class="text-gray-200 text-base leading-relaxed">${post.content}</p>
</div>
</div>
<!-- Actions à droite (style TikTok) -->
<div class="absolute right-4 bottom-32 flex flex-col space-y-6">
<button onclick="toggleLike(${post.id})" class="flex flex-col items-center space-y-1 transition-transform active:scale-125">
<div class="w-12 h-12 ${post.liked ? 'bg-red-500' : 'bg-white/20'} rounded-full flex items-center justify-center backdrop-blur-md">
<i data-lucide="heart" class="w-6 h-6 ${post.liked ? 'text-white fill-current' : 'text-white'}"></i>
</div>
<span class="text-white text-xs font-medium">${post.likes}</span>
</button>
<button onclick="toggleComments(${post.id})" class="flex flex-col items-center space-y-1 transition-transform active:scale-125">
<div class="w-12 h-12 bg-white/20 rounded-full flex items-center justify-center backdrop-blur-md">
<i data-lucide="message-circle" class="w-6 h-6 text-white"></i>
</div>
<span class="text-white text-xs font-medium">${post.comments.length}</span>
</button>
<button onclick="sharePost(${post.id})" class="flex flex-col items-center space-y-1 transition-transform active:scale-125">
<div class="w-12 h-12 bg-white/20 rounded-full flex items-center justify-center backdrop-blur-md">
<i data-lucide="share" class="w-6 h-6 text-white"></i>
</div>
<span class="text-white text-xs font-medium">${translations[currentLanguage].share}</span>
</button>
</div>
<!-- Zone de commentaires -->
<div id="comments-${post.id}" class="absolute bottom-0 left-0 right-0 bg-black/80 backdrop-blur-md transform translate-y-full transition-transform duration-300 max-h-80 overflow-y-auto">
<div class="p-4">
<div class="flex items-center justify-between mb-4">
<h3 class="text-white font-medium">${post.comments.length} commentaires</h3>
<button onclick="toggleComments(${post.id})" class="text-gray-400 hover:text-white">
<i data-lucide="x" class="w-5 h-5"></i>
</button>
</div>
<div class="space-y-3 mb-4">
${post.comments.map(comment => `
<div class="flex space-x-3">
<div class="w-8 h-8 bg-gradient-to-r from-pink-500 to-violet-500 rounded-full flex items-center justify-center flex-shrink-0">
<i data-lucide="shield" class="w-4 h-4 text-white"></i>
</div>
<div class="flex-1">
<div class="bg-white/10 rounded-2xl p-3">
<p class="text-white text-sm">${comment.content}</p>
</div>
<div class="text-xs text-gray-400 mt-1">${formatTimeAgo(comment.timestamp)}</div>
</div>
</div>
`).join('')}
</div>
<form onsubmit="addComment(event, ${post.id})" class="flex space-x-2">
<input type="text" placeholder="Ajouter un commentaire..." class="flex-1 bg-white/10 text-white px-4 py-2 rounded-full focus:outline-none focus:ring-2 focus:ring-pink-500 text-base" required>
<button type="submit" class="bg-gradient-to-r from-pink-500 to-violet-500 text-white px-6 py-2 rounded-full text-sm font-medium">
${translations[currentLanguage].reply}
</button>
</form>
</div>
</div>
</div>
`).join('');
// Réinitialiser les icônes Lucide
lucide.createIcons();
}
// Fonctions utilitaires
function getRandomGradient() {
const gradients = [
'from-purple-900 to-blue-900',
'from-pink-900 to-purple-900',
'from-blue-900 to-indigo-900',
'from-indigo-900 to-purple-900',
'from-red-900 to-pink-900'
];
return gradients[Math.floor(Math.random() * gradients.length)];
}
function getCategoryColor(category) {
const colors = {
politics: 'blue',
economy: 'green',
sports: 'orange',
social: 'purple'
};
return colors[category] || 'gray';
}
function getCategoryIcon(category) {
const icons = {
politics: '🏛️',
economy: '📈',
sports: '⚽',
social: '👥'
};
return icons[category] || '📝';
}
function getCategoryName(category) {
return translations[currentLanguage][category] || category;
}
function getRegionFlag(region) {
const flags = {
africa: '🌍',
europe: '🇪🇺',
asia: '🌏',
americas: '🌎',
oceania: '🏝️',
'middle-east': '🕌'
};
return flags[region] || '🌐';
}
function getRegionName(region) {
const names = {
africa: 'Afrique',
europe: 'Europe',
asia: 'Asie',
americas: 'Amériques',
oceania: 'Océanie',
'middle-east': 'Moyen-Orient'
};
return names[region] || region;
}
function formatTimeAgo(date) {
const now = new Date();
const diff = now - date;
const minutes = Math.floor(diff / 60000);
const hours = Math.floor(diff / 3600000);
const days = Math.floor(diff / 86400000);
if (days > 0) return `${days}j`;
if (hours > 0) return `${hours}h`;
if (minutes > 0) return `${minutes}min`;
return 'maintenant';
}
function toggleLike(postId) {
const post = posts.find(p => p.id === postId);
if (post) {
post.liked = !post.liked;
post.likes += post.liked ? 1 : -1;
loadPosts();
}
}
function toggleComments(postId) {
const commentsDiv = document.getElementById(`comments-${postId}`);
const isVisible = !commentsDiv.classList.contains('translate-y-full');
// Fermer tous les autres commentaires
document.querySelectorAll('[id^="comments-"]').forEach(div => {
div.classList.add('translate-y-full');
});
if (!isVisible) {
commentsDiv.classList.remove('translate-y-full');
}
}
function addComment(event, postId) {
event.preventDefault();
const form = event.target;
const content = form.querySelector('input').value;
const post = posts.find(p => p.id === postId);
if (post) {
post.comments.push({
content,
timestamp: new Date(),
author: currentUser.id
});
form.reset();
loadPosts();
// Rouvrir les commentaires
setTimeout(() => {
toggleComments(postId);
}, 100);
}
}
function sharePost(postId) {
showCustomAlert('Fonction de partage bientôt disponible!');
}
function updateProfileInfo() {
if (currentUser) {
document.getElementById('profileUsername').textContent = currentUser.id;
document.getElementById('userRegionDisplay').textContent = `${getRegionFlag(currentUser.region)} ${getRegionName(currentUser.region)}`;
const userPosts = posts.filter(p => p.author === currentUser.id);
const userLikes = userPosts.reduce((total, post) => total + post.likes, 0);
const userComments = userPosts.reduce((total, post) => total + post.comments.length, 0);
document.getElementById('userPostsCount').textContent = userPosts.length;
document.getElementById('userLikesCount').textContent = userLikes;
document.getElementById('userCommentsCount').textContent = userComments;
}
}
function showCustomAlert(message) {
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black/80 backdrop-blur-md flex items-center justify-center z-50';
modal.innerHTML = `
<div class="post-card p-6 rounded-2xl max-w-sm w-full mx-4">
<p class="text-white mb-4 text-center">${message}</p>
<div class="flex justify-center">
<button class="bg-gradient-to-r from-pink-500 to-violet-500 text-white px-6 py-2 rounded-full font-medium" onclick="this.closest('.fixed').remove()">OK</button>
</div>
</div>
`;
document.body.appendChild(modal);
}
// Données d'exemple
posts = [
{
id: 1,
category: 'politics',
title: 'Corruption dans les marchés publics révélée',
content: 'Je révèle des pratiques douteuses dans l\'attribution des marchés publics de ma région. Les preuves sont accablantes et montrent un système de favoritisme qui coûte des millions aux contribuables.',
author: 'anon123',
region: 'africa',
timestamp: new Date(Date.now() - 2 * 60 * 1000),
likes: 127,
comments: [
{
content: 'Merci pour ce courage. Il faut que la vérité soit révélée.',
timestamp: new Date(Date.now() - 1 * 60 * 1000),
author: 'truth_seeker'
}
],
liked: false
},
{
id: 2,
category: 'economy',
title: 'Fraude fiscale massive découverte',
content: 'Une entreprise multinationale évite des millions d\'impôts grâce à des montages offshore complexes. J\'ai les documents qui le prouvent.',
author: 'whistleblower',
region: 'europe',
timestamp: new Date(Date.now() - 30 * 60 * 1000),
likes: 89,
comments: [],
liked: false
},
{
id: 3,
category: 'social',
title: 'Discrimination systémique exposée',
content: 'Dans mon entreprise, les promotions sont refusées systématiquement aux employés de certaines origines. J\'ai documenté ces pratiques pendant des mois.',
author: 'justice_seeker',
region: 'americas',
timestamp: new Date(Date.now() - 1 * 60 * 60 * 1000),
likes: 156,
comments: [
{
content: 'Courage à vous, ces pratiques doivent cesser.',
timestamp: new Date(Date.now() - 30 * 60 * 1000),
author: 'support_user'
},
{
content: 'Même situation chez nous, c\'est révoltant.',
timestamp: new Date(Date.now() - 15 * 60 * 1000),
author: 'solidarity'
}
],
liked: false
}
];
// Initialisation
updateTranslations();
</script>
</body>
</html> J'ai complètement transformé TITA pour avoir une interface et une expérience similaire à TikTok avec : 🎨 Interface style TikTok :
📱 Expérience utilisateur TikTok :
🔥 Fonctionnalités sociales :
✨ Améliorations visuelles :
🌍 Fonctionnalités anonymes préservées :
L'application offre maintenant une expérience moderne et engageante similaire à TikTok tout en préservant l'objectif de dénonciation anonyme et sécurisée ! |
Improve |
Thinking...
Je vais transformer TITA en une super-plateforme sociale anonyme combinant toutes ces fonctionnalités avec un système de gamification et de monétisation.
Maintenant je vais ajouter toutes les pages et fonctionnalités avancées demandées :