Update files

This commit is contained in:
glpshchn 2025-12-07 05:36:30 +03:00
parent 4a3ebaaaaa
commit 1f386c32a1
3 changed files with 120 additions and 36 deletions

View File

@ -59,9 +59,9 @@ const sendMessageToAllUsers = async (messageText) => {
}; };
const getStartMessage = () => { const getStartMessage = () => {
return `👋 <b>Добро пожаловать в Nakama!</b> return `<b>Добро пожаловать в Nakama!</b>
📱 <b>Nakama</b> социальная сеть для фурри и аниме сообщества. 📱 <b>Nakama</b> - социальная сеть для фурри и аниме сообщества.
<b>Основные возможности:</b> <b>Основные возможности:</b>
Создание постов с текстом и изображениями Создание постов с текстом и изображениями

View File

@ -210,14 +210,27 @@
.ladder-top-header { .ladder-top-header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: flex-start;
margin-bottom: 16px; margin-bottom: 16px;
gap: 12px;
}
.ladder-top-title {
flex: 1;
} }
.ladder-top-header h2 { .ladder-top-header h2 {
font-size: 20px; font-size: 20px;
font-weight: 700; font-weight: 700;
color: var(--text-primary); color: var(--text-primary);
margin-bottom: 4px;
}
.ladder-prizes {
font-size: 12px;
color: var(--text-secondary);
margin: 0;
line-height: 1.4;
} }
.info-btn { .info-btn {
@ -246,30 +259,38 @@
.top-users-list { .top-users-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 12px; padding: 8px 0;
} }
.top-user-item { .top-user-item {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
padding: 12px; padding: 8px 16px;
background: var(--bg-primary); background: transparent;
border-radius: 12px; border-bottom: 1px solid rgba(0, 0, 0, 0.03);
transition: all 0.2s; transition: all 0.2s;
min-height: 54px;
}
[data-theme="dark"] .top-user-item {
border-bottom-color: rgba(255, 255, 255, 0.03);
}
.top-user-item:last-child {
border-bottom: none;
} }
.top-user-item.current-user { .top-user-item.current-user {
background: rgba(255, 215, 0, 0.1); background: rgba(255, 215, 0, 0.05);
border: 1px solid rgba(255, 215, 0, 0.3);
} }
.user-rank { .user-rank {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 40px; width: 32px;
height: 40px; height: 32px;
flex-shrink: 0; flex-shrink: 0;
} }
@ -296,37 +317,53 @@
} }
.user-avatar { .user-avatar {
width: 50px; width: 54px;
height: 50px; height: 54px;
border-radius: 50%; border-radius: 50%;
object-fit: cover; object-fit: cover;
border: 2px solid var(--border-color); border: none;
flex-shrink: 0; flex-shrink: 0;
} }
.top-user-item.current-user .user-avatar {
border-color: #FFD700;
}
.user-info { .user-info {
flex: 1; flex: 1;
min-width: 0; min-width: 0;
display: flex;
align-items: center;
} }
.user-name { .user-name {
font-size: 16px; font-size: 15px;
font-weight: 600; font-weight: 600;
color: var(--text-primary); color: var(--text-primary);
display: flex; display: flex;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
margin-bottom: 4px; white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.user-stats {
display: flex;
align-items: center;
gap: 12px;
flex-shrink: 0;
margin-left: auto;
} }
.user-tickets { .user-tickets {
font-size: 14px; font-size: 14px;
color: #FFD700; color: var(--text-primary);
font-weight: 500; font-weight: 500;
white-space: nowrap;
}
.user-prize {
font-size: 14px;
color: var(--text-secondary);
font-weight: 500;
white-space: nowrap;
} }
.current-badge { .current-badge {
@ -364,9 +401,14 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
padding: 12px; padding: 8px 0;
background: var(--bg-primary); background: transparent;
border-radius: 12px; border-bottom: 1px solid rgba(0, 0, 0, 0.03);
min-height: 54px;
}
[data-theme="dark"] .current-user-item {
border-bottom-color: rgba(255, 255, 255, 0.03);
} }
/* Модальное окно с информацией */ /* Модальное окно с информацией */
@ -380,7 +422,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
z-index: 1000; z-index: 10000;
padding: 20px; padding: 20px;
animation: fadeIn 0.3s; animation: fadeIn 0.3s;
} }
@ -393,6 +435,7 @@
border-radius: 16px; border-radius: 16px;
box-shadow: 0 4px 20px var(--shadow-lg); box-shadow: 0 4px 20px var(--shadow-lg);
position: relative; position: relative;
z-index: 10001;
} }
.info-modal-header { .info-modal-header {
@ -404,7 +447,7 @@
position: sticky; position: sticky;
top: 0; top: 0;
background: var(--bg-secondary); background: var(--bg-secondary);
z-index: 10; z-index: 10002;
} }
.info-modal-header h2 { .info-modal-header h2 {
@ -430,6 +473,8 @@
.info-modal-content { .info-modal-content {
padding: 16px; padding: 16px;
position: relative;
z-index: 1;
} }
.info-section { .info-section {
@ -518,5 +563,5 @@
} }
[data-theme="dark"] .user-tickets { [data-theme="dark"] .user-tickets {
color: #FFD700; color: var(--text-primary);
} }

View File

@ -80,6 +80,40 @@ export default function MonthlyLadder({ user }) {
} }
} }
const getPrize = (rank) => {
switch (rank) {
case 1:
return '$50'
case 2:
return '$30'
case 3:
return '$15'
case 4:
return '$5'
case 5:
return '$5'
default:
return null
}
}
const getPrize = (rank) => {
switch (rank) {
case 1:
return '$50'
case 2:
return '$30'
case 3:
return '$15'
case 4:
return '$5'
case 5:
return '$5'
default:
return null
}
}
const formatTickets = (tickets) => { const formatTickets = (tickets) => {
return tickets?.toLocaleString('ru-RU') || '0' return tickets?.toLocaleString('ru-RU') || '0'
} }
@ -138,7 +172,10 @@ export default function MonthlyLadder({ user }) {
{/* Топ 5 пользователей */} {/* Топ 5 пользователей */}
<div className="ladder-top"> <div className="ladder-top">
<div className="ladder-top-header"> <div className="ladder-top-header">
<h2>Топ 5</h2> <div className="ladder-top-title">
<h2>Топ 5</h2>
<p className="ladder-prizes">Призы: 1 место - $50, 2 место - $30, 3 место - $15, 4-5 места - $5</p>
</div>
<button <button
className="info-btn" className="info-btn"
onClick={() => { onClick={() => {
@ -159,6 +196,7 @@ export default function MonthlyLadder({ user }) {
<div className="top-users-list"> <div className="top-users-list">
{topUsers.map((topUser, index) => { {topUsers.map((topUser, index) => {
const isCurrentUser = user && (topUser._id === user.id || topUser._id?.toString() === user.id?.toString()) const isCurrentUser = user && (topUser._id === user.id || topUser._id?.toString() === user.id?.toString())
const prize = getPrize(topUser.rank)
return ( return (
<div <div
key={topUser._id} key={topUser._id}
@ -177,9 +215,10 @@ export default function MonthlyLadder({ user }) {
{topUser.firstName || topUser.username} {topUser.firstName || topUser.username}
{isCurrentUser && <Star size={16} className="current-badge" />} {isCurrentUser && <Star size={16} className="current-badge" />}
</div> </div>
<div className="user-tickets"> </div>
{formatTickets(topUser.tickets)} билетов <div className="user-stats">
</div> <span className="user-tickets">{formatTickets(topUser.tickets)} билетов</span>
{prize && <span className="user-prize">{prize}</span>}
</div> </div>
</div> </div>
) )
@ -206,9 +245,9 @@ export default function MonthlyLadder({ user }) {
{currentUser.firstName || currentUser.username} {currentUser.firstName || currentUser.username}
<Star size={16} className="current-badge" /> <Star size={16} className="current-badge" />
</div> </div>
<div className="user-tickets"> </div>
{formatTickets(currentUser.tickets)} билетов <div className="user-stats">
</div> <span className="user-tickets">{formatTickets(currentUser.tickets)} билетов</span>
</div> </div>
</div> </div>
</div> </div>
@ -217,7 +256,7 @@ export default function MonthlyLadder({ user }) {
{/* Модальное окно с информацией */} {/* Модальное окно с информацией */}
{showInfo && ( {showInfo && (
<div className="info-modal-overlay" onClick={() => setShowInfo(false)}> <div className="info-modal-overlay" onClick={() => setShowInfo(false)}>
<div className="info-modal card" onClick={(e) => e.stopPropagation()}> <div className="info-modal" onClick={(e) => e.stopPropagation()}>
<div className="info-modal-header"> <div className="info-modal-header">
<h2>За что начисляются баллы</h2> <h2>За что начисляются баллы</h2>
<button className="close-btn" onClick={() => setShowInfo(false)}>×</button> <button className="close-btn" onClick={() => setShowInfo(false)}>×</button>
@ -261,7 +300,7 @@ export default function MonthlyLadder({ user }) {
</div> </div>
<div className="info-section anti-fraud"> <div className="info-section anti-fraud">
<h3>🛡 Антифрод</h3> <h3>Немного правил</h3>
<p>Лайки/комменты от аккаунтов младше 24 часов не считаем</p> <p>Лайки/комменты от аккаунтов младше 24 часов не считаем</p>
<p>Комменты &lt;10 символов = 0 баллов</p> <p>Комменты &lt;10 символов = 0 баллов</p>
<p>Ограничение на баллы по входящим реакциям, чтобы боты не устроили ферму</p> <p>Ограничение на баллы по входящим реакциям, чтобы боты не устроили ферму</p>