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

[TS migration] Migrate remaining libs to TypeScript #32206

Merged
merged 18 commits into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
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
112 changes: 0 additions & 112 deletions src/libs/DistanceRequestUtils.js

This file was deleted.

123 changes: 123 additions & 0 deletions src/libs/DistanceRequestUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import {OnyxEntry} from 'react-native-onyx';
import type {LocaleContextProps} from '@components/LocaleContextProvider';
import CONST from '@src/CONST';
import Policy, {Unit} from '@src/types/onyx/Policy';
import * as CurrencyUtils from './CurrencyUtils';
import * as PolicyUtils from './PolicyUtils';

type DefaultMileageRate = {
rate: number;
currency: string;
unit: Unit;
};

/**
* Retrieves the default mileage rate based on a given policy.
*
* @param policy - The policy from which to extract the default mileage rate.
*
* @returns An object containing the rate and unit for the default mileage or null if not found.
* @returns [rate] - The default rate for the mileage.
* @returns [currency] - The currency associated with the rate.
* @returns [unit] - The unit of measurement for the distance.
*/
function getDefaultMileageRate(policy: OnyxEntry<Policy>): DefaultMileageRate | null {
if (!policy?.customUnits) {
return null;
}

const distanceUnit = Object.values(policy.customUnits).find((unit) => unit.name === CONST.CUSTOM_UNITS.NAME_DISTANCE);
if (!distanceUnit?.rates) {
return null;
}

const distanceRate = Object.values(distanceUnit.rates).find((rate) => rate.name === CONST.CUSTOM_UNITS.DEFAULT_RATE);
if (!distanceRate) {
return null;
}

return {
rate: distanceRate.rate,
currency: distanceRate.currency,
unit: distanceUnit.attributes.unit,
};
}

/**
* Converts a given distance in meters to the specified unit (kilometers or miles).
*
* @param distanceInMeters - The distance in meters to be converted.
* @param unit - The desired unit of conversion, either 'km' for kilometers or 'mi' for miles.
*
* @returns The converted distance in the specified unit.
*/
function convertDistanceUnit(distanceInMeters: number, unit: Unit): number {
const METERS_TO_KM = 0.001; // 1 kilometer is 1000 meters
const METERS_TO_MILES = 0.000621371; // There are approximately 0.000621371 miles in a meter

switch (unit) {
case CONST.CUSTOM_UNITS.DISTANCE_UNIT_KILOMETERS:
return distanceInMeters * METERS_TO_KM;
case CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES:
return distanceInMeters * METERS_TO_MILES;
default:
throw new Error('Unsupported unit. Supported units are "mi" or "km".');
}
}

/**
* @param distanceInMeters Distance traveled
* @param unit Unit that should be used to display the distance
* @returns The distance in requested units, rounded to 2 decimals
*/
function getRoundedDistanceInUnits(distanceInMeters: number, unit: Unit): string {
const convertedDistance = convertDistanceUnit(distanceInMeters, unit);
return convertedDistance.toFixed(2);
}

/**
* @param hasRoute Whether the route exists for the distance request
* @param distanceInMeters Distance traveled
* @param unit Unit that should be used to display the distance
* @param rate Expensable amount allowed per unit
* @param currency The currency associated with the rate
* @param translate Translate function
* @param toLocaleDigit Function to convert to localized digit
* @returns A string that describes the distance traveled and the rate used for expense calculation
*/
function getDistanceMerchant(
hasRoute: boolean,
distanceInMeters: number,
unit: Unit,
rate: number,
currency: string,
translate: LocaleContextProps['translate'],
toLocaleDigit: LocaleContextProps['toLocaleDigit'],
): string {
const distanceInUnits = hasRoute ? getRoundedDistanceInUnits(distanceInMeters, unit) : translate('common.tbd');

const distanceUnit = unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.miles') : translate('common.kilometers');
const singularDistanceUnit = unit === CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES ? translate('common.mile') : translate('common.kilometer');
const unitString = distanceInUnits === '1' ? singularDistanceUnit : distanceUnit;
const ratePerUnit = rate ? PolicyUtils.getUnitRateValue({rate}, toLocaleDigit) : translate('common.tbd');
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const currencySymbol = rate ? CurrencyUtils.getCurrencySymbol(currency) || `${currency} ` : '';

return `${distanceInUnits} ${unitString} @ ${currencySymbol}${ratePerUnit} / ${singularDistanceUnit}`;
}

/**
* Calculates the request amount based on distance, unit, and rate.
*
* @param distance - The distance traveled in meters
* @param unit - The unit of measurement for the distance
* @param rate - Rate used for calculating the request amount
* @returns The computed request amount (rounded) in "cents".
*/
function getDistanceRequestAmount(distance: number, unit: Unit, rate: number): number {
const convertedDistance = convertDistanceUnit(distance, unit);
const roundedDistance = parseFloat(convertedDistance.toFixed(2));
return Math.round(roundedDistance * rate);
}

export default {getDefaultMileageRate, getDistanceMerchant, getDistanceRequestAmount};
28 changes: 0 additions & 28 deletions src/libs/HeaderUtils.js

This file was deleted.

32 changes: 32 additions & 0 deletions src/libs/HeaderUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {OnyxEntry} from 'react-native-onyx';
import {SvgProps} from 'react-native-svg';
import * as Expensicons from '@components/Icon/Expensicons';
import OnyxReport from '@src/types/onyx/Report';
import * as Report from './actions/Report';
import * as Session from './actions/Session';
import * as Localize from './Localize';

type MenuItem = {
icon: string | React.FC<SvgProps>;
text: string;
onSelected: () => void;
};

function getPinMenuItem(report: OnyxEntry<OnyxReport>): MenuItem | undefined {
if (!report) {
return;
}

const isPinned = !!report.isPinned;

return {
icon: Expensicons.Pin,
text: Localize.translateLocal(isPinned ? 'common.pin' : 'common.unPin'),
onSelected: Session.checkIfActionIsAllowed(() => Report.togglePinnedState(report.reportID, isPinned)),
};
}

export {
// eslint-disable-next-line import/prefer-default-export
getPinMenuItem,
};
11 changes: 8 additions & 3 deletions src/libs/NextStepUtils.js → src/libs/NextStepUtils.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import Str from 'expensify-common/lib/str';
import _ from 'underscore';

function parseMessage(messageToParse) {
type Message = {
text: string;
type?: string;
};

function parseMessage(messages: Message[] | undefined) {
let nextStepHTML = '';

_.each(messageToParse, (part) => {
messages?.forEach((part) => {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const tagType = part.type || 'span';
nextStepHTML += `<${tagType}>${Str.safeEscape(part.text)}</${tagType}>`;
});
Expand Down
12 changes: 6 additions & 6 deletions src/libs/getModalState.js → src/libs/getModalState.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import Onyx from 'react-native-onyx';
import Onyx, {OnyxEntry} from 'react-native-onyx';
import ONYXKEYS from '@src/ONYXKEYS';
import Modal from '@src/types/onyx/Modal';

let modalState = {};
let modalState: OnyxEntry<Modal> = {};

Onyx.connect({
key: ONYXKEYS.MODAL,
callback: (val) => {
modalState = val;
callback: (value) => {
modalState = value;
},
});

/**
* Returns the modal state from onyx.
* Note: You should use the HOCs/hooks to get onyx data, instead of using this directly.
* A valid use case to use this is if the value is only needed once for an initial value.
* @returns {Object}
*/
export default function getModalState() {
export default function getModalState(): OnyxEntry<Modal> {
return modalState;
}
Loading
Loading