-
Notifications
You must be signed in to change notification settings - Fork 3.7k
FAB popover decomposition #83299
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
FAB popover decomposition #83299
Changes from all commits
b13d7bb
f3e1f87
c604841
9d65f70
8beca63
2224d4d
538804d
6b5705c
eeeb56d
88ef1b2
c250d47
b551ced
435d558
a7a0179
d9718e0
9549c0f
9ff0839
6a8806e
afc0d0b
f7fceb0
feca2a3
62a0f3d
7a8bfa4
f730894
485d3d1
92f9247
3ff2e56
c98df63
1268655
63c8296
83a45c6
dd240d7
b3cc3b1
ec55ac9
f11caab
f28760b
01a84ae
ab102fe
0bc3349
76d91b3
e4cb850
36c9e5b
2191d94
7d7150b
f17770b
7a06742
3846341
fb048fa
abcb893
b3a0ac3
a1baa97
c953885
3b787df
efdba36
1ebde66
c3b3236
3a98ff8
753f7f2
b359de5
85ed362
66f052f
ce848a5
2748220
ce9f79d
d3edd73
50f6f92
83cded2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,14 @@ | ||
| import type {ReactNode} from 'react'; | ||
| import React, {useCallback, useMemo, useState} from 'react'; | ||
| import React, {useEffect, useRef, useState} from 'react'; | ||
| import {View} from 'react-native'; | ||
| import CheckboxWithLabel from '@components/CheckboxWithLabel'; | ||
| import ConfirmModal from '@components/ConfirmModal'; | ||
| import {ModalActions} from '@components/Modal/Global/ModalContext'; | ||
| import Text from '@components/Text'; | ||
| import TextLink from '@components/TextLink'; | ||
| import Navigation from '@libs/Navigation/Navigation'; | ||
| import {buildCannedSearchQuery} from '@libs/SearchQueryUtils'; | ||
| import CONST from '@src/CONST'; | ||
| import ROUTES from '@src/ROUTES'; | ||
| import useConfirmModal from './useConfirmModal'; | ||
| import useLocalize from './useLocalize'; | ||
| import useThemeStyles from './useThemeStyles'; | ||
|
|
||
|
|
@@ -26,100 +26,76 @@ type UseCreateEmptyReportConfirmationParams = { | |
| type UseCreateEmptyReportConfirmationResult = { | ||
| /** Function to open the confirmation modal */ | ||
| openCreateReportConfirmation: () => void; | ||
| /** The confirmation modal React component to render */ | ||
| CreateReportConfirmationModal: ReactNode; | ||
| }; | ||
|
|
||
| /** | ||
| * A React hook that provides a confirmation modal for creating empty reports. | ||
| * When a user attempts to create a new report in a workspace where they already have an empty report, | ||
| * this hook displays a confirmation modal to prevent accidental duplicate empty reports. | ||
| * | ||
| * @param params - Configuration object for the hook | ||
| * @param params.policyName - The display name of the policy/workspace | ||
| * @param params.onConfirm - Callback function to execute when user confirms report creation | ||
| * @returns An object containing: | ||
| * - openCreateReportConfirmation: Function to open the confirmation modal | ||
| * - CreateReportConfirmationModal: The confirmation modal React component to render | ||
| * | ||
| * @example | ||
| * const {openCreateReportConfirmation, CreateReportConfirmationModal} = useCreateEmptyReportConfirmation({ | ||
| * policyID: 'policy123', | ||
| * policyName: 'Engineering Team', | ||
| * onConfirm: handleCreateReport, | ||
| * }); | ||
| * | ||
| */ | ||
| export default function useCreateEmptyReportConfirmation({policyName, onConfirm, onCancel}: UseCreateEmptyReportConfirmationParams): UseCreateEmptyReportConfirmationResult { | ||
| function ConfirmationPrompt({workspaceName, checkboxRef, onLinkPress}: {workspaceName: string; checkboxRef: React.RefObject<boolean>; onLinkPress: () => void}) { | ||
| const {translate} = useLocalize(); | ||
| const styles = useThemeStyles(); | ||
| const workspaceDisplayName = useMemo(() => (policyName?.trim().length ? policyName : translate('report.newReport.genericWorkspaceName')), [policyName, translate]); | ||
| const [isVisible, setIsVisible] = useState(false); | ||
| const [modalWorkspaceName, setModalWorkspaceName] = useState(workspaceDisplayName); | ||
| const [shouldDismissEmptyReportsConfirmation, setShouldDismissEmptyReportsConfirmation] = useState(false); | ||
| const [isChecked, setIsChecked] = useState(false); | ||
|
|
||
| return ( | ||
| <View style={styles.gap4}> | ||
| <Text> | ||
| {translate('report.newReport.emptyReportConfirmationPrompt', {workspaceName})}{' '} | ||
| <TextLink onPress={onLinkPress}>{translate('report.newReport.emptyReportConfirmationPromptLink')}.</TextLink> | ||
| </Text> | ||
| <CheckboxWithLabel | ||
| accessibilityLabel={translate('report.newReport.emptyReportConfirmationDontShowAgain')} | ||
| label={translate('report.newReport.emptyReportConfirmationDontShowAgain')} | ||
| isChecked={isChecked} | ||
| onInputChange={(value) => { | ||
| const checked = !!value; | ||
| setIsChecked(checked); | ||
| // eslint-disable-next-line no-param-reassign | ||
| checkboxRef.current = checked; | ||
| }} | ||
| /> | ||
| </View> | ||
| ); | ||
| } | ||
|
|
||
| const handleConfirm = useCallback(() => { | ||
| onConfirm(shouldDismissEmptyReportsConfirmation); | ||
| setShouldDismissEmptyReportsConfirmation(false); | ||
| setIsVisible(false); | ||
| }, [onConfirm, shouldDismissEmptyReportsConfirmation]); | ||
| export default function useCreateEmptyReportConfirmation({policyName, onConfirm, onCancel}: UseCreateEmptyReportConfirmationParams): UseCreateEmptyReportConfirmationResult { | ||
| const {translate} = useLocalize(); | ||
| const {showConfirmModal, closeModal} = useConfirmModal(); | ||
| const workspaceDisplayName = policyName?.trim().length ? policyName : translate('report.newReport.genericWorkspaceName'); | ||
|
|
||
| const handleCancel = useCallback(() => { | ||
| onCancel?.(); | ||
| setShouldDismissEmptyReportsConfirmation(false); | ||
| setIsVisible(false); | ||
| }, [onCancel]); | ||
| const onConfirmRef = useRef(onConfirm); | ||
| const onCancelRef = useRef(onCancel); | ||
| useEffect(() => { | ||
| onConfirmRef.current = onConfirm; | ||
| onCancelRef.current = onCancel; | ||
| }, [onConfirm, onCancel]); | ||
|
|
||
| const handleReportsLinkPress = useCallback(() => { | ||
| onCancel?.(); | ||
| setShouldDismissEmptyReportsConfirmation(false); | ||
| setIsVisible(false); | ||
| Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query: buildCannedSearchQuery({type: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT})})); | ||
| }, [onCancel]); | ||
| const openCreateReportConfirmation = () => { | ||
TMisiukiewicz marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Useful? React with 👍 / 👎. |
||
| const checkboxRef = {current: false}; | ||
TMisiukiewicz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| const openCreateReportConfirmation = useCallback(() => { | ||
| // The caller is responsible for determining if empty report confirmation | ||
| // should be shown. We simply open the modal when called. | ||
| setModalWorkspaceName(workspaceDisplayName); | ||
| setShouldDismissEmptyReportsConfirmation(false); | ||
| setIsVisible(true); | ||
| }, [workspaceDisplayName]); | ||
| const handleLinkPress = () => { | ||
| closeModal(); | ||
| Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query: buildCannedSearchQuery({type: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT})})); | ||
|
Comment on lines
+72
to
+74
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The link handler inside the confirmation prompt closes the modal and navigates, but it no longer triggers Useful? React with 👍 / 👎.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. imo Claude is right here, this is happening but implicitly in the promise chain. The review comment is invalid. The bot claims
So
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| }; | ||
|
|
||
| const prompt = useMemo( | ||
| () => ( | ||
| <View style={styles.gap4}> | ||
| <Text> | ||
| {translate('report.newReport.emptyReportConfirmationPrompt', {workspaceName: modalWorkspaceName})}{' '} | ||
| <TextLink onPress={handleReportsLinkPress}>{translate('report.newReport.emptyReportConfirmationPromptLink')}.</TextLink> | ||
| </Text> | ||
| <CheckboxWithLabel | ||
| accessibilityLabel={translate('report.newReport.emptyReportConfirmationDontShowAgain')} | ||
| label={translate('report.newReport.emptyReportConfirmationDontShowAgain')} | ||
| isChecked={shouldDismissEmptyReportsConfirmation} | ||
| onInputChange={(value) => setShouldDismissEmptyReportsConfirmation(!!value)} | ||
| showConfirmModal({ | ||
| // Adding a space at the end because of this bug in react-native: https://github.com/facebook/react-native/issues/53286 | ||
| title: `${translate('report.newReport.emptyReportConfirmationTitle')} `, | ||
| confirmText: translate('report.newReport.createReport'), | ||
| cancelText: translate('common.cancel'), | ||
| prompt: ( | ||
| <ConfirmationPrompt | ||
| workspaceName={workspaceDisplayName} | ||
| checkboxRef={checkboxRef} | ||
| onLinkPress={handleLinkPress} | ||
| /> | ||
| </View> | ||
| ), | ||
| [handleReportsLinkPress, modalWorkspaceName, shouldDismissEmptyReportsConfirmation, styles.gap4, translate], | ||
| ); | ||
|
|
||
| const CreateReportConfirmationModal = useMemo( | ||
| () => ( | ||
| <ConfirmModal | ||
| confirmText={translate('report.newReport.createReport')} | ||
| cancelText={translate('common.cancel')} | ||
| isVisible={isVisible} | ||
| onConfirm={handleConfirm} | ||
| onCancel={handleCancel} | ||
| prompt={prompt} | ||
| title={`${translate('report.newReport.emptyReportConfirmationTitle')} `} // Adding a space at the end because of this bug in react-native: https://github.com/facebook/react-native/issues/53286 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keep original comment |
||
| /> | ||
| ), | ||
| [handleCancel, handleConfirm, isVisible, prompt, translate], | ||
| ); | ||
| ), | ||
| }).then((result) => { | ||
| if (result.action === ModalActions.CONFIRM) { | ||
| onConfirmRef.current(checkboxRef.current); | ||
| } else { | ||
| onCancelRef.current?.(); | ||
| } | ||
| }); | ||
| }; | ||
|
|
||
| return { | ||
| openCreateReportConfirmation, | ||
| CreateReportConfirmationModal, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| const useDragoverDismiss: (isActive: boolean, dismiss: () => void) => void = () => {}; | ||
TMisiukiewicz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| export default useDragoverDismiss; | ||
Uh oh!
There was an error while loading. Please reload this page.