Skip to end of metadata
Go to start of metadata

You are viewing an old version of this content. View the current version.

Compare with Current View Version History

« Previous Version 21 Next »

IBFEC-2795 - Getting issue details... STATUS

🧐 Context

The current DOP platform currently lacks a way to manage disabled products across its global Markets, leading to prolonged periods of product unavailability and sales losses.

Store Managers disable products for various operational reasons (stock shortages, equipment maintenance, etc.), but these products often remain disabled because there is no automated reminder or reactivation process in place. This issue was previously managed by the Iberia Operations Team, who would proactively check for disabled products.

With the current migration to the Whitelabel Platform, this manual process is not reliable anymore and products remain disabled for longer periods than necessary, impacting both user experience and business performance. Customers experience frustration when their desired products are consistently unavailable, leading to decreased retention rates and lost revenue opportunities.

To address this, we propose an enhancement to the DOP system, allowing for better auditing and management of product availability.

🛠️ Potential Solutions

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

image-20250128-180643.png

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

  • The user will be sent to a new route /audit-products

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

  • The user can also download products status (the filtered products to a CSV file)

To understand better this flow: https://www.figma.com/board/rvDVIJQKsiG1SC1yB93JVn/2024---Q4---%5BIBFEC-2795%5D---Ability-to-audit-per-store-available-and-unavailable-products-(DOP)?node-id=0-1&p=f&t=rVNPlynr4mNhYHWv-0.

About DOP Performance

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. Infinite Scroll

  2. To-do

✅ Proposed Solution

New page to audit products

Important: The UX team is defining the experience. This document is already out-dated. The main idea could be reused still.

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

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

 App path route example - frontend/src/App.tsx
// ...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

    • Create a new component to show the header with the new button “Download products status”

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

      • We’ll use the PageHeader as main container inside this new component (ex: PaymentMethodsHeader)

    • 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 “Review Restaurants” button

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

 Common structure example - frontend/src/pages/audit-restaurants-products/AuditRestaurantProducts.tsx
// ... 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>
);
 EditorBar adjustments to show "Audit Restaurants" button - Example (frontend/src/pages/editor/editor-bar/EditorBar.tsx)

Interface example:

PS: The prints below are already outdated, but the idea and logic will be the same. The button label will be “Review restaurant”

image-20241118-153156.pngimage-20250103-182302.png

Code adjustment example:

export const EditorBar: React.VFC<EditorBarProps> = memo(function EditorBar({ type }) {
  // ...rest of the code
  
  // New lines
  const selectedGroups = useRematch(select.restaurantGroups.selectedGroups);
  
  // We need to check the type restaurants because this Editor bar is used in other pages
  // as well (products page, for example) and as this state is global (Rematch) we don't want
  // to show this button there
  const selectedGroups = useRematch(select.restaurantGroups.selectedGroups);
  const hasGroupSelected = type === 'restaurants' && !!selectedGroups.length;
  const hasRestaurantSelected = type === 'restaurants' && !!selectedRestaurants.length;
  const isReviewRestaurantEnabled = hasGroupSelected ?? hasRestaurantSelected;

  // ...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
              {isReviewRestaurantEnabled && (
                <Button large onClick={handleAuditRestaurants}>
                  Review 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)

        • Name

        • Availability

        • Updated

        • Price

        • Service Mode

        • Channel

        • Type

        • Section

        • PLU

        • Internal Name

        • Restaurant

        • ID

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

      • Search products text field

      • Availability

      • Service mode

      • Channel

      • Type

      • Section

      • Restaurant

  • Create a new store property to manage the related state

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

    • 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

 New audit products rematch Model - frontend/src/rematch/models/audit-restaurants.ts - Example
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:

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,
};

Front end to-do: Do we need a pagination system? The solutions to deal with performance problems and querie section will answer that.

  • Note: If yes, as a suggestion, we can consider using the Material UI pagination component because it is very flexible and we can customize the visuals if we want (the app appears to lack a pagination component for the tables). This library is already in use in other applications, like admin-app, so it’s approved for use.

New logic to schedule and automatic reactivation of disabled products

To-do: to confirm if this will be part of this first deliverable or if we’ll only deliver the audit page for now. 

Solutions to deal with performance problems and queries

Today the app depends on data from different places to have the products complete data (considering availability, etc). I'll let here just an example of how the data flow is working for the products page/editor flow → This is only intended for the discovery/draft phase. We can delete this text and the image below later.

Products editor data management example.svg

To-do: proposals to solve this data composition/orchestration layer for the new page and products data

# 1 - To-do solution 1

📈 Metrics

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

🧑‍🚒 QA Plan

Testing scenarios. See example /wiki/spaces/EGMT/pages/4080861189.

⚠️ Call-outs

Tip: Document here any improvement or discussion regarding the feature

  • No labels

0 Comments

You are not logged in. Any changes you make will be marked as anonymous. You may want to Log In if you already have an account.