(() => { function create(dependencies) { const { appState, escapeHtml, cleanString, normalizeString, formatDateInputDisplay, getDateInputValue, formatHours, getWeekStartDate, getLocalDateKey, getTimeManagementDayKey, isTimeManagementSaveEnabled, getTimeManagementRows, getTimeManagementActivityOptions, findTimeManagementServiceRequestByNumber, formatTimeManagementServiceRequestLabel, isNonServiceRequestSrNumber, findOptionValue, findOptionLabel, getTimeManagementTaskTypeOptions, formatTimeManagementHourPayloadValue, } = dependencies; function renderTimeManagementModal() { const modal = appState.timeManagementModal; if (!modal) { return ""; } const selectedDate = modal.selectedDate || getDateInputValue(new Date()); const selectedDateLabel = formatDateInputDisplay(selectedDate); const canSaveTimeManagement = isTimeManagementSaveEnabled(modal); const isSavingTimeManagement = Boolean(modal.isSaving); return `

Horas apontadas

Manage time

${renderTimeManagementHourIndicators(modal)}
${renderTimeManagementBody(modal)}
${ modal.saveErrorMessage ? `

${escapeHtml(modal.saveErrorMessage)}

` : "" }
`; } function renderTimeManagementBody(modal) { if (modal.status === "loading") { return renderTimeManagementSkeleton(); } if (modal.status === "error") { return `

Erro na requisição

${escapeHtml( modal.errorMessage || "Não foi possível carregar o apontamento." )}

`; } const rows = getTimeManagementRows(modal); return `
${renderTimeManagementHeaderRow(modal.weekDays || [])}
${ rows.length ? rows.map((row, index) => renderTimeManagementEntryRow(modal, row, index)).join("") : `
Nenhum apontamento de hora neste período
` }
`; } function renderTimeManagementHeaderRow(weekDays) { return ` `; } function renderTimeManagementDayHeader(day) { return ` ${escapeHtml(day.dayLabel || "-")} ${escapeHtml(day.monthLabel || day.date || "-")} `; } function renderTimeManagementEntryRow(modal, row, index) { const rowId = cleanString(row?.id) || `row-${index}`; const isHighlighted = cleanString(modal?.highlightRowId) && cleanString(modal?.highlightRowId) === rowId; const selectedSr = cleanString(row?.selectedSrNumber); const activityOptions = getTimeManagementActivityOptions(modal, selectedSr); const selectedSrOption = findTimeManagementServiceRequestByNumber( modal, selectedSr ); const isNonServiceRequest = isNonServiceRequestSrNumber(selectedSr); const selectedSrLabel = selectedSrOption?.label || formatTimeManagementServiceRequestLabel(selectedSrOption) || selectedSr; const selectedActivityValue = findOptionValue(activityOptions, row?.selectedActivityValue) || cleanString(row?.selectedActivityValue) || ""; const selectedActivityLabel = findOptionLabel(activityOptions, selectedActivityValue) || selectedActivityValue; const taskTypeOptions = getTimeManagementTaskTypeOptions(modal, selectedSr); const selectedTaskTypeValue = findOptionValue(taskTypeOptions, row?.selectedTaskTypeValue) || cleanString(row?.selectedTaskTypeValue) || ""; const selectedTaskTypeLabel = findOptionLabel(taskTypeOptions, selectedTaskTypeValue) || selectedTaskTypeValue; return `
${(modal.weekDays || []) .map((day) => renderTimeManagementDayInput(day, rowId, row?.dayHours) ) .join("")}
`; } function renderTimeManagementSkeleton() { return `
${["Service Request", "Activity", "Task Type"] .map( (label) => `${label}` ) .join("")} ${Array.from({ length: 7 }, () => ` `).join("")}
${Array.from({ length: 3 }, () => `
`).join("")} ${Array.from({ length: 7 }, () => `
`).join("")}
`; } function renderSearchableCombobox({ field, rowId, selectedValue, value, placeholder, options, valueKey, labelKey, fallbackLabelKey, metaKey, disabled = false, }) { const safeField = escapeHtml(field); const safeRowId = escapeHtml(rowId || ""); const isDisabled = Boolean(disabled); const normalizedSelectedValue = normalizeString(selectedValue); const normalizedOptions = (options || []) .map((item) => ({ value: cleanString(item?.[valueKey]), label: cleanString(item?.[labelKey]) || cleanString(item?.[fallbackLabelKey]) || cleanString(item?.[valueKey]), meta: cleanString(item?.[metaKey]), })) .filter((item) => item.value || item.label); return ` ${escapeHtml(value || placeholder || "")} ${ normalizedOptions.length ? normalizedOptions .map( (item, index) => { const isSelected = normalizedSelectedValue && normalizeString(item.value) === normalizedSelectedValue; const meta = item.meta && normalizeString(item.meta) !== normalizeString(item.label) ? item.meta : ""; const optionId = `arch-panel-extension-combobox-${safeField}-${index}`; return ` `; } ) .join("") : `No options` } `; } function renderTimeManagementDatePicker(selectedDate) { const picker = appState.timeManagementDatePicker; if (!picker.isOpen) { return ""; } const monthStart = new Date(picker.year, picker.month, 1); const calendarStart = getWeekStartDate(monthStart); const selectedDateKey = getLocalDateKey(selectedDate); const todayKey = getLocalDateKey(new Date()); const monthLabel = new Intl.DateTimeFormat("en-US", { month: "long", year: "numeric", }).format(monthStart); const days = Array.from({ length: 42 }, (_, index) => { const date = new Date(calendarStart); date.setDate(calendarStart.getDate() + index); const dateKey = getLocalDateKey(date); const className = [ "arch-panel-extension-date-picker-day", date.getMonth() === picker.month ? "" : "is-muted", dateKey === todayKey ? "is-today" : "", dateKey === selectedDateKey ? "is-selected" : "", ] .filter(Boolean) .join(" "); return ` `; }); return `
${escapeHtml(monthLabel)}
${["S", "M", "T", "W", "T", "F", "S"].map((day) => `${day}`).join("")}
${days.join("")}
`; } function renderTimeManagementHourIndicators(modal) { if (modal?.status === "loading") { return `
${Array.from({ length: 4 }, () => ` `).join("")}
`; } return `
${buildTimeManagementHourIndicators(modal) .map( (indicator) => ` ${escapeHtml(indicator.label)} ${escapeHtml(formatHours(indicator.value))} ` ) .join("")}
`; } function buildTimeManagementHourIndicators(modal) { const totals = getTimeManagementRows(modal).reduce( (accumulator, row) => { const rowTotal = getTimeManagementRowTotalHours(row); const category = getTimeManagementHourCategory(modal, row); accumulator[category] += rowTotal; accumulator.total += rowTotal; return accumulator; }, { service: 0, nonService: 0, timeOff: 0, total: 0, } ); return [ { label: "Service", value: totals.service }, { label: "Non Service", value: totals.nonService }, { label: "Time Off", value: totals.timeOff }, { label: "Total hours", value: totals.total }, ]; } function getTimeManagementRowTotalHours(row) { return Object.values(row?.dayHours || {}).reduce( (sum, value) => sum + formatTimeManagementHourPayloadValue(value), 0 ); } function getTimeManagementHourCategory(modal, row) { if (isTimeManagementTimeOffRow(modal, row)) { return "timeOff"; } return isNonServiceRequestSrNumber(row?.selectedSrNumber) ? "nonService" : "service"; } function isTimeManagementTimeOffRow(modal, row) { const taskTypeValue = cleanString(row?.selectedTaskTypeValue); const taskType = findTimeManagementTaskTypeByValue(modal, taskTypeValue); const candidates = [ taskTypeValue, taskType?.label, taskType?.tags, ].map((value) => normalizeString(value)); return candidates.some( (value) => value === "TIME_OFF" || value === "TIMEOFF" || value.includes("TIME_OFF") || value.includes("TIME OFF") ); } function findTimeManagementTaskTypeByValue(modal, value) { const normalizedValue = normalizeString(value); if (!normalizedValue) { return null; } return (modal?.taskTypes || []).find( (item) => normalizeString(item?.value) === normalizedValue ) || null; } function renderTimeManagementDayInput( day, rowId = "", dayHours = {} ) { const dateKey = getTimeManagementDayKey(day); const value = cleanString(dayHours?.[dateKey]); return ` `; } return { renderTimeManagementModal, }; } globalThis.ArchPanelManageTimeView = Object.freeze({ create, }); })();