Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: fy-select-commute-details business logic #2799

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/core/models/platform/v1/commute-details.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ export interface CommuteDetails {
id?: number;
distance: number;
distance_unit: string;
home_location: Location;
work_location: Location;
home_location: Omit<Location, 'display'>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Backend doesn't allow display key to be sent in the payload and it is also not present in the response

work_location: Omit<Location, 'display'>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { EmployeesService } from './employees.service';

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

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

it('should be created', () => {
expect(service).toBeTruthy();
});
});
19 changes: 19 additions & 0 deletions src/app/core/services/platform/v1/spender/employees.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Injectable } from '@angular/core';
import { SpenderService } from './spender.service';
import { Observable } from 'rxjs';
import { CommuteDetails } from 'src/app/core/models/platform/v1/commute-details.model';

@Injectable({
providedIn: 'root',
})
export class EmployeesService {
constructor(private spenderService: SpenderService) {}

postCommuteDetails(commuteDetails: CommuteDetails): Observable<any> {
return this.spenderService.post('/employees/commute_details', {
data: {
commute_details: commuteDetails,
},
});
}
}
2 changes: 1 addition & 1 deletion src/app/fyle/my-profile/my-profile.page.html
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
</div>
</div>
</div>
<div class="my-profile__card__edit-commute-button">
<div (click)="openCommuteDetailsModal()" class="my-profile__card__edit-commute-button">
<ion-icon
class="my-profile__card__edit-commute-button__icon"
src="../../../assets/svg/edit.svg"
Expand Down
16 changes: 15 additions & 1 deletion src/app/fyle/my-profile/my-profile.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { CommuteDetails } from 'src/app/core/models/platform/v1/commute-details.
import { CommuteDetailsResponse } from 'src/app/core/models/platform/commute-details-response.model';
import { FySelectCommuteDetailsComponent } from 'src/app/shared/components/fy-select-commute-details/fy-select-commute-details.component';
import { ModalPropertiesService } from 'src/app/core/services/modal-properties.service';
import { ToastType } from 'src/app/core/enums/toast-type.enum';

@Component({
selector: 'app-my-profile',
Expand Down Expand Up @@ -212,6 +213,8 @@ export class MyProfilePage {
this.isCommuteDeductionEnabled =
this.orgSettings.commute_deduction_settings?.allowed && this.orgSettings.commute_deduction_settings?.enabled;

this.mileageDistanceUnit = this.orgSettings.mileage?.unit;

if (this.isMileageEnabled && this.isCommuteDeductionEnabled) {
this.setCommuteDetails();
}
Expand Down Expand Up @@ -429,10 +432,21 @@ export class MyProfilePage {
async openCommuteDetailsModal(): Promise<void> {
const commuteDetailsModal = await this.modalController.create({
component: FySelectCommuteDetailsComponent,
componentProps: {},
componentProps: {
distanceUnit: this.mileageDistanceUnit,
existingCommuteDetails: this.commuteDetails,
},
mode: 'ios',
});

await commuteDetailsModal.present();

const { data } = (await commuteDetailsModal.onWillDismiss()) as OverlayResponse<{ action: string }>;

// If the user edited or saved the commute details, refresh the page and show the toast message
if (data.action === 'save') {
this.reset();
this.showToastMessage('Commute details updated successfully', ToastType.SUCCESS);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,87 @@
import { Component, OnInit } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ModalController } from '@ionic/angular';
import { switchMap } from 'rxjs';
import { Location } from 'src/app/core/models/location.model';
import { CommuteDetails } from 'src/app/core/models/platform/v1/commute-details.model';
import { LocationService } from 'src/app/core/services/location.service';
import { EmployeesService } from 'src/app/core/services/platform/v1/spender/employees.service';

@Component({
selector: 'app-fy-select-commute-details',
templateUrl: './fy-select-commute-details.component.html',
styleUrls: ['./fy-select-commute-details.component.scss'],
})
export class FySelectCommuteDetailsComponent implements OnInit {
@Input() distanceUnit: string;

@Input() existingCommuteDetails?: CommuteDetails;

commuteDetails: FormGroup;

constructor(private formBuilder: FormBuilder, private modalController: ModalController) {}
constructor(
private formBuilder: FormBuilder,
private modalController: ModalController,
private locationService: LocationService,
private employeesService: EmployeesService
) {}

ngOnInit(): void {
this.commuteDetails = this.formBuilder.group({
homeLocation: [, Validators.required],
workLocation: [, Validators.required],
});

// In case if spender tries to edit the commute details, prefill form with existing details
if (this.existingCommuteDetails) {
const homeLocation = {
...this.existingCommuteDetails.home_location,
display: this.existingCommuteDetails.home_location.formatted_address,
};
const workLocation = {
...this.existingCommuteDetails.work_location,
display: this.existingCommuteDetails.work_location.formatted_address,
};

this.commuteDetails.controls.homeLocation.patchValue(homeLocation);
this.commuteDetails.controls.workLocation.patchValue(workLocation);
}
}

getCalculatedDistance(distanceResponse: number): number {
const distanceInKM = distanceResponse / 1000;
const finalDistance = this.distanceUnit === 'Miles' ? distanceInKM * 0.6213 : distanceInKM;
return finalDistance;
}

formatLocation(location: Location): Omit<Location, 'display'> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { display, ...formattedLocation } = location;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disabled eslint because display keyword was not used here.
We have to use rest operator to remove display property otherwise backend will throw 400

return formattedLocation;
}

save(): void {
if (this.commuteDetails.valid) {
// TODO - Business logic to go here
const commuteDetailsFormValue = this.commuteDetails.value as { homeLocation: Location; workLocation: Location };

this.locationService
.getDistance(commuteDetailsFormValue.homeLocation, commuteDetailsFormValue.workLocation)
.pipe(
switchMap((distanceResponse) => {
const distance = this.getCalculatedDistance(distanceResponse);
const commuteDetails = {
home_location: this.formatLocation(commuteDetailsFormValue.homeLocation),
work_location: this.formatLocation(commuteDetailsFormValue.workLocation),
distance,
distance_unit: this.distanceUnit.toUpperCase(),
};

return this.employeesService.postCommuteDetails(commuteDetails);
})
)
.subscribe(() => {
this.modalController.dismiss({ action: 'save' });
});
} else {
this.commuteDetails.markAllAsTouched();
}
Expand Down
Loading