Skip to content

Commit

Permalink
feat: new integrations landing page (/landing_v2) (#1151)
Browse files Browse the repository at this point in the history
* feat: create new landing page and add header and tab switcher

* feat: new app tile structure + remove extra content (#1140)

* feat: new app tile structure + remove extra content

* feat: responsive grid layout + new tile layout (#1141)

* feat: responsive grid layout + new tile layout

* 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)
  • Loading branch information
1 parent 668b549 commit 6265028
Show file tree
Hide file tree
Showing 17 changed files with 654 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/app/core/models/enum/enum.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export enum InAppIntegration {
QBD_DIRECT = 'QuickBooks Connector'
}

export type IntegrationAppKey = keyof typeof InAppIntegration;

export enum ToastSeverity {
SUCCESS = 'success',
ERROR = 'error',
Expand Down Expand Up @@ -900,7 +902,8 @@ export enum SizeOption {
export enum ThemeOption {
BRAND = 'brand',
LIGHT = 'light',
DARK = 'dark'
DARK = 'dark',
SUCCESS = 'success'
}

export enum QBDPreRequisiteState {
Expand Down
11 changes: 11 additions & 0 deletions src/app/core/models/integrations/integrations.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import { AccountingIntegrationApp, AppUrl, ClickEvent, InAppIntegration, IntegrationView } from "../enum/enum.model";

export type Integration = {
id: number;
org_id: string;
org_name: string;
tpa_id: string;
tpa_name: string;
type: string;
is_active: boolean;
is_beta: boolean;
}

export type IntegrationsView = {
[IntegrationView.ACCOUNTING]: boolean,
[IntegrationView.ALL]: boolean,
Expand Down
16 changes: 16 additions & 0 deletions src/app/core/services/common/integrations.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { IntegrationsService } from './integrations.service';

xdescribe('IntegrationsService', () => {
let service: IntegrationsService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(IntegrationsService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
22 changes: 22 additions & 0 deletions src/app/core/services/common/integrations.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Injectable } from '@angular/core';
import { AppUrl } from '../../models/enum/enum.model';
import { ApiService } from './api.service';
import { HelperService } from './helper.service';
import { Observable } from 'rxjs';
import { Integration } from '../../models/integrations/integrations.model';

@Injectable({
providedIn: 'root'
})
export class IntegrationsService {
constructor(
private apiService: ApiService,
private helper: HelperService
) {
}

getIntegrations(): Observable<Integration[]> {
this.helper.setBaseApiURL(AppUrl.INTEGRATION);
return this.apiService.get(`/integrations/`, {});
}
}
5 changes: 5 additions & 0 deletions src/app/integrations/integrations-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { IntegrationsComponent } from './integrations.component';
import { LandingComponent } from './landing/landing.component';
import { LandingV2Component } from './landing-v2/landing-v2.component';

const routes: Routes = [
{
Expand All @@ -12,6 +13,10 @@ const routes: Routes = [
path: 'landing',
component: LandingComponent
},
{
path: 'landing_v2',
component: LandingV2Component
},
{
path: 'bamboo_hr',
loadChildren: () => import('./bamboo-hr/bamboo-hr.module').then(m => m.BambooHrModule)
Expand Down
4 changes: 3 additions & 1 deletion src/app/integrations/integrations.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { SharedModule } from '../shared/shared.module';
import { Sage300Component } from './sage300/sage300.component';
import { XeroComponent } from './xero/xero.component';
import { TravelperkComponent } from './travelperk/travelperk.component';
import { LandingV2Component } from './landing-v2/landing-v2.component';

@NgModule({
declarations: [
Expand All @@ -18,7 +19,8 @@ import { TravelperkComponent } from './travelperk/travelperk.component';
QbdComponent,
Sage300Component,
XeroComponent,
TravelperkComponent
TravelperkComponent,
LandingV2Component
],
imports: [
CommonModule,
Expand Down
239 changes: 239 additions & 0 deletions src/app/integrations/landing-v2/landing-v2.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
<div class="tw-text-slightly-normal-text-color tw-py-8 tw-px-6">
<div class="landing-v2--container">
<header>
<h3 class="landing-v2--section-heading">
List of integrations
</h3>

<p class="landing-v2--section-caption">
If your company uses any of the applications listed below, you can easily integrate them with Fyle.
<br>
Need an integration we don't support yet? Let us know at <a class="tw-text-link-primary"
href="mailto:[email protected]">support{{'@'}}fylehq.com</a>
</p>
</header>
<div *ngIf="!exposeC1Apps" class="tw-flex tw-text-14-px tw-border-y tw-border-separator">
<div class="landing-v2--tab" [ngClass]="{'tw-text-menu-inactive-text-color': !integrationTabs.ALL}"
(click)="switchView(IntegrationsView.ALL)">
All
<p *ngIf="integrationTabs.ALL" class="landing-v2--active-tag"></p>
</div>
<div class="landing-v2--tab" [ngClass]="{'tw-text-menu-inactive-text-color': !integrationTabs.ACCOUNTING}"
(click)="switchView(IntegrationsView.ACCOUNTING)">
Accounting
<p *ngIf="integrationTabs.ACCOUNTING" class="landing-v2--active-tag"></p>
</div>
<div class="landing-v2--tab" [ngClass]="{'tw-text-menu-inactive-text-color': !integrationTabs.HRMS}"
(click)="switchView(IntegrationsView.HRMS)">
HRMS
<p *ngIf="integrationTabs.HRMS" class="landing-v2--active-tag"></p>
</div>
<div *ngIf="org.allow_travelperk" class="landing-v2--tab"
[ngClass]="{'tw-text-menu-inactive-text-color': !integrationTabs.TRAVEL}"
(click)="switchView(IntegrationsView.TRAVEL)">
Travel
<p *ngIf="integrationTabs.TRAVEL" class="landing-v2--active-tag"></p>
</div>
</div>

<div
class="tw-grid tw-grid-cols-2 md:tw-grid-cols-3 lg:tw-grid-cols-4 xl:tw-grid-cols-5 tw-gap-4 tw-justify-items-stretch">
<div *ngIf="isAppShown('NETSUITE')">
<div class="landing-v2--accounting-app"
(click)="openAccountingIntegrationApp(AccountingIntegrationApp.NETSUITE)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/netsuite-logo-new.png" />
@if (isAppConnected('NETSUITE')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<div>
<span class="landing-v2--accounting-app-name">
NetSuite
</span>
<span class="landing-v2--accounting-app-type">
Accounting
</span>
</div>
</div>
</div>
<div *ngIf="isAppShown('INTACCT')" class="landing-v2--accounting-app"
(click)="openAccountingIntegrationApp(AccountingIntegrationApp.SAGE_INTACCT)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/intacct-logo-new.png" />
@if (isAppConnected('INTACCT')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<div>
<span class="landing-v2--accounting-app-name">
Sage Intacct
</span>
<span class="landing-v2--accounting-app-type">
Accounting
</span>
</div>
</div>
<div *ngIf="isAppShown('QBO')" class="landing-v2--accounting-app"
(click)="openAccountingIntegrationApp(AccountingIntegrationApp.QBO)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/quickbooks-logo.png" class="!tw-h-[30.7px]" />
@if (isAppConnected('QBO')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<div>
<span class="landing-v2--accounting-app-name">
QuickBooks Online
</span>
<span class="landing-v2--accounting-app-type">
Accounting
</span>
</div>
</div>
<div *ngIf="isAppShown('XERO')" class="landing-v2--accounting-app"
(click)="openAccountingIntegrationApp(AccountingIntegrationApp.XERO)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/xero-logo-new.png" />
@if (isAppConnected('XERO')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<div>
<span class="landing-v2--accounting-app-name">
Xero
</span>
<span class="landing-v2--accounting-app-type">
Accounting
</span>
</div>
</div>
<div *ngIf="isAppShown('QBD')" class="landing-v2--accounting-app"
(click)="openInAppIntegration(InAppIntegration.QBD)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/quickbooks-logo.png" class="!tw-h-[30.7px]" />
@if (isAppConnected('QBD')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<div>
<span class="landing-v2--accounting-app-name">
QuickBooks Desktop (IIF)
</span>
<span class="landing-v2--accounting-app-type">
Accounting
</span>
</div>
</div>
<!-- Direct -->
<div *ngIf="isAppShown('QBD_DIRECT')" class="landing-v2--accounting-app"
(click)="openInAppIntegration(InAppIntegration.QBD_DIRECT)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/quickbooks-logo.png" class="!tw-h-[30.7px]" />
@if (isAppConnected('QBD_DIRECT')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<span class="landing-v2--accounting-app-name tw-items-center tw-gap-4">
<div>
QuickBooks Desktop (Web Connector)
<div class="landing-v2--accounting-app-type">Accounting</div>
</div>
<app-badge [theme]="ThemeOption.DARK" text="Beta"></app-badge>
</span>
</div>
<div *ngIf="isAppShown('SAGE300')" class="landing-v2--accounting-app"
(click)="openInAppIntegration(InAppIntegration.SAGE300)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/sage300-logo.png" class="tw-py-[4px]" />
@if (isAppConnected('SAGE300')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<span class="landing-v2--accounting-app-name tw-items-center tw-gap-4">
<div>
Sage 300 CRE
<div class="landing-v2--accounting-app-type">Accounting</div>
</div>
<app-badge *ngIf="!orgsToHideSage300BetaBadge.includes(org.fyle_org_id)" [theme]="ThemeOption.DARK"
text="Beta"></app-badge>
</span>
</div>
<div *ngIf="isAppShown('BUSINESS_CENTRAL')" class="landing-v2--accounting-app"
(click)="openInAppIntegration(InAppIntegration.BUSINESS_CENTRAL)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/BusinessCentral-logo.svg" />
@if (isAppConnected('BUSINESS_CENTRAL')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<span class="landing-v2--accounting-app-name tw-items-center tw-gap-4">
<div>
Dynamics 365 Business Central
<div class="landing-v2--accounting-app-type">Accounting</div>
</div>
<app-badge *ngIf="!orgsToHideBusinessCentralBetaBadge.includes(org.fyle_org_id)"
[theme]="ThemeOption.DARK" text="Beta"></app-badge>
</span>
</div>

<div *ngIf="isAppShown('BAMBOO_HR')">
<div class="landing-v2--accounting-app" (click)="openInAppIntegration(InAppIntegration.BAMBOO_HR)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/bamboo-hr-logo.png" />
@if (isAppConnected('BAMBOO_HR')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<div>
<span class="landing-v2--accounting-app-name">
BambooHR
</span>
<span class="landing-v2--accounting-app-type">
HRMS
</span>
</div>
</div>
</div>

<div *ngIf="isAppShown('TRAVELPERK')">
<div class="landing-v2--accounting-app" (click)="openInAppIntegration(InAppIntegration.TRAVELPERK)">
<div class="tw-flex tw-justify-between tw-items-center">
<img src="assets/logos/travelperk-logo.png" class="tw-py-[5px]" />
@if (isAppConnected('TRAVELPERK')) {
<app-badge text="Connected" [theme]="ThemeOption.SUCCESS"></app-badge>
} @else {
<button class="btn-connect">Connect</button>
}
</div>
<div>
<span class="landing-v2--accounting-app-name">
TravelPerk
</span>
<span class="landing-v2--accounting-app-type">
Travel
</span>
</div>
</div>
</div>
</div>
</div>
</div>
Loading

0 comments on commit 6265028

Please sign in to comment.