From c290b1a37be41e211c9729dee91900769ed2c57c Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Sat, 28 Dec 2024 17:15:47 +0200 Subject: [PATCH] add date filter to assignments --- .gitignore | 1 + components/reports/ReportForm.js | 1 + pages/api/data/prisma/[...model].ts | 22 +++++++++- pages/cart/publishers/index.tsx | 65 ++++++++++++++++++++++++++--- 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 4339447..12de6ff 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ public/content/output/shifts 2024.1.json !public/content/uploads/* .aider* /shift_generate_log_*.txt +.env diff --git a/components/reports/ReportForm.js b/components/reports/ReportForm.js index ae183e0..c5ede0c 100644 --- a/components/reports/ReportForm.js +++ b/components/reports/ReportForm.js @@ -95,6 +95,7 @@ export default function ReportForm({ shiftId, existingItem, onDone }) { delete item.shift; } else { item.shift = { connect: { id: parseInt(item.shiftId) } }; + // item.shift = { connect: { id: item.shiftId.toString() } }; } delete item.shiftId; item.date = new Date(item.date); diff --git a/pages/api/data/prisma/[...model].ts b/pages/api/data/prisma/[...model].ts index 3ea950c..2260059 100644 --- a/pages/api/data/prisma/[...model].ts +++ b/pages/api/data/prisma/[...model].ts @@ -2,6 +2,7 @@ import { NextApiRequest, NextApiResponse } from 'next'; import { PrismaClient } from '@prisma/client'; import { getServerSession } from "next-auth/next"; import { authOptions } from "../../auth/[...nextauth]"; +import e from 'express'; 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')) { // Handle POST request queryOptions = req.body; - } else { + } else if (req.method === 'GET') { // Handle GET request queryOptions = parseQueryParams(req.query); } + else if (req.method === 'DELETE') { + // Handle DELETE request + queryOptions = req.body; + + } try { if (!modelArray || modelArray.length === 0) { @@ -84,6 +90,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) if (!prisma[modelName]) { 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); if (req.query.format === 'sql') { // Generate SQL if requested via query parameter diff --git a/pages/cart/publishers/index.tsx b/pages/cart/publishers/index.tsx index 8e8b55d..4768f23 100644 --- a/pages/cart/publishers/index.tsx +++ b/pages/cart/publishers/index.tsx @@ -1,6 +1,12 @@ // Next.js page to show all locations in the database with a link to the location page import { useSession } from "next-auth/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 { NextAuth } from 'next-auth/client' import { Publisher, UserRole } from "@prisma/client"; @@ -26,6 +32,7 @@ function PublishersPage({ publishers = [] }: IProps) { const [filter, setFilter] = useState(""); const [showZeroShiftsOnly, setShowZeroShiftsOnly] = useState(false); + const [selectedDate, setSelectedDate] = useState(null); const [filterIsImported, setFilterIsImported] = useState({ checked: false, indeterminate: true, @@ -113,10 +120,22 @@ function PublishersPage({ publishers = [] }: IProps) { // Combine name and email filters, removing duplicates let filteredPublishers = [...new Set([...filteredPublishersByName, ...filteredPublishersByEmail])]; - // inactive publishers filter - filteredPublishers = showZeroShiftsOnly - ? filteredPublishers.filter(p => p.assignments.length === 0) - : filteredPublishers; + // Zero shifts (inactive) and date filter + if (showZeroShiftsOnly && selectedDate) { + filteredPublishers = publishers.filter(publisher => { + // 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 if (flterNoTraining) { @@ -124,9 +143,15 @@ function PublishersPage({ publishers = [] }: IProps) { } 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 = () => { if (shownPubs.length === 0) { @@ -239,6 +264,36 @@ function PublishersPage({ publishers = [] }: IProps) { /> само без смени + {showZeroShiftsOnly && ( +
+ след: + 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]" + /> +
+ )}