Refactor API routes and component logic: Remove unused event and user management routes, streamline feedback handling in components, and enhance state management with transitions for improved user experience. Update service layer methods for better organization and maintainability across the application.
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m38s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 2m38s
This commit is contained in:
131
actions/admin/events.ts
Normal file
131
actions/admin/events.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
'use server'
|
||||
|
||||
import { revalidatePath } from 'next/cache'
|
||||
import { auth } from '@/lib/auth'
|
||||
import { eventService } from '@/services/events/event.service'
|
||||
import { Role, EventType } from '@/prisma/generated/prisma/client'
|
||||
import { ValidationError, NotFoundError } from '@/services/errors'
|
||||
|
||||
function checkAdminAccess() {
|
||||
return async () => {
|
||||
const session = await auth()
|
||||
if (!session?.user || session.user.role !== Role.ADMIN) {
|
||||
throw new Error('Accès refusé')
|
||||
}
|
||||
return session
|
||||
}
|
||||
}
|
||||
|
||||
export async function createEvent(data: {
|
||||
date: string
|
||||
name: string
|
||||
description?: string | null
|
||||
type: string
|
||||
room?: string | null
|
||||
time?: string | null
|
||||
maxPlaces?: number | null
|
||||
}) {
|
||||
try {
|
||||
await checkAdminAccess()()
|
||||
|
||||
const event = await eventService.validateAndCreateEvent({
|
||||
date: data.date,
|
||||
name: data.name,
|
||||
description: data.description ?? '',
|
||||
type: data.type as EventType,
|
||||
room: data.room ?? undefined,
|
||||
time: data.time ?? undefined,
|
||||
maxPlaces: data.maxPlaces ?? undefined,
|
||||
})
|
||||
|
||||
revalidatePath('/admin')
|
||||
revalidatePath('/events')
|
||||
revalidatePath('/')
|
||||
|
||||
return { success: true, data: event }
|
||||
} catch (error) {
|
||||
console.error('Error creating event:', error)
|
||||
|
||||
if (error instanceof ValidationError) {
|
||||
return { success: false, error: error.message }
|
||||
}
|
||||
if (error instanceof Error && error.message === 'Accès refusé') {
|
||||
return { success: false, error: 'Accès refusé' }
|
||||
}
|
||||
|
||||
return { success: false, error: 'Erreur lors de la création de l\'événement' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateEvent(eventId: string, data: {
|
||||
date?: string
|
||||
name?: string
|
||||
description?: string | null
|
||||
type?: string
|
||||
room?: string | null
|
||||
time?: string | null
|
||||
maxPlaces?: number | null
|
||||
}) {
|
||||
try {
|
||||
await checkAdminAccess()()
|
||||
|
||||
const event = await eventService.validateAndUpdateEvent(eventId, {
|
||||
date: data.date,
|
||||
name: data.name,
|
||||
description: data.description ?? undefined,
|
||||
type: data.type as EventType,
|
||||
room: data.room ?? undefined,
|
||||
time: data.time ?? undefined,
|
||||
maxPlaces: data.maxPlaces ?? undefined,
|
||||
})
|
||||
|
||||
revalidatePath('/admin')
|
||||
revalidatePath('/events')
|
||||
revalidatePath('/')
|
||||
|
||||
return { success: true, data: event }
|
||||
} catch (error) {
|
||||
console.error('Error updating event:', error)
|
||||
|
||||
if (error instanceof ValidationError) {
|
||||
return { success: false, error: error.message }
|
||||
}
|
||||
if (error instanceof NotFoundError) {
|
||||
return { success: false, error: error.message }
|
||||
}
|
||||
if (error instanceof Error && error.message === 'Accès refusé') {
|
||||
return { success: false, error: 'Accès refusé' }
|
||||
}
|
||||
|
||||
return { success: false, error: 'Erreur lors de la mise à jour de l\'événement' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteEvent(eventId: string) {
|
||||
try {
|
||||
await checkAdminAccess()()
|
||||
|
||||
const existingEvent = await eventService.getEventById(eventId)
|
||||
|
||||
if (!existingEvent) {
|
||||
return { success: false, error: 'Événement non trouvé' }
|
||||
}
|
||||
|
||||
await eventService.deleteEvent(eventId)
|
||||
|
||||
revalidatePath('/admin')
|
||||
revalidatePath('/events')
|
||||
revalidatePath('/')
|
||||
|
||||
return { success: true }
|
||||
} catch (error) {
|
||||
console.error('Error deleting event:', error)
|
||||
|
||||
if (error instanceof Error && error.message === 'Accès refusé') {
|
||||
return { success: false, error: 'Accès refusé' }
|
||||
}
|
||||
|
||||
return { success: false, error: 'Erreur lors de la suppression de l\'événement' }
|
||||
}
|
||||
}
|
||||
|
||||
48
actions/admin/preferences.ts
Normal file
48
actions/admin/preferences.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
'use server'
|
||||
|
||||
import { revalidatePath } from 'next/cache'
|
||||
import { auth } from '@/lib/auth'
|
||||
import { sitePreferencesService } from '@/services/preferences/site-preferences.service'
|
||||
import { Role } from '@/prisma/generated/prisma/client'
|
||||
|
||||
function checkAdminAccess() {
|
||||
return async () => {
|
||||
const session = await auth()
|
||||
if (!session?.user || session.user.role !== Role.ADMIN) {
|
||||
throw new Error('Accès refusé')
|
||||
}
|
||||
return session
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateSitePreferences(data: {
|
||||
homeBackground?: string | null
|
||||
eventsBackground?: string | null
|
||||
leaderboardBackground?: string | null
|
||||
}) {
|
||||
try {
|
||||
await checkAdminAccess()()
|
||||
|
||||
const preferences = await sitePreferencesService.updateSitePreferences({
|
||||
homeBackground: data.homeBackground,
|
||||
eventsBackground: data.eventsBackground,
|
||||
leaderboardBackground: data.leaderboardBackground,
|
||||
})
|
||||
|
||||
revalidatePath('/admin')
|
||||
revalidatePath('/')
|
||||
revalidatePath('/events')
|
||||
revalidatePath('/leaderboard')
|
||||
|
||||
return { success: true, data: preferences }
|
||||
} catch (error) {
|
||||
console.error('Error updating admin preferences:', error)
|
||||
|
||||
if (error instanceof Error && error.message === 'Accès refusé') {
|
||||
return { success: false, error: 'Accès refusé' }
|
||||
}
|
||||
|
||||
return { success: false, error: 'Erreur lors de la mise à jour des préférences' }
|
||||
}
|
||||
}
|
||||
|
||||
116
actions/admin/users.ts
Normal file
116
actions/admin/users.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
'use server'
|
||||
|
||||
import { revalidatePath } from 'next/cache'
|
||||
import { auth } from '@/lib/auth'
|
||||
import { userService } from '@/services/users/user.service'
|
||||
import { userStatsService } from '@/services/users/user-stats.service'
|
||||
import { Role } from '@/prisma/generated/prisma/client'
|
||||
import {
|
||||
ValidationError,
|
||||
NotFoundError,
|
||||
ConflictError,
|
||||
} from '@/services/errors'
|
||||
|
||||
function checkAdminAccess() {
|
||||
return async () => {
|
||||
const session = await auth()
|
||||
if (!session?.user || session.user.role !== Role.ADMIN) {
|
||||
throw new Error('Accès refusé')
|
||||
}
|
||||
return session
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateUser(userId: string, data: {
|
||||
username?: string
|
||||
avatar?: string | null
|
||||
hpDelta?: number
|
||||
xpDelta?: number
|
||||
score?: number
|
||||
level?: number
|
||||
role?: string
|
||||
}) {
|
||||
try {
|
||||
await checkAdminAccess()()
|
||||
|
||||
// Valider username si fourni
|
||||
if (data.username !== undefined) {
|
||||
try {
|
||||
await userService.validateAndUpdateUserProfile(userId, { username: data.username })
|
||||
} catch (error) {
|
||||
if (error instanceof ValidationError || error instanceof ConflictError) {
|
||||
return { success: false, error: error.message }
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Mettre à jour stats et profil
|
||||
const updatedUser = await userStatsService.updateUserStatsAndProfile(
|
||||
userId,
|
||||
{
|
||||
username: data.username,
|
||||
avatar: data.avatar,
|
||||
hpDelta: data.hpDelta,
|
||||
xpDelta: data.xpDelta,
|
||||
score: data.score,
|
||||
level: data.level,
|
||||
role: data.role ? (data.role as Role) : undefined,
|
||||
},
|
||||
{
|
||||
id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
role: true,
|
||||
score: true,
|
||||
level: true,
|
||||
hp: true,
|
||||
maxHp: true,
|
||||
xp: true,
|
||||
maxXp: true,
|
||||
avatar: true,
|
||||
}
|
||||
)
|
||||
|
||||
revalidatePath('/admin')
|
||||
revalidatePath('/leaderboard')
|
||||
|
||||
return { success: true, data: updatedUser }
|
||||
} catch (error) {
|
||||
console.error('Error updating user:', error)
|
||||
|
||||
if (error instanceof Error && error.message === 'Accès refusé') {
|
||||
return { success: false, error: 'Accès refusé' }
|
||||
}
|
||||
|
||||
return { success: false, error: 'Erreur lors de la mise à jour de l\'utilisateur' }
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteUser(userId: string) {
|
||||
try {
|
||||
const session = await checkAdminAccess()()
|
||||
|
||||
await userService.validateAndDeleteUser(userId, session.user.id)
|
||||
|
||||
revalidatePath('/admin')
|
||||
revalidatePath('/leaderboard')
|
||||
|
||||
return { success: true }
|
||||
} catch (error) {
|
||||
console.error('Error deleting user:', error)
|
||||
|
||||
if (error instanceof ValidationError) {
|
||||
return { success: false, error: error.message }
|
||||
}
|
||||
if (error instanceof NotFoundError) {
|
||||
return { success: false, error: error.message }
|
||||
}
|
||||
if (error instanceof Error && error.message === 'Accès refusé') {
|
||||
return { success: false, error: 'Accès refusé' }
|
||||
}
|
||||
|
||||
return { success: false, error: 'Erreur lors de la suppression de l\'utilisateur' }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user