Skip to content

Commit 6eaa285

Browse files
feat: add CTA and shadow animation on tile hover (#1142)
* fix: update images * feat: add CTA and shadow animation on tile hover * feat: UI for the new "Conencted" badge (#1144) * feat: UI for the new "Conencted" badge * feat: fetch data from integrations API and show connected apps (#1143) * feat: fetch data from integrations API and show connected apps * fix: update route name and keep `exposeC1Apps` (#1145) * fix: update route name and keep `exposeC1Apps` * fix: use new logos in landing-v2 only Use original images everywhere else. * fix: incorrect URL for `/integrations` call and rendering errors (#1149)
1 parent 8039c21 commit 6eaa285

File tree

15 files changed

+185
-15
lines changed

15 files changed

+185
-15
lines changed

src/app/core/models/enum/enum.model.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,8 @@ export enum SizeOption {
902902
export enum ThemeOption {
903903
BRAND = 'brand',
904904
LIGHT = 'light',
905-
DARK = 'dark'
905+
DARK = 'dark',
906+
SUCCESS = 'success'
906907
}
907908

908909
export enum QBDPreRequisiteState {

src/app/core/models/integrations/integrations.model.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
import { AccountingIntegrationApp, AppUrl, ClickEvent, InAppIntegration, IntegrationView } from "../enum/enum.model";
22

3+
export type Integration = {
4+
id: number;
5+
org_id: string;
6+
org_name: string;
7+
tpa_id: string;
8+
tpa_name: string;
9+
type: string;
10+
is_active: boolean;
11+
is_beta: boolean;
12+
}
13+
314
export type IntegrationsView = {
415
[IntegrationView.ACCOUNTING]: boolean,
516
[IntegrationView.ALL]: boolean,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { TestBed } from '@angular/core/testing';
2+
3+
import { IntegrationsService } from './integrations.service';
4+
5+
xdescribe('IntegrationsService', () => {
6+
let service: IntegrationsService;
7+
8+
beforeEach(() => {
9+
TestBed.configureTestingModule({});
10+
service = TestBed.inject(IntegrationsService);
11+
});
12+
13+
it('should be created', () => {
14+
expect(service).toBeTruthy();
15+
});
16+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Injectable } from '@angular/core';
2+
import { AppUrl } from '../../models/enum/enum.model';
3+
import { ApiService } from './api.service';
4+
import { HelperService } from './helper.service';
5+
import { Observable } from 'rxjs';
6+
import { Integration } from '../../models/integrations/integrations.model';
7+
8+
@Injectable({
9+
providedIn: 'root'
10+
})
11+
export class IntegrationsService {
12+
constructor(
13+
private apiService: ApiService,
14+
private helper: HelperService
15+
) {
16+
}
17+
18+
getIntegrations(): Observable<Integration[]> {
19+
this.helper.setBaseApiURL(AppUrl.INTEGRATION);
20+
return this.apiService.get(`/integrations/`, {});
21+
}
22+
}

src/app/integrations/integrations-routing.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const routes: Routes = [
1414
component: LandingComponent
1515
},
1616
{
17-
path: 'landing-v2',
17+
path: 'landing_v2',
1818
component: LandingV2Component
1919
},
2020
{

src/app/integrations/landing-v2/landing-v2.component.html

Lines changed: 81 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ <h3 class="landing-v2--section-heading">
1212
href="mailto:[email protected]">support{{'@'}}fylehq.com</a>
1313
</p>
1414
</header>
15-
<div class="tw-flex tw-text-14-px tw-border-y tw-border-separator">
15+
<div *ngIf="!exposeC1Apps" class="tw-flex tw-text-14-px tw-border-y tw-border-separator">
1616
<div class="landing-v2--tab" [ngClass]="{'tw-text-menu-inactive-text-color': !integrationTabs.ALL}"
1717
(click)="switchView(IntegrationsView.ALL)">
1818
All
@@ -41,7 +41,14 @@ <h3 class="landing-v2--section-heading">
4141
<div *ngIf="isAppShown('NETSUITE')">
4242
<div class="landing-v2--accounting-app"
4343
(click)="openAccountingIntegrationApp(AccountingIntegrationApp.NETSUITE)">
44-
<img src="assets/logos/netsuite-logo.png" />
44+
<div class="tw-flex tw-justify-between tw-items-center">
45+
<img src="assets/logos/netsuite-logo-new.png" />
46+
@if (isAppConnected('NETSUITE')) {
47+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
48+
} @else {
49+
<button class="btn-connect">Connect</button>
50+
}
51+
</div>
4552
<div>
4653
<span class="landing-v2--accounting-app-name">
4754
NetSuite
@@ -54,7 +61,14 @@ <h3 class="landing-v2--section-heading">
5461
</div>
5562
<div *ngIf="isAppShown('INTACCT')" class="landing-v2--accounting-app"
5663
(click)="openAccountingIntegrationApp(AccountingIntegrationApp.SAGE_INTACCT)">
57-
<img src="assets/logos/intacct-logo.png" />
64+
<div class="tw-flex tw-justify-between tw-items-center">
65+
<img src="assets/logos/intacct-logo-new.png" />
66+
@if (isAppConnected('INTACCT')) {
67+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
68+
} @else {
69+
<button class="btn-connect">Connect</button>
70+
}
71+
</div>
5872
<div>
5973
<span class="landing-v2--accounting-app-name">
6074
Sage Intacct
@@ -66,7 +80,14 @@ <h3 class="landing-v2--section-heading">
6680
</div>
6781
<div *ngIf="isAppShown('QBO')" class="landing-v2--accounting-app"
6882
(click)="openAccountingIntegrationApp(AccountingIntegrationApp.QBO)">
69-
<img src="assets/logos/quickbooks-logo.png" />
83+
<div class="tw-flex tw-justify-between tw-items-center">
84+
<img src="assets/logos/quickbooks-logo.png" class="!tw-h-[30.7px]" />
85+
@if (isAppConnected('QBO')) {
86+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
87+
} @else {
88+
<button class="btn-connect">Connect</button>
89+
}
90+
</div>
7091
<div>
7192
<span class="landing-v2--accounting-app-name">
7293
QuickBooks Online
@@ -78,7 +99,14 @@ <h3 class="landing-v2--section-heading">
7899
</div>
79100
<div *ngIf="isAppShown('XERO')" class="landing-v2--accounting-app"
80101
(click)="openAccountingIntegrationApp(AccountingIntegrationApp.XERO)">
81-
<img src="assets/logos/xero-logo.png" />
102+
<div class="tw-flex tw-justify-between tw-items-center">
103+
<img src="assets/logos/xero-logo-new.png" />
104+
@if (isAppConnected('XERO')) {
105+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
106+
} @else {
107+
<button class="btn-connect">Connect</button>
108+
}
109+
</div>
82110
<div>
83111
<span class="landing-v2--accounting-app-name">
84112
Xero
@@ -90,7 +118,14 @@ <h3 class="landing-v2--section-heading">
90118
</div>
91119
<div *ngIf="isAppShown('QBD')" class="landing-v2--accounting-app"
92120
(click)="openInAppIntegration(InAppIntegration.QBD)">
93-
<img src="assets/logos/quickbooks-logo.png" />
121+
<div class="tw-flex tw-justify-between tw-items-center">
122+
<img src="assets/logos/quickbooks-logo.png" class="!tw-h-[30.7px]" />
123+
@if (isAppConnected('QBD')) {
124+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
125+
} @else {
126+
<button class="btn-connect">Connect</button>
127+
}
128+
</div>
94129
<div>
95130
<span class="landing-v2--accounting-app-name">
96131
QuickBooks Desktop (IIF)
@@ -103,7 +138,14 @@ <h3 class="landing-v2--section-heading">
103138
<!-- Direct -->
104139
<div *ngIf="isAppShown('QBD_DIRECT')" class="landing-v2--accounting-app"
105140
(click)="openInAppIntegration(InAppIntegration.QBD_DIRECT)">
106-
<img src="assets/logos/quickbooks-logo.png" />
141+
<div class="tw-flex tw-justify-between tw-items-center">
142+
<img src="assets/logos/quickbooks-logo.png" class="!tw-h-[30.7px]" />
143+
@if (isAppConnected('QBD_DIRECT')) {
144+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
145+
} @else {
146+
<button class="btn-connect">Connect</button>
147+
}
148+
</div>
107149
<span class="landing-v2--accounting-app-name tw-items-center tw-gap-4">
108150
<div>
109151
QuickBooks Desktop (Web Connector)
@@ -114,7 +156,14 @@ <h3 class="landing-v2--section-heading">
114156
</div>
115157
<div *ngIf="isAppShown('SAGE300')" class="landing-v2--accounting-app"
116158
(click)="openInAppIntegration(InAppIntegration.SAGE300)">
117-
<img src="assets/logos/sage300-logo.svg" />
159+
<div class="tw-flex tw-justify-between tw-items-center">
160+
<img src="assets/logos/sage300-logo.png" class="tw-py-[4px]" />
161+
@if (isAppConnected('SAGE300')) {
162+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
163+
} @else {
164+
<button class="btn-connect">Connect</button>
165+
}
166+
</div>
118167
<span class="landing-v2--accounting-app-name tw-items-center tw-gap-4">
119168
<div>
120169
Sage 300 CRE
@@ -126,7 +175,14 @@ <h3 class="landing-v2--section-heading">
126175
</div>
127176
<div *ngIf="isAppShown('BUSINESS_CENTRAL')" class="landing-v2--accounting-app"
128177
(click)="openInAppIntegration(InAppIntegration.BUSINESS_CENTRAL)">
129-
<img src="assets/logos/BusinessCentral-logo.svg" />
178+
<div class="tw-flex tw-justify-between tw-items-center">
179+
<img src="assets/logos/BusinessCentral-logo.svg" />
180+
@if (isAppConnected('BUSINESS_CENTRAL')) {
181+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
182+
} @else {
183+
<button class="btn-connect">Connect</button>
184+
}
185+
</div>
130186
<span class="landing-v2--accounting-app-name tw-items-center tw-gap-4">
131187
<div>
132188
Dynamics 365 Business Central
@@ -139,7 +195,14 @@ <h3 class="landing-v2--section-heading">
139195

140196
<div *ngIf="isAppShown('BAMBOO_HR')">
141197
<div class="landing-v2--accounting-app" (click)="openInAppIntegration(InAppIntegration.BAMBOO_HR)">
142-
<img src="assets/logos/bamboo-hr-logo.svg" />
198+
<div class="tw-flex tw-justify-between tw-items-center">
199+
<img src="assets/logos/bamboo-hr-logo.png" />
200+
@if (isAppConnected('BAMBOO_HR')) {
201+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
202+
} @else {
203+
<button class="btn-connect">Connect</button>
204+
}
205+
</div>
143206
<div>
144207
<span class="landing-v2--accounting-app-name">
145208
BambooHR
@@ -153,7 +216,14 @@ <h3 class="landing-v2--section-heading">
153216

154217
<div *ngIf="isAppShown('TRAVELPERK')">
155218
<div class="landing-v2--accounting-app" (click)="openInAppIntegration(InAppIntegration.TRAVELPERK)">
156-
<img src="assets/logos/travelperk-logo.svg" />
219+
<div class="tw-flex tw-justify-between tw-items-center">
220+
<img src="assets/logos/travelperk-logo.png" class="tw-py-[5px]" />
221+
@if (isAppConnected('TRAVELPERK')) {
222+
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
223+
} @else {
224+
<button class="btn-connect">Connect</button>
225+
}
226+
</div>
157227
<div>
158228
<span class="landing-v2--accounting-app-name">
159229
TravelPerk

src/app/integrations/landing-v2/landing-v2.component.scss

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,16 @@
2323
}
2424

2525
&--accounting-app {
26-
@apply tw-h-full tw-flex tw-flex-col tw-p-4 tw-gap-4 tw-items-start tw-justify-evenly tw-cursor-pointer tw-rounded-8-px tw-border tw-border-separator tw-bg-white;
26+
@apply tw-h-full tw-flex tw-flex-col tw-p-4 tw-gap-4 tw-justify-evenly tw-cursor-pointer tw-rounded-8-px tw-border tw-border-separator tw-bg-white;
27+
@apply tw-transition-shadow;
2728

2829
img {
2930
@apply tw-h-[40px];
3031
}
32+
33+
.btn-connect {
34+
@apply tw-text-14-px tw-hidden;
35+
}
3136
}
3237

3338
&--accounting-app-name {
@@ -57,4 +62,11 @@
5762
&--other-integration-app {
5863
@apply tw-flex tw-items-center tw-justify-center;
5964
}
65+
}
66+
67+
.landing-v2--accounting-app:hover {
68+
box-shadow: 0px 4px 4px 0px rgba(44, 48, 78, 0.10);
69+
.btn-connect {
70+
@apply tw-block;
71+
}
6072
}

src/app/integrations/landing-v2/landing-v2.component.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { QboAuthService } from 'src/app/core/services/qbo/qbo-core/qbo-auth.serv
1515
import { XeroAuthService } from 'src/app/core/services/xero/xero-core/xero-auth.service';
1616
import { exposeAppConfig } from 'src/app/branding/expose-app-config';
1717
import { NetsuiteAuthService } from 'src/app/core/services/netsuite/netsuite-core/netsuite-auth.service';
18+
import { IntegrationsService } from 'src/app/core/services/common/integrations.service';
1819

1920
@Component({
2021
selector: 'app-landing-v2',
@@ -31,6 +32,10 @@ export class LandingV2Component implements OnInit {
3132

3233
org: Org = this.orgService.getCachedOrg();
3334

35+
private connectedApps: IntegrationAppKey[];
36+
37+
readonly exposeC1Apps = brandingFeatureConfig.exposeC1Apps;
38+
3439
private readonly integrationTabsInitialState: IntegrationsView = {
3540
[IntegrationView.ACCOUNTING]: false,
3641
[IntegrationView.HRMS]: false,
@@ -72,6 +77,19 @@ export class LandingV2Component implements OnInit {
7277
[AccountingIntegrationApp.XERO]: '/integrations/xero'
7378
};
7479

80+
private readonly tpaNameToIntegrationKeyMap: Record<string, IntegrationAppKey> = {
81+
'Fyle Netsuite Integration': 'NETSUITE',
82+
'Fyle Sage Intacct Integration': 'INTACCT',
83+
'Fyle Quickbooks Integration': 'QBO',
84+
'Fyle Xero Integration': 'XERO',
85+
'Fyle Quickbooks Desktop (IIF) Integration': 'QBD',
86+
'Fyle Quickbooks Desktop Integration': 'QBD_DIRECT',
87+
'Fyle Sage 300 Integration': 'SAGE300',
88+
'Fyle Business Central Integration': 'BUSINESS_CENTRAL',
89+
'Fyle TravelPerk Integration': 'TRAVELPERK',
90+
'Fyle BambooHR Integration': 'BAMBOO_HR'
91+
};
92+
7593
readonly brandingConfig = brandingConfig;
7694

7795
readonly isINCluster = this.storageService.get('cluster-domain')?.includes('in1');
@@ -100,7 +118,8 @@ export class LandingV2Component implements OnInit {
100118
private router: Router,
101119
private siAuthService: SiAuthService,
102120
private storageService: StorageService,
103-
private orgService: OrgService
121+
private orgService: OrgService,
122+
private integrationService: IntegrationsService
104123
) { }
105124

106125

@@ -146,6 +165,10 @@ export class LandingV2Component implements OnInit {
146165
return false;
147166
}
148167

168+
isAppConnected(appKey: IntegrationAppKey) {
169+
return this.connectedApps?.includes(appKey);
170+
}
171+
149172
openAccountingIntegrationApp(accountingIntegrationApp: AccountingIntegrationApp): void {
150173

151174
// For local dev, we perform auth via loginWithRefreshToken on Fyle login redirect (/auth/redirect)
@@ -215,7 +238,17 @@ export class LandingV2Component implements OnInit {
215238
});
216239
}
217240

241+
private storeConnectedApps() {
242+
this.integrationService.getIntegrations().subscribe(integrations => {
243+
const tpaNames = integrations.map(integration => integration.tpa_name);
244+
const connectedApps = tpaNames.map(tpaName => this.tpaNameToIntegrationKeyMap[tpaName]);
245+
246+
this.connectedApps = connectedApps;
247+
});
248+
}
249+
218250
ngOnInit(): void {
219251
this.setupLoginWatcher();
252+
this.storeConnectedApps();
220253
}
221254
}

src/app/shared/components/core/badge/badge.component.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@
2222
@apply tw-text-badge-dark-text-color;
2323
}
2424

25+
.theme-success {
26+
@apply tw-bg-bg-success-light tw-border tw-border-solid tw-border-border-success-light;
27+
@apply tw-text-text-success;
28+
}
29+
2530
.size-large {
2631
@apply tw-min-w-24-px;
2732
@apply tw-min-h-24-px;
159 KB
Loading

0 commit comments

Comments
 (0)