new cover me logs page
This commit is contained in:
@ -232,4 +232,9 @@ in schedule admin - if a publisher is always pair & family is not in the shift -
|
|||||||
[x] OK заместник, предпочитание в миналото - да не може.
|
[x] OK заместник, предпочитание в миналото - да не може.
|
||||||
[] Да иска потвърждение преди да заместиш някой
|
[] Да иска потвърждение преди да заместиш някой
|
||||||
[] да не се виждат непубликуваните смени в Моите смени
|
[] да не се виждат непубликуваните смени в Моите смени
|
||||||
[] да не се виждат старите предпочитания ако не си админ в публишерс
|
[] да не се виждат старите предпочитания ако не си админ в публишерс
|
||||||
|
|
||||||
|
[] import avalabilities only if no availabilities are set for the month!
|
||||||
|
[] new page to show EventLog (substitutions)
|
||||||
|
[] fix "login as"
|
||||||
|
[] list with open shift replacements (coverMe requests)
|
||||||
|
@ -112,6 +112,11 @@ const sidemenu = [
|
|||||||
text: "Статистика",
|
text: "Статистика",
|
||||||
url: "/cart/publishers/stats",
|
url: "/cart/publishers/stats",
|
||||||
roles: [UserRole.ADMIN, UserRole.POWERUSER],
|
roles: [UserRole.ADMIN, UserRole.POWERUSER],
|
||||||
|
}, {
|
||||||
|
id: "coverMeLogs",
|
||||||
|
text: "Замествания",
|
||||||
|
url: "/cart/reports/coverMe",
|
||||||
|
roles: [UserRole.ADMIN, UserRole.POWERUSER],
|
||||||
},
|
},
|
||||||
|
|
||||||
]
|
]
|
||||||
|
44
pages/api/data/prisma/[...model].ts
Normal file
44
pages/api/data/prisma/[...model].ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
import { PrismaClient } from '@prisma/client';
|
||||||
|
|
||||||
|
const common = require('../../../../src/helpers/common');
|
||||||
|
const logger = require('../../../../src/logger');
|
||||||
|
|
||||||
|
// Utility to parse query parameters into a Prisma query
|
||||||
|
const parseQueryParams = (query: any) => {
|
||||||
|
return {
|
||||||
|
select: query.select ? JSON.parse(query.select) : undefined,
|
||||||
|
include: query.include ? JSON.parse(query.include) : undefined,
|
||||||
|
where: query.where ? JSON.parse(query.where) : undefined,
|
||||||
|
orderBy: query.orderBy ? JSON.parse(query.orderBy) : undefined,
|
||||||
|
skip: query.skip ? parseInt(query.skip, 10) : undefined,
|
||||||
|
limit: query.limit ? parseInt(query.limit, 10) : undefined,
|
||||||
|
distinct: query.distinct ? query.distinct.split(',') : undefined,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
const prisma: PrismaClient = common.getPrismaClient();
|
||||||
|
const modelArray = (req.query.model || (req.body && req.body.model)) as string[];
|
||||||
|
let queryOptions = {};
|
||||||
|
|
||||||
|
if (req.method === 'POST' && req.headers['content-type']?.includes('application/json')) {
|
||||||
|
// Handle POST request
|
||||||
|
queryOptions = req.body;
|
||||||
|
} else {
|
||||||
|
// Handle GET request
|
||||||
|
queryOptions = parseQueryParams(req.query);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!modelArray || modelArray.length === 0) {
|
||||||
|
throw new Error('Model is required as a part of the URL path.');
|
||||||
|
}
|
||||||
|
const modelName = modelArray[0]; // Get the first part of the model array
|
||||||
|
const result = await prisma[modelName].findMany(queryOptions);
|
||||||
|
res.status(200).json(result);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
}
|
133
pages/cart/reports/coverMe.tsx
Normal file
133
pages/cart/reports/coverMe.tsx
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
//page to show all repots in the database with a link to the report page
|
||||||
|
import axiosInstance from '../../../src/axiosSecure';
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useSession } from "next-auth/react"
|
||||||
|
//const common = require('src/helpers/common');
|
||||||
|
import common from '../../../src/helpers/common';
|
||||||
|
import Layout from "../../../components/layout";
|
||||||
|
import ProtectedRoute from '../../../components/protectedRoute';
|
||||||
|
import { Location, Shift, UserRole, EventLog, EventType } from "@prisma/client";
|
||||||
|
import { set } from 'date-fns';
|
||||||
|
|
||||||
|
|
||||||
|
export default function EventLogList() {
|
||||||
|
const [eventLogs, setEventLog] = useState([]);
|
||||||
|
const [publicShifts, setPublicShifts] = useState([]);
|
||||||
|
const router = useRouter();
|
||||||
|
const { data: session } = useSession();
|
||||||
|
|
||||||
|
const [locations, setLocations] = useState([]);
|
||||||
|
const [showOpenRequests, setShowOpenRequests] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchLocations = async () => {
|
||||||
|
try {
|
||||||
|
console.log("fetching locations");
|
||||||
|
const { data: locData } = await axiosInstance.get("/api/data/locations");
|
||||||
|
setLocations(locData);
|
||||||
|
console.log(locData);
|
||||||
|
axiosInstance.get(`/api/data/eventlogs`)
|
||||||
|
.then((res) => {
|
||||||
|
// let reports = res.data;
|
||||||
|
// reports.forEach((report) => {
|
||||||
|
// report.location = data.find((loc) => loc.id === report.locationId);
|
||||||
|
// });
|
||||||
|
setEventLog(res.data);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
//get shifts where publicGuid is not null
|
||||||
|
const { data: shiftsData } = await axiosInstance.get(`/api/data/prisma/assignment?where={"publicGuid":{"not":"NULL"}}`)
|
||||||
|
setPublicShifts(shiftsData);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!locations.length) {
|
||||||
|
fetchLocations();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<ProtectedRoute allowedRoles={[UserRole.POWERUSER, UserRole.ADMIN, UserRole.USER, UserRole.EXTERNAL]}>
|
||||||
|
|
||||||
|
<div className="h-5/6 grid place-items-start px-4 pt-8">
|
||||||
|
<div className="flex flex-col w-full px-4">
|
||||||
|
<h1 className="text-2xl font-bold text-center">Заявки за заместване</h1>
|
||||||
|
{/* <Link href="/cart/reports/report">
|
||||||
|
<button className="mt-4 bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded">
|
||||||
|
Добави нов отчет
|
||||||
|
</button>
|
||||||
|
</Link> */}
|
||||||
|
<div className="flex gap-2 mb-4">
|
||||||
|
|
||||||
|
<label className={`cursor-pointer px-4 py-2 rounded-full ${!showOpenRequests ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-800'}`}>
|
||||||
|
<input type="radio" name="reportType" value="ServiceReport" onChange={() => setShowOpenRequests(false)} checked={!showOpenRequests} className="sr-only" />
|
||||||
|
Заявки
|
||||||
|
</label>
|
||||||
|
<label className={`cursor-pointer px-4 py-2 rounded-full ${showOpenRequests ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-800'}`}>
|
||||||
|
<input type="radio" name="reportType" value="Experience" onChange={() => setShowOpenRequests(true)} checked={showOpenRequests} className="sr-only" />
|
||||||
|
Отворени заявки
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 w-full overflow-x-auto">
|
||||||
|
<table className="w-full table-auto">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th className="px-4 py-2 text-left">От</th>
|
||||||
|
<th className="px-4 py-2 text-left">Дата</th>
|
||||||
|
<th className="px-4 py-2 text-left">Смяна</th>
|
||||||
|
<th className="px-4 py-2 text-left">Действия</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{!showOpenRequests && (eventLogs.map((event) => (
|
||||||
|
<tr key={event.id}>
|
||||||
|
<td className="border px-2 py-2">{event.publisher.firstName + " " + event.publisher.lastName}</td>
|
||||||
|
<td className="border px-2 py-2">{common.getDateFormated(new Date(event.date))}</td>
|
||||||
|
<td className="border px-2 py-2">{event.shift?.name}</td>
|
||||||
|
<td className="border px-2 py-2">
|
||||||
|
{event.content}
|
||||||
|
</td>
|
||||||
|
<td className="border px-4 py-2">
|
||||||
|
<button
|
||||||
|
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">
|
||||||
|
Изтрий
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
{showOpenRequests && (publicShifts.map((shift) => (
|
||||||
|
<tr key={shift.id}>
|
||||||
|
<td className="border px-2 py-2">{shift.publisher.firstName + " " + shift.publisher.lastName}</td>
|
||||||
|
<td className="border px-2 py-2">{common.getDateFormated(new Date(shift.date))}</td>
|
||||||
|
<td className="border px-2 py-2">{shift.name}</td>
|
||||||
|
<td className="border px-2 py-2">
|
||||||
|
{shift.content}
|
||||||
|
</td>
|
||||||
|
<td className="border px-4 py-2">
|
||||||
|
<button
|
||||||
|
className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">
|
||||||
|
Изтрий
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div >
|
||||||
|
</div >
|
||||||
|
</ProtectedRoute >
|
||||||
|
</Layout >
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user