Skip to content

Attendee Tracking: Created AttendeeSelectionPage #48008

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
93edf8b
Enable name in the filter function
zfurtak Jul 23, 2024
a53c355
Blank commit
zfurtak Jul 23, 2024
34d58c6
Merge branch 'main' into @zfurtak/atendee-tracking-enable-names-selec…
zfurtak Jul 23, 2024
fc456f3
Added shouldAcceptName prop
zfurtak Jul 25, 2024
7b8649a
Merge branch 'main' into @zfurtak/enables-plain-string
zfurtak Aug 14, 2024
cb2e4f0
Merge branch 'main' into screen
robertKozik Aug 22, 2024
d2bf2d5
create new route for attendee screen
robertKozik Aug 26, 2024
a355c43
create attendee screen + selector
robertKozik Aug 26, 2024
ae38408
WIP: temporary access attendee from merchant option
robertKozik Aug 26, 2024
d1eb72c
Added translations
zfurtak Aug 26, 2024
79d0d00
Merge branch 'main' into attendee-47171
zfurtak Aug 26, 2024
1c248a1
Changed type to Attendee
zfurtak Aug 26, 2024
a6ae379
Merge branch 'main' into attendee-47171
zfurtak Aug 27, 2024
1d91de1
WIP
zfurtak Aug 28, 2024
923df86
Fix TS and Lint
filip-solecki Aug 28, 2024
21d8a88
Fix not existing user selection
filip-solecki Aug 28, 2024
da74588
Merge branch 'main' into attendee-47171
zfurtak Aug 28, 2024
db64c0a
Merge branch 'attendee-47171' of https://github.com/software-mansion-…
zfurtak Aug 28, 2024
2318920
Adjusted requestMoney function
zfurtak Aug 29, 2024
ea44c0c
Added saving attendees
zfurtak Aug 29, 2024
2d52cec
Merge branch 'main' into attendee-47171
zfurtak Aug 29, 2024
0716dff
Adjusted submitting expense with attendees
zfurtak Aug 29, 2024
56e365d
Fixed ts and lint errors
zfurtak Aug 29, 2024
29e2bfd
Added per person to attendee title
zfurtak Aug 29, 2024
d001c91
Added recents attendees
zfurtak Aug 30, 2024
a8e6354
Adjusted to review
zfurtak Aug 30, 2024
b4ee548
Merge branch 'main' into attendee-47171
zfurtak Sep 1, 2024
f88175a
Merge branch 'main' into attendee-47171
zfurtak Sep 1, 2024
6de6e0d
Adjusted to review
zfurtak Sep 1, 2024
dd1fb0a
Update src/libs/OptionsListUtils.ts
filip-solecki Sep 2, 2024
4668611
Use recentAttendees instead of recentReports and add creator to Recen…
filip-solecki Sep 3, 2024
a8eda3b
Fix creator selecting and unselecting
filip-solecki Sep 3, 2024
97dfef4
Set max recent attendees value to 5
filip-solecki Sep 4, 2024
b048b80
Move rest of recents to top of contacts
filip-solecki Sep 4, 2024
dadb5c2
Merge branch 'main' into attendee-47171
zfurtak Sep 4, 2024
50c006e
Merge branch 'attendee-47171' of https://github.com/software-mansion-…
zfurtak Sep 4, 2024
105bd76
Fixed React Compiler issue
zfurtak Sep 4, 2024
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
5 changes: 5 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {ValueOf} from 'type-fest';
import type CONST from './CONST';
import type * as FormTypes from './types/form';
import type * as OnyxTypes from './types/onyx';
import type {Attendee} from './types/onyx/IOU';
import type Onboarding from './types/onyx/Onboarding';
import type AssertTypesEqual from './types/utils/AssertTypesEqual';
import type DeepValueOf from './types/utils/DeepValueOf';
Expand Down Expand Up @@ -115,6 +116,9 @@ const ONYXKEYS = {
/** Boolean flag only true when first set */
NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER: 'nvp_isFirstTimeNewExpensifyUser',

/** This NVP contains list of at most 5 recent attendees */
NVP_RECENT_ATTENDEES: 'nvp_expensify_recentAttendees',

/** This NVP contains information about whether the onboarding flow was completed or not */
NVP_ONBOARDING: 'nvp_onboarding',

Expand Down Expand Up @@ -828,6 +832,7 @@ type OnyxValuesMapping = {
// The value of this nvp is a string representation of the date when the block expires, or an empty string if the user is not blocked
[ONYXKEYS.NVP_BLOCKED_FROM_CHAT]: string;
[ONYXKEYS.NVP_PRIVATE_PUSH_NOTIFICATION_ID]: string;
[ONYXKEYS.NVP_RECENT_ATTENDEES]: Attendee[];
[ONYXKEYS.NVP_TRY_FOCUS_MODE]: boolean;
[ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION]: boolean;
[ONYXKEYS.FOCUS_MODE_NOTIFICATION]: boolean;
Expand Down
5 changes: 5 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,11 @@ const ROUTES = {
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '', reportActionID?: string) =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo),
},
MONEY_REQUEST_ATTENDEE: {
route: ':action/:iouType/attendees/:transactionID/:reportID',
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>
getUrlWithBackToParam(`${action as string}/${iouType as string}/attendees/${transactionID}/${reportID}`, backTo),
},
SETTINGS_CATEGORIES_ROOT: {
route: 'settings/:policyID/categories',
getRoute: (policyID: string, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/categories`, backTo),
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ const SCREENS = {
EDIT_WAYPOINT: 'Money_Request_Edit_Waypoint',
RECEIPT: 'Money_Request_Receipt',
STATE_SELECTOR: 'Money_Request_State_Selector',
STEP_ATTENDEES: 'Money_Request_Attendee',
},

TRANSACTION_DUPLICATE: {
Expand Down
16 changes: 14 additions & 2 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {Route} from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type {Participant} from '@src/types/onyx/IOU';
import type {Attendee, Participant} from '@src/types/onyx/IOU';
import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import type {SplitShares} from '@src/types/onyx/Transaction';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
Expand Down Expand Up @@ -89,6 +89,9 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps &
/** IOU amount */
iouAmount: number;

/** IOU attendees list */
iouAttendees?: Attendee[];

/** IOU comment */
iouComment?: string;

Expand Down Expand Up @@ -196,6 +199,7 @@ function MoneyRequestConfirmationList({
policyID = '',
reportID = '',
receiptPath = '',
iouAttendees,
iouComment,
receiptFilename = '',
iouCreated,
Expand Down Expand Up @@ -296,7 +300,12 @@ function MoneyRequestConfirmationList({
const formattedAmount = isDistanceRequestWithPendingRoute
? ''
: CurrencyUtils.convertToDisplayString(shouldCalculateDistanceAmount ? distanceRequestAmount : iouAmount, isDistanceRequest ? currency : iouCurrencyCode);

const formattedAmountPerAttendee = isDistanceRequestWithPendingRoute
? ''
: CurrencyUtils.convertToDisplayString(
(shouldCalculateDistanceAmount ? distanceRequestAmount : iouAmount) / (iouAttendees?.length && iouAttendees.length > 0 ? iouAttendees.length : 1),
isDistanceRequest ? currency : iouCurrencyCode,
);
const isFocused = useIsFocused();
const [formError, debouncedFormError, setFormError] = useDebouncedState<TranslationPaths | ''>('');

Expand Down Expand Up @@ -903,8 +912,10 @@ function MoneyRequestConfirmationList({
didConfirm={didConfirm}
distance={distance}
formattedAmount={formattedAmount}
formattedAmountPerAttendee={formattedAmountPerAttendee}
formError={formError}
hasRoute={hasRoute}
iouAttendees={iouAttendees}
iouCategory={iouCategory}
iouComment={iouComment}
iouCreated={iouCreated}
Expand Down Expand Up @@ -1017,6 +1028,7 @@ export default withOnyx<MoneyRequestConfirmationListProps, MoneyRequestConfirmat
prevProps.policyID === nextProps.policyID &&
prevProps.reportID === nextProps.reportID &&
prevProps.receiptPath === nextProps.receiptPath &&
prevProps.iouAttendees === nextProps.iouAttendees &&
prevProps.iouComment === nextProps.iouComment &&
prevProps.receiptFilename === nextProps.receiptFilename &&
prevProps.iouCreated === nextProps.iouCreated &&
Expand Down
30 changes: 29 additions & 1 deletion src/components/MoneyRequestConfirmationListFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import type {IOUAction, IOUType} from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type * as OnyxTypes from '@src/types/onyx';
import type {Participant} from '@src/types/onyx/IOU';
import type {Attendee, Participant} from '@src/types/onyx/IOU';
import type {Unit} from '@src/types/onyx/Policy';
import ConfirmedRoute from './ConfirmedRoute';
import MentionReportContext from './HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext';
Expand Down Expand Up @@ -56,6 +56,9 @@ type MoneyRequestConfirmationListFooterProps = {
/** The formatted amount of the transaction */
formattedAmount: string;

/** The formatted amount of the transaction per 1 attendee */
formattedAmountPerAttendee: string;

/** The error message for the form */
formError: string;

Expand All @@ -65,6 +68,9 @@ type MoneyRequestConfirmationListFooterProps = {
/** The category of the IOU */
iouCategory: string;

/** The list of attendees */
iouAttendees: Attendee[] | undefined;

/** The comment of the IOU */
iouComment: string | undefined;

Expand Down Expand Up @@ -175,8 +181,10 @@ function MoneyRequestConfirmationListFooter({
didConfirm,
distance,
formattedAmount,
formattedAmountPerAttendee,
formError,
hasRoute,
iouAttendees,
iouCategory,
iouComment,
iouCreated,
Expand Down Expand Up @@ -225,6 +233,7 @@ function MoneyRequestConfirmationListFooter({

const shouldShowTags = useMemo(() => isPolicyExpenseChat && OptionsListUtils.hasEnabledTags(policyTagLists), [isPolicyExpenseChat, policyTagLists]);
const isMultilevelTags = useMemo(() => PolicyUtils.isMultiLevelTags(policyTags), [policyTags]);
const shouldShowAttendees = useMemo(() => !!policy?.id && (policy?.type === CONST.POLICY.TYPE.CORPORATE || policy?.type === CONST.POLICY.TYPE.TEAM), [policy?.id, policy?.type]);

const senderWorkspace = useMemo(() => {
const senderWorkspaceParticipant = selectedParticipants.find((participant) => participant.isSender);
Expand Down Expand Up @@ -502,6 +511,25 @@ function MoneyRequestConfirmationListFooter({
shouldShow: shouldShowTax,
isSupplementary: true,
},
{
item: (
<MenuItemWithTopDescription
key="attendees"
shouldShowRightIcon
title={iouAttendees?.map((item) => item.displayName ?? item.login).join(', ')}
description={`${translate('iou.attendees')} ${
iouAttendees?.length && iouAttendees.length > 1 ? `\u00B7 ${formattedAmountPerAttendee} ${translate('common.perPerson')}` : ''
}`}
style={[styles.moneyRequestMenuItem]}
titleStyle={styles.flex1}
onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_ATTENDEE.getRoute(action, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams()))}
interactive
shouldRenderAsHTML
/>
),
shouldShow: shouldShowAttendees,
isSupplementary: true,
},
{
item: (
<View style={[styles.flexRow, styles.justifyContentBetween, styles.alignItemsCenter, styles.ml5, styles.mr8, styles.optionRow]}>
Expand Down
4 changes: 4 additions & 0 deletions src/components/SelectionList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {BrickRoad} from '@libs/WorkspacesSettingsUtils';
// eslint-disable-next-line no-restricted-imports
import type CursorStyles from '@styles/utils/cursor/types';
import type CONST from '@src/CONST';
import type {Attendee} from '@src/types/onyx/IOU';
import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon';
import type {SearchPersonalDetails, SearchReport, SearchTransaction} from '@src/types/onyx/SearchResults';
import type {ReceiptErrors} from '@src/types/onyx/Transaction';
Expand Down Expand Up @@ -195,6 +196,9 @@ type TransactionListItemType = ListItem &

/** Key used internally by React */
keyForList: string;

/** Attendees in the transaction */
attendees?: Attendee[];
};

type ReportListItemType = ListItem &
Expand Down
3 changes: 3 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ export default {
firstName: 'First name',
lastName: 'Last name',
addCardTermsOfService: 'Expensify Terms of Service',
perPerson: 'per person',
phone: 'Phone',
phoneNumber: 'Phone number',
phoneNumberPlaceholder: '(xxx) xxx-xxxx',
Expand Down Expand Up @@ -872,6 +873,7 @@ export default {
atLeastTwoDifferentWaypoints: 'Please enter at least two different addresses.',
splitExpenseMultipleParticipantsErrorMessage: 'An expense cannot be split between a workspace and other members. Please update your selection.',
invalidMerchant: 'Please enter a correct merchant.',
atLeastOneAttendee: 'At least one attendee must be selected',
},
waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) => `started settling up. Payment is on hold until ${submitterDisplayName} enables their wallet.`,
enableWallet: 'Enable wallet',
Expand Down Expand Up @@ -923,6 +925,7 @@ export default {
bookingPendingDescription: "This booking is pending because it hasn't been paid yet.",
bookingArchived: 'This booking is archived',
bookingArchivedDescription: 'This booking is archived because the trip date has passed. Add an expense for the final amount if needed.',
attendees: 'Attendees',
},
notificationPreferencesPage: {
header: 'Notification preferences',
Expand Down
3 changes: 3 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export default {
not: 'No',
privacyPolicy: 'la Política de Privacidad de Expensify',
addCardTermsOfService: 'Términos de Servicio',
perPerson: 'por persona',
signIn: 'Conectarse',
signInWithGoogle: 'Iniciar sesión con Google',
signInWithApple: 'Iniciar sesión con Apple',
Expand Down Expand Up @@ -869,6 +870,7 @@ export default {
atLeastTwoDifferentWaypoints: 'Por favor, introduce al menos dos direcciones diferentes.',
splitExpenseMultipleParticipantsErrorMessage: 'Solo puedes dividir un gasto entre un único espacio de trabajo o con miembros individuales. Por favor, actualiza tu selección.',
invalidMerchant: 'Por favor, introduce un comerciante correcto.',
atLeastOneAttendee: 'Debe seleccionarse al menos un asistente',
},
waitingOnEnabledWallet: ({submitterDisplayName}: WaitingOnBankAccountParams) => `inició el pago, pero no se procesará hasta que ${submitterDisplayName} active su billetera`,
enableWallet: 'Habilitar billetera',
Expand Down Expand Up @@ -928,6 +930,7 @@ export default {
bookingPendingDescription: 'Esta reserva está pendiente porque aún no se ha pagado.',
bookingArchived: 'Esta reserva está archivada',
bookingArchivedDescription: 'Esta reserva está archivada porque la fecha del viaje ha pasado. Agregue un gasto por el monto final si es necesario.',
attendees: 'Asistentes',
},
notificationPreferencesPage: {
header: 'Preferencias de avisos',
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ const WRITE_COMMANDS = {
DELETE_REPORT_FIELD: 'RemoveReportField',
SET_REPORT_NAME: 'RenameReport',
COMPLETE_SPLIT_BILL: 'CompleteSplitBill',
UPDATE_MONEY_REQUEST_ATTENDEES: 'UpdateMoneyRequestAttendees',
UPDATE_MONEY_REQUEST_DATE: 'UpdateMoneyRequestDate',
UPDATE_MONEY_REQUEST_BILLABLE: 'UpdateMoneyRequestBillable',
UPDATE_MONEY_REQUEST_MERCHANT: 'UpdateMoneyRequestMerchant',
Expand Down Expand Up @@ -512,6 +513,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.SET_REPORT_NAME]: Parameters.SetReportNameParams;
[WRITE_COMMANDS.DELETE_REPORT_FIELD]: Parameters.DeleteReportFieldParams;
[WRITE_COMMANDS.COMPLETE_SPLIT_BILL]: Parameters.CompleteSplitBillParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_ATTENDEES]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DATE]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_MERCHANT]: Parameters.UpdateMoneyRequestParams;
[WRITE_COMMANDS.UPDATE_MONEY_REQUEST_BILLABLE]: Parameters.UpdateMoneyRequestParams;
Expand Down
21 changes: 20 additions & 1 deletion src/libs/IOUUtils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type {IOUAction, IOUType} from '@src/CONST';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';
import type {OnyxInputOrEntry, Report, Transaction} from '@src/types/onyx';
import type {OnyxInputOrEntry, PersonalDetails, Report, Transaction} from '@src/types/onyx';
import type {Attendee} from '@src/types/onyx/IOU';
import type {IOURequestType} from './actions/IOU';
import * as CurrencyUtils from './CurrencyUtils';
import Navigation from './Navigation/Navigation';
Expand Down Expand Up @@ -160,6 +161,23 @@ function shouldUseTransactionDraft(action: IOUAction | undefined) {
return action === CONST.IOU.ACTION.CREATE || isMovingTransactionFromTrackExpense(action);
}

function formatCurrentUserToAttendee(currentUser?: PersonalDetails, reportID?: string) {
if (!currentUser) {
return;
}
const initialAttendee: Attendee = {
email: currentUser?.login,
displayName: currentUser.displayName,
avatarUrl: currentUser.avatar?.toString(),
accountID: currentUser.accountID,
text: currentUser.login,
selected: true,
reportID,
};

return [initialAttendee];
}

export {
calculateAmount,
insertTagIntoTransactionTagsString,
Expand All @@ -170,4 +188,5 @@ export {
navigateToStartMoneyRequestStep,
updateIOUOwnerAndTotal,
temporary_isValidMoneyRequestType,
formatCurrentUserToAttendee,
};
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator<MoneyRequestNa
[SCREENS.IOU_SEND.ADD_DEBIT_CARD]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/AddDebitCardPage').default,
[SCREENS.IOU_SEND.ENABLE_PAYMENTS]: () => require<ReactComponentModule>('../../../../pages/EnablePayments/EnablePaymentsPage').default,
[SCREENS.MONEY_REQUEST.STATE_SELECTOR]: () => require<ReactComponentModule>('../../../../pages/settings/Profile/PersonalDetails/StateSelectionPage').default,
[SCREENS.MONEY_REQUEST.STEP_ATTENDEES]: () => require<ReactComponentModule>('../../../../pages/iou/request/step/IOURequestStepAttendees').default,
});

const TravelModalStackNavigator = createModalStackNavigator<TravelNavigatorParamList>({
Expand Down
1 change: 1 addition & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,7 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: ROUTES.MONEY_REQUEST_STEP_TAX_RATE.route,
[SCREENS.MONEY_REQUEST.STATE_SELECTOR]: {path: ROUTES.MONEY_REQUEST_STATE_SELECTOR.route, exact: true},
[SCREENS.MONEY_REQUEST.STEP_SPLIT_PAYER]: ROUTES.MONEY_REQUEST_STEP_SPLIT_PAYER.route,
[SCREENS.MONEY_REQUEST.STEP_ATTENDEES]: ROUTES.MONEY_REQUEST_ATTENDEE.route,
[SCREENS.IOU_SEND.ENABLE_PAYMENTS]: ROUTES.IOU_SEND_ENABLE_PAYMENTS,
[SCREENS.IOU_SEND.ADD_BANK_ACCOUNT]: ROUTES.IOU_SEND_ADD_BANK_ACCOUNT,
[SCREENS.IOU_SEND.ADD_DEBIT_CARD]: ROUTES.IOU_SEND_ADD_DEBIT_CARD,
Expand Down
7 changes: 7 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,13 @@ type MoneyRequestNavigatorParamList = {
backTo?: Routes;
currency?: string;
};
[SCREENS.MONEY_REQUEST.STEP_ATTENDEES]: {
action: IOUAction;
iouType: Exclude<IOUType, typeof CONST.IOU.TYPE.REQUEST | typeof CONST.IOU.TYPE.SEND>;
transactionID: string;
reportID: string;
backTo: Routes;
};
};

type NewTaskNavigatorParamList = {
Expand Down
Loading
Loading