export default function CommunauteGracePartage() {
// ============================================================
// ÉTAT GLOBAL & BASE DE DONNÉES SIMULÉE (STRUCTURE PRÊTE)
// ============================================================
const [page, setPage] = React.useState('home');
const [currentUser, setCurrentUser] = React.useState(null);
const [menuOpen, setMenuOpen] = React.useState(false);
const [preselectedPackage, setPreselectedPackage] = React.useState(null);
// Structure tableaux : 3 packs × 3 tableaux × 7 positions
const initialTables = {
goal: [
{ id: 'Goal Tableau 1', members: [] },
{ id: 'Goal Tableau 2', members: [] },
{ id: 'Goal Tableau 3', members: [] }
],
bronze: [
{ id: 'Bronze Tableau 1', members: [] },
{ id: 'Bronze Tableau 2', members: [] },
{ id: 'Bronze Tableau 3', members: [] }
],
platinium: [
{ id: 'Platinium Tableau 1', members: [] },
{ id: 'Platinium Tableau 2', members: [] },
{ id: 'Platinium Tableau 3', members: [] }
]
};
const [tables, setTables] = React.useState(initialTables);
// Utilisateurs (admin pré-saisi pour démo)
const [users, setUsers] = React.useState([
{
id: 'u-admin',
nom: 'System',
prenom: 'Admin',
username: 'admin',
emailOrPhone: 'admin@cgap.ht',
password: 'admin',
package: 'platinium',
referralCode: 'ADMIN-001',
sponsorId: null,
tableId: 'Admin',
position: '-',
isAdmin: true,
date: new Date().toLocaleDateString('fr-FR')
}
]);
// ============================================================
// UTILITAIRES
// ============================================================
const generateId = () => Math.random().toString(36).substring(2, 9);
const generateRefCode = () => `REF-${Math.random().toString(36).substring(2, 6).toUpperCase()}`;
const navigate = (p) => {
setPage(p);
setMenuOpen(false);
window.scrollTo({ top: 0, behavior: 'smooth' });
};
const getUserById = (id) => users.find((u) => u.id === id);
const getSponsor = (u) => users.find((x) => x.id === u.sponsorId);
const getFilleuls = (u) => users.filter((x) => x.sponsorId === u.id);
const getPackageColor = (pkg) => {
if (pkg === 'goal') return 'emerald';
if (pkg === 'bronze') return 'amber';
return 'indigo';
};
// ============================================================
// AUTHENTIFICATION & INSCRIPTION
// ============================================================
const handleRegister = (form) => {
if (users.some((u) => u.username === form.username)) {
alert("Ce nom d'utilisateur est déjà pris.");
return;
}
if (users.some((u) => u.emailOrPhone === form.emailOrPhone)) {
alert('Cet email ou numéro est déjà utilisé.');
return;
}
if (form.password !== form.confirmPassword) {
alert('Les mots de passe ne correspondent pas.');
return;
}
// Placement automatique dans le premier tableau disponible
const pkgTables = tables[form.package];
const nextTables = pkgTables.map((t) => ({ ...t, members: [...t.members] }));
let assignedTable = null;
let assignedPos = null;
for (const t of nextTables) {
if (!assignedTable && t.members.length < 7) {
t.members.push(form.username + '-' + generateId()); // placeholder temp, remplacé par id ensuite
assignedTable = t.id;
assignedPos = t.members.length;
}
}
// Création utilisateur
const newUser = {
id: generateId(),
nom: form.nom,
prenom: form.prenom,
username: form.username,
emailOrPhone: form.emailOrPhone,
password: form.password,
package: form.package,
referralCode: generateRefCode(),
sponsorId: null,
tableId: assignedTable || 'En attente',
position: assignedPos || '-',
date: new Date().toLocaleDateString('fr-FR')
};
// Lien de parrainage
if (form.sponsorCode) {
const parrain = users.find(
(u) => u.referralCode === form.sponsorCode || u.username === form.sponsorCode
);
if (parrain) newUser.sponsorId = parrain.id;
}
// Remplace le placeholder username par le vrai id
nextTables.forEach((t) => {
const idx = t.members.indexOf(form.username + '-' + newUser.id);
if (idx >= 0) t.members[idx] = newUser.id;
});
// Oups, la logique ci-dessus est bancale : refaisons proprement
// On recalcule proprement
const finalTables = tables[form.package].map((t) => ({ ...t, members: [...t.members] }));
let tableId = null;
let position = null;
for (const t of finalTables) {
if (!tableId && t.members.length < 7) {
t.members.push(newUser.id);
tableId = t.id;
position = t.members.length;
break;
}
}
setTables({ ...tables, [form.package]: finalTables });
newUser.tableId = tableId || 'En attente';
newUser.position = position || '-';
setUsers([...users, newUser]);
setCurrentUser(newUser);
navigate('dashboard');
};
const handleLogin = (username, password) => {
const found = users.find(
(u) => (u.username === username || u.emailOrPhone === username) && u.password === password
);
if (found) {
setCurrentUser(found);
navigate(found.isAdmin ? 'admin' : 'dashboard');
} else {
alert("Nom d'utilisateur / mot de passe incorrect.");
}
};
const handleLogout = () => {
setCurrentUser(null);
navigate('home');
};
// ============================================================
// COMPOSANTS RÉUTILISABLES
// ============================================================
const Btn = ({ children, onClick, variant = 'primary', className = '' }) => {
const base =
'inline-flex items-center justify-center px-6 py-3 rounded-xl font-semibold transition transform hover:scale-105 active:scale-95 shadow-md ';
const colors = {
primary: 'bg-emerald-600 text-white hover:bg-emerald-700 ',
secondary: 'bg-white text-slate-700 border border-slate-200 hover:bg-slate-50 ',
goal: 'bg-emerald-600 text-white hover:bg-emerald-700 ',
bronze: 'bg-amber-600 text-white hover:bg-amber-700 ',
platinium: 'bg-indigo-600 text-white hover:bg-indigo-700 '
};
return (
);
};
const Card = ({ children, className = '' }) => (
{children}
);
const SectionTitle = ({ children, subtitle }) => (
{children}
{subtitle &&
{subtitle}
}
);
const ContactBlock = ({ compact }) => (
Contact & Informations
Nom : St Fort Joseph Charly
Adresse : Delmas, Haiti
Email :{' '}
communautegracepartage@gmail.com
WhatsApp / Téléphone : +509 40928148
Natcash : +509 40928148
MonCash : +509 31966582
);
// ============================================================
// NAVBAR
// ============================================================
const Navbar = () => {
const navLink = (label, target) => (
);
return (
);
};
// ============================================================
// FOOTER
// ============================================================
const Footer = () => (
);
// ============================================================
// PAGE D'ACCUEIL
// ============================================================
const HomePage = () => {
const packages = [
{
key: 'goal',
name: 'GOAL',
price: '$200 HT',
color: 'emerald',
features: ['Accès tableau Goal', '7 positions solidaires', 'Support communautaire']
},
{
key: 'bronze',
name: 'BRONZE',
price: '$400 HT',
color: 'amber',
features: ['Accès tableau Bronze', 'Réseau étendu', 'Accompagnement prioritaire']
},
{
key: 'platinium',
name: 'PLATINIUM',
price: '$800 HT',
color: 'indigo',
features: ['Accès tableau Platinium', 'Communauté premium', 'Opportunités avancées']
}
];
const bgGradient = (color) =>
color === 'emerald'
? 'from-emerald-500 to-teal-600'
: color === 'amber'
? 'from-amber-500 to-orange-600'
: 'from-indigo-500 to-purple-600';
return (
Bienvenue dans la Communauté Grace & Partage
Une communauté basée sur la participation, le partage et la solidarité.
navigate('register')}>Rejoindre la communauté
Nos Packs
{packages.map((pkg) => (
{pkg.name}
{pkg.price}
{pkg.features.map((f, i) => (
-
{f}
))}
{
setPreselectedPackage(pkg.key);
navigate('register');
}}
>
Rejoindre {pkg.name}
))}
);
};
// ============================================================
// PAGE INSCRIPTION
// ============================================================
const RegisterPage = () => {
const [form, setForm] = React.useState({
nom: '',
prenom: '',
username: '',
emailOrPhone: '',
password: '',
confirmPassword: '',
package: preselectedPackage || 'goal',
sponsorCode: ''
});
const update = (field, value) => setForm((f) => ({ ...f, [field]: value }));
return (
Besoin d'aide pour vous inscrire ?
Contactez-nous directement via WhatsApp ou par email. Notre équipe vous guidera.
);
};
// ============================================================
// PAGE CONNEXION
// ============================================================
const LoginPage = () => {
const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState('');
return (
);
};
// ============================================================
// PAGE TABLEAU DE BORD MEMBRE
// ============================================================
const DashboardPage = () => {
if (!currentUser) {
navigate('login');
return null;
}
const sponsor = getSponsor(currentUser);
const filleuls = getFilleuls(currentUser);
const userTable = tables[currentUser.package].find((t) => t.id === currentUser.tableId);
const copyToClipboard = (text) => {
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(text);
}
alert('Copié dans le presse-papiers !');
};
return (
Bonjour, {currentUser.prenom} 👋
Voici votre espace personnel et vos informations de table.
Package
{currentUser.package}
Tableau
{currentUser.tableId}
Position
{currentUser.position}
Parrain
{sponsor ? sponsor.username : 'Aucun'}
Mon tableau ({currentUser.tableId})
{userTable ? (
{Array.from({ length: 7 }).map((_, idx) => {
const memberId = userTable.members[idx];
const member = memberId ? getUserById(memberId) : null;
const isMe = memberId === currentUser.id;
return (
Pos {idx + 1}
{member ? member.username : 'Libre'}
);
})}
) : (
Aucune assignation de table pour le moment.
)}
Mon parrainage
Code de parrainage
{currentUser.referralCode}
Lien de parrainage
{`https://gracepartage.app/?ref=${currentUser.referralCode}`}
Membres invités : {filleuls.length}
{filleuls.length === 0 ? (
Vous n'avez pas encore invité de membres.
) : (
{filleuls.map((f) => (
-
@{f.username}
{f.package}
))}
)}
Mon profil
Nom : {currentUser.nom}
Prénom : {currentUser.prenom}
Email / Téléphone :{' '}
{currentUser.emailOrPhone}
Inscrit le : {currentUser.date}
);
};
// ============================================================
// PAGE PARRAINAGE
// ============================================================
const ParrainagePage = () => {
if (!currentUser) {
navigate('login');
return null;
}
const filleuls = getFilleuls(currentUser);
return (
Centre de Parrainage
Votre code de parrainage
{currentUser.referralCode}
Votre lien de parrainage
{`https://gracepartage.app/?ref=${currentUser.referralCode}`}
Mes filleuls ({filleuls.length})
{filleuls.length === 0 ? (
Aucun membre invité pour le moment.
) : (
| Nom utilisateur |
Package |
Tableau |
Date |
{filleuls.map((f) => (
| {f.username} |
{f.package} |
{f.tableId} |
{f.date} |
))}
)}
);
};
// ============================================================
// PAGE ADMIN
// ============================================================
const AdminPage = () => {
if (!currentUser || !currentUser.isAdmin) {
navigate('login');
return null;
}
const [tab, setTab] = React.useState('stats');
const [search, setSearch] = React.useState('');
const [pkgFilter, setPkgFilter] = React.useState('all');
const members = users.filter((u) => !u.isAdmin);
const filtered = members.filter((u) => {
const matchesSearch =
u.nom.toLowerCase().includes(search.toLowerCase()) ||
u.prenom.toLowerCase().includes(search.toLowerCase()) ||
u.username.toLowerCase().includes(search.toLowerCase()) ||
u.emailOrPhone.includes(search);
const matchesPkg = pkgFilter === 'all' || u.package === pkgFilter;
return matchesSearch && matchesPkg;
});
const stats = {
total: members.length,
goal: members.filter((u) => u.package === 'goal').length,
bronze: members.filter((u) => u.package === 'bronze').length,
platinium: members.filter((u) => u.package === 'platinium').length
};
return (
Tableau de bord Administrateur
{['stats', 'members', 'tables', 'sponsors'].map((t) => (
))}
{tab === 'stats' && (
{stats.total}
Membres total
{stats.goal}
Pack Goal
{stats.bronze}
Pack Bronze
{stats.platinium}
Pack Platinium
Répartition des inscriptions
{['goal', 'bronze', 'platinium'].map((pkg) => {
const count = members.filter((u) => u.package === pkg).length;
const pct = stats.total ? Math.round((count / stats.total) * 100) : 0;
return (
);
})}
)}
{tab === 'members' && (
setSearch(e.target.value)}
/>
| Nom |
Prénom |
Utilisateur |
Contact |
Pack |
Tableau |
Position |
Date |
{filtered.map((u) => (
| {u.nom} |
{u.prenom} |
@{u.username} |
{u.emailOrPhone} |
{u.package} |
{u.tableId} |
{u.position} |
{u.date} |
))}
{filtered.length === 0 && (
|
Aucun membre trouvé.
|
)}
)}
{tab === 'tables' && (
{['goal', 'bronze', 'platinium'].map((pkg) => (
{pkg}
{tables[pkg].map((tbl) => (
{tbl.id}
{tbl.members.length} / 7
{Array.from({ length: 7 }).map((_, idx) => {
const uid = tbl.members[idx];
const m = uid ? getUserById(uid) : null;
return (
{idx + 1}
);
})}
{tbl.members.map((uid, idx) => {
const m = getUserById(uid);
return m ? (
{idx + 1}. {m.prenom} {m.nom} (@{m.username})
) : null;
})}
))}
))}
)}
{tab === 'sponsors' && (
Relations de parrainage
| Membre |
Code du membre |
Parrain |
Code du parrain |
Filleuls |
{members.map((u) => {
const sp = getSponsor(u);
const fCount = getFilleuls(u).length;
return (
| @{u.username} |
{u.referralCode} |
{sp ? `@${sp.username}` : '-'} |
{sp ? sp.referralCode : '-'} |
{fCount} |
);
})}
)}
);
};
// ============================================================
// RENDU GLOBAL
// ============================================================
return (
{page === 'home' && }
{page === 'register' && }
{page === 'login' && }
{page === 'dashboard' && }
{page === 'parrainage' && }
{page === 'admin' && }
);
}