new table for settings and store blocked date there;
non admins can't enter avs before the blocked date new table for survey
This commit is contained in:
@ -259,7 +259,7 @@ in schedule admin - if a publisher is always pair & family is not in the shift -
|
|||||||
[] fix transport UI
|
[] fix transport UI
|
||||||
[] revise import/export to word
|
[] revise import/export to word
|
||||||
[] allow keyman/scheduler role
|
[] allow keyman/scheduler role
|
||||||
[] allow blocking of inputs (different from publishing)
|
[] allow blocking of inputs (different from publishing) TODO: fix to keep previous occurances when repeating evert week
|
||||||
[] user - add createdAt field
|
[] user - add createdAt field
|
||||||
|
|
||||||
[] FIX insecure logins
|
[] FIX insecure logins
|
@ -17,11 +17,22 @@ export default function AvailabilityList({ publisher, showNew }) {
|
|||||||
const [showAv, setShowAv] = useState(showNew || false);
|
const [showAv, setShowAv] = useState(showNew || false);
|
||||||
const [selectedItem, setSelectedItem] = useState(null);
|
const [selectedItem, setSelectedItem] = useState(null);
|
||||||
const [items, setItems] = useState(publisher.availabilities); // Convert items prop to state
|
const [items, setItems] = useState(publisher.availabilities); // Convert items prop to state
|
||||||
|
const [blockedAvailabilityDate, setBlockedAvailabilityDate] = useState(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('items set to:', items?.map(item => item.id));
|
console.log('items set to:', items?.map(item => item.id));
|
||||||
}, [items])
|
}, [items])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
axiosInstance.get(`/api/?action=settings&key=AvailabilityBlockDate`)
|
||||||
|
.then(({ data }) => {
|
||||||
|
setBlockedAvailabilityDate(new Date(data.value));
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("Error getting blocked date:", error);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
const toggleAv = () => setShowAv(!showAv);
|
const toggleAv = () => setShowAv(!showAv);
|
||||||
const editAvailability = (item) => {
|
const editAvailability = (item) => {
|
||||||
setSelectedItem(item);
|
setSelectedItem(item);
|
||||||
@ -72,9 +83,16 @@ export default function AvailabilityList({ publisher, showNew }) {
|
|||||||
{/* <button className="bg-blue-200 hover:bg-blue-300 text-blue-600 py-1 px-2 rounded inline-flex items-center" onClick={() => editAvailability(item)}>
|
{/* <button className="bg-blue-200 hover:bg-blue-300 text-blue-600 py-1 px-2 rounded inline-flex items-center" onClick={() => editAvailability(item)}>
|
||||||
<PencilSquareIcon className="h-6 w-6" />
|
<PencilSquareIcon className="h-6 w-6" />
|
||||||
</button> */}
|
</button> */}
|
||||||
|
{(blockedAvailabilityDate && new Date(item.startTime) < blockedAvailabilityDate) ? (
|
||||||
|
<button className="disabled bg-gray-200 hover:bg-gray-300 text-gray-600 py-1 px-2 rounded inline-flex items-center">
|
||||||
|
<TrashIcon className="h-6 w-6" />
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
<button className="bg-red-200 hover:bg-red-300 text-red-600 py-1 px-2 rounded ml-2 inline-flex items-center" onClick={() => deleteAvailability(item.id)}>
|
<button className="bg-red-200 hover:bg-red-300 text-red-600 py-1 px-2 rounded ml-2 inline-flex items-center" onClick={() => deleteAvailability(item.id)}>
|
||||||
<TrashIcon className="h-6 w-6" />
|
<TrashIcon className="h-6 w-6" />
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
72
package-lock.json
generated
72
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pwwa",
|
"name": "smws",
|
||||||
"version": "1.2.2",
|
"version": "1.2.4",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pwwa",
|
"name": "smws",
|
||||||
"version": "1.2.2",
|
"version": "1.2.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@auth/prisma-adapter": "^1.4.0",
|
"@auth/prisma-adapter": "^1.4.0",
|
||||||
"@emotion/react": "^11.11.3",
|
"@emotion/react": "^11.11.3",
|
||||||
@ -16,7 +16,7 @@
|
|||||||
"@mui/material": "^5.15.10",
|
"@mui/material": "^5.15.10",
|
||||||
"@mui/x-date-pickers": "^6.19.4",
|
"@mui/x-date-pickers": "^6.19.4",
|
||||||
"@premieroctet/next-crud": "^3.0.0",
|
"@premieroctet/next-crud": "^3.0.0",
|
||||||
"@prisma/client": "^5.13.0",
|
"@prisma/client": "^5.15.0",
|
||||||
"@react-pdf/renderer": "^3.3.8",
|
"@react-pdf/renderer": "^3.3.8",
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
"@types/multer": "^1.4.11",
|
"@types/multer": "^1.4.11",
|
||||||
@ -99,7 +99,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"depcheck": "^1.4.7",
|
"depcheck": "^1.4.7",
|
||||||
"prisma": "^5.13.0"
|
"prisma": "^5.15.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@alloc/quick-lru": {
|
"node_modules/@alloc/quick-lru": {
|
||||||
@ -3914,9 +3914,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/client": {
|
"node_modules/@prisma/client": {
|
||||||
"version": "5.13.0",
|
"version": "5.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.15.0.tgz",
|
||||||
"integrity": "sha512-uYdfpPncbZ/syJyiYBwGZS8Gt1PTNoErNYMuqHDa2r30rNSFtgTA/LXsSk55R7pdRTMi5pHkeP9B14K6nHmwkg==",
|
"integrity": "sha512-wPTeTjbd2Q0abOeffN7zCDCbkp9C9cF+e9HPiI64lmpehyq2TepgXE+sY7FXr7Rhbb21prLMnhXX27/E11V09w==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.13"
|
"node": ">=16.13"
|
||||||
@ -3931,39 +3931,39 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/debug": {
|
"node_modules/@prisma/debug": {
|
||||||
"version": "5.13.0",
|
"version": "5.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.15.0.tgz",
|
||||||
"integrity": "sha512-699iqlEvzyCj9ETrXhs8o8wQc/eVW+FigSsHpiskSFydhjVuwTJEfj/nIYqTaWFYuxiWQRfm3r01meuW97SZaQ==",
|
"integrity": "sha512-QpEAOjieLPc/4sMny/WrWqtpIAmBYsgqwWlWwIctqZO0AbhQ9QcT6x2Ut3ojbDo/pFRCCA1Z1+xm2MUy7fAkZA==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines": {
|
"node_modules/@prisma/engines": {
|
||||||
"version": "5.13.0",
|
"version": "5.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.15.0.tgz",
|
||||||
"integrity": "sha512-hIFLm4H1boj6CBZx55P4xKby9jgDTeDG0Jj3iXtwaaHmlD5JmiDkZhh8+DYWkTGchu+rRF36AVROLnk0oaqhHw==",
|
"integrity": "sha512-hXL5Sn9hh/ZpRKWiyPA5GbvF3laqBHKt6Vo70hYqqOhh5e0ZXDzHcdmxNvOefEFeqxra2DMz2hNbFoPvqrVe1w==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "5.13.0",
|
"@prisma/debug": "5.15.0",
|
||||||
"@prisma/engines-version": "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b",
|
"@prisma/engines-version": "5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022",
|
||||||
"@prisma/fetch-engine": "5.13.0",
|
"@prisma/fetch-engine": "5.15.0",
|
||||||
"@prisma/get-platform": "5.13.0"
|
"@prisma/get-platform": "5.15.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/engines-version": {
|
"node_modules/@prisma/engines-version": {
|
||||||
"version": "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b",
|
"version": "5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022.tgz",
|
||||||
"integrity": "sha512-AyUuhahTINGn8auyqYdmxsN+qn0mw3eg+uhkp8zwknXYIqoT3bChG4RqNY/nfDkPvzWAPBa9mrDyBeOnWSgO6A==",
|
"integrity": "sha512-3BEgZ41Qb4oWHz9kZNofToRvNeS4LZYaT9pienR1gWkjhky6t6K1NyeWNBkqSj2llgraUNbgMOCQPY4f7Qp5wA==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/fetch-engine": {
|
"node_modules/@prisma/fetch-engine": {
|
||||||
"version": "5.13.0",
|
"version": "5.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.15.0.tgz",
|
||||||
"integrity": "sha512-Yh4W+t6YKyqgcSEB3odBXt7QyVSm0OQlBSldQF2SNXtmOgMX8D7PF/fvH6E6qBCpjB/yeJLy/FfwfFijoHI6sA==",
|
"integrity": "sha512-z6AY5yyXxc20Klj7wwnfGP0iIUkVKzybqapT02zLYR/nf9ynaeN8bq73WRmi1TkLYn+DJ5Qy+JGu7hBf1pE78A==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "5.13.0",
|
"@prisma/debug": "5.15.0",
|
||||||
"@prisma/engines-version": "5.13.0-23.b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b",
|
"@prisma/engines-version": "5.15.0-29.12e25d8d06f6ea5a0252864dd9a03b1bb51f3022",
|
||||||
"@prisma/get-platform": "5.13.0"
|
"@prisma/get-platform": "5.15.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/generator-helper": {
|
"node_modules/@prisma/generator-helper": {
|
||||||
@ -3980,12 +3980,12 @@
|
|||||||
"integrity": "sha512-tZ+MOjWlVvz1kOEhNYMa4QUGURY+kgOUBqLHYIV8jmCsMuvA1tWcn7qtIMLzYWCbDcQT4ZS8xDgK0R2gl6/0wA=="
|
"integrity": "sha512-tZ+MOjWlVvz1kOEhNYMa4QUGURY+kgOUBqLHYIV8jmCsMuvA1tWcn7qtIMLzYWCbDcQT4ZS8xDgK0R2gl6/0wA=="
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/get-platform": {
|
"node_modules/@prisma/get-platform": {
|
||||||
"version": "5.13.0",
|
"version": "5.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.15.0.tgz",
|
||||||
"integrity": "sha512-B/WrQwYTzwr7qCLifQzYOmQhZcFmIFhR81xC45gweInSUn2hTEbfKUPd2keAog+y5WI5xLAFNJ3wkXplvSVkSw==",
|
"integrity": "sha512-1GULDkW4+/VQb73vihxCBSc4Chc2x88MA+O40tcZFjmBzG4/fF44PaXFxUqKSFltxU9L9GIMLhh0Gfkk/pUbtg==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/debug": "5.13.0"
|
"@prisma/debug": "5.15.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@prisma/internals": {
|
"node_modules/@prisma/internals": {
|
||||||
@ -15118,13 +15118,13 @@
|
|||||||
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
"integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew=="
|
||||||
},
|
},
|
||||||
"node_modules/prisma": {
|
"node_modules/prisma": {
|
||||||
"version": "5.13.0",
|
"version": "5.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/prisma/-/prisma-5.15.0.tgz",
|
||||||
"integrity": "sha512-kGtcJaElNRAdAGsCNykFSZ7dBKpL14Cbs+VaQ8cECxQlRPDjBlMHNFYeYt0SKovAVy2Y65JXQwB3A5+zIQwnTg==",
|
"integrity": "sha512-JA81ACQSCi3a7NUOgonOIkdx8PAVkO+HbUOxmd00Yb8DgIIEpr2V9+Qe/j6MLxIgWtE/OtVQ54rVjfYRbZsCfw==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/engines": "5.13.0"
|
"@prisma/engines": "5.15.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"prisma": "build/index.js"
|
"prisma": "build/index.js"
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
"@mui/material": "^5.15.10",
|
"@mui/material": "^5.15.10",
|
||||||
"@mui/x-date-pickers": "^6.19.4",
|
"@mui/x-date-pickers": "^6.19.4",
|
||||||
"@premieroctet/next-crud": "^3.0.0",
|
"@premieroctet/next-crud": "^3.0.0",
|
||||||
"@prisma/client": "^5.13.0",
|
"@prisma/client": "^5.15.0",
|
||||||
"@react-pdf/renderer": "^3.3.8",
|
"@react-pdf/renderer": "^3.3.8",
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
"@types/multer": "^1.4.11",
|
"@types/multer": "^1.4.11",
|
||||||
@ -117,6 +117,6 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"depcheck": "^1.4.7",
|
"depcheck": "^1.4.7",
|
||||||
"prisma": "^5.13.0"
|
"prisma": "^5.15.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -64,6 +64,50 @@ export default async function handler(req, res) {
|
|||||||
res.status(200).json({ message: "SQL script executed successfully" });
|
res.status(200).json({ message: "SQL script executed successfully" });
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "settings":
|
||||||
|
try {
|
||||||
|
const key = req.query.key;
|
||||||
|
switch (req.method) {
|
||||||
|
case "LIST":
|
||||||
|
let s1 = await prisma.settings.findMany();
|
||||||
|
res.status(200).json(s1.map(setting => setting.key));
|
||||||
|
break;
|
||||||
|
case "GET":
|
||||||
|
const s2 = await prisma.settings.findUnique({
|
||||||
|
where: {
|
||||||
|
key: key
|
||||||
|
}
|
||||||
|
});
|
||||||
|
res.status(200).json(s2);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "PUT": //create or update
|
||||||
|
const value = req.query.value;
|
||||||
|
const results = await prisma.settings.upsert({
|
||||||
|
where: {
|
||||||
|
key: key
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
value: value
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
key: key,
|
||||||
|
value: value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
res.status(200).json(results);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
res.status(405).json({ message: "Method Not Allowed" });
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error getting settings: " + error);
|
||||||
|
res.status(500).json({ error });
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case "deleteAllPublishers":
|
case "deleteAllPublishers":
|
||||||
//get filter and delete all publishers containing that in first name or last name
|
//get filter and delete all publishers containing that in first name or last name
|
||||||
await prisma.publisher.deleteMany({
|
await prisma.publisher.deleteMany({
|
||||||
|
@ -62,6 +62,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
|||||||
const [allShifts, setAllShifts] = useState(initialShifts);
|
const [allShifts, setAllShifts] = useState(initialShifts);
|
||||||
const [isPublished, setIsPublished] = useState(() => initialShifts.some(shift => shift.isPublished));
|
const [isPublished, setIsPublished] = useState(() => initialShifts.some(shift => shift.isPublished));
|
||||||
const [value, onChange] = useState<Date>(new Date());
|
const [value, onChange] = useState<Date>(new Date());
|
||||||
|
const [selectedMonth, setSelectedMonth] = useState(new Date().getMonth());
|
||||||
const [shifts, setShifts] = React.useState([]);
|
const [shifts, setShifts] = React.useState([]);
|
||||||
const [error, setError] = React.useState(null);
|
const [error, setError] = React.useState(null);
|
||||||
const [availablePubs, setAvailablePubs] = React.useState([]);
|
const [availablePubs, setAvailablePubs] = React.useState([]);
|
||||||
@ -89,7 +90,6 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
|||||||
handleCalDateChange(value); // Call handleCalDateChange whenever isCheckboxChecked changes
|
handleCalDateChange(value); // Call handleCalDateChange whenever isCheckboxChecked changes
|
||||||
}, [filterShowWithoutAssignments]); // Dependency array
|
}, [filterShowWithoutAssignments]); // Dependency array
|
||||||
|
|
||||||
const [selectedMonth, setSelectedMonth] = useState(new Date().getMonth());
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newMonth = value.getMonth();
|
const newMonth = value.getMonth();
|
||||||
if (newMonth !== selectedMonth) {
|
if (newMonth !== selectedMonth) {
|
||||||
@ -607,6 +607,29 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
model Settings {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
key String
|
||||||
|
value String
|
||||||
|
description String?
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
async function setAvailabilityBlockDate(AvailabilityBlockDate: Date): Promise<void> {
|
||||||
|
// set AvailabilityBlockDate to the selected date
|
||||||
|
let monthInfo = common.getMonthInfo(value);
|
||||||
|
await axiosInstance.put(`/api/?action=settings&key=AvailabilityBlockDate&value=${common.getISODateOnly(monthInfo.lastSunday)}`)
|
||||||
|
.then((response) => {
|
||||||
|
console.log("AvailabilityBlockDate set to:", response.data);
|
||||||
|
// setShifts([...shifts, response.data]);
|
||||||
|
handleCalDateChange(value);
|
||||||
|
}
|
||||||
|
).catch((error) => {
|
||||||
|
console.error("Error setting AvailabilityBlockDate:", error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Layout>
|
<Layout>
|
||||||
@ -715,8 +738,9 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
|||||||
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={generateXLS}><i className="fas fa-file-excel mr-2"></i> Генерирай XLSX</button>
|
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={generateXLS}><i className="fas fa-file-excel mr-2"></i> Генерирай XLSX</button>
|
||||||
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={fetchShifts}>
|
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={fetchShifts}>
|
||||||
{isLoading('fetchShifts') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-sync-alt mr-2"></i>)} презареди</button>
|
{isLoading('fetchShifts') ? (<i className="fas fa-sync-alt fa-spin mr-2"></i>) : (<i className="fas fa-sync-alt mr-2"></i>)} презареди</button>
|
||||||
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={generateMonthlyStatistics}><i className="fas fa-chart-bar mr-2"></i> Генерирай статистика</button>
|
{/* <button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={generateMonthlyStatistics}><i className="fas fa-chart-bar mr-2"></i> Генерирай статистика</button>
|
||||||
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={copyOldAvailabilities}><i className="fas fa-copy mr-2"></i> Прехвърли предпочитанията</button>
|
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={copyOldAvailabilities}><i className="fas fa-copy mr-2"></i> Прехвърли предпочитанията</button> */}
|
||||||
|
<button className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100" onClick={setAvailabilityBlockDate}><i className="fas fa-copy mr-2"></i> Блокирай предпочитанията до края на {selectedMonth + 1} м.</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -795,7 +819,7 @@ export default function CalendarPage({ initialEvents, initialShifts }) {
|
|||||||
{pub.canTransport && (<LocalShippingIcon className="mx-2 text-gray-500" />)}
|
{pub.canTransport && (<LocalShippingIcon className="mx-2 text-gray-500" />)}
|
||||||
</span>
|
</span>
|
||||||
<div className="flex space-x-1 overflow-hidden">
|
<div className="flex space-x-1 overflow-hidden">
|
||||||
<span title="Възможност: часове | дни" className={`badge py-1 px-2 rounded-md text-xs ${pub.currentMonthAvailabilityHoursCount || pub.currentMonthAvailabilityDaysCount ? 'bg-teal-500 text-white' : 'bg-teal-200 text-gray-300'} hover:underline`} >
|
<span title="Възможност: дни | часове" className={`badge py-1 px-2 rounded-md text-xs ${pub.currentMonthAvailabilityHoursCount || pub.currentMonthAvailabilityDaysCount ? 'bg-teal-500 text-white' : 'bg-teal-200 text-gray-300'} hover:underline`} >
|
||||||
{pub.currentMonthAvailabilityDaysCount || 0} | {pub.currentMonthAvailabilityHoursCount || 0}
|
{pub.currentMonthAvailabilityDaysCount || 0} | {pub.currentMonthAvailabilityHoursCount || 0}
|
||||||
</span>
|
</span>
|
||||||
<span title="участия тази седмица" className={`badge py-1 px-2 rounded-full text-xs ${pub.currentWeekAssignments ? 'bg-yellow-500 text-white' : 'bg-yellow-200 text-gray-400'}`}>{pub.currentWeekAssignments || 0}</span>
|
<span title="участия тази седмица" className={`badge py-1 px-2 rounded-full text-xs ${pub.currentWeekAssignments ? 'bg-yellow-500 text-white' : 'bg-yellow-200 text-gray-400'}`}>{pub.currentWeekAssignments || 0}</span>
|
||||||
|
@ -253,7 +253,7 @@ function ContactsPage({ allPublishers }) {
|
|||||||
<>
|
<>
|
||||||
<td className="border-b p-4">
|
<td className="border-b p-4">
|
||||||
{pub.availabilities.length > 0 ? (
|
{pub.availabilities.length > 0 ? (
|
||||||
<span title="Възможност: часове | дни" className={`badge py-1 px-2 rounded-md text-xs ${pub.currentMonthAvailabilityHoursCount || pub.currentMonthAvailabilityDaysCount ? 'bg-teal-500 text-white' : 'bg-teal-200 text-gray-300'} hover:underline`}>
|
<span title="Възможност: дни | часове" className={`badge py-1 px-2 rounded-md text-xs ${pub.currentMonthAvailabilityHoursCount || pub.currentMonthAvailabilityDaysCount ? 'bg-teal-500 text-white' : 'bg-teal-200 text-gray-300'} hover:underline`}>
|
||||||
{pub.currentMonthAvailabilityDaysCount} | {pub.currentMonthAvailabilityHoursCount}
|
{pub.currentMonthAvailabilityDaysCount} | {pub.currentMonthAvailabilityHoursCount}
|
||||||
</span>
|
</span>
|
||||||
) : <span title="Няма възможности" className="badge py-1 px-2 rounded-md text-xs bg-gray-300 text-gray-500">0</span>}
|
) : <span title="Няма възможности" className="badge py-1 px-2 rounded-md text-xs bg-gray-300 text-gray-500">0</span>}
|
||||||
|
@ -270,7 +270,7 @@ export const getServerSideProps = async (context) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
cartEvents = common.convertDatesToISOStrings(cartEvents);
|
cartEvents = common.convertDatesToISOStrings(cartEvents);
|
||||||
const lastPublishedDate = (await prisma.shift.findFirst({
|
let lastPublishedDate = (await prisma.shift.findFirst({
|
||||||
where: {
|
where: {
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
},
|
},
|
||||||
@ -280,7 +280,17 @@ export const getServerSideProps = async (context) => {
|
|||||||
orderBy: {
|
orderBy: {
|
||||||
endTime: 'desc'
|
endTime: 'desc'
|
||||||
}
|
}
|
||||||
})).endTime;
|
}))?.endTime || new Date();
|
||||||
|
|
||||||
|
let blockedDate = await prisma.settings.findUnique({
|
||||||
|
where: {
|
||||||
|
key: "AvailabilityBlockDate"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (blockedDate)
|
||||||
|
blockedDate.value = new Date(blockedDate.value);
|
||||||
|
|
||||||
|
lastPublishedDate = lastPublishedDate > blockedDate.value ? lastPublishedDate : blockedDate.value;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
9
prisma/migrations/20240614185207_/migration.sql
Normal file
9
prisma/migrations/20240614185207_/migration.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `Settings` (
|
||||||
|
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||||
|
`key` VARCHAR(191) NOT NULL,
|
||||||
|
`value` VARCHAR(191) NOT NULL,
|
||||||
|
`description` VARCHAR(191) NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
- The primary key for the `settings` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||||
|
- You are about to drop the column `id` on the `settings` table. All the data in the column will be lost.
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `Settings`
|
||||||
|
DROP PRIMARY KEY,
|
||||||
|
DROP COLUMN `id`,
|
||||||
|
ADD PRIMARY KEY (`key`);
|
@ -0,0 +1,19 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `message` ADD COLUMN `answer` VARCHAR(191) NULL,
|
||||||
|
ADD COLUMN `answerDate` DATETIME(3) NULL,
|
||||||
|
ADD COLUMN `shownDate` DATETIME(3) NULL,
|
||||||
|
ADD COLUMN `surveyId` INTEGER NULL;
|
||||||
|
|
||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE `Survey` (
|
||||||
|
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||||
|
`content` VARCHAR(191) NOT NULL,
|
||||||
|
`answers` JSON NULL,
|
||||||
|
`publicFrom` DATETIME(3) NULL,
|
||||||
|
`publicUntil` DATETIME(3) NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
ALTER TABLE `Message` ADD CONSTRAINT `Message_surveyId_fkey` FOREIGN KEY (`surveyId`) REFERENCES `Survey`(`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
@ -264,6 +264,15 @@ enum MessageType {
|
|||||||
InApp
|
InApp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model Survey {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
content String
|
||||||
|
answers Json?
|
||||||
|
messages Message[]
|
||||||
|
publicFrom DateTime?
|
||||||
|
publicUntil DateTime?
|
||||||
|
}
|
||||||
|
|
||||||
model Message {
|
model Message {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
publisher Publisher @relation(fields: [publisherId], references: [id])
|
publisher Publisher @relation(fields: [publisherId], references: [id])
|
||||||
@ -274,6 +283,12 @@ model Message {
|
|||||||
isPublic Boolean @default(false)
|
isPublic Boolean @default(false)
|
||||||
type MessageType @default(Email)
|
type MessageType @default(Email)
|
||||||
publicUntil DateTime?
|
publicUntil DateTime?
|
||||||
|
shownDate DateTime?
|
||||||
|
answer String?
|
||||||
|
answerDate DateTime?
|
||||||
|
|
||||||
|
Survey Survey? @relation(fields: [surveyId], references: [id])
|
||||||
|
surveyId Int?
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EventLogType {
|
enum EventLogType {
|
||||||
@ -348,3 +363,9 @@ model VerificationToken {
|
|||||||
|
|
||||||
@@unique([identifier, token])
|
@@unique([identifier, token])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model Settings {
|
||||||
|
key String @id
|
||||||
|
value String
|
||||||
|
description String?
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user