From d1d0ca667e0581ae32a285ca36e9c0ed9ddb4918 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 21 Jun 2024 14:51:08 +0300 Subject: [PATCH 01/43] fix form submit bug --- components/survey/SurveyForm.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/survey/SurveyForm.tsx b/components/survey/SurveyForm.tsx index 60c3ace..389ebda 100644 --- a/components/survey/SurveyForm.tsx +++ b/components/survey/SurveyForm.tsx @@ -62,8 +62,8 @@ const SurveyForm: React.FC = ({ existingItem }) => { ...existingItem, content: existingItem?.content || "Нова анкета", answers: existingItem?.answers.split(",") || [], - publicFrom: existingItem?.publicFrom ? dayjs(existingItem.publicFrom).toISOString() : new Date().toISOString(), - publicUntil: existingItem?.publicUntil ? dayjs(existingItem.publicUntil).toISOString() : new Date().toISOString(), + publicFrom: existingItem?.publicFrom ? dayjs(existingItem.publicFrom).toISOString() : '', + publicUntil: existingItem?.publicUntil ? dayjs(existingItem.publicUntil).toISOString() : null, }); @@ -104,7 +104,7 @@ const SurveyForm: React.FC = ({ existingItem }) => { } else { //get all publisherIds and create a message for each - const messages = pubs.data.map(pub => { + const messages = pubs.map(pub => { return { publisherId: pub.id, content: JSON.stringify({ message: item.content, options: item.answers }), From 784f95cc9f93824f2ed5f43b5c966d794503e127 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 21 Jun 2024 15:41:50 +0300 Subject: [PATCH 02/43] change content size --- prisma/migrations/20240621124135_/migration.sql | 5 +++++ prisma/schema.prisma | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 prisma/migrations/20240621124135_/migration.sql diff --git a/prisma/migrations/20240621124135_/migration.sql b/prisma/migrations/20240621124135_/migration.sql new file mode 100644 index 0000000..9063825 --- /dev/null +++ b/prisma/migrations/20240621124135_/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE `message` MODIFY `content` TEXT NOT NULL; + +-- AlterTable +ALTER TABLE `survey` MODIFY `content` TEXT NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 35996b6..91a0197 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -266,7 +266,7 @@ enum MessageType { model Survey { id Int @id @default(autoincrement()) - content String + content String @db.Text answers Json? messages Message[] publicFrom DateTime? @@ -278,7 +278,7 @@ model Message { publisher Publisher @relation(fields: [publisherId], references: [id]) publisherId String date DateTime - content String + content String @db.Text isRead Boolean @default(false) isPublic Boolean @default(false) type MessageType @default(Email) From 43809487a7b541381393afdd452220302fa8145b Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 21 Jun 2024 16:46:34 +0300 Subject: [PATCH 03/43] fix migration casing, UI improvements --- components/survey/SurveyForm.tsx | 7 +++++-- prisma/migrations/20240621124135_/migration.sql | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/components/survey/SurveyForm.tsx b/components/survey/SurveyForm.tsx index 389ebda..6d9e040 100644 --- a/components/survey/SurveyForm.tsx +++ b/components/survey/SurveyForm.tsx @@ -213,13 +213,16 @@ const SurveyForm: React.FC = ({ existingItem }) => { - handleDateChange('publicFrom', newDate)} value={dayjs(item?.publicFrom)} /> + handleDateChange('publicFrom', newDate)} + value={item && item.publicFrom ? dayjs(item.publicFrom) : null} />
- handleDateChange('publicUntil', newDate)} value={dayjs(item?.publicUntil)} /> + handleDateChange('publicUntil', newDate)} + value={item && item.publicUntil ? dayjs(item.publicUntil) : null} + />
+ {isAdmin &&
{/*
} - {notificationPermission !== "granted" && ( - - )} + { + notificationPermission !== "granted" && ( + + ) + } - {isAdmin &&
- } ); diff --git a/components/publisher/PublisherForm.js b/components/publisher/PublisherForm.js index 7d76de3..85cdb6f 100644 --- a/components/publisher/PublisherForm.js +++ b/components/publisher/PublisherForm.js @@ -303,7 +303,8 @@ export default function PublisherForm({ item, me }) { {/* In-App notifications group */}

Известия в приложението

- + +
diff --git a/components/publisher/PublisherShiftsModal.js b/components/publisher/PublisherShiftsModal.js new file mode 100644 index 0000000..55d31d6 --- /dev/null +++ b/components/publisher/PublisherShiftsModal.js @@ -0,0 +1,128 @@ +//Refactor ToDo: show the whole month instead of just the current week by showing the shift start time in front of the rows, and show all shifts in the month from the first to the last week in the cell where we show one shift now +function PublisherShiftsModal({ publisher, shifts, onClose }) { + const monthInfo = common.getMonthDatesInfo(new Date(value)); + const monthShifts = shifts.filter(shift => { + const shiftDate = new Date(shift.startTime); + return shiftDate > monthInfo.firstDay && shiftDate < monthInfo.lastDay; + }); + const weekShifts = monthShifts.filter(shift => { + const shiftDate = new Date(shift.startTime); + return common.getStartOfWeek(value) <= shiftDate && shiftDate <= common.getEndOfWeek(value); + }); + const dayShifts = weekShifts.map(shift => { + const isAvailable = publisher.availabilities?.some(avail => + avail.startTime <= shift.startTime && avail.endTime >= shift.endTime + ); + let color = isAvailable ? getColorForShift(shift) : 'bg-gray-300'; + if (shift.isFromPreviousMonth) { + color += ' border-l-4 border-orange-500 '; + } + if (shift.isFromPreviousAssignment) { + color += ' border-l-4 border-red-500 '; + } + return { ...shift, isAvailable, color }; + }).reduce((acc, shift) => { + const dayIndex = new Date(shift.startTime).getDay(); + acc[dayIndex] = acc[dayIndex] || []; + acc[dayIndex].push(shift); + return acc; + }, {}); + console.log("dayShifts:", dayShifts); + + const hasAssignment = (shiftId) => { + // return publisher.assignments.some(ass => ass.shift.id == shiftId); + return publisher.assignments?.some(ass => { + //console.log(`Comparing: ${ass.shift.id} to ${shiftId}: ${ass.shift.id === shiftId}`); + return ass.shift.id === shiftId; + }); + }; + + + useEffect(() => { + const handleKeyDown = (event) => { + if (event.key === 'Escape') { + console.log('ESC: closing modal.'); + onClose(); // Call the onClose function when ESC key is pressed + } + }; + + // Add event listener + window.addEventListener('keydown', handleKeyDown); + + // Remove event listener on cleanup + return () => { + window.removeEventListener('keydown', handleKeyDown); + }; + }, [onClose]); // Include onClose in the dependency array + + return ( +
+
+

График на + {publisher.firstName} {publisher.lastName} + {publisher.email} + тази седмица:

+ + {/* ... Display shifts in a calendar-like UI ... */} +
+ {Object.entries(dayShifts).map(([dayIndex, shiftsForDay]) => ( +
+ {/* Day header */} +
{new Date(shiftsForDay[0].startTime).getDate()}-ти
+ + {shiftsForDay.map((shift, index) => { + const assignmentExists = hasAssignment(shift.id); + const availability = publisher.availabilities.find(avail => + avail.startTime <= shift.startTime && avail.endTime >= shift.endTime + ); + const isFromPrevMonth = availability && availability.isFromPreviousMonth; + return ( +
+ {common.getTimeRange(shift.startTime, shift.endTime)} {shift.id} + + {!assignmentExists && shift.isAvailable && ( + + )} + {assignmentExists && ( + + )} +
+ ); + } + )} +
+ ))} +
+ + {/* Close button in the top right corner */} + + + {/* + + */} + {/* Edit button in the top right corner, next to the close button */} + + + + +
+
+ ); +} diff --git a/pages/api/schedule.ts b/pages/api/schedule.ts index d95b1e6..b723095 100644 --- a/pages/api/schedule.ts +++ b/pages/api/schedule.ts @@ -152,15 +152,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) //bold the text after - in the notes notes: notes, notes_bold: notes_bold, - names: shift.assignments - .map((assignment) => { - return ( - assignment.publisher.firstName + - " " + - assignment.publisher.lastName - ); - }) - .join(", "), + names: shift.assignments.length > 0 + ? shift.assignments + .map((assignment) => { + return ( + assignment.publisher.firstName + + " " + + assignment.publisher.lastName + ); + }) + .join(", ") + : shift.name, }; if (shiftSchedule.names.length > 0) { diff --git a/pages/cart/calendar/index.tsx b/pages/cart/calendar/index.tsx index fd55e48..0663bea 100644 --- a/pages/cart/calendar/index.tsx +++ b/pages/cart/calendar/index.tsx @@ -9,6 +9,7 @@ import Shift from '../../../components/calendar/ShiftComponent'; import { DayOfWeek, UserRole } from '@prisma/client'; import { env } from 'process' import ShiftComponent from '../../../components/calendar/ShiftComponent'; +import PublisherShiftsModal from '../../../components/publisher/PublisherShiftsModal'; //import { set } from 'date-fns'; const common = require('src/helpers/common'); import { toast } from 'react-toastify'; @@ -66,6 +67,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) { const [shifts, setShifts] = React.useState([]); const [error, setError] = React.useState(null); const [availablePubs, setAvailablePubs] = React.useState([]); + const [selectedPublisher, setSelectedPublisher] = React.useState(null); const [selectedShiftId, setSelectedShiftId] = useState(null); @@ -214,8 +216,8 @@ export default function CalendarPage({ initialEvents, initialShifts }) { }; const handleSelectedPublisher = (publisher) => { - // Do something with the selected publisher console.log("handle pub clicked:", publisher); + setSelectedPublisher(publisher); } const handlePublisherModalOpen = async (publisher) => { // Do something with the selected publisher @@ -365,6 +367,10 @@ export default function CalendarPage({ initialEvents, initialShifts }) { isConfirmed: true }; const { data } = await axiosInstance.post("/api/data/assignments", newAssignment); + if (selectedShiftId == shiftId) { + handleShiftSelection(shifts.find(shift => shift.id === shiftId)); + } + // Update the 'publisher' property of the returned data with the full publisher object data.publisher = publisher; data.shift = shifts.find(shift => shift.id === shiftId); @@ -816,6 +822,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) { ${bgAndBorderColorClass} ${selectedBorderClass} ${activeOpacityClass} ${pub.currentMonthAssignments >= pub.desiredShiftsPerMonth ? 'text-gray-400' : 'text-gray-800'}`} onDoubleClick={(handlePublisherModalOpen.bind(this, pub))} + onClick={handleSelectedPublisher.bind(this, pub)} > {pub.firstName} {pub.lastName} @@ -831,33 +838,8 @@ export default function CalendarPage({ initialEvents, initialShifts }) { @@ -905,133 +887,6 @@ export default function CalendarPage({ initialEvents, initialShifts }) { ); - function PublisherShiftsModal({ publisher, shifts, onClose }) { - const monthInfo = common.getMonthDatesInfo(new Date(value)); - const monthShifts = shifts.filter(shift => { - const shiftDate = new Date(shift.startTime); - return shiftDate > monthInfo.firstDay && shiftDate < monthInfo.lastDay; - }); - const weekShifts = monthShifts.filter(shift => { - const shiftDate = new Date(shift.startTime); - return common.getStartOfWeek(value) <= shiftDate && shiftDate <= common.getEndOfWeek(value); - }); - const dayShifts = weekShifts.map(shift => { - const isAvailable = publisher.availabilities?.some(avail => - avail.startTime <= shift.startTime && avail.endTime >= shift.endTime - ); - let color = isAvailable ? getColorForShift(shift) : 'bg-gray-300'; - if (shift.isFromPreviousMonth) { - color += ' border-l-4 border-orange-500 '; - } - if (shift.isFromPreviousAssignment) { - color += ' border-l-4 border-red-500 '; - } - return { ...shift, isAvailable, color }; - }).reduce((acc, shift) => { - const dayIndex = new Date(shift.startTime).getDay(); - acc[dayIndex] = acc[dayIndex] || []; - acc[dayIndex].push(shift); - return acc; - }, {}); - console.log("dayShifts:", dayShifts); - - const hasAssignment = (shiftId) => { - // return publisher.assignments.some(ass => ass.shift.id == shiftId); - return publisher.assignments?.some(ass => { - //console.log(`Comparing: ${ass.shift.id} to ${shiftId}: ${ass.shift.id === shiftId}`); - return ass.shift.id === shiftId; - }); - }; - - - useEffect(() => { - const handleKeyDown = (event) => { - if (event.key === 'Escape') { - console.log('ESC: closing modal.'); - onClose(); // Call the onClose function when ESC key is pressed - } - }; - - // Add event listener - window.addEventListener('keydown', handleKeyDown); - - // Remove event listener on cleanup - return () => { - window.removeEventListener('keydown', handleKeyDown); - }; - }, [onClose]); // Include onClose in the dependency array - - return ( -
-
-

График на - {publisher.firstName} {publisher.lastName} - {publisher.email} - тази седмица:

- - {/* ... Display shifts in a calendar-like UI ... */} -
- {Object.entries(dayShifts).map(([dayIndex, shiftsForDay]) => ( -
- {/* Day header */} -
{new Date(shiftsForDay[0].startTime).getDate()}-ти
- - {shiftsForDay.map((shift, index) => { - const assignmentExists = hasAssignment(shift.id); - const availability = publisher.availabilities.find(avail => - avail.startTime <= shift.startTime && avail.endTime >= shift.endTime - ); - const isFromPrevMonth = availability && availability.isFromPreviousMonth; - return ( -
- {common.getTimeRange(shift.startTime, shift.endTime)} {shift.id} - - {!assignmentExists && shift.isAvailable && ( - - )} - {assignmentExists && ( - - )} -
- ); - } - )} -
- ))} -
- - {/* Close button in the top right corner */} - - - {/* - - */} - {/* Edit button in the top right corner, next to the close button */} - - - - -
-
- ); - } function getColorForShift(shift) { const assignedCount = shift.assignedCount || 0; // Assuming each shift has an assignedCount property From 0d8d9bc4fda16ca4e7c86ee2781d68c26d556008 Mon Sep 17 00:00:00 2001 From: Dobromir Popov Date: Fri, 28 Jun 2024 19:57:59 +0300 Subject: [PATCH 05/43] pubs orange if overbooked --- pages/cart/calendar/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/cart/calendar/index.tsx b/pages/cart/calendar/index.tsx index 0663bea..5f0f117 100644 --- a/pages/cart/calendar/index.tsx +++ b/pages/cart/calendar/index.tsx @@ -785,7 +785,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) { със стари предпочитания -