inicio
This commit is contained in:
205
index.html
Normal file
205
index.html
Normal file
@@ -0,0 +1,205 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Telegram Mini App - Perfil de Usuario</title>
|
||||
|
||||
<!-- Script Oficial de Telegram WebApp -->
|
||||
<script src="https://telegram.org/js/telegram-web-app.js"></script>
|
||||
|
||||
<!-- React y ReactDOM -->
|
||||
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
|
||||
|
||||
<!-- Babel para JSX -->
|
||||
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
||||
|
||||
<!-- Tailwind CSS -->
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
|
||||
<!-- Iconos Lucide -->
|
||||
<script src="https://unpkg.com/lucide@latest"></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-color: var(--tg-theme-bg-color, #17212b);
|
||||
color: var(--tg-theme-text-color, #ffffff);
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
<script type="text/babel">
|
||||
const { useState, useEffect } = React;
|
||||
|
||||
// Componente de Tarjeta de Información
|
||||
const InfoCard = ({ icon, label, value, isLink }) => {
|
||||
return (
|
||||
<div className="bg-white/10 p-4 rounded-xl flex items-center justify-between mb-3 backdrop-blur-sm border border-white/5 shadow-sm">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="text-blue-400">
|
||||
{icon}
|
||||
</div>
|
||||
<span className="text-gray-300 text-sm font-medium">{label}</span>
|
||||
</div>
|
||||
<div className="text-white font-semibold text-right truncate max-w-[150px]">
|
||||
{isLink && value ? (
|
||||
<span className="text-blue-400">@{value}</span>
|
||||
) : (
|
||||
value || "N/A"
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const App = () => {
|
||||
const [user, setUser] = useState(null);
|
||||
const [isMock, setIsMock] = useState(false);
|
||||
const [themeParams, setThemeParams] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
const tg = window.Telegram.WebApp;
|
||||
|
||||
// 1. Inicializar la WebApp
|
||||
tg.ready();
|
||||
tg.expand(); // Ocupar toda la altura disponible
|
||||
|
||||
// Guardar parámetros de tema para usar colores nativos si se desea
|
||||
setThemeParams(tg.themeParams);
|
||||
|
||||
// 2. Intentar obtener el usuario
|
||||
const telegramUser = tg.initDataUnsafe?.user;
|
||||
|
||||
if (telegramUser) {
|
||||
// Estamos dentro de Telegram con un usuario real
|
||||
setUser(telegramUser);
|
||||
setIsMock(false);
|
||||
|
||||
// Configurar el color del header de Telegram para que coincida con nuestra app
|
||||
tg.setHeaderColor('#1e293b'); // Un color oscuro tipo slate-800
|
||||
} else {
|
||||
// NO estamos en Telegram (ej: navegador web de desarrollo)
|
||||
// Usamos datos falsos para visualizar el diseño
|
||||
setIsMock(true);
|
||||
setUser({
|
||||
id: 123456789,
|
||||
first_name: "Usuario",
|
||||
last_name: "De Prueba",
|
||||
username: "ejemplo_dev",
|
||||
language_code: "es",
|
||||
is_premium: true,
|
||||
allows_write_to_pm: true
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Función para renderizar iconos de Lucide (ya que estamos en CDN)
|
||||
const renderIcon = (name) => {
|
||||
if (!window.lucide) return null;
|
||||
// Mapeo simple de iconos necesarios
|
||||
const icons = {
|
||||
user: <i data-lucide="user" className="w-5 h-5"></i>,
|
||||
id: <i data-lucide="hash" className="w-5 h-5"></i>,
|
||||
globe: <i data-lucide="globe" className="w-5 h-5"></i>,
|
||||
crown: <i data-lucide="crown" className="w-5 h-5"></i>
|
||||
};
|
||||
return icons[name];
|
||||
};
|
||||
|
||||
// Efecto para activar los iconos de Lucide después del renderizado
|
||||
useEffect(() => {
|
||||
if (window.lucide) {
|
||||
window.lucide.createIcons();
|
||||
}
|
||||
});
|
||||
|
||||
if (!user) return <div className="flex justify-center items-center h-screen text-white">Cargando...</div>;
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-slate-900 p-4 flex flex-col items-center pt-8">
|
||||
|
||||
{/* Aviso si estamos en modo prueba */}
|
||||
{isMock && (
|
||||
<div className="w-full max-w-md bg-yellow-500/20 border border-yellow-500/50 text-yellow-200 px-4 py-2 rounded-lg mb-6 text-xs text-center">
|
||||
⚠️ Modo Vista Previa (Fuera de Telegram)
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Header con Avatar */}
|
||||
<div className="flex flex-col items-center mb-8 animate-fade-in-down">
|
||||
<div className="relative">
|
||||
<div className="w-24 h-24 bg-gradient-to-tr from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-4xl font-bold text-white shadow-xl mb-4 border-4 border-slate-800">
|
||||
{user.photo_url ? (
|
||||
<img src={user.photo_url} alt="Profile" className="w-full h-full rounded-full object-cover" />
|
||||
) : (
|
||||
<span>{user.first_name?.charAt(0) || "U"}</span>
|
||||
)}
|
||||
</div>
|
||||
{user.is_premium && (
|
||||
<div className="absolute bottom-3 right-0 bg-yellow-500 text-slate-900 rounded-full p-1 border-2 border-slate-800">
|
||||
<i data-lucide="star" className="w-4 h-4 fill-current"></i>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<h1 className="text-2xl font-bold text-white">
|
||||
{user.first_name} {user.last_name}
|
||||
</h1>
|
||||
{user.username && (
|
||||
<p className="text-blue-400 font-medium">@{user.username}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Lista de Datos */}
|
||||
<div className="w-full max-w-md space-y-2">
|
||||
<h2 className="text-slate-400 text-xs uppercase font-bold tracking-wider mb-2 ml-1">Información de Cuenta</h2>
|
||||
|
||||
<InfoCard
|
||||
icon={<i data-lucide="hash" className="w-5 h-5"></i>}
|
||||
label="ID de Telegram"
|
||||
value={user.id}
|
||||
/>
|
||||
|
||||
<InfoCard
|
||||
icon={<i data-lucide="globe" className="w-5 h-5"></i>}
|
||||
label="Idioma"
|
||||
value={user.language_code === 'es' ? 'Español' : user.language_code?.toUpperCase()}
|
||||
/>
|
||||
|
||||
<InfoCard
|
||||
icon={<i data-lucide="zap" className="w-5 h-5"></i>}
|
||||
label="Estado Premium"
|
||||
value={user.is_premium ? "Activo" : "No Activo"}
|
||||
/>
|
||||
|
||||
{/* Botón de acción */}
|
||||
<button
|
||||
onClick={() => window.Telegram.WebApp.close()}
|
||||
className="mt-8 w-full bg-blue-600 hover:bg-blue-500 active:scale-95 transition-all text-white font-bold py-3 px-4 rounded-xl shadow-lg flex items-center justify-center gap-2"
|
||||
>
|
||||
<span>Cerrar Mini App</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Raw Data (Opcional, útil para desarrollo) */}
|
||||
<div className="mt-10 w-full max-w-md">
|
||||
<details className="text-xs text-slate-500 cursor-pointer">
|
||||
<summary className="hover:text-slate-300 transition-colors">Ver datos crudos (JSON)</summary>
|
||||
<pre className="mt-2 bg-slate-950 p-3 rounded-lg overflow-x-auto text-green-400 border border-slate-800">
|
||||
{JSON.stringify(user, null, 2)}
|
||||
</pre>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(<App />);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user