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