отображение реальной статистики на главном экране авторизованного пользователя

This commit is contained in:
Professional 2025-05-24 02:02:16 +07:00
parent 9af77b21e1
commit 12a5d0a928
4 changed files with 110 additions and 8 deletions

View File

@ -393,11 +393,69 @@ const getUserById = async (req, res, next) => {
}
};
// @desc Получить статистику пользователя для главной страницы
// @route GET /api/users/stats
// @access Private
const getUserStats = async (req, res, next) => {
try {
const currentUserId = req.user._id;
// 1. Получаем количество лайков (кто лайкнул текущего пользователя)
const likesCount = await User.countDocuments({
liked: currentUserId
});
// 2. Получаем количество совпадений (matches)
const matchesCount = await User.findById(currentUserId)
.select('matches')
.then(user => user?.matches?.length || 0);
// 3. Получаем количество непрочитанных сообщений
const Conversation = require('../models/Conversation');
const Message = require('../models/Message');
// Находим все диалоги пользователя
const userConversations = await Conversation.find({
participants: currentUserId
}).select('_id');
const conversationIds = userConversations.map(conv => conv._id);
// Считаем непрочитанные сообщения в этих диалогах
const unreadMessagesCount = await Message.countDocuments({
conversationId: { $in: conversationIds },
sender: { $ne: currentUserId }, // Сообщения от других пользователей
readBy: { $ne: currentUserId } // Которые текущий пользователь не читал
});
// 4. Для просмотров профиля пока возвращаем заглушку,
// так как у нас нет модели для отслеживания просмотров
// В будущем можно добавить отдельную коллекцию ProfileViews
const profileViewsCount = 0; // TODO: Реализовать отслеживание просмотров
const stats = {
profileViews: profileViewsCount,
likes: likesCount,
matches: matchesCount,
unreadMessages: unreadMessagesCount
};
console.log(`[USER_CTRL] Статистика пользователя ${currentUserId}:`, stats);
res.status(200).json(stats);
} catch (error) {
console.error('[USER_CTRL] Ошибка при получении статистики пользователя:', error.message);
next(error);
}
};
module.exports = {
updateUserProfile,
getUsersForSwiping,
uploadUserProfilePhoto,
setMainPhoto, // <--- Добавлено
deletePhoto, // <--- Добавлено
getUserById, // <--- Добавлено
setMainPhoto,
deletePhoto,
getUserById,
getUserStats, // <--- Добавляем новую функцию
};

View File

@ -1,6 +1,6 @@
const express = require('express');
const router = express.Router();
const { updateUserProfile, getUsersForSwiping, uploadUserProfilePhoto, setMainPhoto, deletePhoto, getUserById } = require('../controllers/userController');
const { updateUserProfile, getUsersForSwiping, uploadUserProfilePhoto, setMainPhoto, deletePhoto, getUserById, getUserStats } = require('../controllers/userController');
const { protect } = require('../middleware/authMiddleware'); // Нам нужен protect для защиты маршрута
const multer = require('multer'); // 1. Импортируем multer
const path = require('path'); // Может понадобиться для фильтрации файлов
@ -36,6 +36,10 @@ const upload = multer({
router.put('/profile', protect, updateUserProfile);
router.get('/suggestions', protect, getUsersForSwiping); // <--- НОВЫЙ МАРШРУТ
// Маршрут для получения статистики пользователя
// GET /api/users/stats
router.get('/stats', protect, getUserStats); // <--- НОВЫЙ МАРШРУТ
// Маршрут для загрузки фотографии профиля
// POST /api/users/profile/photo
router.post('/profile/photo', protect, upload.single('profilePhoto'), uploadUserProfilePhoto);

View File

@ -111,5 +111,10 @@ export default {
// Новый метод для получения профиля пользователя по ID
getUserById(userId) {
return apiClient.get(`/users/${userId}`);
},
// Новый метод для получения статистики пользователя
getUserStats() {
return apiClient.get('/users/stats');
}
};

View File

@ -104,7 +104,7 @@
<i class="bi-eye"></i>
</div>
<div class="stat-info">
<h3>25</h3>
<h3>{{ stats.profileViews }}</h3>
<p>Просмотров профиля</p>
</div>
</div>
@ -114,7 +114,7 @@
<i class="bi-heart"></i>
</div>
<div class="stat-info">
<h3>8</h3>
<h3>{{ stats.likes }}</h3>
<p>Лайков</p>
</div>
</div>
@ -124,7 +124,7 @@
<i class="bi-chat-dots"></i>
</div>
<div class="stat-info">
<h3>3</h3>
<h3>{{ stats.unreadMessages }}</h3>
<p>Новых сообщения</p>
</div>
</div>
@ -181,10 +181,40 @@
<script setup>
import { useAuth } from '@/auth'; // Импортируем наш auth composable
import { onMounted } from 'vue'; // Добавляем импорт onMounted
import { onMounted, ref } from 'vue'; // Добавляем ref для реактивных данных
import api from '@/services/api'; // Импортируем API сервис
const { user, isAuthenticated, fetchUser } = useAuth(); // Добавляем fetchUser
// Реактивные данные для статистики
const stats = ref({
profileViews: 0,
likes: 0,
unreadMessages: 0
});
const statsLoading = ref(false);
const statsError = ref('');
// Функция для загрузки статистики пользователя
const fetchUserStats = async () => {
if (!isAuthenticated.value) return;
statsLoading.value = true;
statsError.value = '';
try {
console.log('[HomeView] Загрузка статистики пользователя...');
const response = await api.getUserStats();
stats.value = response.data;
console.log('[HomeView] Статистика загружена:', stats.value);
} catch (err) {
console.error('[HomeView] Ошибка при загрузке статистики:', err);
statsError.value = 'Не удалось загрузить статистику';
} finally {
statsLoading.value = false;
}
};
// Обновляем данные пользователя при монтировании компонента
onMounted(async () => {
if (localStorage.getItem('userToken')) {
@ -192,6 +222,11 @@ onMounted(async () => {
await fetchUser();
console.log('HomeView: Состояние аутентификации:', isAuthenticated.value);
console.log('HomeView: Пользователь:', user.value);
// Загружаем статистику после загрузки данных пользователя
if (isAuthenticated.value) {
await fetchUserStats();
}
}
});
</script>