reactbridge-sdk 0.2.7 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -1
- package/dist/components/reports/DataQualityAutomation.d.ts.map +1 -1
- package/dist/components/reports/DateRangeSelector.d.ts +1 -1
- package/dist/components/reports/DateRangeSelector.d.ts.map +1 -1
- package/dist/components/reports/ExecutionAuditTrail.d.ts.map +1 -1
- package/dist/components/reports/ExecutiveDashboard.d.ts.map +1 -1
- package/dist/components/reports/PortfolioHealth.d.ts.map +1 -1
- package/dist/components/reports/ReportLayout.d.ts.map +1 -1
- package/dist/components/reports/SupplyChainRisk.d.ts.map +1 -1
- package/dist/hooks/analytics/useReportData.d.ts +4 -2
- package/dist/hooks/analytics/useReportData.d.ts.map +1 -1
- package/dist/index.esm.js +208 -89
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +208 -89
- package/dist/index.js.map +1 -1
- package/dist/utils/request-cache.d.ts +32 -0
- package/dist/utils/request-cache.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2751,47 +2751,167 @@ function AnalyticsDashboard({ onDirectiveAction, className = "", showRefresh = t
|
|
|
2751
2751
|
: "Decline"))))))))))))));
|
|
2752
2752
|
}
|
|
2753
2753
|
|
|
2754
|
+
/**
|
|
2755
|
+
* Request Cache Manager
|
|
2756
|
+
* Implements a simple caching mechanism similar to react-query
|
|
2757
|
+
* Prevents duplicate concurrent requests and caches results
|
|
2758
|
+
*/
|
|
2759
|
+
const DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes
|
|
2760
|
+
class RequestCache {
|
|
2761
|
+
constructor() {
|
|
2762
|
+
this.cache = new Map();
|
|
2763
|
+
this.pendingRequests = new Map();
|
|
2764
|
+
}
|
|
2765
|
+
/**
|
|
2766
|
+
* Generate a cache key from function and parameters
|
|
2767
|
+
*/
|
|
2768
|
+
getCacheKey(fetchFn, params) {
|
|
2769
|
+
const fnString = fetchFn.toString();
|
|
2770
|
+
const paramString = params ? JSON.stringify(params) : '';
|
|
2771
|
+
return `${fnString}::${paramString}`;
|
|
2772
|
+
}
|
|
2773
|
+
/**
|
|
2774
|
+
* Check if cache entry is still valid
|
|
2775
|
+
*/
|
|
2776
|
+
isCacheValid(entry) {
|
|
2777
|
+
return Date.now() - entry.timestamp < entry.ttl;
|
|
2778
|
+
}
|
|
2779
|
+
/**
|
|
2780
|
+
* Fetch or return cached data
|
|
2781
|
+
*/
|
|
2782
|
+
get(fetchFn_1, params_1) {
|
|
2783
|
+
return __awaiter(this, arguments, void 0, function* (fetchFn, params, ttl = DEFAULT_TTL) {
|
|
2784
|
+
const key = this.getCacheKey(fetchFn, params);
|
|
2785
|
+
// Return valid cached data
|
|
2786
|
+
const cached = this.cache.get(key);
|
|
2787
|
+
if (cached && this.isCacheValid(cached)) {
|
|
2788
|
+
return cached.data;
|
|
2789
|
+
}
|
|
2790
|
+
// Return pending request if already in flight
|
|
2791
|
+
const pending = this.pendingRequests.get(key);
|
|
2792
|
+
if (pending) {
|
|
2793
|
+
return pending.promise;
|
|
2794
|
+
}
|
|
2795
|
+
// Create new request
|
|
2796
|
+
const promise = fetchFn().then((data) => {
|
|
2797
|
+
this.cache.set(key, {
|
|
2798
|
+
data,
|
|
2799
|
+
timestamp: Date.now(),
|
|
2800
|
+
ttl,
|
|
2801
|
+
});
|
|
2802
|
+
this.pendingRequests.delete(key);
|
|
2803
|
+
return data;
|
|
2804
|
+
}).catch((error) => {
|
|
2805
|
+
this.pendingRequests.delete(key);
|
|
2806
|
+
throw error;
|
|
2807
|
+
});
|
|
2808
|
+
this.pendingRequests.set(key, { promise });
|
|
2809
|
+
return promise;
|
|
2810
|
+
});
|
|
2811
|
+
}
|
|
2812
|
+
/**
|
|
2813
|
+
* Invalidate cache entry
|
|
2814
|
+
*/
|
|
2815
|
+
invalidate(fetchFn, params) {
|
|
2816
|
+
const key = this.getCacheKey(fetchFn, params);
|
|
2817
|
+
this.cache.delete(key);
|
|
2818
|
+
}
|
|
2819
|
+
/**
|
|
2820
|
+
* Clear all cache
|
|
2821
|
+
*/
|
|
2822
|
+
clear() {
|
|
2823
|
+
this.cache.clear();
|
|
2824
|
+
this.pendingRequests.clear();
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
// Singleton instance
|
|
2828
|
+
const requestCache = new RequestCache();
|
|
2829
|
+
|
|
2754
2830
|
/**
|
|
2755
2831
|
* useReportData Hook
|
|
2756
2832
|
* Fetches and manages report data with error handling
|
|
2833
|
+
* Implements caching to prevent duplicate requests
|
|
2757
2834
|
*/
|
|
2758
2835
|
/**
|
|
2759
2836
|
* Generic hook for fetching report data
|
|
2760
|
-
*
|
|
2837
|
+
* Implements caching and deduplication to prevent infinite requests
|
|
2761
2838
|
* @param fetchFn - Async function to fetch report data
|
|
2762
2839
|
* @param dependencies - Dependencies that trigger refetch when changed
|
|
2763
|
-
* @param options - Hook options (enabled flag)
|
|
2840
|
+
* @param options - Hook options (enabled flag, cache TTL)
|
|
2764
2841
|
*/
|
|
2765
2842
|
function useReportData(fetchFn, dependencies = [], options = {}) {
|
|
2766
|
-
const { api } = useReactBridgeContext();
|
|
2767
2843
|
const [data, setData] = React.useState(null);
|
|
2768
2844
|
const [loading, setLoading] = React.useState(true);
|
|
2769
2845
|
const [error, setError] = React.useState(null);
|
|
2770
|
-
const
|
|
2771
|
-
const
|
|
2846
|
+
const isMountedRef = React.useRef(true);
|
|
2847
|
+
const { enabled = true, ttl = 5 * 60 * 1000 } = options;
|
|
2848
|
+
// Create a stable string representation of dependencies for comparison
|
|
2849
|
+
const depsString = JSON.stringify(dependencies);
|
|
2850
|
+
React.useEffect(() => {
|
|
2851
|
+
isMountedRef.current = true;
|
|
2772
2852
|
if (!enabled) {
|
|
2773
2853
|
setLoading(false);
|
|
2774
2854
|
return;
|
|
2775
2855
|
}
|
|
2856
|
+
let cancelled = false;
|
|
2857
|
+
const fetchData = () => __awaiter(this, void 0, void 0, function* () {
|
|
2858
|
+
try {
|
|
2859
|
+
setLoading(true);
|
|
2860
|
+
setError(null);
|
|
2861
|
+
// Use cache to avoid duplicate requests
|
|
2862
|
+
const result = yield requestCache.get(fetchFn, depsString, ttl);
|
|
2863
|
+
if (!cancelled && isMountedRef.current) {
|
|
2864
|
+
setData(result);
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
catch (err) {
|
|
2868
|
+
if (!cancelled && isMountedRef.current) {
|
|
2869
|
+
const error = err instanceof Error ? err : new Error("Unknown error occurred");
|
|
2870
|
+
setError(error);
|
|
2871
|
+
setData(null);
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
finally {
|
|
2875
|
+
if (!cancelled && isMountedRef.current) {
|
|
2876
|
+
setLoading(false);
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
});
|
|
2880
|
+
fetchData();
|
|
2881
|
+
return () => {
|
|
2882
|
+
cancelled = true;
|
|
2883
|
+
};
|
|
2884
|
+
}, [depsString, enabled, ttl, fetchFn]);
|
|
2885
|
+
React.useEffect(() => {
|
|
2886
|
+
return () => {
|
|
2887
|
+
isMountedRef.current = false;
|
|
2888
|
+
};
|
|
2889
|
+
}, []);
|
|
2890
|
+
const refetch = () => __awaiter(this, void 0, void 0, function* () {
|
|
2891
|
+
// Invalidate cache and refetch
|
|
2892
|
+
requestCache.invalidate(fetchFn, depsString);
|
|
2776
2893
|
try {
|
|
2777
2894
|
setLoading(true);
|
|
2778
2895
|
setError(null);
|
|
2779
|
-
const result = yield fetchFn
|
|
2780
|
-
|
|
2896
|
+
const result = yield requestCache.get(fetchFn, depsString, ttl);
|
|
2897
|
+
if (isMountedRef.current) {
|
|
2898
|
+
setData(result);
|
|
2899
|
+
}
|
|
2781
2900
|
}
|
|
2782
2901
|
catch (err) {
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2902
|
+
if (isMountedRef.current) {
|
|
2903
|
+
const error = err instanceof Error ? err : new Error("Unknown error occurred");
|
|
2904
|
+
setError(error);
|
|
2905
|
+
setData(null);
|
|
2906
|
+
}
|
|
2786
2907
|
}
|
|
2787
2908
|
finally {
|
|
2788
|
-
|
|
2909
|
+
if (isMountedRef.current) {
|
|
2910
|
+
setLoading(false);
|
|
2911
|
+
}
|
|
2789
2912
|
}
|
|
2790
|
-
})
|
|
2791
|
-
|
|
2792
|
-
fetchData();
|
|
2793
|
-
}, [fetchData, ...dependencies]);
|
|
2794
|
-
return { data, loading, error, refetch: fetchData };
|
|
2913
|
+
});
|
|
2914
|
+
return { data, loading, error, refetch };
|
|
2795
2915
|
}
|
|
2796
2916
|
|
|
2797
2917
|
/**
|
|
@@ -2904,40 +3024,29 @@ function useDateRange(defaultOption = "past-month") {
|
|
|
2904
3024
|
|
|
2905
3025
|
/**
|
|
2906
3026
|
* DateRangeSelector Component
|
|
2907
|
-
*
|
|
3027
|
+
* Select dropdown for date range selection
|
|
2908
3028
|
*/
|
|
2909
3029
|
const DateRangeSelector = ({ selectedOption, onSelect, theme, }) => {
|
|
2910
3030
|
const options = DateRangeService.getAllOptions();
|
|
2911
|
-
return (React.createElement("
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
if (!isSelected) {
|
|
2931
|
-
e.currentTarget.style.backgroundColor =
|
|
2932
|
-
(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0";
|
|
2933
|
-
}
|
|
2934
|
-
}, onMouseLeave: (e) => {
|
|
2935
|
-
if (!isSelected) {
|
|
2936
|
-
e.currentTarget.style.backgroundColor =
|
|
2937
|
-
(theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5";
|
|
2938
|
-
}
|
|
2939
|
-
} }, option.label));
|
|
2940
|
-
})));
|
|
3031
|
+
return (React.createElement("select", { value: selectedOption, onChange: (e) => onSelect(e.target.value), style: {
|
|
3032
|
+
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "6px"} ${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px"}`,
|
|
3033
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "13px",
|
|
3034
|
+
fontWeight: "500",
|
|
3035
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3036
|
+
border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#d0d0d0"}`,
|
|
3037
|
+
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f9f9f9",
|
|
3038
|
+
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3039
|
+
cursor: "pointer",
|
|
3040
|
+
transition: "border-color 0.2s ease, box-shadow 0.2s ease",
|
|
3041
|
+
}, onFocus: (e) => {
|
|
3042
|
+
e.currentTarget.style.borderColor =
|
|
3043
|
+
(theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2";
|
|
3044
|
+
e.currentTarget.style.boxShadow = `0 0 0 2px ${((theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2") + "20"}`;
|
|
3045
|
+
}, onBlur: (e) => {
|
|
3046
|
+
e.currentTarget.style.borderColor =
|
|
3047
|
+
(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#d0d0d0";
|
|
3048
|
+
e.currentTarget.style.boxShadow = "none";
|
|
3049
|
+
} }, options.map((option) => (React.createElement("option", { key: option.value, value: option.value }, option.label)))));
|
|
2941
3050
|
};
|
|
2942
3051
|
|
|
2943
3052
|
/**
|
|
@@ -2999,35 +3108,37 @@ const LoadingState = ({ theme, variant = "minimal", }) => {
|
|
|
2999
3108
|
* ReportLayout Component
|
|
3000
3109
|
* Wrapper for report pages with header and date range selector
|
|
3001
3110
|
*/
|
|
3002
|
-
const ReportLayout = ({ title, description, selectedDateRange, onDateRangeChange, loading, error, children, theme, }) => {
|
|
3111
|
+
const ReportLayout = ({ title, description, selectedDateRange, onDateRangeChange, loading, error, children, theme: themeProp, }) => {
|
|
3112
|
+
const { theme: contextTheme } = useReactBridgeContext();
|
|
3113
|
+
const theme = themeProp || contextTheme;
|
|
3003
3114
|
return (React.createElement("div", { style: {
|
|
3004
3115
|
display: "flex",
|
|
3005
3116
|
flexDirection: "column",
|
|
3006
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3117
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "12px",
|
|
3007
3118
|
} },
|
|
3008
3119
|
React.createElement("div", { style: {
|
|
3009
3120
|
display: "flex",
|
|
3010
3121
|
alignItems: "flex-start",
|
|
3011
3122
|
justifyContent: "space-between",
|
|
3012
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3123
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "12px",
|
|
3013
3124
|
flexWrap: "wrap",
|
|
3014
3125
|
} },
|
|
3015
3126
|
React.createElement("div", { style: { flex: 1, minWidth: "200px" } },
|
|
3016
3127
|
React.createElement("h1", { style: {
|
|
3017
3128
|
margin: 0,
|
|
3018
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3129
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.lg) || "20px",
|
|
3019
3130
|
fontWeight: "700",
|
|
3020
3131
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3021
3132
|
} }, title),
|
|
3022
3133
|
description && (React.createElement("p", { style: {
|
|
3023
3134
|
margin: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px"} 0 0 0`,
|
|
3024
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "
|
|
3135
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "12px",
|
|
3025
3136
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
|
|
3026
3137
|
} }, description))),
|
|
3027
3138
|
React.createElement(DateRangeSelector, { selectedOption: selectedDateRange, onSelect: onDateRangeChange, theme: theme })),
|
|
3028
3139
|
loading ? (React.createElement(LoadingState, { theme: theme })) : error ? (React.createElement("div", { style: {
|
|
3029
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3030
|
-
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "
|
|
3140
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "12px",
|
|
3141
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3031
3142
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.error)
|
|
3032
3143
|
? `${theme.colors.error}15`
|
|
3033
3144
|
: "#FEE2E2",
|
|
@@ -3035,7 +3146,7 @@ const ReportLayout = ({ title, description, selectedDateRange, onDateRangeChange
|
|
|
3035
3146
|
} },
|
|
3036
3147
|
React.createElement("p", { style: {
|
|
3037
3148
|
margin: 0,
|
|
3038
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "
|
|
3149
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "12px",
|
|
3039
3150
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#f44336",
|
|
3040
3151
|
fontWeight: "500",
|
|
3041
3152
|
} },
|
|
@@ -3065,8 +3176,8 @@ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, them
|
|
|
3065
3176
|
return "→";
|
|
3066
3177
|
};
|
|
3067
3178
|
const containerStyles = {
|
|
3068
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3069
|
-
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "
|
|
3179
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3180
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3070
3181
|
border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
|
|
3071
3182
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
|
|
3072
3183
|
cursor: onClick ? "pointer" : "default",
|
|
@@ -3089,30 +3200,30 @@ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, them
|
|
|
3089
3200
|
} },
|
|
3090
3201
|
React.createElement("div", { style: { flex: 1 } },
|
|
3091
3202
|
React.createElement("p", { style: {
|
|
3092
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3203
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3093
3204
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
|
|
3094
|
-
margin: "0 0
|
|
3205
|
+
margin: "0 0 6px 0",
|
|
3095
3206
|
} }, label),
|
|
3096
3207
|
React.createElement("div", { style: {
|
|
3097
3208
|
display: "flex",
|
|
3098
3209
|
alignItems: "baseline",
|
|
3099
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3210
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
|
|
3100
3211
|
} },
|
|
3101
3212
|
React.createElement("p", { style: {
|
|
3102
|
-
fontSize: "
|
|
3213
|
+
fontSize: "18px",
|
|
3103
3214
|
fontWeight: "bold",
|
|
3104
3215
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3105
3216
|
margin: 0,
|
|
3106
3217
|
} }, value),
|
|
3107
3218
|
unit && (React.createElement("p", { style: {
|
|
3108
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3219
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3109
3220
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
|
|
3110
3221
|
margin: 0,
|
|
3111
3222
|
} }, unit))),
|
|
3112
3223
|
trend && trendValue !== undefined && (React.createElement("div", { style: {
|
|
3113
|
-
fontSize: "
|
|
3224
|
+
fontSize: "10px",
|
|
3114
3225
|
color: getTrendColor(),
|
|
3115
|
-
marginTop: "
|
|
3226
|
+
marginTop: "4px",
|
|
3116
3227
|
} },
|
|
3117
3228
|
getTrendIcon(),
|
|
3118
3229
|
" ",
|
|
@@ -3120,7 +3231,7 @@ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, them
|
|
|
3120
3231
|
"%"))),
|
|
3121
3232
|
icon && (React.createElement("div", { style: {
|
|
3122
3233
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#999",
|
|
3123
|
-
fontSize: "
|
|
3234
|
+
fontSize: "18px",
|
|
3124
3235
|
} }, icon)))));
|
|
3125
3236
|
};
|
|
3126
3237
|
|
|
@@ -3180,9 +3291,10 @@ const TrendChart = ({ data, title, height = 200, theme, showArea = true, }) => {
|
|
|
3180
3291
|
* Executive Dashboard Report
|
|
3181
3292
|
* High-level directive execution metrics, trends, and cost impact
|
|
3182
3293
|
*/
|
|
3183
|
-
const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
3294
|
+
const ExecutiveDashboard = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3184
3295
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
3185
|
-
const { api } = useReactBridgeContext();
|
|
3296
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
3297
|
+
const theme = themeProp || contextTheme;
|
|
3186
3298
|
const dateRange = useDateRange(defaultDateRange);
|
|
3187
3299
|
const { data, loading, error } = useReportData(() => api.getExecutiveDashboard({
|
|
3188
3300
|
startDate: dateRange.startDate,
|
|
@@ -3195,46 +3307,47 @@ const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
3195
3307
|
return (React.createElement(ReportLayout, { title: "Executive Dashboard", description: "High-level directive execution metrics and trends", selectedDateRange: dateRange.selectedOption, onDateRangeChange: dateRange.setSelectedOption, loading: loading, error: error, theme: theme },
|
|
3196
3308
|
React.createElement("div", { style: {
|
|
3197
3309
|
display: "grid",
|
|
3198
|
-
gridTemplateColumns: "repeat(auto-fit, minmax(
|
|
3199
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3310
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))",
|
|
3311
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3200
3312
|
} },
|
|
3201
3313
|
React.createElement(MetricCard, { label: "Total Directives", value: (_b = data === null || data === void 0 ? void 0 : data.totalDirectives) !== null && _b !== void 0 ? _b : 0, theme: theme }),
|
|
3202
3314
|
React.createElement(MetricCard, { label: "Success Rate", value: (_d = (_c = data === null || data === void 0 ? void 0 : data.successRate) === null || _c === void 0 ? void 0 : _c.toFixed(2)) !== null && _d !== void 0 ? _d : 0, unit: "%", trend: ((_e = data === null || data === void 0 ? void 0 : data.successRate) !== null && _e !== void 0 ? _e : 0 > 80) ? "up" : "neutral", theme: theme }),
|
|
3203
3315
|
React.createElement(MetricCard, { label: "Auto-Executed", value: (_f = data === null || data === void 0 ? void 0 : data.autoExecutedDirectives) !== null && _f !== void 0 ? _f : 0, theme: theme }),
|
|
3204
3316
|
React.createElement(MetricCard, { label: "Cost Impact", value: (_h = (_g = data === null || data === void 0 ? void 0 : data.totalCostImpact) === null || _g === void 0 ? void 0 : _g.toFixed(2)) !== null && _h !== void 0 ? _h : 0, unit: "$", theme: theme })),
|
|
3205
3317
|
trendData.length > 0 && (React.createElement("div", { style: {
|
|
3206
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3318
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3207
3319
|
border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
|
|
3208
|
-
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "
|
|
3320
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3209
3321
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
|
|
3210
3322
|
} },
|
|
3211
3323
|
React.createElement(TrendChart, { data: trendData, title: "Success Rate Trend", theme: theme, showArea: true }))),
|
|
3212
3324
|
React.createElement("div", { style: {
|
|
3213
3325
|
display: "grid",
|
|
3214
|
-
gridTemplateColumns: "repeat(auto-fit, minmax(
|
|
3215
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3326
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
|
|
3327
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3216
3328
|
} },
|
|
3217
3329
|
React.createElement("div", { style: {
|
|
3218
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3330
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3219
3331
|
border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
|
|
3220
|
-
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "
|
|
3332
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3221
3333
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
|
|
3222
3334
|
} },
|
|
3223
3335
|
React.createElement("h3", { style: {
|
|
3224
|
-
margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3225
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3336
|
+
margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px"} 0`,
|
|
3337
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "13px",
|
|
3226
3338
|
fontWeight: "600",
|
|
3227
3339
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3228
3340
|
} }, "Execution Summary"),
|
|
3229
3341
|
React.createElement("div", { style: {
|
|
3230
3342
|
display: "flex",
|
|
3231
3343
|
flexDirection: "column",
|
|
3232
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3344
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
|
|
3233
3345
|
} },
|
|
3234
3346
|
React.createElement("div", { style: {
|
|
3235
3347
|
display: "flex",
|
|
3236
3348
|
justifyContent: "space-between",
|
|
3237
|
-
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "
|
|
3349
|
+
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "3px"} 0`,
|
|
3350
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3238
3351
|
} },
|
|
3239
3352
|
React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Successful:"),
|
|
3240
3353
|
React.createElement("span", { style: {
|
|
@@ -3244,7 +3357,8 @@ const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
3244
3357
|
React.createElement("div", { style: {
|
|
3245
3358
|
display: "flex",
|
|
3246
3359
|
justifyContent: "space-between",
|
|
3247
|
-
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "
|
|
3360
|
+
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "3px"} 0`,
|
|
3361
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3248
3362
|
} },
|
|
3249
3363
|
React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Failed:"),
|
|
3250
3364
|
React.createElement("span", { style: {
|
|
@@ -3254,7 +3368,8 @@ const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
3254
3368
|
React.createElement("div", { style: {
|
|
3255
3369
|
display: "flex",
|
|
3256
3370
|
justifyContent: "space-between",
|
|
3257
|
-
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "
|
|
3371
|
+
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "3px"} 0`,
|
|
3372
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3258
3373
|
} },
|
|
3259
3374
|
React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Avg Cost:"),
|
|
3260
3375
|
React.createElement("span", { style: {
|
|
@@ -3493,9 +3608,10 @@ DataTable.displayName = "DataTable";
|
|
|
3493
3608
|
* Supply Chain Risk Report
|
|
3494
3609
|
* Supply chain risks including inventory, supplier, and cost analysis
|
|
3495
3610
|
*/
|
|
3496
|
-
const SupplyChainRisk = ({ theme, defaultDateRange = "past-month", }) => {
|
|
3611
|
+
const SupplyChainRisk = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3497
3612
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
|
|
3498
|
-
const { api } = useReactBridgeContext();
|
|
3613
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
3614
|
+
const theme = themeProp || contextTheme;
|
|
3499
3615
|
const dateRange = useDateRange(defaultDateRange);
|
|
3500
3616
|
const { data, loading, error } = useReportData(() => api.getSupplyChainRisk({
|
|
3501
3617
|
startDate: dateRange.startDate,
|
|
@@ -3754,9 +3870,10 @@ const StatusBadge = ({ status, label, theme, }) => {
|
|
|
3754
3870
|
* Execution Audit Trail Report
|
|
3755
3871
|
* Complete execution history and audit information
|
|
3756
3872
|
*/
|
|
3757
|
-
const ExecutionAuditTrail = ({ theme, defaultDateRange = "past-month", }) => {
|
|
3873
|
+
const ExecutionAuditTrail = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3758
3874
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
3759
|
-
const { api } = useReactBridgeContext();
|
|
3875
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
3876
|
+
const theme = themeProp || contextTheme;
|
|
3760
3877
|
const dateRange = useDateRange(defaultDateRange);
|
|
3761
3878
|
const [directiveTypeFilter, setDirectiveTypeFilter] = React.useState("");
|
|
3762
3879
|
const { data, loading, error } = useReportData(() => api.getExecutionAuditTrail({
|
|
@@ -3951,9 +4068,10 @@ const HealthGauge = ({ score, label, size = "medium", theme, }) => {
|
|
|
3951
4068
|
* Portfolio Health Report
|
|
3952
4069
|
* Aggregated metric health across the entire portfolio
|
|
3953
4070
|
*/
|
|
3954
|
-
const PortfolioHealth = ({ theme, defaultDateRange = "past-month", }) => {
|
|
4071
|
+
const PortfolioHealth = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3955
4072
|
var _a, _b, _c, _d;
|
|
3956
|
-
const { api } = useReactBridgeContext();
|
|
4073
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
4074
|
+
const theme = themeProp || contextTheme;
|
|
3957
4075
|
const dateRange = useDateRange(defaultDateRange);
|
|
3958
4076
|
const { data, loading, error } = useReportData(() => api.getPortfolioHealth({
|
|
3959
4077
|
startDate: dateRange.startDate,
|
|
@@ -4105,9 +4223,10 @@ const PortfolioHealth = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
4105
4223
|
* Data Quality & Automation Report
|
|
4106
4224
|
* Data gaps, automation opportunities, and actionable recommendations
|
|
4107
4225
|
*/
|
|
4108
|
-
const DataQualityAutomation = ({ theme, defaultDateRange = "past-month", }) => {
|
|
4226
|
+
const DataQualityAutomation = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
4109
4227
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
4110
|
-
const { api } = useReactBridgeContext();
|
|
4228
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
4229
|
+
const theme = themeProp || contextTheme;
|
|
4111
4230
|
const dateRange = useDateRange(defaultDateRange);
|
|
4112
4231
|
const { data, loading, error } = useReportData(() => api.getDataQualityAutomation({
|
|
4113
4232
|
startDate: dateRange.startDate,
|