add date filter to assignments
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -37,3 +37,4 @@ public/content/output/shifts 2024.1.json
|
|||||||
!public/content/uploads/*
|
!public/content/uploads/*
|
||||||
.aider*
|
.aider*
|
||||||
/shift_generate_log_*.txt
|
/shift_generate_log_*.txt
|
||||||
|
.env
|
||||||
|
@ -95,6 +95,7 @@ export default function ReportForm({ shiftId, existingItem, onDone }) {
|
|||||||
delete item.shift;
|
delete item.shift;
|
||||||
} else {
|
} else {
|
||||||
item.shift = { connect: { id: parseInt(item.shiftId) } };
|
item.shift = { connect: { id: parseInt(item.shiftId) } };
|
||||||
|
// item.shift = { connect: { id: item.shiftId.toString() } };
|
||||||
}
|
}
|
||||||
delete item.shiftId;
|
delete item.shiftId;
|
||||||
item.date = new Date(item.date);
|
item.date = new Date(item.date);
|
||||||
|
@ -2,6 +2,7 @@ import { NextApiRequest, NextApiResponse } from 'next';
|
|||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
import { getServerSession } from "next-auth/next";
|
import { getServerSession } from "next-auth/next";
|
||||||
import { authOptions } from "../../auth/[...nextauth]";
|
import { authOptions } from "../../auth/[...nextauth]";
|
||||||
|
import e from 'express';
|
||||||
|
|
||||||
|
|
||||||
const common = require('../../../../src/helpers/common');
|
const common = require('../../../../src/helpers/common');
|
||||||
@ -71,10 +72,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
if (req.method === 'POST' && req.headers['content-type']?.includes('application/json')) {
|
if (req.method === 'POST' && req.headers['content-type']?.includes('application/json')) {
|
||||||
// Handle POST request
|
// Handle POST request
|
||||||
queryOptions = req.body;
|
queryOptions = req.body;
|
||||||
} else {
|
} else if (req.method === 'GET') {
|
||||||
// Handle GET request
|
// Handle GET request
|
||||||
queryOptions = parseQueryParams(req.query);
|
queryOptions = parseQueryParams(req.query);
|
||||||
}
|
}
|
||||||
|
else if (req.method === 'DELETE') {
|
||||||
|
// Handle DELETE request
|
||||||
|
queryOptions = req.body;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!modelArray || modelArray.length === 0) {
|
if (!modelArray || modelArray.length === 0) {
|
||||||
@ -84,6 +90,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
if (!prisma[modelName]) {
|
if (!prisma[modelName]) {
|
||||||
throw new Error(`Model ${modelName} not found in Prisma client.`);
|
throw new Error(`Model ${modelName} not found in Prisma client.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
// Create a new record
|
||||||
|
const result = await prisma[modelName].create({ data: queryOptions });
|
||||||
|
res.status(201).json(result);
|
||||||
|
return;
|
||||||
|
} else if (req.method === 'DELETE') {
|
||||||
|
// Delete a record
|
||||||
|
const result = await prisma[modelName].delete({ where: queryOptions });
|
||||||
|
res.status(200).json(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Fetch records
|
||||||
|
|
||||||
const result = await prisma[modelName].findMany(queryOptions);
|
const result = await prisma[modelName].findMany(queryOptions);
|
||||||
if (req.query.format === 'sql') {
|
if (req.query.format === 'sql') {
|
||||||
// Generate SQL if requested via query parameter
|
// Generate SQL if requested via query parameter
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
// Next.js page to show all locations in the database with a link to the location page
|
// Next.js page to show all locations in the database with a link to the location page
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import { useEffect, useState, useRef, use } from "react";
|
import { useEffect, useState, useRef, use } from "react";
|
||||||
|
|
||||||
|
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
|
||||||
|
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
|
||||||
|
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
|
||||||
|
import { DesktopDatePicker } from '@mui/x-date-pickers/DesktopDatePicker';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
// import { getSession } from 'next-auth/client'
|
// import { getSession } from 'next-auth/client'
|
||||||
// import { NextAuth } from 'next-auth/client'
|
// import { NextAuth } from 'next-auth/client'
|
||||||
import { Publisher, UserRole } from "@prisma/client";
|
import { Publisher, UserRole } from "@prisma/client";
|
||||||
@ -26,6 +32,7 @@ function PublishersPage({ publishers = [] }: IProps) {
|
|||||||
|
|
||||||
const [filter, setFilter] = useState("");
|
const [filter, setFilter] = useState("");
|
||||||
const [showZeroShiftsOnly, setShowZeroShiftsOnly] = useState(false);
|
const [showZeroShiftsOnly, setShowZeroShiftsOnly] = useState(false);
|
||||||
|
const [selectedDate, setSelectedDate] = useState<dayjs.Dayjs | null>(null);
|
||||||
const [filterIsImported, setFilterIsImported] = useState({
|
const [filterIsImported, setFilterIsImported] = useState({
|
||||||
checked: false,
|
checked: false,
|
||||||
indeterminate: true,
|
indeterminate: true,
|
||||||
@ -113,10 +120,22 @@ function PublishersPage({ publishers = [] }: IProps) {
|
|||||||
// Combine name and email filters, removing duplicates
|
// Combine name and email filters, removing duplicates
|
||||||
let filteredPublishers = [...new Set([...filteredPublishersByName, ...filteredPublishersByEmail])];
|
let filteredPublishers = [...new Set([...filteredPublishersByName, ...filteredPublishersByEmail])];
|
||||||
|
|
||||||
// inactive publishers filter
|
// Zero shifts (inactive) and date filter
|
||||||
filteredPublishers = showZeroShiftsOnly
|
if (showZeroShiftsOnly && selectedDate) {
|
||||||
? filteredPublishers.filter(p => p.assignments.length === 0)
|
filteredPublishers = publishers.filter(publisher => {
|
||||||
: filteredPublishers;
|
// If no assignments at all, include in results
|
||||||
|
if (publisher.assignments.length === 0) return true;
|
||||||
|
|
||||||
|
// Only include publishers who don't have any assignments after the selected date
|
||||||
|
return !publisher.assignments.some(assignment => {
|
||||||
|
const shiftDate = dayjs(assignment.shift.startTime);
|
||||||
|
return shiftDate.isAfter(selectedDate);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else if (showZeroShiftsOnly) {
|
||||||
|
// If checkbox is checked but no date selected, show publishers with no assignments
|
||||||
|
filteredPublishers = publishers.filter(publisher => publisher.assignments.length === 0);
|
||||||
|
}
|
||||||
|
|
||||||
// trained filter
|
// trained filter
|
||||||
if (flterNoTraining) {
|
if (flterNoTraining) {
|
||||||
@ -124,9 +143,15 @@ function PublishersPage({ publishers = [] }: IProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setShownPubs(filteredPublishers);
|
setShownPubs(filteredPublishers);
|
||||||
}, [filter, showZeroShiftsOnly, flterNoTraining]);
|
}, [filter, showZeroShiftsOnly, selectedDate, flterNoTraining]);
|
||||||
|
|
||||||
|
|
||||||
|
// Separate effect to handle date reset when checkbox is unchecked
|
||||||
|
useEffect(() => {
|
||||||
|
if (!showZeroShiftsOnly) {
|
||||||
|
setSelectedDate(null);
|
||||||
|
}
|
||||||
|
}, [showZeroShiftsOnly]);
|
||||||
|
|
||||||
const renderPublishers = () => {
|
const renderPublishers = () => {
|
||||||
if (shownPubs.length === 0) {
|
if (shownPubs.length === 0) {
|
||||||
@ -239,6 +264,36 @@ function PublishersPage({ publishers = [] }: IProps) {
|
|||||||
/>
|
/>
|
||||||
<span className="ml-2">само без смени</span>
|
<span className="ml-2">само без смени</span>
|
||||||
</label>
|
</label>
|
||||||
|
{showZeroShiftsOnly && (
|
||||||
|
<div className="flex items-center space-x-2 ml-2">
|
||||||
|
<span className="whitespace-nowrap">след:</span>
|
||||||
|
<DatePicker
|
||||||
|
value={selectedDate}
|
||||||
|
onChange={(newDate) => setSelectedDate(newDate)}
|
||||||
|
slotProps={{
|
||||||
|
textField: {
|
||||||
|
size: "small",
|
||||||
|
sx: {
|
||||||
|
width: '140px',
|
||||||
|
'& .MuiInputBase-input': {
|
||||||
|
padding: '4px 8px',
|
||||||
|
fontSize: '0.875rem'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mobileWrapper: {
|
||||||
|
sx: {
|
||||||
|
'& .MuiPickersLayout-root': {
|
||||||
|
minWidth: 'unset'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
format="DD.MM.YYYY"
|
||||||
|
className="min-w-[120px]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<label htmlFor="filterTrained" className="ml-4 inline-flex items-center">
|
<label htmlFor="filterTrained" className="ml-4 inline-flex items-center">
|
||||||
<input type="checkbox" id="filterTrained" name="filterTrained"
|
<input type="checkbox" id="filterTrained" name="filterTrained"
|
||||||
|
Reference in New Issue
Block a user