@nibssplc/cams-sdk-react 0.0.1-beta.78 → 0.0.1-beta.79

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 ADDED
@@ -0,0 +1,295 @@
1
+ # @nibssplc/cams-sdk-react
2
+
3
+ React hooks and components for NIBSS CAMS SDK with support for both regular CAMS authentication and Azure AD MSAL integration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @nibssplc/cams-sdk-react
9
+ ```
10
+
11
+ For MSAL mode, also install:
12
+ ```bash
13
+ npm install @azure/msal-browser @azure/msal-react
14
+ ```
15
+
16
+ ## Features
17
+
18
+ - ⚛️ React hooks for authentication
19
+ - 🔄 Unified provider supporting both REGULAR and MSAL modes
20
+ - 🎨 Pre-built UI components (login page, MFA gate)
21
+ - 🛡️ Protected route component
22
+ - 🎯 TypeScript support
23
+ - 🪝 Context-based state management
24
+ - 📱 Next.js compatible
25
+
26
+ ## Quick Start
27
+
28
+ ### MSAL Mode (Azure AD + MFA)
29
+
30
+ ```tsx
31
+ import { UnifiedCAMSProvider, useCAMSContext } from '@nibssplc/cams-sdk-react';
32
+
33
+ const msalConfig = {
34
+ auth: {
35
+ clientId: 'your-client-id',
36
+ authority: 'https://login.microsoftonline.com/your-tenant-id',
37
+ redirectUri: window.location.origin
38
+ }
39
+ };
40
+
41
+ function App() {
42
+ return (
43
+ <UnifiedCAMSProvider
44
+ mode="MSAL"
45
+ appCode="your-app-guid"
46
+ msalConfig={msalConfig}
47
+ MFAEndpoint="https://your-mfa-endpoint.com"
48
+ >
49
+ <YourApp />
50
+ </UnifiedCAMSProvider>
51
+ );
52
+ }
53
+
54
+ function YourApp() {
55
+ const { login, logout, isAuthenticated, userProfile } = useCAMSContext();
56
+
57
+ return (
58
+ <div>
59
+ {isAuthenticated ? (
60
+ <>
61
+ <p>Welcome, {userProfile?.name}</p>
62
+ <button onClick={logout}>Logout</button>
63
+ </>
64
+ ) : (
65
+ <button onClick={login}>Login</button>
66
+ )}
67
+ </div>
68
+ );
69
+ }
70
+ ```
71
+
72
+ ### REGULAR Mode (Popup Authentication)
73
+
74
+ ```tsx
75
+ import { UnifiedCAMSProvider, useCAMSContext } from '@nibssplc/cams-sdk-react';
76
+
77
+ function App() {
78
+ return (
79
+ <UnifiedCAMSProvider
80
+ mode="REGULAR"
81
+ appCode="your-app-guid"
82
+ camsUrl="https://your-cams-url.com"
83
+ messageOrigin="https://your-cams-url.com"
84
+ windowWidth={500}
85
+ windowHeight={600}
86
+ >
87
+ <YourApp />
88
+ </UnifiedCAMSProvider>
89
+ );
90
+ }
91
+ ```
92
+
93
+ ## Components
94
+
95
+ ### UnifiedCAMSProvider
96
+
97
+ Main provider component supporting both authentication modes.
98
+
99
+ **Props (MSAL Mode):**
100
+ ```tsx
101
+ interface MSALProviderProps {
102
+ mode: "MSAL";
103
+ appCode: string;
104
+ msalConfig: Configuration;
105
+ msalInstance?: PublicClientApplication;
106
+ MFAEndpoint: string;
107
+ children: React.ReactNode;
108
+ }
109
+ ```
110
+
111
+ **Props (REGULAR Mode):**
112
+ ```tsx
113
+ interface RegularProviderProps {
114
+ mode: "REGULAR";
115
+ appCode: string;
116
+ camsUrl: string;
117
+ messageOrigin: string;
118
+ windowWidth: number;
119
+ windowHeight: number;
120
+ authTimeout?: number;
121
+ debug?: boolean;
122
+ children: React.ReactNode;
123
+ }
124
+ ```
125
+
126
+ ### DefaultLoginPage
127
+
128
+ Pre-built login page with Microsoft and AD authentication options.
129
+
130
+ ```tsx
131
+ import { DefaultLoginPage } from '@nibssplc/cams-sdk-react';
132
+
133
+ function App() {
134
+ return (
135
+ <UnifiedCAMSProvider mode="MSAL" {...config}>
136
+ <DefaultLoginPage />
137
+ </UnifiedCAMSProvider>
138
+ );
139
+ }
140
+ ```
141
+
142
+ ### MFAGate
143
+
144
+ Component that enforces MFA completion before rendering children.
145
+
146
+ ```tsx
147
+ import { MFAGate } from '@nibssplc/cams-sdk-react';
148
+
149
+ function ProtectedContent() {
150
+ return (
151
+ <MFAGate>
152
+ <YourProtectedContent />
153
+ </MFAGate>
154
+ );
155
+ }
156
+ ```
157
+
158
+ ### ProtectedRoute
159
+
160
+ Route wrapper that requires authentication.
161
+
162
+ ```tsx
163
+ import { ProtectedRoute } from '@nibssplc/cams-sdk-react';
164
+
165
+ function App() {
166
+ return (
167
+ <ProtectedRoute>
168
+ <YourProtectedPage />
169
+ </ProtectedRoute>
170
+ );
171
+ }
172
+ ```
173
+
174
+ ## Hooks
175
+
176
+ ### useCAMSContext
177
+
178
+ Access authentication state and methods.
179
+
180
+ ```tsx
181
+ import { useCAMSContext } from '@nibssplc/cams-sdk-react';
182
+
183
+ function MyComponent() {
184
+ const {
185
+ isAuthenticated,
186
+ isLoading,
187
+ userProfile,
188
+ login,
189
+ logout,
190
+ error,
191
+ authMode
192
+ } = useCAMSContext();
193
+
194
+ return (
195
+ <div>
196
+ {isAuthenticated && <p>Hello, {userProfile?.name}</p>}
197
+ </div>
198
+ );
199
+ }
200
+ ```
201
+
202
+ **Return Values:**
203
+
204
+ | Property | Type | Description |
205
+ |----------|------|-------------|
206
+ | `isAuthenticated` | boolean | Authentication status |
207
+ | `isLoading` | boolean | Loading state |
208
+ | `userProfile` | Profile \| null | User profile data |
209
+ | `login` | function | Trigger login flow |
210
+ | `logout` | function | Logout user |
211
+ | `error` | Error \| null | Authentication error |
212
+ | `authMode` | 'REGULAR' \| 'MSAL' | Current auth mode |
213
+ | `requiresMFA` | boolean | MFA required (MSAL only) |
214
+
215
+ ### useCAMSAuth
216
+
217
+ Hook for REGULAR mode authentication.
218
+
219
+ ```tsx
220
+ import { useCAMSAuth } from '@nibssplc/cams-sdk-react';
221
+
222
+ const auth = useCAMSAuth({
223
+ appCode: 'your-app-guid',
224
+ camsUrl: 'https://your-cams-url.com',
225
+ messageOrigin: 'https://your-cams-url.com',
226
+ windowWidth: 500,
227
+ windowHeight: 600
228
+ });
229
+ ```
230
+
231
+ ### useCAMSMSALAuth
232
+
233
+ Hook for MSAL mode authentication.
234
+
235
+ ```tsx
236
+ import { useCAMSMSALAuth } from '@nibssplc/cams-sdk-react';
237
+
238
+ const auth = useCAMSMSALAuth({
239
+ appCode: 'your-app-guid',
240
+ MFAEndpoint: 'https://your-mfa-endpoint.com'
241
+ });
242
+ ```
243
+
244
+ ## Next.js Integration
245
+
246
+ ```tsx
247
+ // app/providers.tsx
248
+ 'use client';
249
+
250
+ import { UnifiedCAMSProvider } from '@nibssplc/cams-sdk-react';
251
+
252
+ export function Providers({ children }: { children: React.ReactNode }) {
253
+ return (
254
+ <UnifiedCAMSProvider mode="MSAL" {...config}>
255
+ {children}
256
+ </UnifiedCAMSProvider>
257
+ );
258
+ }
259
+
260
+ // app/layout.tsx
261
+ import { Providers } from './providers';
262
+
263
+ export default function RootLayout({ children }) {
264
+ return (
265
+ <html>
266
+ <body>
267
+ <Providers>{children}</Providers>
268
+ </body>
269
+ </html>
270
+ );
271
+ }
272
+ ```
273
+
274
+ ## Styling
275
+
276
+ Components use Tailwind CSS. Ensure Tailwind is configured in your project:
277
+
278
+ ```bash
279
+ npm install -D tailwindcss
280
+ npx tailwindcss init
281
+ ```
282
+
283
+ ## Examples
284
+
285
+ See the [examples](../../examples) directory for complete implementations:
286
+ - `integrated-mfa-example.tsx` - MSAL mode with MFA
287
+ - `popup-auth-example.tsx` - Regular popup authentication
288
+
289
+ ## License
290
+
291
+ MIT
292
+
293
+ ## Author
294
+
295
+ NIBSS PLC, Caleb Boluwade
@@ -0,0 +1,7 @@
1
+ interface ADLoginModalProps {
2
+ open: boolean;
3
+ onOpenChange: (open: boolean) => void;
4
+ onLogin: (username: string, password: string, mfaCode: string) => Promise<void>;
5
+ }
6
+ export declare const ADLoginModal: ({ open, onOpenChange, onLogin }: ADLoginModalProps) => import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,5 @@
1
+ import * as React from "react";
2
+ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
3
+ }
4
+ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
5
+ export { Input };
@@ -7,6 +7,7 @@ export interface UseCAMSAuthOptions {
7
7
  onTokenExpired?: () => void;
8
8
  autoClose?: boolean;
9
9
  idleTimeout?: number;
10
+ loginExpiry?: number;
10
11
  }
11
12
  export interface UseCAMSAuthReturn {
12
13
  login: (config: CAMSConfig) => Promise<void>;
@@ -18,5 +19,6 @@ export interface UseCAMSAuthReturn {
18
19
  profile: Profile | null;
19
20
  appCode: string;
20
21
  storageKey: string;
22
+ loginExpiry: number;
21
23
  }
22
24
  export declare function useCAMSAuth(options?: UseCAMSAuthOptions): UseCAMSAuthReturn;
package/dist/index.cjs.js CHANGED
@@ -12,7 +12,7 @@ var resolvers = require('@hookform/resolvers');
12
12
  var clsx = require('clsx');
13
13
  var tailwindMerge = require('tailwind-merge');
14
14
  var reactSlot = require('@radix-ui/react-slot');
15
- require('@radix-ui/react-label');
15
+ var LabelPrimitive = require('@radix-ui/react-label');
16
16
  var classVarianceAuthority = require('class-variance-authority');
17
17
  var DialogPrimitive = require('@radix-ui/react-dialog');
18
18
  var sonner = require('sonner');
@@ -37,6 +37,7 @@ function _interopNamespaceDefault(e) {
37
37
  }
38
38
 
39
39
  var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
40
+ var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(LabelPrimitive);
40
41
  var DialogPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(DialogPrimitive);
41
42
 
42
43
  /******************************************************************************
@@ -134,15 +135,17 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
134
135
 
135
136
  function useCAMSAuth(options) {
136
137
  var _this = this;
138
+ var _a;
137
139
  if (options === void 0) { options = {
138
140
  appCode: "",
141
+ loginExpiry: 1,
139
142
  storageKey: "CAMS-AUTH-SDK",
140
143
  }; }
141
- var _a = React.useState(false), isAuthenticated = _a[0], setIsAuthenticated = _a[1];
142
- var _b = React.useState(false), isLoading = _b[0], setIsLoading = _b[1];
143
- var _c = React.useState(null), error = _c[0], setError = _c[1];
144
- var _d = React.useState(""), token = _d[0], setToken = _d[1];
145
- var _e = React.useState(null), profile = _e[0], setProfile = _e[1];
144
+ var _b = React.useState(false), isAuthenticated = _b[0], setIsAuthenticated = _b[1];
145
+ var _c = React.useState(false), isLoading = _c[0], setIsLoading = _c[1];
146
+ var _d = React.useState(null), error = _d[0], setError = _d[1];
147
+ var _e = React.useState(""), token = _e[0], setToken = _e[1];
148
+ var _f = React.useState(null), profile = _f[0], setProfile = _f[1];
146
149
  var sessionManagerRef = React.useRef(null);
147
150
  React.useEffect(function () {
148
151
  var _a, _b;
@@ -153,7 +156,7 @@ function useCAMSAuth(options) {
153
156
  if (camsSdk.isPopupWindow()) {
154
157
  camsSdk.initializePopupAuth();
155
158
  }
156
- (_a = sessionManagerRef.current) !== null && _a !== void 0 ? _a : (sessionManagerRef.current = new camsSdk.CAMSSessionManager(localStorage, options.storageKey || "CAMS-SDK", {
159
+ (_a = sessionManagerRef.current) !== null && _a !== void 0 ? _a : (sessionManagerRef.current = new camsSdk.CAMSSessionManager(localStorage, options.storageKey || "CAMS-AUTH-SDK", {
157
160
  onAuthSuccess: function (res) {
158
161
  var _a;
159
162
  setToken(res.userProfile.tokens.Bearer);
@@ -189,40 +192,53 @@ function useCAMSAuth(options) {
189
192
  }
190
193
  }, [options.storageKey]);
191
194
  var login = React.useCallback(function (config) { return __awaiter(_this, void 0, void 0, function () {
192
- var loginConfig, userProfile, err_1;
193
- var _a;
194
- return __generator(this, function (_b) {
195
- switch (_b.label) {
195
+ var loginConfig, userProfile, err_1, e, isPopupClosedError, restoredToken, userProfile;
196
+ var _a, _b, _c;
197
+ return __generator(this, function (_d) {
198
+ switch (_d.label) {
196
199
  case 0:
197
200
  if (!sessionManagerRef.current)
198
201
  return [2 /*return*/];
199
202
  setIsLoading(true);
200
203
  setError(null);
201
- _b.label = 1;
204
+ _d.label = 1;
202
205
  case 1:
203
- _b.trys.push([1, 4, 5, 6]);
204
- loginConfig = __assign(__assign({}, config), {
205
- // autoClose: options.autoClose ?? config.autoClose,
206
- idleTimeout: (_a = options.idleTimeout) !== null && _a !== void 0 ? _a : config.idleTimeout });
206
+ _d.trys.push([1, 4, 8, 9]);
207
+ loginConfig = __assign(__assign({}, config), { idleTimeout: options.idleTimeout });
207
208
  return [4 /*yield*/, sessionManagerRef.current.login(loginConfig)];
208
209
  case 2:
209
- _b.sent();
210
+ _d.sent();
210
211
  return [4 /*yield*/, sessionManagerRef.current.getProfile()];
211
212
  case 3:
212
- userProfile = _b.sent();
213
+ userProfile = _d.sent();
213
214
  setProfile(userProfile);
214
- return [3 /*break*/, 6];
215
+ return [3 /*break*/, 9];
215
216
  case 4:
216
- err_1 = _b.sent();
217
+ err_1 = _d.sent();
218
+ e = err_1;
219
+ isPopupClosedError = ((_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.includes("Authentication window was closed")) ||
220
+ (e === null || e === void 0 ? void 0 : e.error) === "Authentication window was closed";
221
+ if (!(isPopupClosedError && sessionManagerRef.current.isAuthenticated())) return [3 /*break*/, 6];
222
+ restoredToken = (_b = sessionManagerRef.current.getAccessToken()) !== null && _b !== void 0 ? _b : "";
223
+ setToken(restoredToken);
224
+ setIsAuthenticated(true);
225
+ return [4 /*yield*/, sessionManagerRef.current.getProfile()];
226
+ case 5:
227
+ userProfile = _d.sent();
228
+ setProfile(userProfile);
229
+ (_c = options.onAuthSuccess) === null || _c === void 0 ? void 0 : _c.call(options, restoredToken);
230
+ return [3 /*break*/, 7];
231
+ case 6:
217
232
  setError(err_1);
218
233
  setIsAuthenticated(false);
219
234
  setToken("");
220
235
  setProfile(null);
221
- return [3 /*break*/, 6];
222
- case 5:
236
+ _d.label = 7;
237
+ case 7: return [3 /*break*/, 9];
238
+ case 8:
223
239
  setIsLoading(false);
224
240
  return [7 /*endfinally*/];
225
- case 6: return [2 /*return*/];
241
+ case 9: return [2 /*return*/];
226
242
  }
227
243
  });
228
244
  }); }, [options.idleTimeout]);
@@ -251,8 +267,9 @@ function useCAMSAuth(options) {
251
267
  error: error,
252
268
  token: token,
253
269
  profile: profile,
270
+ loginExpiry: (_a = options.loginExpiry) !== null && _a !== void 0 ? _a : 1,
254
271
  appCode: options.appCode,
255
- storageKey: options.storageKey || "CAMS-SDK",
272
+ storageKey: options.storageKey || "CAMS-AUTH-SDK",
256
273
  };
257
274
  }
258
275
 
@@ -1418,6 +1435,11 @@ function InputOTPSlot(_a) {
1418
1435
  return (jsxRuntimeExports.jsxs("div", __assign({ "data-slot": "input-otp-slot", "data-active": isActive, className: cn("data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive dark:bg-input/30 border-input relative flex h-12 w-12 items-center justify-center border-y border-r text-lg font-semibold shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:z-10 data-[active=true]:ring-[3px]", className) }, props, { children: [char, hasFakeCaret && (jsxRuntimeExports.jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: jsxRuntimeExports.jsx("div", { className: "animate-caret-blink bg-foreground h-4 w-px duration-1000" }) }))] })));
1419
1436
  }
1420
1437
 
1438
+ function Label(_a) {
1439
+ var className = _a.className, props = __rest(_a, ["className"]);
1440
+ return (jsxRuntimeExports.jsx(LabelPrimitive__namespace.Root, __assign({ "data-slot": "label", className: cn("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", className) }, props)));
1441
+ }
1442
+
1421
1443
  var Form = reactHookForm.FormProvider;
1422
1444
  var FormFieldContext = React__namespace.createContext({});
1423
1445
  var FormField = function (_a) {
@@ -1442,6 +1464,11 @@ function FormItem(_a) {
1442
1464
  var id = React__namespace.useId();
1443
1465
  return (jsxRuntimeExports.jsx(FormItemContext.Provider, { value: { id: id }, children: jsxRuntimeExports.jsx("div", __assign({ "data-slot": "form-item", className: cn("grid gap-2", className) }, props)) }));
1444
1466
  }
1467
+ function FormLabel(_a) {
1468
+ var className = _a.className, props = __rest(_a, ["className"]);
1469
+ var _b = useFormField(), error = _b.error, formItemId = _b.formItemId;
1470
+ return (jsxRuntimeExports.jsx(Label, __assign({ "data-slot": "form-label", "data-error": !!error, className: cn("data-[error=true]:text-destructive", className), htmlFor: formItemId }, props)));
1471
+ }
1445
1472
  function FormControl(_a) {
1446
1473
  var props = __rest(_a, []);
1447
1474
  var _b = useFormField(), error = _b.error, formItemId = _b.formItemId, formDescriptionId = _b.formDescriptionId, formMessageId = _b.formMessageId;
@@ -1861,9 +1888,80 @@ var AuthLogo = "data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2
1861
1888
 
1862
1889
  var MicrosoftLogo = "data:image/svg+xml,%3Csvg%20width%3D%2225%22%20height%3D%2225%22%20viewBox%3D%220%200%2025%2025%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20id%3D%22microsoft_svgrepo.com%22%3E%3Cpath%20id%3D%22Vector%22%20d%3D%22M20.75%2013.25H13.25V20.75H20.75V13.25Z%22%20fill%3D%22%23FEBA08%22%2F%3E%3Cpath%20id%3D%22Vector_2%22%20d%3D%22M11.75%2013.25H4.25V20.75H11.75V13.25Z%22%20fill%3D%22%2305A6F0%22%2F%3E%3Cpath%20id%3D%22Vector_3%22%20d%3D%22M20.75%204.25H13.25V11.75H20.75V4.25Z%22%20fill%3D%22%2380BC06%22%2F%3E%3Cpath%20id%3D%22Vector_4%22%20d%3D%22M11.75%204.25H4.25V11.75H11.75V4.25Z%22%20fill%3D%22%23F25325%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E";
1863
1890
 
1891
+ var Input = React__namespace.forwardRef(function (_a, ref) {
1892
+ var className = _a.className, type = _a.type, props = __rest(_a, ["className", "type"]);
1893
+ return (jsxRuntimeExports.jsx("input", __assign({ type: type, className: cn("flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", className), ref: ref }, props)));
1894
+ });
1895
+ Input.displayName = "Input";
1896
+
1897
+ var credentialsSchema = z.z.object({
1898
+ username: z.z.string().min(1, "Username is required"),
1899
+ password: z.z.string().min(1, "Password is required"),
1900
+ });
1901
+ var ADLoginModal = function (_a) {
1902
+ var open = _a.open, onOpenChange = _a.onOpenChange, onLogin = _a.onLogin;
1903
+ var _b = React.useState("credentials"), step = _b[0], setStep = _b[1];
1904
+ var _c = React.useState({ username: "", password: "" }), credentials = _c[0], setCredentials = _c[1];
1905
+ var _d = React.useState(""), mfaCode = _d[0], setMfaCode = _d[1];
1906
+ var _e = React.useState(false), isLoading = _e[0], setIsLoading = _e[1];
1907
+ var form = reactHookForm.useForm({
1908
+ resolver: a$1(credentialsSchema),
1909
+ defaultValues: { username: "", password: "" },
1910
+ });
1911
+ var handleCredentialsSubmit = function (values) { return __awaiter(void 0, void 0, void 0, function () {
1912
+ return __generator(this, function (_a) {
1913
+ setCredentials(values);
1914
+ setStep("mfa");
1915
+ return [2 /*return*/];
1916
+ });
1917
+ }); };
1918
+ var handleMFASubmit = function (code) { return __awaiter(void 0, void 0, void 0, function () {
1919
+ var error_1;
1920
+ return __generator(this, function (_a) {
1921
+ switch (_a.label) {
1922
+ case 0:
1923
+ setIsLoading(true);
1924
+ _a.label = 1;
1925
+ case 1:
1926
+ _a.trys.push([1, 3, 4, 5]);
1927
+ return [4 /*yield*/, onLogin(credentials.username, credentials.password, code)];
1928
+ case 2:
1929
+ _a.sent();
1930
+ onOpenChange(false);
1931
+ setStep("credentials");
1932
+ form.reset();
1933
+ setMfaCode("");
1934
+ return [3 /*break*/, 5];
1935
+ case 3:
1936
+ error_1 = _a.sent();
1937
+ console.error("AD login failed:", error_1);
1938
+ return [3 /*break*/, 5];
1939
+ case 4:
1940
+ setIsLoading(false);
1941
+ return [7 /*endfinally*/];
1942
+ case 5: return [2 /*return*/];
1943
+ }
1944
+ });
1945
+ }); };
1946
+ var handleClose = function () {
1947
+ onOpenChange(false);
1948
+ setStep("credentials");
1949
+ form.reset();
1950
+ setMfaCode("");
1951
+ };
1952
+ return (jsxRuntimeExports.jsx(Dialog, { open: open, onOpenChange: handleClose, children: jsxRuntimeExports.jsxs(DialogContent, { className: "sm:max-w-md", children: [jsxRuntimeExports.jsx(DialogHeader, { children: jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [jsxRuntimeExports.jsx(lucideReact.KeyIcon, { className: "w-5 h-5 text-[#506f4a]" }), jsxRuntimeExports.jsx(DialogTitle, { children: "Sign in with AD" })] }) }), step === "credentials" ? (jsxRuntimeExports.jsx(Form, __assign({}, form, { children: jsxRuntimeExports.jsxs("form", { onSubmit: form.handleSubmit(handleCredentialsSubmit), className: "space-y-4", children: [jsxRuntimeExports.jsx(FormField, { control: form.control, name: "username", render: function (_a) {
1953
+ var field = _a.field;
1954
+ return (jsxRuntimeExports.jsxs(FormItem, { children: [jsxRuntimeExports.jsx(FormLabel, { children: "Username" }), jsxRuntimeExports.jsx(FormControl, { children: jsxRuntimeExports.jsx(Input, __assign({ placeholder: "Enter your username" }, field)) }), jsxRuntimeExports.jsx(FormMessage, {})] }));
1955
+ } }), jsxRuntimeExports.jsx(FormField, { control: form.control, name: "password", render: function (_a) {
1956
+ var field = _a.field;
1957
+ return (jsxRuntimeExports.jsxs(FormItem, { children: [jsxRuntimeExports.jsx(FormLabel, { children: "Password" }), jsxRuntimeExports.jsx(FormControl, { children: jsxRuntimeExports.jsx(Input, __assign({ type: "password", placeholder: "Enter your password" }, field)) }), jsxRuntimeExports.jsx(FormMessage, {})] }));
1958
+ } }), jsxRuntimeExports.jsx(Button, { type: "submit", className: "w-full bg-[#506f4a] hover:bg-[#506f4a]/90", children: "Continue" })] }) }))) : (jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [jsxRuntimeExports.jsx(GenericOTPVerifier, { value: mfaCode, setValue: setMfaCode, setLoading: setIsLoading, isDisabled: isLoading, onChangeOTP: handleMFASubmit, fieldName: "AuthenticatorCode" }), isLoading && (jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center gap-2 text-sm text-muted-foreground", children: [jsxRuntimeExports.jsx(lucideReact.Loader2, { className: "w-4 h-4 animate-spin" }), jsxRuntimeExports.jsx("span", { children: "Verifying..." })] }))] }))] }) }));
1959
+ };
1960
+
1864
1961
  var DefaultLoginPage = function () {
1865
1962
  var context = useCAMSContext$1();
1866
1963
  var login = context.login, isLoading = context.isLoading, authMode = context.authMode;
1964
+ var _a = React.useState(false), showADModal = _a[0], setShowADModal = _a[1];
1867
1965
  var handleLogin = function () {
1868
1966
  if (authMode === "MSAL") {
1869
1967
  login();
@@ -1883,11 +1981,21 @@ var DefaultLoginPage = function () {
1883
1981
  },
1884
1982
  exit: { opacity: 0, scale: 0.8, y: -50, transition: { duration: 0.3 } },
1885
1983
  };
1886
- return (jsxRuntimeExports.jsx("main", { className: "min-h-screen bg-gray-50", children: jsxRuntimeExports.jsx(framerMotion.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.5 }, children: jsxRuntimeExports.jsx("div", { className: "flex h-screen items-center justify-center", children: jsxRuntimeExports.jsxs(framerMotion.motion.div, { variants: cardVariants, initial: "hidden", animate: "visible", exit: "exit", className: "w-full max-w-md p-6 space-y-4 bg-gray-50 rounded-2xl shadow-2xl --dark:bg-gray-800", children: [jsxRuntimeExports.jsxs(CardHeader, { className: "text-center space-y-3", children: [jsxRuntimeExports.jsx("div", { className: "w-full flex items-center justify-center", children: jsxRuntimeExports.jsx("img", { src: NIBSSLogo, alt: "NIBSS Logo", width: 265, height: 265 }) }), jsxRuntimeExports.jsx(CardTitle, { className: "text-3xl font-bold --text-gray-900 --dark:text-white", children: "NIBSS CAMS" }), jsxRuntimeExports.jsx(CardTitle, { className: "text-gray-500 dark:text-gray-400 font-bold text-lg", children: "Centralized Authentication" })] }), jsxRuntimeExports.jsxs(CardAction, { className: "w-full flex flex-col items-center justify-center text-center text-gray-500 dark:text-gray-400 mb-4", children: [jsxRuntimeExports.jsx("img", { src: AuthLogo, alt: "Auth Logo", width: 365, height: 365 }), "Kindly use the below identity providers to authenticate"] }), jsxRuntimeExports.jsx("div", { className: "space-y-4", children: jsxRuntimeExports.jsxs(Button
1887
- // variant="outline"
1888
- , {
1889
- // variant="outline"
1890
- className: "w-full flex items-center justify-center cursor-pointer bg-[#506f4a] hover:bg-[#506f4a] rounded-lg border border-transparent px-5 py-8 text-base font-medium transition-colors duration-250", onClick: handleLogin, disabled: isLoading, children: [jsxRuntimeExports.jsx("img", { src: MicrosoftLogo, alt: "Microsoft Logo", width: 35, height: 35 }), jsxRuntimeExports.jsx("span", { children: isLoading ? 'Logging in...' : "Sign in with Microsoft" })] }) }), jsxRuntimeExports.jsxs(CardFooter, { className: "flex items-center justify-center mt-6 space-x-2 text-gray-400 text-sm", children: [jsxRuntimeExports.jsx(lucideReact.ShieldCheck, { className: "w-4 h-4 text-[#506f4a] pulse-glow" }), jsxRuntimeExports.jsx("span", { children: "Powered By NIBSS" })] })] }) }) }, "landing") }));
1984
+ return (jsxRuntimeExports.jsxs("main", { className: "min-h-screen bg-gray-50", children: [jsxRuntimeExports.jsx(framerMotion.motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.5 }, children: jsxRuntimeExports.jsx("div", { className: "flex h-screen items-center justify-center", children: jsxRuntimeExports.jsxs(framerMotion.motion.div, { variants: cardVariants, initial: "hidden", animate: "visible", exit: "exit", className: "w-full max-w-md p-6 space-y-4 bg-gray-50 rounded-2xl shadow-2xl --dark:bg-gray-800", children: [jsxRuntimeExports.jsxs(CardHeader, { className: "text-center space-y-3", children: [jsxRuntimeExports.jsx("div", { className: "w-full flex items-center justify-center", children: jsxRuntimeExports.jsx("img", { src: NIBSSLogo, alt: "NIBSS Logo", width: 265, height: 265 }) }), jsxRuntimeExports.jsx(CardTitle, { className: "text-3xl font-bold --text-gray-900 --dark:text-white", children: "NIBSS CAMS" }), jsxRuntimeExports.jsx(CardTitle, { className: "text-gray-500 dark:text-gray-400 font-bold text-lg", children: "Centralized Authentication" })] }), jsxRuntimeExports.jsxs(CardAction, { className: "w-full flex flex-col items-center justify-center text-center text-gray-500 dark:text-gray-400 mb-4", children: [jsxRuntimeExports.jsx("img", { src: AuthLogo, alt: "Auth Logo", width: 365, height: 365 }), "Kindly use the below identity providers to authenticate"] }), jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [jsxRuntimeExports.jsxs(Button
1985
+ // variant="outline"
1986
+ , {
1987
+ // variant="outline"
1988
+ className: "w-full flex items-center justify-center cursor-pointer bg-[#506f4a] hover:bg-[#506f4a] rounded-lg border border-transparent px-5 py-8 text-base font-medium transition-colors duration-250", onClick: handleLogin, disabled: isLoading, children: [jsxRuntimeExports.jsx("img", { src: MicrosoftLogo, alt: "Microsoft Logo", width: 35, height: 35 }), jsxRuntimeExports.jsx("span", { children: isLoading ? "Logging in..." : "Sign in with Microsoft" })] }), jsxRuntimeExports.jsxs(Button
1989
+ // variant="outline"
1990
+ , {
1991
+ // variant="outline"
1992
+ className: "w-full flex items-center justify-center cursor-pointer bg-[#506f4a] hover:bg-[#506f4a] rounded-lg border border-transparent px-5 py-8 text-base font-medium transition-colors duration-250", onClick: function () { return setShowADModal(true); }, disabled: isLoading, children: [jsxRuntimeExports.jsx(lucideReact.KeyIcon, {}), jsxRuntimeExports.jsx("span", { children: isLoading ? "Logging in..." : "Sign in with AD" })] })] }), jsxRuntimeExports.jsxs(CardFooter, { className: "flex items-center justify-center mt-6 space-x-2 text-gray-400 text-sm", children: [jsxRuntimeExports.jsx(lucideReact.ShieldCheck, { className: "w-4 h-4 text-[#506f4a] pulse-glow" }), jsxRuntimeExports.jsx("span", { children: "Powered By NIBSS" })] })] }) }) }, "landing"), jsxRuntimeExports.jsx(ADLoginModal, { open: showADModal, onOpenChange: setShowADModal, onLogin: function (username, password, mfaCode) { return __awaiter(void 0, void 0, void 0, function () {
1993
+ return __generator(this, function (_a) {
1994
+ // Implement your AD login logic here
1995
+ console.log("AD Login:", { username: username, password: password, mfaCode: mfaCode });
1996
+ return [2 /*return*/];
1997
+ });
1998
+ }); } })] }));
1891
1999
  };
1892
2000
 
1893
2001
  var ErrorFallback = function (_a) {