Merge branch 'main' into production
This commit is contained in:
@ -11,5 +11,5 @@ TELEGRAM_BOT=true
|
||||
SSL_KEY=./certificates/localhost-key.pem
|
||||
SSL_CERT=./certificates/localhost.pem
|
||||
|
||||
# DATABASE_URL=mysql://root:Zelen0ku4e@192.168.0.10:3306/cart_dev
|
||||
DATABASE_URL=mysql://cart:cartpw@localhost:3306/cart
|
||||
DATABASE_URL=mysql://root:Zelen0ku4e@192.168.0.10:3306/cart_dev
|
||||
# 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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 # dev-bro
|
||||
|
||||
# -------------update PRISMA schema/sync database ------------------------ #
|
||||
# ----------------------------------------------update PRISMA schema/sync database ----------------------------------------------- #
|
||||
# prisma migrate dev --create-only
|
||||
npx prisma generate
|
||||
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
|
||||
const minTime = new Date();
|
||||
minTime.setHours(8, 0, 0, 0); // 8:00 AM
|
||||
const maxTime = new Date();
|
||||
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(() => {
|
||||
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();
|
||||
}, [router.query.id]);
|
||||
|
||||
@ -193,6 +190,7 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
||||
repeatWeekly: doRepeat,
|
||||
dayOfMonth: doRepeat ? null : startTime.getDate(),
|
||||
endDate: doRepeat ? repeatUntil : null,
|
||||
dateOfEntry: new Date(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -207,13 +205,10 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
||||
availability.repeatWeekly = doRepeat;
|
||||
availability.dayOfMonth = doRepeat ? null : availability.startTime.getDate();
|
||||
availability.endDate = doRepeat ? repeatUntil : null;
|
||||
availability.dateOfEntry = new Date();
|
||||
return availability;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const handleDelete = async (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
@ -231,9 +226,10 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o
|
||||
handleCompletion({ deleted: true });
|
||||
}
|
||||
} catch (error) {
|
||||
alert("Нещо се обърка при изтриването. Моля, опитайте отново или се свържете с нас");
|
||||
//alert("Нещо се обърка при изтриването. Моля, опитайте отново или се свържете с нас");
|
||||
console.log(JSON.stringify(error));
|
||||
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 { useRouter } from "next/router";
|
||||
import Link from "next/link";
|
||||
|
@ -6,28 +6,64 @@ import axiosServer from '../../../src/axiosServer';
|
||||
import common from '../../../src/helpers/common';
|
||||
import ShiftsList from '../../../components/publisher/ShiftsList';
|
||||
|
||||
import { monthNamesBG, GetTimeFormat, GetDateFormat } from "../../../src/helpers/const"
|
||||
import { useSession, getSession } from 'next-auth/react';
|
||||
|
||||
export default function MySchedulePage({ assignments }) {
|
||||
|
||||
const { data: session, status } = useSession();
|
||||
if (status === "loading") {
|
||||
return <div>Loading...</div>;
|
||||
return <div className="flex justify-center items-center h-screen">Loading...</div>;
|
||||
}
|
||||
|
||||
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>
|
||||
<ShiftsList assignments={assignments} selectedtab={common.getCurrentYearMonth()} />
|
||||
<h1 className="text-2xl md:text-3xl font-bold text-center my-4">Моите смени</h1>
|
||||
<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>
|
||||
</ProtectedRoute>
|
||||
</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) => {
|
||||
const session = await getSession(context);
|
||||
@ -72,6 +108,7 @@ export const getServerSideProps = async (context) => {
|
||||
if (assignment.shift && assignment.shift.startTime) {
|
||||
return {
|
||||
...assignment,
|
||||
dateStr: assignment.shift.startTime.toLocaleDateString("bg-BG", { day: "numeric", month: "long" }),
|
||||
shift: {
|
||||
...assignment.shift,
|
||||
startTime: assignment.shift.startTime.toISOString(),
|
||||
@ -82,26 +119,10 @@ export const getServerSideProps = async (context) => {
|
||||
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 {
|
||||
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
|
||||
repeatFrequency Int? // New field to indicate repetition frequency
|
||||
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 {
|
||||
|
Reference in New Issue
Block a user