This commit is contained in:
Dobromir Popov
2024-03-01 14:23:45 +02:00
parent 67e350bdd4
commit a3919f8e84
3 changed files with 115 additions and 17 deletions

View File

@ -96,6 +96,11 @@ const sidemenu = [
text: "Отчети",
url: "/cart/reports/list",
roles: [UserRole.ADMIN, UserRole.POWERUSER],
// }, {
// id: "statistics",
// text: "Статистика",
// url: "/cart/publishers/stats",
// roles: [UserRole.ADMIN, UserRole.POWERUSER],
},
]

View File

@ -0,0 +1,94 @@
import { useState } from 'react';
import Layout from "../../../components/layout";
import ProtectedRoute from '../../../components/protectedRoute';
import { UserRole } from '@prisma/client';
import axiosServer from '../../../src/axiosServer';
import common from '../../../src/helpers/common';
import { filterPublishers, /* other functions */ } from '../../api/index';
function ContactsPage({ publishers }) {
const [searchQuery, setSearchQuery] = useState('');
const filteredPublishers = publishers.filter((publisher) =>
publisher.firstName.toLowerCase().includes(searchQuery.toLowerCase()) ||
publisher.lastName.toLowerCase().includes(searchQuery.toLowerCase()) ||
publisher.email.toLowerCase().includes(searchQuery.toLowerCase()) ||
publisher.phone?.toLowerCase().includes(searchQuery.toLowerCase())
);
return (
<Layout>
<ProtectedRoute allowedRoles={[UserRole.ADMIN, UserRole.POWERUSER, UserRole.USER]}>
<div className="container mx-auto p-4">
<h1 className="text-xl font-semibold mb-4">Контакти</h1>
<input
type="text"
placeholder="Търси по име, имейл или телефон..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="border border-gray-300 rounded-md px-2 py-2 mb-4 w-full text-base md:text-sm"
/>
<div className="overflow-x-auto">
<table className="w-full text-left border-collapse">
<thead>
<tr>
<th className="border-b font-medium p-4 pl-8 pt-0 pb-3">Име</th>
<th className="border-b font-medium p-4 pt-0 pb-3">Имейл</th>
<th className="border-b font-medium p-4 pt-0 pb-3">Телефон</th>
</tr>
</thead>
<tbody>
{filteredPublishers.map((publisher) => (
<tr key={publisher.id}>
<td className="border-b p-4 pl-8">{publisher.firstName} {publisher.lastName}</td>
<td className="border-b p-4">
<a href={`mailto:${publisher.email}`} className="text-blue-500">{publisher.email}</a>
</td>
<td className="border-b p-4">
<div className="flex items-center justify-between">
<span className={common.isValidPhoneNumber(publisher.phone) ? '' : 'text-red-500'}>{publisher.phone}</span>
<div className="flex items-center">
<a href={`tel:${publisher.phone}`} className="inline-block p-2 mr-2">
<i className="fas fa-phone-alt text-blue-500 text-xl" title="Обаждане"></i>
</a>
<a href={`https://wa.me/${publisher.phone}`} className="inline-block p-2 mr-2">
<i className="fab fa-whatsapp text-green-500 text-xl" title="WhatsApp"></i>
</a>
{publisher.phone ? (
<a href={`viber://chat/?number=%2B${publisher.phone.startsWith('+') ? publisher.phone.substring(1) : publisher.phone}`} className="inline-block p-2">
<i className="fab fa-viber text-purple-500 text-xl" title="Viber"></i>
</a>
) : null}
</div>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</ProtectedRoute>
</Layout>
);
}
export default ContactsPage;
export const getServerSideProps = async (context) => {
const dateStr = new Date().toISOString().split('T')[0];
let publishers = await filterPublishers('id,firstName,lastName,isactive,desiredShiftsPerMonth', "", new Date(), true, true);
// const axios = await axiosServer(context);
// const { data: publishers } = await axios.get(`api/?action=filterPublishers&assignments=true&availabilities=true&date=${dateStr}&select=id,firstName,lastName,isactive,desiredShiftsPerMonth`);
// api/index?action=filterPublishers&assignments=true&availabilities=true&date=2024-03-14&select=id%2CfirstName%2ClastName%2Cisactive%2CdesiredShiftsPerMonth
return {
props: {
publishers,
},
};
};

View File

@ -39,8 +39,8 @@ const PORT = process.env.NEXT_PUBLIC_PORT || 3000;
const HOST = process.env.NEXT_PUBLIC_HOST;
const dev = process.env.NODE_ENV !== "production";
const PROTOCOL = process.env.NEXT_PUBLIC_PROTOCOL;
const app = next({ dev });
const handle = app.getRequestHandler();
const nextApp = next({ dev });
const nextHandler = nextApp.getRequestHandler();
console.log("process.env.SSL_ENABLED = ", process.env.SSL_ENABLED);
console.log("process.env.NEXTAUTH_URL = ", process.env.NEXTAUTH_URL);
console.log("process.env.NEXT_PUBLIC_PORT = ", process.env.NEXT_PUBLIC_PORT);
@ -63,7 +63,7 @@ const uploadTmp = multer({ storage: storageMem });
const prisma = common.getPrismaClient();
// handlers
app
nextApp
.prepare()
.then(() => {
const server = express();
@ -518,6 +518,13 @@ app
});
//----------------- log client console messages and their session.user.id and IP----------------
server.post("/log", (req, res) => {
//get ip from request
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
console.log("[client log] " + req.body.message + " user: " + req.body.userId + " IP: " + ip);
res.end("ok");
});
// --------------- EXCEL EXPORT ROUTE ----------------
@ -533,19 +540,19 @@ app
});
server.get("*", (req, res) => {
return handle(req, res);
return nextHandler(req, res);
});
server.post("*", (req, res) => {
return handle(req, res);
return nextHandler(req, res);
});
server.put("*", (req, res) => {
return handle(req, res);
return nextHandler(req, res);
});
server.patch("*", (req, res) => {
return handle(req, res);
return nextHandler(req, res);
});
server.delete("*", (req, res) => {
return handle(req, res);
return nextHandler(req, res);
});
//check if ssl is enabled
@ -652,15 +659,7 @@ async function Stat() {
}
Stat();
exports.baseUrlGlobal = baseUrlGlobal;
exports.default = app;
exports.default = nextApp;