diff --git a/src/assets/styles/analyticalView.scss b/src/assets/styles/analyticalView.scss
index 8b3ab30..3d508cd 100644
--- a/src/assets/styles/analyticalView.scss
+++ b/src/assets/styles/analyticalView.scss
@@ -35,6 +35,10 @@
border-radius: 10px;
position: relative;
+ &.next_activity {
+ background-color: transparent;
+ }
+
.recommendation-status {
position: absolute;
right: 0;
diff --git a/src/assets/styles/case.scss b/src/assets/styles/case.scss
index a169955..1690cb6 100644
--- a/src/assets/styles/case.scss
+++ b/src/assets/styles/case.scss
@@ -69,6 +69,10 @@
.case-performance {
padding-right: 20px;
}
+
+ .kpi {
+ margin-right: 1em;
+ }
}
}
diff --git a/src/assets/styles/cases.scss b/src/assets/styles/cases.scss
index 3b7cd93..26d650b 100644
--- a/src/assets/styles/cases.scss
+++ b/src/assets/styles/cases.scss
@@ -1,8 +1,7 @@
// Cases
-
-
#cases,
-#recommendations {
+#recommendations,
+#resource-management {
padding: 20px 20px;
display: flex;
flex-direction: column;
diff --git a/src/assets/styles/operationalView.scss b/src/assets/styles/operationalView.scss
index 501466d..90ed17a 100644
--- a/src/assets/styles/operationalView.scss
+++ b/src/assets/styles/operationalView.scss
@@ -54,21 +54,75 @@
.recommendation {
display: flex;
flex-direction: row;
- margin: 5px 0px;
+ margin: 5px 0;
padding: 10px;
transition: .2s;
background-color: $k-blue3;
border-radius: 10px;
justify-content: space-between;
- .column {
- margin-right: 5px;
+ .recommendation-content {
+ display: flex;
+ justify-content: space-between;
+ width: 100%;
+ }
+
+ .left-column {
+ flex: 3;
+ margin-right: 10px;
+ }
+
+ .right-column {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ }
+
+ .text-tooltip-container {
+ display: flex;
+ align-items: center;
+ }
+
+ .button-container {
+ display: flex;
+ justify-content: flex-end;
+ gap: 10px;
+ margin-bottom: 10px;
+ }
+
+ .blue-button {
+ background-color: $k-blue;
+ color: white;
+ border: none;
+ padding: 0.4em 2em;
+ text-align: center;
+ text-decoration: none;
+ display: inline-block;
+ font-size: 15px;
+ margin: 4px 2px;
+ cursor: pointer;
+ border-radius: 25px;
+ }
+
+ &.next_activity {
+ background-color: transparent;
}
}
- // .selected{
- // background-color: $k-blue4;
- // }
+ }
+
+ .resource-details {
+ max-width: 60em;
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ background-color: $k-white;
+ padding: 15px;
+ border-radius: 10px;
+ height: calc(100vh - 110px - $case-top);
+ overflow-y: auto;
+ margin-right: 1em;
}
}
\ No newline at end of file
diff --git a/src/assets/styles/style.scss b/src/assets/styles/style.scss
index 7e61ac1..37ddb19 100644
--- a/src/assets/styles/style.scss
+++ b/src/assets/styles/style.scss
@@ -369,7 +369,10 @@ textarea{
}
.cases-table,
-.recommendations-table {
+.recommendations-table,
+.resources-table {
+ width: 100%;
+ overflow-x: auto;
display: flex;
flex: 1;
align-items: flex-start;
@@ -511,4 +514,72 @@ textarea{
width: 0 !important;
height: 0 !important;
}
+}
+
+.kpi {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-around;
+ padding: 10px;
+ margin: 10px 10px 0px 0px;
+ background-color: $k-white;
+ box-shadow: 0px 10px 27px rgba(0, 0, 0, 0.05);
+ color: $k-black;
+ border-radius: 10px;
+ transition: 0.2s;
+ height: max-content;
+}
+
+.kpi-number {
+ color: $k-blue;
+}
+
+.show-details {
+ background: none;
+ border: none;
+ font-size: 14px;
+ color: #007bff;
+}
+
+.resources-table {
+ width: 100%;
+ border-collapse: collapse;
+ table-layout: fixed;
+ overflow-x: auto;
+ //min-width: 55rem;
+}
+
+.resources-table th,
+.resources-table td {
+ padding: 8px;
+ vertical-align: middle;
+ border-bottom: 1px solid #ccc;
+ border-top: none !important;
+
+ th.sortable::after, th.vtl-asc::after, th.vtl-desc::after {
+ display: none !important;
+ }
+}
+
+.fixed-width {
+ width: auto;
+ min-width: 13em;
+ text-align: left;
+}
+
+.resource-status {
+ display: inline-block;
+ padding: 4px 8px;
+ text-align: center;
+ font-weight: bold;
+ border-radius: 7px;
+ width: 8em;
+}
+
+.resource-status.available {
+ background: linear-gradient(135deg, $k-green1 5%, $k-green2 100%);
+}
+
+.resource-status.unavailable {
+ background: linear-gradient(135deg, #AAAAAA 0%, #979797 100%);
}
\ No newline at end of file
diff --git a/src/common/utils.js b/src/common/utils.js
index 2baa624..7c71cb3 100644
--- a/src/common/utils.js
+++ b/src/common/utils.js
@@ -76,6 +76,14 @@ export default {
pStatus: (p) => p.status,
pIsRecommended: (p) => p.output.cate > 0
},
+ 'RESOURCE_ALLOCATION': {
+ pType: 'Resource allocation',
+ pColor: 'background-green',
+ pText: (p) => `Allocate resource ${p.output.resource} until ${new Date(p.output.allocated_until).toLocaleString()}`,
+ pMetric: (p) => `Causal effect: ${p.output.cate_category} (${p.output.cate})`,
+ pStatus: (p) => p.status,
+ pIsRecommended: (p) => p.output.cate > 0
+ }
},
parseDuration(duration) {
diff --git a/src/components/OngoingChartsManagerComponent.vue b/src/components/OngoingChartsManagerComponent.vue
new file mode 100644
index 0000000..8f4b2a2
--- /dev/null
+++ b/src/components/OngoingChartsManagerComponent.vue
@@ -0,0 +1,121 @@
+
+
+
+
{{ recommendationTypesTitle }}
+
+
+
+
+
{{ recommendationsAcceptanceTitle }}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/PositiveOutcomeItemComponent.vue b/src/components/PositiveOutcomeItemComponent.vue
new file mode 100644
index 0000000..23813d3
--- /dev/null
+++ b/src/components/PositiveOutcomeItemComponent.vue
@@ -0,0 +1,31 @@
+
+
+
Target
+
{{ object.value }} {{ object.unit }}
+
Case {{ object.column }} {{ object.operator }}
+
+
+
+
\ No newline at end of file
diff --git a/src/components/ResourcesTableComponent.vue b/src/components/ResourcesTableComponent.vue
new file mode 100644
index 0000000..994051b
--- /dev/null
+++ b/src/components/ResourcesTableComponent.vue
@@ -0,0 +1,70 @@
+
+
+
+
+ {{ data.value.name }}
+
+
+ {{ data.value.role }}
+
+
+
+
+ {{ data.value.status }}
+
+
+
+
+
+ {{ data.value.id }}
+
+
+
+
+
+
+
diff --git a/src/components/SideBarComponent.vue b/src/components/SideBarComponent.vue
index cb760dc..3ae5f82 100644
--- a/src/components/SideBarComponent.vue
+++ b/src/components/SideBarComponent.vue
@@ -1,7 +1,7 @@
-
\ No newline at end of file
+
diff --git a/src/components/casePage/FlowDiagramComponent.vue b/src/components/casePage/FlowDiagramComponent.vue
index 691f369..55965bd 100644
--- a/src/components/casePage/FlowDiagramComponent.vue
+++ b/src/components/casePage/FlowDiagramComponent.vue
@@ -1,6 +1,6 @@
@@ -12,117 +12,118 @@ import dagre from 'cytoscape-dagre';
cytoscape.use(dagre);
export default {
-
name: 'vue-cytoscape',
props: {
currentCase: Object,
caseCompleted: Boolean,
parameters: Object
},
-
data() {
return {
cy: null,
elems: [],
+ uniqueId: `flow-cy-${Math.random().toString(36).substr(2, 9)}`
}
},
-
mounted() {
this.createDiagram();
},
-
watch: {
currentCase() {
this.createNodes();
}
},
-
methods: {
displayDiagram() {
- this.cy.layout({
- fit: false,
- name: 'dagre',
- rankDir: 'LR',
- align: 'DR',
- }).run()
- this.cy.zoom(1.2);
+ if (this.cy) {
+ this.cy.layout({
+ fit: false,
+ name: 'dagre',
+ rankDir: 'LR',
+ align: 'DR',
+ }).run();
+ this.cy.zoom(1.2);
+ }
},
-
createDiagram() {
+ // Wait until the DOM is fully rendered
+ this.$nextTick(() => {
+ const container = document.getElementById(this.uniqueId);
+ if (!container) {
+ console.error("Diagram container not found:", this.uniqueId);
+ return;
+ }
- var width = 15;
- var height = 15;
- var lineWidth = 1;
- var cy = cytoscape({
- container: document.getElementById('flow-cy'),
- // zoomingEnabled: false,
- // panningEnabled: false,
- autoungrabify: true,
- // autounselectify: true,
-
- style: [
-
- {
- selector: 'node',
- style: {
- 'text-halign': 'center',
- 'text-valign': 'bottom',
- 'text-margin-y': 5,
- 'shape': 'ellipse',
- 'background-color': '#d2d6da',
- 'border-width': 0,
- 'text-wrap': 'wrap',
- 'text-max-width': width - 10,
- 'height': height,
- 'width': width,
- 'font-size': 6,
- 'font-family': 'arial'
- }
- },
- {
- selector: 'edge',
- style: {
- 'curve-style': 'straight',
- 'target-arrow-shape': 'vee',
- 'width': lineWidth,
- 'line-color': '#252F40',
- 'target-arrow-color': '#252F40',
- }
- },
- {
- selector: '.nextActivity',
- style: {
- 'label': 'data(label)',
- 'background-color': '#EBF0FF',
- }
- },
+ var width = 15;
+ var height = 15;
+ var lineWidth = 1;
+ var cy = cytoscape({
+ container: container,
+ autoungrabify: true,
+ style: [
+ {
+ selector: 'node',
+ style: {
+ 'text-halign': 'center',
+ 'text-valign': 'bottom',
+ 'text-margin-y': 5,
+ 'shape': 'ellipse',
+ 'background-color': '#d2d6da',
+ 'border-width': 0,
+ 'text-wrap': 'wrap',
+ 'text-max-width': width - 10,
+ 'height': height,
+ 'width': width,
+ 'font-size': 6,
+ 'font-family': 'arial'
+ }
+ },
+ {
+ selector: 'edge',
+ style: {
+ 'curve-style': 'straight',
+ 'target-arrow-shape': 'vee',
+ 'width': lineWidth,
+ 'line-color': '#252F40',
+ 'target-arrow-color': '#252F40',
+ }
+ },
+ {
+ selector: '.nextActivity',
+ style: {
+ 'label': 'data(label)',
+ 'background-color': '#EBF0FF',
+ }
+ },
+ {
+ selector: '.completedActivity',
+ style: {
+ 'label': 'data(label)',
+ 'background-color': '#8392AB',
+ }
+ },
+ ],
+ });
- {
- selector: '.completedActivity',
- style: {
- 'label': 'data(label)',
- 'background-color': '#8392AB',
- }
- },
- ],
+ this.cy = cy;
+ this.createNodes();
});
-
- this.cy = cy;
- this.createNodes();
-
},
-
createNodes() {
+ if (!this.cy || !this.currentCase.activities) {
+ console.error("Cytoscape instance or activities not available");
+ return;
+ }
+
let activities = this.currentCase.activities;
- // activities = activities.slice(-3); // display only last 3 completed activities
const l = activities.length;
var elems = [];
- var lastNodeId = 'an' + (l - 1)
+ var lastNodeId = 'an' + (l - 1);
for (let i = 0; i < l; i++) {
const activity = activities[i];
- let content = activity[this.parameters.columnsDefinitionReverse['ACTIVITY']]
+ let content = activity[this.parameters.columnsDefinitionReverse['ACTIVITY']];
elems.push({
group: "nodes",
@@ -144,6 +145,7 @@ export default {
});
}
}
+
let lastRecommendations = activities[l - 1].prescriptions;
if (lastRecommendations) {
let nextActivityRecommendation = lastRecommendations.filter(r => r.type === 'NEXT_ACTIVITY');
@@ -195,8 +197,6 @@ export default {
this.elems = elems;
this.displayDiagram();
}
-
}
}
-
\ No newline at end of file
diff --git a/src/components/casePage/ManagerViewComponent.vue b/src/components/casePage/ManagerViewComponent.vue
new file mode 100644
index 0000000..7840d17
--- /dev/null
+++ b/src/components/casePage/ManagerViewComponent.vue
@@ -0,0 +1,130 @@
+
+
+
+
+
Case status
+
{{ lastActivity[parameters.columnsDefinitionReverse['ACTIVITY']] }} complete
+
{{ lastActivity[parameters.columnsDefinitionReverse['START_TIMESTAMP']] }}
+
+
+
+
+
+
Resources
+
Recommended resource
+
+
All resources
+
+
+
+
+
Recommendations
+
+
+ Recommendation info
+
+
+ How are recommendations calculated?
+ There are three different algorithms that prescribe recommendations.
+ Intervention
+ An algorithm estimates the causal effect of performing the intervention at a given point in time. It is shown as ”recommended” when an estimated effect is positive (above 0).
+ Alarm
+ Probability of not meeting the KPI is high. It is recommended to check on the application.
+ Next activity
+ There is a high probability of reaching the KPI if you address this recommendation now.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/casePage/OperationalRecommendationManagerComponent.vue b/src/components/casePage/OperationalRecommendationManagerComponent.vue
new file mode 100644
index 0000000..ba44668
--- /dev/null
+++ b/src/components/casePage/OperationalRecommendationManagerComponent.vue
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
{{ r.rec }}
+
+
+ Details - calculation info
+
+
+ Model description
+ {{ m.name }}: {{ m.metric }}
+
+
+
+
{{ r.recommended }}
+
+
+ Assign to
+ Discard
+
+
+
+
+
+
The system recommends to assign this resource to this action. If followed, the probability of reaching the target goal of the process is high.
+
+ Assign
+ Cancel
+
+
+
+
+
+
+
{{ r.status }}
+
+
+
+
+
+
+
diff --git a/src/components/casePage/RecommendationComponent.vue b/src/components/casePage/RecommendationComponent.vue
index 29fe53e..350eea1 100644
--- a/src/components/casePage/RecommendationComponent.vue
+++ b/src/components/casePage/RecommendationComponent.vue
@@ -1,82 +1,80 @@
-
-
Case status: {{ caseStatus }} complete
-
-
-
-
{{ r.rec }}
-
-
{{ r.recommended ? 'Recommended now' : 'Not recommended now' }}
-
-
{{ r.metric }}
-
{{ r.status }}
-
-
+
+
Case status: {{ caseStatus }} complete
+
+
+
+
{{ r.rec }}
+
+
{{ r.recommended ? 'Recommended now' : 'Not recommended now' }}
+
+
{{ r.metric }}
+
{{ r.status }}
+
\ No newline at end of file
diff --git a/src/components/casesPage/CompletedChartsComponent.vue b/src/components/casesPage/CompletedChartsComponent.vue
index 5e713a7..e277aad 100644
--- a/src/components/casesPage/CompletedChartsComponent.vue
+++ b/src/components/casesPage/CompletedChartsComponent.vue
@@ -135,10 +135,10 @@ export default {
name: "Accepted",
data: [0, 0, 0],
},
- {
- name: 'Discarded',
- data: [0, 0, 0]
- }
+ {
+ name: 'Discarded',
+ data: [0, 0, 0]
+ }
],
chartOptions: {
colors: ['#17ad37', '#7e7e7e'],
@@ -224,17 +224,21 @@ export default {
createRecommendationsStatistics() {
this.cases.forEach(({ case_performance, activities }) => {
-
const outcome = utils.calculateCaseOutcome(case_performance);
const prescriptions = activities.map(a => a.prescriptions).flat();
prescriptions.forEach(p => {
+ if (!this.recommendationsStatistics.rows[outcome]) {
+ this.recommendationsStatistics.rows[outcome] = {};
+ }
+ if (!this.recommendationsStatistics.rows[outcome][p.type]) {
+ this.recommendationsStatistics.rows[outcome][p.type] = { total: 0, accepted: 0 };
+ }
if (p.status === 'accepted') this.recommendationsStatistics.rows[outcome][p.type].accepted += 1;
- this.recommendationsStatistics.rows[outcome][p.type].total += 1
+ this.recommendationsStatistics.rows[outcome][p.type].total += 1;
});
});
-
- },
+ }
}
}
diff --git a/src/components/casesPage/OngoingChartsComponent.vue b/src/components/casesPage/OngoingChartsComponent.vue
index c7afc41..01b29b4 100644
--- a/src/components/casesPage/OngoingChartsComponent.vue
+++ b/src/components/casesPage/OngoingChartsComponent.vue
@@ -15,7 +15,6 @@
\ No newline at end of file
diff --git a/src/pages/CasePage.vue b/src/pages/CasePage.vue
index 3ab4457..1077a58 100644
--- a/src/pages/CasePage.vue
+++ b/src/pages/CasePage.vue
@@ -48,19 +48,20 @@
-
-
+
+
+
+
-
+
\ No newline at end of file
diff --git a/src/pages/CasesPage.vue b/src/pages/CasesPage.vue
index bc9d482..e599f81 100644
--- a/src/pages/CasesPage.vue
+++ b/src/pages/CasesPage.vue
@@ -23,31 +23,57 @@
Cases without recommendations
{{ casesData.length - casesWithRecommendations }}
+
+
-
-
-
+
+
+
+
+
+
+
+
Cases Overview Table
- Show full
+ Show full
+
+
- Return
- to overview
-
-
+
+
+ Return
+ to overview
+
+
+
-
+
\ No newline at end of file
diff --git a/src/pages/OngoingCasesManager.vue b/src/pages/OngoingCasesManager.vue
new file mode 100644
index 0000000..3cd2654
--- /dev/null
+++ b/src/pages/OngoingCasesManager.vue
@@ -0,0 +1,205 @@
+
+
+
+
+
{{ completionString }} Cases Overview
+
+
+
+
{{ completionString }} cases
+
+
{{ casesData.length }}
+
+
+
+
+
+
+ Cases with recommendations
+
{{ casesWithRecommendations }}
+
+
+
+ Cases without recommendations
+
{{ casesData.length - casesWithRecommendations }}
+
+
+
+
+
+
+
+
+
+
+
Cases Overview Table
+ Show full
+
+
+ Return
+ to overview
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pages/RecommendationsPage.vue b/src/pages/RecommendationsPage.vue
index 093c83c..e84265d 100644
--- a/src/pages/RecommendationsPage.vue
+++ b/src/pages/RecommendationsPage.vue
@@ -8,50 +8,78 @@
Total current recommendations
-
{{ formattedData.length }}
+ {{ formattedData.length }}
- Export recommendations as
- CSV
-
-
-
-
-
-
- {{ formatId(data.value.id) }}
-
-
-
- {{ data.value.performance.value }} {{ data.value.performance.unit }}
-
-
-
-
+
+
+
+
Export recommendations as
+ CSV
+
+
+
+
+
+ {{ formatId(data.value.id) }}
+
+
+ {{ data.value.performance.value }} {{ data.value.performance.unit }}
+
+
+ {{ data.value.details }}
+
+
+ Show details
+
+
+
+
+
+
+
+
+ {{ formatId(data.value.id) }}
+
+
+ {{ data.value.performance.value }} {{ data.value.performance.unit }}
+
+
+
+
-
-
\ No newline at end of file
+};
+
diff --git a/src/pages/ResourcesPage.vue b/src/pages/ResourcesPage.vue
new file mode 100644
index 0000000..336a596
--- /dev/null
+++ b/src/pages/ResourcesPage.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
Resources
+
+
+
Current Workload
+
{{ currentWorkload }}%
+
+
+
+
All Resources
+
+
{{ totalResources }}
+
+
+
+
+
+
Available Resources
+
+
{{ availableResources }}
+
+
+
+
+
+
Busy Resources
+
+
{{ busyResources }}
+
+
+
+
+
+
+
+
+
diff --git a/src/router.js b/src/router.js
index 84360e2..162fe88 100644
--- a/src/router.js
+++ b/src/router.js
@@ -7,6 +7,7 @@ import DashBoardPage from './pages/DashBoardPage'
import ParametersPage from './pages/ParametersPage'
import ColumnsDefinitionPage from "./pages/ColumnsDefinitionPage"
import RecommendationsPage from './pages/RecommendationsPage'
+import ResourcesPage from './pages/ResourcesPage.vue';
const routes = [
{
@@ -57,14 +58,19 @@ const routes = [
path: 'columns',
name: 'columns',
component: ColumnsDefinitionPage,
- },
- {
- path: "recommendations",
- name: "recommendations",
- component: RecommendationsPage,
- },
+ }
]
},
+ {
+ path: '/resources',
+ name: 'resources',
+ component: ResourcesPage,
+ },
+ {
+ path: "/recommendations",
+ name: "recommendations",
+ component: RecommendationsPage,
+ },
];
diff --git a/src/services/resources.service.js b/src/services/resources.service.js
new file mode 100644
index 0000000..8ed2e49
--- /dev/null
+++ b/src/services/resources.service.js
@@ -0,0 +1,105 @@
+import casesService from "@/services/cases.service";
+import utils from "@/common/utils";
+
+const getSystemTime = (cases) => {
+ const casesArray = Array.isArray(cases) ? cases : [cases];
+ for (let event of casesArray) {
+ if (event.activities && Array.isArray(event.activities) && event.activities.length > 0) {
+ for (let activity of event.activities) {
+ if (activity.prescriptions && Array.isArray(activity.prescriptions) && activity.prescriptions.length > 0) {
+ console.log("Found system time in prescription:", activity.prescriptions[0].date);
+ return activity.prescriptions[0].date;
+ }
+ }
+ }
+ }
+ console.error("No valid system time found in cases.");
+ return null;
+};
+
+const processResourceData = (cases) => {
+ const systemTime = getSystemTime(cases);
+ if (!systemTime) {
+ console.error("System time is not set. Cannot process resource data.");
+ return [];
+ }
+
+ const systemTimeDate = new Date(systemTime);
+ const casesArray = Array.isArray(cases) ? cases : [cases];
+
+ return casesArray.flatMap(event => {
+ if (!event.activities || !Array.isArray(event.activities) || event.activities.length === 0) {
+ return [];
+ }
+
+ const eventSystemTime = new Date(event.activities[0]["time:timestamp"]);
+
+ return event.activities.flatMap(activity => {
+ return activity.prescriptions
+ .filter(p => p.type === 'RESOURCE_ALLOCATION' && p.output && p.output.allocated_until)
+ .map(p => {
+ const currentSystemTime = eventSystemTime;
+ const timeDifference = systemTimeDate - currentSystemTime;
+
+ const originalAllocatedUntilTime = new Date(p.output.allocated_until);
+ // Adjust allocated_until by subtracting the time difference
+ const adjustedAllocatedUntilTime = new Date(originalAllocatedUntilTime.getTime() - timeDifference);
+ const isBusy = adjustedAllocatedUntilTime > currentSystemTime; // Check if the resource is still allocated
+
+ return {
+ id: event._id,
+ name: `${p.output.resource}`,
+ role: 'Dynamic Role',
+ status: isBusy ? 'Busy' : 'Available'
+ };
+ });
+ });
+ });
+};
+
+const fetchResourceData = async () => {
+ try {
+ const response = await casesService.getCasesByLogAndCompletion(utils.getLocal('logId'), 'ongoing');
+ if (response.data && Array.isArray(response.data.cases) && response.data.cases.length > 0) {
+ return processResourceData(response.data.cases);
+ } else {
+ console.log("No cases data returned from API");
+ return [];
+ }
+ } catch (error) {
+ console.error("Fetching error:", error);
+ throw error;
+ }
+};
+
+const fetchResourceDataByCaseId = async (caseId) => {
+ try {
+ console.log("Fetching cases with logId:", utils.getLocal('logId'));
+ const response = await casesService.getCasesByLogAndCompletion(utils.getLocal('logId'), 'ongoing');
+ console.log("Response from API:", response.data);
+
+ if (response.data && Array.isArray(response.data.cases)) {
+ console.log("Cases is an array with length:", response.data.cases.length);
+ const matchingCase = response.data.cases.find(c => c._id === caseId);
+
+ if (matchingCase) {
+ console.log("Case ID matches:", caseId);
+ return processResourceData([matchingCase]);
+ } else {
+ console.log("No matching case ID found. Expected:", caseId);
+ return [];
+ }
+ } else {
+ console.log("Cases is not an array or is undefined. Cases:", response.data.cases);
+ return [];
+ }
+ } catch (error) {
+ console.error("Fetching error:", error);
+ throw error;
+ }
+};
+
+export default {
+ fetchResourceData,
+ fetchResourceDataByCaseId
+};
\ No newline at end of file