import { signedGet, isSuccess } from '@/api/client'; import { dropdownMap } from '@/api/dropdowns'; import { metricOptions, toDateInput } from '@/helpers/metric'; const STATUS = { active: 'Active', disabled: 'Disabled' }; const YES_NO = { yes: 'Yes', no: 'No' }; const MANAGER_LEVELS = { l1manager: 'L1 Manager', l2manager: 'L2 Manager', l3manager: 'L3 Manager', l4manager: 'L4 Manager', }; const DAYS = { MON: 'Monday', TUE: 'Tuesday', WED: 'Wednesday', THU: 'Thursday', FRI: 'Friday', SAT: 'Saturday', SUN: 'Sunday', }; function dateOptions() { const values = { L: 'Last day of month' }; for (let day = 1; day <= 31; day += 1) values[String(day)] = String(day); return values; } function toBool(value) { if (value === true || value === 1) return true; return ['yes', '1', 'true'].includes(String(value ?? '').toLowerCase()); } function fromBool(value) { return toBool(value) ? 'yes' : 'no'; } function toStringList(value) { if (value == null || value === '') return []; if (Array.isArray(value)) return value.map(String).filter((part) => part !== ''); if (typeof value === 'object') return Object.values(value).map(String); return [String(value)]; } function titleMap(items) { const values = {}; (items || []).forEach((item) => { if (item?.id) values[item.id] = item.title || item.name || item.id; }); return values; } async function getAllItems(service, path) { const response = await signedGet(service, path); return isSuccess(response) ? response.data?.items || [] : []; } function newMilestoneId() { if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') { return crypto.randomUUID(); } return `${Date.now()}-${Math.random().toString(16).slice(2)}`; } function flattenMetrics(metrics) { if (!Array.isArray(metrics)) return []; return metrics.map((row) => { const metric = row && typeof row === 'object' ? row : {}; return { metric: metric.metric || '', display: metric.display || '', weight: metric.weight ?? 1, target: metric.target ?? '', }; }); } function firstBadge(value) { if (Array.isArray(value)) return value[0] || ''; return value || ''; } function flattenMilestoneCards(milestones) { if (!Array.isArray(milestones)) return []; return milestones.map((row) => { const card = row && typeof row === 'object' ? row : {}; const target = card.target && typeof card.target === 'object' ? card.target : {}; const actions = card.actions && typeof card.actions === 'object' ? card.actions : {}; const appreciation = Array.isArray(actions.send_appreciation) ? actions.send_appreciation[0] || {} : actions.send_appreciation || {}; return { milestone_id: card.milestone_id || '', target_title: target.target_title ?? '', target: target.value ?? (typeof card.target === 'number' || typeof card.target === 'string' ? card.target : ''), repeat_target: card.repeat_target ? '1' : '0', roles: toStringList(card.roles), reporting_roles: toStringList(card.reporting_roles), user_notification: Boolean(actions.user_notification), user_email: Boolean(actions.user_email), manager_notification: toStringList(actions.manager_notification), manager_email: toStringList(actions.manager_email), send_badge: firstBadge(actions.send_badge), appreciation_category: appreciation.category_id || '', appreciation_image: appreciation.image_id || '', appreciation_message: appreciation.message || '', }; }); } function mapMetricsForSave(rows) { return (Array.isArray(rows) ? rows : []) .filter((row) => row?.metric) .map((row) => ({ metric: row.metric, display: row.display || '', weight: row.weight !== '' && row.weight != null ? String(row.weight) : '1', target: row.target !== '' && row.target != null ? String(row.target) : '', })); } function mapMilestonesForSave(rows) { return (Array.isArray(rows) ? rows : []).map((row) => ({ milestone_id: row.milestone_id || newMilestoneId(), target: { value: Number(row.target || 0), target_title: row.target_title || '', }, repeat_target: String(row.repeat_target) === '1', roles: toStringList(row.roles), reporting_roles: toStringList(row.reporting_roles), actions: { user_notification: Boolean(row.user_notification), user_email: Boolean(row.user_email), manager_notification: toStringList(row.manager_notification), manager_email: toStringList(row.manager_email), send_badge: row.send_badge ? [row.send_badge] : [], send_appreciation: [ { category_id: row.appreciation_category || null, image_id: row.appreciation_image || null, message: row.appreciation_message || null, }, ], }, })); } const milestones = { service: 'formreminders', module: 'milestones', title: 'Milestone', subtitle: 'Recognition', baseUrl: '/milestone', listPath: '/milestones', listFields: [ { key: 'actions', title: 'Actions', buttons: ['edit', 'delete'] }, { key: 'title', title: 'Name', type: 'text' }, { key: 'status', title: 'Status', type: 'select' }, ], formFields: async () => { const [metrics, roles, badges, categories, images, userAttrRes] = await Promise.all([ metricOptions(), dropdownMap('ums', 'roles', (item) => item.name), getAllItems('recognition', 'badge_list/get_all').then(titleMap), getAllItems('recognition', 'appreciation_category/get_all').then(titleMap), getAllItems('recognition', 'appreciation_image/get_all').then((items) => { const values = {}; items.forEach((item) => { if (item?.id) values[item.id] = { title: item.title || item.id, image: item.image || '' }; }); return values; }), signedGet('ums', 'userattribute/get_all'), ]); const userAttributes = {}; const userAttrItems = isSuccess(userAttrRes) ? userAttrRes.data?.items || [] : []; userAttrItems.forEach((attr) => { if (!attr?.code || attr.status === 'disabled') return; userAttributes[attr.code] = attr.attribute || attr.code; }); return [ { key: 'title', title: 'Title', type: 'text', required: true }, { key: 'interval_start_date', title: 'Interval Start Date', type: 'date', required: true }, { key: 'interval_end_date', title: 'Interval End Date', type: 'date', required: true }, { key: 'period', title: 'Period', type: 'select', required: true, values: { daily: 'Daily', weekly: 'Weekly', monthly: 'Monthly', yearly: 'Yearly', overall: 'Overall', custom: 'Custom', }, }, { key: 'custom_start_date', title: 'Custom Start Date', type: 'date', showIf: { period: 'custom' } }, { key: 'custom_end_date', title: 'Custom End Date', type: 'date', showIf: { period: 'custom' } }, { key: 'status', title: 'Status', type: 'select', required: true, values: STATUS }, { key: 'show_positions', title: 'Show Positions', type: 'select', required: true, values: YES_NO }, { key: 'show_positions_type', title: 'Show Positions Type', type: 'select', required: true, values: { all: 'All', loggedin: 'Logged In' }, }, { key: 'show_units_export', title: 'Show Units Export', type: 'select', required: true, values: YES_NO, default: 'yes' }, { key: 'show_user_attributes', title: 'Show User Attributes', type: 'select', required: true, values: YES_NO, default: 'no' }, { key: 'user_attributes', title: 'Include User Attributes', type: 'multiselect', values: userAttributes, default: [], showIf: { show_user_attributes: 'yes' }, }, { key: 'show_normal_metrics', title: 'Show Normal Metrics', type: 'select', required: true, values: YES_NO, default: 'yes' }, { key: 'show_combined_metrics', title: 'Show Combined Metrics', type: 'select', required: true, values: YES_NO, default: 'yes' }, { key: 'manager_details', title: 'Manager Details', type: 'multiselect', values: MANAGER_LEVELS, default: ['l1manager'] }, { key: 'total_units_name', title: 'Total Units Name', type: 'text', default: '' }, { key: 'send_report', title: 'Send Report', type: 'select', required: true, values: YES_NO }, { key: 'performance_period', title: 'Performance Period', type: 'select', values: { daily: 'Daily', weekly: 'Weekly', monthly: 'Monthly' }, showIf: { send_report: 'yes' }, }, { key: 'days_or_dates', title: 'Days or Dates', type: 'radio', fullwidth: true, values: { days: 'Days', dates: 'Dates' }, showIf: { send_report: 'yes' }, }, { key: 'days', title: 'Days', type: 'checkbox', fullwidth: true, values: DAYS, showIf: { send_report: 'yes', days_or_dates: 'days' }, }, { key: 'dates', title: 'Dates', type: 'multiselect', values: dateOptions(), showIf: { send_report: 'yes', days_or_dates: 'dates' }, }, { key: 'send_time', title: 'Send Time', type: 'text', showIf: { send_report: 'yes' } }, { key: 'send_report_roles', title: 'Send Report Roles', type: 'multiselect', values: roles, showIf: { send_report: 'yes' }, }, { key: 'report_roles', title: 'Report Roles', type: 'multiselect', values: roles, showIf: { send_report: 'yes' }, }, { key: 'send_user_performance', title: 'Send User Performance', type: 'select', values: YES_NO, showIf: { send_report: 'yes' }, }, { key: 'ai_action_items', title: 'AI Action Items', type: 'select', values: YES_NO, showIf: { send_report: 'yes' }, }, { key: 'send_pending_users', title: 'Send Pending Users', type: 'select', values: YES_NO, showIf: { send_report: 'yes' }, }, { key: 'show_target_average', title: 'Show Target Average', type: 'select', values: YES_NO, showIf: { send_report: 'yes' }, }, { key: 'show_overall_average', title: 'Show Overall Average', type: 'select', values: YES_NO, showIf: { send_report: 'yes' }, }, { key: 'metrics', title: 'Metric Mapping', type: 'mapping', variant: 'milestone_metrics', required: true, metrics, fullwidth: true, }, { key: 'milestones', title: 'Milestone', type: 'milestonemapping', required: true, roles, badges, appreciationCategories: categories, appreciationImages: images, fullwidth: true, }, ]; }, beforeForm: (item) => { const next = { ...item }; if (next.interval) { const [start, end] = String(next.interval).split('_'); next.interval_start_date = toDateInput(start); next.interval_end_date = toDateInput(end); } else { next.interval_start_date = toDateInput(next.interval_start_date); next.interval_end_date = toDateInput(next.interval_end_date); } next.custom_start_date = toDateInput(next.custom_start_date); next.custom_end_date = toDateInput(next.custom_end_date); next.metrics = flattenMetrics(next.metrics); next.milestones = flattenMilestoneCards(next.milestones); const reportConfig = next.report_config && typeof next.report_config === 'object' ? next.report_config : {}; next.days_or_dates = reportConfig.days_or_dates || 'days'; next.days = toStringList(reportConfig.days); next.dates = toStringList(reportConfig.dates).map(String); next.send_time = reportConfig.send_time || ''; next.performance_period = reportConfig.performance_period || ''; next.send_report_roles = toStringList(reportConfig.send_report_roles); next.report_roles = toStringList(reportConfig.report_roles); next.send_user_performance = fromBool(reportConfig.send_user_performance ?? false); next.ai_action_items = fromBool(reportConfig.ai_action_items ?? false); next.send_pending_users = fromBool(reportConfig.send_pending_users ?? false); next.show_target_average = fromBool(reportConfig.show_target_average ?? false); next.show_overall_average = fromBool(reportConfig.show_overall_average ?? false); next.send_report = fromBool(next.send_report ?? false); next.show_units_export = next.show_units_export || 'yes'; next.show_user_attributes = next.show_user_attributes === 'yes' ? 'yes' : 'no'; next.user_attributes = toStringList(next.user_attributes); next.show_normal_metrics = next.show_normal_metrics || 'yes'; next.show_combined_metrics = next.show_combined_metrics || 'yes'; next.manager_details = toStringList(next.manager_details); if (!next.manager_details.length) next.manager_details = ['l1manager']; next.total_units_name = next.total_units_name || ''; return next; }, beforeSave: (data) => { const payload = { ...data }; const start = toDateInput(payload.interval_start_date); const end = toDateInput(payload.interval_end_date); payload.interval = start && end ? `${start}_${end}` : ''; payload.custom_start_date = payload.period === 'custom' ? toDateInput(payload.custom_start_date) : ''; payload.custom_end_date = payload.period === 'custom' ? toDateInput(payload.custom_end_date) : ''; payload.metrics = mapMetricsForSave(payload.metrics); payload.milestones = mapMilestonesForSave(payload.milestones); const daysOrDates = payload.days_or_dates || 'days'; payload.show_units_export = payload.show_units_export || 'yes'; payload.show_user_attributes = payload.show_user_attributes === 'yes' ? 'yes' : 'no'; payload.user_attributes = toStringList(payload.user_attributes); payload.show_normal_metrics = payload.show_normal_metrics || 'yes'; payload.show_combined_metrics = payload.show_combined_metrics || 'yes'; payload.manager_details = toStringList(payload.manager_details); if (!payload.manager_details.length) payload.manager_details = ['l1manager']; payload.total_units_name = payload.total_units_name || ''; payload.send_report = toBool(payload.send_report ?? 'no'); payload.report_config = { days_or_dates: daysOrDates, days: daysOrDates === 'days' ? toStringList(payload.days) : [], dates: daysOrDates === 'dates' ? toStringList(payload.dates) : [], send_time: payload.send_time || '13:00', performance_period: payload.performance_period || 'monthly', send_report_roles: toStringList(payload.send_report_roles), report_roles: toStringList(payload.report_roles), send_user_performance: toBool(payload.send_user_performance ?? 'no'), ai_action_items: toBool(payload.ai_action_items ?? 'no'), send_pending_users: toBool(payload.send_pending_users ?? 'no'), show_target_average: toBool(payload.show_target_average ?? 'no'), show_overall_average: toBool(payload.show_overall_average ?? 'no'), }; delete payload.interval_start_date; delete payload.interval_end_date; delete payload.days_or_dates; delete payload.days; delete payload.dates; delete payload.send_time; delete payload.performance_period; delete payload.send_report_roles; delete payload.report_roles; delete payload.send_user_performance; delete payload.ai_action_items; delete payload.send_pending_users; delete payload.show_target_average; delete payload.show_overall_average; return payload; }, }; export default milestones;