import { signedGet, isSuccess } from '@/api/client'; import { dropdownMap, fetchUserAttributes } from '@/api/dropdowns'; import { DEFAULT_INTERVAL_VALUES, INTERVAL_VALUES, metricOptions, parseCombinedMetrics, splitHash, stringifyCombinedMetrics, toApiDate, toDateInput, VIEW_COMBINED_TYPES, } from '@/helpers/metric'; function asArray(value) { if (Array.isArray(value)) return value.filter((part) => part !== null && part !== undefined && part !== ''); return splitHash(value); } const metricviews = { service: 'metric', module: 'metric_view', title: 'Metric View', subtitle: 'Metric', baseUrl: '/metricview', listPath: '/metricviews', defaultType: 'simple', listFields: [ { key: 'actions', title: 'Actions', buttons: ['edit', 'duplicate', 'delete'] }, { key: 'name', title: 'Name', type: 'text' }, { key: 'type', title: 'Type', type: 'text' }, { key: 'roles', title: 'Roles', type: 'text' }, { key: 'sort_order', title: 'Sort Order', type: 'number' }, { key: 'validity_start', title: 'Validity start', type: 'date' }, { key: 'validity_end', title: 'Validity end', type: 'date' }, { key: 'agg_type', title: 'Aggregation type', type: 'text' }, { key: 'status', title: 'Status', type: 'select' }, ], listButtons: [ { title: 'Add A vs B', to: '/metricview/addnew?type=verses' }, { title: 'Add Grouped', to: '/metricview/addnew?type=grouped' }, { title: 'Add Simple', to: '/metricview/addnew?type=simple' }, ], mapItems: (items) => (items || []).map((item) => ({ ...item, roles: asArray(item.designations || item.roles).join(', '), sort_order: item.sort_order ?? item.widget_sort_order ?? 0, })), formFields: async () => { const [metrics, roles, contactRes, userAttrItems] = await Promise.all([ metricOptions(), dropdownMap('ums', 'roles', (item) => item.name), signedGet('contact', 'contactattribute/get_all'), fetchUserAttributes(), ]); const contactAttributes = {}; const contactItems = isSuccess(contactRes) ? contactRes.data?.items || [] : []; contactItems.forEach((attr) => { if (attr?.code) contactAttributes[attr.code] = attr.attribute || attr.code; }); const userAttributes = {}; userAttrItems.forEach((attr) => { if (!attr?.code || attr.status === 'disabled') return; userAttributes[attr.code] = attr.attribute || attr.code; }); const versesMetrics = { ...metrics, fixed: 'Fixed Value' }; return [ { key: 'name', title: 'Name', type: 'text', required: true }, { key: 'type', title: 'Type', type: 'select', required: true, values: { simple: 'Simple', grouped: 'Grouped', verses: 'A vs B' }, }, { key: 'validity_start', title: 'Validity start', type: 'date', required: true }, { key: 'validity_end', title: 'Validity end', type: 'date', required: true }, { key: 'designations', title: 'Publish to Roles', type: 'multiselect', required: true, values: roles }, { key: 'metric', title: 'Choose Metric', type: 'select', required: true, values: metrics, showIf: { type: 'simple' } }, { key: 'display_unit', title: 'Display Unit', type: 'text', required: true, showIf: { type: 'simple' } }, { key: 'metric_0', title: 'Choose Metric 1', type: 'select', required: true, values: metrics, showIf: { type: 'verses' } }, { key: 'display_unit_0', title: 'Metric 1 Display Unit', type: 'text', required: true, showIf: { type: 'verses' } }, { key: 'metric_1', title: 'Choose Metric 2', type: 'select', required: true, values: versesMetrics, showIf: { type: 'verses' } }, { key: 'display_unit_1', title: 'Metric 2 Display Unit', type: 'text', required: true, showIf: { type: 'verses' } }, { key: 'fixed_metric', title: 'Fixed Metric value if selected', type: 'text', required: true, showIf: { type: 'verses' } }, { key: 'max_value_color', title: 'Max Value Color', type: 'color', showIf: { type: 'verses' } }, { key: 'color_ranges', title: 'Color Ranges (%)', type: 'color_ranges', fullwidth: true, showIf: { type: 'verses' } }, { key: 'list_chart_type', title: 'List Chart Type', type: 'select', required: true, showIf: { type: 'verses' }, values: { donut: 'Donut', progressbar: 'Progress Bar', horizontal_barchart: 'Horizontal Bar Chart', vertical_barchart: 'Vertical Bar Chart', }, }, { key: 'metrics', title: 'Choose Metric', type: 'mapping', variant: 'grouped', required: true, fullwidth: true, metrics, showIf: { type: 'grouped' }, }, { key: 'operation', title: 'Operation', type: 'select', required: true, values: { sum: 'Sum', avg: 'Avg', value_count: 'Count' } }, { key: 'agg_type', title: 'Aggregation Type', type: 'select', required: true, values: { individual: 'Individual', team: 'Team' }, }, { key: 'graphical_views', title: 'Graphical views', type: 'multiselect', values: { progress: 'Progress', percentile: 'Percentile', pie: 'Pie chart', bar: 'Bar chart', line: 'Line chart' }, }, { key: 'value_views', title: 'Value views', type: 'multiselect', values: { value: 'Value' }, }, { key: 'details_views', title: 'Details views', type: 'multiselect', values: { tabular: 'Tabular', contacts: 'Doctor View', incremental: 'Incremental View' }, }, { key: 'trend_views', title: 'Trend views', type: 'multiselect', values: { bar: 'Bar chart', line: 'Line chart', tabular: 'Tabular' }, }, { key: 'leaderboard_views', title: 'My Team views', type: 'multiselect', values: { leaderboard: 'My Team View' }, }, { key: 'scoreboard_views', title: 'Leaderboard views', type: 'multiselect', values: { leaderboard: 'Leaderboard View' }, }, { key: 'contacts_views', title: 'Doctor views', type: 'multiselect', values: { contacts: 'Doctor View' }, }, { key: 'doctor_view_name', title: 'Enter Doctor View Name', type: 'text' }, { key: 'intervals', title: 'Intervals', type: 'multiselect', required: true, values: INTERVAL_VALUES }, { key: 'default_interval', title: 'Default Interval', type: 'select', required: true, values: DEFAULT_INTERVAL_VALUES }, { key: 'default_tab', title: 'Default Tab', type: 'select', values: { value: 'Value', trend: 'Trend', details: 'Detail', leaderboard: 'My Team', scoreboard: 'Leaderboard', contacts: 'Doctor List', incremental: 'Incremental', }, }, { key: 'widget_sort_order', title: 'Sort Order', type: 'number', required: true }, { key: 'doctor_type', title: 'Doctor Type', type: 'text' }, { key: 'combined_metrics', title: 'Combined Metrics (if any)', type: 'combined_metrics', variant: 'view', fullwidth: true, metrics, types: VIEW_COMBINED_TYPES, }, { key: 'report_roles', title: 'Data Report from Roles', type: 'multiselect', required: true, values: roles }, { key: 'status', title: 'Status', type: 'select', required: true, values: { active: 'Active', disabled: 'Disabled' } }, { key: 'show_positions', title: 'Show Positions', type: 'select', required: true, values: { yes: 'Yes', no: 'No' } }, { key: 'show_positions_type', title: 'Show Positions Type', type: 'select', required: true, values: { all: 'All', loggedin: 'Logged In' }, }, { key: 'contact_attributes', title: 'Include Doctor Attributes', type: 'multiselect', values: contactAttributes }, { key: 'team_leaderboard_widget_roles', title: 'Team Leaderboard Widget Roles', type: 'multiselect', values: roles, }, { key: 'show_user_attributes', title: 'Show User Attributes', type: 'yesno', required: true, default: 'no' }, { key: 'user_attributes', title: 'Include User Attributes', type: 'multiselect', values: userAttributes, default: [], }, { key: 'stateheadwise_leaderboard', title: 'Stateheadwise Leaderboard', type: 'yesno', required: true, default: 'no', }, ]; }, beforeForm: (item) => { const next = { type: 'simple', widget_sort_order: 0, sort_order: 0, show_positions: 'yes', show_positions_type: 'all', show_user_attributes: 'no', user_attributes: [], stateheadwise_leaderboard: 'no', list_chart_type: 'progressbar', value_views: ['value'], default_tab: '', team_leaderboard_widget_roles: [], ...item, }; next.designations = asArray(next.designations); next.report_roles = asArray(next.report_roles); next.graphical_views = asArray(next.graphical_views); next.details_views = asArray(next.details_views); next.trend_views = asArray(next.trend_views); next.leaderboard_views = asArray(next.leaderboard_views); next.scoreboard_views = item && Object.prototype.hasOwnProperty.call(item, 'scoreboard_views') ? asArray(next.scoreboard_views) : asArray(next.leaderboard_views); next.value_views = item && Object.prototype.hasOwnProperty.call(item, 'value_views') ? asArray(next.value_views) : ['value']; next.contacts_views = asArray(next.contacts_views); next.default_tab = next.default_tab || ''; next.intervals = asArray(next.intervals); next.contact_attributes = asArray(next.contact_attributes); next.team_leaderboard_widget_roles = asArray( next.team_leaderboard_widget_roles || next.leaderboard_widget_roles || next.widget_roles, ); next.show_user_attributes = ['yes', '1', 'true', true, 1].includes(next.show_user_attributes) ? 'yes' : 'no'; next.user_attributes = asArray(next.user_attributes); if (next.user_attributes.length && next.show_user_attributes !== 'yes') { next.show_user_attributes = 'yes'; } next.stateheadwise_leaderboard = next.stateheadwise_leaderboard === 'yes' ? 'yes' : 'no'; next.combined_metrics = parseCombinedMetrics(next.combined_metrics); next.validity_start = toDateInput(next.validity_start); next.validity_end = toDateInput(next.validity_end); if (next.sort_order === '' || next.sort_order == null) next.sort_order = next.widget_sort_order || 0; if (next.widget_sort_order === '' || next.widget_sort_order == null) next.widget_sort_order = next.sort_order || 0; if (next.show_positions) next.show_positions = String(next.show_positions).toLowerCase(); if (!Array.isArray(next.color_ranges)) next.color_ranges = []; const metrics = Array.isArray(next.metrics) ? [...next.metrics] : []; metrics.sort((a, b) => (Number(a?.sort_order) || 0) - (Number(b?.sort_order) || 0)); if (next.type === 'simple' && metrics[0]) { next.metric = metrics[0].metric; next.display_unit = metrics[0].display; } else if (next.type === 'verses') { next.metric_0 = metrics[0]?.metric || ''; next.display_unit_0 = metrics[0]?.display || ''; next.metric_1 = metrics[1]?.metric || ''; next.display_unit_1 = metrics[1]?.display || ''; if (!next.list_chart_type) next.list_chart_type = 'progressbar'; } else if (next.type === 'grouped') { next.metrics = metrics.map((row) => ({ metric: row.metric || '', display: row.display || '', sort_order: row.sort_order ?? 0, weight: row.weight ?? 1, list_view: row.list_view || 'yes', })); } return next; }, beforeSave: (data) => { const type = data.type || 'simple'; let metrics = []; if (type === 'simple') { metrics = [{ metric: data.metric, display: data.display_unit }]; } else if (type === 'verses') { metrics = [ { metric: data.metric_0, display: data.display_unit_0 }, { metric: data.metric_1, display: data.display_unit_1 }, ]; } else { metrics = (data.metrics || []) .filter((row) => row.metric) .map((row) => ({ metric: row.metric, display: row.display || '', sort_order: Number(row.sort_order) || 0, list_view: row.list_view || 'yes', weight: row.weight === '' || row.weight == null ? 1 : Number(row.weight), })); } const widgetSort = Number.parseInt(data.widget_sort_order, 10) || 0; const payload = { ...data, type, metrics, designations: asArray(data.designations), report_roles: asArray(data.report_roles), graphical_views: asArray(data.graphical_views), details_views: asArray(data.details_views), trend_views: asArray(data.trend_views), leaderboard_views: asArray(data.leaderboard_views), scoreboard_views: asArray(data.scoreboard_views), value_views: asArray(data.value_views), contacts_views: asArray(data.contacts_views), default_tab: data.default_tab || '', intervals: asArray(data.intervals), contact_attributes: asArray(data.contact_attributes), team_leaderboard_widget_roles: asArray(data.team_leaderboard_widget_roles), show_user_attributes: data.show_user_attributes === 'yes' ? 'yes' : 'no', user_attributes: asArray(data.user_attributes), stateheadwise_leaderboard: data.stateheadwise_leaderboard === 'yes' ? 'yes' : 'no', combined_metrics: stringifyCombinedMetrics( (data.combined_metrics || []) .filter((row) => row.type) .map((row) => ({ type: row.type, title: row.title || '', fields: Array.isArray(row.fields) ? row.fields : [], list_view: row.list_view || 'yes', })), ), widget_sort_order: widgetSort, sort_order: widgetSort, validity_start: toApiDate(data.validity_start), validity_end: toApiDate(data.validity_end), }; if (type === 'verses') { payload.max_value_color = (data.max_value_color || '').trim(); payload.color_ranges = (data.color_ranges || []) .filter((row) => row.min !== '' || row.max !== '' || row.color) .map((row) => ({ min: Number(row.min) || 0, max: Number(row.max) || 0, color: row.color || '#000000', })); payload.list_chart_type = data.list_chart_type || 'progressbar'; } else { delete payload.max_value_color; delete payload.color_ranges; delete payload.list_chart_type; delete payload.fixed_metric; } delete payload.metric; delete payload.display_unit; delete payload.metric_0; delete payload.display_unit_0; delete payload.metric_1; delete payload.display_unit_1; if (payload.id === '' || payload.id == null) delete payload.id; return payload; }, }; export default metricviews;