From db17572ea6cce2b675af844e0c8fbfdaf289e0fb Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Thu, 2 May 2024 01:50:09 +0300 Subject: [PATCH] add statsFilters --- pages/cart/publishers/stats.tsx | 297 ++++++++++++++++---------------- 1 file changed, 144 insertions(+), 153 deletions(-) diff --git a/pages/cart/publishers/stats.tsx b/pages/cart/publishers/stats.tsx index 2e8b558..70d503d 100644 --- a/pages/cart/publishers/stats.tsx +++ b/pages/cart/publishers/stats.tsx @@ -1,62 +1,173 @@ -import { useState } from 'react'; +import { useState, useEffect, useRef } from 'react'; import Layout from "../../../components/layout"; import ProtectedRoute from '../../../components/protectedRoute'; -import { Prisma, UserRole } from '@prisma/client'; +import { Prisma, UserRole, PublisherType } from '@prisma/client'; import axiosServer from '../../../src/axiosServer'; import common from '../../../src/helpers/common'; // import { filterPublishers, /* other functions */ } from '../../api/index'; import data from '../../../src/helpers/data'; +import axiosInstance from '../../../src/axiosSecure'; +import { setFlagsFromString } from 'v8'; +import { set } from 'date-fns'; -// const data = require('../../src/helpers/data'); +function ContactsPage({ allPublishers }) { + + const currentMonth = new Date().getMonth(); + const [selectedMonth, setSelectedMonth] = useState(""); + const isMounted = useRef(false); -function ContactsPage({ publishers, allPublishers }) { const [searchQuery, setSearchQuery] = useState(''); + const [publisherType, setPublisherType] = useState(''); + const [publishers, setPublishers] = useState(allPublishers); + const [pubWithAssignmentsCount, setPubWithAssignmentsCount] = useState(0); + const [filteredPublishers, setFilteredPublishers] = useState(allPublishers); - const filteredPublishers = allPublishers.filter((publisher) => - publisher.firstName.toLowerCase().includes(searchQuery.toLowerCase()) || - publisher.lastName.toLowerCase().includes(searchQuery.toLowerCase()) || - publisher.email.toLowerCase().includes(searchQuery.toLowerCase()) || - publisher.phone?.toLowerCase().includes(searchQuery.toLowerCase()) - ); + const [sortField, setSortField] = useState('firstName'); + const [sortOrder, setSortOrder] = useState('asc'); + + const months = common.getMonthNames(); + const subsetMonths = Array.from({ length: 7 }, (_, i) => { + const monthIndex = (currentMonth - 3 + i + 12) % 12; // Adjust for year wrap-around + return { + name: months[monthIndex], + index: monthIndex + 1 + }; + }); + const datesOn15th = Array.from({ length: 7 }, (_, i) => new Date(new Date().getFullYear(), new Date().getMonth() - 3 + i, 15)) + .map(date => date.toISOString().split('T')[0]); + + + function handleSort(field) { + const order = sortField === field && sortOrder === 'asc' ? 'desc' : 'asc'; + setSortField(field); + setSortOrder(order); + } + + useEffect(() => { + let filtered = allPublishers.filter(publisher => + (publisher.firstName.toLowerCase().includes(searchQuery.toLowerCase()) || + publisher.lastName.toLowerCase().includes(searchQuery.toLowerCase()) || + publisher.email.toLowerCase().includes(searchQuery.toLowerCase()) || + (publisher.phone?.toLowerCase().includes(searchQuery.toLowerCase()))) && + (publisherType ? publisher.type === publisherType : true) + ); + + if (sortField) { + filtered.sort((a, b) => { + // Check for undefined or null values and treat them as "larger" when sorting ascending + const aValue = a[sortField] || 0; // Treat undefined, null as 0 + const bValue = b[sortField] || 0; // Treat undefined, null as 0 + + if (aValue === 0 && bValue !== 0) return 1; // aValue is falsy, push it to end if asc + if (bValue === 0 && aValue !== 0) return -1; // bValue is falsy, push it to end if asc + + if (aValue < bValue) return sortOrder === 'asc' ? -1 : 1; + if (aValue > bValue) return sortOrder === 'asc' ? 1 : -1; + return 0; + }); + } + setFilteredPublishers(filtered); + }, [searchQuery, publisherType, sortField, sortOrder, allPublishers]); + + useEffect(() => { + if (isMounted.current) { + const fetchData = async () => { + const month = parseInt(selectedMonth); + const filterDate = new Date(new Date().getFullYear(), month - 1, 15); + try { + const response = await axiosInstance.get(`/api/?action=getAllPublishersWithStatistics&date=${filterDate.toISOString()}`); + setPublishers(response.data); + setFilteredPublishers(response.data); + + setPubWithAssignmentsCount(response.data.filter(publisher => publisher.currentMonthAvailabilityHoursCount && publisher.currentMonthAvailabilityHoursCount > 0).length); + } catch (error) { + console.error('Failed to fetch publishers data:', error); + // Optionally, handle errors more gracefully here + } + }; + fetchData(); + } else { + // Set the ref to true after the initial render + isMounted.current = true; + } + }, [selectedMonth]); // Dependency array includes only selectedMonth + + function renderSortArrow(field) { + return sortField === field ? sortOrder === 'asc' ? ' ↑' : ' ↓' : ''; + } return (

Статистика

-
{publishers.length} участника с предпочитания за месеца (от {allPublishers.length} )
- setSearchQuery(e.target.value)} - className="border border-gray-300 rounded-md px-2 py-2 mb-4 w-full text-base md:text-sm" - /> +
{pubWithAssignmentsCount} участника с предпочитания за месеца (от {allPublishers.length} )
+
+ setSearchQuery(e.target.value)} + className="border border-gray-300 rounded-md px-2 py-2 text-base md:text-sm flex-grow mr-2" + /> + {/* Month dropdown */} + + {/* Publisher type dropdown */} + +
- - - - + + + + - {filteredPublishers.map((allPub) => { + {filteredPublishers.map((pub) => { // Find the publisher in the publishers collection to access statistics - const pub = publishers.find(publisher => publisher.id === allPub.id); + //const pub = publishers.find(publisher => publisher.id === allPub.id); return ( - - + + {/* Display statistics if publisher is found */} {pub ? ( <>
ИмеВъзможностиУчастияПоследно влизане handleSort('firstName')}> + Име{renderSortArrow('firstName')} + handleSort('currentMonthAvailabilityDaysCount')}> + Възможности{renderSortArrow('currentMonthAvailabilityDaysCount')} + handleSort('currentMonthAssignments')}> + Участия{renderSortArrow('currentMonthAssignments')} + handleSort('lastLogin')}> + Последно влизане{renderSortArrow('lastLogin')} +
{allPub.firstName} {allPub.lastName}
{pub.firstName} {pub.lastName} - - {pub.currentMonthAvailabilityDaysCount || 0} | {pub.currentMonthAvailabilityHoursCount || 0} - + {pub.availabilities.length > 0 ? ( + + {pub.currentMonthAvailabilityDaysCount} | {pub.currentMonthAvailabilityHoursCount} + + ) : 0}
@@ -79,10 +190,10 @@ function ContactsPage({ publishers, allPublishers }) {
- {allPub.currentMonthAssignments || 0} + {pub.currentMonthAssignments} - {allPub.previousMonthAssignments || 0} + {pub.previousMonthAssignments}
@@ -106,132 +217,12 @@ function ContactsPage({ publishers, allPublishers }) { 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) => { - - const prisma = common.getPrismaClient(); - const dateStr = new Date().toISOString().split('T')[0]; - - let publishers = await data.filterPublishersNew('id,firstName,lastName,email,isActive,desiredShiftsPerMonth,lastLogin', dateStr, false, true, true, true, true); - - // const axios = await axiosServer(context); - // const { data: publishers } = await axios.get(`api/?action=filterPublishers&assignments=true&availabilities=true&date=${dateStr}&select=id,firstName,lastName,isActive,desiredShiftsPerMonth`); - - // api/index?action=filterPublishers&assignments=true&availabilities=true&date=2024-03-14&select=id%2CfirstName%2ClastName%2CisActive%2CdesiredShiftsPerMonth - publishers.forEach(publisher => { - publisher.desiredShiftsPerMonth = publisher.desiredShiftsPerMonth || 0; - publisher.assignments = publisher.assignments || []; - publisher.availabilities = publisher.availabilities || []; - publisher.lastUpdate = publisher.availabilities.reduce((acc, curr) => curr.dateOfEntry > acc ? curr.dateOfEntry : acc, null); - if (publisher.lastUpdate) { - publisher.lastUpdate = common.getDateFormated(publisher.lastUpdate); - } - else { - publisher.lastUpdate = "Няма данни"; - } - //serialize dates in publisher.assignments and publisher.availabilities - publisher.assignments.forEach(assignment => { - if (assignment.shift && assignment.shift.startTime) { - assignment.shift.startTime = assignment.shift.startTime.toISOString(); - assignment.shift.endTime = assignment.shift.endTime.toISOString(); - } - }); - publisher.availabilities.forEach(availability => { - if (availability.startTime) { - availability.startTime = availability.startTime.toISOString(); - availability.endTime = availability.endTime.toISOString(); - if (availability.dateOfEntry) { - availability.dateOfEntry = availability.dateOfEntry.toISOString(); - } - } - }); - publisher.lastLogin = publisher.lastLogin ? publisher.lastLogin.toISOString() : null; - //remove availabilities that isFromPreviousAssignment - publisher.availabilities = publisher.availabilities.filter(availability => !availability.isFromPreviousAssignment); - - - }); - //remove publishers without availabilities - 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, - lastLogin: 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); - - publisher.lastLogin = publisher.lastLogin ? publisher.lastLogin.toISOString() : null; - // 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 - })); - allPublishers.sort((a, b) => a.firstName.localeCompare(b.firstName) || a.lastName.localeCompare(b.lastName)); - - + const allPublishers = await data.getAllPublishersWithStatistics(new Date()); return { props: { - publishers, - allPublishers, + allPublishers }, }; };