diff --git a/server/controllers/processes/visits.js b/server/controllers/processes/visits.js index 703491c6..7f98dbee 100644 --- a/server/controllers/processes/visits.js +++ b/server/controllers/processes/visits.js @@ -543,6 +543,75 @@ router.get('/:id', async (req, res) => { res.json(data[0]) }) +router.get('/seminars/:personId', async (req, res) => { + if (!req.user) { + return res.status(401).json({ result: "Unauthorized" }); + } + + const { startDate, endDate } = req.query; + if (!startDate || !endDate) { + return res.status(400).json({ error: "startDate and endDate are required" }); + } + + const seminars = await EventSeminar.aggregate([ + { + $match: { + speakers: new ObjectId(req.params.personId), + $expr: { + $and: [ + { + $or: [ + { $eq: [new Date(endDate), null] }, + { $eq: ["$startDatetime", null] }, + { $lte: ["$startDatetime", new Date(endDate)] } + ] + }, + { + $or: [ + { $eq: [new Date(startDate), null] }, + { $eq: ["$startDatetime", null] }, + { $gte: ["$startDatetime", new Date(startDate)] } + ] + } + ] + } + } + }, + {$lookup: { + from: 'people', + localField: 'speakers', + foreignField: '_id', + as: 'speakers', + pipeline: [ + {$project: { + _id: 1, + firstName: 1, + lastName: 1, + affiliations: 1, + email: 1, + }}, + { + $lookup: { + from: 'institutions', + localField: 'affiliations', + foreignField: '_id', + as: 'affiliations', + pipeline: [ + {$project: { + _id: 1, + name: 1, + }} + ] + } + } + ] + }}, + {$sort: {"startDatetime": 1}} + ]); + + res.json({ data: seminars }); +}); + // TODO: should be "post" instead of "put" router.put('/', async (req, res) => { const payload = {...req.body} diff --git a/src/pages/Profile.js b/src/pages/Profile.js index 51cfdffc..5e8c5b63 100644 --- a/src/pages/Profile.js +++ b/src/pages/Profile.js @@ -118,7 +118,7 @@ export default function Profile() { about_en: "informazioni opzionali (in inglese) da pubblicare nella propria scheda personale", }).map(([field, label]) => field === "arxiv_orcid" - ?
+ ?
selezionare sì se il proprio profilo arXiv è stato associato al proprio profilo ORCID diff --git a/src/processes/Visit.js b/src/processes/Visit.js index 4c819475..504207b4 100644 --- a/src/processes/Visit.js +++ b/src/processes/Visit.js @@ -42,8 +42,8 @@ function VisitForm({visit, variant}) { const queryClient = useQueryClient() const [activeSection, setActiveSection] = useState(visit ? 'data' : '') const [seminar, setSeminar] = useState(null) + const [existingSeminars, setExistingSeminars] = useState(() => data.seminars || []); const user = useEngine().user - const seminars = visit.seminars const roomAssignments = visit.roomAssignments const canCreateSeminar = user.hasProcessPermission('/process/seminars') const addMessage = useEngine().addMessage @@ -53,12 +53,13 @@ function VisitForm({visit, variant}) { ? "Modifica visita inserita" : "Inserimento nuova visita"} {save();nextStep()}} edit={() => setActiveSection('data')} variant={variant} + fetchSeminars={fetchSeminars} /> { (data.requireRoom || roomAssignments?.length>0) && } - { // mostra i seminari già inseriti - seminars && - seminars.map(seminar =>
- setActiveSection(seminar._id)} - done={() => { - setActiveSection('') - save() // save visit to force notification - }} - variant={variant} - /> -
)} { // mostra il pulsante per inserire un nuovo seminario - (!seminars || seminars.length === 0) && data.requireSeminar && !seminar && canCreateSeminar && - + data.requireSeminar && !seminar && canCreateSeminar && +
@@ -101,8 +89,22 @@ function VisitForm({visit, variant}) {
- { errorVisit() &&
{errorVisit()}
} - nessun seminario inserito nel periodo della visita + { errorVisit() ? ( +
{errorVisit()}
+ ) : ( + <> + { existingSeminars.length > 0 ? ( +
+ { existingSeminars.length === 1 + ? "C'è già un seminario inserito nel periodo della visita. Per inserire comunque un nuovo seminario premere il pulsante 'Inserisci seminario'" + : "Ci sono già seminari inseriti nel periodo della visita. Per inserire comunque un nuovo seminario premere il pulsante 'Inserisci seminario'" + } +
+ ) : ( + Per inserire un seminario per il visitatore premere il pulsante 'Inserisci seminario' + )} + + )}
} @@ -113,11 +115,44 @@ function VisitForm({visit, variant}) { done={() => { setActiveSection(''); setSeminar(null); - save() // save visit to force notification + save(); // save visit to force notification + fetchSeminars(data); }} variant={variant} /> } + { // mostra i seminari già inseriti + data.requireSeminar && data.startDate && data.endDate && data.person?._id && + + Seminari già inseriti + + {(() => { + return existingSeminars.length ? ( + <> +
+ I seguenti seminari sono stati già inseriti per il visitatore nel periodo selezionato: +
+ {existingSeminars.map(seminar => ( +
+ setActiveSection(seminar._id)} + done={() => { + setActiveSection('') + save() // save visit to force notification + }} + variant={variant} + /> +
+ ))} + + ) : ( + Nessun seminario trovato nel periodo selezionato + ) + })()} +
+
+ } @@ -143,6 +178,19 @@ function VisitForm({visit, variant}) { setActiveSection(section) console.log(`nextStep: ${section}`) } + + function fetchSeminars(newData) { + const queryParams = { + startDate: new Date(newData.startDate).toISOString().split('T')[0], + endDate: new Date(newData.endDate).toISOString().split('T')[0] + } + + api.get(`/api/v0/process/visits/seminars/${data.person._id}`, queryParams).then(res => { + setExistingSeminars(res.data || []) + }).catch(err => { + addMessage(`Error fetching seminars: ${err}`) + }) + } async function save() { if (data.person.affiliations && !data.affiliations?.length) { @@ -169,7 +217,7 @@ function VisitForm({visit, variant}) { } } -function VisitDetailsBlock({data, setData, active, done, edit, variant}) { +function VisitDetailsBlock({data, setData, active, done, edit, variant, fetchSeminars}) { const user = useEngine().user const isAdmin = user.roles && user.roles.includes('admin') @@ -186,7 +234,7 @@ function VisitDetailsBlock({data, setData, active, done, edit, variant}) { { active - ? + ? : <> visitatore: {data.person.firstName} {data.person.lastName} ({data.person.affiliations.map(a=>a.name).join(', ')}) {data.person.email} {data.referencePeople.map(person =>
referente: {person.firstName} {person.lastName} <{person.email}>
)} @@ -211,7 +259,7 @@ function VisitDetailsBlock({data, setData, active, done, edit, variant}) { } -function ActiveVisitDetailsBlock({data, setData, done, variant}) { +function ActiveVisitDetailsBlock({data, setData, done, variant, fetchSeminars}) { return <>
@@ -241,7 +289,7 @@ function ActiveVisitDetailsBlock({data, setData, done, variant}) { - + @@ -289,10 +337,21 @@ function ActiveVisitDetailsBlock({data, setData, done, variant}) {
- Se un seminario per lo speaker è stato già inserito apparirà solo dopo aver salvato la visita}> + Se un seminario per lo speaker nel periodo della visita è stato già inserito apparirà sotto}> - setData({...data, requireSeminar: e.target.checked})} style={{marginRight: '5px'}}/> + { + const newData = {...data, requireSeminar: e.target.checked} + setData(newData) + if (e.target.checked && newData.startDate && newData.endDate && newData.person?._id) { + fetchSeminars(newData) + } + }} + style={{marginRight: '5px'}} + /> {} È previsto un seminario
@@ -308,14 +367,31 @@ function ActiveVisitDetailsBlock({data, setData, done, variant}) {
-
+ +
{ error() &&
{error()}
} + function handleDataChange(newData) { + setData(newData) + if (newData.startDate && newData.endDate && newData.person?._id && newData.requireSeminar) { + fetchSeminars(newData) + } + } + function startDateSetter(value) { - setData(data => { - const endDate = data.endDate || value - return ({...data, startDate: value, endDate}) + const endDate = data.endDate || value + handleDataChange({ + ...data, + startDate: value, + endDate + }) + } + + function endDateSetter(value) { + handleDataChange({ + ...data, + endDate: value }) } diff --git a/src/processes/Visits.js b/src/processes/Visits.js index 6927a03d..fde0da5d 100644 --- a/src/processes/Visits.js +++ b/src/processes/Visits.js @@ -39,31 +39,52 @@ export default function ProcessVisits({variant}) { } -function Rooms({variant, id}) { +function RoomsAndSeminars({variant, id}) { const path = `process/${variant||''}visits/${id}` const query = useQuery(path.split('/')) + if (query.isLoading) return if (query.isError) return
Errore caricamento: {query.error.response.data?.error || `${query.error}`}
if (!query.data) return
No data available
; let visit = {...query.data} - if (! visit.requireRoom) return
- Ufficio: non richiesto -
- else if (visit.roomAssignments?.length > 0) return visit.roomAssignments.map(r => -
- Ufficio: - edificio {r.room.building}, {r.room.floor === '0' ? 'piano terra' : - r.room.floor === '1' ? 'primo piano' : - r.room.floor === '2' ? 'secondo piano' : - 'piano ' + r.room.floor}, - ufficio {r.room.number}, - dal {myDateFormat(r.startDate)} al {myDateFormat(r.endDate)} -
) - else return
- Ufficio: da assegnare -
+ let roomAssignments; + if (visit.requireRoom) { + if (visit.roomAssignments?.length > 0) { + roomAssignments = visit.roomAssignments.map(r => ( +
+ Ufficio: + edificio {r.room.building}, {r.room.floor === '0' ? 'piano terra' : + r.room.floor === '1' ? 'primo piano' : + r.room.floor === '2' ? 'secondo piano' : + 'piano ' + r.room.floor}, + ufficio {r.room.number}, + dal {myDateFormat(r.startDate)} al {myDateFormat(r.endDate)} +
+ )); + } else { + roomAssignments =
Ufficio: da assegnare
; + } + } else { + roomAssignments =
Ufficio: non richiesto
; + } + + let seminars; + if (visit.requireSeminar && visit.seminars && visit.seminars.length > 0 ) { + seminars = ( +
+ {visit.seminars.length > 1 ? "Seminari" : "Seminario"}: {visit.seminars.map(seminar => seminar.title).join(", ")} +
+ ) + } + + return ( +
+ {roomAssignments} + {seminars} +
+ ) } function VisitList({variant}) { @@ -95,16 +116,16 @@ function VisitList({variant}) { {/*JSON.stringify(visit)*/} Visitatore: {visit.person.firstName} { visit.person.lastName } ({visit.affiliations.map(x => x.name).join(", ")})
{variant === '' && visit.referencePeople.length > 0 && ( - <> - {visit.referencePeople.length > 1 ? "Referenti" : "Referente"}: { - visit.referencePeople.map(p => ( - `${p.firstName} ${p.lastName}` - )).join(", ")} -
- - )} + <> + {visit.referencePeople.length > 1 ? "Referenti" : "Referente"}: { + visit.referencePeople.map(p => ( + `${p.firstName} ${p.lastName}` + )).join(", ")} +
+ + )} Periodo: {myDateFormat(visit.startDate)} – {myDateFormat(visit.endDate)}
- +
{ removeVisit(visit._id)}>