Initial commit: Helpdesk application setup
- Backend: Node.js/TypeScript with Prisma ORM - Frontend: Vite + TypeScript - Project configuration and documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
333
backend/src/controllers/dashboard.controller.ts
Normal file
333
backend/src/controllers/dashboard.controller.ts
Normal file
@@ -0,0 +1,333 @@
|
||||
import { Response } from 'express';
|
||||
import prisma from '../config/database';
|
||||
import { successResponse, errorResponse } from '../utils/helpers';
|
||||
import { AuthRequest } from '../middleware/auth.middleware';
|
||||
|
||||
// Hlavný dashboard endpoint - štatistiky pre karty
|
||||
export const getDashboard = async (_req: AuthRequest, res: Response): Promise<void> => {
|
||||
try {
|
||||
const today = new Date();
|
||||
const nextMonth = new Date(today);
|
||||
nextMonth.setDate(nextMonth.getDate() + 30);
|
||||
|
||||
const [
|
||||
totalProjects,
|
||||
activeProjects,
|
||||
totalTasks,
|
||||
pendingTasks,
|
||||
inProgressTasks,
|
||||
totalCustomers,
|
||||
activeCustomers,
|
||||
totalEquipment,
|
||||
upcomingRevisions,
|
||||
totalRMAs,
|
||||
pendingRMAs,
|
||||
] = await Promise.all([
|
||||
prisma.project.count(),
|
||||
prisma.project.count({ where: { status: { isFinal: false } } }),
|
||||
prisma.task.count(),
|
||||
prisma.task.count({ where: { status: { code: 'NEW' } } }),
|
||||
prisma.task.count({ where: { status: { code: 'IN_PROGRESS' } } }),
|
||||
prisma.customer.count(),
|
||||
prisma.customer.count({ where: { active: true } }),
|
||||
prisma.equipment.count({ where: { active: true } }),
|
||||
prisma.revision.count({
|
||||
where: {
|
||||
nextDueDate: {
|
||||
gte: today,
|
||||
lte: nextMonth,
|
||||
},
|
||||
},
|
||||
}),
|
||||
prisma.rMA.count(),
|
||||
prisma.rMA.count({ where: { status: { isFinal: false } } }),
|
||||
]);
|
||||
|
||||
successResponse(res, {
|
||||
projects: {
|
||||
total: totalProjects,
|
||||
active: activeProjects,
|
||||
},
|
||||
tasks: {
|
||||
total: totalTasks,
|
||||
pending: pendingTasks,
|
||||
inProgress: inProgressTasks,
|
||||
},
|
||||
customers: {
|
||||
total: totalCustomers,
|
||||
active: activeCustomers,
|
||||
},
|
||||
equipment: {
|
||||
total: totalEquipment,
|
||||
upcomingRevisions,
|
||||
},
|
||||
rma: {
|
||||
total: totalRMAs,
|
||||
pending: pendingRMAs,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching dashboard:', error);
|
||||
errorResponse(res, 'Chyba pri načítaní dashboardu.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
export const getDashboardToday = async (req: AuthRequest, res: Response): Promise<void> => {
|
||||
try {
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
const tomorrow = new Date(today);
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
|
||||
const userId = req.user!.userId;
|
||||
|
||||
const [myTasks, myProjects, recentRMAs] = await Promise.all([
|
||||
// Tasks assigned to me that are not completed
|
||||
prisma.task.findMany({
|
||||
where: {
|
||||
assignees: { some: { userId } },
|
||||
status: { isFinal: false },
|
||||
},
|
||||
include: {
|
||||
status: true,
|
||||
priority: true,
|
||||
project: { select: { id: true, name: true } },
|
||||
createdBy: { select: { id: true, name: true } },
|
||||
assignees: { include: { user: { select: { id: true, name: true } } } },
|
||||
},
|
||||
orderBy: [{ priority: { level: 'desc' } }, { deadline: 'asc' }],
|
||||
take: 10,
|
||||
}),
|
||||
|
||||
// My active projects
|
||||
prisma.project.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{ ownerId: userId },
|
||||
{ members: { some: { userId } } },
|
||||
],
|
||||
status: { isFinal: false },
|
||||
},
|
||||
include: {
|
||||
status: true,
|
||||
_count: { select: { tasks: true } },
|
||||
},
|
||||
take: 5,
|
||||
}),
|
||||
|
||||
// Recent RMAs
|
||||
prisma.rMA.findMany({
|
||||
where: {
|
||||
OR: [
|
||||
{ assignedToId: userId },
|
||||
{ createdById: userId },
|
||||
],
|
||||
},
|
||||
include: {
|
||||
status: true,
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 5,
|
||||
}),
|
||||
]);
|
||||
|
||||
successResponse(res, {
|
||||
myTasks,
|
||||
myProjects,
|
||||
recentRMAs,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching dashboard today:', error);
|
||||
errorResponse(res, 'Chyba pri načítaní dashboardu.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
export const getDashboardWeek = async (req: AuthRequest, res: Response): Promise<void> => {
|
||||
try {
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
const nextWeek = new Date(today);
|
||||
nextWeek.setDate(nextWeek.getDate() + 7);
|
||||
|
||||
const userId = req.user!.userId;
|
||||
|
||||
const [tasksDeadlineThisWeek, upcomingRevisions] = await Promise.all([
|
||||
// Tasks with deadline this week
|
||||
prisma.task.findMany({
|
||||
where: {
|
||||
deadline: {
|
||||
gte: today,
|
||||
lte: nextWeek,
|
||||
},
|
||||
status: { isFinal: false },
|
||||
OR: [
|
||||
{ createdById: userId },
|
||||
{ assignees: { some: { userId } } },
|
||||
],
|
||||
},
|
||||
include: {
|
||||
status: true,
|
||||
priority: true,
|
||||
project: { select: { id: true, name: true } },
|
||||
assignees: { include: { user: { select: { id: true, name: true } } } },
|
||||
},
|
||||
orderBy: { deadline: 'asc' },
|
||||
}),
|
||||
|
||||
// Upcoming equipment revisions
|
||||
prisma.revision.findMany({
|
||||
where: {
|
||||
nextDueDate: {
|
||||
gte: today,
|
||||
lte: nextWeek,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
equipment: {
|
||||
include: {
|
||||
type: true,
|
||||
customer: { select: { id: true, name: true } },
|
||||
},
|
||||
},
|
||||
type: true,
|
||||
},
|
||||
orderBy: { nextDueDate: 'asc' },
|
||||
}),
|
||||
]);
|
||||
|
||||
successResponse(res, {
|
||||
tasksDeadlineThisWeek,
|
||||
upcomingRevisions,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching dashboard week:', error);
|
||||
errorResponse(res, 'Chyba pri načítaní týždenného prehľadu.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
export const getDashboardStats = async (req: AuthRequest, res: Response): Promise<void> => {
|
||||
try {
|
||||
const [
|
||||
totalProjects,
|
||||
activeProjects,
|
||||
totalTasks,
|
||||
completedTasks,
|
||||
totalCustomers,
|
||||
totalEquipment,
|
||||
totalRMAs,
|
||||
openRMAs,
|
||||
] = await Promise.all([
|
||||
prisma.project.count(),
|
||||
prisma.project.count({ where: { status: { isFinal: false } } }),
|
||||
prisma.task.count(),
|
||||
prisma.task.count({ where: { status: { isFinal: true } } }),
|
||||
prisma.customer.count({ where: { active: true } }),
|
||||
prisma.equipment.count({ where: { active: true } }),
|
||||
prisma.rMA.count(),
|
||||
prisma.rMA.count({ where: { status: { isFinal: false } } }),
|
||||
]);
|
||||
|
||||
successResponse(res, {
|
||||
projects: {
|
||||
total: totalProjects,
|
||||
active: activeProjects,
|
||||
},
|
||||
tasks: {
|
||||
total: totalTasks,
|
||||
completed: completedTasks,
|
||||
completionRate: totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0,
|
||||
},
|
||||
customers: {
|
||||
total: totalCustomers,
|
||||
},
|
||||
equipment: {
|
||||
total: totalEquipment,
|
||||
},
|
||||
rmas: {
|
||||
total: totalRMAs,
|
||||
open: openRMAs,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching dashboard stats:', error);
|
||||
errorResponse(res, 'Chyba pri načítaní štatistík.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
export const getDashboardReminders = async (req: AuthRequest, res: Response): Promise<void> => {
|
||||
try {
|
||||
const today = new Date();
|
||||
const nextMonth = new Date(today);
|
||||
nextMonth.setDate(nextMonth.getDate() + 30);
|
||||
|
||||
const userId = req.user!.userId;
|
||||
|
||||
const [taskReminders, equipmentRevisions, overdueRMAs] = await Promise.all([
|
||||
// Task reminders
|
||||
prisma.reminder.findMany({
|
||||
where: {
|
||||
userId,
|
||||
dismissed: false,
|
||||
remindAt: {
|
||||
lte: nextMonth,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
task: {
|
||||
include: {
|
||||
status: true,
|
||||
project: { select: { id: true, name: true } },
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { remindAt: 'asc' },
|
||||
}),
|
||||
|
||||
// Equipment revision reminders
|
||||
prisma.revision.findMany({
|
||||
where: {
|
||||
nextDueDate: {
|
||||
gte: today,
|
||||
lte: nextMonth,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
equipment: {
|
||||
include: {
|
||||
type: true,
|
||||
customer: { select: { id: true, name: true } },
|
||||
},
|
||||
},
|
||||
type: true,
|
||||
},
|
||||
orderBy: { nextDueDate: 'asc' },
|
||||
take: 10,
|
||||
}),
|
||||
|
||||
// Overdue or old RMAs
|
||||
prisma.rMA.findMany({
|
||||
where: {
|
||||
status: { isFinal: false },
|
||||
createdAt: {
|
||||
lte: new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000), // Older than 7 days
|
||||
},
|
||||
},
|
||||
include: {
|
||||
status: true,
|
||||
customer: { select: { id: true, name: true } },
|
||||
},
|
||||
orderBy: { createdAt: 'asc' },
|
||||
take: 10,
|
||||
}),
|
||||
]);
|
||||
|
||||
successResponse(res, {
|
||||
taskReminders,
|
||||
equipmentRevisions,
|
||||
overdueRMAs,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching dashboard reminders:', error);
|
||||
errorResponse(res, 'Chyba pri načítaní upomienok.', 500);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user