upgrade stats page
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import Layout from "../../../components/layout";
|
import Layout from "../../../components/layout";
|
||||||
import ProtectedRoute from '../../../components/protectedRoute';
|
import ProtectedRoute from '../../../components/protectedRoute';
|
||||||
import { UserRole } from '@prisma/client';
|
import { Prisma, UserRole } from '@prisma/client';
|
||||||
import axiosServer from '../../../src/axiosServer';
|
import axiosServer from '../../../src/axiosServer';
|
||||||
import common from '../../../src/helpers/common';
|
import common from '../../../src/helpers/common';
|
||||||
// import { filterPublishers, /* other functions */ } from '../../api/index';
|
// import { filterPublishers, /* other functions */ } from '../../api/index';
|
||||||
@ -9,10 +9,10 @@ import data from '../../../src/helpers/data';
|
|||||||
|
|
||||||
// const data = require('../../src/helpers/data');
|
// const data = require('../../src/helpers/data');
|
||||||
|
|
||||||
function ContactsPage({ publishers }) {
|
function ContactsPage({ publishers, allPublishers }) {
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
|
|
||||||
const filteredPublishers = publishers.filter((publisher) =>
|
const filteredPublishers = allPublishers.filter((publisher) =>
|
||||||
publisher.firstName.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
publisher.firstName.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||||
publisher.lastName.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
publisher.lastName.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||||
publisher.email.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
publisher.email.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||||
@ -24,7 +24,7 @@ function ContactsPage({ publishers }) {
|
|||||||
<ProtectedRoute allowedRoles={[UserRole.ADMIN, UserRole.POWERUSER, UserRole.USER]}>
|
<ProtectedRoute allowedRoles={[UserRole.ADMIN, UserRole.POWERUSER, UserRole.USER]}>
|
||||||
<div className="container mx-auto p-4">
|
<div className="container mx-auto p-4">
|
||||||
<h1 className="text-xl font-semibold mb-4">Статистика </h1>
|
<h1 className="text-xl font-semibold mb-4">Статистика </h1>
|
||||||
<h5 className="text-lg font-semibold mb-4">{publishers.length} участника с предпочитания</h5>
|
<h5 className="text-lg font-semibold mb-4">{publishers.length} участника с предпочитания (от {allPublishers.length} )</h5>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Търси по име, имейл или телефон..."
|
placeholder="Търси по име, имейл или телефон..."
|
||||||
@ -42,26 +42,55 @@ function ContactsPage({ publishers }) {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{filteredPublishers.map((pub) => (
|
{filteredPublishers.map((allPub) => {
|
||||||
<tr key={pub.id}>
|
// Find the publisher in the publishers collection to access statistics
|
||||||
<td className="border-b p-4 pl-8" title={pub.lastUpdate}>{pub.firstName} {pub.lastName}</td>
|
const pub = publishers.find(publisher => publisher.id === allPub.id);
|
||||||
<td className="border-b p-4">
|
|
||||||
<span title="Възможност: часове | дни" className={`badge py-1 px-2 rounded-md text-xs ${pub.currentMonthAvailabilityHoursCount || pub.currentMonthAvailabilityDaysCount ? 'bg-teal-500 text-white' : 'bg-teal-200 text-gray-300'} hover:underline`} >
|
return (
|
||||||
{pub.currentMonthAvailabilityDaysCount || 0} | {pub.currentMonthAvailabilityHoursCount || 0}
|
<tr key={allPub.id}>
|
||||||
</span>
|
<td className="border-b p-4 pl-8" title={allPub.lastUpdate}>{allPub.firstName} {allPub.lastName}</td>
|
||||||
</td>
|
{/* Display statistics if publisher is found */}
|
||||||
<td className="border-b p-4">
|
{pub ? (
|
||||||
<div className="flex items-center justify-between">
|
<>
|
||||||
<div className="flex items-center">
|
<td className="border-b p-4">
|
||||||
<span title="участия тази седмица" className={`badge py-1 px-2 rounded-full text-xs ${pub.currentWeekAssignments ? 'bg-yellow-500 text-white' : 'bg-yellow-200 text-gray-400'}`}>{pub.currentWeekAssignments || 0}</span>
|
<span title="Възможност: часове | дни" className={`badge py-1 px-2 rounded-md text-xs ${pub.currentMonthAvailabilityHoursCount || pub.currentMonthAvailabilityDaysCount ? 'bg-teal-500 text-white' : 'bg-teal-200 text-gray-300'} hover:underline`}>
|
||||||
<span title="участия този месец" className={`badge py-1 px-2 rounded-full text-xs ${pub.currentMonthAssignments ? 'bg-green-500 text-white' : 'bg-green-200 text-gray-400'}`}>{pub.currentMonthAssignments || 0}</span>
|
{pub.currentMonthAvailabilityDaysCount || 0} | {pub.currentMonthAvailabilityHoursCount || 0}
|
||||||
<span tooltip="участия миналия месец" title="участия миналия месец" className={`badge py-1 px-2 rounded-full text-xs ${pub.previousMonthAssignments ? 'bg-blue-500 text-white' : 'bg-blue-200 text-gray-400'}`}>{pub.previousMonthAssignments || 0}</span>
|
</span>
|
||||||
<button tooltip="желани участия този месец" title="желани участия" className={`badge py-1 px-2 rounded-md text-xs ${pub.desiredShiftsPerMonth ? 'bg-purple-500 text-white' : 'bg-purple-200 text-gray-400'}`}>{pub.desiredShiftsPerMonth || 0}</button>
|
</td>
|
||||||
</div>
|
<td className="border-b p-4">
|
||||||
</div>
|
<div className="flex items-center justify-between">
|
||||||
</td>
|
<div className="flex items-center">
|
||||||
</tr>
|
<span title="участия тази седмица" className={`badge py-1 px-2 rounded-full text-xs ${pub.currentWeekAssignments ? 'bg-yellow-500 text-white' : 'bg-yellow-200 text-gray-400'}`}>{pub.currentWeekAssignments || 0}</span>
|
||||||
))}
|
<span title="участия този месец" className={`badge py-1 px-2 rounded-full text-xs ${pub.currentMonthAssignments ? 'bg-green-500 text-white' : 'bg-green-200 text-gray-400'}`}>{pub.currentMonthAssignments || 0}</span>
|
||||||
|
<span title="участия миналия месец" className={`badge py-1 px-2 rounded-full text-xs ${pub.previousMonthAssignments ? 'bg-blue-500 text-white' : 'bg-blue-200 text-gray-400'}`}>{pub.previousMonthAssignments || 0}</span>
|
||||||
|
<button title="желани участия" className={`badge py-1 px-2 rounded-md text-xs ${pub.desiredShiftsPerMonth ? 'bg-purple-500 text-white' : 'bg-purple-200 text-gray-400'}`}>{pub.desiredShiftsPerMonth || 0}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<td className="border-b p-4">
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td className="border-b p-4">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div className="flex items-center">
|
||||||
|
<span className="badge py-1 px-2 rounded-md text-xs bg-gray-300 text-gray-500" title="участия този месец">
|
||||||
|
{allPub.currentMonthAssignments || 0}
|
||||||
|
</span>
|
||||||
|
<span className="badge py-1 px-2 rounded-md text-xs bg-gray-300 text-gray-500" title="участия миналия месец">
|
||||||
|
{allPub.previousMonthAssignments || 0}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="border-b p-4"></td> {/* Empty cell for alignment */}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -74,7 +103,26 @@ function ContactsPage({ publishers }) {
|
|||||||
|
|
||||||
export default ContactsPage;
|
export default ContactsPage;
|
||||||
|
|
||||||
|
|
||||||
|
// Helper functions ToDo: move them to common and replace all implementations with the common ones
|
||||||
|
function countAssignments(assignments, startTime, endTime) {
|
||||||
|
return assignments.filter(assignment =>
|
||||||
|
assignment.shift.startTime >= startTime && assignment.shift.startTime <= endTime
|
||||||
|
).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertShiftDates(assignments) {
|
||||||
|
assignments.forEach(assignment => {
|
||||||
|
if (assignment.shift && assignment.shift.startTime) {
|
||||||
|
assignment.shift.startTime = new Date(assignment.shift.startTime).toISOString();
|
||||||
|
assignment.shift.endTime = new Date(assignment.shift.endTime).toISOString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export const getServerSideProps = async (context) => {
|
export const getServerSideProps = async (context) => {
|
||||||
|
|
||||||
|
const prisma = common.getPrismaClient();
|
||||||
const dateStr = new Date().toISOString().split('T')[0];
|
const dateStr = new Date().toISOString().split('T')[0];
|
||||||
|
|
||||||
let publishers = await data.filterPublishersNew('id,firstName,lastName,email,isActive,desiredShiftsPerMonth', dateStr, false, true, true);
|
let publishers = await data.filterPublishersNew('id,firstName,lastName,email,isActive,desiredShiftsPerMonth', dateStr, false, true, true);
|
||||||
@ -118,9 +166,65 @@ export const getServerSideProps = async (context) => {
|
|||||||
//remove publishers without availabilities
|
//remove publishers without availabilities
|
||||||
publishers = publishers.filter(publisher => publisher.availabilities.length > 0);
|
publishers = publishers.filter(publisher => publisher.availabilities.length > 0);
|
||||||
|
|
||||||
|
let allPublishers = await prisma.publisher.findMany({
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
email: true,
|
||||||
|
phone: true,
|
||||||
|
isActive: true,
|
||||||
|
desiredShiftsPerMonth: true,
|
||||||
|
assignments: {
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
shift: {
|
||||||
|
select: {
|
||||||
|
startTime: true,
|
||||||
|
endTime: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let monthInfo,
|
||||||
|
currentMonthStart, currentMonthEnd,
|
||||||
|
previousMonthStart, previousMonthEnd;
|
||||||
|
|
||||||
|
monthInfo = common.getMonthDatesInfo(new Date());
|
||||||
|
currentMonthStart = monthInfo.firstMonday;
|
||||||
|
currentMonthEnd = monthInfo.lastSunday;
|
||||||
|
let prevMnt = new Date();
|
||||||
|
prevMnt.setMonth(prevMnt.getMonth() - 1);
|
||||||
|
monthInfo = common.getMonthDatesInfo(prevMnt);
|
||||||
|
previousMonthStart = monthInfo.firstMonday;
|
||||||
|
previousMonthEnd = monthInfo.lastSunday;
|
||||||
|
|
||||||
|
|
||||||
|
allPublishers.forEach(publisher => {
|
||||||
|
// Use helper functions to calculate and assign assignment counts
|
||||||
|
publisher.currentMonthAssignments = countAssignments(publisher.assignments, currentMonthStart, currentMonthEnd);
|
||||||
|
publisher.previousMonthAssignments = countAssignments(publisher.assignments, previousMonthStart, previousMonthEnd);
|
||||||
|
|
||||||
|
// Convert date formats within the same iteration
|
||||||
|
convertShiftDates(publisher.assignments);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Optionally, if you need a transformed list or additional properties, map the publishers
|
||||||
|
allPublishers = allPublishers.map(publisher => ({
|
||||||
|
...publisher,
|
||||||
|
// Potentially add more computed properties or transformations here if needed
|
||||||
|
}));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
publishers,
|
publishers,
|
||||||
|
allPublishers,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -482,6 +482,7 @@ async function filterPublishersNew(selectFields, filterDate, isExactTime = false
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function matchesAvailability(avail, filterDate) {
|
function matchesAvailability(avail, filterDate) {
|
||||||
// Setting the start and end time of the filterDate
|
// Setting the start and end time of the filterDate
|
||||||
filterDate.setHours(0, 0, 0, 0);
|
filterDate.setHours(0, 0, 0, 0);
|
||||||
|
Reference in New Issue
Block a user