Merge branch 'main' into production
This commit is contained in:
@ -1,124 +1,121 @@
|
||||
import Link from "next/link"
|
||||
import { signIn, signOut, useSession } from "next-auth/react"
|
||||
import styles from "../styles/header.module.css"
|
||||
// import Link from "next/link"
|
||||
// import { signIn, signOut, useSession } from "next-auth/react"
|
||||
// import styles from "../styles/header.module.css"
|
||||
|
||||
// The approach used in this component shows how to build a sign in and sign out
|
||||
// component that works on pages which support both client and server side
|
||||
// rendering, and avoids any flash incorrect content on initial page load.
|
||||
export default function Header() {
|
||||
const { data: session, status } = useSession()
|
||||
const loading = status === "loading"
|
||||
// // The approach used in this component shows how to build a sign in and sign out
|
||||
// // component that works on pages which support both client and server side
|
||||
// // rendering, and avoids any flash incorrect content on initial page load.
|
||||
// export default function Header() {
|
||||
// const { data: session, status } = useSession()
|
||||
// const loading = status === "loading"
|
||||
|
||||
//generate top header with sign in/out button and dropdown menu and user name/surname using tailwindcss
|
||||
// //generate top header with sign in/out button and dropdown menu and user name/surname using tailwindcss
|
||||
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<header className="">
|
||||
<noscript>
|
||||
<style>{`.nojs-show { opacity: 1; top: 0; }`}</style>
|
||||
</noscript>
|
||||
{/* <script src="https://cdn.jsdelivr.net/npm/tw-elements/dist/js/index.min.js"></script> */}
|
||||
<div className={styles.signedInStatus}>
|
||||
<p
|
||||
className={`nojs-show ${
|
||||
!session && loading ? styles.loading : styles.loaded
|
||||
}`}
|
||||
>
|
||||
{!session && (
|
||||
<>
|
||||
<span className={styles.notSignedInText}>
|
||||
You are not signed in
|
||||
</span>
|
||||
<a
|
||||
href={`/api/auth/signin`}
|
||||
className={styles.buttonPrimary}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
signIn()
|
||||
}}
|
||||
>
|
||||
Sign in
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
{session?.user && (
|
||||
<>
|
||||
{session.user.image && (
|
||||
<span
|
||||
style={{ backgroundImage: `url('${session.user.image}')` }}
|
||||
className={styles.avatar}
|
||||
/>
|
||||
)}
|
||||
<span className={styles.signedInText}>
|
||||
<small>Signed in as</small>
|
||||
<br />
|
||||
<strong>{session.user.email ?? session.user.name}</strong>
|
||||
</span>
|
||||
<a
|
||||
href={`/api/auth/signout`}
|
||||
className={styles.button}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
signOut()
|
||||
}}
|
||||
>
|
||||
Sign out
|
||||
</a>
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<nav className="max-w-7xl mx-auto ">
|
||||
<ul className={styles.navItems}>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/">Home</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/client">Client</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/server">Server</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/protected">Protected</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/api-example">API</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/admin">Admin</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/me">Me</Link>
|
||||
</li>
|
||||
<li className={styles.navItem}>
|
||||
CART
|
||||
{/* cart submenus */}
|
||||
<ul className={styles.submenu}>
|
||||
<li className={styles.submenuItem}>
|
||||
<Link href="/cart/locations">Locations</Link>
|
||||
</li>
|
||||
<li className={styles.submenuItem}>
|
||||
<Link href="/cart/publishers">Publishers</Link>
|
||||
</li>
|
||||
<li className={styles.submenuItem}>
|
||||
<Link href="/cart/availabilities">Availabilities</Link>
|
||||
</li>
|
||||
<li className={styles.submenuItem}>
|
||||
<Link href="/cart/cartevents">Cart Event</Link>
|
||||
</li>
|
||||
</ul>
|
||||
// return (
|
||||
// <header className="">
|
||||
// <noscript>
|
||||
// <style>{`.nojs-show { opacity: 1; top: 0; }`}</style>
|
||||
// </noscript>
|
||||
// {/* <script src="https://cdn.jsdelivr.net/npm/tw-elements/dist/js/index.min.js"></script> */}
|
||||
// <div className={styles.signedInStatus}>
|
||||
// <p className={`nojs-show ${!session && loading ? styles.loading : styles.loaded}`}>
|
||||
// {!session && (
|
||||
// <>
|
||||
// <span className={styles.notSignedInText}>
|
||||
// You are not signed in
|
||||
// </span>
|
||||
// <a
|
||||
// href={`/api/auth/signin`}
|
||||
// className={styles.buttonPrimary}
|
||||
// onClick={(e) => {
|
||||
// e.preventDefault()
|
||||
// signIn()
|
||||
// }}
|
||||
// >
|
||||
// Sign in
|
||||
// </a>
|
||||
// </>
|
||||
// )}
|
||||
// {session?.user && (
|
||||
// <>
|
||||
// {session.user.image && (
|
||||
// <span
|
||||
// style={{ backgroundImage: `url('${session.user.image}')` }}
|
||||
// className={styles.avatar}
|
||||
// />
|
||||
// )}
|
||||
// <span className={styles.signedInText}>
|
||||
// <small>Signed in as</small>
|
||||
// <br />
|
||||
// <strong>{session.user.email ?? session.user.name}</strong>
|
||||
// </span>
|
||||
// <a
|
||||
// href={`/api/auth/signout`}
|
||||
// className={styles.button}
|
||||
// onClick={(e) => {
|
||||
// e.preventDefault()
|
||||
// signOut()
|
||||
// }}
|
||||
// >
|
||||
// Sign out
|
||||
// </a>
|
||||
// </>
|
||||
// )}
|
||||
// </p>
|
||||
// </div>
|
||||
// {/* <nav className="max-w-7xl mx-auto ">
|
||||
// <ul className={styles.navItems}>
|
||||
// <li className={styles.navItem}>
|
||||
// <Link href="/">Home</Link>
|
||||
// </li>
|
||||
// <li className={styles.navItem}>
|
||||
// <Link href="/client">Client</Link>
|
||||
// </li>
|
||||
// <li className={styles.navItem}>
|
||||
// <Link href="/server">Server</Link>
|
||||
// </li>
|
||||
// <li className={styles.navItem}>
|
||||
// <Link href="/protected">Protected</Link>
|
||||
// </li>
|
||||
// <li className={styles.navItem}>
|
||||
// <Link href="/api-example">API</Link>
|
||||
// </li>
|
||||
// <li className={styles.navItem}>
|
||||
// <Link href="/admin">Admin</Link>
|
||||
// </li>
|
||||
// <li className={styles.navItem}>
|
||||
// <Link href="/me">Me</Link>
|
||||
// </li>
|
||||
// <li className={styles.navItem}>
|
||||
// CART
|
||||
// {/* cart submenus * / }
|
||||
// <ul className={styles.submenu}>
|
||||
// <li className={styles.submenuItem}>
|
||||
// <Link href="/cart/locations">Locations</Link>
|
||||
// </li>
|
||||
// <li className={styles.submenuItem}>
|
||||
// <Link href="/cart/publishers">Publishers</Link>
|
||||
// </li>
|
||||
// <li className={styles.submenuItem}>
|
||||
// <Link href="/cart/availabilities">Availabilities</Link>
|
||||
// </li>
|
||||
// <li className={styles.submenuItem}>
|
||||
// <Link href="/cart/cartevents">Cart Event</Link>
|
||||
// </li>
|
||||
// </ul>
|
||||
|
||||
</li>
|
||||
{/* end cart submenus */}
|
||||
// </li>
|
||||
// {/* end cart submenus * / }
|
||||
|
||||
<li className={styles.navItem}>
|
||||
<Link href="/cart/calendar">Calendar</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
// <li className={styles.navItem}>
|
||||
// <Link href="/cart/calendar">Calendar</Link>
|
||||
// </li>
|
||||
// </ul >
|
||||
// </nav > */ }
|
||||
|
||||
// </header >
|
||||
// )
|
||||
// }
|
||||
|
@ -1,4 +1,4 @@
|
||||
import Header from "./header"
|
||||
|
||||
import Link from 'next/link'
|
||||
import Footer from "./footer"
|
||||
import Sidebar from "./sidebar"
|
||||
|
@ -16,6 +16,7 @@ import { UserRole } from "@prisma/client";
|
||||
const packageVersion = require('../package.json').version;
|
||||
|
||||
function SidebarMenuItem({ item, session, isSubmenu }) {
|
||||
|
||||
// const tMenu = useTranslations('menu');
|
||||
// const [t, locale] = useState(useTranslations('menu'));
|
||||
// useEffect(() => {
|
||||
|
@ -32,5 +32,13 @@
|
||||
"statistics": "Статистика",
|
||||
"coverMeLogs": "Замествания",
|
||||
"translations": "Преводи"
|
||||
},
|
||||
"content": {
|
||||
"location": {
|
||||
"warehouse": {
|
||||
"description": "- снимки как да се поставят количките\n- снимка с код за катинар\nвсеки може да всима/връща\n- преди да влизаме трябва да почистим краката.\n- зареждаме/почистваме извън\n- влизане/озлизане няма код\n- влизане/излизане има код",
|
||||
"title": "СНЛАД"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -32,5 +32,13 @@
|
||||
"statistics": "View Statistics",
|
||||
"coverMeLogs": "View CoverMe logs",
|
||||
"translations": "Translation"
|
||||
},
|
||||
"content": {
|
||||
"location": {
|
||||
"warehouse": {
|
||||
"description": "- снимки как да се поставят количките\n- снимка с код за катинар\nвсеки може да всима/връща\n- преди да влизаме трябва да почистим краката.\n- зареждаме/почистваме извън\n- влизане/озлизане няма код\n- влизане/излизане има код",
|
||||
"title": "СНЛАД"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -8,10 +8,17 @@
|
||||
"BG": "болгарский",
|
||||
"EN": "английский",
|
||||
"RU": "русский",
|
||||
"login": "вход",
|
||||
"contacts": "Контакти te"
|
||||
"login": "вход"
|
||||
},
|
||||
"menu": {
|
||||
"dashboard": "Начало"
|
||||
},
|
||||
"content": {
|
||||
"location": {
|
||||
"warehouse": {
|
||||
"description": "- снимки как да се поставят количките\n- снимка с код за катинар\nвсеки може да всима/връща\n- преди да влизаме трябва да почистим краката.\n- зареждаме/почистваме извън\n- влизане/озлизане няма код\n- влизане/излизане има код",
|
||||
"title": "СНЛАД"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ import "react-responsive-carousel/lib/styles/carousel.min.css"; // requires a lo
|
||||
import { GetServerSideProps } from 'next';
|
||||
import { Location, UserRole } from "@prisma/client";
|
||||
import axiosServer from '../../../src/axiosServer';
|
||||
import { useTranslations, createTranslator } from 'next-intl';
|
||||
// import { getTranslations } from 'next-intl/server';
|
||||
|
||||
const ViewLocationPage: React.FC<ViewLocationPageProps> = ({ location }) => {
|
||||
const [activeTab, setActiveTab] = useState('mainLocation');
|
||||
@ -12,6 +14,7 @@ const ViewLocationPage: React.FC<ViewLocationPageProps> = ({ location }) => {
|
||||
|
||||
const [images, setImages] = useState([]);
|
||||
const [mainLocationImageCount, setMainLocationImageCount] = useState(0);
|
||||
const t = useTranslations('content');
|
||||
|
||||
useEffect(() => {
|
||||
const mainLocationImages = [location.picture1, location.picture2, location.picture3].filter(Boolean);
|
||||
@ -98,15 +101,44 @@ const ViewLocationPage: React.FC<ViewLocationPageProps> = ({ location }) => {
|
||||
export const getServerSideProps: GetServerSideProps = async (context) => {
|
||||
const axios = await axiosServer(context);
|
||||
|
||||
// Get the locale from context or use default
|
||||
const locale = context.locale || 'en';
|
||||
const messages = (await import(`../../../content/i18n/${locale}.json`)).default;
|
||||
|
||||
const t = createTranslator({ locale, messages });
|
||||
// Function to replace placeholders in HTML content
|
||||
const replacePlaceholders = (content: string) => {
|
||||
if (!content) return '';
|
||||
const placeholderPattern = /{([^}]+)}/g;
|
||||
return content.replace(placeholderPattern, (match, key) => {
|
||||
try {
|
||||
const translation = t('content.' + key);
|
||||
// Check if translation exists and is not empty
|
||||
if (translation && translation !== 'content.' + key) {
|
||||
return translation;
|
||||
}
|
||||
// Return formatted placeholder if translation not found
|
||||
return `[${locale}:${key}]`;
|
||||
} catch (error) {
|
||||
// Return formatted placeholder on error
|
||||
return `[${locale}:${key}]`;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
const { data: location } = await axios.get(
|
||||
`${process.env.NEXT_PUBLIC_PUBLIC_URL}/api/data/locations/${context.params.id}`
|
||||
);
|
||||
location.content = replacePlaceholders(location.content);
|
||||
|
||||
if (location.backupLocationId !== null) {
|
||||
const { data: backupLocation } = await axios.get(
|
||||
process.env.NEXT_PUBLIC_PUBLIC_URL + "/api/data/locations/" + location.backupLocationId
|
||||
);
|
||||
location.backupLocationName = backupLocation.name;
|
||||
location.backupLocationContent = backupLocation ? backupLocation.content : "";
|
||||
location.backupLocationContent = backupLocation ? replacePlaceholders(backupLocation.content) : "";
|
||||
location.backupLocationImages = backupLocation ? [backupLocation.picture1, backupLocation.picture2, backupLocation.picture3].filter(Boolean) : [];
|
||||
}
|
||||
|
||||
|
@ -1,144 +1,206 @@
|
||||
//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 axiosInstance from "../../../src/axiosSecure";
|
||||
import { useSession } from "next-auth/react";
|
||||
import Layout from "../../../components/layout";
|
||||
import ProtectedRoute from '../../../components/protectedRoute';
|
||||
import { Location, Shift, UserRole, EventLog, EventType, EventLogType } from "@prisma/client";
|
||||
import { set } from 'date-fns';
|
||||
import ProtectedRoute from "../../../components/protectedRoute";
|
||||
import { UserRole, EventLogType } from "@prisma/client";
|
||||
|
||||
const timeFilters = [
|
||||
{ label: "1 седмица", value: 7 },
|
||||
{ label: "1 месец", value: 30 },
|
||||
{ label: "3 месеца", value: 90 },
|
||||
{ label: "Всички", value: null },
|
||||
];
|
||||
|
||||
const eventTypes = [
|
||||
{ label: "Заявки", value: EventLogType.AssignmentReplacementRequested },
|
||||
{ label: "Приети замествания", value: EventLogType.AssignmentReplacementAccepted },
|
||||
{ label: "Ръчно въведени замествания", value: EventLogType.AssignmentReplacementManual },
|
||||
];
|
||||
|
||||
export default function EventLogList() {
|
||||
const [eventLogs, setEventLog] = useState([]);
|
||||
const [requestedAssignments, setRequestedAssignments] = useState([]);
|
||||
const router = useRouter();
|
||||
const [showOpenRequests, setShowOpenRequests] = useState(false);
|
||||
const [selectedTimeFilter, setSelectedTimeFilter] = useState(null); // Time filter state
|
||||
const [selectedEventTypes, setSelectedEventTypes] = useState(eventTypes.map((et) => et.value)); // Default: all types
|
||||
const { data: session } = useSession();
|
||||
|
||||
const [locations, setLocations] = useState([]);
|
||||
const [showOpenRequests, setShowOpenRequests] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchLocations = async () => {
|
||||
const fetchEventLogs = async () => {
|
||||
try {
|
||||
const { data: eventLogsDataold } = await axiosInstance.get(`/api/data/prisma/eventLog?where={"type":"${EventLogType.AssignmentReplacementAccepted}"}&include={"publisher":{"select":{"firstName":true,"lastName":true}},"shift":{"include":{"assignments":{"include":{"publisher":{"select":{"firstName":true,"lastName":true}}}}}}}`);
|
||||
const where = encodeURIComponent(
|
||||
JSON.stringify({
|
||||
OR: selectedEventTypes.map((type) => ({ type })),
|
||||
})
|
||||
);
|
||||
|
||||
// const where = encodeURIComponent(`{OR: [{type: "${EventLogType.AssignmentReplacementAccepted}"}, {type: "${EventLogType.AssignmentReplacementManual}"}]}`);
|
||||
const where = encodeURIComponent(JSON.stringify({
|
||||
OR: [
|
||||
{ type: EventLogType.AssignmentReplacementAccepted },
|
||||
{ type: EventLogType.AssignmentReplacementManual }
|
||||
]
|
||||
}));
|
||||
|
||||
const { data: eventLogsData } = await axiosInstance.get(`/api/data/prisma/eventLog?where=${where}&include={"publisher":{"select":{"firstName":true,"lastName":true}},"shift":{"include":{"assignments":{"include":{"publisher":{"select":{"firstName":true,"lastName":true}}}}}}}`);
|
||||
const { data: eventLogsData } = await axiosInstance.get(
|
||||
`/api/data/prisma/eventLog?where=${where}&include={"publisher":{"select":{"firstName":true,"lastName":true}},"shift":{"include":{"assignments":{"include":{"publisher":{"select":{"firstName":true,"lastName":true}}}}}}}`
|
||||
);
|
||||
|
||||
setEventLog(eventLogsData);
|
||||
|
||||
const { data: shiftsData } = await axiosInstance.get(`/api/data/prisma/assignment?where={"publicGuid":{"not":"null"}}&include={"shift":{"include":{"assignments":{"include":{"publisher":{"select":{"firstName":true,"lastName":true}}}}}},"publisher":{"select":{"firstName":true,"lastName":true}}}`);
|
||||
const { data: shiftsData } = await axiosInstance.get(
|
||||
`/api/data/prisma/assignment?where={"publicGuid":{"not":"null"}}&include={"shift":{"include":{"assignments":{"include":{"publisher":{"select":{"firstName":true,"lastName":true}}}}}},"publisher":{"select":{"firstName":true,"lastName":true}}}`
|
||||
);
|
||||
setRequestedAssignments(shiftsData);
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
if (!locations.length) {
|
||||
fetchLocations();
|
||||
}
|
||||
}, []);
|
||||
|
||||
fetchEventLogs();
|
||||
}, [selectedEventTypes]);
|
||||
|
||||
// Filter events based on the selected time range
|
||||
const filteredEventLogs = eventLogs.filter((event) => {
|
||||
if (!selectedTimeFilter) return true;
|
||||
const eventDate = new Date(event.date);
|
||||
const cutoffDate = new Date();
|
||||
cutoffDate.setDate(cutoffDate.getDate() - selectedTimeFilter);
|
||||
return eventDate >= cutoffDate;
|
||||
});
|
||||
|
||||
// Toggle event type selection
|
||||
const toggleEventType = (eventType) => {
|
||||
setSelectedEventTypes((prev) =>
|
||||
prev.includes(eventType)
|
||||
? prev.filter((type) => type !== eventType)
|
||||
: [...prev, eventType]
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<ProtectedRoute allowedRoles={[UserRole.POWERUSER, UserRole.ADMIN]}>
|
||||
|
||||
<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" />
|
||||
Приети заявки
|
||||
<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
|
||||
className={`cursor-pointer px-4 py-2 rounded-full ${showOpenRequests ? "bg-yellow-500 text-white" : "bg-yellow-100 text-gray-800"
|
||||
}`}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
name="reportType"
|
||||
value="Experience"
|
||||
onChange={() => setShowOpenRequests(true)}
|
||||
checked={showOpenRequests}
|
||||
className="sr-only"
|
||||
/>
|
||||
Отворени заявки (Без отговор/Още се търси)
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{/* Event Type Filter Pills */}
|
||||
<div className="flex gap-2 mb-4">
|
||||
{eventTypes.map((type) => (
|
||||
<button
|
||||
key={type.value}
|
||||
onClick={() => toggleEventType(type.value)}
|
||||
className={`px-4 py-2 rounded-full ${selectedEventTypes.includes(type.value)
|
||||
? "bg-blue-500 text-white"
|
||||
: "bg-gray-200 text-gray-800"
|
||||
}`}
|
||||
>
|
||||
{type.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
{/* Time Filter Pills */}
|
||||
<div className="flex gap-2 mb-4">
|
||||
{timeFilters.map((filter) => (
|
||||
<button
|
||||
key={filter.value}
|
||||
onClick={() => setSelectedTimeFilter(filter.value)}
|
||||
className={`px-4 py-2 rounded-full ${selectedTimeFilter === filter.value
|
||||
? "bg-blue-500 text-white"
|
||||
: "bg-gray-200 text-gray-800"
|
||||
}`}
|
||||
>
|
||||
{filter.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-4 w-full overflow-x-auto">
|
||||
<table className="w-full table-auto">
|
||||
<thead>
|
||||
<table className="w-full table-auto border-collapse">
|
||||
<thead className="bg-gray-100">
|
||||
<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>
|
||||
<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 sticky top-0 z-10 bg-gray-100 border">На</th>
|
||||
<th className="px-4 py-2 text-left sticky top-0 z-10 bg-gray-100 border">От</th>
|
||||
<th className="px-4 py-2 text-left sticky top-0 z-10 bg-gray-100 border">Дата</th>
|
||||
<th className="px-4 py-2 text-left sticky top-0 z-10 bg-gray-100 border">Смяна</th>
|
||||
<th className="px-4 py-2 text-left sticky top-0 z-10 bg-gray-100 border">Събитие</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{!showOpenRequests && (eventLogs.map((event) => (
|
||||
<tr key={event.id}>
|
||||
<td className="border px-2 py-2">{new Date(event.date).toLocaleString('bg')}</td>
|
||||
<td className="border px-2 py-2">{event.publisher.firstName + " " + event.publisher.lastName}</td>
|
||||
<td className="border px-2 py-2">{new Date(event.shift?.startTime).toLocaleString('bg')}</td>
|
||||
<td className="border px-2 py-2">
|
||||
{event.shift?.assignments.map((ass) => (
|
||||
<div key={ass.id}>{ass.publisher.firstName + " " + ass.publisher.lastName}</div>
|
||||
))}
|
||||
</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 && (requestedAssignments.map((assignment) => (
|
||||
<tr key={assignment.id}>
|
||||
<td className="border px-2 py-2">{new Date(assignment.date).toLocaleString('bg')}</td>
|
||||
<td className="border px-2 py-2">{assignment.publisher.firstName + " " + assignment.publisher.lastName}</td>
|
||||
<td className="border px-2 py-2">{new Date(assignment.shift.startTime).toLocaleString('bg')}</td>
|
||||
<td className="border px-2 py-2">
|
||||
{assignment.shift.assignments.map((ass) => (
|
||||
<div key={ass.id}>{ass.publisher.firstName + " " + ass.publisher.lastName}</div>
|
||||
))}
|
||||
</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 &&
|
||||
filteredEventLogs.map((event) => (
|
||||
<tr key={event.id}>
|
||||
<td className="border px-2 py-2">{new Date(event.date).toLocaleString("bg")}</td>
|
||||
<td className="border px-2 py-2">
|
||||
{event.publisher?.firstName && event.publisher?.lastName
|
||||
? `${event.publisher.firstName} ${event.publisher.lastName}`
|
||||
: "???"}
|
||||
</td>
|
||||
<td className="border px-2 py-2">{new Date(event.shift?.startTime).toLocaleString("bg")}</td>
|
||||
<td className="border px-2 py-2">
|
||||
{event.shift?.assignments.map((ass) => (
|
||||
<div key={ass.id}>
|
||||
{ass.publisher.firstName + " " + ass.publisher.lastName}
|
||||
</div>
|
||||
))}
|
||||
</td>
|
||||
<td className="border px-2 py-2">{event.content}</td>
|
||||
</tr>
|
||||
))}
|
||||
|
||||
{showOpenRequests &&
|
||||
requestedAssignments.map((assignment) => (
|
||||
<tr key={assignment.id}>
|
||||
<td className="border px-2 py-2">
|
||||
{new Date(assignment.date).toLocaleString("bg")}
|
||||
</td>
|
||||
<td className="border px-2 py-2">
|
||||
{assignment.publisher.firstName + " " + assignment.publisher.lastName}
|
||||
</td>
|
||||
<td className="border px-2 py-2">
|
||||
{new Date(assignment.shift.startTime).toLocaleString("bg")}
|
||||
</td>
|
||||
<td className="border px-2 py-2">
|
||||
{assignment.shift.assignments.map((ass) => (
|
||||
<div key={ass.id}>
|
||||
{ass.publisher.firstName + " " + ass.publisher.lastName}
|
||||
</div>
|
||||
))}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div >
|
||||
</div >
|
||||
</ProtectedRoute >
|
||||
</Layout >
|
||||
</div>
|
||||
</div>
|
||||
</ProtectedRoute>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,7 +2,9 @@
|
||||
box-sizing: border-box;
|
||||
} */
|
||||
body {
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
"Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
padding: 0 1rem 1rem 1rem;
|
||||
max-width: 768px;
|
||||
margin: 0 auto;
|
||||
@ -52,7 +54,7 @@ iframe {
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
|
||||
|
||||
z-index: 1051; /* High z-index */
|
||||
}
|
||||
|
||||
@ -119,7 +121,6 @@ iframe {
|
||||
/* Add any additional styles you need */
|
||||
}
|
||||
|
||||
|
||||
.disabled {
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
@ -162,11 +163,11 @@ iframe {
|
||||
overflow-y: auto; /* Vertical scroll only when needed */
|
||||
}
|
||||
|
||||
/* CALENDAR */
|
||||
.icon-large {
|
||||
/* CALENDAR */
|
||||
.icon-large {
|
||||
font-size: 16px; /* Example size, adjust as needed */
|
||||
}
|
||||
.rbc-calendar {
|
||||
.rbc-calendar {
|
||||
font-family: sans-serif;
|
||||
font-size: 18px;
|
||||
}
|
||||
@ -179,13 +180,12 @@ iframe {
|
||||
margin: 0 10px; /* Adding margin for spacing */
|
||||
border-radius: 4px; /* Optional: rounding the corners for a softer look */
|
||||
background-color: #ecf0f1; /* Light background color to make it stand out */
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* Optional: adding a subtle shadow for depth */
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Optional: adding a subtle shadow for depth */
|
||||
display: inline-block; /* To apply padding and background color correctly */
|
||||
/* Adding glow to the text */
|
||||
/* Adding glow to the text */
|
||||
/* text-shadow: 0 0 2px rgba(252, 252, 252, 0.8); Adjust color and glow size as needed */
|
||||
}
|
||||
|
||||
|
||||
.mobile-calendar .rbc-btn-group button {
|
||||
padding: 4px 6px; /* Smaller buttons */
|
||||
font-size: 16px; /* Smaller button text */
|
||||
@ -232,8 +232,7 @@ iframe {
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
} */
|
||||
.rbc-calendar .rbc-month-view .rbc-event
|
||||
{
|
||||
.rbc-calendar .rbc-month-view .rbc-event {
|
||||
padding: 2;
|
||||
margin: 2;
|
||||
background-color: transparent;
|
||||
@ -246,14 +245,10 @@ iframe {
|
||||
/* min-height:150px !important; * /
|
||||
} */
|
||||
|
||||
|
||||
|
||||
.react-responsive-carousel .control-arrow {
|
||||
width: 25%;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Custom CSS for responsive table */
|
||||
@media (max-width: 768px) {
|
||||
/* Hide table headers on small screens */
|
||||
@ -291,4 +286,3 @@ iframe {
|
||||
align-items: center;
|
||||
justify-content: center; /* Optional: center buttons in the group */
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user