Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
796e69d
Revert "[CP Staging] Revert "Remove Review button from Inbox and Repo…
nkdengineer Nov 7, 2025
1bfd773
resolve conflict
nkdengineer Nov 10, 2025
51c085e
fix test
nkdengineer Nov 10, 2025
5bbd9a1
fix style issue
nkdengineer Nov 10, 2025
957dc5b
fix submit button in the case held expense
nkdengineer Nov 10, 2025
18c261b
fix submit button in the case held expense
nkdengineer Nov 10, 2025
8b2b439
run prettier
nkdengineer Nov 10, 2025
762f7d5
resolve conflict
nkdengineer Nov 13, 2025
10dda32
show view button for approve/pay with held expense
nkdengineer Nov 13, 2025
1bf3dc8
fix prettier
nkdengineer Nov 13, 2025
5e57c1a
Merge branch 'main' into revert-74396-cmartins-revert-nkdengineer/fix…
nkdengineer Nov 18, 2025
239fed1
Merge branch 'main' into revert-74396-cmartins-revert-nkdengineer/fix…
nkdengineer Nov 19, 2025
0ec168e
fix animation on mounted
nkdengineer Nov 19, 2025
1cb0eec
Merge branch 'main' into revert-74396-cmartins-revert-nkdengineer/fix…
nkdengineer Nov 20, 2025
0176563
Merge branch 'main' into revert-74396-cmartins-revert-nkdengineer/fix…
nkdengineer Nov 21, 2025
b044a22
resolve conflict
nkdengineer Nov 25, 2025
ba5eb19
fix ts error
nkdengineer Nov 25, 2025
5e471d1
Merge branch 'main' into revert-74396-cmartins-revert-nkdengineer/fix…
nkdengineer Nov 27, 2025
20c290a
implement violation message to new UI
nkdengineer Nov 27, 2025
2ceec40
resolve conflict
nkdengineer Dec 2, 2025
9f8cbab
Merge branch 'main' into revert-74396-cmartins-revert-nkdengineer/fix…
nkdengineer Dec 2, 2025
755d896
update getAction function
nkdengineer Dec 2, 2025
378ef3d
fix new function error
nkdengineer Dec 2, 2025
2b95c62
update new UI
nkdengineer Dec 2, 2025
0b3fae1
fix test
nkdengineer Dec 2, 2025
0b7bad3
fix eslint
nkdengineer Dec 2, 2025
6323f27
fix eslint
nkdengineer Dec 2, 2025
e50c6b9
update dependency
nkdengineer Dec 2, 2025
71707aa
remove Expensicons
nkdengineer Dec 2, 2025
4eb55a9
Merge branch 'main' into revert-74396-cmartins-revert-nkdengineer/fix…
nkdengineer Dec 3, 2025
ac0b6d1
use new method
nkdengineer Dec 3, 2025
9ac1249
Merge branch 'main' into revert-74396-cmartins-revert-nkdengineer/fix…
nkdengineer Dec 3, 2025
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
2 changes: 0 additions & 2 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1161,7 +1161,6 @@ const CONST = {
REPORT_PREVIEW_ACTIONS: {
VIEW: 'view',
ADD_EXPENSE: 'addExpense',
REVIEW: 'review',
SUBMIT: 'submit',
APPROVE: 'approve',
PAY: 'pay',
Expand Down Expand Up @@ -6621,7 +6620,6 @@ const CONST = {
},
ACTION_TYPES: {
VIEW: 'view',
REVIEW: 'review',
SUBMIT: 'submit',
APPROVE: 'approve',
PAY: 'pay',
Expand Down
42 changes: 39 additions & 3 deletions src/components/AnimatedCollapsible/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import type {StyleProp, ViewStyle} from 'react-native';
import Animated, {useAnimatedStyle, useDerivedValue, useSharedValue, withTiming} from 'react-native-reanimated';
import {scheduleOnRN} from 'react-native-worklets';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import {easing} from '@components/Modal/ReanimatedModal/utils';
import {PressableWithFeedback} from '@components/Pressable';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import CONST from '@src/CONST';
Expand All @@ -22,6 +22,9 @@ type AnimatedCollapsibleProps = {
/** Header content to display above the collapsible content */
header: ReactNode;

/** Description content to display below the header */
description?: ReactNode;

/** Duration of expansion animation */
duration?: number;

Expand Down Expand Up @@ -54,6 +57,7 @@ function AnimatedCollapsible({
isExpanded,
children,
header,
description,
duration = 300,
style,
headerStyle,
Expand All @@ -66,10 +70,11 @@ function AnimatedCollapsible({
}: AnimatedCollapsibleProps) {
const theme = useTheme();
const styles = useThemeStyles();
const expensifyIcons = useMemoizedLazyExpensifyIcons(['UpArrow', 'DownArrow'] as const);
const contentHeight = useSharedValue(0);
const descriptionHeight = useSharedValue(0);
const hasExpanded = useSharedValue(isExpanded);
const [isRendered, setIsRendered] = React.useState(isExpanded);

useEffect(() => {
hasExpanded.set(isExpanded);
if (isExpanded) {
Expand Down Expand Up @@ -100,6 +105,22 @@ function AnimatedCollapsible({
return withTiming(hasExpanded.get() ? 1 : 0, {duration, easing});
});

const descriptionOpacity = useDerivedValue(() => {
return withTiming(!hasExpanded.get() ? 1 : 0, {duration, easing});
});

const descriptionAnimatedHeight = useDerivedValue(() => {
return withTiming(!isExpanded ? descriptionHeight.get() : 0, {duration, easing});
});

const descriptionAnimatedStyle = useAnimatedStyle(() => {
return {
opacity: descriptionOpacity.get(),
// The row is collapsed by default, so we don't need to animate the height when it's not expanded
height: isRendered ? descriptionAnimatedHeight.get() : undefined,
};
}, [isRendered]);

const contentAnimatedStyle = useAnimatedStyle(() => {
return {
height: animatedHeight.get(),
Expand All @@ -121,7 +142,7 @@ function AnimatedCollapsible({
>
{({hovered}) => (
<Icon
src={isExpanded ? Expensicons.UpArrow : Expensicons.DownArrow}
src={isExpanded ? expensifyIcons.UpArrow : expensifyIcons.DownArrow}
fill={theme.icon}
additionalStyles={!hovered && styles.opacitySemiTransparent}
small
Expand All @@ -130,6 +151,21 @@ function AnimatedCollapsible({
</PressableWithFeedback>
)}
</View>
<Animated.View style={descriptionAnimatedStyle}>
{!!description && !isExpanded && (
<Animated.View
style={isRendered && styles.stickToTop}
onLayout={(e) => {
const height = e.nativeEvent.layout.height;
if (height) {
descriptionHeight.set(height);
}
}}
>
{description}
</Animated.View>
)}
</Animated.View>
<Animated.View style={[contentAnimatedStyle, contentStyle]}>
{isExpanded || isRendered ? (
<Animated.View
Expand Down
2 changes: 1 addition & 1 deletion src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ function MoneyReportHeader({
formattedAmount: getTotalAmountForIOUReportPreviewButton(moneyRequestReport, policy, actionType),
});

const {formattedAmount: totalAmount} = hasOnlyHeldExpenses ? getAmount(CONST.REPORT.REPORT_PREVIEW_ACTIONS.REVIEW) : getAmount(CONST.REPORT.PRIMARY_ACTIONS.PAY);
const {formattedAmount: totalAmount} = getAmount(CONST.REPORT.PRIMARY_ACTIONS.PAY);

const paymentButtonOptions = usePaymentOptions({
currency: moneyRequestReport?.currency,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu';
import ConfirmModal from '@components/ConfirmModal';
import {DelegateNoAccessContext} from '@components/DelegateNoAccessModalProvider';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import type {PaymentMethod} from '@components/KYCWall/types';
import MoneyReportHeaderStatusBarSkeleton from '@components/MoneyReportHeaderStatusBarSkeleton';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
Expand All @@ -24,6 +23,7 @@ import AnimatedSettlementButton from '@components/SettlementButton/AnimatedSettl
import {showContextMenuForReport} from '@components/ShowContextMenuContext';
import Text from '@components/Text';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
Expand All @@ -33,7 +33,6 @@ import usePermissions from '@hooks/usePermissions';
import usePolicy from '@hooks/usePolicy';
import useReportIsArchived from '@hooks/useReportIsArchived';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStrictPolicyRules from '@hooks/useStrictPolicyRules';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
Expand All @@ -44,12 +43,12 @@ import {getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportU
import Navigation from '@libs/Navigation/Navigation';
import Performance from '@libs/Performance';
import {getConnectedIntegration, hasDynamicExternalWorkflow} from '@libs/PolicyUtils';
import {getReportPreviewAction} from '@libs/ReportPreviewActionUtils';
import {getInvoicePayerName} from '@libs/ReportNameUtils';
import getReportPreviewAction from '@libs/ReportPreviewActionUtils';
import {
areAllRequestsBeingSmartScanned as areAllRequestsBeingSmartScannedReportUtils,
getAddExpenseDropdownOptions,
getDisplayNameForParticipant,
getInvoicePayerName,
getMoneyReportPreviewName,
getMoneyRequestSpendBreakdown,
getNonHeldAndFullAmount,
Expand Down Expand Up @@ -108,7 +107,6 @@ function MoneyRequestReportPreviewContent({
invoiceReceiverPolicy,
iouReport,
transactions,
violations,
policy,
invoiceReceiverPersonalDetail,
lastTransactionViolations,
Expand Down Expand Up @@ -140,9 +138,9 @@ function MoneyRequestReportPreviewContent({
const StyleUtils = useStyleUtils();
const {translate, formatPhoneNumber} = useLocalize();
const {isOffline} = useNetwork();
const {areStrictPolicyRulesEnabled} = useStrictPolicyRules();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const currentUserDetails = useCurrentUserPersonalDetails();
const expensifyIcons = useMemoizedLazyExpensifyIcons(['ArrowRight', 'BackArrow'] as const);

const {areAllRequestsBeingSmartScanned, hasNonReimbursableTransactions} = useMemo(
() => ({
Expand Down Expand Up @@ -492,9 +490,7 @@ function MoneyRequestReportPreviewContent({

const reportPreviewAction = useMemo(() => {
return getReportPreviewAction(
violations,
isIouReportArchived || isChatReportArchived,
currentUserDetails.email ?? '',
currentUserDetails.accountID,
iouReport,
policy,
Expand All @@ -503,21 +499,17 @@ function MoneyRequestReportPreviewContent({
isPaidAnimationRunning,
isApprovedAnimationRunning,
isSubmittingAnimationRunning,
areStrictPolicyRulesEnabled,
);
}, [
isPaidAnimationRunning,
isApprovedAnimationRunning,
isSubmittingAnimationRunning,
violations,
iouReport,
policy,
transactions,
isIouReportArchived,
invoiceReceiverPolicy,
isChatReportArchived,
areStrictPolicyRulesEnabled,
currentUserDetails.email,
currentUserDetails.accountID,
]);

Expand Down Expand Up @@ -596,15 +588,6 @@ function MoneyRequestReportPreviewContent({
}}
/>
) : null,
[CONST.REPORT.REPORT_PREVIEW_ACTIONS.REVIEW]: (
<Button
icon={Expensicons.DotIndicator}
iconFill={theme.danger}
iconHoverFill={theme.danger}
text={translate('common.review')}
onPress={() => openReportFromPreview()}
/>
),
[CONST.REPORT.REPORT_PREVIEW_ACTIONS.VIEW]: (
<Button
text={translate('common.view')}
Expand Down Expand Up @@ -737,7 +720,7 @@ function MoneyRequestReportPreviewContent({
disabledStyle={[styles.cursorDefault, styles.buttonOpacityDisabled]}
>
<Icon
src={Expensicons.BackArrow}
src={expensifyIcons.BackArrow}
small
fill={theme.icon}
isButtonIcon
Expand All @@ -757,7 +740,7 @@ function MoneyRequestReportPreviewContent({
disabledStyle={[styles.cursorDefault, styles.buttonOpacityDisabled]}
>
<Icon
src={Expensicons.ArrowRight}
src={expensifyIcons.ArrowRight}
small
fill={theme.icon}
isButtonIcon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function MoneyRequestReportPreview({
const invoiceReceiverPolicy =
policies?.[`${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : undefined}`];
const invoiceReceiverPersonalDetail = chatReport?.invoiceReceiver && 'accountID' in chatReport.invoiceReceiver ? personalDetailsList?.[chatReport.invoiceReceiver.accountID] : null;
const [iouReport, transactions, violations] = useReportWithTransactionsAndViolations(iouReportID);
const [iouReport, transactions] = useReportWithTransactionsAndViolations(iouReportID);
const policy = usePolicy(policyID);
const lastTransaction = transactions?.at(0);
const lastTransactionViolations = useTransactionViolations(lastTransaction?.transactionID);
Expand Down Expand Up @@ -154,7 +154,6 @@ function MoneyRequestReportPreview({
onPaymentOptionsShow={onPaymentOptionsShow}
onPaymentOptionsHide={onPaymentOptionsHide}
transactions={transactions}
violations={violations}
policy={policy}
invoiceReceiverPersonalDetail={invoiceReceiverPersonalDetail}
invoiceReceiverPolicy={invoiceReceiverPolicy}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import type {TransactionPreviewStyleType} from '@components/ReportActionItem/TransactionPreview/types';
import type {ForwardedFSClassProps} from '@libs/Fullstory/types';
import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import type {PersonalDetails, Policy, Report, ReportAction, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
import type {PersonalDetails, Policy, Report, ReportAction, Transaction, TransactionViolations} from '@src/types/onyx';

type TransactionPreviewCarouselStyle = {
[key in keyof TransactionPreviewStyleType]: number;
Expand Down Expand Up @@ -75,7 +75,6 @@ type MoneyRequestReportPreviewContentOnyxProps = {
invoiceReceiverPolicy: OnyxEntry<Policy>;
iouReport: OnyxEntry<Report>;
transactions: Transaction[];
violations: OnyxCollection<TransactionViolation[]>;
policy: OnyxEntry<Policy>;
invoiceReceiverPersonalDetail: OnyxEntry<PersonalDetails> | null;
lastTransactionViolations: TransactionViolations;
Expand Down
11 changes: 4 additions & 7 deletions src/components/SelectionListWithSections/Search/ActionCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import {View} from 'react-native';
import type {ValueOf} from 'type-fest';
import Badge from '@components/Badge';
import Button from '@components/Button';
import * as Expensicons from '@components/Icon/Expensicons';
import type {PaymentMethod} from '@components/KYCWall/types';
import {SearchScopeProvider} from '@components/Search/SearchScopeProvider';
import SettlementButton from '@components/SettlementButton';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
Expand All @@ -28,7 +28,6 @@ import type {SearchTransactionAction} from '@src/types/onyx/SearchResults';

const actionTranslationsMap: Record<SearchTransactionAction, TranslationPaths> = {
view: 'common.view',
review: 'common.review',
submit: 'common.submit',
approve: 'iou.approve',
pay: 'iou.pay',
Expand Down Expand Up @@ -73,6 +72,7 @@ function ActionCell({
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {isOffline} = useNetwork();
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Checkmark', 'Checkbox'] as const);
const [iouReport, transactions] = useReportWithTransactionsAndViolations(reportID);
const policy = usePolicy(policyID);
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`, {canBeMissing: true});
Expand Down Expand Up @@ -103,7 +103,7 @@ function ActionCell({
>
<Badge
text={text}
icon={action === CONST.SEARCH.ACTION_TYPES.DONE ? Expensicons.Checkbox : Expensicons.Checkmark}
icon={action === CONST.SEARCH.ACTION_TYPES.DONE ? expensifyIcons.Checkbox : expensifyIcons.Checkmark}
badgeStyles={[
styles.ml0,
styles.ph2,
Expand All @@ -122,7 +122,7 @@ function ActionCell({
);
}

if (action === CONST.SEARCH.ACTION_TYPES.VIEW || action === CONST.SEARCH.ACTION_TYPES.REVIEW || shouldUseViewAction || isChildListItem) {
if (action === CONST.SEARCH.ACTION_TYPES.VIEW || shouldUseViewAction || isChildListItem) {
const buttonInnerStyles = isSelected ? styles.buttonDefaultSelected : {};

return isLargeScreenWidth ? (
Expand All @@ -138,9 +138,6 @@ function ActionCell({
innerStyles={buttonInnerStyles}
link={isChildListItem}
shouldUseDefaultHover={!isChildListItem}
icon={!isChildListItem && action === CONST.SEARCH.ACTION_TYPES.REVIEW ? Expensicons.DotIndicator : undefined}
iconFill={theme.danger}
iconHoverFill={theme.dangerHover}
isNested
/>
) : null;
Expand Down
Loading
Loading