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.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,31 @@ 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
|
-
|
|
2929
|
-
|
|
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} ${theme === null || theme === void 0 ? void 0 : theme.spacing.sm}`,
|
|
3031
|
+
borderRadius: theme === null || theme === void 0 ? void 0 : theme.borderRadius,
|
|
3032
|
+
border: `1px solid ${theme === null || theme === void 0 ? void 0 : theme.colors.border}`,
|
|
3033
|
+
background: theme === null || theme === void 0 ? void 0 : theme.colors.surface,
|
|
3034
|
+
color: theme === null || theme === void 0 ? void 0 : theme.colors.text,
|
|
3035
|
+
fontSize: theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm,
|
|
3036
|
+
fontWeight: 500,
|
|
3037
|
+
outline: "none",
|
|
3038
|
+
minWidth: 120,
|
|
3039
|
+
marginLeft: theme === null || theme === void 0 ? void 0 : theme.spacing.sm,
|
|
3040
|
+
cursor: "pointer",
|
|
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)))));
|
|
2939
3050
|
};
|
|
2940
3051
|
|
|
2941
3052
|
/**
|
|
@@ -2997,35 +3108,37 @@ const LoadingState = ({ theme, variant = "minimal", }) => {
|
|
|
2997
3108
|
* ReportLayout Component
|
|
2998
3109
|
* Wrapper for report pages with header and date range selector
|
|
2999
3110
|
*/
|
|
3000
|
-
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;
|
|
3001
3114
|
return (React.createElement("div", { style: {
|
|
3002
3115
|
display: "flex",
|
|
3003
3116
|
flexDirection: "column",
|
|
3004
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3117
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.md) || "12px",
|
|
3005
3118
|
} },
|
|
3006
3119
|
React.createElement("div", { style: {
|
|
3007
3120
|
display: "flex",
|
|
3008
3121
|
alignItems: "flex-start",
|
|
3009
3122
|
justifyContent: "space-between",
|
|
3010
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3123
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "12px",
|
|
3011
3124
|
flexWrap: "wrap",
|
|
3012
3125
|
} },
|
|
3013
3126
|
React.createElement("div", { style: { flex: 1, minWidth: "200px" } },
|
|
3014
3127
|
React.createElement("h1", { style: {
|
|
3015
3128
|
margin: 0,
|
|
3016
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3129
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.lg) || "20px",
|
|
3017
3130
|
fontWeight: "700",
|
|
3018
3131
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3019
3132
|
} }, title),
|
|
3020
3133
|
description && (React.createElement("p", { style: {
|
|
3021
3134
|
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) || "
|
|
3135
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "12px",
|
|
3023
3136
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
|
|
3024
3137
|
} }, description))),
|
|
3025
3138
|
React.createElement(DateRangeSelector, { selectedOption: selectedDateRange, onSelect: onDateRangeChange, theme: theme })),
|
|
3026
3139
|
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) || "
|
|
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",
|
|
3029
3142
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.error)
|
|
3030
3143
|
? `${theme.colors.error}15`
|
|
3031
3144
|
: "#FEE2E2",
|
|
@@ -3033,7 +3146,7 @@ const ReportLayout = ({ title, description, selectedDateRange, onDateRangeChange
|
|
|
3033
3146
|
} },
|
|
3034
3147
|
React.createElement("p", { style: {
|
|
3035
3148
|
margin: 0,
|
|
3036
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "
|
|
3149
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.sm) || "12px",
|
|
3037
3150
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.error) || "#f44336",
|
|
3038
3151
|
fontWeight: "500",
|
|
3039
3152
|
} },
|
|
@@ -3063,8 +3176,8 @@ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, them
|
|
|
3063
3176
|
return "→";
|
|
3064
3177
|
};
|
|
3065
3178
|
const containerStyles = {
|
|
3066
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3067
|
-
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",
|
|
3068
3181
|
border: `1px solid ${(theme === null || theme === void 0 ? void 0 : theme.colors.border) || "#e0e0e0"}`,
|
|
3069
3182
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
|
|
3070
3183
|
cursor: onClick ? "pointer" : "default",
|
|
@@ -3087,30 +3200,30 @@ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, them
|
|
|
3087
3200
|
} },
|
|
3088
3201
|
React.createElement("div", { style: { flex: 1 } },
|
|
3089
3202
|
React.createElement("p", { style: {
|
|
3090
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3203
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3091
3204
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
|
|
3092
|
-
margin: "0 0
|
|
3205
|
+
margin: "0 0 6px 0",
|
|
3093
3206
|
} }, label),
|
|
3094
3207
|
React.createElement("div", { style: {
|
|
3095
3208
|
display: "flex",
|
|
3096
3209
|
alignItems: "baseline",
|
|
3097
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3210
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
|
|
3098
3211
|
} },
|
|
3099
3212
|
React.createElement("p", { style: {
|
|
3100
|
-
fontSize: "
|
|
3213
|
+
fontSize: "18px",
|
|
3101
3214
|
fontWeight: "bold",
|
|
3102
3215
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3103
3216
|
margin: 0,
|
|
3104
3217
|
} }, value),
|
|
3105
3218
|
unit && (React.createElement("p", { style: {
|
|
3106
|
-
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.
|
|
3219
|
+
fontSize: (theme === null || theme === void 0 ? void 0 : theme.fontSizes.xs) || "11px",
|
|
3107
3220
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666",
|
|
3108
3221
|
margin: 0,
|
|
3109
3222
|
} }, unit))),
|
|
3110
3223
|
trend && trendValue !== undefined && (React.createElement("div", { style: {
|
|
3111
|
-
fontSize: "
|
|
3224
|
+
fontSize: "10px",
|
|
3112
3225
|
color: getTrendColor(),
|
|
3113
|
-
marginTop: "
|
|
3226
|
+
marginTop: "4px",
|
|
3114
3227
|
} },
|
|
3115
3228
|
getTrendIcon(),
|
|
3116
3229
|
" ",
|
|
@@ -3118,7 +3231,7 @@ const MetricCard = ({ label, value, unit, trend, trendValue, icon, onClick, them
|
|
|
3118
3231
|
"%"))),
|
|
3119
3232
|
icon && (React.createElement("div", { style: {
|
|
3120
3233
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#999",
|
|
3121
|
-
fontSize: "
|
|
3234
|
+
fontSize: "18px",
|
|
3122
3235
|
} }, icon)))));
|
|
3123
3236
|
};
|
|
3124
3237
|
|
|
@@ -3178,9 +3291,10 @@ const TrendChart = ({ data, title, height = 200, theme, showArea = true, }) => {
|
|
|
3178
3291
|
* Executive Dashboard Report
|
|
3179
3292
|
* High-level directive execution metrics, trends, and cost impact
|
|
3180
3293
|
*/
|
|
3181
|
-
const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
3294
|
+
const ExecutiveDashboard = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3182
3295
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
3183
|
-
const { api } = useReactBridgeContext();
|
|
3296
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
3297
|
+
const theme = themeProp || contextTheme;
|
|
3184
3298
|
const dateRange = useDateRange(defaultDateRange);
|
|
3185
3299
|
const { data, loading, error } = useReportData(() => api.getExecutiveDashboard({
|
|
3186
3300
|
startDate: dateRange.startDate,
|
|
@@ -3193,46 +3307,47 @@ const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
3193
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 },
|
|
3194
3308
|
React.createElement("div", { style: {
|
|
3195
3309
|
display: "grid",
|
|
3196
|
-
gridTemplateColumns: "repeat(auto-fit, minmax(
|
|
3197
|
-
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",
|
|
3198
3312
|
} },
|
|
3199
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 }),
|
|
3200
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 }),
|
|
3201
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 }),
|
|
3202
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 })),
|
|
3203
3317
|
trendData.length > 0 && (React.createElement("div", { style: {
|
|
3204
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3318
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3205
3319
|
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) || "
|
|
3320
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3207
3321
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
|
|
3208
3322
|
} },
|
|
3209
3323
|
React.createElement(TrendChart, { data: trendData, title: "Success Rate Trend", theme: theme, showArea: true }))),
|
|
3210
3324
|
React.createElement("div", { style: {
|
|
3211
3325
|
display: "grid",
|
|
3212
|
-
gridTemplateColumns: "repeat(auto-fit, minmax(
|
|
3213
|
-
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",
|
|
3214
3328
|
} },
|
|
3215
3329
|
React.createElement("div", { style: {
|
|
3216
|
-
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3330
|
+
padding: (theme === null || theme === void 0 ? void 0 : theme.spacing.sm) || "10px",
|
|
3217
3331
|
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) || "
|
|
3332
|
+
borderRadius: (theme === null || theme === void 0 ? void 0 : theme.borderRadius) || "6px",
|
|
3219
3333
|
backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.colors.surface) || "#f5f5f5",
|
|
3220
3334
|
} },
|
|
3221
3335
|
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.
|
|
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",
|
|
3224
3338
|
fontWeight: "600",
|
|
3225
3339
|
color: (theme === null || theme === void 0 ? void 0 : theme.colors.text) || "#000",
|
|
3226
3340
|
} }, "Execution Summary"),
|
|
3227
3341
|
React.createElement("div", { style: {
|
|
3228
3342
|
display: "flex",
|
|
3229
3343
|
flexDirection: "column",
|
|
3230
|
-
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.
|
|
3344
|
+
gap: (theme === null || theme === void 0 ? void 0 : theme.spacing.xs) || "4px",
|
|
3231
3345
|
} },
|
|
3232
3346
|
React.createElement("div", { style: {
|
|
3233
3347
|
display: "flex",
|
|
3234
3348
|
justifyContent: "space-between",
|
|
3235
|
-
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",
|
|
3236
3351
|
} },
|
|
3237
3352
|
React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Successful:"),
|
|
3238
3353
|
React.createElement("span", { style: {
|
|
@@ -3242,7 +3357,8 @@ const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
3242
3357
|
React.createElement("div", { style: {
|
|
3243
3358
|
display: "flex",
|
|
3244
3359
|
justifyContent: "space-between",
|
|
3245
|
-
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",
|
|
3246
3362
|
} },
|
|
3247
3363
|
React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Failed:"),
|
|
3248
3364
|
React.createElement("span", { style: {
|
|
@@ -3252,7 +3368,8 @@ const ExecutiveDashboard = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
3252
3368
|
React.createElement("div", { style: {
|
|
3253
3369
|
display: "flex",
|
|
3254
3370
|
justifyContent: "space-between",
|
|
3255
|
-
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",
|
|
3256
3373
|
} },
|
|
3257
3374
|
React.createElement("span", { style: { color: (theme === null || theme === void 0 ? void 0 : theme.colors.textSecondary) || "#666" } }, "Avg Cost:"),
|
|
3258
3375
|
React.createElement("span", { style: {
|
|
@@ -3491,9 +3608,10 @@ DataTable.displayName = "DataTable";
|
|
|
3491
3608
|
* Supply Chain Risk Report
|
|
3492
3609
|
* Supply chain risks including inventory, supplier, and cost analysis
|
|
3493
3610
|
*/
|
|
3494
|
-
const SupplyChainRisk = ({ theme, defaultDateRange = "past-month", }) => {
|
|
3611
|
+
const SupplyChainRisk = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3495
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;
|
|
3496
|
-
const { api } = useReactBridgeContext();
|
|
3613
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
3614
|
+
const theme = themeProp || contextTheme;
|
|
3497
3615
|
const dateRange = useDateRange(defaultDateRange);
|
|
3498
3616
|
const { data, loading, error } = useReportData(() => api.getSupplyChainRisk({
|
|
3499
3617
|
startDate: dateRange.startDate,
|
|
@@ -3752,9 +3870,10 @@ const StatusBadge = ({ status, label, theme, }) => {
|
|
|
3752
3870
|
* Execution Audit Trail Report
|
|
3753
3871
|
* Complete execution history and audit information
|
|
3754
3872
|
*/
|
|
3755
|
-
const ExecutionAuditTrail = ({ theme, defaultDateRange = "past-month", }) => {
|
|
3873
|
+
const ExecutionAuditTrail = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3756
3874
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
3757
|
-
const { api } = useReactBridgeContext();
|
|
3875
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
3876
|
+
const theme = themeProp || contextTheme;
|
|
3758
3877
|
const dateRange = useDateRange(defaultDateRange);
|
|
3759
3878
|
const [directiveTypeFilter, setDirectiveTypeFilter] = useState("");
|
|
3760
3879
|
const { data, loading, error } = useReportData(() => api.getExecutionAuditTrail({
|
|
@@ -3949,9 +4068,10 @@ const HealthGauge = ({ score, label, size = "medium", theme, }) => {
|
|
|
3949
4068
|
* Portfolio Health Report
|
|
3950
4069
|
* Aggregated metric health across the entire portfolio
|
|
3951
4070
|
*/
|
|
3952
|
-
const PortfolioHealth = ({ theme, defaultDateRange = "past-month", }) => {
|
|
4071
|
+
const PortfolioHealth = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
3953
4072
|
var _a, _b, _c, _d;
|
|
3954
|
-
const { api } = useReactBridgeContext();
|
|
4073
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
4074
|
+
const theme = themeProp || contextTheme;
|
|
3955
4075
|
const dateRange = useDateRange(defaultDateRange);
|
|
3956
4076
|
const { data, loading, error } = useReportData(() => api.getPortfolioHealth({
|
|
3957
4077
|
startDate: dateRange.startDate,
|
|
@@ -4103,9 +4223,10 @@ const PortfolioHealth = ({ theme, defaultDateRange = "past-month", }) => {
|
|
|
4103
4223
|
* Data Quality & Automation Report
|
|
4104
4224
|
* Data gaps, automation opportunities, and actionable recommendations
|
|
4105
4225
|
*/
|
|
4106
|
-
const DataQualityAutomation = ({ theme, defaultDateRange = "past-month", }) => {
|
|
4226
|
+
const DataQualityAutomation = ({ theme: themeProp, defaultDateRange = "past-month", }) => {
|
|
4107
4227
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
4108
|
-
const { api } = useReactBridgeContext();
|
|
4228
|
+
const { api, theme: contextTheme } = useReactBridgeContext();
|
|
4229
|
+
const theme = themeProp || contextTheme;
|
|
4109
4230
|
const dateRange = useDateRange(defaultDateRange);
|
|
4110
4231
|
const { data, loading, error } = useReportData(() => api.getDataQualityAutomation({
|
|
4111
4232
|
startDate: dateRange.startDate,
|