@wealthx/shadcn 1.5.4 → 1.5.6

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.
@@ -8,46 +8,39 @@ import {
8
8
  } from "@react-awesome-query-builder/ui";
9
9
  import type { AlertQueryField, AlertQueryOperator } from "./types";
10
10
 
11
+ const NUMERIC_OPERATORS_DEFAULT: AlertQueryOperator[] = [
12
+ "equal",
13
+ "less",
14
+ "less_or_equal",
15
+ "greater",
16
+ "greater_or_equal",
17
+ ];
18
+
11
19
  export const ALERT_QUERY_FIELDS: AlertQueryField[] = [
12
20
  {
13
21
  key: "userMetric.max_loan_amount",
14
22
  label: "Borrowing Capacity",
15
23
  type: "number",
16
24
  unit: "dollar",
17
- operators: [
18
- "equal",
19
- "less",
20
- "less_or_equal",
21
- "greater",
22
- "greater_or_equal",
23
- "between",
24
- ],
25
+ operators: NUMERIC_OPERATORS_DEFAULT,
26
+ min: 0,
25
27
  },
26
28
  {
27
29
  key: "userMetric.debt_outstanding",
28
30
  label: "Outstanding Debt",
29
31
  type: "number",
30
32
  unit: "dollar",
31
- operators: [
32
- "equal",
33
- "less",
34
- "less_or_equal",
35
- "greater",
36
- "greater_or_equal",
37
- ],
33
+ operators: NUMERIC_OPERATORS_DEFAULT,
34
+ min: 0,
38
35
  },
39
36
  {
40
37
  key: "userMetric.lvr",
41
38
  label: "Current LVR",
42
39
  type: "number",
43
40
  unit: "percent",
44
- operators: [
45
- "equal",
46
- "less",
47
- "less_or_equal",
48
- "greater",
49
- "greater_or_equal",
50
- ],
41
+ operators: NUMERIC_OPERATORS_DEFAULT,
42
+ min: 0,
43
+ max: 100,
51
44
  },
52
45
  {
53
46
  key: "userMetric.has_met_buying_goal",
@@ -59,79 +52,52 @@ export const ALERT_QUERY_FIELDS: AlertQueryField[] = [
59
52
  label: "Excess Monthly Surplus",
60
53
  type: "number",
61
54
  unit: "dollar",
62
- operators: [
63
- "equal",
64
- "less",
65
- "less_or_equal",
66
- "greater",
67
- "greater_or_equal",
68
- ],
55
+ operators: NUMERIC_OPERATORS_DEFAULT,
56
+ min: 0,
69
57
  },
70
58
  {
71
59
  key: "userMetric.equity",
72
60
  label: "Equity Amount",
73
61
  type: "number",
74
62
  unit: "dollar",
75
- operators: [
76
- "equal",
77
- "less",
78
- "less_or_equal",
79
- "greater",
80
- "greater_or_equal",
81
- ],
63
+ operators: NUMERIC_OPERATORS_DEFAULT,
64
+ min: 0,
82
65
  },
83
66
  {
84
67
  key: "userMetric.max_debt_interest_rate",
85
68
  label: "Max Debt Interest Rate",
86
69
  type: "number",
87
70
  unit: "percent",
88
- operators: [
89
- "equal",
90
- "less",
91
- "less_or_equal",
92
- "greater",
93
- "greater_or_equal",
94
- ],
71
+ operators: NUMERIC_OPERATORS_DEFAULT,
72
+ min: 0,
73
+ max: 100,
95
74
  },
96
75
  {
97
76
  key: "userMetric.min_debt_interest_rate",
98
77
  label: "Min Debt Interest Rate",
99
78
  type: "number",
100
79
  unit: "percent",
101
- operators: [
102
- "equal",
103
- "less",
104
- "less_or_equal",
105
- "greater",
106
- "greater_or_equal",
107
- ],
80
+ operators: NUMERIC_OPERATORS_DEFAULT,
81
+ min: 0,
82
+ max: 100,
108
83
  },
109
84
  ];
110
85
 
111
- export const ALL_NUMERIC_OPERATORS: AlertQueryOperator[] = [
112
- "equal",
113
- "not_equal",
114
- "less",
115
- "less_or_equal",
116
- "greater",
117
- "greater_or_equal",
118
- "between",
119
- ];
86
+ export const ALL_NUMERIC_OPERATORS: AlertQueryOperator[] =
87
+ NUMERIC_OPERATORS_DEFAULT;
120
88
 
121
89
  export const BOOLEAN_OPERATORS: AlertQueryOperator[] = ["equal"];
122
90
 
123
91
  export const OPERATOR_LABELS: Record<AlertQueryOperator, string> = {
124
92
  equal: "=",
125
- not_equal: "≠",
126
93
  less: "<",
127
94
  less_or_equal: "≤",
128
95
  greater: ">",
129
96
  greater_or_equal: "≥",
130
- between: "between",
131
97
  };
132
98
 
133
99
  export const SEVERITY_LABELS = {
134
- INSIGHT: "Insight",
100
+ HEALTHY: "Healthy",
135
101
  WATCH: "Watch",
136
102
  NEED_ACTION: "Need Action",
137
103
  } as const;
@@ -139,43 +105,32 @@ export const SEVERITY_LABELS = {
139
105
  // react-awesome-query-builder config — drives ImmutableTree state.
140
106
  export const QB_CONFIG: Config = {
141
107
  ...BasicConfig,
108
+ settings: {
109
+ ...BasicConfig.settings,
110
+ maxNesting: 3,
111
+ maxNumberOfRules: 5,
112
+ },
142
113
  fields: {
143
114
  "userMetric.max_loan_amount": {
144
115
  label: "Borrowing Capacity",
145
116
  type: "number",
146
- operators: [
147
- "equal",
148
- "less",
149
- "less_or_equal",
150
- "greater",
151
- "greater_or_equal",
152
- "between",
153
- ],
117
+ operators: NUMERIC_OPERATORS_DEFAULT,
154
118
  valueSources: ["value"],
119
+ fieldSettings: { min: 0 },
155
120
  },
156
121
  "userMetric.debt_outstanding": {
157
122
  label: "Outstanding Debt",
158
123
  type: "number",
159
- operators: [
160
- "equal",
161
- "less",
162
- "less_or_equal",
163
- "greater",
164
- "greater_or_equal",
165
- ],
124
+ operators: NUMERIC_OPERATORS_DEFAULT,
166
125
  valueSources: ["value"],
126
+ fieldSettings: { min: 0 },
167
127
  },
168
128
  "userMetric.lvr": {
169
129
  label: "Current LVR",
170
130
  type: "number",
171
- operators: [
172
- "equal",
173
- "less",
174
- "less_or_equal",
175
- "greater",
176
- "greater_or_equal",
177
- ],
131
+ operators: NUMERIC_OPERATORS_DEFAULT,
178
132
  valueSources: ["value"],
133
+ fieldSettings: { min: 0, max: 100 },
179
134
  },
180
135
  "userMetric.has_met_buying_goal": {
181
136
  label: "Has Met Buying Goal",
@@ -186,50 +141,30 @@ export const QB_CONFIG: Config = {
186
141
  "userMetric.excess_monthly_surplus": {
187
142
  label: "Excess Monthly Surplus",
188
143
  type: "number",
189
- operators: [
190
- "equal",
191
- "less",
192
- "less_or_equal",
193
- "greater",
194
- "greater_or_equal",
195
- ],
144
+ operators: NUMERIC_OPERATORS_DEFAULT,
196
145
  valueSources: ["value"],
146
+ fieldSettings: { min: 0 },
197
147
  },
198
148
  "userMetric.equity": {
199
149
  label: "Equity Amount",
200
150
  type: "number",
201
- operators: [
202
- "equal",
203
- "less",
204
- "less_or_equal",
205
- "greater",
206
- "greater_or_equal",
207
- ],
151
+ operators: NUMERIC_OPERATORS_DEFAULT,
208
152
  valueSources: ["value"],
153
+ fieldSettings: { min: 0 },
209
154
  },
210
155
  "userMetric.max_debt_interest_rate": {
211
156
  label: "Max Debt Interest Rate",
212
157
  type: "number",
213
- operators: [
214
- "equal",
215
- "less",
216
- "less_or_equal",
217
- "greater",
218
- "greater_or_equal",
219
- ],
158
+ operators: NUMERIC_OPERATORS_DEFAULT,
220
159
  valueSources: ["value"],
160
+ fieldSettings: { min: 0, max: 100 },
221
161
  },
222
162
  "userMetric.min_debt_interest_rate": {
223
163
  label: "Min Debt Interest Rate",
224
164
  type: "number",
225
- operators: [
226
- "equal",
227
- "less",
228
- "less_or_equal",
229
- "greater",
230
- "greater_or_equal",
231
- ],
165
+ operators: NUMERIC_OPERATORS_DEFAULT,
232
166
  valueSources: ["value"],
167
+ fieldSettings: { min: 0, max: 100 },
233
168
  },
234
169
  },
235
170
  };
@@ -88,6 +88,7 @@ export function ContactAlertDialog({
88
88
  isCompanyAdmin = false,
89
89
  initialShareAcrossCompany = false,
90
90
  onSave,
91
+ onError,
91
92
  isLoading = false,
92
93
  className,
93
94
  }: ContactAlertDialogProps) {
@@ -116,10 +117,17 @@ export function ContactAlertDialog({
116
117
 
117
118
  function handleSave() {
118
119
  if (!canSave) return;
120
+ let filterSegment: ImmutableTree;
121
+ try {
122
+ filterSegment = QbUtils.sanitizeTree(tree, QB_CONFIG).fixedTree;
123
+ } catch (e) {
124
+ onError?.(e instanceof Error ? e : new Error(String(e)));
125
+ return;
126
+ }
119
127
  onSave({
120
128
  name: name.trim(),
121
129
  severity,
122
- filterSegment: QbUtils.sanitizeTree(tree, QB_CONFIG).fixedTree,
130
+ filterSegment,
123
131
  sharingType: shareAcrossCompany
124
132
  ? AlertSharingType.COMPANY
125
133
  : AlertSharingType.PRIVATE,
@@ -151,7 +159,7 @@ export function ContactAlertDialog({
151
159
  }
152
160
  >
153
161
  {(
154
- ["NEED_ACTION", "WATCH", "INSIGHT"] as ContactAlertSeverity[]
162
+ ["NEED_ACTION", "WATCH", "HEALTHY"] as ContactAlertSeverity[]
155
163
  ).map((s) => (
156
164
  <ToggleGroupItem key={s} value={s}>
157
165
  {SEVERITY_LABELS[s]}
@@ -4,16 +4,14 @@ export type AlertQueryCombinator = "AND" | "OR";
4
4
 
5
5
  export type AlertQueryOperator =
6
6
  | "equal"
7
- | "not_equal"
8
7
  | "less"
9
8
  | "less_or_equal"
10
9
  | "greater"
11
- | "greater_or_equal"
12
- | "between";
10
+ | "greater_or_equal";
13
11
 
14
12
  export type AlertQueryFieldType = "number" | "boolean";
15
13
 
16
- export type ContactAlertSeverity = "INSIGHT" | "WATCH" | "NEED_ACTION";
14
+ export type ContactAlertSeverity = "HEALTHY" | "WATCH" | "NEED_ACTION";
17
15
 
18
16
  export enum AlertSharingType {
19
17
  PRIVATE = "PRIVATE",
@@ -28,6 +26,10 @@ export interface AlertQueryField {
28
26
  unit?: "dollar" | "percent";
29
27
  /** Allowed operators (defaults to all numeric operators). */
30
28
  operators?: AlertQueryOperator[];
29
+ /** Lower bound for numeric value (inclusive). Enforced at input time. */
30
+ min?: number;
31
+ /** Upper bound for numeric value (inclusive). Enforced at input time. */
32
+ max?: number;
31
33
  }
32
34
 
33
35
  export interface ContactAlertQueryBuilderProps {
@@ -57,5 +59,7 @@ export interface ContactAlertDialogProps {
57
59
  sharingType: AlertSharingType;
58
60
  }) => void;
59
61
  isLoading?: boolean;
62
+ /** Fired when the underlying QB sanitizeTree throws while saving. */
63
+ onError?: (error: Error) => void;
60
64
  className?: string;
61
65
  }
@@ -45,7 +45,6 @@ export function ruleSummary(
45
45
  const field: string = ruleProps?.field ?? "";
46
46
  const operator: string = ruleProps?.operator ?? "equal";
47
47
  const value0 = ruleProps?.value?.[0];
48
- const value1 = ruleProps?.value?.[1];
49
48
 
50
49
  const fieldDef = fields.find((f) => f.key === field);
51
50
  const fieldLabel = fieldDef?.label ?? field;
@@ -62,9 +61,6 @@ export function ruleSummary(
62
61
  return String(v);
63
62
  };
64
63
 
65
- if (operator === "between") {
66
- return `${fieldLabel} between ${formatVal(value0)} and ${formatVal(value1)}`;
67
- }
68
64
  return `${fieldLabel} ${opLabel} ${formatVal(value0)}`;
69
65
  }
70
66
 
@@ -392,7 +392,6 @@ export function SidebarNav({
392
392
  "h-8 w-auto object-contain object-left px-5 transition-opacity duration-200",
393
393
  collapsed ? "opacity-0" : "opacity-100",
394
394
  )}
395
- style={{ filter: "brightness(0) invert(1)" }}
396
395
  />
397
396
  )}
398
397
  {logoCollapsed && (
@@ -403,7 +402,6 @@ export function SidebarNav({
403
402
  "absolute inset-y-0 left-0 right-0 m-auto h-8 w-8 object-contain transition-opacity duration-200",
404
403
  collapsed ? "opacity-100" : "opacity-0",
405
404
  )}
406
- style={{ filter: "brightness(0) invert(1)" }}
407
405
  />
408
406
  )}
409
407
  </div>