}> = (props) => {\n\n const {arg, sortBy, timeSheets, setCalendarAbsenceSidebarProps, setCalendarSignedSidebarProps, setCalendarEventSidebarProps, setCalendarTimeTableProps} = props;\n\n if (arg.resource.extendedProps.hierarchy === calendarTypes.RESOURCE_HIERARCHY_GROUP){\n return \n \n {arg.resource.title}\n \n {arg.resource.extendedProps.underTitle && <>\n \n \n {arg.resource.extendedProps.underTitle}\n \n >}\n \n }\n\n switch (arg.resource.extendedProps.resourceType){\n case calendarTypes.RESOURCE_TYPE_EVENT:\n case calendarTypes.RESOURCE_TYPE_SIGNED:\n switch (arg.resource.extendedProps.hierarchy){\n case calendarTypes.RESOURCE_HIERARCHY_GRAND_CHILD:\n return \n {arg.resource.title}\n \n case calendarTypes.RESOURCE_HIERARCHY_CHILD:\n if (arg.resource.extendedProps.grouped) return <>>\n return \n \n \n \n {Granted(accessRights.LIST_SALARY, arg.resource.extendedProps.salary.id) ? {arg.resource.title} : <>{arg.resource.title}>}\n \n \n {Granted(accessRights.LIST_REPORTING, arg.resource.extendedProps.salary.id) && timeSheets && \n \n }\n \n {GrantedAny([accessRights.EDIT_BOOKING, accessRights.EDIT_TIME_CLOCK, accessRights.EDIT_ABSENCE], arg.resource.extendedProps.salary?.id) && \n \n \n \n {setCalendarSignedSidebarProps !== undefined && arg.resource.extendedProps.resourceType === 'TYPE_SIGNED' && Granted(accessRights.EDIT_TIME_CLOCK, arg.resource.extendedProps.salary.id) &&\n - setCalendarSignedSidebarProps((prev: any) => ({\n sidebarType: \"SIGNED_ADD\",\n trigger: prev.trigger + 1,\n salary: arg.resource.extendedProps.salary,\n company: arg.resource.extendedProps.company\n }))}\n >\n Ajouter un badgeage\n
}\n {setCalendarEventSidebarProps !== undefined && Granted(accessRights.EDIT_BOOKING, arg.resource.extendedProps.salary?.id) && getVersion() === 1 && - setCalendarEventSidebarProps((prev: any) => ({\n sidebarType: \"EVENT_ADD\",\n trigger: prev.trigger + 1,\n dt: setHours(arg.view.calendar.getDate(), (new Date()).getHours()),\n salary: arg.resource.extendedProps.salary,\n company: arg.resource.extendedProps.company,\n localisation: arg.resource.extendedProps.localisation,\n activity: arg.resource.extendedProps.activity\n }))}\n >\n Planifier un créneau\n
}\n {setCalendarTimeTableProps !== undefined && Granted(accessRights.EDIT_BOOKING, arg.resource.extendedProps.salary.id) && getVersion() === 1 && - setCalendarTimeTableProps((prev: any) => ({\n salary: arg.resource.extendedProps.salary,\n date: arg.view.calendar.getDate(),\n }))}\n >\n Modifier la structure\n
}\n {setCalendarAbsenceSidebarProps !== undefined && Granted(accessRights.EDIT_ABSENCE, arg.resource.extendedProps.salary.id) && - setCalendarAbsenceSidebarProps((prev: any) => ({\n sidebarType: \"ABSENCE_ADD\",\n trigger: prev.trigger + 1,\n salary: arg.resource.extendedProps.salary,\n }))}\n >\n Ajouter une absence\n
}\n
\n \n }\n \n \n case calendarTypes.RESOURCE_HIERARCHY_PARENT:\n return \n \n {arg.resource.title}\n \n \n \n
\n {arg.resource.extendedProps.icon && }\n
\n
\n \n \n default:\n return <>{arg.resource.title}>\n }\n case calendarTypes.RESOURCE_TYPE_KEEP_NOTE:\n return <>>\n case calendarTypes.RESOURCE_TYPE_TASK:\n switch (sortBy){\n case 1:\n switch (arg.resource.extendedProps.hierarchy){\n case 'child':\n return \n \n \n \n {Granted(accessRights.LIST_SALARY, arg.resource.extendedProps.salary.id) ? {arg.resource.title} : <>{arg.resource.title}>}\n \n \n
\n \n case 'parent':\n return \n \n {arg.resource.title}\n \n \n \n
\n {arg.resource.extendedProps.icon && }\n
\n
\n \n \n }\n return <>{arg.resource.title}>\n case 2:\n switch (arg.resource.extendedProps.hierarchy){\n case 'grandChild':\n return {arg.resource.title}\n case 'child':\n return {arg.resource.title}\n case 'parent':\n return {arg.resource.title}\n }\n }\n }\n\n return <>{arg.resource.title}>\n}\n\nexport function renderEvent(arg: EventContentArg, displayEventTime?: boolean) { \n switch (arg.event.extendedProps.eventType) {\n case calendarTypes.EVENT_TYPE_TIME_CLOCK:\n case calendarTypes.EVENT_TYPE_TIME_CLOCK_MISSING:\n case calendarTypes.EVENT_TYPE_TIME_CLOCK_EXCEPTION:\n return \n
\n {arg.event.extendedProps.files?.length > 0 && }\n {arg.event.extendedProps.eventType === calendarTypes.EVENT_TYPE_TIME_CLOCK_EXCEPTION && }\n {[calendarTypes.EVENT_TYPE_TIME_CLOCK, calendarTypes.EVENT_TYPE_TIME_CLOCK_EXCEPTION].includes(arg.event.extendedProps.eventType) && (arg.event.extendedProps._start || arg.event.extendedProps._end) && }\n {arg.event.title}\n \n
\n
\n {arg.event.extendedProps.isAnomaly && } {arg.timeText} | {duration(arg.event.start, arg.event.end)}\n \n
\n {['timeGridWeek', 'timeGridDay'].includes(arg.view.type) && arg.event.extendedProps.description &&
\n {arg.event.extendedProps.description}\n }\n
\n case calendarTypes.EVENT_TYPE_PRESENCE:\n let className = '';\n switch (arg.event.extendedProps.presenceType){\n case calendarTypes.EVENT_TYPE_PRESENCE_GLOBAL:\n let counter = Number(arg.event.extendedProps.values.reduce((accumulator: number, object: PresenceEvent) => {\n return accumulator + object.value;\n }, 0));\n\n let need = Number(arg.event.extendedProps.need || 0);\n\n className = (need && need > counter ? ' badge text-danger ' : (need && need < counter ? ' badge text-primary ' : ' badge text-success '));\n\n return \n \n {counter}{!!need && <>/{need}>}\n \n
\n case calendarTypes.EVENT_TYPE_PRESENCE_BY_JOB:\n let v: any[] = arg.event.extendedProps.values\n let n: any[] = arg.event.extendedProps.need\n\n let array = v.filter(_v => _v.id).map(_v => {\n let val = Number(_v.values.reduce((accumulator: number, object: PresenceEvent) => {\n return accumulator + object.value;\n }, 0))\n\n let need = (n ? (n[_v.id] || 0) : 0)\n\n if(val < need) return 0;\n if(val > need) return 2;\n\n return 1;\n })\n\n className = array.includes(0) ? 'text-danger' : (array.includes(2) ? 'text-primary' : 'text-success')\n let icon = array.includes(0) ? 'bi bi-x-lg text-danger' : (array.includes(2) ? 'bi bi-plus-lg text-primary' : 'bi bi-check-lg text-success')\n\n return _v.id).map(_v => {\n\n let _vv = Number(_v.values.reduce((accumulator: number, object: PresenceEvent) => {\n return accumulator + object.value;\n }, 0));\n\n let _vn = (n ? (n[_v.id] || 0) : 0);\n\n return _v.title + \" _vn ? 'text-primary' : 'text-success')) +\"'>\" + _vv + \"/\" + (n ? (n[_v.id] || 0) : 0) + \"\"\n }).join('
')}\n onMouseEnter={(e) => onMouseEnterTooltip(e.currentTarget)}\n className={'text-center w-100 badge btn-light ' + className}>\n \n \n \n
\n }\n break;\n case calendarTypes.EVENT_TYPE_EVENT:\n case calendarTypes.EVENT_TYPE_EVENT_EXCEPTION: \n switch (arg.view.type){ \n case calendarTypes.RESOURCE_TIMELINE_DAY_VIEW:\n return \n \n
\n {arg.event.title}\n
\n
\n {arg.event.extendedProps.isSlotExchange && }\n {arg.event.extendedProps.substitution && }\n {arg.event.extendedProps.absence && {Granted(accessRights.LIST_ABSENCE, arg.event.extendedProps.absence) && arg.event.extendedProps.absence.typeShortName} }\n {arg.event.extendedProps.comment && }\n
\n
\n
\n {arg.event.extendedProps.eventType === calendarTypes.EVENT_TYPE_EVENT_EXCEPTION && }\n {arg.event.extendedProps.eventType === calendarTypes.EVENT_TYPE_EVENT && (arg.event.extendedProps.type === TYPE_EVENT_RECURRING ? : )}\n {arg.timeText} | {duration(arg.event.start, arg.event.end)}\n {arg.event.extendedProps.localisation && \n {arg.event.extendedProps.localisation.title}\n }\n {arg.event.extendedProps.activity && \n {arg.event.extendedProps.activity.title}\n }\n \n case calendarTypes.RESOURCE_TIMELINE_WEEK_VIEW:\n return (\n \n \n
\n
\n {arg.event.extendedProps.localisation &&
\n \n
}\n {arg.event.extendedProps.activity &&
\n \n
}\n
\n
\n {arg.event.title}\n
\n
\n
\n {arg.event.extendedProps.isSlotExchange && }\n {arg.event.extendedProps.substitution && }\n {arg.event.extendedProps.absence && {Granted(accessRights.LIST_ABSENCE, arg.event.extendedProps.absence) && arg.event.extendedProps.absence.typeShortName} }\n {arg.event.extendedProps.comment && }\n
\n
\n \n
\n {arg.event.extendedProps.eventType === TYPE_EVENT_EXCEPTION && }\n {arg.event.extendedProps.eventType === calendarTypes.EVENT_TYPE_EVENT && (arg.event.extendedProps.type === TYPE_EVENT_RECURRING ? : )}\n {arg.timeText} | {duration(arg.event.start, arg.event.end)}\n
\n
\n \n )\n case calendarTypes.RESOURCE_TIMELINE_VIEW:\n case calendarTypes.RESOURCE_TIMELINE_MONTH_VIEW:\n return {arg.event.extendedProps.absence ? <> {Granted(accessRights.LIST_ABSENCE, arg.event.extendedProps.absence) && arg.event.extendedProps.absence.typeShortName}> : (displayEventTime ? arg.timeText : duration(arg.event.start, arg.event.end))}\n case calendarTypes.TIME_GRID_DAY_VIEW:\n case calendarTypes.TIME_GRID_WEEK_VIEW:\n return <>\n \n {arg.event.extendedProps.eventType === TYPE_EVENT_EXCEPTION && }\n {arg.event.extendedProps.eventType === calendarTypes.EVENT_TYPE_EVENT && (arg.event.extendedProps.type === TYPE_EVENT_RECURRING ? : )}\n {arg.event.extendedProps.exchange && }\n {arg.event.extendedProps.substitution && }\n {arg.timeText}\n \n {(arg.event.end && arg.event.start) ? format(new Date(arg.event.end!.getTime() - arg.event.start!.getTime() - (3600 * 1000)), 'HH:mm') : arg.event.extendedProps.exceptionId}\n \n {arg.event.extendedProps.exchanged && <>{{arg.event.title}}>}\n
\n {arg.event.extendedProps.company && <>\n {arg.event.extendedProps.company.title}\n
\n >}\n {arg.event.extendedProps.localisation && <>\n {arg.event.extendedProps.localisation.title}\n
\n >}\n {arg.event.extendedProps.activity && <>\n {arg.event.extendedProps.activity.title}\n
\n >}\n {arg.event.extendedProps.absence && <>\n {arg.event.extendedProps.absence.typeName}\n
\n >}\n {arg.event.extendedProps.comment && <>\n {arg.event.extendedProps.comment}\n \n >}\n >\n case calendarTypes.DAY_GRID_MONTH_VIEW:\n return \n
\n {arg.event.extendedProps.eventType === TYPE_EVENT_EXCEPTION && }\n {arg.event.extendedProps.eventType === calendarTypes.EVENT_TYPE_EVENT && (arg.event.extendedProps.type === TYPE_EVENT_RECURRING ? : )}\n {arg.event.extendedProps.exchange && }\n {arg.event.extendedProps.substitution && }\n {arg.timeText}\n \n {arg.event.extendedProps.exchanged && <>{
{arg.event.title}}>}\n
\n {arg.event.extendedProps.company && <>\n
{arg.event.extendedProps.company.title}\n
\n >}\n {arg.event.extendedProps.localisation && <>\n
{arg.event.extendedProps.localisation.title}\n
\n >}\n {arg.event.extendedProps.activity && <>\n
{arg.event.extendedProps.activity.title}\n
\n >}\n {arg.event.extendedProps.absence && <>\n
{arg.event.extendedProps.absence.typeName}\n
\n >}\n {arg.event.extendedProps.comment && <>\n
{arg.event.extendedProps.comment}\n
\n >}\n
\n case 'listDay':\n case 'listWeek':\n return <>\n \n {arg.event.extendedProps.comment &&
}\n {arg.event.extendedProps.substitution &&
}\n {arg.event.extendedProps.exchange &&
}\n
\n {arg.event.extendedProps.salary.title}\n \n {arg.event.extendedProps.absence && <>\n
{arg.event.extendedProps.absence.typeName}\n >}\n {arg.event.extendedProps.localisation &&
\n {arg.event.extendedProps.localisation.title}\n }\n {arg.event.extendedProps.activity &&
\n {arg.event.extendedProps.activity.title}\n }\n
\n
\n {arg.event.extendedProps?.company?.title}\n
\n
\n
\n {arg.event.extendedProps.salary.information.job.title}\n
\n
\n >\n }\n break;\n case calendarTypes.EVENT_TYPE_BOOKING:\n case calendarTypes.EVENT_TYPE_BOOKING_EXCEPTION:\n case calendarTypes.EVENT_TYPE_BOOKING_OUTER:\n switch (arg.view.type){\n case calendarTypes.RESOURCE_TIMELINE_DAY_VIEW:\n return (\n \n \n
\n {arg.event.title}\n
\n
\n {arg.event.extendedProps.isSlotExchange && }\n {arg.event.extendedProps.substitute && }\n {arg.event.extendedProps.absence && {Granted(accessRights.LIST_ABSENCE, arg.event.extendedProps.absence) && arg.event.extendedProps.absence.typeShortName} }\n
\n
\n
\n {arg.event.extendedProps.eventType === 'booking' && arg.event.extendedProps.isException && }\n {arg.event.extendedProps.eventType === 'booking' && arg.event.extendedProps.recurrence.type !== 1 && !arg.event.extendedProps.isException && }\n {arg.timeText} - {format(new Date(arg.event.end!.getTime() - arg.event.start!.getTime() - (3600 * 1000)), 'HH:mm')}\n {arg.event.extendedProps.localisation && \n {arg.event.extendedProps.localisation.title}\n }\n {arg.event.extendedProps.activity && \n {arg.event.extendedProps.activity.title}\n }\n \n )\n case calendarTypes.RESOURCE_TIMELINE_WEEK_VIEW:\n return (\n \n \n
\n {arg.event.title}\n
\n
\n {arg.event.extendedProps.isSlotExchange && }\n {arg.event.extendedProps.substitute && }\n {arg.event.extendedProps.absence && {Granted(accessRights.LIST_ABSENCE, arg.event.extendedProps.absence) && arg.event.extendedProps.absence.typeShortName} }\n
\n
\n \n
\n {arg.event.extendedProps.eventType === 'bookingException' && }\n {arg.event.extendedProps.eventType === 'booking' && arg.event.extendedProps.recurrence.type !== 1 && !arg.event.extendedProps.isException && }\n {arg.timeText}\n
\n {arg.event.extendedProps.localisation &&
\n \n
}\n {arg.event.extendedProps.activity &&
\n \n
}\n
\n \n )\n case calendarTypes.RESOURCE_TIMELINE_VIEW:\n case calendarTypes.RESOURCE_TIMELINE_MONTH_VIEW:\n return (\n <>\n {displayEventTime ? arg.timeText : duration(arg.event.start, arg.event.end)}\n >\n )\n case calendarTypes.DAY_GRID_MONTH_VIEW:\n return \n
\n {arg.event.extendedProps.isException && }\n {arg.event.extendedProps.isSlotExchange && }\n {arg.event.extendedProps.substitute && }\n {!arg.event.extendedProps.isException && arg.event.extendedProps.recurrence?.type > 1 && }\n {arg.timeText}\n \n {arg.event.extendedProps.exchanged && <>{
{arg.event.title}}>}\n
\n {arg.event.extendedProps.company && <>\n
{arg.event.extendedProps.company.title}\n
\n >}\n {arg.event.extendedProps.localisation && <>\n
{arg.event.extendedProps.localisation.title}\n
\n >}\n {arg.event.extendedProps.activity && <>\n
{arg.event.extendedProps.activity.title}\n
\n >}\n {arg.event.extendedProps.absence && <>\n
{arg.event.extendedProps.absence.typeName}\n
\n >}\n {arg.event.extendedProps.comment && <>\n
{arg.event.extendedProps.comment}\n
\n >}\n
\n case calendarTypes.TIME_GRID_DAY_VIEW:\n case calendarTypes.TIME_GRID_WEEK_VIEW:\n return <>\n \n {arg.event.extendedProps.isException && }\n {arg.event.extendedProps.isSlotExchange && }\n {arg.event.extendedProps.substitute && }\n {!arg.event.extendedProps.isException && arg.event.extendedProps.recurrence?.type > 1 && }\n {arg.timeText}\n \n {arg.event.start && arg.event.end && <>{format(new Date(arg.event.end!.getTime() - arg.event.start!.getTime() - (3600 * 1000)), 'HH:mm')}>}\n \n
\n {arg.event.extendedProps.company && <>\n {arg.event.extendedProps.company.title}\n
\n >}\n {arg.event.extendedProps.localisation && <>\n {arg.event.extendedProps.localisation.title}\n
\n >}\n {arg.event.extendedProps.activity && <>\n {arg.event.extendedProps.activity.title}\n
\n >}\n {arg.event.extendedProps.absence && <>\n {arg.event.extendedProps.absence.typeName}\n
\n >}\n >\n case 'listDay':\n case 'listWeek':\n return <>\n \n {arg.event.extendedProps.substitute &&
}\n {arg.event.extendedProps.isSlotExchange &&
}\n
\n {arg.event.extendedProps.salary.title}\n \n {arg.event.extendedProps.absence && <>\n
{arg.event.extendedProps.absence.typeName}\n >}\n {arg.event.extendedProps.localisation &&
\n {arg.event.extendedProps.localisation.title}\n }\n {arg.event.extendedProps.activity &&
\n {arg.event.extendedProps.activity.title}\n }\n
\n
\n {arg.event.extendedProps?.company?.title}\n
\n
\n
\n {arg.event.extendedProps.salary.information.job.title}\n
\n
\n >\n }\n break;\n case calendarTypes.EVENT_TYPE_OFFER_VALIDATED:\n case calendarTypes.EVENT_TYPE_OFFER_PENDING:\n switch (arg.view.type){\n case calendarTypes.TIME_GRID_WEEK_VIEW:\n case calendarTypes.TIME_GRID_DAY_VIEW:\n return <>\n \n {arg.timeText}\n \n {format(new Date(arg.event.end!.getTime() - arg.event.start!.getTime() - (3600 * 1000)), 'HH:mm')}\n \n
\n {arg.event.extendedProps.company && <>\n {arg.event.extendedProps.company.title}\n
\n >}\n {arg.event.extendedProps.localisation && <>\n {arg.event.extendedProps.localisation.title}\n
\n >}\n {arg.event.extendedProps.activity && <>\n {arg.event.extendedProps.activity.title}\n
\n >}\n >\n case calendarTypes.RESOURCE_TIMELINE_DAY_VIEW:\n case calendarTypes.RESOURCE_TIMELINE_WEEK_VIEW:\n return <>\n \n
\n
\n {arg.event.title}\n
\n
\n
\n \n
\n {arg.timeText}\n
\n {arg.event.extendedProps.localisation &&
\n \n
}\n {arg.event.extendedProps.activity &&
\n \n
}\n
\n >\n case calendarTypes.RESOURCE_TIMELINE_VIEW:\n case calendarTypes.RESOURCE_TIMELINE_MONTH_VIEW:\n return {arg.event.extendedProps.absence && Granted(accessRights.LIST_ABSENCE, arg.event.extendedProps.absence) ? arg.event.extendedProps.absence.typeShortName : arg.timeText}
\n }\n break;\n case 'templateBookingException':\n case 'templateBooking':\n switch (arg.view.type){\n case 'resourceTimelineDay':\n return <>\n \n
\n {arg.event.extendedProps.resource.job.title}\n
\n
\n \n
\n {arg.event.extendedProps.isException && }\n {arg.event.extendedProps.recurrence.type > 1 && !arg.event.extendedProps.isException && }\n {arg.timeText} - {format(new Date(arg.event.end!.getTime() - arg.event.start!.getTime() - (3600 * 1000)), 'HH:mm')}\n
\n {arg.event.extendedProps.localisation &&
\n {\n \n }\n {arg.event.extendedProps.localisation?.title || ''}\n
}\n {arg.event.extendedProps.activity &&
\n {\n \n }\n {arg.event.extendedProps.activity.title || ''}\n
}\n
\n >\n case 'resourceTimelineWeek':\n return (\n <>\n \n
\n {arg.event.extendedProps.resource.job.title}\n
\n
\n \n
\n {arg.event.extendedProps.isException && }\n {arg.event.extendedProps.recurrence.type > 1 && !arg.event.extendedProps.isException && }\n {arg.timeText}\n
\n {arg.event.extendedProps.localisation &&
\n \n
}\n {arg.event.extendedProps.activity &&
\n \n
}\n
\n >\n )\n }\n break;\n case calendarTypes.EVENT_TYPE_ABSENCE:\n return <>\n \n
\n
\n {arg.event.title}\n
\n \n
\n {format(new Date(arg.event.extendedProps.absence.start))} {format(new Date(arg.event.extendedProps.absence.end))}\n
\n
\n >\n case calendarTypes.EVENT_TYPE_KEEP_NOTE:\n return <>\n {arg.event.extendedProps.private && }\n {arg.event.title}\n >\n case calendarTypes.EVENT_TYPE_TASK:\n case calendarTypes.EVENT_TYPE_TASK_EXCEPTION:\n // switch (arg.view.type){\n //\n // }\n return <>\n {arg.timeText} {arg.event.title}\n >\n case calendarTypes.EVENT_TYPE_TEMPLATE_APPLIED_EVENT:\n case calendarTypes.EVENT_TYPE_TEMPLATE_APPLIED_EVENT_EXCEPTION:\n case calendarTypes.EVENT_TYPE_TEMPLATE_APPLIED_EVENT_APPLIED_EXCEPTION:\n case calendarTypes.EVENT_TYPE_TEMPLATE_EVENT:\n case calendarTypes.EVENT_TYPE_TEMPLATE_EVENT_EXCEPTION:\n switch (arg.view.type){\n case calendarTypes.RESOURCE_TIMELINE_WEEK_VIEW:\n return \n \n
\n
\n {arg.event.extendedProps.localisation &&
\n \n
}\n {arg.event.extendedProps.activity &&
\n \n
}\n
\n
\n {arg.event.title}\n
\n {arg.event.extendedProps.substitution &&
}\n
\n
\n {arg.event.extendedProps.absence && {Granted(accessRights.LIST_ABSENCE, arg.event.extendedProps.absence) && arg.event.extendedProps.absence.typeShortName} }\n
\n
\n \n
\n {arg.event.extendedProps.eventType === calendarTypes.EVENT_TYPE_TEMPLATE_APPLIED_EVENT_APPLIED_EXCEPTION && }\n {arg.timeText} | {duration(arg.event.start, arg.event.end)}\n
\n
\n \n case calendarTypes.RESOURCE_TIMELINE_DAY_VIEW:\n return \n \n
\n {arg.event.title}\n
\n
\n {arg.event.extendedProps.absence && {Granted(accessRights.LIST_ABSENCE, arg.event.extendedProps.absence) && arg.event.extendedProps.absence.typeShortName} }\n
\n {arg.event.extendedProps.substitution &&
}\n
\n
\n {arg.event.extendedProps.eventType === calendarTypes.EVENT_TYPE_TEMPLATE_APPLIED_EVENT_APPLIED_EXCEPTION && }\n {arg.timeText} | {duration(arg.event.start, arg.event.end)}\n {arg.event.extendedProps.localisation && \n {arg.event.extendedProps.localisation.title}\n }\n {arg.event.extendedProps.activity && \n {arg.event.extendedProps.activity.title}\n }\n \n case calendarTypes.RESOURCE_TIMELINE_VIEW:\n case calendarTypes.RESOURCE_TIMELINE_MONTH_VIEW:\n return {(arg.event.extendedProps.absence && Granted(accessRights.LIST_ABSENCE, arg.event.extendedProps.absence)) ? arg.event.extendedProps.absence.typeShortName : (displayEventTime ? arg.timeText : duration(arg.event.start, arg.event.end))}\n case calendarTypes.LIST_WEEK_VIEW:\n case calendarTypes.LIST_DAY_VIEW:\n return <>>\n case calendarTypes.TIME_GRID_DAY_VIEW:\n case calendarTypes.TIME_GRID_WEEK_VIEW:\n return <>\n \n {arg.event.extendedProps.eventType === calendarTypes.EVENT_TYPE_TEMPLATE_APPLIED_EVENT_APPLIED_EXCEPTION && }\n {arg.event.extendedProps.exchange && }\n {arg.event.extendedProps.substitution && }\n {arg.timeText}\n \n {(arg.event.end && arg.event.start) ? format(new Date(arg.event.end!.getTime() - arg.event.start!.getTime() - (3600 * 1000)), 'HH:mm') : arg.event.extendedProps.exceptionId}\n \n
\n {arg.event.extendedProps.company && <>\n {arg.event.extendedProps.company.title}\n
\n >}\n {arg.event.extendedProps.localisation && <>\n {arg.event.extendedProps.localisation.title}\n
\n >}\n {arg.event.extendedProps.activity && <>\n {arg.event.extendedProps.activity.title}\n
\n >}\n {arg.event.extendedProps.absence && <>\n {arg.event.extendedProps.absence.typeName}\n
\n >}\n {arg.event.extendedProps.comment && <>\n {arg.event.extendedProps.comment}\n \n >}\n >\n }\n return <>\n {arg.timeText} {arg.event.title}\n >\n\n }\n\n return <>>\n}\n\nexport function resourceLaneContent(e: { resource: ResourceApi }){\n if (e.resource.extendedProps.hierarchy === 'parent' && e.resource.extendedProps.backgroundColor){\n let lane = document.querySelector(`.fc-timeline-lane.fc-resource[data-resource-id=\"${e.resource.id}\"]`) as HTMLTableColElement;\n if (lane){\n lane.style.backgroundColor = e.resource.extendedProps.backgroundColor;\n }\n }else if(e.resource.extendedProps.hierarchy === 'grandChild'){\n let lane = document.querySelector(`.fc-timeline-lane.fc-resource[data-resource-id=\"${e.resource.id}\"]`) as HTMLTableColElement;\n if (lane){\n lane.style.backgroundColor = \"#e9ecef\";\n }\n }\n}\n\nexport const ResourceAreaHeaderContent:React.FC<{\n isAbsence: boolean,\n setIsAbsence: React.Dispatch,\n filterEventsWithResources: boolean,\n setFilterEventsWithResources: React.Dispatch,\n setIsBackgroundEvents: React.Dispatch,\n isBackgroundEvents: boolean,\n setIsOuterEvent: React.Dispatch\n isOuterEvents: boolean,\n}> = (props) => {\n const {isAbsence, setIsAbsence, filterEventsWithResources, setFilterEventsWithResources, setIsBackgroundEvents, isBackgroundEvents, setIsOuterEvent, isOuterEvents} = props;\n\n return \n \n \n - \n \n
\n - \n \n
\n - \n \n
\n - \n \n
\n
\n \n}\n\nconst ViewTitleContainer = forwardRef((props, ref) => {\n const { onClick, viewTitle, prevClick, nextClick, endDate, handlePickedDateChange } = props;\n\n let maxDate = getMaxVisibilityDate();\n\n return (\n \n \n \n \n \n
\n )\n});\n\nexport const CalendarTitle: React.FC<{pickerDate: Date, handlePickerDateChange: (pickerDate: Date) => void, title: string, prevClick: () => void, nextClick: () => void, endDate: Date}> = (props) => {\n const { handlePickerDateChange, pickerDate, title, prevClick, nextClick, endDate } = props;\n\n return (\n {\n if (date instanceof Date){\n handlePickerDateChange(date)\n }\n }}\n customInput={\n \n }\n />\n )\n}\n\n\nexport const renderDaySeparator = () => {\n const leadingZero = (num: number) => `0${num}`.slice(-2);\n const formatTime = (date: Date) =>\n [date.getHours(), date.getMinutes(), date.getSeconds()]\n .map(leadingZero)\n .join(':');\n\n let lanes = Array.from(document.querySelectorAll('td.fc-timeline-slot-lane') as NodeListOf);\n let dates = lanes.filter((lane) => !!lane.dataset?.date).map((lane) => new Date(lane.dataset.date!).getTime())\n const maxDate = new Date(Math.max.apply(null, dates));\n const maxTime = formatTime(maxDate)\n for (let i in lanes){\n if(typeof lanes[i] === 'object'){\n if (lanes[i].hasAttribute('data-date')){\n if(lanes[i].getAttribute('data-date')?.split('T')[1] === maxTime){\n lanes[i].style.cssText = 'border-right: solid #4723D9 2px !important;'\n }else{\n lanes[i].style.cssText = ''\n }\n }\n }\n }\n}","import React, { useEffect, useState } from \"react\";\n\nimport FullCalendar, { EventClickArg } from \"@fullcalendar/react\";\nimport listPlugin from \"@fullcalendar/list\";\nimport CalendarTaskSidebar, { CalendarTaskSidebarInterface } from \"../sidebar\";\nimport allLocales from \"@fullcalendar/core/locales-all\";\n\nimport * as types from \"../../../../constants/calendar\";\nimport * as accessRights from \"../../../../constants/accessRight\";\n\nimport * as api from \"../../../../adapters/calendar\";\n\nimport { Granted } from \"../../../../security/granted\";\nimport { CalendarTitle, renderEvent } from \"../../utils\";\nimport format from \"../../../../utils/locale\";\nimport onMouseEnterTooltip from \"../../../../utils/mouseOverTooltip\";\n\ninterface Controlled {\n type: 'CONTROLLED'\n setCalendarTaskSidebarProps: React.Dispatch,\n tasks: any[],\n initialView: string,\n initialDate: Date\n}\n\ninterface Uncontrolled {\n type: 'UNCONTROLLED'\n}\n\nconst CalendarTaskList:React.FC = (props) => { \n const [tasks, setTasks] = useState([])\n const [pickerDate, setPickerDate] = useState(new Date());\n const [title, setTitle] = useState('');\n const [loading, setLoading] = useState(false);\n const calendarRef = React.createRef();\n const [calendarTaskSidebarProps, setCalendarTaskSidebarProps] = useState({sidebarType: 'EMPTY', trigger: 0});\n const [initialDate, setInitialDate] = useState(props.type === 'UNCONTROLLED' ? new Date() : props.initialDate);\n const [initialView, setInitialView] = useState('listWeek');\n const [endDate, setEndDate] = useState(new Date());\n const [view, setView] = useState(initialView)\n\n function fetchCalendar() {\n let API = calendarRef.current?.getApi();\n\n if (API) {\n setEndDate(API.view.activeEnd)\n setLoading(true)\n api.test({\n calendar: types.CALENDAR_TASK,\n start: format(API.view.currentStart, 'uuuu-MM-dd'),\n end: format(API.view.activeEnd, 'uuuu-MM-dd'),\n options: {\n sortBy: types.SORT_TASK_BY_GROUP\n }\n }).then(r => {\n setTasks(r.data.tasks)\n }).then(() => {\n setLoading(false)\n })\n }\n }\n\n function refreshCalendar(salaries: number[]) {\n let API = calendarRef.current?.getApi();\n\n if (API) {\n return api.test({\n start: format(API.view.currentStart, 'uuuu-MM-dd'),\n end: format(API.view.activeEnd, 'uuuu-MM-dd'),\n calendar: types.CALENDAR_TASK,\n options: {\n sortBy: types.SORT_TASK_BY_GROUP,\n salaries: salaries,\n }\n }).then((data) => {\n setTasks(prev =>[...[...prev.filter((e: any) => !(e.salaries.filter((s: any) => salaries.includes(s.id))))], ...data.data.tasks || []])\n }).then(() => true)\n } else {\n return false;\n }\n }\n\n function handleEventChange(ev: any) {\n let salaries: number[] = [];\n ev.salaries.map((s: any) => salaries.push(s.id))\n\n return refreshCalendar([...salaries, ...ev.previousSalaries || []]);\n }\n\n\n function handlePickerDateChange(dt: Date) {\n if (hasApi()) {\n setPickerDate(dt)\n getApi().gotoDate(dt)\n fetchCalendar()\n }\n }\n\n function getApi() {\n return calendarRef.current!.getApi();\n }\n\n function hasApi() {\n return !!calendarRef.current?.getApi();\n }\n\n function prevClick() {\n if (hasApi()){\n getApi().prev()\n setTitle(getApi().view.title)\n fetchCalendar()\n }\n }\n\n function nextClick() {\n if (hasApi()){\n getApi().next()\n setTitle(getApi().view.title)\n fetchCalendar()\n }\n }\n\n function onClick(arg: EventClickArg) {\n arg.jsEvent.stopPropagation()\n if (Granted(accessRights.LIST_TASK_GROUP)){\n if (props.type === 'UNCONTROLLED') {\n setCalendarTaskSidebarProps(prev => ({\n sidebarType: \"TASK_SHOW\",\n trigger: prev.trigger + 1,\n arg: arg,\n setCalendarTaskSidebarProps: setCalendarTaskSidebarProps\n }))\n } else if (props.type === 'CONTROLLED') {\n props.setCalendarTaskSidebarProps((prev: any) => ({\n sidebarType: \"TASK_SHOW\",\n trigger: prev.trigger + 1,\n arg: arg,\n setCalendarTaskSidebarProps: props.setCalendarTaskSidebarProps\n }))\n }\n }\n }\n\n function changeView(_view: string) {\n if (hasApi()){\n setView(_view)\n getApi().changeView(_view);\n setTitle(getApi().view.title)\n fetchCalendar()\n }\n }\n\n useEffect(() => {\n if (props.type === 'CONTROLLED') {\n if (props.initialDate.getTime() !== initialDate.getTime()){\n setInitialDate(props.initialDate)\n }\n if (props.initialView !== initialView){\n setInitialView(props.initialView)\n }\n }\n })\n\n useEffect(() => {\n if (props.type === 'UNCONTROLLED') {\n fetchCalendar()\n } else if (props.type === 'CONTROLLED') {\n if (hasApi()){\n setEndDate(getApi().view.activeEnd)\n switch (initialView){\n case types.RESOURCE_TIMELINE_MONTH_VIEW:\n getApi().changeView('listMonth', initialDate)\n break;\n case types.RESOURCE_TIMELINE_WEEK_VIEW:\n getApi().changeView('listWeek', initialDate)\n break;\n case types.RESOURCE_TIMELINE_DAY_VIEW:\n getApi().changeView('listDay', initialDate)\n break;\n }\n }\n }\n }, [initialDate, initialView])\n\n const Toolbar = () => {\n return (\n \n
\n
\n
\n Tâches\n
\n \n
\n
\n
\n
\n - changeView('listDay')}>\n Jour\n
\n - changeView('listWeek')}>\n Semaine\n
\n
\n
\n
\n {Granted(accessRights.EDIT_TASK) &&\n
onMouseEnterTooltip(e.currentTarget)}\n title={\"Ajouter une tâche\"}\n >\n \n
\n }\n
\n
\n
\n )\n }\n\n return (\n \n {props.type === 'UNCONTROLLED' &&\n
\n }\n\n
\n setTitle(arg.view.title)}\n locales={allLocales}\n locale={'fr'}\n eventClick={onClick}\n eventContent={renderEvent}\n />\n
\n\n {props.type === 'UNCONTROLLED' &&\n
\n }\n
\n )\n}\n\nexport default CalendarTaskList;","import React, {useEffect, useState} from \"react\";\nimport {RootStateOrAny, useDispatch, useSelector} from \"react-redux\";\nimport * as api from \"../../../adapters/absence\"\nimport * as actions from \"../../../actions/absence\"\nimport Loader from \"../../../utils/loader\";\nimport {openSidebar} from \"../../../actions/rightSidebar\";\nimport {FORM_NEW_ABSENCE, PENDING_ABSENCE_LIST} from \"../../../constants/rightSidebar\";\nimport * as accessRights from \"../../../constants/accessRight\";\nimport {Absence} from \"../../../models/absence\";\nimport {axiosError} from \"../../../actions/axios\";\nimport {Granted} from \"../../../security/granted\";\nimport getUser from \"../../../security/getUser\";\n\n\nconst DashboardAbsenceRequest:React.FC = () => {\n\n\n const dispatch = useDispatch();\n const state = useSelector((state: RootStateOrAny) => state);\n\n useEffect(() => {\n const controller = new AbortController();\n\n dispatch(actions.fetchAbsences())\n api.list({status: ['1']}, controller.signal)\n .then(data => dispatch(actions.fetchAbsencesSuccess(data.data)))\n .catch(error => dispatch(axiosError(error)))\n\n return () => controller.abort();\n }, [])\n\n return <>\n \n
dispatch(openSidebar(PENDING_ABSENCE_LIST))}>\n
\n
\n
\n \n Congés\n \n
\n
\n en attente\n \n
\n
\n {state.absence.isLoading ?
\n Loading...\n
:
{state.absence.payload.filter((absence: Absence) => absence.status === 1).length}}\n
\n
\n
\n {Granted(accessRights.EDIT_ABSENCE) &&
}\n {Granted(accessRights.REQUEST_ABSENCE) && !Granted(accessRights.EDIT_ABSENCE) &&
}\n
\n >\n}\n\nexport default DashboardAbsenceRequest;","import {get, post} from \"../xhr\";\n\nexport function list(requestData: { start: string, end: string}, signal: AbortSignal){\n return post('keep_note/list', requestData, {signal: signal});\n}\n\nexport function edit(requestData: { private: boolean, description: string, dueDate: Date }, id: number){\n return post('keep_note/edit/' + id, requestData);\n}\n\nexport function create(requestData: { private: boolean, description: string, dueDate: Date }){\n return post('keep_note/create', requestData);\n}\n\nexport function show(id: string){\n return get('keep_note/show/' + id);\n}\n\nexport function cancel(id: number){\n return get('keep_note/delete/' + id);\n}","import React, {useEffect, useState} from \"react\";\nimport {RootStateOrAny, useDispatch, useSelector} from \"react-redux\";\nimport * as api from \"../../../adapters/keepNote\";\nimport * as action from \"../../../actions/keepNote\";\nimport format from \"../../../utils/locale\";\nimport {openSidebar} from \"../../../actions/rightSidebar\";\nimport {\n FORM_KEEP_NOTE_ADD,\n FORM_KEEP_NOTE_LIST,\n} from \"../../../constants/rightSidebar\";\nimport {axiosError} from \"../../../actions/axios\";\nimport * as accessRights from \"../../../constants/accessRight\";\nimport {Granted} from \"../../../security/granted\";\n\n\nconst DashboardKeepNote:React.FC = () => {\n const dispatch = useDispatch();\n const state = useSelector((state: RootStateOrAny) => state.keepNote)\n let today = new Date();\n let end = new Date(today.setDate(today.getDate() + 7))\n\n useEffect(() => {\n const controller = new AbortController();\n\n dispatch(action.fetchKeepNotes());\n api.list({start: format(new Date(), 'uuu-MM-dd'), end: format(end, 'uuu-MM-dd')}, controller.signal)\n .then(data => dispatch(action.fetchKeepNotesSuccess(data.data)))\n .catch(error => dispatch(axiosError(error)))\n\n return () => controller.abort();\n }, [])\n\n return <>\n \n
dispatch(openSidebar(FORM_KEEP_NOTE_LIST))}>\n
\n
\n
\n \n Notes\n \n
\n
\n +7 jours\n \n
\n
\n {state.isLoading ?
\n Loading...\n
:
{state.payload.length}}\n
\n
\n
\n {Granted(accessRights.EDIT_KEEP_NOTE) &&
}\n
\n >\n}\n\nexport default DashboardKeepNote;","import {get, post} from \"../../xhr\";\n\nexport function setting(requestData: {setting: string, value: any}, id: number){\n return post(`salary/${id}/setting`, requestData);\n}\n\nexport function disable(id: number){\n return get('salary/disable/' + id);\n}\n\nexport function enable(id: number){\n return get('salary/enable/' + id);\n}","import React, {useEffect, useState} from \"react\";\nimport * as api from \"../../../adapters/salary\";\nimport * as settingsApi from \"../../../adapters/salary/settings\";\nimport * as accessRights from \"../../../constants/accessRight\";\nimport format from \"../../../utils/locale\";\nimport {useDispatch} from \"react-redux\";\nimport {FEED_LIST} from \"../../../constants/rightSidebar\";\nimport {openSidebar} from \"../../../actions/rightSidebar\";\nimport {axiosError} from \"../../../actions/axios\";\nimport {Granted} from \"../../../security/granted\";\n\nconst DashboardFeed:React.FC = () => {\n\n const dispatch = useDispatch();\n const [feeds, setFeeds] = useState<{type: \"birthdate\"|\"trial\"|\"seniority\"|\"start\"|\"end\"|\"endActivated\", initials: string, dueDate: string, title: string, value: string, salaryId: number}[]>([]);\n let start = new Date();\n let end = new Date((new Date()).setDate((new Date().getDate() + 15)));\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n const controller = new AbortController();\n\n api.feed({start: format(start, 'uuuu-MM-dd'), end: format(end, 'uuuu-MM-dd')}, controller.signal).then(data => {\n setFeeds(data.data)\n setIsLoading(false)\n }).catch(error => dispatch(axiosError(error)))\n\n return () => controller.abort();\n }, [])\n\n const removeFeed = (index: number) => {\n let _feeds = [...feeds]\n _feeds.splice(index, 1)\n setFeeds([..._feeds]);\n }\n\n const getIcon = (type: string) => {\n switch (type){\n case 'trial':\n return ;\n case 'birthday':\n return ;\n case 'seniority':\n return ;\n case 'start':\n return ;\n case 'end':\n return ;\n case 'endActivated':\n return ;\n }\n }\n\n return <>\n \n
\n
\n \n Actualités\n \n
\n
\n +15 jours\n \n
\n
\n \n {!isLoading && feeds.length}\n \n
\n
\n
\n {isLoading ?\n <>\n \n >\n : (feeds.length ?\n : <> Aucune actualité >)}\n {!isLoading && feeds.length > 8 && }\n >\n}\n\nexport default DashboardFeed;","import {post, get} from \"../xhr\";\n\ninterface FetchPayload {\n start: string;\n end: string;\n options?: {\n salaries?: number[];\n companies?: number[];\n isResource?: boolean;\n workingTime?: boolean;\n };\n}\n\nexport function fetch(requestData: FetchPayload, signal: AbortSignal){\n return post('time_clock/booking/fetch', requestData, {signal: signal});\n}\n\nexport function create(requestData: {salary?: number, company?: number, beginAt?: Date, endAt?: Date}){\n return post('time_clock/booking/create', requestData);\n}\n\nexport function edit(requestData: any, id: number){\n return post(`time_clock/booking/edit/${id}`, requestData);\n}\n\nexport function removeAnomaly(id: number){\n return get(`time_clock/booking/remove_anomaly/${id}`);\n}\n\nexport function remove(id: number){\n return get(`time_clock/booking/remove/${id}`);\n}\n\nexport function clockIn(requestData: {company: number, type: number}){\n return post('time_clock/clock_in', requestData);\n}","import React, {useState} from \"react\";\nimport * as API from \"../../../adapters/timeClock\";\nimport {RootStateOrAny, useDispatch, useSelector} from \"react-redux\";\nimport BootstrapSelect from \"../../../utils/bootstrapSelect\";\nimport {showAlertSuccess} from \"../../../actions/alert\";\nimport {Company} from \"../../../models/companies\";\n\nconst DashboardPointing:React.FC = () => {\n\n const state = useSelector((state: RootStateOrAny) => state);\n const dispatch = useDispatch();\n const [type, setType] = useState<\"in\"|\"out\">();\n const [company, setCompany] = useState(state.auth.user.currentSalary.companies[0].id);\n const [isLoading, setIsLoading] = useState(false);\n const [showError, setShowError] = useState(false);\n\n const _clockIn = () => {\n\n if (!type || !company){\n setShowError(true)\n return false;\n }\n\n setIsLoading(true);\n\n API.clockIn({\n company: company,\n type: type === \"in\" ? 1 : 2,\n }).then(() => {\n dispatch(showAlertSuccess('Pointage efféctué'))\n setIsLoading(false);\n setType(undefined)\n });\n }\n\n return <>\n \n
\n
\n
\n Badgeuse\n
\n
\n Choisissez une entrée ou une sortie puis validez.\n
\n
\n
\n
\n {state.auth.user.currentSalary.companies.length > 1 &&
\n ({\n label: company.title,\n value: company.id\n }))}\n notFloating={true}\n required={true}\n value={{\n label: state.auth.user.currentSalary.companies[0].title,\n value: state.auth.user.currentSalary.companies[0].id\n }}\n onChange={(choice) => setCompany(Number(choice?.value))}\n />\n
}\n
\n \n \n
\n
\n \n
\n
\n
\n
\n
\n {showError && !company && <>\n \n Veuillez séléctionner un point de vente\n \n >}\n \n {showError && !type && <>\n \n Veuillez séléctionner une entrée ou une sortie.\n \n >}\n
\n
\n >\n}\n\nexport default DashboardPointing;","import {get, post} from \"../../xhr\";\n\ninterface BookingOfferPayload {\n description: string,\n beginAt: Date,\n endAt: Date,\n salaries: number[],\n localisation?: number,\n activity?: number,\n}\n\nexport function list(requestData: {start?: Date, end?: Date}, signal: AbortSignal){\n return post('booking/offer/list', requestData, {signal: signal});\n}\n\nexport function edit(requestData: BookingOfferPayload, id: number){\n return post('booking/offer/edit/' + id, requestData);\n}\n\nexport function create(requestData: BookingOfferPayload){\n return post('booking/offer/create', requestData);\n}\n\nexport function disable(id: number){\n return get('booking/offer/disable/' + id);\n}\n\nexport function show(id: number){\n return get('booking/offer/show/' + id);\n}\n\nexport function enable(id: number){\n return get('booking/offer/enable/' + id);\n}","export const ADD_BOOKING_OFFER = 'ADD_BOOKING_OFFER';\nexport const ADD_BOOKING_OFFER_SUCCESS = 'ADD_BOOKING_OFFER_SUCCESS';\nexport const ADD_BOOKING_OFFER_FAILURE = 'ADD_BOOKING_OFFER_FAILURE';\n\nexport const EDIT_BOOKING_OFFER = 'EDIT_BOOKING_OFFER';\nexport const EDIT_BOOKING_OFFER_SUCCESS = 'EDIT_BOOKING_OFFER_SUCCESS';\nexport const EDIT_BOOKING_OFFER_FAILURE = 'EDIT_BOOKING_OFFER_FAILURE';\n\nexport const FETCH_BOOKING_OFFERS = 'FETCH_BOOKING_OFFERS';\nexport const FETCH_BOOKING_OFFERS_SUCCESS = 'FETCH_BOOKING_OFFERS_SUCCESS';\nexport const FETCH_BOOKING_OFFERS_FAILURE = 'FETCH_BOOKING_OFFERS_FAILURE';\n\nexport const SHOW_BOOKING_OFFER = 'SHOW_BOOKING_OFFER';\nexport const SHOW_BOOKING_OFFER_SUCCESS = 'SHOW_BOOKING_OFFER_SUCCESS';\nexport const SHOW_BOOKING_OFFER_FAILURE = 'SHOW_BOOKING_OFFER_FAILURE';\n\nexport const CANCEL_BOOKING_OFFER_SUCCESS = 'CANCEL_BOOKING_OFFER_SUCCESS';","import * as types from \"../../../constants/booking/offer\";\nimport * as models from \"../../../models/booking/offer\";\n\nexport const addBookingOffer = () => {\n return {\n type: types.ADD_BOOKING_OFFER,\n }\n}\n\nexport const addBookingOfferSuccess = (bookingOffer: models.BookingOffer) => {\n return {\n type: types.ADD_BOOKING_OFFER_SUCCESS,\n bookingOffer: bookingOffer,\n }\n}\nexport const removeBookingOfferSuccess = (bookingOffer: models.BookingOffer) => {\n return {\n type: types.ADD_BOOKING_OFFER_SUCCESS,\n bookingOffer: bookingOffer,\n }\n}\n\nexport const addBookingOfferFailure = (error: string) => {\n return {\n type: types.ADD_BOOKING_OFFER_FAILURE,\n bookingOffer: null,\n bookingOffers: null,\n error: error\n }\n}\n\nexport const editBookingOffer = () => {\n return {\n type: types.EDIT_BOOKING_OFFER,\n }\n}\n\nexport const cancelBookingOfferSuccess = (bookingOffer: models.BookingOffer) => {\n return {\n type: types.CANCEL_BOOKING_OFFER_SUCCESS,\n bookingOffer: bookingOffer\n }\n}\n\nexport const editBookingOfferSuccess = (bookingOffer: models.BookingOffer) => {\n return {\n type: types.EDIT_BOOKING_OFFER_SUCCESS,\n bookingOffer: bookingOffer\n }\n}\n\nexport const editBookingOfferFailure = (error: string) => {\n return {\n type: types.EDIT_BOOKING_OFFER_FAILURE,\n bookingOffer: null,\n bookingOffers: null,\n error: error\n }\n}\n\nexport const fetchBookingOffers = () => {\n return {\n type: types.FETCH_BOOKING_OFFERS,\n }\n}\n\nexport const fetchBookingOffersFailure = (error: string) => {\n return {\n type: types.FETCH_BOOKING_OFFERS_FAILURE,\n bookingOffer: null,\n bookingOffers: [],\n error: error\n }\n}\n\nexport const fetchBookingOffersSuccess = (bookingOffers: models.BookingOffers) => {\n return {\n type: types.FETCH_BOOKING_OFFERS_SUCCESS,\n bookingOffer: null,\n bookingOffers: bookingOffers\n }\n}\n\n\nexport const showBookingOffer = () => {\n return {\n type: types.SHOW_BOOKING_OFFER,\n }\n}\nexport const showBookingOfferSuccess = (bookingOffer: models.BookingOffer) => {\n return {\n type: types.SHOW_BOOKING_OFFER_SUCCESS,\n bookingOffer: bookingOffer\n }\n}\nexport const showBookingOfferFailure = (error: string) => {\n return {\n type: types.SHOW_BOOKING_OFFER_FAILURE,\n bookingOffer: null,\n bookingOffers: null,\n error: error\n }\n}","import React, {useEffect} from \"react\";\nimport {RootStateOrAny, useDispatch, useSelector} from \"react-redux\";\nimport * as api from \"../../../adapters/booking/offer\"\nimport * as actions from \"../../../actions/booking/offer\"\nimport {openSidebar} from \"../../../actions/rightSidebar\";\nimport {LIST_BOOKING_OFFER} from \"../../../constants/rightSidebar\";\nimport {axiosError} from \"../../../actions/axios\";\nimport {BookingOffer} from \"../../../models/booking/offer\";\n\nconst DashboardBookingOffer:React.FC = () => {\n\n\n const dispatch = useDispatch();\n const state = useSelector((state: RootStateOrAny) => state);\n\n let now = new Date()\n now.setDate(now.getDate() + 30);\n\n useEffect(() => {\n const controller = new AbortController();\n\n dispatch(actions.fetchBookingOffers())\n api.list({}, controller.signal)\n .then(data => dispatch(actions.fetchBookingOffersSuccess(data.data)))\n .catch(error => dispatch(axiosError(error)))\n\n return () => controller.abort();\n }, [])\n\n return <>\n dispatch(openSidebar(LIST_BOOKING_OFFER, {status: 'pending'}))}>\n
\n
\n
\n \n Propositions de créneaux\n \n
\n
\n +30 jours\n \n
\n
\n {state.bookingOffer.isLoading ?
\n Loading...\n
:
{state.bookingOffer.payload.filter((bookingOffer: BookingOffer) => !bookingOffer.applicants.find(a => a.validated)).length}}\n
\n
\n
\n >\n}\n\nexport default DashboardBookingOffer;","import {get, post} from \"../xhr\";\n\nexport function save(requestData: {start: string, end: string}){\n return post(`counter/save`, requestData)\n}\n\nexport function saveSingle(requestData: {start: string, end: string}, salaryId: number){\n return post(`counter/save/${salaryId}`, requestData)\n}\n\nexport function sum(signal: AbortSignal ,requestData?: {date?: string}){\n return post(`counter/sum`, requestData || {}, {signal: signal})\n}\n\nexport function sumSingle(){\n return get(`counter/sum_single`)\n}\n\nexport function listTable(){\n return get(`counter/list_table`)\n}\n\nexport function edit(requestData: {signe: string, valueHour: number, valueMin: number, paidOverTimeHour: number, paidOverTimeMin: number}, id: number){\n return post(`counter/edit/${id}`, requestData)\n}\n\nexport function remove(id: number){\n return get(`counter/delete/${id}`)\n}\n\nexport function saveMany(salary: number, requestData: {wn: number, year: number, value: number}[]){\n return post(`counter/save_many/${salary}`, requestData)\n}\n\nexport function clearMany(salary: number, requestData: {wn: number, year: number}[]){\n return post(`counter/clear_many/${salary}`, requestData)\n}\n\nexport function editWeek(salary: number, requestData: {wn: number, year: number}){\n return post(`counter/edit_week/${salary}`, requestData)\n}","import React, {useEffect, useState} from \"react\";\nimport * as api from \"../../../adapters/counter\";\n\nconst DashboardCounter:React.FC = () => {\n\n\n const [counter, setCounter] = useState();\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n api.sumSingle().then(data => setCounter(data.data)).then(() => setIsLoading(false))\n }, [])\n\n return <>\n \n
\n
\n
\n \n Compteur\n \n
\n
\n à date\n \n
\n
\n {isLoading ?
\n Loading...\n
:
\n {!!counter && counter < 0 && }\n {!!counter && counter > 0 && }\n {counter}h\n }\n
\n
\n
\n >\n}\n\nexport default DashboardCounter;","import {get, post} from \"../../xhr\";\n\ninterface EventOfferPayload {\n description: string,\n start: Date,\n end: Date,\n salaries: number[],\n localisation?: number,\n activity?: number,\n}\n\nexport function list(requestData: {start?: Date, end?: Date}, signal: AbortSignal){\n return post('event/offer/list', requestData, {signal: signal});\n}\n\nexport function edit(requestData: EventOfferPayload, id: number){\n return post('event/offer/edit/' + id, requestData);\n}\n\nexport function create(requestData: EventOfferPayload){\n return post('event/offer/create', requestData);\n}\n\nexport function disable(id: number){\n return get('event/offer/disable/' + id);\n}\n\nexport function show(id: number){\n return get('event/offer/show/' + id);\n}\n\nexport function enable(id: number){\n return get('event/offer/enable/' + id);\n}","export const ADD_EVENT_OFFER = 'ADD_EVENT_OFFER';\nexport const ADD_EVENT_OFFER_SUCCESS = 'ADD_EVENT_OFFER_SUCCESS';\nexport const ADD_EVENT_OFFER_FAILURE = 'ADD_EVENT_OFFER_FAILURE';\n\nexport const EDIT_EVENT_OFFER = 'EDIT_EVENT_OFFER';\nexport const EDIT_EVENT_OFFER_SUCCESS = 'EDIT_EVENT_OFFER_SUCCESS';\nexport const EDIT_EVENT_OFFER_FAILURE = 'EDIT_EVENT_OFFER_FAILURE';\n\nexport const FETCH_EVENT_OFFERS = 'FETCH_EVENT_OFFERS';\nexport const FETCH_EVENT_OFFERS_SUCCESS = 'FETCH_EVENT_OFFERS_SUCCESS';\nexport const FETCH_EVENT_OFFERS_FAILURE = 'FETCH_EVENT_OFFERS_FAILURE';\n\nexport const SHOW_EVENT_OFFER = 'SHOW_EVENT_OFFER';\nexport const SHOW_EVENT_OFFER_SUCCESS = 'SHOW_EVENT_OFFER_SUCCESS';\nexport const SHOW_EVENT_OFFER_FAILURE = 'SHOW_EVENT_OFFER_FAILURE';\n\nexport const CANCEL_EVENT_OFFER_SUCCESS = 'CANCEL_EVENT_OFFER_SUCCESS';","import * as types from \"../../../constants/event/offer\";\nimport * as models from \"../../../models/event/offer\";\n\nexport const addEventOffer = () => {\n return {\n type: types.ADD_EVENT_OFFER,\n }\n}\n\nexport const addEventOfferSuccess = (eventOffer: models.EventOffer) => {\n return {\n type: types.ADD_EVENT_OFFER_SUCCESS,\n eventOffer: eventOffer,\n }\n}\nexport const removeEventOfferSuccess = (eventOffer: models.EventOffer) => {\n return {\n type: types.ADD_EVENT_OFFER_SUCCESS,\n eventOffer: eventOffer,\n }\n}\n\nexport const addEventOfferFailure = (error: string) => {\n return {\n type: types.ADD_EVENT_OFFER_FAILURE,\n eventOffer: null,\n eventOffers: null,\n error: error\n }\n}\n\nexport const editEventOffer = () => {\n return {\n type: types.EDIT_EVENT_OFFER,\n }\n}\n\nexport const cancelEventOfferSuccess = (eventOffer: models.EventOffer) => {\n return {\n type: types.CANCEL_EVENT_OFFER_SUCCESS,\n eventOffer: eventOffer\n }\n}\n\nexport const editEventOfferSuccess = (eventOffer: models.EventOffer) => {\n return {\n type: types.EDIT_EVENT_OFFER_SUCCESS,\n eventOffer: eventOffer\n }\n}\n\nexport const editEventOfferFailure = (error: string) => {\n return {\n type: types.EDIT_EVENT_OFFER_FAILURE,\n eventOffer: null,\n eventOffers: null,\n error: error\n }\n}\n\nexport const fetchEventOffers = () => {\n return {\n type: types.FETCH_EVENT_OFFERS,\n }\n}\n\nexport const fetchEventOffersFailure = (error: string) => {\n return {\n type: types.FETCH_EVENT_OFFERS_FAILURE,\n eventOffer: null,\n eventOffers: [],\n error: error\n }\n}\n\nexport const fetchEventOffersSuccess = (eventOffers: models.EventOffers) => {\n return {\n type: types.FETCH_EVENT_OFFERS_SUCCESS,\n eventOffer: null,\n eventOffers: eventOffers\n }\n}\n\n\nexport const showEventOffer = () => {\n return {\n type: types.SHOW_EVENT_OFFER,\n }\n}\nexport const showEventOfferSuccess = (eventOffer: models.EventOffer) => {\n return {\n type: types.SHOW_EVENT_OFFER_SUCCESS,\n eventOffer: eventOffer\n }\n}\nexport const showEventOfferFailure = (error: string) => {\n return {\n type: types.SHOW_EVENT_OFFER_FAILURE,\n eventOffer: null,\n eventOffers: null,\n error: error\n }\n}","import React, {useEffect} from \"react\";\nimport {RootStateOrAny, useDispatch, useSelector} from \"react-redux\";\nimport * as api from \"../../../adapters/event/offer\"\nimport * as actions from \"../../../actions/event/offer\"\nimport {openSidebar} from \"../../../actions/rightSidebar\";\nimport {FORM_NEW_ABSENCE, FORM_NEW_EVENT_OFFER, LIST_EVENT_OFFER} from \"../../../constants/rightSidebar\";\nimport {axiosError} from \"../../../actions/axios\";\nimport {EventOffer} from \"../../../models/event/offer\";\nimport * as accessRights from \"../../../constants/accessRight\";\nimport {Granted} from \"../../../security/granted\";\n\nconst DashboardEventOffer:React.FC = () => {\n\n\n const dispatch = useDispatch();\n const state = useSelector((state: RootStateOrAny) => state);\n\n let now = new Date()\n now.setDate(now.getDate() + 30);\n\n useEffect(() => {\n const controller = new AbortController();\n\n dispatch(actions.fetchEventOffers())\n api.list({}, controller.signal)\n .then(data => dispatch(actions.fetchEventOffersSuccess(data.data)))\n .catch(error => dispatch(axiosError(error)))\n\n return () => controller.abort();\n }, [])\n\n return <>\n \n
dispatch(openSidebar(LIST_EVENT_OFFER, {status: 'pending'}))}>\n
\n
\n
\n \n Propositions de créneaux\n \n
\n
\n +30 jours\n \n
\n
\n {state.eventOffer.isLoading ?
\n Loading...\n
:
{state.eventOffer.payload.filter((eventOffer: EventOffer) => !(eventOffer.applications.find(a => a.validated))).length}}\n
\n
\n
\n {Granted(accessRights.EDIT_BOOKING_OFFER) &&
}\n
\n\n >\n}\n\nexport default DashboardEventOffer;","import * as xhr from \"../xhr\";\n\ninterface listPayload {\n offset? : number,\n status? : number[],\n types? : number[],\n dates? : [string|null, string|null],\n salaries?: number[],\n companies?: number[],\n}\n\nexport function list(requestData: listPayload, signal: AbortSignal){\n return xhr.post('expense/list', requestData, {signal: signal});\n}\n\nexport function edit(requestData: any, id: number){\n return xhr.post('expense/edit/' + id.toString(), requestData);\n}\n\nexport function editStatus(requestData: { status: number }, id: number){\n return xhr.post(`expense/edit/${id}/status`, requestData);\n}\n\nexport function create(requestData: any, options?:xhr.Options){\n return xhr.post('expense/create', requestData, options);\n}\n\nexport function get(id: string){\n return xhr.get('expense/show/' + id);\n}\n\nexport function cancel(id: number){\n return xhr.get('expense/delete/' + id);\n}\n\nexport function downloadFile(id: string, options?:xhr.Options){\n return xhr.get('expense/justification/'+ id +'/download', options);\n}","import * as types from \"../../constants/expense\";\nimport * as models from \"../../models/expense\";\n\nexport const addExpense = () => {\n return {\n type: types.ADD_EXPENSE,\n }\n}\n\nexport const addExpenseSuccess = (expense: models.Expense) => {\n return {\n type: types.ADD_EXPENSE_SUCCESS,\n expense: expense,\n }\n}\n\nexport const addExpenseFailure = (error: string) => {\n return {\n type: types.ADD_EXPENSE_FAILURE,\n expense: null,\n expenses: null,\n error: error\n }\n}\n\nexport const editExpense = () => {\n return {\n type: types.EDIT_EXPENSE,\n }\n}\n\nexport const cancelExpenseSuccess = (expense: models.Expense) => {\n return {\n type: types.CANCEL_EXPENSE_SUCCESS,\n expense: expense\n }\n}\n\nexport const editExpenseSuccess = (expense: models.Expense) => {\n return {\n type: types.EDIT_EXPENSE_SUCCESS,\n expense: expense\n }\n}\n\nexport const editExpenseFailure = (error: string) => {\n return {\n type: types.EDIT_EXPENSE_FAILURE,\n expense: null,\n expenses: null,\n error: error\n }\n}\n\nexport const fetchExpenses = () => {\n return {\n type: types.FETCH_EXPENSES,\n }\n}\n\nexport const fetchExpensesFailure = (error: string) => {\n return {\n type: types.FETCH_EXPENSES_FAILURE,\n expense: null,\n expenses: [],\n error: error\n }\n}\n\nexport const fetchExpensesSuccess = (expenses: models.Expenses) => {\n return {\n type: types.FETCH_EXPENSES_SUCCESS,\n expense: null,\n expenses: expenses\n }\n}\n\n\nexport const showExpense = () => {\n return {\n type: types.SHOW_EXPENSE,\n }\n}\nexport const showExpenseSuccess = (expense: models.Expense) => {\n return {\n type: types.SHOW_EXPENSE_SUCCESS,\n expense: expense\n }\n}\nexport const showExpenseFailure = (error: string) => {\n return {\n type: types.SHOW_EXPENSE_FAILURE,\n expense: null,\n expenses: null,\n error: error\n }\n}","import React, {useState} from \"react\";\nimport {RootStateOrAny, useDispatch, useSelector} from \"react-redux\";\nimport {Expenses, Expense} from \"../../../../models/expense\";\nimport * as types from \"../../../../constants/expense\";\nimport * as globals from \"../../../../constants/global\";\nimport * as api from \"../../../../adapters/expense\";\nimport * as actions from \"../../../../actions/expense\";\nimport {Granted} from \"../../../../security/granted\";\nimport * as accessRights from \"../../../../constants/accessRight\";\nimport format from \"../../../../utils/locale\";\n\nconst DashboardExpenseRequestList:React.FC = () => {\n\n const expenses: Expenses = useSelector((state: RootStateOrAny) => state.expense.payload);\n const dispatch = useDispatch();\n\n const [statusLoading, setStatusLoading] = useState(false)\n\n const manageStatus = (status: number, expense: Expense) => {\n setStatusLoading(true)\n api.editStatus({status: status}, expense.id).then(resp => dispatch(actions.editExpenseSuccess(resp.data))).then(() => setStatusLoading(false))\n }\n\n return \n
\n
Demandes de note de frais
\n \n \n
\n
\n {expenses.filter(expense => expense.status === types.STATUS_PENDING).map(expense => - \n
\n
\n
\n {expense.salary.title} | {types.getTypeChoice(expense.type)?.label}\n
\n
{expense.title}
\n
{format(new Date(expense.dueDate))}
\n
\n {expense.amount} {globals.CurrencyIcon(expense.currency)}\n
\n
\n
\n
\n
\n
\n
\n
\n {types.getStatusChoices().filter(c => c.value !== expense.status).map(c => - manageStatus(c.value, expense)}\n className={'dropdown-item'}>\n {types.STATUS_NAMES[c.value]}\n
)}\n
\n
\n \n
\n
\n
\n )}\n
\n
\n
\n}\n\nexport default DashboardExpenseRequestList;","import React, {useEffect} from \"react\";\nimport {RootStateOrAny, useDispatch, useSelector} from \"react-redux\";\nimport * as api from \"../../../adapters/expense\"\nimport * as actions from \"../../../actions/expense\"\nimport {openSidebar} from \"../../../actions/rightSidebar\";\nimport {FORM_EXPENSE_ADD, FORM_NEW_ABSENCE, PENDING_ABSENCE_LIST} from \"../../../constants/rightSidebar\";\nimport * as accessRights from \"../../../constants/accessRight\";\nimport {Expense} from \"../../../models/expense\";\nimport {axiosError} from \"../../../actions/axios\";\nimport {Granted, GrantedAny} from \"../../../security/granted\";\nimport DashboardExpenseRequestList from \"./list\";\n\n\nconst DashboardExpenseRequest:React.FC = () => {\n\n\n const dispatch = useDispatch();\n const state = useSelector((state: RootStateOrAny) => state);\n\n useEffect(() => {\n const controller = new AbortController();\n\n dispatch(actions.fetchExpenses())\n api.list({}, controller.signal)\n .then(data => dispatch(actions.fetchExpensesSuccess(data.data)))\n .catch(error => dispatch(axiosError(error)))\n\n return () => controller.abort();\n }, [])\n\n return <>\n \n
\n
\n
\n
\n \n Notes de frais\n \n
\n
\n en attente\n \n
\n
\n {state.expense.isLoading ?
\n Loading...\n
:
{state.expense.payload.filter((expense: Expense) => expense.status === 1).length}}\n
\n
\n
\n {Granted(accessRights.EDIT_EXPENSE) &&
}\n
\n \n >\n}\n\nexport default DashboardExpenseRequest;","import React, {useEffect, useState} from \"react\";\nimport {RootStateOrAny, useSelector} from \"react-redux\";\nimport * as calendarTypes from \"../../../../constants/calendar\"\n\ninterface Interface {\n loading: boolean;\n signed: any[],\n handleClick: (origin: string) => any\n}\n\nconst DashboardTimeClockMissing:React.FC = (props) => {\n\n const {loading, signed, handleClick} = props;\n const state = useSelector((state: RootStateOrAny) => state);\n\n const [signedMissing, setSignedMissing] = useState([])\n\n useEffect(() => {\n setSignedMissing([...signed.filter((s: any) => s.eventType === calendarTypes.EVENT_TYPE_TIME_CLOCK_MISSING)])\n }, [signed])\n\n return <>\n handleClick('missing')}>\n
\n
\n
\n \n Absences\n \n
\n
\n + {state.auth.user.currentSalary.companyGroup.timeClockSettings?.lateAfter} minutes\n \n
\n
\n {loading ?
\n Loading...\n
:
{signedMissing.length}}\n
\n
\n
\n >\n}\n\nexport default DashboardTimeClockMissing;","import React, {useEffect, useState} from \"react\";\nimport {RootStateOrAny, useSelector} from \"react-redux\";\n\ninterface Interface {\n loading: boolean;\n signed: any[],\n handleClick: (origin: string) => any\n}\n\nconst DashboardTimeClockLate:React.FC = (props) => {\n\n const {loading, signed, handleClick} = props;\n const state = useSelector((state: RootStateOrAny) => state);\n\n const [signedLate, setSignedLate] = useState([])\n\n useEffect(() => {\n setSignedLate([...signed.filter((s: any) => s.isLate)])\n }, [signed])\n\n return <>\n handleClick('late')}>\n
\n
\n
\n \n Retards\n \n
\n
\n + {state.auth.user.currentSalary.companyGroup.timeClockSettings?.lateAfter} minutes\n \n
\n
\n {loading ?
\n Loading...\n
:
{signedLate.length}}\n
\n
\n
\n >\n}\n\nexport default DashboardTimeClockLate;","import React, {useEffect, useState} from \"react\";\nimport format from \"../../../../utils/locale\";\nimport * as calendarTypes from \"../../../../constants/calendar\";\nimport Loader from \"../../../../utils/loader\";\n\ninterface Interface {\n loading: boolean,\n signed: any[],\n refresh: (salary: number) => void,\n origin: string\n}\n\nconst TimeClockDashboardList:React.FC = (props) => {\n\n const {loading, signed, refresh, origin} = props;\n\n const [onTime, setOnTime] = useState(false);\n const [late, setLate] = useState(origin === 'late');\n const [missing, setMissing] = useState(origin === 'missing');\n const [clockInId, setClockInId] = useState();\n\n useEffect(() => {\n if (origin){\n switch (origin){\n case 'late':\n setLate(true);\n setMissing(false);\n setOnTime(false);\n break;\n case 'missing':\n setMissing(true);\n setLate(false);\n setOnTime(false);\n break;\n }\n }\n }, [origin])\n\n return \n
\n
Reporting badgeage
\n \n \n
\n
\n
\n {loading ? : signed.filter(s => applyFilters(s)).map(s => - \n
\n
\n
\n {s.salary.title}\n
\n \n {s.salary.information.job.title}\n \n \n
\n {s.eventType === calendarTypes.EVENT_TYPE_TIME_CLOCK_MISSING && <>\n
\n
\n Absent\n
\n \n
\n Prévu à {format(new Date(s.start), 'HH:mm')}\n \n >}\n {s.isLate && <>\n
\n Retard\n
\n
\n Retard de {s.lateOfCaption}\n \n >}\n {!(s.eventType === calendarTypes.EVENT_TYPE_TIME_CLOCK_MISSING) && !s.isLate && <>\n
\n Arrivé à {format(new Date(s.start), 'HH:mm')}\n
\n >}\n
\n
\n )}\n
\n
\n
\n\n function applyFilters(s: any){\n\n if ([calendarTypes.EVENT_TYPE_BOOKING, calendarTypes.EVENT_TYPE_BOOKING_EXCEPTION, calendarTypes.EVENT_TYPE_EVENT, calendarTypes.EVENT_TYPE_EVENT_EXCEPTION].includes(s.eventType)) return false;\n if (s.isLate) return late;\n if (s.eventType === calendarTypes.EVENT_TYPE_TIME_CLOCK_MISSING) return missing;\n\n return onTime;\n }\n}\n\nexport default TimeClockDashboardList;","import React, {useEffect, useState} from \"react\";\nimport * as api from \"../../../adapters/calendar\";\nimport format from \"../../../utils/locale\";\nimport * as calendarTypes from \"../../../constants/calendar\"\nimport DashboardTimeClockMissing from \"./missing\";\nimport DashboardTimeClockLate from \"./late\";\nimport TimeClockDashboardList from \"./list\";\nimport {Offcanvas} from \"bootstrap\";\n\nconst DashboardTimeClock: React.FC = () => {\n\n const [signed, setSigned] = useState([])\n const [loading, setIsLoading] = useState(true)\n const [origin, setOrigin] = useState('');\n let today = new Date();\n let tomorrow = new Date(new Date().setDate(new Date().getDate() + 1))\n\n useEffect(() => {\n fetchSigned();\n }, [])\n\n return <>\n \n \n
\n \n \n
\n \n >\n\n function fetchSigned(){\n setIsLoading(true);\n api.test({\n start: format(today, 'uuuu-MM-dd'),\n end: format(tomorrow, 'uuuu-MM-dd'),\n calendar: calendarTypes.CALENDAR_SIGNED_REPORTING\n }).then((resp) => {\n setSigned(resp.data.signed)\n setIsLoading(false);\n })\n }\n\n function refresh(salaryId: number){\n api.test({\n start: format(today, 'uuuu-MM-dd'),\n end: format(tomorrow, 'uuuu-MM-dd'),\n calendar: calendarTypes.CALENDAR_SIGNED_REPORTING,\n options: {\n salary: salaryId\n }\n }).then((resp) => {\n setSigned([...signed.filter(s => s.salary.id !== salaryId), ...resp.data.signed])\n })\n }\n\n function handleClick(origin: string){\n setOrigin(origin)\n let el = document.getElementById('offcanvasTimeClockDashboardList')\n if (el){\n let offcanvas = new Offcanvas(el);\n offcanvas.toggle(el);\n }\n }\n}\n\nexport default DashboardTimeClock;","import React, {useEffect, useState} from \"react\";\nimport BootstrapSelect from \"../../../../utils/bootstrapSelect\";\nimport {useDispatch} from \"react-redux\";\nimport * as Yup from \"yup\";\nimport {useFormik} from \"formik\";\nimport FormError from \"../../../../utils/formError\";\nimport * as exceptionApi from \"../../../../adapters/event/exception\";\nimport DatePicker from \"react-datepicker\";\nimport validationClass from \"../../../../utils/validationClass\";\nimport DateCustomInput from \"../../../../utils/customInput\";\nimport {Salary} from \"../../../../models/salary\";\nimport {Company} from \"../../../../models/companies\";\nimport {AccountingTypes, getAccountingTypeChoice} from \"../../../../constants/booking\";\nimport {showAlertSuccess} from \"../../../../actions/alert\";\nimport * as types from \"../../../../constants/calendar\";\nimport {Activity} from \"../../../../models/activity\";\nimport {Localisation} from \"../../../../models/localisation\";\nimport * as accessRightsTypes from \"../../../../constants/accessRight\";\nimport SalarySelector from \"../../../salary/selector\";\n\ninterface Interface {\n values: {\n start: Date\n end: Date\n salary: Salary\n company: Company\n accountingType: number\n activity?: Activity\n localisation?: Localisation\n eventType: string\n eventId?: number\n exceptionId?: number,\n comment?: string\n },\n handleSubmitSuccess: (ev: any) => any;\n}\n\nconst EventEditForm:React.FC = (props) => {\n\n const {values, handleSubmitSuccess} = props;\n\n const dispatch = useDispatch();\n const [salary, setSalary] = useState(values.salary)\n const [company, setCompany] = useState(values.company)\n\n const initialValues = {\n salary: salary.id,\n start: values.start,\n end: values.end,\n accountingType: values.accountingType,\n company: values.company.id,\n activity: values.activity?.id,\n localisation: values.localisation?.id,\n comment: values.comment || '',\n }\n\n const validationSchema = Yup.object().shape({\n salary: Yup.number().required('Veuillez séléctionner un collaborateur dans la liste ci-dessus'),\n start: Yup.date().required(),\n end: Yup.date().required().test(\"is-greater\", \"La fin doit être après le début\", function(value: any) {\n const { start } = this.parent;\n return value && start < value\n }),\n company: Yup.number().required(),\n activity: Yup.number().nullable(),\n localisation: Yup.number().nullable(),\n accountingType: Yup.number().required(),\n comment: Yup.string().nullable(),\n })\n\n const formik = useFormik({\n initialValues: initialValues,\n validationSchema: validationSchema,\n onSubmit: (_values, formikHelpers) => {\n switch (values.eventType){\n case types.EVENT_TYPE_EVENT:\n exceptionApi.create({..._values, exdate: values.start}, values.eventId!).then(resp => {\n Promise.all([\n handleSubmitSuccess(resp.data)\n ]).then(() => {\n dispatch(showAlertSuccess('Créneau mis à jour'));\n formikHelpers.setSubmitting(false)\n })\n })\n break;\n case types.EVENT_TYPE_EVENT_EXCEPTION:\n exceptionApi.edit(_values, values.exceptionId!).then(resp => {\n Promise.all([\n handleSubmitSuccess(resp.data)\n ]).then(() => {\n dispatch(showAlertSuccess('Créneau ajouté'));\n formikHelpers.setSubmitting(false)\n })\n })\n break;\n }\n }\n })\n\n return \n}\n\nexport default EventEditForm;","import React, {useEffect, useState} from \"react\";\nimport EventEditForm from \"../../../event/edit/form\";\nimport {EventClickArg} from \"@fullcalendar/react\";\n\nconst CalendarEventEdit:React.FC<{arg?: EventClickArg, handleSubmitSuccess: (ev: any) => any, close: () => any}> = (props) => { \n const {arg, handleSubmitSuccess, close} = props;\n \n const [key, setKey] = useState(0);\n\n const handleSubmit = (ev: any) => {\n return Promise.all([\n handleSubmitSuccess(ev)\n ])\n .then(() => close())\n .then(() => true)\n }\n\n useEffect(() => {\n setKey(prevState => prevState + 1);\n }, [arg])\n\n return <>\n \n
Modifier un créneau
\n \n \n \n {arg && }\n
\n >\n}\n\nexport default CalendarEventEdit;","import React, {useEffect, useState} from \"react\";\nimport EventEditForm from \"../../../../event/edit/form\";\nimport {EventResizeDoneArg} from \"@fullcalendar/interaction\";\n\nconst EventResizeEdit:React.FC<{arg?: EventResizeDoneArg, handleSubmitSuccess: (ev: any) => any, close: () => any}> = (props) => {\n\n const {arg, handleSubmitSuccess, close} = props;\n const [key, setKey] = useState(0);\n\n\n useEffect(() => {\n const el = document.getElementById('offcanvasCalendarEvent')! as HTMLDivElement;\n el.addEventListener('hide.bs.offcanvas', cancelResize)\n\n return () => el?.removeEventListener('hide.bs.offcanvas', cancelResize)\n }, [arg])\n\n const cancelResize = () => {\n if (arg && arg.oldEvent){\n arg.event.setDates(arg.oldEvent.start!, arg.oldEvent.end!);\n }\n }\n\n const handleSubmit = (ev: any) => {\n return Promise.all([\n handleSubmitSuccess(ev)\n ])\n .then(() => close())\n .then(() => true)\n }\n\n\n return <>\n \n
Modifier un créneau
\n \n \n \n {arg && }\n
\n >\n}\n\nexport default EventResizeEdit;","import * as xhr from \"../xhr\";\nimport {get, post} from \"../xhr\";\n\ninterface requestData {\n start: Date,\n end: Date,\n week?: number,\n daysOfWeek: string[],\n accountingType: number,\n company: number,\n activity: string,\n localisation: string,\n weekNumber?: number,\n year?: number,\n salary?: number,\n template?: number,\n}\n\nexport function create(requestData: requestData){\n return post(`event/create`, requestData);\n}\n\nexport function edit(requestData: requestData, eventId: number){\n return post(`event/${eventId}/edit`, requestData);\n}\n\nexport function cancel(eventId: number){\n return get(`event/${eventId}/cancel`);\n}\n\nexport function cancelOnce(event: number, requestData: any){\n return xhr.post(`event/${event}/cancel_once`, requestData);\n}\n\nexport function labourDayWorked(eventId: number, requestData: any){\n return xhr.post(`event/${eventId}/labour_day`, requestData);\n}\n\nexport function sub(eventId: number, substituteId: number, requestData: {exDate: string}){\n return xhr.post(`event/${eventId}/substitute/${substituteId}`, requestData);\n}","import React, {useEffect, useState} from \"react\";\nimport {EventClickArg} from \"@fullcalendar/react\";\nimport format from \"../../../../utils/locale\";\nimport {getAccountingTypeChoice} from \"../../../../constants/booking\";\nimport * as exceptionApi from \"../../../../adapters/event/exception\";\nimport * as eventApi from \"../../../../adapters/event\";\nimport * as exchangeApi from \"../../../../adapters/eventExchange\";\nimport * as absenceApi from \"../../../../adapters/absence\";\nimport * as calendarTypes from \"../../../../constants/calendar\";\nimport {TYPE_EVENT, TYPE_EVENT_EXCEPTION} from \"../../../../constants/event\";\nimport SmallLoader from \"../../../../utils/loader/small\";\nimport {showAlertSuccess} from \"../../../../actions/alert\";\nimport {useDispatch} from \"react-redux\";\nimport * as accessRights from \"../../../../constants/accessRight\";\nimport {Granted} from \"../../../../security/granted\";\nimport {TYPE_CP} from \"../../../../constants/absence\";\n\ninterface Interface {\n arg: EventClickArg,\n handleEventChange: (ev: any) => any,\n calendar: string,\n setCalendarAbsenceSidebarProps: React.Dispatch,\n setCalendarEventSidebarProps: React.Dispatch,\n close: () => any,\n setCalendarSignedSidebarProps: React.Dispatch,\n}\n\nconst EventShow:React.FC = (props) => {\n\n const {arg, handleEventChange, calendar, setCalendarAbsenceSidebarProps, setCalendarSignedSidebarProps, setCalendarEventSidebarProps, close} = props;\n\n const dispatch = useDispatch();\n const [removingEvent, setRemovingEvent] = useState(false)\n const [removingAbsence, setRemovingAbsence] = useState(false)\n\n const removeEvent = () => {\n if (arg){\n setRemovingEvent(true)\n switch (arg.event.extendedProps.eventType){\n case TYPE_EVENT:\n eventApi.cancelOnce(arg.event.extendedProps.eventId, {\n start: arg.event.start,\n end: arg.event.end,\n accountingType: arg.event.extendedProps.accountingType,\n salary: arg.event.extendedProps.salary.id,\n company: arg.event.extendedProps.company.id,\n localisation: arg.event.extendedProps.localisation?.id,\n activity: arg.event.extendedProps.activity?.id,\n comment: arg.event.extendedProps.comment,\n exdate: arg.event.start\n }).then((resp) => removeEventSuccess(resp.data));\n break;\n case TYPE_EVENT_EXCEPTION:\n exceptionApi.cancel(arg.event.extendedProps.exceptionId).then((resp) => removeEventSuccess(resp.data));\n break;\n }\n }\n }\n\n const [absenceInfoLoading, setAbsenceInfoLoading] = useState(false);\n const [nbDays, setNbDays] = useState()\n const [nextWorkingDay, setNextWorkingDay] = useState()\n useEffect(() => {\n setNbDays(undefined);\n setNextWorkingDay(undefined);\n if (arg.event.extendedProps.absence){\n setAbsenceInfoLoading(true)\n absenceApi.days(arg.event.extendedProps.absence.id).then(resp => {\n setNbDays(resp.data.nbDays);\n if (resp.data.nextWorkingDay){\n setNextWorkingDay(resp.data.nextWorkingDay);\n }\n\n setAbsenceInfoLoading(false);\n })\n }\n }, [arg.event.extendedProps.absence])\n\n const [removingSub, setRemovingSub] = useState(false)\n const cancelSub = () => {\n setRemovingSub(true)\n exceptionApi.removeSub(arg.event.extendedProps.exceptionId)\n .then(() => removeSubSuccess(arg.event.extendedProps));\n }\n\n const [removingExchange, setRemovingExchange] = useState(false)\n const cancelExchange = () => {\n setRemovingExchange(true)\n exchangeApi.cancel(arg.event.extendedProps.exchangeId)\n .then(resp => removeExchangeSuccess({ids: [resp.data.finalEvent.salary.id, resp.data.finalTarget.salary.id]}));\n }\n\n const removeAbsence = () => {\n if (arg.event.extendedProps.absence){\n setRemovingAbsence(true);\n absenceApi.cancel(arg.event.extendedProps.absence.id).then((data) => removeAbsenceSuccess(data.data))\n }\n }\n\n const removeEventSuccess = (ev: any) => {\n return Promise.all([\n handleEventChange(ev)\n ])\n .then(() => dispatch(showAlertSuccess(\"Créneau supprimé\")))\n .then(() => close())\n .then(() => setRemovingEvent(false))\n .then(() => true)\n }\n\n const removeSubSuccess = (ev: any) => {\n return Promise.all([\n handleEventChange(ev)\n ])\n .then(() => close())\n .then(() => dispatch(showAlertSuccess(\"Remplacement supprimé\")))\n .then(() => setRemovingSub(false))\n .then(() => true)\n }\n\n const removeExchangeSuccess = (ev: any) => {\n return Promise.all([\n handleEventChange(ev)\n ])\n .then(() => close())\n .then(() => dispatch(showAlertSuccess(\"Échange supprimé\")))\n .then(() => setRemovingSub(false))\n .then(() => true)\n }\n\n const removeAbsenceSuccess = (ev: any) => {\n return Promise.all([\n handleEventChange(ev)\n ])\n .then(() => setRemovingAbsence(false))\n .then(() => dispatch(showAlertSuccess('Absence supprimé')))\n .then(() => close())\n }\n\n const setLabourDayWorked = (worked: boolean) => {\n if (arg){\n switch (arg.event.extendedProps.eventType){\n case TYPE_EVENT:\n exceptionApi.create( {\n start: arg.event.start,\n end: arg.event.end,\n accountingType: arg.event.extendedProps.accountingType,\n salary: arg.event.extendedProps.salary.id,\n company: arg.event.extendedProps.company.id,\n localisation: arg.event.extendedProps.localisation?.id,\n activity: arg.event.extendedProps.activity?.id,\n comment: arg.event.extendedProps.comment,\n labourDayWorked: worked,\n exdate: arg.event.start,\n }, arg.event.extendedProps.eventId)\n .then((resp) => handleEventChange(resp.data))\n .then(() => close());\n break;\n case TYPE_EVENT_EXCEPTION:\n exceptionApi.edit({\n start: arg.event.start,\n end: arg.event.end,\n accountingType: arg.event.extendedProps.accountingType,\n salary: arg.event.extendedProps.salary.id,\n company: arg.event.extendedProps.company.id,\n localisation: arg.event.extendedProps.localisation?.id,\n activity: arg.event.extendedProps.activity?.id,\n labourDayWorked: worked,\n comment: arg.event.extendedProps.comment,\n }, arg.event.extendedProps.exceptionId)\n .then((resp) => handleEventChange(resp.data))\n .then(() => close());\n break;\n }\n }\n }\n\n return <>\n \n
Créneau de {arg.event.extendedProps.salary.title}
\n \n \n {\n
\n Détails du créneau\n
\n
\n
\n
\n \n \n Début\n | \n \n {format(arg.event.start!, \"E dd MMMM uuuu HH:mm\")}\n | \n
\n \n \n Fin\n | \n \n {format(arg.event.end!, \"E dd MMMM uuuu HH:mm\")}\n | \n
\n \n \n Type d'heure\n | \n \n {getAccountingTypeChoice(arg.event.extendedProps.accountingType)?.label}\n | \n
\n \n \n Établissement\n | \n \n {arg.event.extendedProps.company?.title || }\n | \n
\n \n \n Emplacement\n | \n \n {arg.event.extendedProps.localisation?.title || }\n | \n
\n \n \n Activité\n | \n \n {arg.event.extendedProps.activity?.title || }\n | \n
\n \n \n Commentaire\n | \n \n {arg.event.extendedProps.comment || }\n | \n
\n \n \n\n {arg.event.extendedProps.substitution &&
\n
\n Remplacement de {arg.event.extendedProps.substituted.title}\n
\n {Granted(accessRights.EDIT_BOOKING, arg.event.extendedProps.salary.id) &&
\n \n
}\n
}\n\n {Granted(accessRights.EDIT_BOOKING, arg.event.extendedProps.salary.id) && arg.event.extendedProps.isSlotExchange &&
\n
\n {arg.event.extendedProps.salary.title} {arg.event.extendedProps.exchanged.title}\n
\n
\n \n
\n
}\n\n {Granted(accessRights.EDIT_BOOKING, arg.event.extendedProps.salary.id) && !arg.event.extendedProps.substitution && arg.event.extendedProps.substitute &&
\n
\n Remplacé.e par {arg.event.extendedProps.substitute.title}\n
\n
\n \n
\n
}\n\n
\n {Granted(accessRights.EDIT_BOOKING, arg.event.extendedProps.salary.id) &&
\n \n
}\n {Granted(accessRights.DELETE_BOOKING, arg.event.extendedProps.salary.id) &&
\n \n
}\n
\n
\n\n
\n {Granted(accessRights.EDIT_BOOKING, arg.event.extendedProps.salary.id) &&
\n {!arg.event.extendedProps.substitution &&
\n \n
}\n
}\n {Granted(accessRights.EDIT_BOOKING, arg.event.extendedProps.salary.id) &&
\n {!arg.event.extendedProps.substitution &&
\n \n
}\n
}\n
\n\n {Granted(accessRights.EDIT_TIME_CLOCK, arg.event.extendedProps.salary.id) && calendarTypes.CALENDAR_SIGNED_GLOBAL === calendar && <>\n
\n \n
\n >}\n\n {arg.event.extendedProps.isLabourDay &&
\n
\n
\n Jour férié\n
\n
\n Cochez la case ci dessous si le collaborateur travail ce jour.\n
\n
\n setLabourDayWorked(e.target.checked)} type=\"checkbox\" id=\"labourDayWorked\"/>\n \n
\n
}\n\n {arg.event.extendedProps.absence &&
\n
\n
\n Absence\n
\n
\n \n \n \n Type\n | \n \n {arg.event.extendedProps.absence.typeName}\n | \n
\n \n \n Début\n | \n \n {format(new Date(arg.event.extendedProps.absence.start))}\n | \n
\n \n \n Fin\n | \n \n {format(new Date(arg.event.extendedProps.absence.end))}\n | \n
\n {arg.event.extendedProps.absence.type === TYPE_CP && \n \n Jour de reprise prévu\n | \n \n {absenceInfoLoading ? : (nextWorkingDay ? format(new Date(nextWorkingDay)) : )}\n | \n
}\n \n \n Nb de jours\n | \n \n {absenceInfoLoading ? : (nbDays ? nbDays : )}\n | \n
\n \n
\n
\n {Granted(accessRights.EDIT_ABSENCE, arg.event.extendedProps.salary.id) &&
\n \n
}\n {Granted(accessRights.DELETE_ABSENCE, arg.event.extendedProps.salary.id) &&
\n \n
}\n
\n
}\n\n
}\n >\n}\n\nexport default EventShow;","import moment from 'moment'\nimport 'moment/locale/fr'\n\nmoment.locale('fr')\n\nexport default moment","import React, {useEffect, useState} from \"react\";\nimport format from \"../../../../utils/locale\";\nimport * as Yup from \"yup\";\nimport {useFormik} from \"formik\";\nimport * as api from \"../../../../adapters/event\";\nimport {showAlertSuccess} from \"../../../../actions/alert\";\nimport BootstrapSelect from \"../../../../utils/bootstrapSelect\";\nimport validationClass from \"../../../../utils/validationClass\";\nimport {Salary} from \"../../../../models/salary\";\nimport FormError from \"../../../../utils/formError\";\nimport DatePicker from \"react-datepicker\";\nimport DateCustomInput from \"../../../../utils/customInput\";\nimport {AccountingTypes} from \"../../../../constants/booking\";\nimport {Company} from \"../../../../models/companies\";\nimport {Activity} from \"../../../../models/activity\";\nimport {Localisation} from \"../../../../models/localisation\";\nimport {useDispatch} from \"react-redux\";\nimport * as accessRightsTypes from \"../../../../constants/accessRight\";\nimport SalarySelector from \"../../../salary/selector\";\nimport {setSeconds} from \"date-fns\";\nimport moment from \"../../../../utils/moment.utils\";\n\ninterface Interface {\n start?: Date,\n end?: Date,\n initialSalary?: Salary,\n initialCompany?: Company,\n activity?: Activity,\n localisation?: Localisation,\n handleSubmitSuccess: (props: any[]) => any\n}\n\nconst EventAddForm:React.FC = (props) => {\n\n const {initialSalary, initialCompany, start, end, localisation, activity, handleSubmitSuccess} = props;\n\n const dispatch = useDispatch();\n const [salary, setSalary] = useState(initialSalary)\n //const [company, setCompany] = useState(initialCompany)\n\n const initialValues: any = {\n salary: salary?.id,\n start: start || new Date(),\n end: end || new Date(),\n accountingType: 1,\n company: initialCompany?.id,\n activity: activity?.id,\n localisation: localisation?.id,\n daysOfWeek: [String(Number(format(start || new Date(), 'i')) - 1)],\n weekNumber: moment(start).isoWeek(),\n year: moment(start).weekYear(),\n comment: \"\"\n }\n\n const validationSchema = Yup.object().shape({\n salary: Yup.number().required('Veuillez séléctionner un collaborateur dans la liste ci-dessus'),\n start: Yup.date().required(),\n end: Yup.date().required().test(\"is-greater\", \"La fin doit être après le début\", function(value: any) {\n const { start } = this.parent;\n\n if (!value) return false;\n\n if (start.getTime() > value.getTime()) {\n\n let clone = setSeconds(new Date(value), 0)\n clone.setDate(value.getDate() + 1)\n\n return clone.getTime() > start.getTime();\n }\n\n return value && start < value\n }),\n company: Yup.number().required(),\n activity: Yup.number().nullable(),\n localisation: Yup.number().nullable(),\n accountingType: Yup.number().required(),\n daysOfWeek: Yup.array().of(Yup.number()).min(1),\n weekNumber: Yup.number().required(),\n year: Yup.number().required(),\n comment: Yup.string().nullable(),\n })\n\n const formik = useFormik({\n initialValues: initialValues,\n validationSchema: validationSchema,\n onSubmit: (values, formikHelpers) => {\n api.create(values).then(resp => {\n Promise.all([\n handleSubmitSuccess(resp.data)\n ]).then(() => {\n dispatch(showAlertSuccess('Créneau ajouté'));\n formikHelpers.setSubmitting(false)\n })\n });\n }\n })\n\n return \n}\n\nexport default EventAddForm;","import React, {useEffect, useState} from \"react\";\nimport EventAddForm from \"../../../event/add/form\";\nimport {Salary} from \"../../../../models/salary\";\nimport {Company} from \"../../../../models/companies\";\nimport {Activity} from \"../../../../models/activity\";\nimport {Localisation} from \"../../../../models/localisation\";\nimport {setMinutes} from \"date-fns\";\n\nconst EventAdd:React.FC<{close: () => any, handleSubmitSuccess: (ev: any[]) => any, dt: Date, salary?: Salary, company?: Company, localisation?: Localisation, activity?: Activity}> = (props) => {\n\n const {handleSubmitSuccess, salary, company, activity, localisation, close, dt} = props;\n\n const [key, setKey] = useState(0);\n\n const handleSubmit = (ev: any) => {\n return Promise.all([\n handleSubmitSuccess(ev)\n ])\n .then(() => close())\n .then(() => true)\n }\n\n useEffect(() => {\n setKey(prevState => prevState + 1);\n }, [salary, company, activity, localisation])\n\n return <>\n \n
Ajouter un créneau
\n \n \n \n \n
\n >\n}\n\nexport default EventAdd;","import React, {useEffect, useState} from \"react\";\nimport {EventDropArg} from \"@fullcalendar/react\";\nimport EventAddForm from \"../../../../event/add/form\";\n\ninterface Interface {\n arg: EventDropArg,\n handleSubmitSuccess: (props: any[]) => any,\n close: () => any\n}\n\nconst EventDrop:React.FC = (props) => {\n\n const {arg, handleSubmitSuccess, close} = props;\n const [key, setKey] = useState(1);\n\n useEffect(() => {\n const el = document.getElementById('offcanvasCalendarEvent')! as HTMLDivElement;\n el.addEventListener('hide.bs.offcanvas', cancelDrop)\n setKey(prevState => prevState + 1)\n\n return () => el?.removeEventListener('hide.bs.offcanvas', cancelDrop)\n }, [arg])\n\n const cancelDrop = () => {\n if (arg.oldEvent){\n arg?.event.setDates(arg?.oldEvent.start!, arg.oldEvent.end);\n if (arg.oldResource){\n arg.event.setResources([arg.oldResource])\n }\n }\n }\n\n const handleSubmit = (ev: any) => {\n cancelDrop();\n\n return Promise.all([\n handleSubmitSuccess(ev)\n ])\n .then(() => close())\n .then(() => true)\n }\n\n return <>\n \n
Ajouter un créneau
\n \n \n \n \n
\n >\n}\n\nexport default EventDrop;","import React, {useEffect, useState} from \"react\";\nimport {DateSelectArg} from \"@fullcalendar/react\";\nimport EventAddForm from \"../../../../event/add/form\";\nimport {Salary} from \"../../../../../models/salary\";\nimport {Company} from \"../../../../../models/companies\";\nimport {Activity} from \"../../../../../models/activity\";\nimport {Localisation} from \"../../../../../models/localisation\";\nimport {setMinutes} from \"date-fns\";\n\ninterface Interface {\n arg?: DateSelectArg,\n salary?: Salary,\n company?: Company,\n activity?: Activity,\n localisation?: Localisation,\n handleSubmitSuccess: (props: any[]) => any,\n close: () => any,\n}\n\nconst EventSelect:React.FC = (props) => {\n\n const {handleSubmitSuccess, close, arg, salary, company, activity, localisation} = props;\n const [key, setKey] = useState(1);\n\n const handleSubmit = (ev: any) => {\n return Promise.all([\n handleSubmitSuccess(ev)\n ])\n .then(() => close())\n .then(() => true)\n }\n\n useEffect(() => {\n setKey(prevState => prevState + 1)\n }, [arg])\n\n return <>\n \n
Ajouter un créneau
\n \n \n \n {arg && }\n
\n >\n}\n\nexport default EventSelect;","import React, {useEffect, useState} from \"react\";\nimport {EventClickArg} from \"@fullcalendar/react\";\nimport * as eventApi from \"../../../../adapters/event\";\nimport * as salaryApi from \"../../../../adapters/salary\";\nimport format from \"../../../../utils/locale\";\nimport Loader from \"../../../../utils/loader\";\nimport BootstrapSelect from \"../../../../utils/bootstrapSelect\";\nimport {Salaries, Salary} from \"../../../../models/salary\";\nimport {showAlertSuccess} from \"../../../../actions/alert\";\nimport {useDispatch} from \"react-redux\";\n\ninterface Interface {\n arg: EventClickArg,\n handleSubmitSuccess: (ev: any) => any,\n close: () => any,\n}\n\nconst EventSubstitute:React.FC = (props) => {\n const {arg, handleSubmitSuccess, close} = props;\n const dispatch = useDispatch()\n\n const [loading, setLoading] = useState(false)\n const [jobs, setJobs] = useState([])\n const [salaries, setSalaries] = useState<(Salary & {rate: string, counter: string, counterDuration: number})[]>([])\n\n useEffect(() => {\n\n if (arg){\n setLoading(true)\n salaryApi.available({\n beginAt: format(arg.event.start!, 'uuuu-MM-dd HH:mm:ss'),\n endAt: format(arg.event.end!, 'uuuu-MM-dd HH:mm:ss'),\n options: {\n companies: [arg.event.extendedProps.company.id],\n jobs: jobs\n }\n }).then(resp => setSalaries(resp.data))\n .then(() => setLoading(false))\n }\n\n\n }, [arg, jobs])\n\n const handleSelectChange = (salary: Salary) => {\n setLoading(true)\n\n eventApi.sub(arg.event.extendedProps.eventId, salary.id, {exDate: format(arg.event.start!, 'uuuu-MM-dd')})\n .then((resp) => Promise.all([\n handleSubmitSuccess(resp.data)\n ]).then(() => {\n dispatch(showAlertSuccess('Créneau ajouté'));\n }).then(() => true))\n .then(() => close())\n .then(() => setLoading(false))\n }\n\n return <>\n \n
Remplacer le créneau de {arg?.event.extendedProps.salary.title}
\n \n \n \n
\n \n \n \n Horaires\n | \n \n {format(arg.event.start!, 'E dd MMMM uuuu HH:mm')} { format(arg.event.end!, 'E dd MMMM uuuu HH:mm')}\n | \n
\n \n \n Établissement\n | \n \n {arg.event.extendedProps.company.title}\n | \n
\n \n
\n \n
\n setJobs(choices?.map(c => Number(c.value)) || [])}\n />\n
\n\n
\n {loading &&
}\n {!loading &&
\n {salaries.map(salary => - handleSelectChange(salary)}>\n
\n
\n
\n {salary.title}\n
\n
\n {salary.information?.job.title}\n
\n
\n
\n \n {salary.rate} \n \n \n {salary.counterDuration < 0 ?\n \n : (salary.counterDuration > 0 ?\n \n : )\n } {salary.counter}\n \n
\n
\n )}\n
}\n
\n
\n >\n}\n\nexport default EventSubstitute;","import React, {useEffect, useState} from \"react\";\nimport format from \"../../../../utils/locale\";\nimport * as api from \"../../../../adapters/eventExchange\";\nimport {Salary} from \"../../../../models/salary\";\nimport {Company} from \"../../../../models/companies\";\nimport FullCalendar, {EventClickArg} from \"@fullcalendar/react\";\nimport listPlugin from \"@fullcalendar/list\";\nimport {CalendarTitle} from \"../../utils\";\nimport allLocales from \"@fullcalendar/core/locales-all\";\nimport {useDispatch} from \"react-redux\";\nimport {showAlertSuccess} from \"../../../../actions/alert\";\nimport Loader from \"../../../../utils/loader\";\nimport SmallLoader from \"../../../../utils/loader/small\";\nimport getMaxVisibilityDate from \"../../../../security/getMaxDate\";\n\n\ninterface Interface {\n arg: EventClickArg,\n handleSubmitSuccess: (ev: any) => any,\n close: () => any,\n}\n\nconst CalendarEventExchange:React.FC = (props) => {\n\n const {close, arg, handleSubmitSuccess} = props;\n\n const dispatch = useDispatch();\n const [pickerDate, setPickerDate] = useState(new Date());\n const [title, setTitle] = useState('');\n const calendarRef = React.createRef();\n const [selected, setSelected] = useState()\n const [submiting, setSubmiting] = useState(false)\n const [endDate, setEndDate] = useState(arg.view.activeEnd);\n\n const [jobs, setJobs] = useState([])\n const [isLoading, setIsLoading] = useState(true)\n const [isSameDuration, setIsSameDuration] = useState(true)\n const [slots, setSlots] = useState<{\n start: string,\n end: string,\n timeCaption: string,\n timeDiff: number,\n timeDiffCaption: string,\n salary: Salary,\n company: Company,\n eventId: number,\n initialStart: string,\n }[]>([])\n\n\n useEffect(() => fetchCalendar(), [isSameDuration]);\n\n function validate()\n {\n if (selected){\n setSubmiting(true)\n api.create({\n event: arg.event.extendedProps.eventId,\n exDate: arg.event.extendedProps.initialStart,\n target: selected.event.extendedProps.eventId,\n targetExDate: selected.event.extendedProps.initialStart\n }).then(() => handleSubmitSuccess({salaries: [arg.event.extendedProps.salary, selected.event.extendedProps.salary]}))\n .then(() => setSubmiting(false))\n .then(() => dispatch(showAlertSuccess('Créneau échangé')))\n .then(() => close())\n }\n }\n\n return <>\n \n
Échanger un créneau
\n \n \n \n {selected &&
\n
\n Récapitulatif\n
\n
\n
\n
\n
\n {arg.event.extendedProps.salary.title}\n
\n
\n {format(arg.event.start!, 'E dd MMMM uuuu HH:mm')} {format(arg.event.end!, 'HH:mm')}\n
\n
\n
\n
\n
\n
\n
\n
\n
\n {selected.event.extendedProps.salary.title}\n
\n
\n {format(selected.event.start!, 'E dd MMMM uuuu HH:mm')} {format(selected.event.end!, 'HH:mm')}\n
\n
\n
\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
}\n {!selected &&
\n
\n
\n
\n Filtrer\n
\n
\n
\n setIsSameDuration(e.currentTarget.checked)} type=\"checkbox\" role=\"switch\" id=\"sameDuration\" defaultChecked={isSameDuration} />\n \n
\n
\n
\n
\n
\n
\n
<>\n \n {e.event.extendedProps.salary.title}\n
\n \n {e.event.extendedProps.salary.information.job.title}\n
\n >}\n viewDidMount={(arg) => setTitle(arg.view.title)}\n initialView={'listWeek'}\n locales={allLocales}\n locale={'fr'}\n eventClick={setSelected}\n />\n {isLoading && }\n \n
}\n
\n >\n\n\n function handlePickerDateChange(dt: Date)\n {\n if (hasApi()){\n setPickerDate(dt)\n getApi().gotoDate(dt)\n setTitle(getApi().view.title)\n setEndDate(getApi().view.activeEnd)\n fetchCalendar()\n }\n }\n\n function getApi(){\n return calendarRef.current!.getApi();\n }\n\n function hasApi(){\n return !!calendarRef.current?.getApi();\n }\n function prevClick(){\n if (hasApi()){\n getApi().prev()\n setTitle(getApi().view.title)\n setEndDate(getApi().view.activeEnd)\n fetchCalendar()\n }\n }\n\n function nextClick(){\n if (hasApi()){\n getApi().next()\n setTitle(getApi().view.title)\n setEndDate(getApi().view.activeEnd)\n fetchCalendar()\n }\n }\n\n function fetchCalendar(){\n\n if (hasApi()){\n setSlots([])\n setIsLoading(true)\n api.list({\n event: {\n start: format(arg.event.start!, 'uuuu-MM-dd HH:mm:ss'),\n end: format(arg.event.end!, 'uuuu-MM-dd HH:mm:ss'),\n company: arg.event.extendedProps.company.id,\n salary: arg.event.extendedProps.salary.id\n },\n isSameDuration: isSameDuration,\n jobs: jobs,\n start: format(getApi().view.activeStart, 'uuuu-MM-dd'),\n end: format(getApi().view.activeEnd, 'uuuu-MM-dd')\n })\n .then(data => {\n setSlots(data.data)\n setIsLoading(false);\n })\n }\n }\n}\n\nexport default CalendarEventExchange;","import React, {useEffect, useState} from \"react\";\nimport {DateSelectArg, EventClickArg, EventDropArg} from \"@fullcalendar/react\";\nimport CalendarEventEdit from \"../edit\";\nimport CalendarEventResize from \"../edit/resize\";\nimport CalendarEventShow from \"../show\";\nimport CalendarEventAdd from \"../add\";\nimport CalendarEventDrop from \"../add/drop\";\nimport CalendarEventSelect from \"../add/select\";\nimport CalendarEventSubstitute from \"../substitute\";\nimport CalendarEventExchange from \"../exchange\";\nimport {EventResizeDoneArg} from \"@fullcalendar/interaction\";\nimport {Salary} from \"../../../../models/salary\";\nimport {Company} from \"../../../../models/companies\";\nimport {Localisation} from \"../../../../models/localisation\";\nimport {Activity} from \"../../../../models/activity\";\nimport {Offcanvas} from \"bootstrap\";\n\ninterface InterfaceEventShow {\n sidebarType: 'EVENT_SHOW',\n arg: EventClickArg,\n calendar: string,\n setCalendarAbsenceSidebarProps: React.Dispatch\n setCalendarEventSidebarProps: React.Dispatch,\n setCalendarSignedSidebarProps: React.Dispatch\n}\n\ninterface InterfaceEventEdit {\n sidebarType: 'EVENT_EDIT',\n arg?: EventClickArg,\n}\n\ninterface InterfaceEventResize {\n sidebarType: 'EVENT_RESIZE',\n arg?: EventResizeDoneArg,\n}\n\ninterface InterfaceEventAdd {\n sidebarType: 'EVENT_ADD',\n dt: Date\n salary?: Salary,\n company?: Company,\n localisation?: Localisation,\n activity?: Activity,\n}\n\ninterface InterfaceEventDop {\n sidebarType: 'EVENT_DROP',\n arg: EventDropArg,\n}\n\ninterface InterfaceEventSelect {\n sidebarType: 'EVENT_SELECT',\n arg?: DateSelectArg,\n salary?: Salary,\n company?: Company,\n activity?: Activity,\n localisation?: Localisation,\n}\n\ninterface InterfaceEventSubstitute {\n sidebarType: 'EVENT_SUBSTITUTE',\n arg: EventClickArg,\n}\n\ninterface InterfaceEventExchange {\n sidebarType: 'EVENT_EXCHANGE',\n arg: EventClickArg,\n}\n\ninterface Interface {\n sidebarType: 'EMPTY',\n}\n\nexport type CalendarEventSidebarInterface = {trigger: number} & (Interface | InterfaceEventSubstitute | InterfaceEventExchange | InterfaceEventShow | InterfaceEventEdit | InterfaceEventResize | InterfaceEventAdd | InterfaceEventDop | InterfaceEventSelect)\n\nconst CalendarEventSidebar:React.FC = (props) => {\n\n const [offcanvas, setOffcanvas] = useState()\n const [isOpen, setIsOpen] = useState(false)\n\n const reset = () => setIsOpen(false)\n\n useEffect(() => {\n const el = document.getElementById('offcanvasCalendarEvent')! as HTMLDivElement;\n setOffcanvas(new Offcanvas(el));\n\n el.addEventListener('hidden.bs.offcanvas', reset)\n return () => el.removeEventListener('hidden.bs.offcanvas', reset)\n }, [])\n\n useEffect(() => {\n if (isOpen){\n if (offcanvas){\n let elem = document.getElementById('offcanvasCalendarEvent')!\n offcanvas.show(elem)\n }\n }\n }, [isOpen])\n\n useEffect(() => {\n if (props.trigger > 0){\n open();\n }else{\n close();\n }\n\n }, [props.trigger])\n\n function close(){\n if (!offcanvas) return;\n offcanvas.hide();\n }\n\n function open(){\n if (!offcanvas) return;\n setIsOpen(true)\n }\n\n const Content = () => {\n if (offcanvas){\n switch (props.sidebarType){\n case \"EVENT_EDIT\":\n return \n case \"EVENT_SHOW\":\n return \n case \"EVENT_RESIZE\":\n return \n case \"EVENT_ADD\":\n return \n case \"EVENT_DROP\":\n return \n case \"EVENT_SELECT\":\n return \n case \"EVENT_SUBSTITUTE\":\n return \n case \"EVENT_EXCHANGE\":\n return \n }\n }\n\n return Une erreur est survenue veuillez réésayer\n }\n\n return \n {isOpen && }\n
\n}\n\nfunction areEqual(prevProps: CalendarEventSidebarInterface & {handleEventChange: any}, nextProps: CalendarEventSidebarInterface & {handleEventChange: any}){\n return prevProps.trigger === nextProps.trigger;\n}\n\nexport default React.memo(CalendarEventSidebar, areEqual);","\nexport const ADD_SALARY = 'ADD_SALARY';\nexport const ADD_SALARY_SUCCESS = 'ADD_SALARY_SUCCESS';\nexport const ADD_SALARY_FAILURE = 'ADD_SALARY_FAILURE';\n\nexport const ADD_SALARY_INFORMATION = 'ADD_SALARY_INFORMATION';\nexport const ADD_SALARY_INFORMATION_SUCCESS = 'ADD_SALARY_INFORMATION_SUCCESS';\nexport const ADD_SALARY_INFORMATION_FAILURE = 'ADD_SALARY_INFORMATION_FAILURE';\n\nexport const EDIT_SALARY = 'EDIT_SALARY';\nexport const EDIT_SALARY_SUCCESS = 'EDIT_SALARY_SUCCESS';\nexport const EDIT_SALARY_FAILURE = 'EDIT_SALARY_FAILURE';\n\nexport const FETCH_SALARIES = 'FETCH_SALARIES';\nexport const FETCH_SALARIES_SUCCESS = 'FETCH_SALARIES_SUCCESS';\nexport const FETCH_SALARIES_FAILURE = 'FETCH_SALARIES_FAILURE';\n\nexport const SHOW_SALARY = 'SHOW_SALARY';\nexport const SHOW_SALARY_SUCCESS = 'SHOW_SALARY_SUCCESS';\nexport const SHOW_SALARY_FAILURE = 'SHOW_SALARY_FAILURE';\n\nexport const FLAT_RATE_HC = 1;\nexport const FLAT_RATE_DAILY = 2;\nexport const FLAT_RATE_EXECUTIVE_OFFICER = 3;\nexport const FLAT_RATE_ELSE = 4;\n\nexport const getFlatRateChoices = () => {\n return [\n {value: FLAT_RATE_HC, label: 'Heures contrat'},\n {value: FLAT_RATE_DAILY, label: 'Forfait jour'},\n {value: FLAT_RATE_EXECUTIVE_OFFICER, label: 'Cadre dirigeant'},\n {value: FLAT_RATE_ELSE, label: 'Autre'},\n ]\n}\n\nexport const getContractChoices = () => {\n return [\n {value: 1, label: 'CDI temps plein'},\n {value: 2, label: 'CDI temps partiel'},\n {value: 3, label: 'CDD temps plein'},\n {value: 4, label: 'CDD temps partiel'},\n {value: 5, label: 'Freelance'},\n {value: 6, label: 'Autre'},\n ]\n}\n","import * as types from \"../../constants/salary\";\nimport * as models from \"../../models/salary\";\n\nexport const addSalary = () => {\n return {\n type: types.ADD_SALARY,\n }\n}\n\nexport const addSalaryInformation = () => {\n return {\n type: types.ADD_SALARY,\n }\n}\n\nexport const addSalarySuccess = (salary: models.Salary) => {\n return {\n type: types.ADD_SALARY_SUCCESS,\n salary,\n }\n}\n\nexport const addSalaryInformationSuccess = (salary: models.Salary) => {\n return {\n type: types.ADD_SALARY_INFORMATION_SUCCESS,\n salary,\n }\n}\n\nexport const addSalaryFailure = (error: string) => {\n return {\n type: types.ADD_SALARY_FAILURE,\n salary: null,\n salaries: null,\n error\n }\n}\n\nexport const addSalaryInformationFailure = (error: string) => {\n return {\n type: types.ADD_SALARY_INFORMATION_FAILURE,\n salary: null,\n salaries: null,\n error\n }\n}\n\nexport const editSalary = () => {\n return {\n type: types.EDIT_SALARY,\n }\n}\n\nexport const editSalarySuccess = (salary: models.Salary) => {\n return {\n type: types.EDIT_SALARY_SUCCESS,\n salary: salary,\n }\n}\n\nexport const fetchSalaries = () => {\n return {\n type: types.FETCH_SALARIES,\n }\n}\n\nexport const fetchSalariesFailure = (error: string) => {\n return {\n type: types.FETCH_SALARIES_FAILURE,\n salary: null,\n salaries: [],\n error\n }\n}\n\nexport const fetchSalariesSuccess = (salaries: models.Salaries) => {\n return {\n type: types.FETCH_SALARIES_SUCCESS,\n salary: null,\n salaries\n }\n}\n\n\nexport const showSalary = () => {\n return {\n type: types.SHOW_SALARY,\n }\n}\nexport const showSalarySuccess = (salary: models.Salary) => {\n return {\n type: types.SHOW_SALARY_SUCCESS,\n salary: salary\n }\n}\nexport const showSalaryFailure = (error: string) => {\n return {\n type: types.SHOW_SALARY_FAILURE,\n salary: null,\n salaries: null,\n error: error\n }\n}","import {Salaries, Salary} from \"../../../models/salary\";\nimport React, {useEffect, useState} from \"react\";\nimport * as salaryApi from \"../../../adapters/salary\";\nimport {useDispatch} from \"react-redux\";\nimport * as actions from \"../../../actions/salary\";\nimport {Jobs} from \"../../../models/job\";\nimport {Companies} from \"../../../models/companies\";\nimport {PAGINATION} from \"../../../constants/global\";\n\ninterface SingleSalarySelectorProps {\n onSubmit: (s: Salary) => any,\n onClose: any,\n initialValue?: number,\n required?: boolean,\n jobs?: Jobs,\n companies?: Companies,\n salaries?: Salaries\n}\n\nexport const SingleSalarySelector:React.FC = (props) => {\n const {onSubmit, onClose, initialValue, required, companies, salaries, jobs} = props;\n\n const [offset, setOffset] = useState(0)\n const [isLast, setIsLast] = useState(false)\n const [query, setQuery] = useState()\n const [isLoading, setIsLoading] = useState(true)\n const [isFiltering, setIsFiltering] = useState(false)\n const [error, setError] = useState()\n const [fetchedSalaries, setFetchedSalaries] = useState([])\n const dispatch = useDispatch();\n const [scrollBottom, setScrollBottom] = useState(false)\n\n const jobsArray = jobs ? jobs.map((job) => job.id!) : [];\n const companiesArray = companies ? companies.map((companies) => companies.id!) : [];\n const salariesArray = salaries ? salaries.map((salaries) => salaries.id!) : [];\n\n useEffect(() => {\n let container = document.getElementsByClassName('offcanvas-body')[0]!\n container.addEventListener(\"scroll\", onScrollBottom)\n\n setIsLoading(true);\n\n salaryApi.list({\n query: query,\n offset: offset,\n jobs: jobsArray,\n salaries: salariesArray,\n companies: companiesArray,\n }).then(data => {\n fetchSuccess([...data.data], 1)\n })\n\n return () => {\n container.removeEventListener(\"scroll\", onScrollBottom)\n }\n }, [])\n\n useEffect(() => {\n let timer = setTimeout(() => {\n if (typeof query != \"undefined\"){\n dispatch(actions.fetchSalaries())\n setIsFiltering(true);\n setOffset(0)\n salaryApi.list({\n query: query,\n offset: 0,\n jobs: jobsArray,\n salaries: salariesArray,\n companies: companiesArray,\n }).then(data => {\n fetchSuccess([...data.data])\n\n })\n }\n }, 1000);\n\n return () => clearTimeout(timer)\n }, [query])\n\n useEffect(() => {\n if (!isLoading){\n if(offset > 0 && !isLast){\n setIsLoading(true)\n salaryApi.list({\n query: query,\n offset: offset,\n jobs: jobsArray,\n salaries: salariesArray,\n companies: companiesArray,\n }).then(data => {\n fetchSuccess([...fetchedSalaries, ...data.data])\n })\n }\n }\n }, [scrollBottom])\n\n\n const fetchSuccess = (items: Salaries, offset?: number) => {\n setIsLast(items.length < PAGINATION);\n setFetchedSalaries(items)\n setOffset(prevState => (offset ? offset : prevState + 1))\n setIsLoading(false)\n }\n\n const onScrollBottom = () => {\n let elem = document.getElementsByClassName('offcanvas-body')[0]!;\n if (Math.ceil(elem.clientHeight + elem.scrollTop) >= elem.scrollHeight) {\n setScrollBottom((prevState) => !prevState)\n }\n }\n\n return (\n \n
\n
\n
\n {isFiltering ? \n Loading...\n
: }\n \n
{\n setQuery(e.target.value)\n }} className=\"form-control\" placeholder=\"Rechercher un collaborateur\" aria-describedby=\"search-addon\" />\n
\n
\n
\n {error &&
\n {error}\n
}\n
\n {fetchedSalaries.map((salary: Salary, index: number) => {\n return (\n - {\n onSubmit(salary)\n onClose()\n }} key={index}>\n
\n {initialValue === salary.id &&
\n \n }\n
\n \n \n {salary.firstname} {salary.lastname}\n \n \n \n \n {salary.information?.job.title}\n \n \n
\n \n \n
\n \n )\n })}\n {isLoading && - \n
\n Loading...\n
\n }\n
\n {!isLast && !isLoading &&
}\n
\n )\n}\n\ninterface SingleSalarySelectedProps {\n onDelete: any,\n onOpen: any,\n required?: boolean,\n initialValue?: number,\n initialSalary?: Salary,\n validationClass?: string,\n disabled?: boolean\n}\n\nexport const SingleSalarySelected:React.FC = (props) => {\n\n const {\n onDelete,\n onOpen,\n initialValue,\n initialSalary,\n validationClass,\n required,\n disabled\n } = props;\n\n\n const [salary, setSalary] = useState(initialSalary)\n const [isLoading, setIsLoading] = useState(false)\n\n useEffect(() => {\n if (initialValue && initialSalary?.id !== initialValue){\n setIsLoading(true)\n salaryApi.show(initialValue).then(data => {\n setSalary(data.data)\n setIsLoading(false)\n })\n }\n }, [initialValue])\n\n useEffect(() => {\n setSalary(initialSalary);\n }, [initialSalary])\n\n return (\n \n
\n
\n {\n initialValue &&\n
\n \n {salary && !isLoading ? salary.title :\n \n Loading...\n
}\n \n {!required && {\n onDelete(initialValue)\n setSalary(undefined)\n }}>\n \n }\n \n }\n
\n \n \n
\n
\n
\n
\n )\n}\n","import {Salary} from \"../salary\";\nimport {Company} from \"../companies\";\nimport {Localisation} from \"../localisation\";\nimport {Activity} from \"../activity\";\n\nexport interface BookingRecurrence {\n type: 1|2|3,\n start: string,\n end: string,\n daysOfWeek?: number[],\n weekLetters?: number[],\n separationCount?: number,\n description?: string\n}\n\nexport interface Booking {\n id?: number,\n start: string,\n end: string,\n salary: Salary,\n company: Company,\n accountingType: 1|2|3|4,\n localisation: Localisation|null,\n activity: Activity|null,\n recurrence: BookingRecurrence,\n}\n\nexport type Bookings = Booking[];\n\nexport const BOOKING_RECURRENCE_CHOICES = [\n {label: 'Une seule fois', value: 1},\n {label: 'Semaines X', value: 2},\n {label: 'Personnalisé', value: 3},\n];\n\nexport const getBookingRecurrenceChoice = (type: number) => [\n {label: 'Une seule fois', value: 1},\n {label: 'Semaines X', value: 2},\n {label: 'Personnalisé', value: 3},\n][type - 1];","import React, {useEffect, useState} from \"react\";\nimport {RootStateOrAny, useDispatch, useSelector} from \"react-redux\";\nimport {FormikHelpers, useFormik} from \"formik\";\nimport * as Yup from \"yup\"\nimport {SingleSalarySelected, SingleSalarySelector} from \"../../../../utils/salarySelector/single\";\nimport {Salary} from \"../../../../models/salary\";\nimport {Company} from \"../../../../models/companies\";\nimport {Localisation} from \"../../../../models/localisation\";\nimport {Activity} from \"../../../../models/activity\";\nimport DatePicker from \"react-datepicker\";\nimport {setHours, setMinutes} from \"date-fns\";\nimport * as api from \"../../../../adapters/booking\"\nimport {submitSidebar} from \"../../../../actions/rightSidebar\";\nimport FormError from \"../../../../utils/formError\";\nimport validationClass from \"../../../../utils/validationClass\";\nimport DateCustomInput from \"../../../../utils/customInput\";\nimport BootstrapSelect from \"../../../../utils/bootstrapSelect\";\nimport {Choice} from \"../../../../utils/form/model\";\nimport format from \"../../../../utils/locale\";\nimport {AccountingTypes, getAccountingTypeChoice} from \"../../../../constants/booking\";\nimport * as calendarTypes from \"../../../../constants/calendar\";\nimport {BOOKING_RECURRENCE_CHOICES, getBookingRecurrenceChoice} from \"../../../../models/booking\";\nimport {showAlertSuccess} from \"../../../../actions/alert\";\nimport SmallLoader from \"../../../../utils/loader/small\";\nimport Loader from \"../../../../utils/loader\";\n\ninterface Interface {\n values: {\n salary: Salary,\n company: Company,\n start: Date,\n end: Date,\n localisation?: Localisation,\n activity?: Activity\n accountingType: number\n description: string\n recurrence: any\n },\n bookingGroupTitle?: string,\n bookingGroupId?: number,\n exceptionId?: number,\n bookingId: number,\n instanceToken: string,\n eventType: string,\n handleSubmitSuccess: (ev: any) => any;\n}\n\nconst BookingEditForm:React.FC = (props) => {\n\n const {values,bookingGroupTitle, bookingGroupId, bookingId, exceptionId, instanceToken, eventType, handleSubmitSuccess } = props;\n\n const dispatch = useDispatch();\n const [salary, setSalary] = useState(values.salary)\n const [displayConfirmationTypeSelector, setDisplayConfirmationTypeSelector] = useState(false);\n const [confirmationType, setConfirmationType] = useState(1);\n const [displaySalarySelector, setDisplaySalarySelector] = useState(false);\n // const [weeks, setWeeks] = useState([])\n\n let now = new Date(values.start)\n now.setDate(now.getDate() + 7);\n const [startDate, setStartDate] = useState(values.start);\n const [endDate, setEndDate] = useState(now);\n const [weeks, setWeeks] = useState([])\n const [company, setCompany] = useState(values.company)\n const [init, setInit] = useState(false)\n\n const [initialValues, setInitialValues] = useState({\n salary: values.salary.id,\n company: values.company.id,\n localisation: values.localisation?.id,\n activity: values.activity?.id,\n beginAt: values.start,\n endAt: values.end,\n accountingType: values.accountingType,\n description: values.description,\n recurrence: {\n type: String(values.recurrence.type)\n }\n })\n\n const [validationSchema, setValidationSchema] = useState(Yup.object().shape({\n salary: Yup.number().required(),\n company: Yup.number().required(),\n localisation: Yup.number().nullable(),\n activity: Yup.number().nullable(),\n beginAt: Yup.date().required(),\n endAt: Yup.date().required().test(\"is-greater\", \"La fin doit être après le début\", function(value: any) {\n const { beginAt } = this.parent;\n return value && beginAt <= value\n }),\n accountingType: Yup.number().required(),\n description: Yup.string().nullable(),\n recurrence: Yup.object().shape({\n type: Yup.number().required()\n })\n }))\n\n const formik = useFormik({\n initialValues: initialValues,\n validationSchema: validationSchema,\n enableReinitialize: true,\n onSubmit: (values, formikHelpers) => {\n switch (confirmationType){\n case 1:\n switch (eventType) {\n case calendarTypes.EVENT_TYPE_BOOKING_EXCEPTION:\n api.editException(values, exceptionId!).then((resp) => submitSuccess(resp.data, formikHelpers))\n break;\n case calendarTypes.EVENT_TYPE_BOOKING:\n api.createException(values, bookingId, instanceToken).then((resp) => submitSuccess(resp.data, formikHelpers))\n break;\n }\n break;\n case 2:\n api.split(values, bookingId).then((resp) => submitSuccess(resp.data, formikHelpers))\n break;\n case 3:\n api.edit(values, bookingId).then((resp) => submitSuccess(resp.data, formikHelpers))\n break;\n case 4:\n api.splitBetween(values, bookingId, format(startDate, \"uuuu-MM-dd\"), format(endDate, \"uuuu-MM-dd\")).then((resp) => submitSuccess(resp.data, formikHelpers))\n break;\n case 5:\n api.splitDay(values, bookingId).then((resp) => submitSuccess(resp.data, formikHelpers))\n break;\n case 6:\n api.editDay(values, bookingId).then((resp) => submitSuccess(resp.data, formikHelpers))\n break;\n }\n },\n });\n\n const submitSuccess = (data: any, formikHelpers: FormikHelpers) => {\n Promise.all([\n handleSubmitSuccess(data)\n ]).then(() => {\n dispatch(showAlertSuccess('Créneau mis à jour'));\n formikHelpers.setSubmitting(false)\n })\n }\n\n useEffect(() => {\n getWeeks(company)\n }, [company])\n\n useEffect(() => {\n let _initialValues = {...initialValues}\n let data = init ? {..._initialValues} : {...values}\n let _validationSchema = {...validationSchema.fields}\n\n let fields: string[] = [];\n\n if ([2,3].includes(Number(_initialValues.recurrence.type))){\n _validationSchema.recurrence.fields.daysOfWeek = Yup.array().of(Yup.number()).min(1);\n\n if (!bookingGroupId){\n fields.push('start', 'end')\n _validationSchema.recurrence.fields.start = Yup.date().required();\n _validationSchema.recurrence.fields.end = Yup.date().nullable();\n }\n }\n\n switch (String(_initialValues.recurrence.type)){\n case '1':\n fields.push('type');\n break;\n case '2':\n fields.push('type', 'daysOfWeek', 'weekLetters', 'start');\n _validationSchema.recurrence.fields.weekLetters = Yup.array().of(Yup.number()).min(1);\n break;\n case '3':\n fields.push('type', 'daysOfWeek', 'separationCount', 'start');\n _validationSchema.recurrence.fields.separationCount = Yup.number().required();\n break;\n }\n\n // setValues\n for (let i in fields){\n switch (fields[i]) {\n case 'type':\n _initialValues.recurrence[fields[i]] = data.recurrence[fields[i]].toString();\n break;\n case 'daysOfWeek':\n case 'weekLetters':\n if (data.recurrence.hasOwnProperty(fields[i])){\n _initialValues.recurrence[fields[i]] = data.recurrence[fields[i]].map((num: number) => num.toString());\n break;\n }\n\n _initialValues.recurrence[fields[i]] = [];\n break;\n case 'end':\n case 'start':\n if (data.recurrence.hasOwnProperty(fields[i])) {\n _initialValues.recurrence[fields[i]] = data.recurrence[fields[i]] ? new Date(values.recurrence[fields[i]]) : null;\n break;\n }\n\n _initialValues.recurrence[fields[i]] = new Date();\n break;\n case 'separationCount':\n if (data.recurrence.hasOwnProperty(fields[i])) {\n _initialValues.recurrence[fields[i]] = data.recurrence[fields[i]].toString();\n break;\n }\n\n _initialValues.recurrence[fields[i]] = String(1);\n break;\n default:\n if (data.recurrence.hasOwnProperty(fields[i])) {\n _initialValues.recurrence[fields[i]] = data.recurrence[fields[i]];\n break;\n }\n _initialValues.recurrence[fields[i]] = null;\n }\n }\n\n setInit(true);\n setInitialValues({..._initialValues});\n setValidationSchema(Yup.object().shape({..._validationSchema}))\n\n }, [formik.values.recurrence.type])\n\n const getWeeks = (company: Company) => {\n\n let length = company.timesheet.recurrence;\n let ret: string[] = [];\n for (let i = 0; i < length; i++){\n ret.push(String.fromCharCode(65 + i));\n }\n\n setWeeks(ret);\n }\n\n\n if (displayConfirmationTypeSelector){\n return \n
\n
\n
\n \n Créneau récurrent\n
\n
\n\n
\n
\n
\n \n
\n
\n
\n Vous souhaitez que la modification s'applique :\n
\n
\n - {\n setConfirmationType(1)\n formik.submitForm().then(data => console.log(data));\n }}>\n Une seule fois\n
\n {<>\n - {\n setConfirmationType(2)\n formik.submitForm().then(data => console.log(data));\n }}>\n Cette occurence et toute les suivantes\n
\n {bookingGroupId && \n Créer un nouvel emploi du temps à partir du {format(new Date(formik.values.beginAt))} {values.recurrence.end && <>jusqu'au {format(new Date(values.recurrence.end))}>}\n }\n \n - {\n setConfirmationType(5)\n formik.submitForm().then(data => console.log(data));\n }}>\n Cette occurence et toute les suivantes le {format(formik.values.beginAt, 'eeee')} seulement\n
\n {bookingGroupId && \n Créer un nouvel emploi du temps à partir du {format(new Date(formik.values.beginAt))} {values.recurrence.end && <>jusqu'au {format(new Date(values.recurrence.end))}>}\n }\n \n >}\n\n {<>\n - {\n setConfirmationType(3)\n formik.submitForm().then(data => console.log(data));\n }}>\n Toutes les occurences\n \n \n Attention, en modifiant toutes les occurences, les modifications ponctuel apportés au créneau seront perdues.\n \n \n {!bookingGroupId && \n {formik.values.recurrence.start && formik.values.recurrence.end && <>Du {format(formik.values.recurrence.start, 'dd/MM/uuuu')} au {format(formik.values.recurrence.end, 'dd/MM/uuuu')}>}\n {formik.values.recurrence.start && !formik.values.recurrence.end && <>A partir\n du {format(formik.values.recurrence.start, 'dd/MM/uuuu')}>}\n }\n {bookingGroupId &&
\n Modifier toutes les occurrences du créneau à partir du {format(new Date(values.recurrence.start))} {values.recurrence.end && <>jusqu'au {format(new Date(values.recurrence.end))}>}\n
}\n \n\n - {\n setConfirmationType(6)\n formik.submitForm().then(data => console.log(data));\n }}>\n Toutes les occurences le {format(formik.values.beginAt, 'eeee')} seulement\n
\n \n Attention, en modifiant toutes les occurences, les modifications ponctuel apportés au créneau seront perdues.\n \n \n {!bookingGroupId && \n {formik.values.recurrence.start && formik.values.recurrence.end && <>Du {format(formik.values.recurrence.start, 'dd/MM/uuuu')} au {format(formik.values.recurrence.end, 'dd/MM/uuuu')}>}\n {formik.values.recurrence.start && !formik.values.recurrence.end && <>A partir\n du {format(formik.values.recurrence.start, 'dd/MM/uuuu')}>}\n }\n {bookingGroupId && \n Modifier toutes les occurrences du créneau le {format(formik.values.beginAt, 'eeee')} à partir du {format(new Date(values.recurrence.start))} {values.recurrence.end && <>jusqu'au {format(new Date(values.recurrence.end))}>}\n
}\n \n >}\n
\n {formik.isSubmitting &&
}\n
\n }\n\n return <>\n \n >\n}\n\nexport default BookingEditForm;","import React, {useEffect, useState} from \"react\";\nimport BookingEditForm from \"../../../booking/edit/form\";\nimport {EventClickArg} from \"@fullcalendar/react\";\n\nconst CalendarBookingEdit:React.FC<{arg?: EventClickArg, handleSubmitSuccess: (ev: any) => any; close: () => any}> = (props) => {\n\n const {arg, handleSubmitSuccess, close} = props;\n const [key, setKey] = useState(0);\n\n\n const handleSubmit = (ev: any) => {\n return Promise.all([\n handleSubmitSuccess(ev)\n ])\n .then(() => close())\n .then(() => true)\n }\n\n useEffect(() => {\n setKey(prevState => prevState + 1);\n }, [arg])\n\n return <>\n \n
Modifier un créneau
\n \n \n \n {arg && }\n
\n >\n}\n\nexport default CalendarBookingEdit;","import React, {useEffect, useState} from \"react\";\nimport BookingEditForm from \"../../../../booking/edit/form\";\nimport {EventResizeDoneArg} from \"@fullcalendar/interaction\";\n\nconst BookingResizeEdit:React.FC<{arg?: EventResizeDoneArg, handleSubmitSuccess: (ev: any) => any; close: () => any}> = (props) => {\n\n const {arg, handleSubmitSuccess, close} = props;\n const [key, setKey] = useState(0);\n\n useEffect(() => {\n const el = document.getElementById('offcanvasCalendarBooking')! as HTMLDivElement;\n el.addEventListener('hide.bs.offcanvas', cancelResize)\n\n return () => el?.removeEventListener('hide.bs.offcanvas', cancelResize)\n }, [arg])\n\n const cancelResize = () => {\n if (arg && arg.oldEvent){\n arg.event.setDates(arg.oldEvent.start!, arg.oldEvent.end!);\n }\n }\n\n const handleSubmit = (ev: any) => {\n return Promise.all([\n handleSubmitSuccess(ev)\n ])\n .then(() => close())\n .then(() => true)\n }\n\n useEffect(() => {\n setKey(prevState => prevState + 1)\n }, [arg])\n\n return <>\n \n
Modifier un créneau
\n \n \n \n {arg && }\n
\n >\n}\n\nexport default BookingResizeEdit;","import {Salary} from \"../../models/salary\";\nimport {Granted} from \"../granted\";\n\nconst IsGranted = (right: string, salary?: Salary) => {\n return Granted(right, salary?.id);\n}\n\nexport default IsGranted;","import React, {useEffect, useState} from \"react\";\nimport {EventClickArg} from \"@fullcalendar/react\";\nimport format from \"../../../../utils/locale\";\nimport {getAccountingTypeChoice} from \"../../../../constants/booking\";\nimport * as exceptionApi from \"../../../../adapters/booking/exception\";\nimport * as bookingApi from \"../../../../adapters/booking\";\nimport * as absenceApi from \"../../../../adapters/absence\";\nimport * as calendarTypes from \"../../../../constants/calendar\";\nimport {TYPE_EVENT, TYPE_EVENT_EXCEPTION} from \"../../../../constants/event\";\nimport SmallLoader from \"../../../../utils/loader/small\";\nimport {EVENT_TYPE_BOOKING, EVENT_TYPE_BOOKING_EXCEPTION} from \"../../../../constants/calendar\";\nimport {closeSidebar} from \"../../../../actions/rightSidebar\";\nimport * as API from \"../../../../adapters/booking\";\nimport Granted from \"../../../../security/isGranted\";\nimport * as accessRights from \"../../../../constants/accessRight\";\n\ninterface Interface {\n arg: EventClickArg,\n handleEventChange: (ev: any) => any,\n calendar: string,\n setCalendarSidebarBookingProps: React.Dispatch,\n setCalendarSidebarSignedProps: React.Dispatch,\n setCalendarAbsenceSidebarProps: React.Dispatch,\n close: () => any\n}\n\n\nconst BookingShow:React.FC = (props) => {\n\n const {arg, handleEventChange, calendar, close, setCalendarSidebarBookingProps, setCalendarAbsenceSidebarProps, setCalendarSidebarSignedProps} = props;\n\n const [confirmCancel, setConfirmCancel] = useState(false)\n const [cancelType, setCancelType] = useState(1)\n const [removingBooking, setRemovingBooking] = useState(false)\n const [removingAbsence, setRemovingAbsence] = useState(false)\n\n const removeBooking = () => {\n if (arg){\n setRemovingBooking(true)\n switch (cancelType){\n case 1:\n API.cancelOnce(arg.event.extendedProps.bookingId, arg.event.extendedProps.instanceToken).then(resp => removeBookingSuccess(resp.data))\n break;\n case 3:\n API.cancelAfter(arg.event.extendedProps.bookingId, format(arg.event.start!, 'uuuu-MM-dd')).then(resp => removeBookingSuccess(resp.data))\n break;\n case 2:\n API.cancel(arg.event.extendedProps.bookingId).then(resp => removeBookingSuccess(resp.data))\n break;\n }\n }\n }\n\n const removeAbsence = () => {\n if (arg.event.extendedProps.absence){\n setRemovingAbsence(true);\n absenceApi.cancel(arg.event.extendedProps.absence.id).then((data) => removeAbsenceSuccess(data.data))\n }\n }\n\n const removeBookingSuccess = (ev: any) => {\n return Promise.all([\n handleEventChange(ev)\n ])\n .then(() => close())\n .then(() => setRemovingBooking(false))\n .then(() => true)\n }\n\n const removeAbsenceSuccess = (ev: any) => {\n if(arg){\n return Promise.all([\n handleEventChange(ev)\n ])\n .then(() => arg.event.setExtendedProp('absence', null))\n .then(() => setRemovingAbsence(false))\n .then(() => true)\n }\n }\n\n const setLabourDayWorked = (worked: boolean) => {\n if (arg){\n switch (arg.event.extendedProps.eventType){\n case EVENT_TYPE_BOOKING:\n break;\n case EVENT_TYPE_BOOKING_EXCEPTION:\n break;\n }\n }\n }\n\n if (confirmCancel && arg){\n return <>\n \n
Créneau de {arg.event.extendedProps.salary.title}
\n \n \n \n
\n
\n Êtes vous sûr de vouloir supprimer le créneau suivant ?\n
\n
\n
\n
\n {arg.event.extendedProps.salary.title}\n
\n
\n
{format(arg.event.start!, \"E dd MMMM uuuu HH:mm\")} - {format(arg.event.end!, \"HH:mm\")}
\n
\n {arg.event.extendedProps.timeCaption}\n
\n
\n
\n {arg.event.extendedProps.recurrence.type !== 1 && <>\n
\n
\n \n Créneau récurrent\n \n {arg.event.extendedProps.recurrence.description}\n
\n\n
\n - \n \n
\n - \n \n
\n - \n \n
\n
\n
\n >}\n {arg.event.extendedProps.bookingGroupId && cancelType === 3 &&
\n Attention, ce créneau est rataché à l'emploi du temps {arg.event.extendedProps.bookingGroupTitle},\n en retirant les occurences suivantes, les autres créneaux ratachés s'arreteront en même temps\n
}\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n
\n >\n }\n\n return <>\n \n
Créneau de {arg.event.extendedProps.salary.title}
\n \n \n {!arg && \n
\n Aucun créneau séléctionné\n
\n }\n {arg && \n
\n Détails du créneau\n
\n
\n
\n
\n \n \n Début\n | \n \n {format(arg.event.start!, \"E dd MMMM uuuu HH:mm\")}\n | \n
\n \n \n Fin\n | \n \n {format(arg.event.end!, \"E dd MMMM uuuu HH:mm\")}\n | \n
\n \n \n Type d'heure\n | \n \n {getAccountingTypeChoice(arg.event.extendedProps.accountingType)?.label}\n | \n
\n \n \n Établissement\n | \n \n {arg.event.extendedProps.company?.title || }\n | \n
\n \n \n Emplacement\n | \n \n {arg.event.extendedProps.localisation?.title || }\n | \n
\n \n \n Activité\n | \n \n {arg.event.extendedProps.activity?.title || }\n | \n
\n \n \n\n
\n {Granted(accessRights.EDIT_BOOKING, arg.event.extendedProps.salary.id) &&
\n \n
}\n
\n \n
\n
\n
\n\n {Granted(accessRights.EDIT_TIME_CLOCK, arg.event.extendedProps.salary.id) && calendarTypes.CALENDAR_SIGNED_GLOBAL === calendar && <>\n
\n \n
\n >}\n\n {arg.event.extendedProps.isLabourDay &&
\n
\n
\n Jour férié\n
\n
\n Cochez la case ci dessous si le collaborateur travail ce jour.\n
\n
\n setLabourDayWorked(e.target.checked)} type=\"checkbox\" id=\"labourDayWorked\"/>\n \n
\n
}\n\n {arg.event.extendedProps.absence &&
\n
\n
\n Absence\n
\n
\n \n \n \n Type\n | \n \n {arg.event.extendedProps.absence.typeName}\n | \n
\n \n \n Début\n | \n \n {format(new Date(arg.event.extendedProps.absence.start))}\n | \n
\n \n \n Fin\n | \n \n {format(new Date(arg.event.extendedProps.absence.end))}\n | \n
\n \n \n Nb de jours\n | \n \n {arg.event.extendedProps.absence.nbDays}\n | \n
\n \n
\n
\n {Granted(accessRights.EDIT_ABSENCE, arg.event.extendedProps.salary.id) &&
\n \n
}\n {Granted(accessRights.DELETE_ABSENCE, arg.event.extendedProps.salary.id) &&
\n \n
}\n
\n
}\n\n
}\n >\n}\n\nexport default BookingShow;","import {post, get} from \"../../xhr\";\nimport * as models from \"../../../models/booking/group\"\n\n\nexport function create(requestData: models.Payload){\n return post('booking/group/create', requestData);\n}\n\nexport function edit(id: number, requestData: models.Payload){\n return post('booking/group/edit/' + id, requestData);\n}\n\nexport function list(requestData: {salary: number, query?: string}){\n return post('booking/group/list', requestData);\n}\n\nexport function show(id: number){\n return get('booking/group/show/' + id);\n}\n\nexport function cancel(id: number){\n return get('booking/group/cancel/' + id);\n}","import React, {BaseSyntheticEvent, useEffect, useState} from \"react\";\nimport * as Yup from \"yup\";\nimport {useFormik} from \"formik\";\nimport {RootStateOrAny, useDispatch, useSelector} from \"react-redux\";\nimport {Company} from \"../../../../models/companies\";\nimport {Salary} from \"../../../../models/salary\";\nimport * as api from \"../../../../adapters/booking\";\nimport DatePicker from \"react-datepicker\";\nimport {Localisation} from \"../../../../models/localisation\";\nimport {Activity} from \"../../../../models/activity\";\nimport Loader from \"../../../../utils/loader\";\nimport {showAlertSuccess} from \"../../../../actions/alert\";\nimport {setMinutes, setHours} from \"date-fns\";\nimport {SingleSalarySelected, SingleSalarySelector} from \"../../../../utils/salarySelector/single\";\nimport format from \"../../../../utils/locale\"\nimport FormError from \"../../../../utils/formError\";\nimport validationClass from \"../../../../utils/validationClass\";\nimport DateCustomInput from \"../../../../utils/customInput\";\nimport BootstrapSelect from \"../../../../utils/bootstrapSelect\";\nimport {axiosError} from \"../../../../actions/axios\";\nimport {AccountingTypes, getAccountingTypeChoice} from \"../../../../constants/booking\";\nimport * as groupApi from \"../../../../adapters/booking/group\";\nimport {BookingRecurrence} from \"../../../../models/booking\";\nimport SmallLoader from \"../../../../utils/loader/small\";\n\ninterface Interface {\n initialSalary?: Salary,\n initialCompany?: Company,\n start?: Date,\n end?: Date,\n localisation?: Localisation,\n activity?: Activity,\n recurrence?: BookingRecurrence,\n bookingGroupId?: number,\n handleSubmitSuccess: (props: any[]) => any\n}\n\nconst BookingAddForm: React.FC = (props) => {\n\n const {initialCompany, initialSalary, end, start, localisation, activity, recurrence, bookingGroupId, handleSubmitSuccess} = props;\n\n const [isLoading, setIsLoading] = useState(true);\n const [displaySalarySelector, setDisplaySalarySelector] = useState(false);\n const [weeks, setWeeks] = useState([]);\n const [groups, setGroups] = useState<{title: string, id: number, start: string, finish: string}[]>([])\n const [salary, setSalary] = useState(initialSalary);\n const [company, setCompany] = useState(initialCompany);\n\n const dispatch = useDispatch();\n\n useEffect(() => {\n if (salary) {\n groupApi.list({\n salary: salary.id\n }).then(data => setGroups(data.data))\n }\n }, [salary])\n\n const [initialValues, setInitialValues] = useState({\n salary: salary?.id,\n beginAt: start ? start : setMinutes(new Date(), 0),\n endAt: end ? end : setMinutes(new Date(), 30),\n accountingType: 1,\n company: company?.id,\n localisation: localisation?.id || salary?.defaultLabels?.find(d => d.company.id === company?.id)?.localisation?.id,\n activity: activity?.id || salary?.defaultLabels?.find(d => d.company.id === company?.id)?.activity?.id,\n bookingGroup: bookingGroupId || \"\",\n recurrence: {\n type: String(recurrence?.type || '1'),\n }\n })\n\n const [validationSchema, setValidationSchema] = useState(Yup.object().shape({\n salary: Yup.number(),\n beginAt: Yup.date().required('Début de créneau requis'),\n endAt: Yup.date().required('Fin de créneau requis')\n .test(\"is-greater\", \"La fin doit être après le début\", function(value: any) {\n const { beginAt } = this.parent;\n return value && beginAt <= value\n }),\n accountingType: Yup.number().required(),\n company: Yup.number().required('Veuillez choisir un point de vente'),\n localisation: Yup.number().nullable(),\n activity: Yup.number().nullable(),\n description: Yup.string().nullable(),\n bookingGroup: Yup.number().nullable(),\n recurrence: Yup.object().shape({\n type: Yup.string().required(),\n })\n }))\n\n useEffect(() => {\n let _initialValues:any = {...initialValues}\n\n if (String(_initialValues.recurrence.type) !== '1'){\n if(recurrence?.daysOfWeek){\n _initialValues.recurrence.daysOfWeek = recurrence.daysOfWeek.map((d: number) => String(d));\n }\n handleRecurrenceTypeChange(String(_initialValues.recurrence.type))\n }\n\n if(_initialValues.recurrence.type === '2' && recurrence?.weekLetters){\n _initialValues.recurrence.weekLetters = recurrence.weekLetters.map((d: number) => String(d));\n }\n\n if(_initialValues.recurrence.type === '3' && recurrence?.separationCount){\n _initialValues.recurrence.separationCount = recurrence.separationCount;\n }\n\n setInitialValues({..._initialValues})\n setIsLoading(false);\n }, [])\n\n useEffect(() => {\n if (company){\n getWeeks(company)\n }\n }, [company])\n\n const formik = useFormik({\n initialValues: initialValues,\n validationSchema: validationSchema,\n validateOnChange: true,\n enableReinitialize: true,\n isInitialValid: false,\n onSubmit: (values, formikHelpers) => {\n api.create(values)\n .then(resp => {\n Promise.all([\n handleSubmitSuccess(resp.data)\n ]).then(() => {\n dispatch(showAlertSuccess('Créneau ajouté'));\n formikHelpers.setSubmitting(false)\n })\n })\n .catch(error => dispatch(axiosError(error)))\n }\n })\n\n const handleSalaryChange = (data: Salary) => {\n let _values = {...formik.values}\n\n if (company && data.companies.find(c => c.id === company.id)){\n _values.company = data.companies.find(c => c.id === company.id)!.id\n }else{\n _values.company = data.companies[0].id\n }\n\n formik.setValues(_values)\n\n setSalary(data)\n handleBookingGroupChange();\n setCompany(data.companies[0])\n }\n\n const handleBookingGroupChange = (id?: number|string) => {\n let recurrenceValidation = {...validationSchema.fields.recurrence.fields};\n let _values = {...formik.values};\n _values.bookingGroup = id;\n\n if (id){\n delete _values.recurrence.start\n delete recurrenceValidation.start\n delete _values.recurrence.end\n delete recurrenceValidation.end\n }else if(formik.values.recurrence.type !== '1'){\n _values.recurrence.start = _values.beginAt\n _values.recurrence.end = null\n recurrenceValidation.start = Yup.date().required('Champs requis');\n recurrenceValidation.end = Yup.date().nullable()\n .test(\"is-greater\", \"La fin doit être après le début\", function(value: any) {\n const { start } = this.parent;\n return !value || (value && start <= value)\n })\n }\n\n let validation = {\n salary: Yup.number().required('Veuillez choisir un collaborateur'),\n bookingGroup: Yup.number().nullable(),\n beginAt: Yup.date().required('Début de créneau obligatoire'),\n endAt: Yup.date().required('Fin de créneau requis')\n .test(\"is-greater\", \"La fin doit être après le début\", function(value: any) {\n const { beginAt } = this.parent;\n return value && beginAt <= value\n }),\n company: Yup.number().required('Veuillez préciser un point de vente'),\n localisation: Yup.number().nullable(),\n activity: Yup.number().nullable(),\n recurrence: Yup.object().shape({...recurrenceValidation})\n }\n\n setValidationSchema(Yup.object().shape({...validation}));\n setInitialValues({..._values})\n }\n\n const handleRecurrenceTypeChange = (type : string) => {\n let fields:string[] = [];\n\n let recurrenceValidation: any = {\n type: Yup.string().required(),\n }\n\n switch (type){\n case '1':\n fields = ['type'];\n break;\n case '2':\n recurrenceValidation.daysOfWeek = Yup.array().of(Yup.number()).min(1, 'Veuillez choisir au moins un jour').required();\n recurrenceValidation.weekLetters = Yup.array().of(Yup.number()).min(1, 'Veuillez choisir au moins une semaine').required();\n fields = ['type', 'daysOfWeek', 'weekLetters'];\n break;\n case '3':\n recurrenceValidation.daysOfWeek = Yup.array().of(Yup.number()).min(1, 'Veuillez choisir au moins un jour');\n recurrenceValidation.separationCount = Yup.number().min(1).required('Veuillez préciser une répétition de semaine');\n fields = ['type', 'daysOfWeek', 'separationCount'];\n break;\n }\n\n let _values = {...formik.values}\n _values.recurrence.type = type;\n\n if (!_values.bookingGroup && type !== '1'){\n fields.push('start', 'end')\n recurrenceValidation.start = Yup.date().required('Début de récurrence requise');\n recurrenceValidation.end = Yup.date().nullable()\n .test(\"is-greater\", \"La fin doit être après le début\", function(value: any) {\n const { start } = this.parent;\n return !value || (value && start <= value)\n })\n }\n\n // delete unecessary values\n for(let key in _values.recurrence){\n if (!fields.includes(key) && _values.recurrence.hasOwnProperty(key)){\n delete _values.recurrence[key];\n }\n }\n\n // add default values\n for(let key in fields){\n if(!_values.recurrence.hasOwnProperty(fields[key])){\n switch (fields[key]){\n case 'daysOfWeek':\n _values.recurrence.daysOfWeek = [format(_values.beginAt, 'i')];\n break;\n case 'weekLetters':\n _values.recurrence.weekLetters = [];\n break;\n case 'separationCount':\n _values.recurrence.separationCount = 1;\n break;\n case 'start':\n _values.recurrence.start = _values.beginAt;\n break;\n case 'end':\n _values.recurrence.end = null;\n break;\n }\n }\n }\n\n let validation = {\n salary: Yup.number().required('Veuillez choisir un collaborateur'),\n bookingGroup: Yup.number().nullable(),\n beginAt: Yup.date().required('Début de créneau obligatoire'),\n endAt: Yup.date().required('Fin de créneau requis')\n .test(\"is-greater\", \"La fin doit être après le début\", function(value: any) {\n const { beginAt } = this.parent;\n return value && beginAt <= value\n }),\n company: Yup.number().required('Veuillez préciser un point de vente'),\n localisation: Yup.number().nullable(),\n activity: Yup.number().nullable(),\n recurrence: Yup.object().shape({...recurrenceValidation})\n }\n\n setValidationSchema(Yup.object().shape({...validation}));\n setInitialValues({..._values})\n }\n\n const handleWeekDayChange = (e: BaseSyntheticEvent) => {\n let checked = e.target.checked;\n let _values = {...formik.values};\n let dayElements: HTMLInputElement[]|any = document.getElementsByName(\"recurrence.daysOfWeek\")\n let daysOfWeek_copy: string[] = [];\n dayElements.forEach((day: HTMLInputElement) => {\n day.checked = checked;\n if (checked) {\n daysOfWeek_copy.push(day.value)\n }\n })\n\n _values.recurrence.daysOfWeek = daysOfWeek_copy;\n setInitialValues({..._values});\n }\n\n const handleWeekChange = (e: BaseSyntheticEvent) => {\n let checked = e.target.checked;\n let _values = {...formik.values};\n let weekElements: HTMLInputElement[]|any = document.getElementsByName(\"recurrence.weekLetters\")\n let weekLetters_copy: string[] = [];\n weekElements.forEach((week: HTMLInputElement) => {\n week.checked = checked;\n if (checked) {\n weekLetters_copy.push(week.value)\n }\n })\n _values.recurrence.weekLetters = weekLetters_copy;\n setInitialValues({..._values});\n }\n\n const getWeeks = (company: Company) => {\n\n if (!company) return false;\n\n let length = company.timesheet.recurrence;\n let ret: string[] = [];\n for (let i = 0; i < length; i++){\n ret.push(String.fromCharCode(65 + i));\n }\n setWeeks(ret);\n }\n\n if (isLoading){\n return \n }\n\n\n if (!formik.values.salary || displaySalarySelector){\n return {\n handleSalaryChange(data)\n formik.setFieldValue('salary', data.id)\n setDisplaySalarySelector(false)\n }}\n onClose={() => setDisplaySalarySelector(false)}\n initialValue={formik.values.salary}\n required={true}\n />;\n }\n\n return (\n