diff --git a/.env.demo b/.env.demo index 2a2aa9a..17f98ce 100644 --- a/.env.demo +++ b/.env.demo @@ -1,37 +1,9 @@ -NODE_TLS_REJECT_UNAUTHORIZED='0' -# DATABASE_URL="file:./src/data/dev.db" -# DATABASE_URL="mysql://root:Zelen0ku4e@192.168.0.10:3306/cart" - -NEXT_PUBLIC_PORT= -# NEXT_PUBLIC_NEXTAUTH_URL=https://cart.d-popov.com NEXT_PUBLIC_PROTOCOL=https -NEXT_PUBLIC_HOST=cart.d-popov.com -NEXTAUTH_URL=https://cart.d-popov.com -# NEXTAUTH_URL= https://demo.mwhitnessing.com +NEXT_PUBLIC_PORT= +NEXT_PUBLIC_HOST=staging.mwhitnessing.com +NEXTAUTH_URL= https://staging.mwhitnessing.com # Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32 -NEXTAUTH_SECRET=ed8a9681efc414df89dfd03cd188ed58 -DATABASE_URL=mysql://cart:cart2023@192.168.0.10:3306/cart_demo - -APPLE_ID= -APPLE_TEAM_ID= -APPLE_PRIVATE_KEY= -APPLE_KEY_ID= - -AUTH0_ID=Aa9f3HJowauUrmBVY4iQzQJ7fYsaZDbK -AUTH0_SECRET=_c0O9GkyRXkoWMQW7jNExnl6UoXN6O4oD3mg7NZ_uHVeAinCUtcTAkeQmcKXpZ4x -AUTH0_ISSUER=https://dev-wkzi658ckibr1amv.us.auth0.com - -FACEBOOK_ID= -FACEBOOK_SECRET= - -GITHUB_ID= -GITHUB_SECRET= -# GOOGLE_ID=926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com -# GOOGLE_SECRET=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 - -TWITTER_ID= -TWITTER_SECRET= - -EMAIL_SERVER=smtp://8ec69527ff2104:c7bc05f171c96c@smtp.mailtrap.io:2525 -EMAIL_FROM=noreply@example.com +NEXTAUTH_SECRET=1dd8a5457970d1dda50600be28e935ecc4513ff27c49c431849e6746f158d638 +# ? do we need to duplicate this? already defined in the deoployment yml file +DATABASE_URL=mysql://jwpwsofia_demo:dwxhns9p9vp248@mariadb:3306/jwpwsofia_demo \ No newline at end of file diff --git a/.env.homelab b/.env.homelab new file mode 100644 index 0000000..2a2aa9a --- /dev/null +++ b/.env.homelab @@ -0,0 +1,37 @@ +NODE_TLS_REJECT_UNAUTHORIZED='0' +# DATABASE_URL="file:./src/data/dev.db" +# DATABASE_URL="mysql://root:Zelen0ku4e@192.168.0.10:3306/cart" + +NEXT_PUBLIC_PORT= +# NEXT_PUBLIC_NEXTAUTH_URL=https://cart.d-popov.com +NEXT_PUBLIC_PROTOCOL=https +NEXT_PUBLIC_HOST=cart.d-popov.com +NEXTAUTH_URL=https://cart.d-popov.com +# NEXTAUTH_URL= https://demo.mwhitnessing.com + +# Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32 +NEXTAUTH_SECRET=ed8a9681efc414df89dfd03cd188ed58 +DATABASE_URL=mysql://cart:cart2023@192.168.0.10:3306/cart_demo + +APPLE_ID= +APPLE_TEAM_ID= +APPLE_PRIVATE_KEY= +APPLE_KEY_ID= + +AUTH0_ID=Aa9f3HJowauUrmBVY4iQzQJ7fYsaZDbK +AUTH0_SECRET=_c0O9GkyRXkoWMQW7jNExnl6UoXN6O4oD3mg7NZ_uHVeAinCUtcTAkeQmcKXpZ4x +AUTH0_ISSUER=https://dev-wkzi658ckibr1amv.us.auth0.com + +FACEBOOK_ID= +FACEBOOK_SECRET= + +GITHUB_ID= +GITHUB_SECRET= +# GOOGLE_ID=926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com +# GOOGLE_SECRET=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 + +TWITTER_ID= +TWITTER_SECRET= + +EMAIL_SERVER=smtp://8ec69527ff2104:c7bc05f171c96c@smtp.mailtrap.io:2525 +EMAIL_FROM=noreply@example.com diff --git a/.env.prod_staging b/.env.prod_staging deleted file mode 100644 index 4542e30..0000000 --- a/.env.prod_staging +++ /dev/null @@ -1,9 +0,0 @@ -NEXT_PUBLIC_PROTOCOL=https -NEXT_PUBLIC_PORT= -NEXT_PUBLIC_HOST=staging.mwhitnessing.com -NEXTAUTH_URL= https://staging.mwhitnessing.com - -# Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32 -NEXTAUTH_SECRET=1dd8a5457970d1dda50600be28e935ecc4513ff27c49c431849e6746f158d638 -# ? do we need to duplicate this? already defined in the deoployment yml file -DATABASE_URL=mysql://jwpwsofia:dwxhns9p9vp248V39xJyRthUsZ2gR9@mariadb-staging:3306/jwpwsofia \ No newline at end of file diff --git a/_deploy/deoloy.azure.demo.yml b/_deploy/deoloy.azure.demo.yml new file mode 100644 index 0000000..924858a --- /dev/null +++ b/_deploy/deoloy.azure.demo.yml @@ -0,0 +1,39 @@ +version: "3" +services: + nextjs-app: # https://sofia.mwhitnessing.com/ + hostname: jwpw-app-staging # jwpw-nextjs-app-1 + image: docker.d-popov.com/jwpw:latest + volumes: + - /mnt/docker_volumes/pw-demo/app/public/content/uploads/:/app/public/content/uploads + environment: + - NODE_ENV=demo + - TZ=Europe/Sofia + - DATABASE_URL=mysql://jwpwsofia_demo:dwxhns9p9vp248@jwpwsofia:3306/jwpwsofia_demo + - UPDATE_CODE_FROM_GIT=true # Set to true to pull latest code from Git + - GIT_BRANCH=main + - GIT_USERNAME=deploy + - GIT_PASSWORD=L3Kr2R438u4F7 + command: sh -c " cd /app && npm install && npx next build && npm run nodeenv; tail -f /dev/null" + tty: true + stdin_open: true + restart: always + networks: + - infrastructure_default + mariadb: + deploy: + replicas: 0 + hostname: mariadb-demo + image: mariadb:latest #mariadb:10.4 + volumes: + - /mnt/docker_volumes/pw-demo/data/mysql:/var/lib/mysql + environment: + MARIADB_ROOT_PASSWORD: i4966cWBtP3xJ7BLsbsgo93 + MYSQL_ROOT_PASSWORD: i4966cWBtP3xJ7BLsbsgo93 + MYSQL_DATABASE: jwpwsofia_demo + MYSQL_USER: jwpwsofia_demo + MYSQL_PASSWORD: dwxhns9p9vp248 + networks: + - infrastructure_default +networks: + infrastructure_default: + external: true diff --git a/_deploy/deoloy.azure.prod.stage.yml b/_deploy/deoloy.azure.prod.stage.yml deleted file mode 100644 index 9590d67..0000000 --- a/_deploy/deoloy.azure.prod.stage.yml +++ /dev/null @@ -1,57 +0,0 @@ -version: "3" -services: - nextjs-app: # https://sofia.mwhitnessing.com/ - hostname: jwpw-app-staging # jwpw-nextjs-app-1 - image: docker.d-popov.com/jwpw:latest - volumes: - - /mnt/docker_volumes/pw-staging/app/public/content/uploads/:/app/public/content/uploads - environment: - - NODE_ENV=prod_staging - - TZ=Europe/Sofia - - DATABASE_URL=mysql://jwpwsofia:dwxhns9p9vp248V39xJyRthUsZ2gR9@mariadb-staging:3306/jwpwsofia - - UPDATE_CODE_FROM_GIT=true # Set to true to pull latest code from Git - - GIT_BRANCH=main - - GIT_USERNAME=deploy - - GIT_PASSWORD=L3Kr2R438u4F7 - command: sh -c " cd /app && npm install && npm run nodeenv; tail -f /dev/null" - tty: true - stdin_open: true - restart: always - # ports: - # - "3001:3000" - networks: - - infrastructure_default - mariadb: - hostname: mariadb-staging - image: mariadb:latest #mariadb:10.4 - volumes: - - /mnt/docker_volumes/pw-staging/data/mysql:/var/lib/mysql - environment: - MARIADB_ROOT_PASSWORD: i4966cWBtP3xJ7BLsbsgo93C8Q5262 - MYSQL_ROOT_PASSWORD: i4966cWBtP3xJ7BLsbsgo93C8Q5262 - MYSQL_DATABASE: jwpwsofia - MYSQL_USER: jwpwsofia - MYSQL_PASSWORD: dwxhns9p9vp248V39xJyRthUsZ2gR9 - #command: ["mysqld", "--max-connections=1000", "--sql-mode=ALLOW_INVALID_DATES,ANSI_QUOTES,ERROR_FOR_DIVISION_BY_ZERO,HIGH_NOT_PRECEDENCE,IGNORE_SPACE,NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION,NO_FIELD_OPTIONS,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_UNSIGNED_SUBTRACTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY,PIPES_AS_CONCAT,REAL_AS_FLOAT,STRICT_ALL_TABLES,STRICT_TRANS_TABLES,ANSI,DB2,MAXDB,MSSQL,MYSQL323,MYSQL40,ORACLE,POSTGRESQL,TRADITIONAL", "--wait-timeout=28800"] - networks: - - infrastructure_default - postgres: - hostname: postgres - image: postgres - restart: always - # set shared memory limit when using docker-compose - shm_size: 128mb - # or set shared memory limit when deploy via swarm stack - #volumes: - # - type: tmpfs - # target: /dev/shm - # tmpfs: - # size: 134217728 # 128*2^20 bytes = 128Mb - environment: - POSTGRES_PASSWORD: i4966cWBtP3xJ7BLsbsgo93C8Q5262 - - networks: - - infrastructure_default -networks: - infrastructure_default: - external: true diff --git a/_deploy/deoloy.azure.prod.yml b/_deploy/deoloy.azure.production.yml similarity index 96% rename from _deploy/deoloy.azure.prod.yml rename to _deploy/deoloy.azure.production.yml index 0cb1e8b..87372a8 100644 --- a/_deploy/deoloy.azure.prod.yml +++ b/_deploy/deoloy.azure.production.yml @@ -3,6 +3,8 @@ services: nextjs-app: # https://sofia.mwhitnessing.com/ hostname: jwpw-app # jwpw-nextjs-app-1 image: docker.d-popov.com/jwpw:latest + deploy: + replicas: 2 #ports: # - "3000:3000" volumes: @@ -30,7 +32,7 @@ services: volumes: - /mnt/docker_volumes/pw/data/mysql:/var/lib/mysql environment: - MARIADB_ROOT_PASSWORD: dwxhns9p9vp248V39xJyRthUsZ2gR9 + # MARIADB_ROOT_PASSWORD: dwxhns9p9vp248V39xJyRthUsZ2gR9 MYSQL_ROOT_PASSWORD: i4966cWBtP3xJ7BLsbsgo93C8Q5262 MYSQL_DATABASE: jwpwsofia MYSQL_USER: jwpwsofia @@ -38,7 +40,6 @@ services: networks: - default - infrastructure_default - mariadb_backup: image: alpine:latest volumes: @@ -51,7 +52,6 @@ services: MYSQL_HOST: mariadb # GOOGLE_DRIVE_FOLDER_ID: your_google_drive_folder_id entrypoint: /bin/sh -c - networks: - infrastructure_default command: | diff --git a/_deploy/deploy.homelab.production.yml b/_deploy/homelab.deploy.production.yml similarity index 57% rename from _deploy/deploy.homelab.production.yml rename to _deploy/homelab.deploy.production.yml index cf14df8..402af4d 100644 --- a/_deploy/deploy.homelab.production.yml +++ b/_deploy/homelab.deploy.production.yml @@ -15,7 +15,7 @@ services: stdin_open: true mariadb: hostname: mariadb - image: mariadb #bitnami/mariadb:latest #mariadb:10.4 + image: mariadb #bitnami/mariadb:latest #mariadb:10.4 environment: MARIADB_ROOT_PASSWORD: Pw62L$3332JH MYSQL_ROOT_PASSWORD: Pw62L$3332JH @@ -24,4 +24,20 @@ services: MYSQL_PASSWORD: o74x642Rc8 networks: - default - - mysql_default \ No newline at end of file + - mysql_default + postgres: + deploy: + replicas: 0 + hostname: postgres + image: postgres + restart: always + # set shared memory limit when using docker-compose + shm_size: 128mb + # or set shared memory limit when deploy via swarm stack + #volumes: + # - type: tmpfs + # target: /dev/shm + # tmpfs: + # size: 134217728 # 128*2^20 bytes = 128Mb + environment: + POSTGRES_PASSWORD: i4966cWBtP3xJ7BLsbsgo93C8Q5262 diff --git a/_doc/notes.mb b/_doc/notes.mb index 4862741..bd38d8e 100644 --- a/_doc/notes.mb +++ b/_doc/notes.mb @@ -164,8 +164,15 @@ SET PASSWORD FOR 'root'@'localhost' = PASSWORD('i4966cWBtP3xJ7BLsbsgo93C8Q5262') GRANT ALL PRIVILEGES ON jwpwsofia.* TO 'jwpwsofia'@'%' IDENTIFIED BY 'dwxhns9p9vp248V39xJyRthUsZ2gR9' WITH GRANT OPTION; GRANT ALL PRIVILEGES ON jwpwsofia.* TO 'jwpwsofia'@'172.22.0.3' IDENTIFIED BY 'dwxhns9p9vp248V39xJyRthUsZ2gR9' WITH GRANT OPTION; +GRANT ALL PRIVILEGES ON jwpwsofia.* TO 'jwpwsofia'@'172.22.0.%' IDENTIFIED BY 'dwxhns9p9vp248V39xJyRthUsZ2gR9' WITH GRANT OPTION; FLUSH PRIVILEGES; exit; +ALTER USER 'jwpwsofia'@'172.22.0.%' IDENTIFIED BY 'dwxhns9p9vp248V39xJyRthUsZ2gR9'; +--if error (does not exist) +CREATE USER 'jwpwsofia'@'172.22.0.%' IDENTIFIED BY 'dwxhns9p9vp248V39xJyRthUsZ2gR9'; +GRANT ALL PRIVILEGES ON jwpwsofia.* TO 'jwpwsofia'@'172.22.0.%' WITH GRANT OPTION; + + #Install depcheck: diff --git a/components/calendar/ShiftComponent.tsx b/components/calendar/ShiftComponent.tsx index f78f498..c6c5ec2 100644 --- a/components/calendar/ShiftComponent.tsx +++ b/components/calendar/ShiftComponent.tsx @@ -2,6 +2,8 @@ import React, { useState, useEffect } from 'react'; import axiosInstance from '../../src/axiosSecure'; import PublisherSearchBox from '../publisher/PublisherSearchBox'; // Update the path +import LocalShippingIcon from '@mui/icons-material/LocalShipping'; + const common = require('src/helpers/common'); @@ -52,10 +54,11 @@ function ShiftComponent({ shift, onShiftSelect, isSelected, onPublisherSelect, a const [useFilterDate, setUseFilterDate] = useState(true); const [selectedPublisher, setSelectedPublisher] = useState(null); const [showCopyHint, setShowCopyHint] = useState(false); - + const [transportProvided, setTransportProvided] = useState(false); // Update assignments when shift changes useEffect(() => { setAssignments(shift.assignments); + setTransportProvided(!shift.requiresTransport || shift.assignments.some(ass => ass.isWithTransport)); }, [shift.assignments]); const handleShiftClick = (shiftId) => { @@ -106,7 +109,7 @@ function ShiftComponent({ shift, onShiftSelect, isSelected, onPublisherSelect, a publisher: { connect: { id: publisher.id } }, shift: { connect: { id: shiftId } }, //isactive: true, - isConfirmed: true + isConfirmed: true, }; const { data } = await axiosInstance.post("/api/data/assignments", newAssignment); // Update the 'publisher' property of the returned data with the full publisher object @@ -124,9 +127,16 @@ function ShiftComponent({ shift, onShiftSelect, isSelected, onPublisherSelect, a setTimeout(() => setShowCopyHint(false), 1500); }; - - - + async function toggleTransport(assignment): Promise { + try { + assignment.isWithTransport = !assignment.isWithTransport; + const { data } = await axiosInstance.put("/api/data/assignments/" + assignment.id, + { isWithTransport: assignment.isWithTransport }) + .then(() => { + setTransportProvided(assignments.some(ass => ass.isWithTransport)) + }); + } catch (error) { } + } return (
{`${common.getTimeRange(new Date(shift.startTime), new Date(shift.endTime))}`} + {/* {shift.requiresTransport && ()} */} {/* Copy All Names Button */} @@ -149,13 +160,13 @@ function ShiftComponent({ shift, onShiftSelect, isSelected, onPublisherSelect, a )}
- {/* Assignments */} {assignments.map((ass, index) => { const publisherInfo = allPublishersInfo.find(info => info?.id === ass.publisher.id) || ass.publisher; // Determine border styles let borderStyles = ''; + let canTransport = false; if (selectedPublisher && selectedPublisher.id === ass.publisher.id) { borderStyles += 'border-2 border-blue-300'; // Bottom border for selected publishers } @@ -172,10 +183,12 @@ function ShiftComponent({ shift, onShiftSelect, isSelected, onPublisherSelect, a else { // checkig if the publisher is available for this assignment - if (publisherInfo.availabilities?.some(av => - av.startTime <= shift.startTime && - av.endTime >= shift.endTime)) { + const av = publisherInfo.availabilities?.find(av => + av.startTime <= shift.startTime && av.endTime >= shift.endTime + ); + if (av) { borderStyles += 'border-l-2 border-blue-500 '; // Left border for specific availability conditions + ass.canTransport = av.isWithTransportIn || av.isWithTransportOut; } if (publisherInfo.hasUpToDateAvailabilities) { @@ -194,17 +207,29 @@ function ShiftComponent({ shift, onShiftSelect, isSelected, onPublisherSelect, a } } + return (
handlePublisherClick(ass.publisher)}> {publisherInfo.firstName} {publisherInfo.lastName} - +
+ {/* //if shift.isWithTransport, add trnsport button toggle, which sets ass.isWithTransportIn */} + {shift.requiresTransport && ( + toggleTransport(ass) : undefined} + className={`material-icons ${ass.isWithTransport ? 'text-green-500 font-bold' : (transportProvided ? 'text-gray-400 ' : 'text-orange-400 font-bold')} ${ass.canTransport ? ' cursor-pointer' : 'cursor-not-allowed'} px-3 py-1 ml-2 rounded-md`} + > + {ass.isWithTransport ? "транспорт" : ass.canTransport ? "може транспорт" : "без транспорт"} + + )} + + +
+
); @@ -243,7 +268,7 @@ function ShiftComponent({ shift, onShiftSelect, isSelected, onPublisherSelect, a showList={false} /> - + ); } diff --git a/pages/api/shiftgenerate.ts b/pages/api/shiftgenerate.ts index ba61fb8..c1bc139 100644 --- a/pages/api/shiftgenerate.ts +++ b/pages/api/shiftgenerate.ts @@ -178,7 +178,8 @@ async function GenerateSchedule(axios: Axios, date: string, copyFromPreviousMont shiftNr++; const __shiftName = String(shiftStart.getHours()).padStart(2, "0") + ":" + String(shiftStart.getMinutes()).padStart(2, "0") + " - " + String(shiftEnd.getHours()).padStart(2, "0") + ":" + String(shiftEnd.getMinutes()).padStart(2, "0"); shiftAssignments = []; - console.log("[shift " + shiftNr + "] " + __shiftName); + let isTransportRequired = shiftNr == 1 || shiftEnd.getTime() == endTime.getTime(); + console.log("[shift " + shiftNr + "] " + __shiftName + ", transport: " + (isTransportRequired ? "yes" : "no") + ", " + shiftStart.toLocaleTimeString() + " - " + shiftEnd.toLocaleTimeString() + " (end time: " + endTime.toLocaleTimeString() + ", " + event.shiftDuration + " min)"); if (autoFill || copyFromPreviousMonth) { // ########################################### @@ -395,6 +396,7 @@ async function GenerateSchedule(axios: Axios, date: string, copyFromPreviousMont startTime: shiftStart, endTime: shiftEnd, name: event.dayofweek + " " + shiftStart.toLocaleTimeString() + " - " + shiftEnd.toLocaleTimeString(), + requiresTransport: isTransportRequired, cartEvent: { connect: { id: event.id, diff --git a/pages/cart/calendar/index.tsx b/pages/cart/calendar/index.tsx index 244128c..a3f5746 100644 --- a/pages/cart/calendar/index.tsx +++ b/pages/cart/calendar/index.tsx @@ -14,6 +14,7 @@ const common = require('src/helpers/common'); import { toast } from 'react-toastify'; import ProtectedRoute from '../../../components/protectedRoute'; import ConfirmationModal from '../../../components/ConfirmationModal'; +import LocalShippingIcon from '@mui/icons-material/LocalShipping'; // import { FaPlus, FaCogs, FaTrashAlt, FaSpinner } from 'react-icons/fa'; // Import FontAwesome icons @@ -108,6 +109,12 @@ export default function CalendarPage({ initialEvents, initialShifts }) { const { data: shiftsForDate } = await axiosInstance.get(`/api/?action=getShiftsForDay&date=${dateStr}`); setShifts(shiftsForDate); let { data: availablePubsForDate } = await axiosInstance.get(`/api/?action=filterPublishers&assignments=true&availabilities=true&date=${dateStr}&select=id,firstName,lastName,isactive,desiredShiftsPerMonth`); + + availablePubsForDate.forEach(pub => { + pub.canTransport = pub.availabilities.some(av => + av.isWithTransportIn || av.isWithTransportOut + ); + }); //remove availabilities that are isFromPreviousAssignment or from previous month for each publisher // availablePubsForDate = availablePubsForDate.map(pub => { // pub.availabilities = pub.availabilities.filter(avail => avail.isFromPreviousAssignment == false); @@ -134,22 +141,31 @@ export default function CalendarPage({ initialEvents, initialShifts }) { const handleShiftSelection = (selectedShift) => { setSelectedShiftId(selectedShift.id); const updatedPubs = availablePubs.map(pub => { - const isAvailableForShift = pub.availabilities.some(avail => + const av = pub.availabilities?.find(avail => avail.startTime <= selectedShift.startTime && avail.endTime >= selectedShift.endTime - && avail.isFromPreviousAssignment == false ); + if (av) { + pub.isAvailableForShift = true; + pub.canTransport = av.isWithTransportIn || av.isWithTransportOut; + } + + // const isAvailableForShift = pub.availabilities.some(avail => + // avail.startTime <= selectedShift.startTime + // && avail.endTime >= selectedShift.endTime + // && avail.isFromPreviousAssignment == false + // ); const isAvailableForShiftWithPrevious = pub.availabilities.some(avail => avail.startTime <= selectedShift.startTime && avail.endTime >= selectedShift.endTime ); - //! console.log(`Publisher ${pub.firstName} ${pub.lastName} is available for shift ${selectedShift.id}: ${isAvailableForShift}`); - //// console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities :` + pub.availabilities.map(avail => avail.startTime + " - " + avail.endTime)); - //// console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities :` + stringify.join(', 'pub.availabilities.map(avail => avail.id))); + // //! console.log(`Publisher ${pub.firstName} ${pub.lastName} is available for shift ${selectedShift.id}: ${isAvailableForShift}`); + // //// console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities :` + pub.availabilities.map(avail => avail.startTime + " - " + avail.endTime)); + // //// console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities :` + stringify.join(', 'pub.availabilities.map(avail => avail.id))); - const availabilitiesIds = pub.availabilities.map(avail => avail.id).join(', '); - //! console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities with IDs: ${availabilitiesIds}`); - return { ...pub, isAvailableForShift, isAvailableForShiftWithPrevious, isSelected: pub.id === selectedShift.selectedPublisher?.id }; + // const availabilitiesIds = pub.availabilities.map(avail => avail.id).join(', '); + // //! console.log(`Publisher ${pub.firstName} ${pub.lastName} has ${pub.availabilities.length} availabilities with IDs: ${availabilitiesIds}`); + return { ...pub, isAvailableForShiftWithPrevious, isSelected: pub.id === selectedShift.selectedPublisher?.id }; }); // Sort publishers based on their availability state. use currentDayAssignments, currentWeekAssignments, @@ -664,6 +680,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) { > {pub.firstName} {pub.lastName} + {pub.canTransport && ()}
diff --git a/pages/cart/publishers/stats.tsx b/pages/cart/publishers/stats.tsx index 6945583..e69f47f 100644 --- a/pages/cart/publishers/stats.tsx +++ b/pages/cart/publishers/stats.tsx @@ -95,6 +95,9 @@ export const getServerSideProps = async (context) => { if (availability.startTime) { availability.startTime = availability.startTime.toISOString(); availability.endTime = availability.endTime.toISOString(); + if (availability.dateOfEntry) { + availability.dateOfEntry = availability.dateOfEntry.toISOString(); + } } }); diff --git a/src/helpers/excel.js b/src/helpers/excel.js index 49a62f3..40f2f1c 100644 --- a/src/helpers/excel.js +++ b/src/helpers/excel.js @@ -404,20 +404,21 @@ exports.processEvents = async function (events, year, monthNumber, progressCallb s.cartEventId === cartEvent.id && new Date(s.startTime).getTime() === new Date(start).getTime() ); - + // get only hh:mm from the date + let isTransportRequired = event.shiftNr == 1 || end.toLocaleTimeString().substring(0, 5) == cartEvent.endTime.toLocaleTimeString().substring(0, 5); if (!shift) { //if shiftnr = 1, notes = "Докарва" + event.transport //if shiftnr = 8, notes = "Взема" + event.transport - - let note = event.shiftNr === 1 ? "Докарва количка от Люлин - " + event.transport : - event.shiftNr === 6 ? "Прибира количка в Люлин - " + event.transport : ""; + let note = isTransportRequired ? event.transport : ""; + // "Докарва количка от Люлин/Прибира количка в Люлин" const shiftEntity = await prisma.shift.create({ data: { name: event.dayOfWeek + " " + event.dayOfMonth + ", " + start.toLocaleTimeString() + " - " + end.toLocaleTimeString(), startTime: start, endTime: end, notes: note, + requiresTransport: isTransportRequired, cartEvent: { connect: { id: cartEvent.id, @@ -506,6 +507,13 @@ exports.processEvents = async function (events, year, monthNumber, progressCallb } if (location != null && publisher != null && shift != null) { + let isWithTransport = false; + if (isTransportRequired) { + const pubInitials = publisher.firstName[0] + publisher.lastName[0]; + // get cotent after last - or long dash-`-` and remove spaces, trim dots and make lowercase + let transportInitials = event.transport.split("-").pop().replace(/[\s.]/g, "").toUpperCase(); + isWithTransport = transportInitials.includes(pubInitials); + } const assignment = await prisma.assignment.create({ data: { //publisherId: publisher.id, @@ -520,6 +528,7 @@ exports.processEvents = async function (events, year, monthNumber, progressCallb id: shift.id, }, }, + isWithTransport: isWithTransport, }, }); //ToDo: fix findPublisherAvailability and creation of availabilities