This commit is contained in:
Chris Chen
2026-05-27 07:49:26 -07:00
parent 62428cd2d4
commit 60405ef0aa
19 changed files with 74 additions and 49 deletions
+1
View File
@@ -91,3 +91,4 @@ logs/
*.log *.log
*.tmp *.tmp
*.temp *.temp
/.claude
+27 -1
View File
@@ -1,20 +1,46 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.14.36623.8 d17.14 VisualStudioVersion = 17.14.36623.8
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ROLAC.API", "ROLAC.API.csproj", "{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ROLAC.API", "ROLAC.API.csproj", "{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ROLAC.API.Tests", "..\ROLAC.API.Tests\ROLAC.API.Tests.csproj", "{2065B769-3D62-48F5-9456-96BED5FAF659}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Debug|x64.ActiveCfg = Debug|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Debug|x64.Build.0 = Debug|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Debug|x86.ActiveCfg = Debug|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Debug|x86.Build.0 = Debug|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Release|Any CPU.ActiveCfg = Release|Any CPU {1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Release|Any CPU.Build.0 = Release|Any CPU {1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Release|Any CPU.Build.0 = Release|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Release|x64.ActiveCfg = Release|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Release|x64.Build.0 = Release|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Release|x86.ActiveCfg = Release|Any CPU
{1F8C6494-4B18-4AD5-B63E-4958A8E2C21A}.Release|x86.Build.0 = Release|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Debug|x64.ActiveCfg = Debug|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Debug|x64.Build.0 = Debug|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Debug|x86.ActiveCfg = Debug|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Debug|x86.Build.0 = Debug|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Release|Any CPU.Build.0 = Release|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Release|x64.ActiveCfg = Release|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Release|x64.Build.0 = Release|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Release|x86.ActiveCfg = Release|Any CPU
{2065B769-3D62-48F5-9456-96BED5FAF659}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
+1 -1
View File
@@ -13,6 +13,6 @@
"RefreshTokenExpiryDays": "30" "RefreshTokenExpiryDays": "30"
}, },
"Cors": { "Cors": {
"AllowedOrigins": [ "https://localhost:4200" ] "AllowedOrigins": [ "http://localhost:4200", "https://localhost:4200" ]
} }
} }
+8 -8
View File
@@ -4,7 +4,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Escrow Portal Access - RBJ Identity</title> <title>Escrow Portal Access - ROLCC AC</title>
<style> <style>
/* Email-safe CSS - compatible with most email clients */ /* Email-safe CSS - compatible with most email clients */
body { body {
@@ -236,8 +236,8 @@
<img src="assets/rbj-logo.svg" alt="RBJ Logo" class="logo-image" <img src="assets/rbj-logo.svg" alt="RBJ Logo" class="logo-image"
style="height: 50px; width: auto; margin-bottom: 15px;"> style="height: 50px; width: auto; margin-bottom: 15px;">
<div class="logo-text"> <div class="logo-text">
<h1 style="font-size: 28px; font-weight: bold; margin: 0 0 5px 0;">RBJ Identity</h1> <h1 style="font-size: 28px; font-weight: bold; margin: 0 0 5px 0;">ROLCC AC</h1>
<span class="tagline" style="font-size: 14px; opacity: 0.9;">Escrow Management <span class="tagline" style="font-size: 14px; opacity: 0.9;">Church Management
Portal</span> Portal</span>
</div> </div>
<h2 class="email-title" style="font-size: 24px; font-weight: bold; margin: 20px 0 0 0;"> <h2 class="email-title" style="font-size: 24px; font-weight: bold; margin: 20px 0 0 0;">
@@ -255,11 +255,11 @@
<div class="message" <div class="message"
style="font-size: 16px; line-height: 1.6; margin-bottom: 25px; color: #4b5563;"> style="font-size: 16px; line-height: 1.6; margin-bottom: 25px; color: #4b5563;">
Your escrow transaction is ready for review. Please use the secure link below to access Your church transaction is ready for review. Please use the secure link below to access
your your
personalized portal where you can view transaction details, upload required documents, personalized portal where you can view transaction details, upload required documents,
and communicate and communicate
with your escrow officer. with your church officer.
</div> </div>
<!-- Transaction Details --> <!-- Transaction Details -->
@@ -350,7 +350,7 @@
This link is secure and personalized for your transaction. Please do not This link is secure and personalized for your transaction. Please do not
share this link with share this link with
others. If you did not request this access or have any concerns, please others. If you did not request this access or have any concerns, please
contact your escrow officer contact your church officer
immediately. immediately.
</div> </div>
</td> </td>
@@ -360,7 +360,7 @@
<div class="message" <div class="message"
style="font-size: 16px; line-height: 1.6; margin-bottom: 25px; color: #4b5563;"> style="font-size: 16px; line-height: 1.6; margin-bottom: 25px; color: #4b5563;">
If you have any questions or need assistance, please don't hesitate to contact your If you have any questions or need assistance, please don't hesitate to contact your
escrow officer church officer
directly. We're here to help make your transaction as smooth as possible. directly. We're here to help make your transaction as smooth as possible.
</div> </div>
</td> </td>
@@ -371,7 +371,7 @@
<td class="email-footer" <td class="email-footer"
style="background-color: #f8f9fa; padding: 20px; text-align: center; border-top: 1px solid #e9ecef;"> style="background-color: #f8f9fa; padding: 20px; text-align: center; border-top: 1px solid #e9ecef;">
<div class="footer-text" style="font-size: 14px; color: #6b7280; margin-bottom: 8px;"> <div class="footer-text" style="font-size: 14px; color: #6b7280; margin-bottom: 8px;">
This email was sent by RBJ Identity Escrow Management Portal This email was sent by ROLCC AC Church Management Portal
</div> </div>
<div class="footer-contact" style="font-size: 12px; color: #9ca3af;"> <div class="footer-contact" style="font-size: 12px; color: #9ca3af;">
For technical support, contact: support@clientbridge.com | Phone: (555) 123-4567 For technical support, contact: support@clientbridge.com | Phone: (555) 123-4567
+2 -2
View File
@@ -1,11 +1,11 @@
{ {
"name": "client-bridge", "name": "RBJ.Identity.App",
"version": "0.0.0", "version": "0.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "client-bridge", "name": "RBJ.Identity.App",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@angular/animations": "^20.1.0", "@angular/animations": "^20.1.0",
+3 -11
View File
@@ -1,8 +1,7 @@
import { Component, ViewEncapsulation, OnInit } from '@angular/core'; import { Component, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router'; import { RouterOutlet } from '@angular/router';
import { DialogModule } from '@progress/kendo-angular-dialog'; import { DialogModule } from '@progress/kendo-angular-dialog';
import { AuthService } from './shared/services/auth.service';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@@ -16,13 +15,6 @@ import { AuthService } from './shared/services/auth.service';
styleUrls: ['./app.scss', '../styles.scss'], styleUrls: ['./app.scss', '../styles.scss'],
encapsulation: ViewEncapsulation.None encapsulation: ViewEncapsulation.None
}) })
export class App implements OnInit { export class App {
title = 'RBJ Identity'; title = 'ROLCC AC';
constructor(private authService: AuthService) { }
ngOnInit(): void {
// Initialize authentication state from refresh token cookie
this.authService.initializeFromRefreshToken();
}
} }
@@ -14,21 +14,21 @@
<div class="logo-container"> <div class="logo-container">
<img src="assets/rbj-logo.svg" alt="RBJ Logo" class="logo-image"> <img src="assets/rbj-logo.svg" alt="RBJ Logo" class="logo-image">
<div class="logo-text"> <div class="logo-text">
<h1>RBJ Identity</h1> <h1>ROLCC AC</h1>
<span class="tagline">Escrow Management Portal</span> <span class="tagline">Church Management Portal</span>
</div> </div>
</div> </div>
<div class="welcome-text"> <div class="welcome-text">
<h2>Welcome Back</h2> <h2>Welcome Back</h2>
<p>Access your escrow transactions, manage client communications, and track document workflows <p>Access your church transactions, manage client communications, and track document workflows
securely.</p> securely.</p>
</div> </div>
<div class="features-list"> <div class="features-list">
<div class="feature-item"> <div class="feature-item">
<div class="feature-icon">🔒</div> <div class="feature-icon">🔒</div>
<span>Secure Escrow Management</span> <span>Secure Church Management</span>
</div> </div>
<div class="feature-item"> <div class="feature-item">
<div class="feature-icon">💬</div> <div class="feature-icon">💬</div>
@@ -53,7 +53,7 @@
<div *ngIf="!showLoginForm" class="initial-state"> <div *ngIf="!showLoginForm" class="initial-state">
<div class="login-header"> <div class="login-header">
<h3>Access Your Account</h3> <h3>Access Your Account</h3>
<p>Sign in to manage your escrow transactions and client communications</p> <p>Sign in to manage your church transactions and client communications</p>
</div> </div>
<div class="login-actions"> <div class="login-actions">
@@ -4,11 +4,11 @@
<kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-gap-2"> <kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-gap-2">
<button kendoButton [svgIcon]="menuIcon" fillMode="clear" title="Menu" (click)="onMenuClick()"></button> <button kendoButton [svgIcon]="menuIcon" fillMode="clear" title="Menu" (click)="onMenuClick()"></button>
<a href="#" class="k-d-none k-d-sm-flex logo-link"> <a href="#" class="k-d-none k-d-sm-flex logo-link">
<img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ RBJ Identity logo" /> <img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ ROLCC AC logo" />
<span class="logo-text">RBJ Identity Portal</span> <span class="logo-text">ROLCC AC Portal</span>
</a> </a>
<a href="#" class="k-d-flex k-d-sm-none"> <a href="#" class="k-d-flex k-d-sm-none">
<img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ RBJ Identity compact logo" /> <img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ ROLCC AC compact logo" />
</a> </a>
</kendo-appbar-section> </kendo-appbar-section>
<kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-justify-content-center"> <kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-justify-content-center">
@@ -3,11 +3,11 @@
<kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-gap-2"> <kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-gap-2">
<button kendoButton [svgIcon]="menuIcon" fillMode="clear" title="Menu" (click)="onMenuClick()"></button> <button kendoButton [svgIcon]="menuIcon" fillMode="clear" title="Menu" (click)="onMenuClick()"></button>
<a href="#" class="k-d-none k-d-sm-flex logo-link"> <a href="#" class="k-d-none k-d-sm-flex logo-link">
<img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ RBJ Identity logo" /> <img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ ROLCC AC logo" />
<span class="logo-text">RBJ Identity Portal</span> <span class="logo-text">ROLCC AC Portal</span>
</a> </a>
<a href="#" class="k-d-flex k-d-sm-none"> <a href="#" class="k-d-flex k-d-sm-none">
<img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ RBJ Identity compact logo" /> <img src="assets/rbj-logo.svg" class="k-h-8" alt="RBJ ROLCC AC compact logo" />
</a> </a>
</kendo-appbar-section> </kendo-appbar-section>
<kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-justify-content-center"> <kendo-appbar-section class="k-flex-basis-0 k-flex-grow k-justify-content-center">
@@ -5,7 +5,7 @@
<div class="drawer-content"> <div class="drawer-content">
<div class="drawer-header"> <div class="drawer-header">
<h3>User Portal</h3> <h3>User Portal</h3>
<p>RBJ Identity Portal</p> <p>ROLCC AC Portal</p>
</div> </div>
<nav class="drawer-nav"> <nav class="drawer-nav">
@@ -3,7 +3,7 @@
<div class="welcome-section"> <div class="welcome-section">
<div class="welcome-content"> <div class="welcome-content">
<h1>Welcome back, {{ getDisplayName() || 'User' }}!</h1> <h1>Welcome back, {{ getDisplayName() || 'User' }}!</h1>
<p>Here's a mock overview of the RBJ Identity escrow dashboard.</p> <p>Here's a mock overview of the ROLCC AC church dashboard.</p>
</div> </div>
</div> </div>
@@ -123,7 +123,7 @@
</div> </div>
<div class="action-content"> <div class="action-content">
<div class="action-title">New Transaction</div> <div class="action-title">New Transaction</div>
<div class="action-description">Start a new escrow process</div> <div class="action-description">Start a new church process</div>
</div> </div>
</button> </button>
@@ -18,7 +18,7 @@
<div class="logo-section"> <div class="logo-section">
<img src="assets/rbj-logo.svg" alt="RBJ Logo" class="logo-image"> <img src="assets/rbj-logo.svg" alt="RBJ Logo" class="logo-image">
<div class="logo-text" *ngIf="!sidebarCollapsed"> <div class="logo-text" *ngIf="!sidebarCollapsed">
<h2>RBJ Identity</h2> <h2>ROLCC AC</h2>
<span class="tagline">Escrow Portal</span> <span class="tagline">Escrow Portal</span>
</div> </div>
</div> </div>
+1 -1
View File
@@ -1,4 +1,4 @@
// Placeholder enums — expand as the escrow module is built out // Placeholder enums — expand as the church module is built out
export enum EscrowStatus { export enum EscrowStatus {
Open = 'Open', Open = 'Open',
Closed = 'Closed', Closed = 'Closed',
+7 -1
View File
@@ -46,6 +46,8 @@ export interface TokenVerificationResult {
isValid: boolean; isValid: boolean;
/** Constructed from JWT claims when using secret-link login. */ /** Constructed from JWT claims when using secret-link login. */
user?: UserInfo; user?: UserInfo;
/** The raw JWT from the URL — use as the access token for this session. */
accessToken?: string;
message?: string; message?: string;
expiresAt?: Date; expiresAt?: Date;
requiresMfa?: boolean; requiresMfa?: boolean;
@@ -56,7 +58,11 @@ export interface TokenVerificationResult {
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class AuthService { export class AuthService {
/** In-memory only — never written to localStorage. */ /**
* In-memory only — never written to localStorage.
* Non-private intentionally: unit tests seed state via these subjects directly.
* Production code must use getToken(), getCurrentUser(), and setCurrentUser().
*/
accessToken$ = new BehaviorSubject<string | null>(null); accessToken$ = new BehaviorSubject<string | null>(null);
currentUser$ = new BehaviorSubject<UserInfo | null>(null); currentUser$ = new BehaviorSubject<UserInfo | null>(null);
@@ -19,7 +19,7 @@ export class UiUtilsService {
constructor() { } constructor() { }
/** /**
* Get CSS class for escrow status * Get CSS class for church status
*/ */
getStatusClass(status: EscrowStatus): string { getStatusClass(status: EscrowStatus): string {
switch (status) { switch (status) {
@@ -35,7 +35,7 @@ export class UiUtilsService {
} }
/** /**
* Get display label for escrow status * Get display label for church status
*/ */
getEscrowStatusLabel(status: EscrowStatus): string { getEscrowStatusLabel(status: EscrowStatus): string {
switch (status) { switch (status) {
@@ -67,7 +67,7 @@ export class UiUtilsService {
} }
/** /**
* Get icon for escrow status * Get icon for church status
*/ */
getStatusIcon(status: EscrowStatus): SVGIcon | undefined { getStatusIcon(status: EscrowStatus): SVGIcon | undefined {
switch (status) { switch (status) {
@@ -96,7 +96,7 @@ export class UiUtilsService {
return 'role-agent'; return 'role-agent';
case CbAssigneeRole.EscrowOfficer: case CbAssigneeRole.EscrowOfficer:
case CbAssigneeRole.EscrowAssignee: case CbAssigneeRole.EscrowAssignee:
return 'role-escrow'; return 'role-church';
case CbAssigneeRole.LoanBroker: case CbAssigneeRole.LoanBroker:
case CbAssigneeRole.Lender: case CbAssigneeRole.Lender:
return 'role-lender'; return 'role-lender';
+2 -2
View File
@@ -105,7 +105,7 @@
color: #16a34a; color: #16a34a;
} }
&.role-escrow { &.role-church {
background: rgba(245, 158, 11, 0.1); background: rgba(245, 158, 11, 0.1);
color: #d97706; color: #d97706;
} }
@@ -248,7 +248,7 @@
color: #4ade80; color: #4ade80;
} }
&.role-escrow { &.role-church {
background: rgba(245, 158, 11, 0.2); background: rgba(245, 158, 11, 0.2);
color: #fbbf24; color: #fbbf24;
} }
+1 -1
View File
@@ -1,4 +1,4 @@
export const environment = { export const environment = {
production: false, production: false,
apiUrl: 'https://localhost:44302/api' apiUrl: 'http://localhost:42019/api'
}; };
+1 -1
View File
@@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>RBJ Identity</title> <title>ROLCC AC</title>
<base href="/"> <base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="icon" type="image/x-icon" href="favicon.ico">
+1 -1
View File
@@ -2,7 +2,7 @@ export class LocalStorageKeys {
//public static HOLIDAYS = "HOLIDAYS_FOR_DATE_PICKER"; //public static HOLIDAYS = "HOLIDAYS_FOR_DATE_PICKER";
public static NEW_TAB_PROFILE = "LoginPortal_newTabProfile"; public static NEW_TAB_PROFILE = "LoginPortal_newTabProfile";
public static ESCROW_RECALL = "LoginPortal_escrowRecalls"; public static ESCROW_RECALL = "LoginPortal_churchRecalls";
public static SCREEN_HISTORY = "LoginPortal_screenHistory"; public static SCREEN_HISTORY = "LoginPortal_screenHistory";
public static LOGIN_ALL_ACCESS = "LoginPortal_allAccess"; public static LOGIN_ALL_ACCESS = "LoginPortal_allAccess";
public static USER_PREFERENCE = "LoginPortal_userPreference"; public static USER_PREFERENCE = "LoginPortal_userPreference";