Skip to content

Commit

Permalink
Merge branch 'main' into jamesdeanexpensify-patch-2
Browse files Browse the repository at this point in the history
  • Loading branch information
MonilBhavsar authored Jun 26, 2024
2 parents 22cc4b0 + 1a1daee commit 2dfd9da
Show file tree
Hide file tree
Showing 69 changed files with 440 additions and 474 deletions.
20 changes: 20 additions & 0 deletions src/components/AddPaymentCard/PaymentCardForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ function PaymentCardForm({

const [isCurrencyModalVisible, setIsCurrencyModalVisible] = useState(false);
const [currency, setCurrency] = useState<keyof typeof CONST.CURRENCY>(CONST.CURRENCY.USD);
const [cardNumber, setCardNumber] = useState('');

const validate = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.ADD_DEBIT_CARD_FORM> => {
const errors = ValidationUtils.getFieldRequiredErrors(values, REQUIRED_FIELDS);
Expand Down Expand Up @@ -181,6 +182,23 @@ function PaymentCardForm({
setIsCurrencyModalVisible(false);
}, []);

const onChangeCardNumber = useCallback((newValue: string) => {
// replace all characters that are not spaces or digits
let validCardNumber = newValue.replace(/[^\d ]/g, '');

// gets only the first 16 digits if the inputted number have more digits than that
validCardNumber = validCardNumber.match(/(?:\d *){1,16}/)?.[0] ?? '';

// add the spacing between every 4 digits
validCardNumber =
validCardNumber
.replace(/ /g, '')
.match(/.{1,4}/g)
?.join(' ') ?? '';

setCardNumber(validCardNumber);
}, []);

if (!shouldShowPaymentCardForm) {
return null;
}
Expand All @@ -204,6 +222,8 @@ function PaymentCardForm({
role={CONST.ROLE.PRESENTATION}
ref={cardNumberRef}
inputMode={CONST.INPUT_MODE.NUMERIC}
onChangeText={onChangeCardNumber}
value={cardNumber}
/>
<InputWrapper
InputComponent={TextInput}
Expand Down
7 changes: 3 additions & 4 deletions src/components/AddPaymentMethodMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type {AnchorPosition} from '@src/styles';
import type {Report, Session} from '@src/types/onyx';
import type AnchorAlignment from '@src/types/utils/AnchorAlignment';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import * as Expensicons from './Icon/Expensicons';
import type {PaymentMethod} from './KYCWall/types';
import PopoverMenu from './PopoverMenu';
Expand All @@ -32,7 +31,7 @@ type AddPaymentMethodMenuProps = AddPaymentMethodMenuOnyxProps & {
onItemSelected: (paymentMethod: PaymentMethod) => void;

/** The IOU/Expense report we are paying */
iouReport?: OnyxEntry<Report> | EmptyObject;
iouReport?: OnyxEntry<Report>;

/** Anchor position for the AddPaymentMenu. */
anchorPosition: AnchorPosition;
Expand Down Expand Up @@ -65,9 +64,9 @@ function AddPaymentMethodMenu({

// Users can choose to pay with business bank account in case of Expense reports or in case of P2P IOU report
// which then starts a bottom up flow and creates a Collect workspace where the payer is an admin and payee is an employee.
const isIOUReport = ReportUtils.isIOUReport(iouReport ?? {});
const isIOUReport = ReportUtils.isIOUReport(iouReport);
const canUseBusinessBankAccount =
ReportUtils.isExpenseReport(iouReport ?? {}) || (isIOUReport && !ReportActionsUtils.hasRequestFromCurrentAccount(iouReport?.reportID ?? '-1', session?.accountID ?? -1));
ReportUtils.isExpenseReport(iouReport) || (isIOUReport && !ReportActionsUtils.hasRequestFromCurrentAccount(iouReport?.reportID ?? '-1', session?.accountID ?? -1));

const canUsePersonalBankAccount = shouldShowPersonalBankAccountOption || isIOUReport;

Expand Down
3 changes: 1 addition & 2 deletions src/components/AttachmentModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import type {TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type ModalType from '@src/types/utils/ModalType';
import AttachmentCarousel from './Attachments/AttachmentCarousel';
Expand Down Expand Up @@ -99,7 +98,7 @@ type AttachmentModalProps = AttachmentModalOnyxProps & {
headerTitle?: string;

/** The report that has this attachment */
report?: OnyxEntry<OnyxTypes.Report> | EmptyObject;
report?: OnyxEntry<OnyxTypes.Report>;

/** The type of the attachment */
type?: ValueOf<typeof CONST.ATTACHMENT_TYPE>;
Expand Down
4 changes: 2 additions & 2 deletions src/components/ConnectionLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ function ConnectionLayout({
}: ConnectionLayoutProps) {
const {translate} = useLocalize();

const policy = PolicyUtils.getPolicy(policyID ?? '');
const isConnectionEmpty = isEmpty(policy.connections?.[connectionName]);
const policy = PolicyUtils.getPolicy(policyID);
const isConnectionEmpty = isEmpty(policy?.connections?.[connectionName]);

const renderSelectionContent = useMemo(
() => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {Report} from '@src/types/onyx';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject} from '@src/types/utils/EmptyObject';

type MentionReportOnyxProps = {
Expand All @@ -27,7 +26,7 @@ type MentionReportRendererProps = MentionReportOnyxProps & CustomRendererProps<T

const removeLeadingLTRAndHash = (value: string) => value.replace(CONST.UNICODE.LTR, '').replace('#', '');

const getMentionDetails = (htmlAttributeReportID: string, currentReport: OnyxEntry<Report> | EmptyObject, reports: OnyxCollection<Report>, tnode: TText | TPhrasing) => {
const getMentionDetails = (htmlAttributeReportID: string, currentReport: OnyxEntry<Report>, reports: OnyxCollection<Report>, tnode: TText | TPhrasing) => {
let reportID: string | undefined;
let mentionDisplayText: string;

Expand Down
3 changes: 1 addition & 2 deletions src/components/KYCWall/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type {Route} from '@src/ROUTES';
import type {Report} from '@src/types/onyx';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import type AnchorAlignment from '@src/types/utils/AnchorAlignment';
import type {EmptyObject} from '@src/types/utils/EmptyObject';

type Source = ValueOf<typeof CONST.KYC_WALL_SOURCE>;

Expand Down Expand Up @@ -45,7 +44,7 @@ type KYCWallProps = {
chatReportID?: string;

/** The IOU/Expense report we are paying */
iouReport?: OnyxEntry<Report> | EmptyObject;
iouReport?: OnyxEntry<Report>;

/** Where the popover should be positioned relative to the anchor points. */
anchorAlignment?: AnchorAlignment;
Expand Down
2 changes: 1 addition & 1 deletion src/components/LHNOptionsList/LHNOptionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ function LHNOptionsList({style, contentContainerStyles, data, onSelectRow, optio
if (ReportActionsUtils.isMoneyRequestAction(lastReportAction)) {
lastReportActionTransactionID = ReportActionsUtils.getOriginalMessage(lastReportAction)?.IOUTransactionID ?? '-1';
}
const lastReportActionTransaction = transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${lastReportActionTransactionID}`] ?? {};
const lastReportActionTransaction = transactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${lastReportActionTransactionID}`];

return (
<OptionRowLHNData
Expand Down
2 changes: 1 addition & 1 deletion src/components/LHNOptionsList/OptionRowLHNData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function OptionRowLHNData({
receiptTransactions,
parentReportAction,
transaction,
lastReportActionTransaction = {},
lastReportActionTransaction,
transactionViolations,
canUseViolations,
...propsToForward
Expand Down
3 changes: 1 addition & 2 deletions src/components/LHNOptionsList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type {ValueOf} from 'type-fest';
import type CONST from '@src/CONST';
import type {OptionData} from '@src/libs/ReportUtils';
import type {Locale, PersonalDetailsList, Policy, Report, ReportAction, ReportActions, Transaction, TransactionViolation} from '@src/types/onyx';
import type {EmptyObject} from '@src/types/utils/EmptyObject';

type OptionMode = ValueOf<typeof CONST.OPTION_MODE>;

Expand Down Expand Up @@ -58,7 +57,7 @@ type OptionRowLHNDataProps = {
transaction: OnyxEntry<Transaction>;

/** The transaction linked to the report's last action */
lastReportActionTransaction?: OnyxEntry<Transaction | EmptyObject>;
lastReportActionTransaction?: OnyxEntry<Transaction>;

/** Whether a report contains a draft */
hasDraftComment: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/components/LocaleContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const LocaleContext = createContext<LocaleContextProps>({
preferredLocale: CONST.LOCALES.DEFAULT,
});

function LocaleContextProvider({preferredLocale, currentUserPersonalDetails = {}, children}: LocaleContextProviderProps) {
function LocaleContextProvider({preferredLocale, currentUserPersonalDetails, children}: LocaleContextProviderProps) {
const locale = preferredLocale ?? CONST.LOCALES.DEFAULT;

const selectedTimezone = useMemo(() => currentUserPersonalDetails?.timezone?.selected, [currentUserPersonalDetails]);
Expand Down
4 changes: 2 additions & 2 deletions src/components/PopoverProvider/index.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {PopoverContextProps, PopoverContextValue} from './types';

const PopoverContext = React.createContext<PopoverContextValue>({
onOpen: () => {},
popover: {},
popover: null,
close: () => {},
isOpen: false,
});
Expand All @@ -13,7 +13,7 @@ function PopoverContextProvider(props: PopoverContextProps) {
() => ({
onOpen: () => {},
close: () => {},
popover: {},
popover: null,
isOpen: false,
}),
[],
Expand Down
2 changes: 1 addition & 1 deletion src/components/PopoverProvider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {AnchorRef, PopoverContextProps, PopoverContextValue} from './types'

const PopoverContext = createContext<PopoverContextValue>({
onOpen: () => {},
popover: {},
popover: null,
close: () => {},
isOpen: false,
});
Expand Down
2 changes: 1 addition & 1 deletion src/components/PopoverProvider/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type PopoverContextProps = {

type PopoverContextValue = {
onOpen?: (popoverParams: AnchorRef) => void;
popover?: AnchorRef | Record<string, never> | null;
popover?: AnchorRef | null;
close: (anchorRef?: RefObject<View | HTMLDivElement | Text>) => void;
isOpen: boolean;
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/Reactions/ReactionTooltipContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type ReactionTooltipContentProps = Pick<WithCurrentUserPersonalDetailsProps, 'cu
accountIDs: number[];
};

function ReactionTooltipContent({accountIDs, currentUserPersonalDetails = {}, emojiCodes, emojiName}: ReactionTooltipContentProps) {
function ReactionTooltipContent({accountIDs, currentUserPersonalDetails, emojiCodes, emojiName}: ReactionTooltipContentProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const users = useMemo(() => PersonalDetailsUtils.getPersonalDetailsByIDs(accountIDs, currentUserPersonalDetails.accountID, true), [currentUserPersonalDetails.accountID, accountIDs]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import truncate from 'lodash/truncate';
import React, {useMemo} from 'react';
import {View} from 'react-native';
import type {GestureResponderEvent} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import Button from '@components/Button';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
Expand Down Expand Up @@ -42,7 +43,6 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import SCREENS from '@src/SCREENS';
import type {OriginalMessageIOU} from '@src/types/onyx/OriginalMessage';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type {MoneyRequestPreviewProps, PendingMessageProps} from './types';

Expand Down Expand Up @@ -247,10 +247,8 @@ function MoneyRequestPreviewContent({
};

const getDisplayDeleteAmountText = (): string => {
const iouOriginalMessage: OriginalMessageIOU | EmptyObject = ReportActionsUtils.isMoneyRequestAction(action) ? ReportActionsUtils.getOriginalMessage(action) ?? {} : {};
const {amount = 0, currency = CONST.CURRENCY.USD} = iouOriginalMessage;

return CurrencyUtils.convertToDisplayString(amount, currency);
const iouOriginalMessage: OnyxEntry<OriginalMessageIOU> = ReportActionsUtils.isMoneyRequestAction(action) ? ReportActionsUtils.getOriginalMessage(action) ?? undefined : undefined;
return CurrencyUtils.convertToDisplayString(iouOriginalMessage?.amount, iouOriginalMessage?.currency);
};

const displayAmount = isDeleted ? getDisplayDeleteAmountText() : getDisplayAmountText();
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReportActionItem/ReportPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ function ReportPreview({
if (ReportUtils.hasHeldExpenses(iouReport?.reportID)) {
setIsHoldMenuVisible(true);
} else {
IOU.approveMoneyRequest(iouReport ?? {}, true);
IOU.approveMoneyRequest(iouReport, true);
}
};

Expand Down
4 changes: 2 additions & 2 deletions src/components/SelectionScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ function SelectionScreen({
}: SelectionScreenProps) {
const {translate} = useLocalize();

const policy = PolicyUtils.getPolicy(policyID ?? '');
const isConnectionEmpty = isEmpty(policy.connections?.[connectionName]);
const policy = PolicyUtils.getPolicy(policyID);
const isConnectionEmpty = isEmpty(policy?.connections?.[connectionName]);

return (
<AccessOrNotFoundWrapper
Expand Down
13 changes: 6 additions & 7 deletions src/components/SettlementButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import type {ButtonSizeValue} from '@src/styles/utils/types';
import type {LastPaymentMethod, Policy, Report} from '@src/types/onyx';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import type AnchorAlignment from '@src/types/utils/AnchorAlignment';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import ButtonWithDropdownMenu from './ButtonWithDropdownMenu';
import type {PaymentType} from './ButtonWithDropdownMenu/types';
Expand Down Expand Up @@ -55,7 +54,7 @@ type SettlementButtonProps = SettlementButtonOnyxProps & {
chatReportID?: string;

/** The IOU/Expense report we are paying */
iouReport?: OnyxEntry<Report> | EmptyObject;
iouReport?: OnyxEntry<Report>;

/** Should we show the payment options? */
shouldHidePaymentOptions?: boolean;
Expand Down Expand Up @@ -121,9 +120,9 @@ function SettlementButton({
chatReportID = '',
currency = CONST.CURRENCY.USD,
enablePaymentsRoute,
// The "iouReport" and "nvpLastPaymentMethod" objects needs to be stable to prevent the "useMemo"
// hook from being recreated unnecessarily, hence the use of CONST.EMPTY_ARRAY and CONST.EMPTY_OBJECT
iouReport = CONST.EMPTY_OBJECT,
iouReport,
// The "nvpLastPaymentMethod" object needs to be stable to prevent the "useMemo"
// hook from being recreated unnecessarily, hence the use of CONST.EMPTY_OBJECT
nvpLastPaymentMethod = CONST.EMPTY_OBJECT,
isDisabled = false,
isLoading = false,
Expand All @@ -148,7 +147,7 @@ function SettlementButton({
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || -1}`);
const isInvoiceReport = (!isEmptyObject(iouReport) && ReportUtils.isInvoiceReport(iouReport)) || false;
const isPaidGroupPolicy = ReportUtils.isPaidGroupPolicyExpenseChat(chatReport);
const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport as OnyxEntry<Report>));
const shouldShowPaywithExpensifyOption = !isPaidGroupPolicy || (!shouldHidePaymentOptions && ReportUtils.isPayer(session, iouReport));
const shouldShowPayElsewhereOption = (!isPaidGroupPolicy || policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL) && !isInvoiceReport;
const paymentButtonOptions = useMemo(() => {
const buttonOptions = [];
Expand Down Expand Up @@ -238,7 +237,7 @@ function SettlementButton({
if (confirmApproval) {
confirmApproval();
} else {
IOU.approveMoneyRequest(iouReport ?? {});
IOU.approveMoneyRequest(iouReport);
}
return;
}
Expand Down
6 changes: 2 additions & 4 deletions src/components/withCurrentUserPersonalDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'
import getComponentDisplayName from '@libs/getComponentDisplayName';
import type {PersonalDetails} from '@src/types/onyx';

type CurrentUserPersonalDetails = PersonalDetails | Record<string, never>;

type HOCProps = {
currentUserPersonalDetails: CurrentUserPersonalDetails;
currentUserPersonalDetails: PersonalDetails;
};

type WithCurrentUserPersonalDetailsProps = HOCProps;
Expand All @@ -32,4 +30,4 @@ export default function <TProps extends WithCurrentUserPersonalDetailsProps, TRe
return React.forwardRef(WithCurrentUserPersonalDetails);
}

export type {WithCurrentUserPersonalDetailsProps, CurrentUserPersonalDetails};
export type {WithCurrentUserPersonalDetailsProps};
10 changes: 2 additions & 8 deletions src/hooks/useCurrentUserPersonalDetails.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import {useMemo} from 'react';
import {usePersonalDetails, useSession} from '@components/OnyxProvider';
import CONST from '@src/CONST';
import type {PersonalDetails} from '@src/types/onyx';

type CurrentUserPersonalDetails = PersonalDetails | Record<string, never>;

function useCurrentUserPersonalDetails() {
const session = useSession();
const personalDetails = usePersonalDetails() ?? CONST.EMPTY_OBJECT;
const personalDetails = usePersonalDetails();
const accountID = session?.accountID ?? -1;
const accountPersonalDetails = personalDetails?.[accountID];
const currentUserPersonalDetails: CurrentUserPersonalDetails = useMemo(
() => (accountPersonalDetails ? {...accountPersonalDetails, accountID} : {}) as CurrentUserPersonalDetails,
[accountPersonalDetails, accountID],
);
const currentUserPersonalDetails: PersonalDetails = useMemo(() => ({...accountPersonalDetails, accountID}), [accountPersonalDetails, accountID]);

return currentUserPersonalDetails;
}
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useKeyboardShortcut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type KeyboardShortcutConfig = {
* Register a keyboard shortcut handler.
* Recommendation: To ensure stability, wrap the `callback` function with the useCallback hook before using it with this hook.
*/
export default function useKeyboardShortcut(shortcut: Shortcut, callback: (e?: GestureResponderEvent | KeyboardEvent) => void, config: KeyboardShortcutConfig | Record<string, never> = {}) {
export default function useKeyboardShortcut(shortcut: Shortcut, callback: (e?: GestureResponderEvent | KeyboardEvent) => void, config: KeyboardShortcutConfig = {}) {
const {
captureOnInputs = true,
shouldBubble = false,
Expand Down
Loading

0 comments on commit 2dfd9da

Please sign in to comment.