Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Document Status

Status
titleWIP

Document Owner(s)

Augusto Romao, Vinicius

Reviewers

 

Epic

Jira Legacy
serverSystem Jira
serverId255417eb-03fa-3e2f-a6ba-05d325fec50d
keyIBFEC-2795

...

To address this, we propose an enhancement to the DOP system, allowing for better auditing and management of product availability. This includes the ability to schedule product disablement and automatic reactivation, as well as providing comprehensive reports on the status of disabled products.

🛠️ Potential Solutions

For the navigation/flow experience, this will be the summarized solution:

  • The audit process starts when the user clicks on the "Audit Restaurants" button in the /restaurants age

  • The user will be sent to a new route /audit-products (to be defined/confirmed with UX team)

  • On this new page, we'll show the new products table for the audit restaurants experience

    • If the user goes out to another page or cancels the operation, he’ll need to restart the audit process again

    • We want this experience for now to be close to what we already have on the /editor flow

  • Besides the ability to filter what's been presented on the table, the user can also download products status (the filtered products to a CSV file)

To understand the complete flow check this Figma: pending info

Check the proposed solution below to understand technically:

Today we already know that the application has performance problems to deal with big content on the table (high loadings, slowness, etc.). To deal with this problem, we have the following proposals:

  1. To-do

  2. To-do

✅ Proposed Solution

New front end page development

# 1 - Create new page, route and state management property

  • Create a new route /audit-products (suggestion)

Expand
titleApp path route example - frontend/src/App.tsx
Code Block
// ...rest of the file

const AuditRestaurantProducts = lazy(() => import('./pages/audit-restaurants-products'));

const App: React.FC = () => {
  // ...rest of the function

  return (
    <BaseLayout>
      <Suspense fallback={null}>
        <Routes>
          // ...other routes
          <Route
            path="/audit-products" element={<AuditRestaurantProducts />} />
        </Routes>
      </Suspense>
    </BaseLayout>
  );
}
  • Create a new component to represent the new audit page (suggestion: AuditRestaurantProducts)

    • We need to include the common structure for pages following the current pattern

    • We’ll need to get here any state related data to download the products Status

    • Create a new component to show the footer (suggestion: AuditProductsFooter)

      • On this footer, we’ll only have the cancel button that will send the user back to the /restaurants page

    • Adjust the EditorBar component to show the new “Audit Restaurants” button

      • This button will only be shown if we’re on the /restaurants page, groups tab, and select at least one group there

Expand
titleCommon structure example - frontend/src/pages/audit-restaurants-products/AuditRestaurantProducts.tsx
Code Block
languagetsx
// ... Rest of the code above. Component return example
return (
    <Page>
      <PageHeader>
          // Editor title example
          <EditorPageTitle>{formatMessage({ id: 'audit-products.header' })}</EditorPageTitle>
          // Desired content here
      </PageHeader>
      <PageContent hasActionBar>
        // Desired content here
      </PageContent>            

      // New footer component
      <AuditProductsFooter />
    </Page>
);
Expand
titleEditorBar adjustments to show "Audit Restaurants" button - Example

Interface example:

image-20241118-153156.pngImage Added

Code adjustment:

Code Block
languagetsx
export const EditorBar: React.VFC<EditorBarProps> = memo(function EditorBar({ type }) {
  // ...rest of the code
  
  // New lines
  const selectedGroups = useRematch(select.restaurantGroups.selectedGroups);
  const segment = useRematch(select.restaurants.segment);
  
  // Ensure that the user selected groups tab and at least one value. The type check
  // could be optional but adds confidence to avoid problems
  const showAuditProducts =
    segment === 'groups' && type === 'restaurants' && !!selectedGroups.length;

  // ...rest of the code
  
  // new function to navigate the user
  const handleAuditRestaurants = useCallback(() => {
    navigate('/audit-products');
  }, []);
  
  return (
    <ActionBar active={isModalVisible ? false : isEditing}>
      <ActionBarInner>
        // ...rest of the code
        <ActionBarEnd>
          {!isCopyMode && (
            <>
              // ...rest of the code
              )}
              {isDropdownEditor ? (
                // ...rest of the code
              ) : (
                // ...rest of the code
              )}
              // New audit button
              {showAuditProducts && (
                <Button large onClick={handleAuditRestaurants}>
                  Audit Restaurants
                </Button>
              )}
            </>
          )}
         // ...rest of the code
        </ActionBarEnd>
      </ActionBarInner>
    </ActionBar>
  );
});
  • Create a new component for the audit products table

    • This new component can be based on the current frontend/src/pages/products/products-content/ProductsContent.tsx implementation

    • Our new table will be similar to this one, but

      • We want a better experience, not a copy/paste

      • We’ll have new columns (besides the current ones in the products table)

        • Restaurant

        • Availability

        • Date

    • To filter the table we’ll need the following filters

      • Search products text field

      • Restaurant

      • Service mode

      • Type

      • Section

      • Availability

  • Create a new store property to manage the related state

    • Motivation: isolate and separate responsibilities. Let’s the current products state untouched.

    • The new “Download products Status” button lives in the application header. We’ll need to save in memory the products filtered result to be able to generate the CSV when clicking in the header button

Expand
titleNew audit products rematch Model - frontend/src/rematch/models/audit-restaurants.ts - Example
Code Block
languagetypescript
export interface AuditProductsState {
  auditableProducts: Record<string, desiredFragmentHere>;
}

/**
 * Audit products redux store
 */
export const auditProducts = createModel<RootModel>()({
  state: {
    auditableProducts: false,
    filters: {
      // any desirable filter, if we want
    },
  } as AuditProductsState,

  reducers: {
    /**
     * Method to set the auditableProducts
     */
    setAuditableProducts(state, payload: desiredProductsInterface) {
      return { ...state, auditableProducts: payload };
    },

    // any other filter reducer if necessary
  },

  selectors: slice => ({
    auditableProducts() {
      return slice(state => state.auditableProducts);
    },
  }),
});

Update the Rematch models index:

Code Block
languagetypescript
import { Models } from '@rematch/core';

// ...rest of the code
import { auditProducts } from './audit-products';

export interface RootModel extends Models<RootModel> {
  // ...rest of the code
  auditRestaurants: typeof auditProducts;
}

export const models: RootModel = {
  // ...rest of the code
  auditProducts,
};

Solutions to deal with performance problems and queries

  1. To-do

📈 Metrics

Info

Describe the metrics that will be used to measure the solution’s success, as well as how to measure those KPIs.

...