Update files
This commit is contained in:
parent
48a3955c37
commit
4150c03bdb
|
|
@ -19,6 +19,8 @@ router.get('/', async (req, res) => {
|
||||||
.sort({ usageCount: -1, name: 1 })
|
.sort({ usageCount: -1, name: 1 })
|
||||||
.select('name category description usageCount');
|
.select('name category description usageCount');
|
||||||
|
|
||||||
|
console.log(`[TAGS API] Found ${tags.length} tags with status 'approved'`);
|
||||||
|
|
||||||
// Группировка по категориям
|
// Группировка по категориям
|
||||||
const grouped = {
|
const grouped = {
|
||||||
theme: [],
|
theme: [],
|
||||||
|
|
@ -33,6 +35,8 @@ router.get('/', async (req, res) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(`[TAGS API] Grouped:`, Object.keys(grouped).map(k => `${k}: ${grouped[k].length}`).join(', '));
|
||||||
|
|
||||||
res.json({ tags: grouped, all: tags });
|
res.json({ tags: grouped, all: tags });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logError('Ошибка получения тегов', error);
|
logError('Ошибка получения тегов', error);
|
||||||
|
|
|
||||||
|
|
@ -53,10 +53,20 @@ async function initTags() {
|
||||||
for (const tagData of INITIAL_TAGS) {
|
for (const tagData of INITIAL_TAGS) {
|
||||||
const existing = await Tag.findOne({ name: tagData.name });
|
const existing = await Tag.findOne({ name: tagData.name });
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
await Tag.create(tagData);
|
// Явно устанавливаем статус
|
||||||
|
await Tag.create({
|
||||||
|
...tagData,
|
||||||
|
status: 'approved' // Явно устанавливаем статус
|
||||||
|
});
|
||||||
created++;
|
created++;
|
||||||
console.log(`✅ Создан тег: ${tagData.name}`);
|
console.log(`✅ Создан тег: ${tagData.name}`);
|
||||||
} else {
|
} else {
|
||||||
|
// Обновляем статус существующего тега, если он не approved
|
||||||
|
if (existing.status !== 'approved') {
|
||||||
|
existing.status = 'approved';
|
||||||
|
await existing.save();
|
||||||
|
console.log(`✅ Обновлен статус тега: ${tagData.name}`);
|
||||||
|
}
|
||||||
skipped++;
|
skipped++;
|
||||||
console.log(`⏭️ Тег уже существует: ${tagData.name}`);
|
console.log(`⏭️ Тег уже существует: ${tagData.name}`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,15 @@
|
||||||
.empty-state p {
|
.empty-state p {
|
||||||
color: var(--text-secondary);
|
color: var(--text-secondary);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state-hint {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0.7;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: -8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
|
|
@ -124,6 +133,10 @@
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-theme="dark"] .btn-primary {
|
[data-theme="dark"] .btn-primary {
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
import { useSearchParams } from 'react-router-dom'
|
import { useSearchParams, useNavigate } from 'react-router-dom'
|
||||||
import { getPosts } from '../utils/api'
|
import { getPosts } from '../utils/api'
|
||||||
import PostCard from '../components/PostCard'
|
import PostCard from '../components/PostCard'
|
||||||
import CreatePostModal from '../components/CreatePostModal'
|
import CreatePostModal from '../components/CreatePostModal'
|
||||||
import { Plus } from 'lucide-react'
|
import { Plus, Settings } from 'lucide-react'
|
||||||
import { hapticFeedback } from '../utils/telegram'
|
import { hapticFeedback } from '../utils/telegram'
|
||||||
import './Feed.css'
|
import './Feed.css'
|
||||||
|
|
||||||
export default function Feed({ user }) {
|
export default function Feed({ user }) {
|
||||||
const [searchParams] = useSearchParams()
|
const [searchParams] = useSearchParams()
|
||||||
|
const navigate = useNavigate()
|
||||||
const [posts, setPosts] = useState([])
|
const [posts, setPosts] = useState([])
|
||||||
const [loading, setLoading] = useState(true)
|
const [loading, setLoading] = useState(true)
|
||||||
const [showCreateModal, setShowCreateModal] = useState(false)
|
const [showCreateModal, setShowCreateModal] = useState(false)
|
||||||
|
|
@ -153,10 +154,41 @@ export default function Feed({ user }) {
|
||||||
</div>
|
</div>
|
||||||
) : posts.length === 0 ? (
|
) : posts.length === 0 ? (
|
||||||
<div className="empty-state">
|
<div className="empty-state">
|
||||||
|
{filter === 'interests' ? (
|
||||||
|
<>
|
||||||
|
<p>Нет постов по вашим интересам</p>
|
||||||
|
<p className="empty-state-hint">
|
||||||
|
Проверьте выбранные теги в настройках профиля
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
className="btn-primary"
|
||||||
|
onClick={() => {
|
||||||
|
hapticFeedback('light')
|
||||||
|
navigate('/profile')
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Settings size={18} style={{ marginRight: '8px' }} />
|
||||||
|
Открыть настройки
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
) : filter === 'following' ? (
|
||||||
|
<>
|
||||||
|
<p>Нет постов от подписок</p>
|
||||||
|
<p className="empty-state-hint">
|
||||||
|
Подпишитесь на пользователей, чтобы видеть их посты здесь
|
||||||
|
</p>
|
||||||
|
<button className="btn-primary" onClick={handleCreatePost}>
|
||||||
|
Создать пост
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<p>Пока нет постов</p>
|
<p>Пока нет постов</p>
|
||||||
<button className="btn-primary" onClick={handleCreatePost}>
|
<button className="btn-primary" onClick={handleCreatePost}>
|
||||||
Создать первый пост
|
Создать первый пост
|
||||||
</button>
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -685,6 +685,20 @@
|
||||||
to { transform: rotate(360deg); }
|
to { transform: rotate(360deg); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty-tags-message {
|
||||||
|
padding: 24px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-tags-message code {
|
||||||
|
background: var(--bg-primary);
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
/* Модалка с информацией о теге */
|
/* Модалка с информацией о теге */
|
||||||
.tag-info-modal {
|
.tag-info-modal {
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,9 @@ export default function Profile({ user, setUser }) {
|
||||||
try {
|
try {
|
||||||
setLoadingTags(true)
|
setLoadingTags(true)
|
||||||
const data = await getTags()
|
const data = await getTags()
|
||||||
|
console.log('[Profile] Tags data received:', data)
|
||||||
|
console.log('[Profile] Tags grouped:', data.tags)
|
||||||
|
console.log('[Profile] Tags all:', data.all)
|
||||||
setAllTags(data.tags || { theme: [], style: [], mood: [], technical: [] })
|
setAllTags(data.tags || { theme: [], style: [], mood: [], technical: [] })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка загрузки тегов:', error)
|
console.error('Ошибка загрузки тегов:', error)
|
||||||
|
|
@ -537,7 +540,21 @@ export default function Profile({ user, setUser }) {
|
||||||
<div className="spinner" />
|
<div className="spinner" />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
Object.entries(TAG_CATEGORIES).map(([categoryKey, categoryName]) => {
|
(() => {
|
||||||
|
const hasAnyTags = Object.values(allTags).some(tags => tags.length > 0)
|
||||||
|
|
||||||
|
if (!hasAnyTags) {
|
||||||
|
return (
|
||||||
|
<div className="empty-tags-message">
|
||||||
|
<p>Теги не найдены. Убедитесь, что скрипт инициализации тегов был запущен.</p>
|
||||||
|
<p style={{ fontSize: '12px', color: 'var(--text-secondary)', marginTop: '8px' }}>
|
||||||
|
Запустите: <code>node backend/scripts/initTags.js</code>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.entries(TAG_CATEGORIES).map(([categoryKey, categoryName]) => {
|
||||||
const categoryTags = allTags[categoryKey] || []
|
const categoryTags = allTags[categoryKey] || []
|
||||||
if (categoryTags.length === 0) return null
|
if (categoryTags.length === 0) return null
|
||||||
|
|
||||||
|
|
@ -588,6 +605,7 @@ export default function Profile({ user, setUser }) {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
})()
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{selectedTags.length > 0 && (
|
{selectedTags.length > 0 && (
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue