6.3.0: Готовые желания на экране прогресса недели
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m19s

This commit is contained in:
poignatov
2026-03-05 19:41:43 +03:00
parent 25317997e5
commit 7f51411175
5 changed files with 277 additions and 21 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "play-life-web",
"version": "6.2.0",
"version": "6.3.0",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -405,3 +405,14 @@
font-size: 0.875rem;
color: #6b7280;
}
/* Текст "Готово!" синим для WishRowCard */
.wish-row-unlock.ready {
color: #3b82f6;
font-weight: 600;
}
/* Синяя обводка для готового MiniWishCard */
.mini-wish-image.ready {
border: 2px solid #3b82f6;
}

View File

@@ -104,7 +104,13 @@ function MiniWishCard({ wish, onClick, pendingScoresByProject = {} }) {
}
}
const cond = wish.first_locked_condition
// Желание помечено как готовое на бэкенде
const isReady = wish.is_ready === true
// Для готовых желаний берём условие из unlock_conditions, иначе из first_locked_condition
const cond = isReady
? wish.unlock_conditions?.find(c => c.type === 'project_points')
: wish.first_locked_condition
const isPointsCondition = cond?.type === 'project_points'
const required = cond?.required_points ?? 0
const current = cond?.current_points ?? 0
@@ -119,14 +125,14 @@ function MiniWishCard({ wish, onClick, pendingScoresByProject = {} }) {
return (
<div className="mini-wish-card" onClick={handleClick}>
<div className="mini-wish-image">
<div className={`mini-wish-image ${isReady ? 'ready' : ''}`}>
{wish.image_url ? (
<img src={wish.image_url} alt={wish.name} />
) : (
<div className="mini-wish-placeholder">🎁</div>
)}
<div className="mini-wish-overlay" aria-hidden="true" />
{showUnlockPoints && (
{!isReady && <div className="mini-wish-overlay" aria-hidden="true" />}
{showUnlockPoints && !isReady && (
<div
className="mini-wish-unlock-points"
style={{ fontSize: `${fontSizePx}px` }}
@@ -149,7 +155,13 @@ function WishRowCard({ wish, onClick, pendingScoresByProject = {}, position, min
}
}
const cond = wish.first_locked_condition
// Желание помечено как готовое на бэкенде
const isReady = wish.is_ready === true
// Для готовых желаний берём условие из unlock_conditions, иначе из first_locked_condition
const cond = isReady
? wish.unlock_conditions?.find(c => c.type === 'project_points')
: wish.first_locked_condition
const isPointsCondition = cond?.type === 'project_points'
const required = cond?.required_points ?? 0
const current = cond?.current_points ?? 0
@@ -176,6 +188,9 @@ function WishRowCard({ wish, onClick, pendingScoresByProject = {}, position, min
}
const getUnlockText = () => {
if (isReady) {
return 'Готово!'
}
if (remaining <= 0) {
return 'скоро'
}
@@ -199,11 +214,11 @@ function WishRowCard({ wish, onClick, pendingScoresByProject = {}, position, min
) : (
<div className="wish-row-placeholder">🎁</div>
)}
<div className="wish-row-overlay" aria-hidden="true" />
{!isReady && <div className="wish-row-overlay" aria-hidden="true" />}
</div>
<div className="wish-row-info">
<div className="wish-row-title">{wish.name}</div>
<div className="wish-row-unlock">{getUnlockText()}</div>
<div className={`wish-row-unlock ${isReady ? 'ready' : ''}`}>{getUnlockText()}</div>
</div>
</div>
)
@@ -683,19 +698,31 @@ function CurrentWeek({ onProjectClick, data, loading, error, onRetry, allProject
}
// Функция фильтрации желаний для проекта
// Фильтрация уже выполнена на бэкенде, здесь только группируем по проекту
const getWishesForProject = (projectId) => {
// Вспомогательная функция для получения projectId из желания
const getWishProjectId = (wish) => {
// Сначала пробуем first_locked_condition
if (wish.first_locked_condition?.project_id) {
return wish.first_locked_condition.project_id
}
// Иначе ищем в unlock_conditions (для готовых/разблокированных желаний)
if (wish.unlock_conditions) {
const cond = wish.unlock_conditions.find(c => c.type === 'project_points')
return cond?.project_id
}
return null
}
const filtered = wishes.filter(wish => {
if (wish.unlocked || wish.completed) return false
if (wish.locked_conditions_count !== 1) return false
const condition = wish.first_locked_condition
if (!condition || condition.project_id !== projectId) return false
const weeksText = condition.weeks_text
if (!weeksText) return false
return weeksText === '1 неделя' || weeksText === '<1 недели'
return getWishProjectId(wish) === projectId
})
// Сортируем по сроку разблокировки (от меньшего к большему)
// Сортируем: готовые желания первыми, затем по сроку разблокировки
return filtered.sort((a, b) => {
// Готовые желания показываем первыми
if (a.is_ready && !b.is_ready) return -1
if (!a.is_ready && b.is_ready) return 1
const weeksA = getWeeksValue(a.first_locked_condition?.weeks_text)
const weeksB = getWeeksValue(b.first_locked_condition?.weeks_text)
return weeksA - weeksB