diff --git a/.env b/.env index f4b7091..66b2fe7 100644 --- a/.env +++ b/.env @@ -8,6 +8,7 @@ NEXTAUTH_SECRET=ed8a9681efc414df89dfd03cd188ed58 NODE_ENV=development # mysql +DATABASE=mysql://cart:cartpw@localhost:3306/cart # // owner: dobromir.popov@gmail.com | Специално Свидетелстване София # // https://console.cloud.google.com/apis/credentials/oauthclient/926212607479-d3m8hm8f8esp3rf1639prskn445sa01v.apps.googleusercontent.com?project=grand-forge-108716 @@ -18,16 +19,18 @@ AZURE_AD_CLIENT_ID=9e13bedd-1f9d-4c23-910e-a806aba308b6 # Application (client) I AZURE_AD_CLIENT_SECRET=5ic8Q~GQmW-IUhuxzVGx3BE-i30GXDSpjfMHcb~z #client secret value AZURE_AD_TENANT_ID=f69d1a93-bfba-498a-9b60-e87c1bc26276 +# First APPLE_SECRET=eyJhbGciOiJFUzI1NiIsImtpZCI6IlRCM1YzNTVHNVkifQ.eyJhdWQiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiaXNzIjoiWEM1N1A5U1hESyIsImlhdCI6MTcxMjE3ODM0MiwiZXhwIjoxNzI3NzMwMzQzLCJzdWIiOiJjb20ubXdoaXRuZXNzaW5nLnNvZmlhIn0.XceA0qUQi0tXg0GM_LkJkpNU5AqXLiSB2JlEVbHCB_nINbQTWkjtoWxfqmvdOkIzwKtvdQ8FFb-crK9no9Bbbw -APPLE_ID=com.mwhitnessing.sofia -APPLE_SECRET=eyJhbGciOiJFUzI1NiIsImtpZCI6IlRCM1YzNTVHNVkifQ.eyJhdWQiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiaXNzIjoiWEM1N1A5U1hESyIsImlhdCI6MTcxMjY5NzM5NywiZXhwIjoxNzI4MjQ5Mzk4LCJzdWIiOiJYQzU3UDlTWERLLmNvbS5td2hpdG5lc3Npbmcuc29maWEifQ.QDX9eoRWAKMd10iRMW9Od88-0H_oZ_B6sPG61fw-zjHbNOvlHG3ddfxY1AqfdSMvLrXg1URKM1lnxOB-OCxg4A -# with team in the ID? -#APPLE_ID=XC57P9SXDK.com.mwhitnessing.sofia -#APPLE_SECRET=eyJhbGciOiJFUzI1NiIsImtpZCI6IlRCM1YzNTVHNVkifQ.eyJhdWQiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiaXNzIjoiWEM1N1A5U1hESyIsImlhdCI6MTcxMjE3ODM0MiwiZXhwIjoxNzI3NzMwMzQzLCJzdWIiOiJjb20ubXdoaXRuZXNzaW5nLnNvZmlhIn0.XceA0qUQi0tXg0GM_LkJkpNU5AqXLiSB2JlEVbHCB_nINbQTWkjtoWxfqmvdOkIzwKtvdQ8FFb-crK9no9Bbbw -# to generate APPLE_TEAM_ID=XC57P9SXDK APPLE_KEY_ID=TB3V355G5Y -APPLE_PRIVATE_KEY= + +APPLE_APP_ID=com.mwhitnessing.sofia +APPLE_SECRET=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlRCM1YzNTVHNVkifQ.eyJpYXQiOjE3MTMzMDQ1OTMsImV4cCI6MTcyODg1NjU5MywiYXVkIjoiaHR0cHM6Ly9hcHBsZWlkLmFwcGxlLmNvbSIsImlzcyI6IlhDNTdQOVNYREsiLCJzdWIiOiJjb20ubXdoaXRuZXNzaW5nLnNvZmlhIn0.iO2prjQ_4P7F17R7LTJfG9zHluj59uUtm8DA1LbK49jVBMeGHQP_Az7s_yU5D-GeMHSwU7VnVHcaVKiGWT_Yjg + +# with team in the ID? +#APPLE_APP_ID=XC57P9SXDK.com.mwhitnessing.sofia +#APPLE_SECRET=eyJhbGciOiJFUzI1NiIsImtpZCI6IlRCM1YzNTVHNVkifQ.eyJhdWQiOiJodHRwczovL2FwcGxlaWQuYXBwbGUuY29tIiwiaXNzIjoiWEM1N1A5U1hESyIsImlhdCI6MTcxMjE3ODM0MiwiZXhwIjoxNzI3NzMwMzQzLCJzdWIiOiJjb20ubXdoaXRuZXNzaW5nLnNvZmlhIn0.XceA0qUQi0tXg0GM_LkJkpNU5AqXLiSB2JlEVbHCB_nINbQTWkjtoWxfqmvdOkIzwKtvdQ8FFb-crK9no9Bbbw +# to generate AUTH0_ID=Aa9f3HJowauUrmBVY4iQzQJ7fYsaZDbK @@ -45,18 +48,18 @@ GITHUB_SECRET= TWITTER_ID= TWITTER_SECRET= - +# EMAIL_BYPASS_TO=mwitnessing@gmail.com +EMAIL_SENDER='"ССОМ" ' # EMAIL_SERVER=smtp://8ec69527ff2104:c7bc05f171c96c@smtp.mailtrap.io:2525 -EMAIL_FROM=noreply@mwitnessing.com +# ?EMAIL_FROM=noreply@mwitnessing.com -MAILTRAP_HOST_BULK=bulk.smtp.mailtrap.io +EMAIL_SERVICE=mailtrap +# MAILTRAP_HOST_BULK=bulk.smtp.mailtrap.io MAILTRAP_HOST=sandbox.smtp.mailtrap.io +MAILTRAP_PORT=2525 MAILTRAP_USER=8ec69527ff2104 MAILTRAP_PASS=c7bc05f171c96c -GMAIL_EMAIL_USERNAME= -GMAIL_EMAIL_APP_PASS= - TELEGRAM_BOT=false TELEGRAM_BOT_TOKEN=7050075088:AAH6VRpNCyQd9x9sW6CLm6q0q4ibUgYBfnM diff --git a/.env.development b/.env.development index 40806ac..6e49486 100644 --- a/.env.development +++ b/.env.development @@ -7,5 +7,12 @@ NEXT_PUBLIC_PUBLIC_URL=https://localhost:3003 # DATABASE=mysql://cart:cartpw@192.168.0.10:3306/cart_dev DATABASE=mysql://cart:cartpw@localhost:3306/cart + +EMAIL_SENDER='"ССОМ [ТЕСТ] " ' +# MAILTRAP_HOST_BULK=bulk.smtp.mailtrap.io +# MAILTRAP_HOST=sandbox.smtp.mailtrap.io +# MAILTRAP_USER=8ec69527ff2104 +# MAILTRAP_PASS=c7bc05f171c96c + SSL_KEY=./certificates/localhost-key.pem SSL_CERT=./certificates/localhost.pem diff --git a/.env.production b/.env.production index 82f44eb..5431048 100644 --- a/.env.production +++ b/.env.production @@ -7,9 +7,15 @@ NEXT_PUBLIC_PUBLIC_URL= https://sofia.mwitnessing.com NEXTAUTH_SECRET=1dd8a5457970d1dda50600be28e935ecc4513ff27c49c431849e6746f158d638 # ? do we need to duplicate this? already defined in the deoployment yml file DATABASE=mysql://jwpwsofia:dwxhns9p9vp248V39xJyRthUsZ2gR9@mariadb:3306/jwpwsofia +# DATABASE=mysql://cart:cartpw@localhost:3306/cart -MAILTRAP_HOST_BULK=bulk.smtp.mailtrap.io -MAILTRAP_HOST=live.smtp.mailtrap.io -MAILTRAP_USER=api -MAILTRAP_PASS=1cfe82e747b8dc3390ed08bb16e0f48d \ No newline at end of file +EMAIL_BYPASS_TO= +EMAIL_SENDER='"Специално Свидетелстване София" ' +EMAIL_SERVICE=gmail +EMAIL_GMAIL_USERNAME=mwitnessing +EMAIL_GMAIL_APP_PASS="acys uzsp eere qzyh" +# MAILTRAP_HOST_BULK=bulk.smtp.mailtrap.io +# MAILTRAP_HOST=live.smtp.mailtrap.io +# MAILTRAP_USER=api +# MAILTRAP_PASS=1cfe82e747b8dc3390ed08bb16e0f48d \ No newline at end of file diff --git a/.env.test b/.env.test index 6a513e6..94abc74 100644 --- a/.env.test +++ b/.env.test @@ -10,26 +10,14 @@ NEXTAUTH_SECRET=1dd8a5457970d1dda50600be28e935ecc4513ff27c49c431849e6746f158d638 # ? do we need to duplicate this? already defined in the deoployment yml file DATABASE=mysql://jwpwsofia_demo:dwxhns9p9vp248@mariadb:3306/jwpwsofia_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_SERVICE=mailtrap MAILTRAP_HOST_BULK=bulk.smtp.mailtrap.io MAILTRAP_HOST=live.smtp.mailtrap.io MAILTRAP_USER=api diff --git a/_deploy/deoloy.azure.production.yml b/_deploy/deoloy.azure.production.yml index 7f8bcdb..eb32023 100644 --- a/_deploy/deoloy.azure.production.yml +++ b/_deploy/deoloy.azure.production.yml @@ -19,7 +19,7 @@ services: - GIT_USERNAME=deploy - GIT_PASSWORD=L3Kr2R438u4F7 command: sh -c " cd /app && npm install && npm run prod; tail -f /dev/null" - #command: sh -c " cd /app && n + #command: sh -c " cd /app && tail -f /dev/null" tty: true stdin_open: true restart: always diff --git a/_deploy/entrypoint.sh b/_deploy/entrypoint.sh index f0ea095..db16b09 100644 --- a/_deploy/entrypoint.sh +++ b/_deploy/entrypoint.sh @@ -27,13 +27,15 @@ if [ "$UPDATE_CODE_FROM_GIT" = "true" ]; then rsync -av /tmp/clone/package.json /app/package.json || echo "Rsync failed: Issue copying package.json" rsync -av /tmp/clone/package-lock.json /app/package-lock.json || echo "Rsync failed: Issue copying package-lock.json" rm -rf /app/node_modules - cd /app - npm install --no-audit --no-fund --no-optional --omit=optional yes | npx prisma generate else echo "Package files have not changed. Skipping package installation." fi + cd /app + npm install --no-audit --no-fund --no-optional --omit=optional + npx next build + # Clean up rm -rf /tmp/clone echo "Update process completed." diff --git a/_deploy/setupAppleId.mjs b/_deploy/setupAppleId.mjs index ef22074..7ff3383 100644 --- a/_deploy/setupAppleId.mjs +++ b/_deploy/setupAppleId.mjs @@ -4,14 +4,14 @@ import { SignJWT } from "jose" import { createPrivateKey } from "crypto" if (process.argv.includes("--help") || process.argv.includes("-h")) { - console.log(` + console.log(` Creates a JWT from the components found at Apple. By default, the JWT has a 6 months expiry date. Read more: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048 Usage: node apple.mjs [--kid] [--iss] [--private_key] [--sub] [--expires_in] [--exp] - APPLE_ID=com.mwhitnessing.sofia + APPLE_APP_ID=com.mwhitnessing.sofia APPLE_TEAM_ID=XC57P9SXDK APPLE_KEY_ID=TB3V355G5Y APPLE_KEY @@ -37,45 +37,45 @@ eyJhbGciOiJFUzI1NiIsImtpZCI6IlRCM1YzNTVHNVkifQ.eyJhdWQiOiJodHRwczovL2FwcGxlaWQuY --exp Future date in seconds when the JWT expires `) } else { - const args = process.argv.slice(2).reduce((acc, arg, i) => { - if (arg.match(/^--\w/)) { - const key = arg.replace(/^--/, "").toLowerCase() - acc[key] = process.argv[i + 3] - } - return acc - }, {}) + const args = process.argv.slice(2).reduce((acc, arg, i) => { + if (arg.match(/^--\w/)) { + const key = arg.replace(/^--/, "").toLowerCase() + acc[key] = process.argv[i + 3] + } + return acc + }, {}) - const { - team_id, - iss = team_id, + const { + team_id, + iss = team_id, - private_key, + private_key, - client_id, - sub = client_id, + client_id, + sub = client_id, - key_id, - kid = key_id, + key_id, + kid = key_id, - expires_in = 86400 * 180, - exp = Math.ceil(Date.now() / 1000) + expires_in, - } = args + expires_in = 86400 * 180, + exp = Math.ceil(Date.now() / 1000) + expires_in, + } = args - /** - * How long is the secret valid in seconds. - * @default 15780000 - */ - const expiresAt = Math.ceil(Date.now() / 1000) + expires_in - const expirationTime = exp ?? expiresAt - console.log(` + /** + * How long is the secret valid in seconds. + * @default 15780000 + */ + const expiresAt = Math.ceil(Date.now() / 1000) + expires_in + const expirationTime = exp ?? expiresAt + console.log(` Apple client secret generated. Valid until: ${new Date(expirationTime * 1000)} ${await new SignJWT({}) - .setAudience("https://appleid.apple.com") - .setIssuer(iss) - .setIssuedAt() - .setExpirationTime(expirationTime) - .setSubject(sub) - .setProtectedHeader({ alg: "ES256", kid }) - .sign(createPrivateKey(private_key.replace(/\\n/g, "\n")))}`) + .setAudience("https://appleid.apple.com") + .setIssuer(iss) + .setIssuedAt() + .setExpirationTime(expirationTime) + .setSubject(sub) + .setProtectedHeader({ alg: "ES256", kid }) + .sign(createPrivateKey(private_key.replace(/\\n/g, "\n")))}`) } \ No newline at end of file diff --git a/_doc/ToDo.md b/_doc/ToDo.md index 93f88cb..9c64117 100644 --- a/_doc/ToDo.md +++ b/_doc/ToDo.md @@ -207,6 +207,18 @@ push notifications store replacement test email + problem with my repeating availability3 + relax add/remove transport for publishers +fix published schedule to cover end of the week + +имейлите - ОК +графика - синк - ОК +вестителите от Фабио - +потребителите с двойни имейли - + + + админс can send *urgent* email to everybody to ask for shift +in schedule admin - if a publisher is always pair & family is not in the shift - add + button to add them постоянен лог лог ако е изрит потребител. diff --git a/_doc/apple-gen-secret.mjs b/_doc/apple-gen-secret.mjs deleted file mode 100644 index 4a6600c..0000000 --- a/_doc/apple-gen-secret.mjs +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/node -# https://gist.githubusercontent.com/balazsorban44/09613175e7b37ec03f676dcefb7be5eb/raw/b0d31aa0c7f58e0088fdf59ec30cad1415a3475b/apple-gen-secret.mjs - -import { SignJWT } from "jose" -import { createPrivateKey } from "crypto" - -if (process.argv.includes("--help") || process.argv.includes("-h")) { - console.log(` - Creates a JWT from the components found at Apple. - By default, the JWT has a 6 months expiry date. - Read more: https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048 - - Usage: - node apple.mjs [--kid] [--iss] [--private_key] [--sub] [--expires_in] [--exp] - - Options: - --help Print this help message - --kid, --key_id The key id of the private key - --iss, --team_id The Apple team ID - --private_key The private key to use to sign the JWT. (Starts with -----BEGIN PRIVATE KEY-----) - --sub, --client_id The client id to use in the JWT. - --expires_in Number of seconds from now when the JWT should expire. Defaults to 6 months. - --exp Future date in seconds when the JWT expires - `) -} else { - const args = process.argv.slice(2).reduce((acc, arg, i) => { - if (arg.match(/^--\w/)) { - const key = arg.replace(/^--/, "").toLowerCase() - acc[key] = process.argv[i + 3] - } - return acc - }, {}) - - const { - team_id, - iss = team_id, - - private_key, - - client_id, - sub = client_id, - - key_id, - kid = key_id, - - expires_in = 86400 * 180, - exp = Math.ceil(Date.now() / 1000) + expires_in, - } = args - - /** - * How long is the secret valid in seconds. - * @default 15780000 - */ - const expiresAt = Math.ceil(Date.now() / 1000) + expires_in - const expirationTime = exp ?? expiresAt - console.log(` -Apple client secret generated. Valid until: ${new Date(expirationTime * 1000)} - -${await new SignJWT({}) - .setAudience("https://appleid.apple.com") - .setIssuer(iss) - .setIssuedAt() - .setExpirationTime(expirationTime) - .setSubject(sub) - .setProtectedHeader({ alg: "ES256", kid }) - .sign(createPrivateKey(private_key.replace(/\\n/g, "\n")))}`) -} \ No newline at end of file diff --git a/components/PwaManager.tsx b/components/PwaManager.tsx index 1eae6ce..3bce4fc 100644 --- a/components/PwaManager.tsx +++ b/components/PwaManager.tsx @@ -151,7 +151,7 @@ function PwaManager() { return; } - await fetch('/api/notification', { + await fetch('/api/notify', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -219,6 +219,11 @@ function PwaManager() { Телеграм +
+ + Apple sign-in + +
); diff --git a/components/availability/AvailabilityForm.js b/components/availability/AvailabilityForm.js index 721df18..ce2ce5f 100644 --- a/components/availability/AvailabilityForm.js +++ b/components/availability/AvailabilityForm.js @@ -10,6 +10,8 @@ import { bgBG } from '../x-date-pickers/locales/bgBG'; import { ToastContainer } from 'react-toastify'; const common = require('src/helpers/common'); //todo import Availability type from prisma schema +import { isBefore, addMinutes, isAfter, isEqual, set, getHours, getMinutes, getSeconds } from 'date-fns'; + const fetchConfig = async () => { @@ -25,6 +27,7 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o indexUrl: "/cart/availabilities" }; + const id = parseInt(router.query.id); //coalsce existingItems to empty array existingItems = existingItems || []; @@ -74,7 +77,6 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o const fetchItemFromDB = async () => { - const id = parseInt(router.query.id); if (existingItems.length == 0 && id) { try { const response = await axiosInstance.get(`/api/data/availabilities/${id}`); @@ -183,59 +185,6 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o return groupedIntervals; } - // // const firstSlotWithTransport = timeSlots[0].checked && timeSlots[0]?.isWithTransport; - // // const lastSlotWithTransport = timeSlots[timeSlots.length - 1].checked && timeSlots[timeSlots.length - 1]?.isWithTransport; - // function createAvailabilityFromGroup(group) { - // let startTime = new Date(day); - // startTime.setHours(group[0].startTime.getHours(), group[0].startTime.getMinutes(), group[0].startTime.getSeconds(), 0); - - // let endTime = new Date(day); - // endTime.setHours(group[group.length - 1].endTime.getHours(), group[group.length - 1].endTime.getMinutes(), group[group.length - 1].endTime.getSeconds(), 0); - - - // return { - // name: common.getTimeFomatted(startTime) + "-" + common.getTimeFomatted(endTime), - // publisherId: publisher.id, - // startTime: startTime, - // endTime: endTime, - // isWithTransportIn: group[0].isFirst && timeSlots[0].isWithTransport, - // isWithTransportOut: group[group.length - 1].isLast && timeSlots[timeSlots.length - 1].isWithTransport, - // dayofweek: common.getDayOfWeekNameEnEnumForDate(day.getDay()), - // repeatWeekly: doRepeat, - // dayOfMonth: doRepeat ? null : startTime.getDate(), - // endDate: doRepeat ? repeatUntil : null, - // dateOfEntry: new Date(), - // }; - // } - - // function updateAvailabilityFromGroup(availability, group) { - // availability.startTime.setTime(group[0].startTime); - // availability.endTime.setTime(group[group.length - 1].endTime); - // availability.name = common.getTimeFomatted(availability.startTime) + "-" + common.getTimeFomatted(availability.endTime); - - // availability.isWithTransportIn = group[0].isFirst && timeSlots[0].isWithTransport; - // availability.isWithTransportOut = group[group.length - 1].isLast && timeSlots[timeSlots.length - 1].isWithTransport; - - // delete availability.weekOfMonth; - // if (doRepeat) { - // availability.repeatWeekly = true; - // availability.dayOfMonth = null; - // availability.weekOfMonth = 0; - // availability.endDate = repeatUntil; - // } else { - // availability.repeatWeekly = false; - // availability.dayOfMonth = availability.startTime.getDate(); - // availability.endDate = null; - // } - - // availability.dateOfEntry = new Date(); - // if (availability.parentAvailabilityId) { - // availability.parentAvailability = { connect: { id: parentAvailabilityId } }; - // } - // delete availability.parentAvailabilityId; - - // return availability; - // } // Common function to set shared properties function setSharedAvailabilityProperties(availability, group, timeSlots) { let startTime = new Date(availability.startTime || day); @@ -263,7 +212,7 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o availability.dayOfMonth = startTime.getDate(); availability.endDate = null; } - + availability.isFromPreviousMonth = false; availability.dateOfEntry = new Date(); } @@ -332,22 +281,25 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o } // console.log("AvailabilityForm: publisherId: " + publisher.id + ", id: " + availabilit .id, ", inline: " + isInline); - + //ToDo: this is examplary function to be used in the future. replace all date/time related functions with this one const generateTimeSlots = (start, end, increment, items) => { const slots = []; - let currentTime = start.getTime(); + let currentTime = start; - const endTime = end.getTime(); + const baseDate = new Date(2000, 0, 1); // Use a constant date for all time comparisons - while (currentTime < endTime) { - let slotStart = new Date(currentTime); - let slotEnd = new Date(currentTime + increment * 60000); // increment is in minutes + while (isBefore(currentTime, end)) { + let slotStart = normalizeTime(currentTime, baseDate); + let slotEnd = normalizeTime(addMinutes(currentTime, increment), baseDate); - const isChecked = items.some(item => - item.startTime && item.endTime && - (slotStart.getTime() < item.endTime.getTime()) && - (slotEnd.getTime() > item.startTime.getTime()) - ); + const isChecked = items.some(item => { + let itemStart = item.startTime ? normalizeTime(new Date(item.startTime), baseDate) : null; + let itemEnd = item.endTime ? normalizeTime(new Date(item.endTime), baseDate) : null; + + return itemStart && itemEnd && + (slotStart.getTime() < itemEnd.getTime()) && + (slotEnd.getTime() > itemStart.getTime()); + }); slots.push({ startTime: slotStart, @@ -355,10 +307,9 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o isChecked: isChecked, }); - currentTime += increment * 60000; // Increment in milliseconds (minutes to milliseconds) + currentTime = addMinutes(currentTime, increment); } - // Optional: Add isFirst, isLast, and isWithTransport properties if (slots.length > 0 && items?.length > 0) { slots[0].isFirst = true; slots[slots.length - 1].isLast = true; @@ -369,6 +320,16 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o return slots; }; + // Normalize the time part of a date by using a base date + function normalizeTime(date, baseDate) { + return set(baseDate, { + hours: getHours(date), + minutes: getMinutes(date), + seconds: getSeconds(date), + milliseconds: 0 + }); + } + const TimeSlotCheckboxes = ({ slots, setSlots, items: [] }) => { const [allDay, setAllDay] = useState(slots.every(slot => slot.isChecked)); const handleAllDayChange = (e) => { @@ -467,13 +428,14 @@ export default function AvailabilityForm({ publisherId, existingItems, inline, o

- {editMode ? "Редактирай" : "Нова"} възможност + {editMode ? "Редактирай" : "Нова"} възможност: {common.getDateFormatedShort(day)}

-
+ {/*
setDay({ value })} /> -
+
*/} +