import { useState, useEffect, useRef } from 'react'; import Layout from "../../../components/layout"; import ProtectedRoute from '../../../components/protectedRoute'; 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'; function ContactsPage({ allPublishers }) { const currentMonth = new Date().getMonth(); const [selectedMonth, setSelectedMonth] = useState(currentMonth + 1); const isMounted = useRef(false); const [searchQuery, setSearchQuery] = useState(''); const [publisherType, setPublisherType] = useState(''); const [publishers, setPublishers] = useState(allPublishers); const [pubWithAssignmentsCount, setPubWithAssignmentsCount] = useState(0); const [filteredPublishers, setFilteredPublishers] = useState(allPublishers); const [sortField, setSortField] = useState('name'); const [sortOrder, setSortOrder] = useState('asc'); const months = common.getMonthNames(); const subsetMonths = Array.from({ length: 9 }, (_, i) => { const monthIndex = (currentMonth - 3 + i + 12) % 12; // Adjust for year wrap-around return { name: months[monthIndex], index: monthIndex + 1 }; }); const [hideEmptyFields, setHideEmptyFields] = useState({ availability: 'off', // 'on', 'off', 'onlyEmpty' assignments: 'off', // 'on', 'off', 'onlyEmpty' lastLogin: false, notifiications: false }); const availabilityRef = useRef(null); const assignmentsRef = useRef(null); useEffect(() => { if (availabilityRef.current) { availabilityRef.current.indeterminate = hideEmptyFields.availability === 'off'; } }, [hideEmptyFields.availability]); useEffect(() => { if (assignmentsRef.current) { assignmentsRef.current.indeterminate = hideEmptyFields.assignments === 'off'; } }, [hideEmptyFields.assignments]); const getCheckboxState = (field) => { switch (hideEmptyFields[field]) { case 'on': return true; case 'onlyEmpty': return false; default: return undefined; // this will be used to set indeterminate } }; const getCheckboxTooltip = (field, label) => { switch (hideEmptyFields[field]) { case 'on': return 'Само със ' + label; case 'onlyEmpty': return 'Само без ' + label; default: return 'Всички ' + label; } } function handleSort(field) { const order = sortField === field && sortOrder === 'asc' ? 'desc' : 'asc'; setSortField(field); setSortOrder(order); } useEffect(() => { let filtered = publishers.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) // && (!hideEmptyFields.availability || publisher.currentMonthAvailabilityDaysCount > 0) // && (!hideEmptyFields.assignments || publisher.currentMonthAssignments > 0) && (hideEmptyFields.availability === 'on' ? publisher.currentMonthAvailabilityDaysCount > 0 : hideEmptyFields.availability === 'onlyEmpty' ? !publisher.currentMonthAvailabilityDaysCount || publisher.currentMonthAvailabilityDaysCount === 0 : true) && (hideEmptyFields.assignments === 'on' ? publisher.currentMonthAssignments > 0 : hideEmptyFields.assignments === 'onlyEmpty' ? publisher.currentMonthAssignments === 0 : true) && (!hideEmptyFields.lastLogin || publisher.lastLogin) && (!hideEmptyFields.notifiications || publisher.isPushActive) ); 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); setPubWithAssignmentsCount(filtered.filter(publisher => publisher.currentMonthAvailabilityHoursCount && publisher.currentMonthAvailabilityHoursCount > 0).length); }, [searchQuery, publisherType, sortField, sortOrder, allPublishers, hideEmptyFields, selectedMonth]); 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()}&noEndDate=false`); setPublishers(response.data); setFilteredPublishers(response.data); setPubWithAssignmentsCount(response.data.filter(publisher => publisher.currentMonthAvailabilityHoursCount && publisher.currentMonthAvailabilityHoursCount > 0).length); setHideEmptyFields({ availability: 'off', assignments: 'off', lastLogin: false, notifiications: false }) } 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 (

Статистика

{pubWithAssignmentsCount} участника с предпочитания за месеца (от {filteredPublishers.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((pub, i) => { return ( {/* Display statistics if publisher is found */} {pub ? ( <> ) : ( <> {/* Empty cell for alignment */} )} ); })}
handleSort('name')}> Име{renderSortArrow('name')}

handleSort('currentMonthAvailabilityDaysCount')}> Възможности{renderSortArrow('currentMonthAvailabilityDaysCount')}

{ const newState = hideEmptyFields.availability === 'on' ? 'onlyEmpty' : (hideEmptyFields.availability === 'onlyEmpty' ? 'off' : 'on'); setHideEmptyFields({ ...hideEmptyFields, availability: newState }); }} title={getCheckboxTooltip('availability', "възможности")} />

handleSort('currentMonthAssignments')}> Участия{renderSortArrow('currentMonthAssignments')}

{ const newState = hideEmptyFields.assignments === 'on' ? 'onlyEmpty' : (hideEmptyFields.assignments === 'onlyEmpty' ? 'off' : 'on'); setHideEmptyFields({ ...hideEmptyFields, assignments: newState }); }} title={getCheckboxTooltip('assignments', "участия")} />

handleSort('lastLogin')}> Последно влизане{renderSortArrow('lastLogin')}

setHideEmptyFields({ ...hideEmptyFields, lastLogin: !hideEmptyFields.lastLogin })} title="Скрий редове без нотификации" />

Нотификации

setHideEmptyFields({ ...hideEmptyFields, notifiications: !hideEmptyFields.notifiications })} title="Скрий редове без последно влизане" />
{i + 1}. {pub.firstName} {pub.lastName} {pub.availabilities.length > 0 ? ( {pub.currentMonthAvailabilityDaysCount} | {pub.currentMonthAvailabilityHoursCount} ) : 0}
{pub.currentWeekAssignments || 0} {pub.currentMonthAssignments || 0} {pub.previousMonthAssignments || 0}
{pub.lastLogin ? new Date(pub.lastLogin).toLocaleString("bg") : ""}
{pub.currentMonthAssignments} {pub.previousMonthAssignments}
{pub.isPushActive ? ( ) : ( )}
); } export default ContactsPage; export const getServerSideProps = async (context) => { const allPublishers = await data.getAllPublishersWithStatisticsMonth(new Date()); // Merge first and last name and serialize Date objects allPublishers.forEach(publisher => { publisher.name = `${publisher.firstName} ${publisher.lastName}`; if (publisher.currentMonthAvailability) { publisher.currentMonthAvailability = publisher.currentMonthAvailability.map(availability => { return { ...availability, startTime: availability.startTime instanceof Date ? availability.startTime.toISOString() : availability.startTime, endTime: availability.endTime instanceof Date ? availability.endTime.toISOString() : availability.endTime, dateOfEntry: availability.dateOfEntry instanceof Date ? availability.dateOfEntry.toISOString() : availability.dateOfEntry, }; }); } }); return { props: { allPublishers }, }; };