feat: stabilize admin dashboard, refactor group management, implement PWA, and fix routing

This commit is contained in:
2026-05-03 19:51:18 +05:00
parent 622ca04170
commit 0598e07823
36 changed files with 1387 additions and 467 deletions
+17 -4
View File
@@ -8,10 +8,23 @@ export default defineEventHandler(async (event) => {
}
// Get user's recent activities
const userActivities = Array.from(activities.values())
.filter(activity => activity.userId === userId)
.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
.slice(0, 50) // Limit to 50 most recent
const user = await prisma.user.findFirst({
where: {
OR: [{ id: userId }, { username: userId }]
}
})
if (!user) {
throw createError({ statusCode: 404, message: 'User not found' })
}
// Get user's activities from database or memory
const userActivities = await prisma.activity.findMany({
where: { userId: user.id },
orderBy: { timestamp: 'desc' },
take: 20
})
// Limit to 50 most recent
return { activities: userActivities }
})
@@ -7,6 +7,12 @@ export default defineEventHandler(async (event) => {
throw createError({ statusCode: 400, message: 'User ID is required' })
}
const user = await prisma.user.findFirst({
where: {
OR: [{ id: userId }, { username: userId }]
}
})
// Get user's group memberships
const userGroupIds = Array.from(userGroups.values())
.filter(membership => membership.userId === userId)
@@ -0,0 +1,39 @@
import { requireAuth } from '~/server/utils/auth'
import { prisma } from '~/server/utils/prisma'
export default defineEventHandler(async (event) => {
const currentUser = requireAuth(event)
const targetUserIdOrUsername = getRouterParam(event, 'id')
if (!targetUserIdOrUsername) {
throw createError({ statusCode: 400, message: 'User ID is required' })
}
// Находим целевого пользователя (по ID или username)
const targetUser = await prisma.user.findFirst({
where: {
OR: [
{ id: targetUserIdOrUsername },
{ username: targetUserIdOrUsername }
]
}
})
if (!targetUser) {
throw createError({ statusCode: 404, message: 'Target user not found' })
}
try {
const follow = await prisma.follows.findUnique({
where: {
followerId_followingId: {
followerId: currentUser.id,
followingId: targetUser.id
}
}
})
return { isFollowing: !!follow }
} catch (e) {
return { isFollowing: false }
}
})
+40
View File
@@ -0,0 +1,40 @@
import { requireAuth } from '~/server/utils/auth'
import { prisma } from '~/server/utils/prisma'
export default defineEventHandler(async (event) => {
const currentUser = requireAuth(event)
const targetIdOrUsername = getRouterParam(event, 'id')
const targetUser = await prisma.user.findFirst({
where: {
OR: [
{ id: targetIdOrUsername },
{ username: targetIdOrUsername }
]
}
})
if (!targetUser) {
throw createError({ statusCode: 404, message: 'User not found' })
}
if (targetUser.id === currentUser.id) {
throw createError({ statusCode: 400, message: 'You cannot follow yourself' })
}
await prisma.follows.upsert({
where: {
followerId_followingId: {
followerId: currentUser.id,
followingId: targetUser.id
}
},
update: {},
create: {
followerId: currentUser.id,
followingId: targetUser.id
}
})
return { success: true }
})
+35 -10
View File
@@ -7,27 +7,52 @@ export default defineEventHandler(async (event) => {
throw createError({ statusCode: 400, message: 'User ID is required' })
}
const profile = await prisma.profile.findUnique({
where: { userId },
let profile = await prisma.profile.findFirst({
where: {
OR: [
{ userId: userId },
{ user: { username: userId } }
]
},
include: {
user: {
include: {
_count: {
select: {
canvases: true,
followers: true,
following: true
}
select: { canvases: true, followers: true, following: true }
}
}
}
}
})
// If profile doesn't exist but user does, create it
if (!profile) {
// If profile doesn't exist but user might exist in Firebase,
// we could potentially create it here or return 404
throw createError({ statusCode: 404, message: 'Profile not found' })
const user = await prisma.user.findFirst({
where: {
OR: [{ id: userId }, { username: userId }]
}
})
if (!user) {
throw createError({ statusCode: 404, message: 'User not found' })
}
profile = await prisma.profile.create({
data: {
userId: user.id,
displayName: user.username,
avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${user.id}`
},
include: {
user: {
include: {
_count: {
select: { canvases: true, followers: true, following: true }
}
}
}
}
})
}
return {