reactbridge-sdk 0.2.7 → 0.2.9
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 +210 -89
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +210 -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,31 @@ 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
|
-
|
|
2931
|
-
|
|
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} ${theme === null || theme === void 0 ? void 0 : theme.spacing.sm}`,
|
|
3033
|
+
borderRadius: theme === null || theme === void 0 ? void 0 : theme.borderRadius,
|
|
3034
|
+
border: `1px solid ${theme === null || theme === void 0 ? void 0 : theme.colors.border}`,
|
|
3035
|
+
background: theme === null || theme === void 0 ? void 0 : theme.colors.surface,
|
|
3036
|
+
color: theme === null || theme === void 0 ? void 0 : theme.colors.text,
|
|
3037
|
+
fontSize: theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm,
|
|
3038
|
+
fontWeight: 500,
|
|
3039
|
+
outline: "none",
|
|
3040
|
+
minWidth: 120,
|
|
3041
|
+
marginLeft: theme === null || theme === void 0 ? void 0 : theme.spacing.sm,
|
|
3042
|
+
cursor: "pointer",
|
|
3043
|
+
}, onFocus: (e) => {
|
|
3044
|
+
e.currentTarget.style.borderColor =
|
|
3045
|
+
(theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2";
|
|
3046
|
+
e.currentTarget.style.boxShadow = `0 0 0 2px ${((theme === null || theme === void 0 ? void 0 : theme.colors.primary) || "#1976d2") + "20"}`;
|
|
3047
|
+
}, onBlur: (e) => {
|
|
3048
|
+
e.currentTarget.style.borderColor =
|
|
3049
|
+
(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#d0d0d0";
|
|
3050
|
+
e.currentTarget.style.boxShadow = "none";
|
|
3051
|
+
} }, options.map((option) => (React.createElement("option", { key: option.value, value: option.value }, option.label)))));
|
|
2941
3052
|
};
|
|
2942
3053
|
|
|
2943
3054
|
/**
|
|
@@ -2999,35 +3110,37 @@ const LoadingState = ({ theme, variant = "minimal", }) => {
|
|
|
2999
3110
|
* ReportLayout Component
|
|
3000
3111
|
* Wrapper for report pages with header and date range selector
|
|
3001
3112
|
*/
|
|
3002
|
-
const ReportLayout = ({ title, description, selectedDateRange, onDateRangeChange, loading, error, children, theme, }) => {
|
|
3113
|
+
const ReportLayout = ({ title, description, selectedDateRange, onDateRangeChange, loading, error, children, theme: themeProp, }) => {
|
|
3114
|
+
const { theme: contextTheme } = useReactBridgeContext();
|
|
3115
|
+
const theme = themeProp || contextTheme;
|
|
3003
3116
|
return (React.createElement("div", { style: {
|
|
3004
3117
|
display: "flex",
|
|
3005
3118
|
flexDirection: "column",
|
|
3006
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3119
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "12px",
|
|
3007
3120
|
} },
|
|
3008
3121
|
React.createElement("div", { style: {
|
|
3009
3122
|
display: "flex",
|
|
3010
3123
|
alignItems: "flex-start",
|
|
3011
3124
|
justifyContent: "space-between",
|
|
3012
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3125
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "12px",
|
|
3013
3126
|
flexWrap: "wrap",
|
|
3014
3127
|
} },
|
|
3015
3128
|
React.createElement("div", { style: { flex: 1, minWidth: "200px" } },
|
|
3016
3129
|
React.createElement("h1", { style: {
|
|
3017
3130
|
margin: 0,
|
|
3018
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3131
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.lg) || "20px",
|
|
3019
3132
|
fontWeight: "700",
|
|
3020
3133
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3021
3134
|
} }, title),
|
|
3022
3135
|
description && (React.createElement("p", { style: {
|
|
3023
3136
|
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) || "
|
|
3137
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "12px",
|
|
3025
3138
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
|
|
3026
3139
|
} }, description))),
|
|
3027
3140
|
React.createElement(DateRangeSelector, { selectedOption: selectedDateRange, onSelect: onDateRangeChange, theme: theme })),
|
|
3028
3141
|
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) || "
|
|
3142
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "12px",
|
|
3143
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3031
3144
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.error)
|
|
3032
3145
|
? `${theme.colors.error}15`
|
|
3033
3146
|
: "#FEE2E2",
|
|
@@ -3035,7 +3148,7 @@ const ReportLayout = ({ title, description, selectedDateRange, onDateRangeChange
|
|
|
3035
3148
|
} },
|
|
3036
3149
|
React.createElement("p", { style: {
|
|
3037
3150
|
margin: 0,
|
|
3038
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "
|
|
3151
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "12px",
|
|
3039
3152
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#f44336",
|
|
3040
3153
|
fontWeight: "500",
|
|
3041
3154
|
} },
|
|
@@ -3065,8 +3178,8 @@ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, them
|
|
|
3065
3178
|
return "→";
|
|
3066
3179
|
};
|
|
3067
3180
|
const containerStyles = {
|
|
3068
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3069
|
-
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "
|
|
3181
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3182
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3070
3183
|
border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
|
|
3071
3184
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
|
|
3072
3185
|
cursor: onClick ? "pointer" : "default",
|
|
@@ -3089,30 +3202,30 @@ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, them
|
|
|
3089
3202
|
} },
|
|
3090
3203
|
React.createElement("div", { style: { flex: 1 } },
|
|
3091
3204
|
React.createElement("p", { style: {
|
|
3092
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3205
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3093
3206
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
|
|
3094
|
-
margin: "0 0
|
|
3207
|
+
margin: "0 0 6px 0",
|
|
3095
3208
|
} }, label),
|
|
3096
3209
|
React.createElement("div", { style: {
|
|
3097
3210
|
display: "flex",
|
|
3098
3211
|
alignItems: "baseline",
|
|
3099
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3212
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
|
|
3100
3213
|
} },
|
|
3101
3214
|
React.createElement("p", { style: {
|
|
3102
|
-
fontSize: "
|
|
3215
|
+
fontSize: "18px",
|
|
3103
3216
|
fontWeight: "bold",
|
|
3104
3217
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3105
3218
|
margin: 0,
|
|
3106
3219
|
} }, value),
|
|
3107
3220
|
unit && (React.createElement("p", { style: {
|
|
3108
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3221
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3109
3222
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
|
|
3110
3223
|
margin: 0,
|
|
3111
3224
|
} }, unit))),
|
|
3112
3225
|
trend && trendValue !== undefined && (React.createElement("div", { style: {
|
|
3113
|
-
fontSize: "
|
|
3226
|
+
fontSize: "10px",
|
|
3114
3227
|
color: getTrendColor(),
|
|
3115
|
-
marginTop: "
|
|
3228
|
+
marginTop: "4px",
|
|
3116
3229
|
} },
|
|
3117
3230
|
getTrendIcon(),
|
|
3118
3231
|
" ",
|
|
@@ -3120,7 +3233,7 @@ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, them
|
|
|
3120
3233
|
"%"))),
|
|
3121
3234
|
icon && (React.createElement("div", { style: {
|
|
3122
3235
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#999",
|
|
3123
|
-
fontSize: "
|
|
3236
|
+
fontSize: "18px",
|
|
3124
3237
|
} }, icon)))));
|
|
3125
3238
|
};
|
|
3126
3239
|
|
|
@@ -3180,9 +3293,10 @@ const TrendChart = ({ data, title, height = 200, theme, showArea = true, }) => {
|
|
|
3180
3293
|
* Executive Dashboard Report
|
|
3181
3294
|
* High-level directive execution metrics, trends, and cost impact
|
|
3182
3295
|
*/
|
|
3183
|
-
const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
3296
|
+
const ExecutiveDashboard = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3184
3297
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
3185
|
-
const { api } = useReactBridgeContext();
|
|
3298
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
3299
|
+
const theme = themeProp || contextTheme;
|
|
3186
3300
|
const dateRange = useDateRange(defaultDateRange);
|
|
3187
3301
|
const { data, loading, error } = useReportData(() => api.getExecutiveDashboard({
|
|
3188
3302
|
startDate: dateRange.startDate,
|
|
@@ -3195,46 +3309,47 @@ const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
3195
3309
|
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
3310
|
React.createElement("div", { style: {
|
|
3197
3311
|
display: "grid",
|
|
3198
|
-
gridTemplateColumns: "repeat(auto-fit, minmax(
|
|
3199
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3312
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))",
|
|
3313
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3200
3314
|
} },
|
|
3201
3315
|
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
3316
|
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
3317
|
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
3318
|
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
3319
|
trendData.length > 0 && (React.createElement("div", { style: {
|
|
3206
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3320
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3207
3321
|
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) || "
|
|
3322
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3209
3323
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
|
|
3210
3324
|
} },
|
|
3211
3325
|
React.createElement(TrendChart, { data: trendData, title: "Success Rate Trend", theme: theme, showArea: true }))),
|
|
3212
3326
|
React.createElement("div", { style: {
|
|
3213
3327
|
display: "grid",
|
|
3214
|
-
gridTemplateColumns: "repeat(auto-fit, minmax(
|
|
3215
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3328
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(220px, 1fr))",
|
|
3329
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3216
3330
|
} },
|
|
3217
3331
|
React.createElement("div", { style: {
|
|
3218
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3332
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3219
3333
|
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) || "
|
|
3334
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3221
3335
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
|
|
3222
3336
|
} },
|
|
3223
3337
|
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.
|
|
3338
|
+
margin: `0 0 ${(theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "8px"} 0`,
|
|
3339
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "13px",
|
|
3226
3340
|
fontWeight: "600",
|
|
3227
3341
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3228
3342
|
} }, "Execution Summary"),
|
|
3229
3343
|
React.createElement("div", { style: {
|
|
3230
3344
|
display: "flex",
|
|
3231
3345
|
flexDirection: "column",
|
|
3232
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3346
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
|
|
3233
3347
|
} },
|
|
3234
3348
|
React.createElement("div", { style: {
|
|
3235
3349
|
display: "flex",
|
|
3236
3350
|
justifyContent: "space-between",
|
|
3237
|
-
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "
|
|
3351
|
+
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "3px"} 0`,
|
|
3352
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3238
3353
|
} },
|
|
3239
3354
|
React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Successful:"),
|
|
3240
3355
|
React.createElement("span", { style: {
|
|
@@ -3244,7 +3359,8 @@ const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
3244
3359
|
React.createElement("div", { style: {
|
|
3245
3360
|
display: "flex",
|
|
3246
3361
|
justifyContent: "space-between",
|
|
3247
|
-
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "
|
|
3362
|
+
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "3px"} 0`,
|
|
3363
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3248
3364
|
} },
|
|
3249
3365
|
React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Failed:"),
|
|
3250
3366
|
React.createElement("span", { style: {
|
|
@@ -3254,7 +3370,8 @@ const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
3254
3370
|
React.createElement("div", { style: {
|
|
3255
3371
|
display: "flex",
|
|
3256
3372
|
justifyContent: "space-between",
|
|
3257
|
-
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "
|
|
3373
|
+
padding: `${(theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "3px"} 0`,
|
|
3374
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3258
3375
|
} },
|
|
3259
3376
|
React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Avg Cost:"),
|
|
3260
3377
|
React.createElement("span", { style: {
|
|
@@ -3493,9 +3610,10 @@ DataTable.displayName = "DataTable";
|
|
|
3493
3610
|
* Supply Chain Risk Report
|
|
3494
3611
|
* Supply chain risks including inventory, supplier, and cost analysis
|
|
3495
3612
|
*/
|
|
3496
|
-
const SupplyChainRisk = ({ theme, defaultDateRange = "past-month", }) => {
|
|
3613
|
+
const SupplyChainRisk = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3497
3614
|
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();
|
|
3615
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
3616
|
+
const theme = themeProp || contextTheme;
|
|
3499
3617
|
const dateRange = useDateRange(defaultDateRange);
|
|
3500
3618
|
const { data, loading, error } = useReportData(() => api.getSupplyChainRisk({
|
|
3501
3619
|
startDate: dateRange.startDate,
|
|
@@ -3754,9 +3872,10 @@ const StatusBadge = ({ status, label, theme, }) => {
|
|
|
3754
3872
|
* Execution Audit Trail Report
|
|
3755
3873
|
* Complete execution history and audit information
|
|
3756
3874
|
*/
|
|
3757
|
-
const ExecutionAuditTrail = ({ theme, defaultDateRange = "past-month", }) => {
|
|
3875
|
+
const ExecutionAuditTrail = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3758
3876
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
3759
|
-
const { api } = useReactBridgeContext();
|
|
3877
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
3878
|
+
const theme = themeProp || contextTheme;
|
|
3760
3879
|
const dateRange = useDateRange(defaultDateRange);
|
|
3761
3880
|
const [directiveTypeFilter, setDirectiveTypeFilter] = React.useState("");
|
|
3762
3881
|
const { data, loading, error } = useReportData(() => api.getExecutionAuditTrail({
|
|
@@ -3951,9 +4070,10 @@ const HealthGauge = ({ score, label, size = "medium", theme, }) => {
|
|
|
3951
4070
|
* Portfolio Health Report
|
|
3952
4071
|
* Aggregated metric health across the entire portfolio
|
|
3953
4072
|
*/
|
|
3954
|
-
const PortfolioHealth = ({ theme, defaultDateRange = "past-month", }) => {
|
|
4073
|
+
const PortfolioHealth = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3955
4074
|
var _a, _b, _c, _d;
|
|
3956
|
-
const { api } = useReactBridgeContext();
|
|
4075
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
4076
|
+
const theme = themeProp || contextTheme;
|
|
3957
4077
|
const dateRange = useDateRange(defaultDateRange);
|
|
3958
4078
|
const { data, loading, error } = useReportData(() => api.getPortfolioHealth({
|
|
3959
4079
|
startDate: dateRange.startDate,
|
|
@@ -4105,9 +4225,10 @@ const PortfolioHealth = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
4105
4225
|
* Data Quality & Automation Report
|
|
4106
4226
|
* Data gaps, automation opportunities, and actionable recommendations
|
|
4107
4227
|
*/
|
|
4108
|
-
const DataQualityAutomation = ({ theme, defaultDateRange = "past-month", }) => {
|
|
4228
|
+
const DataQualityAutomation = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
4109
4229
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
4110
|
-
const { api } = useReactBridgeContext();
|
|
4230
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
4231
|
+
const theme = themeProp || contextTheme;
|
|
4111
4232
|
const dateRange = useDateRange(defaultDateRange);
|
|
4112
4233
|
const { data, loading, error } = useReportData(() => api.getDataQualityAutomation({
|
|
4113
4234
|
startDate: dateRange.startDate,
|