Merge branch 'main' into production
This commit is contained in:
@ -11,5 +11,5 @@ TELEGRAM_BOT=true
|
|||||||
SSL_KEY=./certificates/localhost-key.pem
|
SSL_KEY=./certificates/localhost-key.pem
|
||||||
SSL_CERT=./certificates/localhost.pem
|
SSL_CERT=./certificates/localhost.pem
|
||||||
|
|
||||||
# DATABASE_URL=mysql://root:Zelen0ku4e@192.168.0.10:3306/cart_dev
|
DATABASE_URL=mysql://root:Zelen0ku4e@192.168.0.10:3306/cart_dev
|
||||||
DATABASE_URL=mysql://cart:cartpw@localhost:3306/cart
|
# DATABASE_URL=mysql://cart:cartpw@localhost:3306/cart
|
||||||
|
@ -109,7 +109,7 @@ next start
|
|||||||
export OPENAI_API_KEY=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 # personal
|
export OPENAI_API_KEY=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 # personal
|
||||||
export OPENAI_API_KEY=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 # dev-bro
|
export OPENAI_API_KEY=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 # dev-bro
|
||||||
|
|
||||||
# -------------update PRISMA schema/sync database ------------------------ #
|
# ----------------------------------------------update PRISMA schema/sync database ----------------------------------------------- #
|
||||||
# prisma migrate dev --create-only
|
# prisma migrate dev --create-only
|
||||||
npx prisma generate
|
npx prisma generate
|
||||||
npx prisma migrate dev --name fix_nextauth_schema --create-only
|
npx prisma migrate dev --name fix_nextauth_schema --create-only
|
||||||
|
@ -56,30 +56,27 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Define the minimum and maximum times
|
// Define the minimum and maximum times
|
||||||
const minTime = new Date();
|
const minTime = new Date();
|
||||||
minTime.setHours(8, 0, 0, 0); // 8:00 AM
|
minTime.setHours(8, 0, 0, 0); // 8:00 AM
|
||||||
const maxTime = new Date();
|
const maxTime = new Date();
|
||||||
maxTime.setHours(20, 0, 0, 0); // 8:00 PM
|
maxTime.setHours(20, 0, 0, 0); // 8:00 PM
|
||||||
|
|
||||||
|
const fetchItemFromDB = async () => {
|
||||||
|
const id = parseInt(router.query.id);
|
||||||
|
if (existingItems.length == 0 && id) {
|
||||||
|
try {
|
||||||
|
const response = await axiosInstance.get(`/api/data/availabilities/${id}`);
|
||||||
|
setAvailabilities([response.data]);
|
||||||
|
setEditMode(true);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Error fetching availability data.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchItemFromDB = async () => {
|
|
||||||
const id = parseInt(router.query.id);
|
|
||||||
if (existingItems.length == 0 && id) {
|
|
||||||
try {
|
|
||||||
const response = await axiosInstance.get(`/api/data/availabilities/${id}`);
|
|
||||||
setAvailabilities([response.data]);
|
|
||||||
setEditMode(true);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
toast.error("Error fetching availability data.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchItemFromDB();
|
fetchItemFromDB();
|
||||||
}, [router.query.id]);
|
}, [router.query.id]);
|
||||||
|
|
||||||
@ -193,6 +190,7 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
repeatWeekly: doRepeat,
|
repeatWeekly: doRepeat,
|
||||||
dayOfMonth: doRepeat ? null : startTime.getDate(),
|
dayOfMonth: doRepeat ? null : startTime.getDate(),
|
||||||
endDate: doRepeat ? repeatUntil : null,
|
endDate: doRepeat ? repeatUntil : null,
|
||||||
|
dateOfEntry: new Date(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,13 +205,10 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
availability.repeatWeekly = doRepeat;
|
availability.repeatWeekly = doRepeat;
|
||||||
availability.dayOfMonth = doRepeat ? null : availability.startTime.getDate();
|
availability.dayOfMonth = doRepeat ? null : availability.startTime.getDate();
|
||||||
availability.endDate = doRepeat ? repeatUntil : null;
|
availability.endDate = doRepeat ? repeatUntil : null;
|
||||||
|
availability.dateOfEntry = new Date();
|
||||||
return availability;
|
return availability;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleDelete = async (e) => {
|
const handleDelete = async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
try {
|
try {
|
||||||
@ -231,9 +226,10 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
|||||||
handleCompletion({ deleted: true });
|
handleCompletion({ deleted: true });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert("Нещо се обърка при изтриването. Моля, опитайте отново или се свържете с нас");
|
//alert("Нещо се обърка при изтриването. Моля, опитайте отново или се свържете с нас");
|
||||||
console.log(JSON.stringify(error));
|
console.log(JSON.stringify(error));
|
||||||
toast.error(error.response?.data?.message || "An error occurred");
|
toast.error(error.response?.data?.message || "An error occurred");
|
||||||
|
fetchItemFromDB();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
@ -6,28 +6,64 @@ import axiosServer from '../../../src/axiosServer';
|
|||||||
import common from '../../../src/helpers/common';
|
import common from '../../../src/helpers/common';
|
||||||
import ShiftsList from '../../../components/publisher/ShiftsList';
|
import ShiftsList from '../../../components/publisher/ShiftsList';
|
||||||
|
|
||||||
|
import { monthNamesBG, GetTimeFormat, GetDateFormat } from "../../../src/helpers/const"
|
||||||
import { useSession, getSession } from 'next-auth/react';
|
import { useSession, getSession } from 'next-auth/react';
|
||||||
|
|
||||||
export default function MySchedulePage({ assignments }) {
|
export default function MySchedulePage({ assignments }) {
|
||||||
|
|
||||||
const { data: session, status } = useSession();
|
const { data: session, status } = useSession();
|
||||||
if (status === "loading") {
|
if (status === "loading") {
|
||||||
return <div>Loading...</div>;
|
return <div className="flex justify-center items-center h-screen">Loading...</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<ProtectedRoute allowedRoles={[UserRole.ADMIN, UserRole.POWERUSER, UserRole.USER]}>
|
<ProtectedRoute allowedRoles={[UserRole.ADMIN, UserRole.POWERUSER, UserRole.USER]}>
|
||||||
<div className="container mx-auto p-4">
|
<div className="container mx-auto p-4">
|
||||||
<h1 className="text-xl font-semibold mb-4">Моите смени</h1>
|
<h1 className="text-2xl md:text-3xl font-bold text-center my-4">Моите смени</h1>
|
||||||
<ShiftsList assignments={assignments} selectedtab={common.getCurrentYearMonth()} />
|
<div className="space-y-4">
|
||||||
|
{assignments && assignments.map((assignment) => (
|
||||||
|
<div key={assignment.dateStr} className="bg-white shadow overflow-hidden rounded-lg">
|
||||||
|
<div className="px-4 py-5 sm:px-6">
|
||||||
|
<h3 className="text-lg leading-6 font-medium text-gray-900">{assignment.dateStr}</h3>
|
||||||
|
</div>
|
||||||
|
<div className="border-t border-gray-200">
|
||||||
|
<dl>
|
||||||
|
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||||
|
<dt className="text-sm font-medium text-gray-500">Час</dt>
|
||||||
|
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
|
{GetTimeFormat(assignment.shift.startTime)} - {GetTimeFormat(assignment.shift.endTime)}
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||||
|
<dt className="text-sm font-medium text-gray-500">Действия</dt>
|
||||||
|
<dd className="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
|
<button
|
||||||
|
className="mr-2 mb-2 inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md shadow-sm text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500"
|
||||||
|
onClick={() => AddToGoogleCalendar(assignment.id)}
|
||||||
|
>
|
||||||
|
Добави в календар
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
||||||
|
onClick={() => searchReplacement(assignment.id)}
|
||||||
|
>
|
||||||
|
Търси заместник
|
||||||
|
</button>
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get future assignmenrs for the current user (session.user.id)
|
//get future assignments for the current user (session.user.id)
|
||||||
|
|
||||||
export const getServerSideProps = async (context) => {
|
export const getServerSideProps = async (context) => {
|
||||||
const session = await getSession(context);
|
const session = await getSession(context);
|
||||||
@ -72,6 +108,7 @@ export const getServerSideProps = async (context) => {
|
|||||||
if (assignment.shift && assignment.shift.startTime) {
|
if (assignment.shift && assignment.shift.startTime) {
|
||||||
return {
|
return {
|
||||||
...assignment,
|
...assignment,
|
||||||
|
dateStr: assignment.shift.startTime.toLocaleDateString("bg-BG", { day: "numeric", month: "long" }),
|
||||||
shift: {
|
shift: {
|
||||||
...assignment.shift,
|
...assignment.shift,
|
||||||
startTime: assignment.shift.startTime.toISOString(),
|
startTime: assignment.shift.startTime.toISOString(),
|
||||||
@ -82,26 +119,10 @@ export const getServerSideProps = async (context) => {
|
|||||||
return assignment;
|
return assignment;
|
||||||
});
|
});
|
||||||
|
|
||||||
const singleKey = "all";
|
|
||||||
const assignmentsStructure = {
|
|
||||||
assignments: {
|
|
||||||
items: {
|
|
||||||
[singleKey]: [],
|
|
||||||
},
|
|
||||||
keys: [singleKey],
|
|
||||||
months: {
|
|
||||||
[singleKey]: "Всички смени",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
selectedtab: singleKey,
|
|
||||||
};
|
|
||||||
|
|
||||||
transformedAssignments.forEach(assignment => {
|
|
||||||
assignmentsStructure.assignments.items[singleKey].push(assignment);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: assignmentsStructure
|
props: { assignments: transformedAssignments }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `Availability` ADD COLUMN `dateOfEntry` DATETIME(3) NULL;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `Message` (
|
||||||
|
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||||
|
`publisherId` VARCHAR(191) NOT NULL,
|
||||||
|
`date` DATETIME(3) NOT NULL,
|
||||||
|
`content` VARCHAR(191) NOT NULL,
|
||||||
|
`isRead` BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
`isPublic` BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
`type` ENUM('Email', 'SMS', 'Push', 'InApp') NOT NULL DEFAULT 'Email',
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `Message` ADD CONSTRAINT `Message_publisherId_fkey` FOREIGN KEY (`publisherId`) REFERENCES `Publisher`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
|
@ -133,7 +133,7 @@ model Availability {
|
|||||||
repeatWeekly Boolean? // New field to indicate weekly repetition // until now dayofweek was used for repetition when dayOfMonth is null
|
repeatWeekly Boolean? // New field to indicate weekly repetition // until now dayofweek was used for repetition when dayOfMonth is null
|
||||||
repeatFrequency Int? // New field to indicate repetition frequency
|
repeatFrequency Int? // New field to indicate repetition frequency
|
||||||
endDate DateTime? // New field for the end date of repetition
|
endDate DateTime? // New field for the end date of repetition
|
||||||
//dateOfEntry DateTime? //NEW v1.0.1 trade storage for intuintivity
|
dateOfEntry DateTime? //NEW v1.0.1 trade storage for intuintivity
|
||||||
}
|
}
|
||||||
|
|
||||||
model CartEvent {
|
model CartEvent {
|
||||||
|
Reference in New Issue
Block a user