Files
mwitnessing/pages/dash.tsx
2024-06-17 22:17:51 +03:00

348 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useSession } from "next-auth/react"
import { useRouter } from 'next/router';
import React, { useState, useEffect } from 'react';
import Layout from "../components/layout"
import { toast } from 'react-toastify';
import AvCalendar from '../components/calendar/avcalendar';
import { getSession } from "next-auth/react";
import common from '../src/helpers/common';
import { Availability, UserRole } from "@prisma/client";
import ProtectedRoute, { serverSideAuth } from "../components/protectedRoute";
import axiosInstance from '../src/axiosSecure';
// const dataHelper = require('../../src/helpers/data');
import dataHelper from '../src/helpers/data';
import { authOptions } from './api/auth/[...nextauth]'
import { getServerSession } from "next-auth/next"
import PublisherSearchBox from '../components/publisher/PublisherSearchBox';
import PublisherInlineForm from '../components/publisher/PublisherInlineForm';
import CartEventForm from "components/cartevent/CartEventForm";
interface IProps {
initialItems: Availability[];
initialUserId: string;
cartEvents: any;
lastPublishedDate: Date;
messages: any;
}
export default function DashboardPage({ initialItems, initialUserId, cartEvents, lastPublishedDate, messages }: IProps) {
const router = useRouter();
const { newLogin } = router.query;
const { data: session } = useSession();
const [userName, setUserName] = useState('');
const [userId, setUserId] = useState(initialUserId);
const [events, setEvents] = useState(initialItems?.map(item => ({
...item,
title: item.name,
date: new Date(item.startTime),
startTime: new Date(item.startTime),
endTime: new Date(item.endTime),
publisherId: item.publisherId,
})));
useEffect(() => {
if (session && userName === '' && session.user.name) {
setUserName(session.user.name);
setUserId(session.user.id);
//handleUserSelection({ id: session.user.id, firstName: session.user.name, lastName: '' });
}
}, [session]);
// MESSAGES
//const [notificationsVisible, setNotificationsVisible] = useState(false);
// useEffect(() => {
// //if (newLogin === 'true')
// {
// // alert("Мили братя, искаме само да ви напомним да ни изпратите вашите предпочитания за юни до 25-то число като използвате меню 'Възможности'. Ако имате проблем, моля пишете ни на 'specialnosvidetelstvanesofia@gmail.com'");
// const currentPath = router.pathname;
// router.replace(currentPath, undefined, { shallow: true }); // Removes the query without affecting the history
// }
// }, []);// show the message every time we load the page
useEffect(() => {
if (messages && messages.length > 0) {
console.log("user has ", messages.length, " messages.");
showMessageToasts(messages);
}
}, []);
const showMessageToasts = (messages, handleMessageOptionAnswer) => {
const handleOptionClick = async (messageId, option, toastId) => {
try {
await axiosInstance.put(`/api/data/messages/${messageId}`, { answer: option });
toast.dismiss(toastId);
} catch (error) {
console.error("Error updating message:", error);
toast.error("Error updating message. Please try again.");
}
};
const handleClose = (toastId) => {
toast.dismiss(toastId);
};
messages.forEach((message) => {
const toastId = `message-${message.id}`;
const content = (
<div>
<div>{message.content.message}</div>
<div>
{message.content.options?.map((option, index) => (
<button
key={index}
onClick={() => handleOptionClick(message.id, option, toastId)}
className="btn bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded m-1"
>
{option}
</button>
))}
</div>
</div>
);
toast(content, {
toastId,
autoClose: false, // Keep the toast open until manually closed
closeButton: false,
onClose: () => handleClose(toastId),
});
});
};
// const showMessageToastNewModal = (messages, handleMessageOptionAnswer) => {
// let currentMessageIndex = 0;
// const showModal = () => {
// if (currentMessageIndex >= messages.length) {
// return; // All messages have been shown
// }
// const message = messages[currentMessageIndex];
// const content = (
// <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
// <div className="bg-white rounded shadow-lg p-4 max-w-lg w-full">
// <div className="text-right">
// <button
// className="text-gray-500 hover:text-gray-700"
// onClick={handleClose}
// >
// &times;
// </button>
// </div>
// <div className="mb-4">{message.content.message}</div>
// <div>
// {message.content.options?.map((option, index) => (
// <button
// key={index}
// onClick={() => handleOptionClick(message.id, option)}
// className="btn bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-2 rounded m-1"
// >
// {option}
// </button>
// ))}
// </div>
// </div>
// </div>
// );
// toast(content, {
// autoClose: false, // Keep the toast open until manually closed
// closeButton: false,
// onClose: handleClose,
// //className: 'custom-toast', // Optional custom class for additional styling
// });
// };
// const handleOptionClick = async (messageId, option) => {
// try {
// await axiosInstance.put(`/api/data/messages/${messageId}`, { answer: option });
// toast.dismiss();
// currentMessageIndex++;
// showModal();
// } catch (error) {
// console.error("Error updating message:", error);
// toast.error("Error updating message. Please try again.");
// }
// };
// const handleClose = () => {
// toast.dismiss();
// };
// showModal();
// };
// FOR ADMINS ONLY
const handleUserSelection = async (publisher) => {
if (!publisher || publisher.id === undefined) return;
console.log("selecting publisher", publisher.id);
setUserName(publisher.firstName + " " + publisher.lastName);
setUserId(publisher.id);
try {
let events = await axiosInstance.get(`/api/?action=getCalendarEvents&publisherId=${publisher.id}`);
setEvents(events.data);
} catch (error) {
console.error("Error fetching publisher info:", error);
// Handle the error appropriately
}
};
// EXAMPLE USAGE OF ProtectedRoute
ProtectedRoute.IsInRole(UserRole.ADMIN).then(isAdmin => {
if (isAdmin) {
console.log("User is an admin.");
} else {
console.log("User is not an admin.");
}
});
return (
<Layout>
<ProtectedRoute allowedRoles={[UserRole.ADMIN, UserRole.POWERUSER, UserRole.USER, UserRole.EXTERNAL]} deniedMessage="">
<h1 className="pt-2 pb-1 text-xl font-bold text-center">Графика на {userName}</h1>
<ProtectedRoute allowedRoles={[UserRole.ADMIN]} deniedMessage="">
<PublisherSearchBox selectedId={userId} infoText="" onChange={handleUserSelection} />
</ProtectedRoute>
<div className="flex flex-row md:flex-row mt-4 xs:mt-1 space-y-4 md:space-y-0 md:space-x-4 h-[calc(100vh-10rem)]">
<div className="flex-1">
<div className="text-center font-bold pb-3 xs:pb-1">
<PublisherInlineForm publisherId={userId} />
</div>
<AvCalendar publisherId={userId} events={events} selectedDate={new Date()} cartEvents={cartEvents} lastPublishedDate={lastPublishedDate} />
</div>
</div>
</ProtectedRoute>
</Layout>
);
}
export const getServerSideProps = async (context) => {
const auth = await serverSideAuth({
req: context.req,
allowedRoles: [/* ...allowed roles... */]
});
// const session = await getSession(context);
const sessionServer = await getServerSession(context.req, context.res, authOptions)
if (!sessionServer) {
return {
redirect: {
destination: '/auth/signin',
permanent: false,
},
};
}
const role = sessionServer?.user.role;
console.log("server role: " + role);
const userId = sessionServer?.user.id;
var isAdmin = sessionServer?.user.role == UserRole.ADMIN;//role.localeCompare(UserRole.ADMIN) === 0;
var items = await dataHelper.getCalendarEvents(userId, true, true, isAdmin);
// common.convertDatesToISOStrings(items);
//serializable dates
items = items.map(item => {
const updatedItem = {
...item,
startTime: item.startTime.toISOString(),
endTime: item.endTime.toISOString(),
date: item.date.toISOString(),
name: common.getTimeFormatted(item.startTime) + "-" + common.getTimeFormatted(item.endTime)
};
if (updatedItem.shift) {
updatedItem.shift = {
...updatedItem.shift,
startTime: updatedItem.shift.startTime.toISOString(),
endTime: updatedItem.shift.endTime.toISOString()
};
updatedItem.isPublished = updatedItem.shift.isPublished;
}
return updatedItem;
});
// log first availability startTime to verify timezone and UTC conversion
const prisma = common.getPrismaClient();
let cartEvents = await prisma.cartEvent.findMany({
where: {
isActive: true,
},
select: {
id: true,
startTime: true,
endTime: true,
dayofweek: true,
shiftDuration: true,
}
});
cartEvents = common.convertDatesToISOStrings(cartEvents);
let lastPublishedDate = (await prisma.shift.findFirst({
where: {
isPublished: true,
},
select: {
endTime: true,
},
orderBy: {
endTime: 'desc'
}
}))?.endTime || new Date();
let blockedDate = await prisma.settings.findUnique({
where: {
key: "AvailabilityBlockDate"
}
});
if (blockedDate) {
blockedDate.value = new Date(blockedDate.value);
lastPublishedDate = lastPublishedDate > blockedDate.value ? lastPublishedDate : blockedDate.value;
}
let messages = await prisma.message.findMany({
where: {
publisherId: userId,
isPublic: false,
answer: null,
},
include: {
Survey: true,
}
});
messages = messages.filter((message) => {
return (!message.Survey.publicFrom || message.Survey.publicFrom >= common.getStartOfDay(new Date()))
&& (!message.Survey.publicUntil || message.Survey.publicUntil <= common.getEndOfDay(new Date()))
});
messages = common.convertDatesToISOStrings(messages);
messages = messages.map(message => {
if (message.content) {
message.content = JSON.parse(message.content);
message.content.options = message.content.options?.split(",");
}
return message;
});
return {
props: {
initialItems: items,
userId: sessionServer?.user.id,
cartEvents: cartEvents,
lastPublishedDate: lastPublishedDate.toISOString(),
messages: messages
},
};
}