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

[HOLD for payment 2023-09-21] [Wave 6: Categories] CRITICAL - Create Category MenuItem and CategoryPicker component #24463

Closed
2 of 3 tasks
puneetlath opened this issue Aug 11, 2023 · 29 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Daily KSv2 Engineering NewFeature Something to build that is a new item. Reviewing Has a PR in review

Comments

@puneetlath
Copy link
Contributor

puneetlath commented Aug 11, 2023

Tracking Issue: https://github.com/Expensify/Expensify/issues/282161

Design Doc: https://docs.google.com/document/d/1itXKWlhms5YHcF4-lujO6g8T5LPdLVD_7onjtZBsATQ/edit#

HOLD ON https://github.com/Expensify/Expensify/issues/302028


(Context) Fetching and Storing Categories

Even though the categoryObjects map is part of the policy object, we'll store them under a new collection key in Onyx: policyCategories_<policyID>. This has a few benefits over storing them directly in the policy. For instance, it allows categories to be evicted independently of the policy they belong to and makes it easier to update categories via Pusher.

Thus, we'll push category Onyx updates to all the members of the policy whenever changes are made by an admin in the policy editor. This will ensure clients have the most up-to-date copy of their policies' categoryObjects maps without having to fetch the full list each time they need to display categories.

With #vip-reliable-updates, we'll rely on GetMissingOnyxUpdates to keep the list up to date if you were offline when the changes were made.

Category Menu Item

We will build off of what will be added for the Date and Merchant fields in Wave 4: Scan Receipt.
Note: If this is not implemented yet, refer to the Wave 4 doc to implement the Category field before the Date and Merchant fields cc @MariaHCD

When creating a Money Request on a policy that has categories, we'll show a "Category" menu item that is initially empty:
image
image

We'll show the category as part of the MoneyRequestConfirmationList, as a MenuItemWithTopDescription, similar to what we presently do for the "amount" and "description" fields.

With the Distance Requests project, we'll start connecting to the workspace policyID in the MoneyRequestConfirm component. We'll only show the menu item if there's a policyID. Additionally, we'll use the policyID to connect to the corresponding policyCategories_ Onyx key. With that, we can confirm that the policy has categories enabled and populated (we'll know this because we load categories when opening the MoneyRequestConfirmPage beforehand).
Note: If this is not implemented yet, refer to the Wave 5 doc to implement the workspace policyID connection in the MoneyRequestConfirm component cc @neil-marcellini

function MoneyRequestConfirmationList(props) {

// ...

    return (
        <OptionsSelector>

            // ... Other Menu Items

            {props.policyCategories != null && (
                <MenuItemWithTopDescription
                    shouldShowRightIcon={!props.isReadOnly}
                    title={props.iouCategory}
                    description={translate('common.category')}
                    onPress={() => Navigation.navigate(ROUTES.getMoneyRequestCategoryRoute(props.iouType, props.reportID))}
                    style={[styles.moneyRequestMenuItem, styles.mb2]}
                    disabled={didConfirm || props.isReadOnly}
                />
            )}



        </OptionsSelector>
    );
withOnyx({

    // ... Other Onyx Connection props

    policyCategories: {
        key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
    },
}),
  • We'll create a new method ROUTES.getMoneyRequestCategoryRoute that links to ${iouType}/new/category/${reportID}.
  • This route will take you to the Category Picker.
  • The category selector will always sit in the same section as Merchant / Date. This will ensure that it is hidden behind the "Show more" dropdown just like those fields.
  • The category selector will follow the same offline patterns as the Merchant and Date fields.

Category Picker

We'll use a single page to render both the "simple" categories selector and the more complex category selector (for when you have >= 8 categories). Both versions of the page will mainly utilize an OptionsList component. This will support sections, custom container styling, keyboard controls, and search via text input already.

The CategoryPicker will take in the following props:

  • onSubmit: Callback function to fire the moment a category is selected.
    • For the case of creating a Money Request, this saves the selected category (or lack thereof) to the local Money Request. This will be called from the onSelectRow function we pass to the OptionsSelector.
  • policyID: Used so that we may fetch the corresponding policy categories from Onyx
  • categoryList (Onyx prop): The category list from the COLLECTION_POLICY_CATEGORIES Onyx key.
  • recentlyUsedCategories (Onyx prop): The recentlyUsedCategories NVP of the user stored in Onyx.

Less than 8 categories

When a policy has less than 8 categories, rendering the sections for the OptionsSelector is very simple. We'll have a single, untitled section with each of our category names passed as options. The shouldShowTextInput prop will be passed as false.

image

More than 8 categories

When a policy has 8 or more categories, we'll render up to three sections, as well as show the text input for search.

image
image

The sections will be as follows, and will be returned by a method similar to what we use for the MoneyRequestParticipantsSelector:

  • Selected category: This section will have no title and only will display if a category is already on the expense. That category will render as selected as well as be omitted from the "All" and "Recents" sections below.
  • Recents: This section will have a title. These will be the 5 most recent categories of the policy for the user - less the selected category if applicable. It will be grabbed from the recentlyUsedCategories prop. We'll only display this section if the array of recently used categories for the policies is non-empty.
  • All: This will also have a title. This will be all the categories on the policy passed as options - less the selected category if applicable.

We'll utilize some methods in CategoryPicker to help us display our options:

  • getOptionTree: In order to format the parent sections we'll need to utilize a helper method to transform the "parent category:child category" format into a format that is easier to interpret. We can follow a similar logic to what we have with buildOptions for the categorySelector in OldDot. This will still be used even if we're displaying < 8 categories.
    image

  • getOptions: When there is text in the search bar, we'll hide the Recents section and flatten the options (including the selected option) as one unified section. They will use their original names (i.e. in "parent: child" format). We'll filter the options using the getNewChatOptions method, passing in our search term. If our search term ever goes back to an empty string, we'll change back to using the result of getOptionTree above, as well as re-showing all sections.
    image

Other details across both cases

  • If a category name is super long, it will continue onto a second line in the same OptionRow.
  • If there are no results matching the search term, we'll show "No results found", which is the default behavior already.

CreateTransaction

The action to create transactions, both for distance and regular requests already exists or will exist. The updates for each are quite simple. We'll need to update createTransaction to incorporate the selected category. We'll also need to update createDistanceRequest to incorporate the category as well.


Automated Tests

We'll add tests for the CategoryPicker logic, most notably around creating the list of options to be displayed. We'll test that the following criteria are satisfied:

getOptionTree

  • Sub-categories are properly indented when returned from getOptionTree.
  • Multiple levels of sub-categories are indented properly when returned from getOptionTree - and that alphabetical order is still honored from the original parent category.
  • If a parent category is not in the category list, it is disabled when returned from getOptionTree.
  • Sub-categories are shown in "parent: child" format when:
    • Shown as the selected category in the request detailed view
    • Shown as the top selected category when there are more than 8 categories
    • Appearing in search results
    • Appearing in the recent categories section
    • Appearing in the "All" section but it's parent category is the currently selected category.

getOptions

  • All three sections (Selected category, Recents, All) are present when there are recentlyUsedCategories for the policy, a category has already been selected, and there are more than 8 categories.
  • The selected category is not present in "All" when there are more than 8 categories.
  • There are only two sections (Recents, All) present when there are recentlyUsedCategories for the policy and there are more than 8 categories, but no category is selected.
  • There is only one section displayed (All) when no category is selected and recentlyUsedCategories for the policy are empty.
  • When there are less than 8 categories:
    • Only one section is displayed with no title
    • "Recents" are not displayed even though recentlyUsedCategories is present and has values
    • The selected category shows within the list instead

Implementation:

  • Category MenuItem and CategoryPicker component #25470
    • Add a “Category” menu item to the Money Request screen.
    • Creates a basic Category Picker screen. It includes: title, description and simple list.
  • Category list helpers #25777
    • Create getOptionTree function, to format the parent sections we'll need to utilize a helper method to transform the "Parent: Child" category format into a format that is easier to interpret.
    • Extend getOptions function, to split categories by sections.
    • Extend getNewChatOptions function, to filter the options using the function.
    • Implement tests for as many cases as possible.
  • Categories UI/UX #26501
    • Connect previously created categories simple
    • Enable categories for manual and distance requests.
    • Send a selected category among other request details
@puneetlath puneetlath added Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels Aug 11, 2023
@melvin-bot
Copy link

melvin-bot bot commented Aug 11, 2023

Triggered auto assignment to @joekaufmanexpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

@melvin-bot
Copy link

melvin-bot bot commented Aug 11, 2023

Bug0 Triage Checklist (Main S/O)

  • This "bug" occurs on a supported platform (ensure Platforms in OP are ✅)
  • This bug is not a duplicate report (check E/App issues and #expensify-bugs)
    • If it is, comment with a link to the original report, close the issue and add any novel details to the original issue instead
  • This bug is reproducible using the reproduction steps in the OP. S/O
    • If the reproduction steps are clear and you're unable to reproduce the bug, check with the reporter and QA first, then close the issue.
    • If the reproduction steps aren't clear and you determine the correct steps, please update the OP.
  • This issue is filled out as thoroughly and clearly as possible
    • Pay special attention to the title, results, platforms where the bug occurs, and if the bug happens on staging/production.
  • I have reviewed and subscribed to the linked Slack conversation to ensure Slack/Github stay in sync

@puneetlath puneetlath added NewFeature Something to build that is a new item. and removed Bug Something is broken. Auto assigns a BugZero manager. labels Aug 11, 2023
@melvin-bot
Copy link

melvin-bot bot commented Aug 11, 2023

@melvin-bot melvin-bot bot added the Weekly KSv2 label Aug 11, 2023
@melvin-bot melvin-bot bot removed the Daily KSv2 label Aug 11, 2023
@melvin-bot
Copy link

melvin-bot bot commented Aug 11, 2023

Triggered auto assignment to Design team member for new feature review - @shawnborton (NewFeature)

@rezkiy37
Copy link
Contributor

Hi, I'm Michael (Mykhailo) from Callstack and I would like to work in this issue.

@waterim
Copy link
Contributor

waterim commented Aug 14, 2023

Hello, Im Artem from Callstack and I would like to take this issue as well.

@puneetlath puneetlath changed the title [HOLD E/E #302028][Wave 6: Categories] Create Category MenuItem and CategoryPicker component [Wave 6: Categories] Create Category MenuItem and CategoryPicker component Aug 14, 2023
@melvin-bot melvin-bot bot added Reviewing Has a PR in review Weekly KSv2 and removed Weekly KSv2 labels Aug 18, 2023
@melvin-bot
Copy link

melvin-bot bot commented Sep 13, 2023

⚠️ Looks like this issue was linked to a Deploy Blocker here

If you are the assigned CME please investigate whether the linked PR caused a regression and leave a comment with the results.

If a regression has occurred and you are the assigned CM follow the instructions here.

If this regression could have been avoided please consider also proposing a recommendation to the PR checklist so that we can avoid it in the future.

@rezkiy37
Copy link
Contributor

Already working on a fix.

@rezkiy37
Copy link
Contributor

The PR already reviewing internally, public review gonna be soon.

@melvin-bot melvin-bot bot added Weekly KSv2 Awaiting Payment Auto-added when associated PR is deployed to production and removed Weekly KSv2 labels Sep 13, 2023
@melvin-bot melvin-bot bot changed the title [Wave 6: Categories] CRITICAL - Create Category MenuItem and CategoryPicker component [HOLD for payment 2023-09-21] [Wave 6: Categories] CRITICAL - Create Category MenuItem and CategoryPicker component Sep 14, 2023
@melvin-bot melvin-bot bot removed the Reviewing Has a PR in review label Sep 14, 2023
@melvin-bot
Copy link

melvin-bot bot commented Sep 14, 2023

Reviewing label has been removed, please complete the "BugZero Checklist".

@melvin-bot
Copy link

melvin-bot bot commented Sep 14, 2023

The solution for this issue has been 🚀 deployed to production 🚀 in version 1.3.69-2 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2023-09-21. 🎊

After the hold period is over and BZ checklist items are completed, please complete any of the applicable payments for this issue, and check them off once done.

  • External issue reporter
  • Contributor that fixed the issue
  • Contributor+ that helped on the issue and/or PR

For reference, here are some details about the assignees on this issue:

  • @waterim does not require payment (Contractor)
  • @rezkiy37 does not require payment (Contractor)

As a reminder, here are the bonuses/penalties that should be applied for any External issue:

  • Merged PR within 3 business days of assignment - 50% bonus
  • Merged PR more than 9 business days after assignment - 50% penalty

@melvin-bot melvin-bot bot added Reviewing Has a PR in review Weekly KSv2 and removed Weekly KSv2 labels Sep 15, 2023
@puneetlath puneetlath moved this from In Progress to Done in [#whatsnext] Wave 06 - Collect Submitters Sep 19, 2023
@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 labels Sep 21, 2023
@yuwenmemon
Copy link
Contributor

@puneetlath can we close this?

@puneetlath
Copy link
Contributor Author

I need to pay out the C+ that were involved. I'll do that tomorrow and then we can close.

@puneetlath
Copy link
Contributor Author

puneetlath commented Sep 22, 2023

Ok so it looks like we had three PRs here:

Does that all seem right? If so the payment summary would be:

All to be paid out via Upwork.

@jjcoffee
Copy link
Contributor

@puneetlath I think @situchan and I both had our PR reviews from before the compensation was updated (Aug 30), so I wonder if it should be $1000 instead?

@situchan
Copy link
Contributor

From #27509 (comment), seems like it's still applied to PRs created before announcement

@puneetlath
Copy link
Contributor Author

Looks like you're right. I'll update that. Thanks for letting me know.

@puneetlath
Copy link
Contributor Author

@jjcoffee
Copy link
Contributor

@puneetlath Offer accepted, thanks!

@puneetlath
Copy link
Contributor Author

puneetlath commented Sep 24, 2023

@situchan and @jjcoffee have been paid.

Now just waiting for @abdulrahuman5196 to accept the contract and we should be good to go here.

@yuwenmemon
Copy link
Contributor

@puneetlath are we good to close here?

@puneetlath
Copy link
Contributor Author

All paid now. Thanks everyone!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Daily KSv2 Engineering NewFeature Something to build that is a new item. Reviewing Has a PR in review
Projects
No open projects
Development

No branches or pull requests

10 participants