lava / Olddocs.html
Reaperxxxx's picture
Rename docs.html to Olddocs.html
8a703cd verified
Raw
History Blame Contribute Delete
53.2 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Finral - User Profile Search</title>
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%);
color: #e0e6ed;
padding: 0;
margin: 0;
min-height: 100vh;
position: relative;
overflow-x: hidden;
max-width: 100vw;
}
.header {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border-bottom: 2px solid #00bcd4;
padding: 10px;
text-align: center;
box-shadow: 0 4px 20px rgba(0, 188, 212, 0.3);
position: relative;
z-index: 100;
}
.header::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, transparent 30%, rgba(0, 188, 212, 0.1) 50%, transparent 70%);
animation: shimmer 3s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.page-title {
font-size: 1.6rem;
font-weight: 900;
background: linear-gradient(45deg, #00bcd4, #87ceeb, #ffffff, #00bcd4);
background-size: 300% 300%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 3px;
text-shadow: 0 0 30px rgba(0, 188, 212, 0.8);
animation: gradientShift 4s ease-in-out infinite;
letter-spacing: 1px;
position: relative;
z-index: 3;
}
.page-title::after {
content: '🔍';
position: absolute;
right: -25px;
top: -3px;
font-size: 1rem;
animation: spark 2s infinite;
}
@keyframes gradientShift {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
@keyframes spark {
0%, 100% { transform: rotate(0deg) scale(1); opacity: 0.7; }
50% { transform: rotate(15deg) scale(1.2); opacity: 1; }
}
.creator {
font-size: 0.7rem;
background: linear-gradient(45deg, #87ceeb, #00bcd4);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
margin-bottom: 3px;
font-weight: 600;
letter-spacing: 0.5px;
position: relative;
z-index: 3;
}
.page-subtitle {
font-size: 0.65rem;
color: rgba(135, 206, 235, 0.8);
margin-bottom: 0;
font-style: italic;
font-weight: 300;
position: relative;
z-index: 3;
}
.main-layout {
display: flex;
min-height: calc(100vh - 80px);
}
.sidebar {
width: 280px;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border-right: 2px solid #00bcd4;
padding: 15px;
position: fixed;
left: 0;
top: 80px;
height: calc(100vh - 80px);
overflow-y: auto;
z-index: 50;
box-shadow: 4px 0 20px rgba(0, 188, 212, 0.3);
}
.sidebar-toggle {
display: none;
position: fixed;
top: 90px;
left: 10px;
z-index: 60;
background: linear-gradient(45deg, #00bcd4, #87ceeb);
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
color: #0a0a0a;
font-size: 1.2rem;
cursor: pointer;
box-shadow: 0 4px 15px rgba(0, 188, 212, 0.5);
}
.search-section {
background: linear-gradient(135deg, #16213e 0%, #1a1a2e 100%);
border: 1px solid #00bcd4;
border-radius: 10px;
padding: 15px;
margin-bottom: 15px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
position: relative;
overflow: hidden;
}
.search-section::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #00bcd4, transparent);
}
.search-section h3 {
font-size: 1rem;
color: #00bcd4;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 6px;
}
.search-section h3::before {
content: '';
width: 3px;
height: 15px;
background: linear-gradient(45deg, #00bcd4, #87ceeb);
border-radius: 2px;
}
.search-input {
padding: 10px 12px;
font-size: 0.9rem;
width: 100%;
border: 2px solid #00bcd4;
border-radius: 6px;
margin-bottom: 10px;
background: rgba(26, 26, 46, 0.8);
color: #e0e6ed;
transition: all 0.3s ease;
}
.search-input:focus {
outline: none;
border-color: #87ceeb;
box-shadow: 0 0 10px rgba(0, 188, 212, 0.4);
}
.search-input::placeholder {
color: #87ceeb;
}
.search-btn {
padding: 10px 16px;
font-size: 0.9rem;
background: linear-gradient(45deg, #00bcd4, #87ceeb);
color: #0a0a0a;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
width: 100%;
}
.search-btn:hover {
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(0, 188, 212, 0.4);
}
.search-btn:disabled {
background: #555;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.search-result {
margin-top: 10px;
padding: 12px;
background: rgba(0, 188, 212, 0.1);
border: 1px solid rgba(0, 188, 212, 0.3);
border-radius: 6px;
font-size: 0.85rem;
}
.view-profile-btn {
padding: 6px 12px;
background: linear-gradient(45deg, #4caf50, #66bb6a);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-top: 8px;
font-weight: bold;
font-size: 0.8rem;
transition: all 0.3s ease;
width: 100%;
}
.view-profile-btn:hover {
transform: translateY(-1px);
box-shadow: 0 3px 10px rgba(76, 175, 80, 0.4);
}
.content {
flex: 1;
margin-left: 280px;
padding: 15px;
overflow-x: auto;
}
.top-section {
display: grid;
grid-template-columns: 1fr 300px;
gap: 15px;
margin-bottom: 15px;
min-height: 200px;
}
.banner-profile-container {
position: relative;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border: 1px solid #00bcd4;
border-radius: 10px;
overflow: hidden;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
}
.banner-profile-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #00bcd4, transparent);
z-index: 2;
}
#banner {
width: 100%;
height: 140px;
object-fit: cover;
border-radius: 0;
}
.banner-overlay {
position: absolute;
top: 2px;
left: 0;
right: 0;
height: 138px;
background: linear-gradient(
to bottom,
rgba(0, 0, 0, 0.1) 0%,
rgba(0, 0, 0, 0.3) 50%,
rgba(26, 26, 46, 0.8) 100%
);
z-index: 2;
}
#pfp {
position: absolute;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
width: 105px;
height: 105px;
object-fit: cover;
border-radius: 5%;
border: 3px solid #00bcd4;
box-shadow:
0 0 20px rgba(0, 188, 212, 0.8),
0 0 40px rgba(0, 188, 212, 0.4);
background: #1a1a2e;
z-index: 4;
}
.profile-glow {
position: absolute;
bottom: -30px;
left: 50%;
transform: translateX(-50%);
width: 100px;
height: 100px;
border-radius: 50%;
background: radial-gradient(circle, rgba(0, 188, 212, 0.4) 0%, rgba(0, 188, 212, 0.2) 50%, transparent 70%);
z-index: 3;
animation: profileGlow 3s ease-in-out infinite alternate;
}
@keyframes profileGlow {
0% { transform: translateX(-50%) scale(1); opacity: 0.6; }
100% { transform: translateX(-50%) scale(1.1); opacity: 0.9; }
}
.user-info-card {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border: 1px solid #00bcd4;
border-radius: 10px;
padding: 15px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
}
.user-info-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #00bcd4, transparent);
}
.welcome-title {
font-size: 1.2rem;
font-weight: bold;
color: #e0e6ed;
margin-bottom: 8px;
background: linear-gradient(45deg, #e0e6ed, #87ceeb);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-align: center;
}
.chat-id {
font-size: 1rem;
font-weight: bold;
color: #00bcd4;
background: rgba(0, 188, 212, 0.1);
border: 1px solid rgba(0, 188, 212, 0.3);
border-radius: 6px;
padding: 8px;
text-align: center;
margin-bottom: 10px;
}
.stats-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin-bottom: 15px;
}
.stats-section {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border: 1px solid #00bcd4;
border-radius: 10px;
padding: 15px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
position: relative;
overflow: hidden;
}
.stats-section::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #00bcd4, transparent);
}
.stats-section h3 {
font-size: 1.1rem;
color: #00bcd4;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 6px;
}
.stats-section h3::before {
content: '';
width: 3px;
height: 15px;
background: linear-gradient(45deg, #00bcd4, #87ceeb);
border-radius: 2px;
}
.basic-stats-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.stat-item {
background: rgba(0, 188, 212, 0.1);
border: 1px solid rgba(0, 188, 212, 0.3);
border-radius: 6px;
padding: 8px 6px;
text-align: center;
transition: all 0.3s ease;
}
.stat-item:hover {
border-color: #00bcd4;
box-shadow: 0 2px 8px rgba(0, 188, 212, 0.3);
transform: translateY(-1px);
}
.stat-item strong {
color: #87ceeb;
font-size: 0.75rem;
display: block;
margin-bottom: 2px;
}
.stat-value {
color: #00bcd4;
font-weight: bold;
font-size: 0.9rem;
}
.groups-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 12px;
}
.group-box {
background: linear-gradient(135deg, #16213e 0%, #1a1a2e 100%);
border: 1px solid rgba(0, 188, 212, 0.5);
border-radius: 8px;
padding: 12px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.group-box::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, #00bcd4, transparent);
}
.group-box:hover {
border-color: #00bcd4;
box-shadow: 0 4px 15px rgba(0, 188, 212, 0.3);
transform: translateY(-2px);
}
.group-header {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 10px;
}
.group-pic {
width: 50px;
height: 50px;
object-fit: cover;
border-radius: 8px;
border: 2px solid #00bcd4;
flex-shrink: 0;
}
.group-info {
flex: 1;
min-width: 0;
}
.group-name {
font-weight: bold;
color: #00bcd4;
font-size: 0.9rem;
margin-bottom: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.group-id {
font-size: 0.75rem;
color: #87ceeb;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.group-stats {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
margin-bottom: 8px;
}
.group-stat-item {
background: rgba(0, 188, 212, 0.05);
border: 1px solid rgba(0, 188, 212, 0.2);
border-radius: 4px;
padding: 4px 6px;
text-align: center;
}
.group-stat-value {
font-weight: bold;
color: #00bcd4;
font-size: 0.8rem;
display: block;
}
.group-stat-label {
font-size: 0.65rem;
color: #87ceeb;
}
.group-admins {
margin-top: 8px;
font-size: 0.8rem;
}
.group-admins summary {
color: #87ceeb;
cursor: pointer;
font-weight: bold;
margin-bottom: 4px;
}
.admin-list {
display: flex;
flex-wrap: wrap;
gap: 4px;
margin-top: 4px;
}
.admin-tag {
background: rgba(0, 188, 212, 0.2);
border: 1px solid rgba(0, 188, 212, 0.4);
border-radius: 12px;
padding: 2px 6px;
font-size: 0.7rem;
color: #87ceeb;
cursor: pointer;
transition: all 0.3s ease;
}
.admin-tag:hover {
background: rgba(0, 188, 212, 0.3);
color: #00bcd4;
}
.error {
color: #ff6b6b;
font-style: italic;
background: rgba(255, 107, 107, 0.1);
border: 1px solid rgba(255, 107, 107, 0.3);
border-radius: 4px;
padding: 6px;
margin: 6px 0;
font-size: 0.8rem;
}
.loading {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
color: #87ceeb;
font-size: 1rem;
padding: 40px 20px;
}
.loading-spinner {
width: 20px;
height: 20px;
border: 2px solid #87ceeb;
border-top: 2px solid #00bcd4;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-dots {
display: inline-flex;
gap: 4px;
}
.loading-dot {
width: 6px;
height: 6px;
background: #00bcd4;
border-radius: 50%;
animation: loadingDots 1.4s infinite ease-in-out;
}
.loading-dot:nth-child(1) { animation-delay: -0.32s; }
.loading-dot:nth-child(2) { animation-delay: -0.16s; }
@keyframes loadingDots {
0%, 80%, 100% { transform: scale(0); opacity: 0.5; }
40% { transform: scale(1); opacity: 1; }
}
/* NFT Styles */
.nfts-section {
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
border: 1px solid #00bcd4;
border-radius: 10px;
padding: 15px;
margin-bottom: 15px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
position: relative;
overflow: hidden;
}
.nfts-section::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #00bcd4, transparent);
}
.nfts-section h3 {
font-size: 1.1rem;
color: #00bcd4;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 8px;
}
.nfts-section h3::before {
content: '';
width: 3px;
height: 15px;
background: linear-gradient(45deg, #00bcd4, #87ceeb);
border-radius: 2px;
}
.nfts-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 15px;
margin-bottom: 15px;
}
.nft-card {
border-radius: 12px;
padding: 12px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
cursor: pointer;
}
/* Basic Quality (0-20) */
.nft-card.basic {
background: linear-gradient(135deg, #2a2a3e 0%, #1e1e32 100%);
border: 1px solid #555;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
.nft-card.basic:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(85, 85, 85, 0.4);
}
/* Better Quality (21-40) */
.nft-card.better {
background: linear-gradient(135deg, #1a2e3e 0%, #16213e 100%);
border: 1px solid #4caf50;
box-shadow: 0 3px 10px rgba(76, 175, 80, 0.3);
}
.nft-card.better::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #4caf50, transparent);
}
.nft-card.better:hover {
transform: translateY(-3px);
box-shadow: 0 6px 15px rgba(76, 175, 80, 0.5);
}
/* Even Better Quality (41-60) */
.nft-card.even-better {
background: linear-gradient(135deg, #1a1e3e 0%, #2e1a3e 100%);
border: 1px solid #9c27b0;
box-shadow: 0 4px 12px rgba(156, 39, 176, 0.4);
position: relative;
}
.nft-card.even-better::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #9c27b0, #e91e63, transparent);
}
.nft-card.even-better::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, transparent 30%, rgba(156, 39, 176, 0.1) 50%, transparent 70%);
animation: shimmer 3s infinite;
pointer-events: none;
}
.nft-card.even-better:hover {
transform: translateY(-4px);
box-shadow: 0 8px 20px rgba(156, 39, 176, 0.6);
}
/* Way Better Quality (61-80) */
.nft-card.way-better {
background: linear-gradient(135deg, #3e1a1a 0%, #3e2a1a 100%);
border: 2px solid #ff9800;
box-shadow: 0 5px 15px rgba(255, 152, 0, 0.5);
position: relative;
}
.nft-card.way-better::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: linear-gradient(45deg, #ff9800, #ffc107, #ff5722, #ff9800);
background-size: 300% 300%;
border-radius: 12px;
z-index: -1;
animation: gradientShift 2s ease-in-out infinite;
}
.nft-card.way-better::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, transparent 30%, rgba(255, 152, 0, 0.2) 50%, transparent 70%);
animation: shimmer 2s infinite;
pointer-events: none;
}
.nft-card.way-better:hover {
transform: translateY(-5px) scale(1.02);
box-shadow: 0 10px 25px rgba(255, 152, 0, 0.7);
}
/* Legendary Quality (81-100) */
.nft-card.legendary {
background: linear-gradient(135deg, #3e1a3e 0%, #1a3e3e 100%);
border: 3px solid #ffd700;
box-shadow:
0 0 20px rgba(255, 215, 0, 0.6),
0 0 40px rgba(255, 215, 0, 0.4),
0 0 60px rgba(255, 215, 0, 0.2);
position: relative;
overflow: hidden;
}
.nft-card.legendary::before {
content: '';
position: absolute;
top: -3px;
left: -3px;
right: -3px;
bottom: -3px;
background: linear-gradient(45deg, #ffd700, #ffeb3b, #ff6f00, #ffd700);
background-size: 400% 400%;
border-radius: 12px;
z-index: -1;
animation: legendaryGlow 1.5s ease-in-out infinite;
}
.nft-card.legendary::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
radial-gradient(circle at 20% 20%, rgba(255, 215, 0, 0.3) 0%, transparent 50%),
radial-gradient(circle at 80% 80%, rgba(255, 235, 59, 0.3) 0%, transparent 50%),
linear-gradient(45deg, transparent 30%, rgba(255, 215, 0, 0.1) 50%, transparent 70%);
animation: legendaryShimmer 3s infinite;
pointer-events: none;
}
.nft-card.legendary:hover {
transform: translateY(-6px) scale(1.05);
box-shadow:
0 0 30px rgba(255, 215, 0, 0.8),
0 0 60px rgba(255, 215, 0, 0.6),
0 0 90px rgba(255, 215, 0, 0.4);
}
@keyframes legendaryGlow {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
@keyframes legendaryShimmer {
0% { transform: translateX(-100%) rotate(45deg); }
100% { transform: translateX(100%) rotate(45deg); }
}
.nft-image {
width: 100%;
aspect-ratio: 1;
object-fit: cover;
border-radius: 8px;
margin-bottom: 12px;
transition: all 0.3s ease;
}
.nft-card:hover .nft-image {
transform: scale(1.05);
}
.nft-info {
position: relative;
z-index: 2;
}
.nft-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 8px;
}
.nft-name {
font-weight: bold;
font-size: 1rem;
color: #e0e6ed;
flex: 1;
margin-right: 8px;
line-height: 1.2;
}
.nft-id {
font-size: 0.7rem;
color: #87ceeb;
background: rgba(0, 188, 212, 0.1);
border: 1px solid rgba(0, 188, 212, 0.3);
border-radius: 4px;
padding: 2px 6px;
white-space: nowrap;
}
.nft-rarity {
font-size: 0.8rem;
padding: 3px 8px;
border-radius: 12px;
display: inline-block;
margin-bottom: 8px;
font-weight: bold;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.rarity-common { background: #666; color: #fff; }
.rarity-uncommon { background: #4caf50; color: #fff; }
.rarity-rare { background: #2196f3; color: #fff; }
.rarity-epic { background: #9c27b0; color: #fff; }
.rarity-legendary { background: #ff9800; color: #fff; }
.rarity-mythic { background: #f44336; color: #fff; }
.nft-details {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px;
margin-bottom: 10px;
}
.nft-detail {
background: rgba(0, 188, 212, 0.1);
border: 1px solid rgba(0, 188, 212, 0.2);
border-radius: 6px;
padding: 6px 8px;
text-align: center;
transition: all 0.3s ease;
}
.nft-detail:hover {
background: rgba(0, 188, 212, 0.15);
border-color: rgba(0, 188, 212, 0.4);
}
.nft-detail-label {
color: #87ceeb;
display: block;
font-size: 0.7rem;
margin-bottom: 2px;
font-weight: 500;
}
.nft-detail-value {
color: #00bcd4;
font-weight: bold;
font-size: 0.85rem;
display: block;
}
.nft-obtained {
background: rgba(135, 206, 235, 0.1);
border: 1px solid rgba(135, 206, 235, 0.3);
border-radius: 6px;
padding: 6px 8px;
text-align: center;
grid-column: 1 / -1;
}
.nft-obtained-label {
color: #87ceeb;
font-size: 0.7rem;
margin-bottom: 2px;
display: block;
}
.nft-obtained-value {
color: #87ceeb;
font-weight: bold;
font-size: 0.8rem;
}
.quality-badge {
position: absolute;
top: 8px;
right: 8px;
padding: 4px 8px;
border-radius: 12px;
font-size: 0.75rem;
font-weight: bold;
z-index: 3;
display: flex;
align-items: center;
gap: 4px;
}
.quality-basic {
background: linear-gradient(45deg, #666, #888);
color: #fff;
}
.quality-better {
background: linear-gradient(45deg, #4caf50, #66bb6a);
color: #fff;
}
.quality-even-better {
background: linear-gradient(45deg, #9c27b0, #ba68c8);
color: #fff;
}
.quality-way-better {
background: linear-gradient(45deg, #ff9800, #ffb74d);
color: #fff;
}
.quality-legendary {
background: linear-gradient(45deg, #ffd700, #ffeb3b);
color: #000;
box-shadow: 0 0 10px rgba(255, 215, 0, 0.5);
}
.quality-badge::before {
content: '⭐';
font-size: 0.8rem;
}
.no-nfts {
text-align: center;
padding: 60px 20px;
color: #87ceeb;
font-style: italic;
}
.no-nfts-icon {
font-size: 4rem;
margin-bottom: 15px;
opacity: 0.5;
}
.no-nfts h4 {
font-size: 1.2rem;
margin-bottom: 8px;
color: #e0e6ed;
}
.no-nfts p {
font-size: 0.9rem;
margin-bottom: 5px;
}
.show-all-btn {
background: linear-gradient(45deg, #00bcd4, #87ceeb);
color: #0a0a0a;
border: none;
border-radius: 8px;
padding: 12px 24px;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
display: block;
margin: 0 auto;
font-size: 0.9rem;
}
.show-all-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(0, 188, 212, 0.4);
}
.nft-loading {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
padding: 60px;
color: #87ceeb;
}
.nft-stats {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding: 10px 15px;
background: rgba(0, 188, 212, 0.1);
border: 1px solid rgba(0, 188, 212, 0.3);
border-radius: 8px;
}
.nft-stat {
text-align: center;
}
.nft-stat-value {
font-size: 1.2rem;
font-weight: bold;
color: #00bcd4;
display: block;
}
.nft-stat-label {
font-size: 0.7rem;
color: #87ceeb;
margin-top: 2px;
}
/* Mobile Responsive */
@media (max-width: 768px) {
.sidebar {
transform: translateX(-100%);
transition: transform 0.3s ease;
}
.sidebar.open {
transform: translateX(0);
}
.sidebar-toggle {
display: block;
}
.content {
margin-left: 0;
padding: 10px;
}
.top-section {
grid-template-columns: 1fr;
gap: 10px;
}
.stats-grid {
grid-template-columns: 1fr;
gap: 10px;
}
.basic-stats-grid {
grid-template-columns: repeat(3, 1fr);
gap: 6px;
}
.groups-container {
grid-template-columns: 1fr;
gap: 10px;
}
.group-stats {
grid-template-columns: repeat(4, 1fr);
gap: 4px;
}
.group-stat-item {
padding: 3px 4px;
}
.group-stat-value {
font-size: 0.75rem;
}
.toggle-details {
background: none;
border: none;
color: #007bff;
cursor: pointer;
font-weight: bold;
margin-top: 5px;
padding: 0;
}
.toggle-details:hover {
text-decoration: underline;
}
.group-stat-label {
font-size: 0.6rem;
}
.nfts-grid {
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
gap: 10px;
}
.nft-card {
padding: 10px;
}
.nft-name {
font-size: 0.9rem;
}
.nft-details {
gap: 4px;
}
.nft-detail {
padding: 4px 6px;
}
.nft-stats {
flex-direction: column;
gap: 8px;
}
.nft-stats > div {
display: flex;
justify-content: space-around;
width: 100%;
}
}
@media (max-width: 480px) {
.page-title {
font-size: 1.4rem;
}
.page-title::after {
right: -20px;
font-size: 0.9rem;
}
.header {
padding: 8px;
}
.content {
padding: 8px;
}
.basic-stats-grid {
grid-template-columns: 1fr 1fr;
gap: 4px;
}
.stat-item {
padding: 6px 4px;
}
.stat-item strong {
font-size: 0.7rem;
}
.stat-value {
font-size: 0.8rem;
}
.nfts-grid {
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
gap: 8px;
}
.nft-card {
padding: 8px;
}
.nft-name {
font-size: 0.8rem;
}
.nft-rarity {
font-size: 0.7rem;
padding: 2px 6px;
}
.nft-details {
grid-template-columns: 1fr;
gap: 3px;
}
.nft-detail {
padding: 4px 6px;
}
.quality-badge {
padding: 2px 6px;
font-size: 0.7rem;
}
}
</style>
</head>
<body>
<div class="header">
<div class="page-title">Finral Search</div>
<div class="creator">✨ Crafted with Excellence by Saul ✨</div>
<div class="page-subtitle">"Find Any Telegram User"</div>
</div>
<button class="sidebar-toggle" id="sidebarToggle">🔍</button>
<div class="main-layout">
<div class="sidebar" id="sidebar">
<div class="search-section">
<h3>🔍 Search User</h3>
<input type="text" id="searchInput" class="search-input" placeholder="Enter Chat/User ID">
<button id="searchBtn" class="search-btn">
<span class="btn-text">Search User</span>
<div class="loading-dots" style="display: none;">
<div class="loading-dot"></div>
<div class="loading-dot"></div>
<div class="loading-dot"></div>
</div>
</button>
<div id="searchResult" class="search-result" style="display:none;"></div>
</div>
</div>
<div class="content">
<div class="top-section">
<div class="banner-profile-container" id="bannerContainer" style="display:none;">
<img id="banner" src="/placeholder.svg" alt="User Banner">
<div class="banner-overlay"></div>
<div class="profile-glow"></div>
<img id="pfp" src="/placeholder.svg" alt="Profile Picture">
</div>
<div class="user-info-card">
<div class="welcome-title" id="welcomeTitle">Welcome to Finral</div>
<div id="chatId" class="chat-id">
<div class="loading">
<div class="loading-spinner"></div>
Loading...
</div>
</div>
</div>
</div>
<div class="stats-grid" id="statsGrid" style="display:none;">
<div class="stats-section">
<h3>📊 Basic Stats</h3>
<div class="basic-stats-grid">
<div class="stat-item">
<strong>Level</strong>
<div class="stat-value" id="totalLevel">-</div>
</div>
<div class="stat-item">
<strong>Total XP</strong>
<div class="stat-value" id="totalXP">-</div>
</div>
<div class="stat-item">
<strong>Royalties</strong>
<div class="stat-value" id="totalRoyalties">-</div>
</div>
<div class="stat-item">
<strong>Daily Msgs</strong>
<div class="stat-value" id="totalDailyMessages">-</div>
</div>
</div>
</div>
<div class="stats-section">
<h3>👤 User Info</h3>
<div class="basic-stats-grid">
<div class="stat-item">
<strong>Full Name</strong>
<div class="stat-value" id="fullName">-</div>
</div>
<div class="stat-item">
<strong>Username</strong>
<div class="stat-value" id="username">-</div>
</div>
<div class="stat-item">
<strong>Groups</strong>
<div class="stat-value" id="groupCount">-</div>
</div>
<div class="stat-item">
<strong>Status</strong>
<div class="stat-value">Active</div>
</div>
</div>
</div>
</div>
<!-- NFT Section FIRST -->
<div class="nfts-section" id="nftsSection" style="display:none;">
<h3>🎨 NFT Collection</h3>
<div class="nft-stats" id="nftStats" style="display:none;">
<div>
<div class="nft-stat">
<span class="nft-stat-value" id="totalNfts">0</span>
<span class="nft-stat-label">Total NFTs</span>
</div>
<div class="nft-stat">
<span class="nft-stat-value" id="avgQuality">0</span>
<span class="nft-stat-label">Avg Quality</span>
</div>
</div>
<div>
<div class="nft-stat">
<span class="nft-stat-value" id="rarestHolders">0</span>
<span class="nft-stat-label">Rarest (Holders)</span>
</div>
<div class="nft-stat">
<span class="nft-stat-value" id="highestQuality">0</span>
<span class="nft-stat-label">Highest Quality</span>
</div>
</div>
</div>
<div id="nftsContainer">
<div class="nft-loading">
<div class="loading-spinner"></div>
Loading NFTs...
</div>
</div>
<button id="showAllNftsBtn" class="show-all-btn" style="display:none;">
Show All NFTs (<span id="remainingCount">0</span> more)
</button>
</div>
<!-- Group Section SECOND -->
<div class="stats-section" id="groupsSection" style="display:none;">
<h3>👥 Group Memberships</h3>
<div class="groups-container" id="groupsContainer"></div>
</div>
<script>
// Sidebar toggle functionality
const sidebarToggle = document.getElementById('sidebarToggle');
const sidebar = document.getElementById('sidebar');
sidebarToggle.addEventListener('click', () => {
sidebar.classList.toggle('open');
sidebarToggle.textContent = sidebar.classList.contains('open') ? '✕' : '🔍';
});
// Close sidebar when clicking outside on mobile
document.addEventListener('click', (e) => {
if (window.innerWidth <= 768 &&
!sidebar.contains(e.target) &&
!sidebarToggle.contains(e.target) &&
sidebar.classList.contains('open')) {
sidebar.classList.remove('open');
sidebarToggle.textContent = '🔍';
}
});
// Function to search user by chat ID
async function searchUser(chatId) {
const searchBtn = document.getElementById('searchBtn');
const searchResult = document.getElementById('searchResult');
const btnText = searchBtn.querySelector('.btn-text');
const loadingDots = searchBtn.querySelector('.loading-dots');
searchBtn.disabled = true;
btnText.style.display = 'none';
loadingDots.style.display = 'flex';
searchResult.style.display = 'none';
try {
const response = await fetch(`https://reaperxxxx-testldb.hf.space/user/${chatId}/info`);
const data = await response.json();
if (data.status && data.groups && data.groups.length > 0) {
const userInfo = data.groups[0];
searchResult.innerHTML = `
<p><strong>✅ Found User:</strong></p>
<p><strong>Name:</strong> ${userInfo.fullName || 'N/A'}</p>
<p><strong>Username:</strong> ${userInfo.username || 'N/A'}</p>
<p><strong>ID:</strong> ${chatId}</p>
<button class="view-profile-btn" onclick="window.open('https://t.me/finralxbot/info?startapp=${chatId}', '_blank')">
View Full Profile
</button>
`;
searchResult.style.display = 'block';
} else {
searchResult.innerHTML = '<p class="error">❌ User not found or no data available.</p>';
searchResult.style.display = 'block';
}
} catch (error) {
searchResult.innerHTML = '<p class="error">⚠️ Error searching for user. Please try again.</p>';
searchResult.style.display = 'block';
}
searchBtn.disabled = false;
btnText.style.display = 'block';
loadingDots.style.display = 'none';
}
window.addEventListener('DOMContentLoaded', async () => {
// Set up search functionality
const searchBtn = document.getElementById('searchBtn');
const searchInput = document.getElementById('searchInput');
searchBtn.addEventListener('click', () => {
const chatId = searchInput.value.trim();
if (chatId) {
searchUser(chatId);
}
});
searchInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
const chatId = searchInput.value.trim();
if (chatId) {
searchUser(chatId);
}
}
});
// Get userId from Telegram WebApp start parameter or current user
let userId;
let isViewingOther = false;
const initData = Telegram.WebApp.initDataUnsafe;
const startParam = initData.start_param;
if (startParam) {
userId = startParam;
isViewingOther = true;
document.getElementById('welcomeTitle').textContent = `Viewing Profile`;
} else {
const user = initData.user;
if (user && user.id) {
userId = user.id;
document.getElementById('welcomeTitle').textContent = `Welcome to Finral`;
} else {
document.getElementById('chatId').innerHTML = '<div class="error">❌ Unable to fetch chat ID</div>';
return;
}
}
document.getElementById('chatId').textContent = userId;
try {
// Fetch user banner with fallback
try {
const bannerRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/banner`);
const bannerData = await bannerRes.json();
const bannerEl = document.getElementById('banner');
if (bannerData.status && bannerData.catboxUrl) {
bannerEl.src = bannerData.catboxUrl;
} else {
bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg';
}
document.getElementById('bannerContainer').style.display = 'block';
} catch (err) {
const bannerEl = document.getElementById('banner');
bannerEl.src = 'https://files.catbox.moe/pdt55w.jpg';
document.getElementById('bannerContainer').style.display = 'block';
}
// Fetch user PFP
const pfpRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/pfp`);
const pfpData = await pfpRes.json();
const imgEl = document.getElementById('pfp');
if (pfpData.status && pfpData.catboxUrl) {
imgEl.src = pfpData.catboxUrl;
} else {
imgEl.src = 'https://files.catbox.moe/hmicys.jpeg';
}
// Fetch user info
const infoRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/info`);
const infoData = await infoRes.json();
if (infoData.status) {
const userInfo = infoData.groups[0] || {};
// Display basic stats
document.getElementById('fullName').textContent = userInfo.fullName || 'N/A';
document.getElementById('username').textContent = userInfo.username || 'N/A';
document.getElementById('totalXP').textContent = infoData.totalXP.toLocaleString();
document.getElementById('totalLevel').textContent = infoData.totalLevel;
document.getElementById('totalRoyalties').textContent = infoData.totalRoyalties.toLocaleString();
document.getElementById('totalDailyMessages').textContent = infoData.totalDailyMessages;
document.getElementById('groupCount').textContent = infoData.groups.length;
// Show stats grid
document.getElementById('statsGrid').style.display = 'grid';
// Group unique groups by groupId
const uniqueGroups = {};
for (const group of infoData.groups) {
const groupId = group.groupId || group.id;
if (!uniqueGroups[groupId]) {
uniqueGroups[groupId] = {
groupId: groupId,
fullName: group.fullName,
username: group.username,
totalLevel: 0,
totalXP: 0,
totalRoyalties: 0,
totalDailyMessages: 0,
entries: []
};
}
uniqueGroups[groupId].totalLevel += group.level || 0;
uniqueGroups[groupId].totalXP += group.xp || 0;
uniqueGroups[groupId].totalRoyalties += group.royalties || 0;
uniqueGroups[groupId].totalDailyMessages += group.dailyMessages || 0;
uniqueGroups[groupId].entries.push({
level: group.level,
xp: group.xp,
royalties: group.royalties,
dailyMessages: group.dailyMessages
});
}
// Display group stats
const groupsContainer = document.getElementById('groupsContainer');
groupsContainer.innerHTML = '';
for (const groupId in uniqueGroups) {
const group = uniqueGroups[groupId];
let groupMeta = null;
let metaError = null;
try {
const groupMetaRes = await fetch(`https://reaperxxxx-testldb.hf.space/group/${groupId}/meta`);
if (groupMetaRes.ok) {
groupMeta = await groupMetaRes.json();
} else {
const errorText = await groupMetaRes.text();
metaError = `API Error: ${groupMetaRes.status}`;
}
} catch (err) {
metaError = `Fetch Error: ${err.message}`;
}
const div = document.createElement('div');
div.className = 'group-box';
const displayName = (groupMeta && groupMeta.status && groupMeta.groupName)
? groupMeta.groupName
: group.fullName || 'Unknown Group';
const groupPic = (groupMeta && groupMeta.status && groupMeta.groupPic)
? groupMeta.groupPic
: null;
const admins = (groupMeta && groupMeta.status && groupMeta.admins)
? groupMeta.admins
: null;
div.innerHTML = `
<div class="group-header">
${groupPic ? `<img class="group-pic" src="${groupPic}" alt="Group Picture">` : '<div class="group-pic" style="background: linear-gradient(45deg, #00bcd4, #87ceeb); display: flex; align-items: center; justify-content: center; color: #0a0a0a; font-weight: bold;">👥</div>'}
<div class="group-info">
<div class="group-name">${displayName}</div>
<div class="group-id">ID: ${groupId}</div>
</div>
</div>
<div class="group-stats">
<div class="group-stat-item">
<span class="group-stat-value">${group.totalLevel}</span>
<span class="group-stat-label">Level</span>
</div>
<div class="group-stat-item">
<span class="group-stat-value">${group.totalXP.toLocaleString()}</span>
<span class="group-stat-label">XP</span>
</div>
<div class="group-stat-item">
<span class="group-stat-value">${group.totalRoyalties.toLocaleString()}</span>
<span class="group-stat-label">Royalties</span>
</div>
<div class="group-stat-item">
<span class="group-stat-value">${group.totalDailyMessages}</span>
<span class="group-stat-label">Daily</span>
</div>
</div>
${metaError ? `<div class="error">⚠️ ${metaError}</div>` : ''}
${admins && admins.length > 0 ? `
<div class="group-admins">
<details>
<summary>👑 Admins (${admins.length})</summary>
<div class="admin-list">
${admins.slice(0, 5).map(a => `<span class="admin-tag" onclick="window.open('https://t.me/finralxbot/info?startapp=${a.id}', '_blank')">${a.name || 'Unknown'}</span>`).join('')}
${admins.length > 5 ? `<span class="admin-tag">+${admins.length - 5} more</span>` : ''}
</div>
</details>
</div>` : ''}
`;
groupsContainer.appendChild(div);
}
document.getElementById('groupsSection').style.display = 'block';
}
// Fetch and display user NFTs
try {
const nftsRes = await fetch(`https://reaperxxxx-testldb.hf.space/user/${userId}/nfts`);
const nftsData = await nftsRes.json();
const nftsContainer = document.getElementById('nftsContainer');
const showAllBtn = document.getElementById('showAllNftsBtn');
const remainingCount = document.getElementById('remainingCount');
const nftStats = document.getElementById('nftStats');
if (nftsData.status && nftsData.nfts && nftsData.nfts.length > 0) {
// Sort NFTs by holders (ascending) to show rarest first
const sortedNfts = nftsData.nfts.sort((a, b) => a.holders - b.holders);
// Calculate NFT statistics
const totalNfts = sortedNfts.length;
const avgQuality = Math.round(sortedNfts.reduce((sum, nft) => sum + nft.nftquality, 0) / totalNfts);
const rarestHolders = Math.min(...sortedNfts.map(nft => nft.holders));
const highestQuality = Math.max(...sortedNfts.map(nft => nft.nftquality));
// Update NFT stats
document.getElementById('totalNfts').textContent = totalNfts;
document.getElementById('avgQuality').textContent = avgQuality;
document.getElementById('rarestHolders').textContent = rarestHolders;
document.getElementById('highestQuality').textContent = highestQuality;
nftStats.style.display = 'block';
function getQualityClass(quality) {
if (quality >= 81) return 'legendary';
if (quality >= 61) return 'way-better';
if (quality >= 41) return 'even-better';
if (quality >= 21) return 'better';
return 'basic';
}
function getQualityBadgeClass(quality) {
if (quality >= 81) return 'quality-legendary';
if (quality >= 61) return 'quality-way-better';
if (quality >= 41) return 'quality-even-better';
if (quality >= 21) return 'quality-better';
return 'quality-basic';
}
function getRarityClass(rarity) {
const rarityLower = rarity.toLowerCase();
if (rarityLower.includes('mythic')) return 'rarity-mythic';
if (rarityLower.includes('legendary')) return 'rarity-legendary';
if (rarityLower.includes('epic')) return 'rarity-epic';
if (rarityLower.includes('rare')) return 'rarity-rare';
if (rarityLower.includes('uncommon')) return 'rarity-uncommon';
return 'rarity-common';
}
function formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
});
}
function formatDateTime(dateString) {
const date = new Date(dateString);
return date.toLocaleString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
}
function createNftCard(nft) {
const qualityClass = getQualityClass(nft.nftquality);
const qualityBadgeClass = getQualityBadgeClass(nft.nftquality);
const rarityClass = getRarityClass(nft.rarity);
const uniqueId = `details-${nft.nftid}`;
return `
<div class="nft-card ${qualityClass}">
<div class="quality-badge ${qualityBadgeClass}">${nft.nftquality}</div>
<img src="${nft.nftimage}" alt="${nft.name}" class="nft-image" loading="lazy">
<div class="nft-info">
<div class="nft-header">
<div class="nft-name" title="${nft.name}">${nft.name}</div>
<div class="nft-id">#${nft.nftid}</div>
</div>
<div class="nft-rarity ${rarityClass}">${nft.rarity}</div>
<button class="toggle-details" onclick="toggleDetails('${uniqueId}', this)">▼ Show Details</button>
<div class="nft-details-wrapper" id="${uniqueId}" style="display: none;">
<div class="nft-details">
<div class="nft-detail">
<span class="nft-detail-label">Quality</span>
<span class="nft-detail-value">${nft.nftquality}/100</span>
</div>
<div class="nft-detail">
<span class="nft-detail-label">Holders</span>
<span class="nft-detail-value">${nft.holders}</span>
</div>
</div>
<div class="nft-obtained">
<span class="nft-obtained-label">Obtained On</span>
<span class="nft-obtained-value">${formatDateTime(nft.gotten_on)}</span>
</div>
</div>
</div>
</div>
`;
}
// Show first 5 NFTs initially
const initialNfts = sortedNfts.slice(0, 5);
const remainingNfts = sortedNfts.slice(5);
nftsContainer.innerHTML = `
<div class="nfts-grid">
${initialNfts.map(nft => createNftCard(nft)).join('')}
</div>
`;
// Show "Show All" button if there are more NFTs
if (remainingNfts.length > 0) {
remainingCount.textContent = remainingNfts.length;
showAllBtn.style.display = 'block';
let allShown = false;
showAllBtn.addEventListener('click', () => {
if (!allShown) {
const nftsGrid = nftsContainer.querySelector('.nfts-grid');
nftsGrid.innerHTML += remainingNfts.map(nft => createNftCard(nft)).join('');
showAllBtn.textContent = 'Show Less';
allShown = true;
} else {
const nftsGrid = nftsContainer.querySelector('.nfts-grid');
nftsGrid.innerHTML = initialNfts.map(nft => createNftCard(nft)).join('');
showAllBtn.innerHTML = `Show All NFTs (<span id="remainingCount">${remainingNfts.length}</span> more)`;
allShown = false;
}
});
}
document.getElementById('nftsSection').style.display = 'block';
} else {
// No NFTs found
nftsContainer.innerHTML = `
<div class="no-nfts">
<div class="no-nfts-icon">🎨</div>
<h4>No NFTs Found</h4>
<p>This user hasn't collected any NFTs yet.</p>
<p>Start your digital art journey today!</p>
</div>
`;
document.getElementById('nftsSection').style.display = 'block';
}
} catch (err) {
console.error('Error fetching NFTs:', err);
const nftsContainer = document.getElementById('nftsContainer');
nftsContainer.innerHTML = `
<div class="no-nfts">
<div class="no-nfts-icon">⚠️</div>
<h4>Failed to Load NFTs</h4>
<p>Unable to fetch NFT collection data.</p>
<p>Please try again later.</p>
</div>
`;
document.getElementById('nftsSection').style.display = 'block';
}
} catch (err) {
console.error('Error fetching user data:', err);
document.getElementById('chatId').innerHTML = '<div class="error">❌ Failed to load user info</div>';
}
});
</script>
<script>
function toggleDetails(id, button) {
const details = document.getElementById(id);
const isVisible = details.style.display === 'block';
details.style.display = isVisible ? 'none' : 'block';
button.textContent = isVisible ? '▼ Show Details' : '▲ Hide Details';
}
</script>
</body>
</html>