Skip to content

Conversation

@Aunshon
Copy link
Collaborator

@Aunshon Aunshon commented Nov 20, 2025

All Submissions:

  • My code follow the WordPress' coding standards
  • My code satisfies feature requirements
  • My code is tested
  • My code passes the PHPCS tests
  • My code has proper inline documentation
  • I've included related pull request(s) (optional)
  • I've included developer documentation (optional)
  • I've added proper labels to this pull request

Related Pull Request(s)

Closes

How to test the changes in this Pull Request:

  • Test tools and dummy data page

Changelog entry

- **update:** Admin Dashboard Dummy data importer page UI with Modern Design and Improved User Experience.

@Aunshon Aunshon self-assigned this Nov 20, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 20, 2025

Walkthrough

Adds a new Dummy Data importer page and components, registers a /dummy-data admin route, updates the legacy import-dummy-data menu URL to point to the Dokan dashboard, and extends the admin panel switcher supported keys to include tools and dummy-data.

Changes

Cohort / File(s) Summary
Dummy Data Import UI
src/admin/dashboard/pages/dummy-data/index.tsx, src/admin/dashboard/pages/dummy-data/Importer.tsx, src/admin/dashboard/pages/dummy-data/Result.tsx, src/admin/dashboard/pages/dummy-data/HeaderImage.tsx, src/admin/dashboard/pages/dummy-data/StatusSkeleton.tsx, src/admin/dashboard/pages/dummy-data/RemovableDatasObj.ts
Adds a CSV-driven dummy data importer page and supporting components: CSV fetch & parse, vendor/product formatting, import orchestration and progress tracking, result/actions UI, header SVG, loading skeleton, and lists of removable data keys.
Dashboard Route Integration
src/admin/dashboard/components/Dashboard.tsx, includes/Admin/Dashboard/Dashboard.php
Registers a new /dummy-data React route and changes the import-dummy-data menu URL to use the Dokan dashboard page (admin.php?page=dokan-dashboard#\/dummy-data).
Panel Switcher Support
src/admin/panel-switcher/PanelSwitch.tsx
Extends supported admin panel keys returned by the filter to include 'tools' and 'dummy-data'.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Dashboard
    participant DummyPage as Dummy Data Page
    participant CSV
    participant API

    User->>Dashboard: Navigate to /dummy-data
    Dashboard->>DummyPage: Render DummyData component
    DummyPage->>CSV: Fetch CSV URL
    CSV-->>DummyPage: Return rows
    DummyPage->>DummyPage: Parse → vendors & products

    User->>DummyPage: Click "Run Import"
    loop per vendor
      DummyPage->>API: POST vendor + products
      API-->>DummyPage: Response
      DummyPage->>DummyPage: Update progress
    end

    DummyPage->>User: Show Result card
    User->>DummyPage: Click "Clear Data"
    DummyPage->>API: DELETE dummy data
    API-->>DummyPage: Confirm deletion
    DummyPage->>DummyPage: Reset state
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Files needing extra attention:
    • src/admin/dashboard/pages/dummy-data/index.tsx — CSV fetching/parsing, data transformations, import loop, progress calculation, error handling.
    • API integration points invoked from the importer (vendor/product creation, clear data) — verify request payloads, response handling, retries.
    • includes/Admin/Dashboard/Dashboard.php and route anchor usage — confirm admin_url correctness and hash/fragment behavior.
    • src/admin/panel-switcher/PanelSwitch.tsx — ensure filter change won't break existing panel switching logic.

Possibly related PRs

Suggested labels

Needs: Testing, Dev Review Done

Suggested reviewers

  • mrabbani
  • shohag121

Poem

🐰 I hopped in code and parsed each row,
vendors and products in tidy rows,
progress bars gleam as imports run true,
clear then reset — a fresh field to view,
hop, click, success — a carrot for you!

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 2 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ⚠️ Warning PR description is incomplete; missing key sections like 'Changes proposed', testing steps, before/after context, and changelog details. Add detailed description of changes proposed, concrete testing steps, and before/after screenshots. Provide a comprehensive changelog entry with previous vs. new behavior.
Title check ❓ Inconclusive The title 'enhance/tools-dummy-data-react' is vague and uses a branch-like naming format rather than a clear, descriptive title summarizing the main change. Use a clear, concise title that describes the feature (e.g., 'Add React-based dummy data importer to admin tools dashboard').
Linked Issues check ❓ Inconclusive The PR implements a React-based dummy data importer component for the admin dashboard, which aligns with the Tools UI redesign objective but doesn't explicitly show implementation of the complete new Tools directory UI layout mentioned in issue #4680. Clarify whether this PR fully addresses the Tools directory UI redesign or is part of a larger effort; verify alignment with the Figma design mockup.
✅ Passed checks (1 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed Most changes appear focused on the dummy data importer feature; the PHP admin URL change and panel switcher update are directly related to routing to the new dummy-data page.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch enhance/tools-dummy-data-react

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (3)
src/admin/dashboard/pages/dummy-data/Importer.tsx (1)

39-40: Simplify boolean coercion.

The double negation !! loading is unnecessary since the disabled and loading props already expect boolean values.

Apply this diff:

-                    <DokanButton
-                        disabled={ !! loading }
-                        loading={ !! loading }
-                        onClick={ onRun }
+                    <DokanButton
+                        disabled={ loading }
+                        loading={ loading }
+                        onClick={ onRun }
src/admin/dashboard/pages/dummy-data/HeaderImage.tsx (1)

1-1: Consider adding explicit prop types.

While the inline destructuring with default value works, defining an explicit TypeScript interface would improve type safety and maintainability.

Apply this diff:

+type HeaderImageProps = {
+    className?: string;
+};
+
-function HeaderImage( { className = '' } ) {
+function HeaderImage( { className = '' }: HeaderImageProps ) {
src/admin/dashboard/pages/dummy-data/index.tsx (1)

337-341: Document or remove ts-ignore directive.

The ts-ignore comment suppresses TypeScript errors without explanation. Consider properly typing dokanAdminDashboard or adding a comment explaining why the ignore is necessary.

Consider creating a proper type declaration or adding a comment:

             <DokanLink
                 href={
-                    // @ts-ignore
                     `${ dokanAdminDashboard.urls.adminRoot }admin.php?page=dokan-dashboard#/tools`
                 }

If dokanAdminDashboard is a global, add it to your type declarations file:

// In types/externals.d.ts or similar
declare const dokanAdminDashboard: {
    urls: {
        adminRoot: string;
        dummy_data: string;
    };
    nonce: string;
};
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c3e64b and c1cf347.

📒 Files selected for processing (8)
  • includes/Admin/Dashboard/Dashboard.php (1 hunks)
  • src/admin/dashboard/components/Dashboard.tsx (2 hunks)
  • src/admin/dashboard/pages/dummy-data/HeaderImage.tsx (1 hunks)
  • src/admin/dashboard/pages/dummy-data/Importer.tsx (1 hunks)
  • src/admin/dashboard/pages/dummy-data/Result.tsx (1 hunks)
  • src/admin/dashboard/pages/dummy-data/StatusSkeleton.tsx (1 hunks)
  • src/admin/dashboard/pages/dummy-data/index.tsx (1 hunks)
  • src/admin/panel-switcher/PanelSwitch.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/admin/dashboard/pages/dummy-data/index.tsx (1)
includes/DummyData/Importer.php (1)
  • Importer (26-356)
src/admin/dashboard/pages/dummy-data/Result.tsx (1)
types/externals.d.ts (1)
  • DokanModal (65-65)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: api tests (1, 1)
  • GitHub Check: e2e tests (3, 3)
  • GitHub Check: e2e tests (2, 3)
  • GitHub Check: e2e tests (1, 3)
🔇 Additional comments (5)
src/admin/panel-switcher/PanelSwitch.tsx (1)

17-17: LGTM!

The addition of 'tools' and 'dummy-data' to the supported panel keys correctly enables navigation to the new dummy-data route introduced in this PR.

includes/Admin/Dashboard/Dashboard.php (1)

220-220: LGTM!

The menu link correctly points to the Dokan dashboard page with the new /dummy-data route, aligning with the routing changes in this PR.

src/admin/dashboard/components/Dashboard.tsx (2)

13-13: LGTM!

The import correctly references the new dummy-data page component.


64-68: LGTM!

The route configuration is consistent with other routes and properly integrates the new DummyData page.

src/admin/dashboard/pages/dummy-data/StatusSkeleton.tsx (1)

3-28: LGTM!

The skeleton loading component is well-structured with appropriate accessibility considerations (sr-only text).

Comment on lines 16 to 21
const [ dummyData, setDummyData ] = useState< any[] >( [] );
const [ loading, setLoading ] = useState< boolean >( true );
const [ allVendors, setAllVendors ] = useState< any[] >( [] );
const [ allProducts, setAllProducts ] = useState< any[] >( [] );
const [ done, setDone ] = useState< boolean >( false );
const [ statusLoader, setStatusLoader ] = useState< boolean >( true );

This comment was marked as outdated.

Comment on lines 31 to 44
{ /* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */ }
<div
className="mb-[14px] border border-[#E9E9E9] rounded-[6px] flex items-center gap-[12px] p-[12px] hover:bg-[#F8F9F8]"
role="button"
tabIndex={ 0 }
onClick={ () => navigate( '/vendors' ) }
>
<div className="h-[44px] w-[44px] border border-[#E9E9E9] bg-[#F8F9F8] flex justify-center items-center rounded-[5px]">
<Users size="24" color="#828282" />
</div>
<p className="text-[14px] font-[600] text-[#25252D]">
{ __( 'View Dummy Vendors', 'dokan-lite' ) }
</p>
</div>

This comment was marked as resolved.

Comment on lines 46 to 64
{ /* eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions */ }
<div
className="mb-[14px] border border-[#E9E9E9] rounded-[6px] flex items-center gap-[12px] p-[12px] hover:bg-[#F8F9F8]"
role="button"
tabIndex={ 0 }
onClick={ () =>
window.open(
`${ dokanAdminDashboard.urls.adminRoot }edit.php?post_type=product`,
'_self'
)
}
>
<div className="h-[44px] w-[44px] border border-[#E9E9E9] bg-[#F8F9F8] flex justify-center items-center rounded-[5px]">
<Box size="24" color="#828282" />
</div>
<p className="text-[14px] font-[600] text-[#25252D]">
{ __( 'View Dummy Products', 'dokan-lite' ) }
</p>
</div>

This comment was marked as resolved.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/admin/dashboard/pages/dummy-data/index.tsx (2)

335-344: Replace @ts-ignore with proper type handling.

The @ts-ignore directive on line 337 suppresses TypeScript errors when accessing the global dokanAdminDashboard. This hides potential runtime issues if the global is undefined.

Consider using optional chaining with a fallback, similar to line 23:

             <DokanLink
                 href={
-                    // @ts-ignore
-                    `${ dokanAdminDashboard.urls.adminRoot }admin.php?page=dokan-dashboard#/tools`
+                    `${ ( window as any )?.dokanAdminDashboard?.urls?.adminRoot || '' }admin.php?page=dokan-dashboard#/tools`
                 }

Or define a proper type for the window object to avoid casting to any throughout the component.


18-19: Consider defining explicit types for vendor and product data.

Both allVendors and allProducts use any[], which bypasses type checking. While this works for dynamic CSV data, defining proper interfaces would improve type safety and code maintainability.

Consider creating interfaces based on the CSV structure:

interface VendorData {
    id: string;
    email: string;
    password: string;
    store_name: string;
    // ... other vendor fields
}

interface ProductData {
    id: string;
    name: string;
    sku: string;
    vendor: string;
    raw_attributes?: Array<{
        name: string;
        value: string[];
        visible: string;
        taxonomy: string;
    }>;
    // ... other product fields
}

Then update the state declarations:

const [ allVendors, setAllVendors ] = useState<VendorData[]>( [] );
const [ allProducts, setAllProducts ] = useState<ProductData[]>( [] );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1cf347 and d9b2766.

📒 Files selected for processing (3)
  • src/admin/dashboard/pages/dummy-data/Importer.tsx (1 hunks)
  • src/admin/dashboard/pages/dummy-data/Result.tsx (1 hunks)
  • src/admin/dashboard/pages/dummy-data/index.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/admin/dashboard/pages/dummy-data/Result.tsx
  • src/admin/dashboard/pages/dummy-data/Importer.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/admin/dashboard/pages/dummy-data/index.tsx (2)
src/definitions/RouterProps.ts (1)
  • RouterProps (10-18)
includes/DummyData/Importer.php (1)
  • Importer (26-356)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: e2e tests (2, 3)
  • GitHub Check: e2e tests (3, 3)
  • GitHub Check: e2e tests (1, 3)
  • GitHub Check: api tests (1, 1)
🔇 Additional comments (3)
src/admin/dashboard/pages/dummy-data/index.tsx (3)

263-284: LGTM - attribute formatting and data cleanup.

The function correctly:

  • Builds structured raw_attributes from CSV columns
  • Converts manage_stock to boolean
  • Removes vendor-specific fields from product data

The approach of splitting attribute values by comma and converting manage_stock using Boolean() is appropriate for CSV-based dummy data.


210-253: LGTM - sequential import with recursive chaining.

The recursive pattern for sequential vendor imports is appropriate here:

  • Ensures vendors are imported one at a time in order
  • Progress updates after each vendor
  • Stops gracefully on error
  • Shows success toast only when all vendors complete (line 217-223)

The use of the nullish coalescing operator on line 239 correctly handles the response index.


115-119: LGTM - intentional mount-only effect.

The useEffect with an empty dependency array correctly runs initialization logic once on mount. The eslint-disable comment is appropriate for this intentional pattern.

Comment on lines +16 to +21
const [ progress, setProgress ] = useState( 0 );
const [ loading, setLoading ] = useState< boolean >( true );
const [ allVendors, setAllVendors ] = useState< any[] >( [] );
const [ allProducts, setAllProducts ] = useState< any[] >( [] );
const [ done, setDone ] = useState< boolean >( false );
const [ statusLoader, setStatusLoader ] = useState< boolean >( true );

This comment was marked as outdated.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
src/admin/dashboard/pages/dummy-data/RemovableDatasObj.ts (1)

1-51: Remove duplicate 'status' entry from vendorsDataToRemove.

vendorsDataToRemove contains 'status' twice (Lines 3 and 36). This is harmless at runtime but redundant and suggests a copy‑paste oversight. It’s better to keep each key only once for clarity and to avoid confusion in future edits.

You can safely drop the second occurrence:

     'menu_order',
     'virtual',
     'downloadable',
-    'status',
     'attribute_1_name',
src/admin/dashboard/pages/dummy-data/index.tsx (1)

210-243: Move success toast out of finally so it only fires on successful clear.

Right now the success toast is inside the finally block of clearAllDummyData. That block runs for both success and failure, so users will see a “success” message even when the clear request fails (and an error toast has already been shown), which is misleading.

Move the success toast into the .then handler and keep only the loading/confirm state resets in finally:

     apiFetch( {
         path: 'dokan/v1/dummy-data/clear',
         method: 'DELETE',
         data: { nonce: ( window as any )?.dokanAdminDashboard?.nonce },
     } )
-        .then( () => {
-            resetToImport();
-            // reload CSV and status so user can import again
-            loadImportStatus();
-            loadCsvFile();
-        } )
+        .then( () => {
+            resetToImport();
+            // reload CSV and status so user can import again
+            loadImportStatus();
+            loadCsvFile();
+
+            toast( {
+                type: 'success',
+                title: __(
+                    'All dummy data remove successfully',
+                    'dokan-lite'
+                ),
+            } );
+        } )
         .catch( ( err: any ) => {
             toast( {
                 type: 'error',
                 title:
                     err?.message ||
                     __( 'Something went wrong', 'dokan-lite' ),
             } );
         } )
         .finally( () => {
             setLoading( false );
             setIsConfirmOpen( false );
-
-            toast( {
-                type: 'success',
-                title: __(
-                    'All dummy data remove successfully',
-                    'dokan-lite'
-                ),
-            } );
         } );
🧹 Nitpick comments (1)
src/admin/dashboard/pages/dummy-data/index.tsx (1)

88-120: Consider handling the “no vendors in CSV” case explicitly.

If allVendors is empty (e.g., unexpected CSV contents) and the user triggers import, handleImport( 0 ) will immediately set done to true without importing anything, and the UI will move to the “completed” state silently.

Not critical, but you may want to surface a clearer message (e.g., “No vendors found in CSV”) instead of treating this as a successful run.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d9b2766 and 53489fc.

📒 Files selected for processing (2)
  • src/admin/dashboard/pages/dummy-data/RemovableDatasObj.ts (1 hunks)
  • src/admin/dashboard/pages/dummy-data/index.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/admin/dashboard/pages/dummy-data/index.tsx (3)
src/definitions/RouterProps.ts (1)
  • RouterProps (10-18)
src/admin/dashboard/pages/dummy-data/RemovableDatasObj.ts (2)
  • vendorsDataToRemove (1-51)
  • productsDataToRemove (52-82)
includes/DummyData/Importer.php (1)
  • Importer (26-356)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: e2e tests (1, 3)
  • GitHub Check: e2e tests (2, 3)
  • GitHub Check: e2e tests (3, 3)
  • GitHub Check: api tests (1, 1)
🔇 Additional comments (2)
src/admin/dashboard/pages/dummy-data/index.tsx (2)

15-22: State typing and use of any[] look acceptable for this UI layer.

The state definitions rely on inference for progress and use any[] for CSV-derived vendor/product collections. Given the dynamic CSV shape and downstream PHP importer, this is a reasonable compromise here, and the overall state wiring (progress, loading, done, statusLoader) is consistent with the intended UX.


245-307: Importer body and layout wiring look coherent with the dummy-data flow.

loadImporterBody cleanly switches between skeleton, importer, and result views based on statusLoader and done, and the surrounding layout (back link, explanatory copy, header image, Card wrapper, and DokanToaster) is wired correctly.

No functional issues spotted in this section.

@Aunshon Aunshon added Needs: Testing This requires further testing Needs: Dev Review It requires a developer review and approval labels Nov 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs: Dev Review It requires a developer review and approval Needs: Testing This requires further testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants