Skip to content

Feature/show doc in dokan vendor dashboard (recover #303)#319

Merged
iftakharul-islam merged 5 commits into
weDevsOfficial:developfrom
arifulhoque7:recover/pr-303
Jun 19, 2026
Merged

Feature/show doc in dokan vendor dashboard (recover #303)#319
iftakharul-islam merged 5 commits into
weDevsOfficial:developfrom
arifulhoque7:recover/pr-303

Conversation

@arifulhoque7

@arifulhoque7 arifulhoque7 commented May 20, 2026

Copy link
Copy Markdown
Contributor

Recovered from sapayth's deleted fork.

  • Original closed PR: Feature/show doc in dokan vendor dashboard #303
  • Head branch: feature/show_doc_in_dokan_vendor_dashboard (preserved on fork as recover/pr-303)
  • Recovery method: fetched refs/pull/303/head from base repo, pushed to arifulhoque7/wedocs-plugin

Security note: any sapayth device-compromise payload (config.bat .gitignore entry, captcha-config.php dropper) was stripped via a single cleanup commit on top before push. Branches without markers were pushed unchanged.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a Dokan vendor dashboard experience for Docs, including a vendor-scoped docs browser and search.
    • Added “Vendor Doc” visibility/type controls when creating or updating docs (with an upgrade gate when applicable).
    • Added a “Vendor Doc” badge on doc headers in the editor.
  • Bug Fixes

    • Improved public-facing filtering so vendor-only docs don’t appear by default in public doc listings/search.
  • Style

    • Updated single-doc and responsive sidebar layout, plus improved docs typography and link/button styling.

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3b93161f-b558-4de2-b8b9-fff99429361c

📥 Commits

Reviewing files that changed from the base of the PR and between 065952c and ece604c.

📒 Files selected for processing (7)
  • includes/Dokan/VendorDashboard.php
  • includes/Frontend.php
  • includes/Post_Types.php
  • src/assets/less/frontend.less
  • src/components/AddDocModal.js
  • src/components/DocActions.js
  • src/hooks/useVendorDocGating.js
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/hooks/useVendorDocGating.js
  • src/assets/less/frontend.less
  • src/components/AddDocModal.js
  • includes/Post_Types.php
  • src/components/DocActions.js
  • includes/Frontend.php

Walkthrough

This PR adds Dokan vendor dashboard integration to WeDocs, introducing vendor-scoped documentation through _is_vendor_doc post meta with auto-inheritance and cascading propagation, a VendorDashboard class wiring Dokan settings/routing/templates, a dedicated get_vendor_docs() AJAX endpoint, public query filtering to hide vendor docs from non-vendor views, React UI components for vendor doc selection with pro-gating, and two new Dokan dashboard templates (vendor-docs.php, vendor-single-doc.php) with dashboard-aware link URLs and sidebar helpers.

Changes

Vendor Documentation Dashboard for Dokan Integration

Layer / File(s) Summary
Vendor doc post meta registration and inheritance
includes/Post_Types.php, includes/functions.php
Registers _is_vendor_doc post meta with REST exposure and edit_docs capability gating. Enables custom-fields support on docs post type. Adds REST insert hook to inherit _is_vendor_doc from root ancestor to new descendants. Implements propagate_vendor_doc_meta() to cascade meta changes from root doc to all descendants with recursive-loop prevention via hook unhooking.
Vendor doc exclusion helper and public query filters
includes/Frontend.php, includes/API/API.php, includes/Shortcode.php, includes/functions.php
Adds wedocs_exclude_vendor_doc_meta_query() helper for reusable vendor-doc exclusion. Hooks exclude_vendor_docs() into pre_get_posts for public docs queries (skipping admin, privileged users, vendor dashboard). Updates REST helpful-docs and contributors API queries, filters shortcode parent docs and recomputes pagination. Includes is_dokan_vendor_dashboard() detection helper.
Frontend script localization and pro-asset dequeuing
includes/Frontend.php
Updates wp_localize_script() to include isVendorDashboard, vendorDocsBaseUrl (Dokan nav-derived), and dynamic isSingleDoc. Adds dequeue_pro_scripts_on_vendor_dashboard() hook to conditionally remove pro messaging assets on vendor dashboard requests.
Vendor docs AJAX endpoint
includes/Ajax.php
Registers wedocs_get_vendor_docs AJAX actions (authenticated/unauthenticated). Adds get_vendor_docs() handler with nonce verification, dokandar/manage_options capability check (403 JSON error on failure), vendor-only post retrieval, hierarchical docs tree response. Refactors get_docs() from get_pages() to get_posts() with integer posts_per_page.
VendorDashboard class and Dokan integration
includes/Dokan/VendorDashboard.php, wedocs.php
Introduces WeDevs\WeDocs\Dokan\VendorDashboard instantiated in init_classes() when Dokan is present. Registers hooks for Dokan settings toggle, conditional menu injection at position 185, docs query var, template routing (vendor-single-doc.php or vendor-docs.php based on doc_id), and inline script collapsing Dokan sidebar on docs pages via localStorage.
Vendor dashboard listing and single-doc templates
templates/vendor-docs.php, templates/vendor-single-doc.php
Adds vendor-docs.php with search UI, asset enqueueing, published parent-doc query filtered by _is_vendor_doc, hierarchical assembly via get_children(), dynamic 1–2 column layout. Adds vendor-single-doc.php with wedocs_get_vendor_descendants() and recursive wedocs_vendor_sidebar_nav() helpers, dashboard-scoped doc_id URLs, main doc/articles panel, Dokan dashboard hooks, and helpful footer.
UpgradePopup controlled mode and useVendorDocGating hook
src/components/ProPreviews/common/UpgradePopup.js, src/hooks/useVendorDocGating.js
Extends UpgradePopup with controlledIsOpen/onControlledClose props for controlled state and conditional UpgradeButton rendering. Adds useVendorDocGating hook computing Pro-load state, vendor root-doc count from DOCS_STORE, and isGated logic.
React modal and action components for vendor selection
src/components/AddDocModal.js, src/components/DocActions.js, src/components/Documentations/ParentDocs.js
Updates AddDocModal with visibility Listbox, gating-aware state, _is_vendor_doc in create payload, controlled UpgradePopup. Adds vendor-doc toggle in DocActions with gating check and DOCS_STORE update, plus action-menu button. Adds "Vendor Doc" badge in ParentDocs.
Frontend search modal context and dashboard-scoped URLs
assets/js/frontend.js
Guards loadSingleDocSearchModal() to single-doc/vendor-dashboard context, selects AJAX action accordingly. Adds buildDocUrl() helper for dashboard-scoped or permalink URLs. Sets result link target to _self on dashboard, _blank otherwise. Updates parent nav data-url via buildDocUrl().
Shortcode template conditional dashboard-scoped links
templates/shortcode.php
Computes $target_blank and $dashboard_base. Updates document, section, article, and "view details" links to conditionally use dashboard-scoped doc_id URLs or fallback to get_permalink(). Applies consistent esc_url() escaping and shared $target_blank.
Block-theme header/footer refactor
templates/single-docs.php
Eliminates pre-buffered header/footer HTML. Now directly emits minimal block-theme skeleton (DOCTYPE, wp_head(), wp_body_open(), .wp-site-blocks) and calls block_header_area()/block_footer_area() helpers inline. Preserves get_header()/get_footer() fallback for non-block themes.
Styling and responsive updates
src/assets/less/frontend.less, src/assets/less/responsive.less
Adjusts sidebar width 25%→20%, content 75%→80%. Adds .wedocs-view-details-btn styling (border, transparent bg, hover fill). Adds .dokan-wedocs-content .dokan-panel-body typography (headings, lists, blockquotes, links, code, tables). Changes mobile breakpoint 480px→425px and relocates mobile rules.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~90 minutes

Possibly related PRs

  • weDevsOfficial/wedocs-plugin#207: Both PRs modify templates/single-docs.php to refactor block-theme rendering by introducing/using block_header_area() and block_footer_area() helpers and adjusting the template flow.
  • weDevsOfficial/wedocs-plugin#213: Both PRs update includes/Post_Types.php's docs post-type supports array — this PR adds custom-fields, the retrieved PR adds elementor.

Suggested labels

Needs Review, Need Testing

Suggested reviewers

  • iftakharul-islam
  • sapayth

Poem

🐇 Hop, hop! The vendor's got a docs dashboard now,
With Dokan menus, meta flags, and sidebar collapsed just so,
A gating hook guards vendor slots with a pro-check bow,
Templates and AJAX endpoints join the warren's flow,
From 480px to 425px, breakpoints shrink and grow—
No doc left untagged, no link unescaped below! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main feature: adding documentation support to the Dokan vendor dashboard, which aligns with the extensive changes across frontend, backend, and template files.
Docstring Coverage ✅ Passed Docstring coverage is 84.62% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 PHPStan (2.2.2)

PHP Fatal error: Uncaught Error: Undefined constant "ABSPATH" in /includes/functions.php:423
Stack trace:
#0 /includes/functions.php(397): wedocs_is_plugin_active()
#1 /vendor/composer/autoload_real.php(39): require('...')
#2 /vendor/composer/autoload_real.php(43): {closure}()
#3 /vendor/autoload.php(25): ComposerAutoloaderInit7cbf31d16174c9dcebc13fd948b54b78::getLoader()
#4 phar:///usr/bin/phpstan/bin/phpstan(46): require_once('...')
#5 phar:///usr/bin/phpstan/bin/phpstan(107): _PHPStan_2874a496b{closure}()
#6 /usr/bin/phpstan(7): require('...')
#7 {main}
thrown in /includes/functions.php on line 423
Fatal error: Uncaught Error: Undefined constant "ABSPATH" in /includes/functions.php:423
Stack trace:
#0 /includes/functions.php(397): wedocs_is_plugin_active()
#1 /vendor/composer/autoload_real.php(39): require('...')
#2 /vendor/composer/autoload_real.php(43): {closure}()
#3 /vendor/autoload.php(25): ComposerAutoloaderInit7cbf31d16174c9dcebc13fd948b54b78::getLoader()
#4 phar:///usr/bin/phpstan/bin/phpstan(46): require_once('...')
#5 phar:///usr/bin/phpstan/bin/phpstan(107): _PHPStan_2874a496b{closure}()
#6 /usr/bin/phpstan(7): require('...')
#7 {main}
thrown in /includes/functions.php on line 423


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.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
includes/Frontend.php (1)

91-119: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove the duplicated localization keys.

The second half of this array overwrites the new values you just added, so isSingleDoc ends up hard-coded to true again and the dashboard-aware frontend state is only partially applied.

Suggested fix
         wp_localize_script( 'wedocs-scripts', 'weDocs_Vars', [
             'nonce'             => wp_create_nonce( 'wedocs-ajax' ),
             'style'             => WEDOCS_ASSETS . '/build/print.css?v=10',
+            'assetsUrl'         => WEDOCS_ASSETS,
             'ajaxurl'           => admin_url( 'admin-ajax.php' ),
             'powered'           => sprintf( '&copy; %s, %d. %s<br>%s', get_bloginfo( 'name' ), date( 'Y' ), __( 'Powered by weDocs plugin for WordPress', 'wedocs' ), home_url() ),
             'isSingleDoc'       => is_singular( 'docs' ),
             'isVendorDashboard' => $this->is_dokan_vendor_dashboard(),
             'vendorDocsBaseUrl' => $this->is_dokan_vendor_dashboard() && function_exists( 'dokan_get_navigation_url' )
                 ? trailingslashit( dokan_get_navigation_url( 'docs' ) )
                 : '',
             'searchModal'       => $searchModal,
             'docNavLabel'       => __( 'Doc: ', 'wedocs' ),
             'searchBlankMsg'    => __( 'Search field cannot be blank', 'wedocs' ),
             'searchEmptyMsg'    => __( 'Your search didn\'t match any documents', 'wedocs' ),
             'sectionNavLabel'   => __( 'Section: ', 'wedocs' ),
             'searchModalColors' => wedocs_get_search_modal_active_colors(),
-            'nonce'             => wp_create_nonce( 'wedocs-ajax' ),
-            'style'             => WEDOCS_ASSETS . '/build/print.css?v=10',
-            'assetsUrl'         => WEDOCS_ASSETS,
-            'ajaxurl'           => admin_url( 'admin-ajax.php' ),
-            'powered'           => sprintf( '&copy; %s, %d. %s<br>%s', get_bloginfo( 'name' ), date( 'Y' ), __( 'Powered by weDocs plugin for WordPress', 'wedocs' ), home_url() ),
-            'isSingleDoc'       => true, // Always enable search modal functionality
-            'searchModal'       => $searchModal,
-            'docNavLabel'       => __( 'Doc: ', 'wedocs' ),
-            'searchBlankMsg'    => __( 'Search field cannot be blank', 'wedocs' ),
-            'searchEmptyMsg'    => __( 'Your search didn\'t match any documents', 'wedocs' ),
-            'sectionNavLabel'   => __( 'Section: ', 'wedocs' ),
-            'searchModalColors' => wedocs_get_search_modal_active_colors(),
         ] );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@includes/Frontend.php` around lines 91 - 119, The wp_localize_script call for
'weDocs_Vars' contains duplicated keys (nonce, style, ajaxurl, powered,
isSingleDoc, searchModal, docNavLabel, searchBlankMsg, searchEmptyMsg,
sectionNavLabel, searchModalColors, assetsUrl, vendorDocsBaseUrl) where the
second group overwrites the first and forces isSingleDoc to true; remove the
duplicate second half and keep the original entries that reference
is_singular('docs'), $this->is_dokan_vendor_dashboard(), vendorDocsBaseUrl
logic, $searchModal and wedocs_get_search_modal_active_colors() so the localized
data reflects the intended dashboard-aware state and newly added values.
assets/js/frontend.js (1)

379-383: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use dashboard-aware target for breadcrumb/path clicks too.

Line 382 still hardcodes _blank, so parent/section path clicks ignore the new vendor-dashboard _self behavior.

💡 Proposed fix
-            window.open( $( this ).data( 'url' ), '_blank' );
+            window.open(
+              $( this ).data( 'url' ),
+              weDocs_Vars.isVendorDashboard ? '_self' : '_blank'
+            );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/js/frontend.js` around lines 379 - 383, The click handler attached to
liNode.querySelectorAll('.doc-search-hit-path') currently hardcodes
window.open(..., '_blank'); change it to use the same dashboard-aware target
logic as other search/link handlers: compute a target from the element (e.g.
const target = $(this).data('target') || '_blank') and call
window.open($(this).data('url'), target) so path/breadcrumb clicks respect the
vendor-dashboard `_self` behavior instead of always opening in a new tab.
src/components/AddDocModal.js (1)

47-63: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enforce gating again at submit time.

Line 33 blocks gated selection changes, but createDoc() (Line 47 onward) does not re-check gating. If gating flips after selection, a vendor doc can still be submitted.

💡 Suggested fix
  const createDoc = () => {
    if ( newDoc.title.raw === '' ) {
      setFormError( true );
      return;
    }
+   if ( selectedVisibility.value === '1' && isGated ) {
+      setIsUpgradeOpen( true );
+      return;
+   }

    // Make it disabled for creating a doc.
    setDisabled( true );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/AddDocModal.js` around lines 47 - 63, createDoc is not
re-checking the current gating state before submitting, so a vendor doc can
still be created if gating flipped after selection; before building docData or
dispatching DOCS_STORE.createDoc, read the current gating state (e.g.
vendorGatingEnabled / isVendorGatingEnabled() or the relevant prop/state used to
block selection earlier) and if gating is enabled and selectedVisibility.value
is true either (a) setFormError(true) and return to block submission or (b)
override meta._is_vendor_doc to false to enforce the gate; ensure this check
happens immediately before setDisabled(true) or before creating docData so
createDoc, meta._is_vendor_doc and DOCS_STORE.createDoc cannot proceed with an
invalid vendor flag.
🧹 Nitpick comments (1)
src/assets/less/frontend.less (1)

317-336: ⚡ Quick win

Consider extracting the hardcoded color to a LESS variable.

The color #3B82F6 is hardcoded here and appears in several other places (lines 403, 432, 670). The rest of the stylesheet uses variables like @mainColor and @borderColor for consistency and maintainability.

♻️ Suggested approach

Define a variable in src/assets/less/variables.less:

`@accentColor`: `#3B82F6`;

Then use it consistently:

 .wedocs-doc-link {
     .wedocs-view-details-btn {
         display: inline-block;
         padding: 10px 24px;
         font-size: 14px;
         font-weight: 500;
         line-height: 1.5;
-        color: `#3B82F6`;
+        color: `@accentColor`;
         background: transparent;
-        border: 1px solid `#3B82F6`;
+        border: 1px solid `@accentColor`;
         border-radius: 6px;
         text-decoration: none;
         transition: background 0.2s, color 0.2s;

         &:hover {
             color: `#fff`;
-            background: `#3B82F6`;
+            background: `@accentColor`;
         }
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/assets/less/frontend.less` around lines 317 - 336, The .wedocs-doc-link
.wedocs-view-details-btn rule hardcodes the color `#3B82F6`; define a LESS
variable (e.g. `@accentColor`) in variables.less and replace this hex in the
.wedocs-view-details-btn declarations (color, border, &:hover background) with
`@accentColor`, and update the other occurrences (the other places using `#3B82F6`)
to use `@accentColor` so the stylesheet remains consistent and maintainable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@includes/Dokan/VendorDashboard.php`:
- Around line 118-129: The template is required while only a local $post exists,
so before requiring vendor-single-doc.php assign the fetched post to the global
$post and call setup_postdata( $post ) so template functions and the_content
filters run in the correct context, then call wp_reset_postdata() immediately
after the require; locate the code that sets $post = get_post( $doc_id ) and the
require WEDOCS_PATH . '/templates/vendor-single-doc.php' and wrap the require
with global $post assignment, setup_postdata( $post ), and wp_reset_postdata().

In `@includes/Frontend.php`:
- Around line 179-217: The exclusion misses cases where post_type is an array
and where an existing meta_query with relation 'OR' allows vendor docs to pass;
in exclude_vendor_docs change the post_type check to handle arrays (use
in_array('docs', (array) $post_type) or similar) and when adding
wedocs_exclude_vendor_doc_meta_query() ensure the overall meta_query enforces
AND semantics (if meta_query has a 'relation' of 'OR' or no relation, wrap
existing clauses and the new exclusion into a new meta_query with 'relation' =>
'AND' or set relation to 'AND' before appending) so the vendor-exclusion clause
cannot be bypassed.

In `@includes/Post_Types.php`:
- Around line 25-27: The propagation currently only hooks
propagate_vendor_doc_meta to 'updated_postmeta', missing the case where
_is_vendor_doc is newly added; update the hooks to also attach
propagate_vendor_doc_meta to 'added_postmeta' (and similarly add the same
'added_postmeta' listener in the other block around the
propagate_vendor_doc_meta registration at lines ~210-217) so that both updated
and newly created _is_vendor_doc meta changes trigger the
propagate_vendor_doc_meta method; keep the same callback signature and priority
when registering to 'added_postmeta' and ensure inherit_vendor_doc_meta remains
attached to 'rest_after_insert_docs' as-is.
- Around line 166-177: The inherit_vendor_doc_meta function only sets
'_is_vendor_doc' when the computed root is vendor but never clears it; modify
inherit_vendor_doc_meta to check the computed $root_id via
get_post_ancestors/get_post_parent and then if get_post_meta($root_id,
'_is_vendor_doc', true) === '1' call update_post_meta($post->ID,
'_is_vendor_doc', '1'), otherwise remove/clear the flag (use
delete_post_meta($post->ID, '_is_vendor_doc') or update_post_meta($post->ID,
'_is_vendor_doc', '0')). Ensure you change the branch that currently only
updates when '1' to handle the else case so stale vendor flags are removed when
the post is reparented to a non-vendor root.

In `@src/assets/less/frontend.less`:
- Line 29: The sidebar width was changed to 20% (selector
.wedocs-single-sidebar) but .wedocs-single-content still uses 75%, leaving a 5%
gap; update .wedocs-single-content to 80% (or switch both selectors to a flex
layout and use flex: 0 0 20% and flex: 1 for content) so the sidebar and content
widths sum to 100% and eliminate the whitespace issue.

In `@src/assets/less/responsive.less`:
- Line 84: The CSS media query in responsive.less uses `@media` (max-width: 425px)
while block-helpers.js treats mobile as window.innerWidth <= 480, causing
mismatched behavior for 426–480px; update one side so they match: either change
the responsive.less breakpoint to `@media` (max-width: 480px) (affecting
.wedocs-hide-mobile and related spacing overrides) or adjust block-helpers.js
mobile threshold to <= 425 to match CSS, or alternatively add an explicit
426–480px rule in responsive.less to cover that range; pick the consistent
breakpoint and run the UI at widths ~426–480px to verify .wedocs-hide-mobile and
spacing behave as expected.

In `@src/components/AddDocModal.js`:
- Around line 21-28: visibilityOptions is recreated each render so
selectedVisibility must be a primitive ('0'|'1') instead of an option object to
keep Listbox selection stable; change the useState for selectedVisibility to
initialize to '0' (visibilityOptions[0].value), update all setSelectedVisibility
calls to pass the option.value instead of the whole option object, ensure the
Listbox value/selected comparison uses the primitive selectedVisibility against
option.value (or map options to provide value), and update the reset after
creation (the setSelectedVisibility(...) call) to reset to the primitive '0'
rather than visibilityOptions[0].

In `@src/components/DocActions.js`:
- Around line 128-135: The interactive span used for toggling vendor docs is not
keyboard-accessible; replace the <span> with a real <button> element in the
DocActions component so keyboard and assistive tech can activate it, keep the
same onClick handler (toggleVendorDoc) and className, add type="button" to
prevent form submits, and include an accessible state attribute such as
aria-pressed={isVendorDoc} (or aria-checked if you prefer a checkbox semantics)
so screen readers announce the current state when type === 'doc' and the label
still reads based on isVendorDoc.

In `@src/hooks/useVendorDocGating.js`:
- Around line 18-21: The selector for vendorDocCount assumes
select(DOCS_STORE).getDocs() returns an array and calls .filter(), which can
throw if getDocs() is undefined/null; update the useSelect callback in
useVendorDocGating.js (the vendorDocCount selector) to guard the getDocs()
result (from select(DOCS_STORE).getDocs())—e.g., check Array.isArray(docs) or
coalesce to [] before calling .filter()—so filtering only runs on a valid array
and the modal/actions render path won’t break during store hydration.

In `@templates/single-docs.php`:
- Around line 29-42: Move rendering of block template parts so their enqueued
head assets are printed before wp_head(); specifically, call block_header_area()
(and ensure any block-footer rendering like block_footer_area() if present near
the bottom) before invoking wp_head() in the template. Edit the template around
the current wp_head() call to render block_header_area() (and any top-level
block template parts that register head assets) immediately prior to wp_head(),
and confirm block_footer_area() is rendered in a location that allows its
head-registered assets to be output before the closing head if needed.

---

Outside diff comments:
In `@assets/js/frontend.js`:
- Around line 379-383: The click handler attached to
liNode.querySelectorAll('.doc-search-hit-path') currently hardcodes
window.open(..., '_blank'); change it to use the same dashboard-aware target
logic as other search/link handlers: compute a target from the element (e.g.
const target = $(this).data('target') || '_blank') and call
window.open($(this).data('url'), target) so path/breadcrumb clicks respect the
vendor-dashboard `_self` behavior instead of always opening in a new tab.

In `@includes/Frontend.php`:
- Around line 91-119: The wp_localize_script call for 'weDocs_Vars' contains
duplicated keys (nonce, style, ajaxurl, powered, isSingleDoc, searchModal,
docNavLabel, searchBlankMsg, searchEmptyMsg, sectionNavLabel, searchModalColors,
assetsUrl, vendorDocsBaseUrl) where the second group overwrites the first and
forces isSingleDoc to true; remove the duplicate second half and keep the
original entries that reference is_singular('docs'),
$this->is_dokan_vendor_dashboard(), vendorDocsBaseUrl logic, $searchModal and
wedocs_get_search_modal_active_colors() so the localized data reflects the
intended dashboard-aware state and newly added values.

In `@src/components/AddDocModal.js`:
- Around line 47-63: createDoc is not re-checking the current gating state
before submitting, so a vendor doc can still be created if gating flipped after
selection; before building docData or dispatching DOCS_STORE.createDoc, read the
current gating state (e.g. vendorGatingEnabled / isVendorGatingEnabled() or the
relevant prop/state used to block selection earlier) and if gating is enabled
and selectedVisibility.value is true either (a) setFormError(true) and return to
block submission or (b) override meta._is_vendor_doc to false to enforce the
gate; ensure this check happens immediately before setDisabled(true) or before
creating docData so createDoc, meta._is_vendor_doc and DOCS_STORE.createDoc
cannot proceed with an invalid vendor flag.

---

Nitpick comments:
In `@src/assets/less/frontend.less`:
- Around line 317-336: The .wedocs-doc-link .wedocs-view-details-btn rule
hardcodes the color `#3B82F6`; define a LESS variable (e.g. `@accentColor`) in
variables.less and replace this hex in the .wedocs-view-details-btn declarations
(color, border, &:hover background) with `@accentColor`, and update the other
occurrences (the other places using `#3B82F6`) to use `@accentColor` so the
stylesheet remains consistent and maintainable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 88e5b7bd-5465-4ff0-9d50-09ce229f7ad8

📥 Commits

Reviewing files that changed from the base of the PR and between 3b31f16 and 7ba5d02.

📒 Files selected for processing (21)
  • assets/js/frontend.js
  • includes/API/API.php
  • includes/Ajax.php
  • includes/Dokan/VendorDashboard.php
  • includes/Frontend.php
  • includes/Post_Types.php
  • includes/Shortcode.php
  • includes/functions.php
  • package.json
  • src/assets/less/frontend.less
  • src/assets/less/responsive.less
  • src/components/AddDocModal.js
  • src/components/DocActions.js
  • src/components/Documentations/ParentDocs.js
  • src/components/ProPreviews/common/UpgradePopup.js
  • src/hooks/useVendorDocGating.js
  • templates/shortcode.php
  • templates/single-docs.php
  • templates/vendor-docs.php
  • templates/vendor-single-doc.php
  • wedocs.php

Comment thread includes/Dokan/VendorDashboard.php Outdated
Comment thread includes/Frontend.php
Comment thread includes/Post_Types.php
Comment thread includes/Post_Types.php
Comment thread src/assets/less/frontend.less
}

@media screen and (max-width: 480px) {
@media screen and (max-width: 425px) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check for any related mobile breakpoint references or documentation

# Search for other mobile breakpoint values or related comments
rg -n -C2 '(max-width|min-width).*4[2-8][0-9]px' --glob '*.less' --glob '*.css' --glob '*.js'

# Look for any documentation or comments about breakpoints
rg -n -i 'breakpoint|responsive|mobile.*width' --glob '*.md' --glob '*.txt'

Repository: weDevsOfficial/wedocs-plugin

Length of output: 1082


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Occurrences of 480px and similar =="
rg -n --fixed-string "480px" --glob '*.less' --glob '*.css' --glob '*.js' --glob '*.md' || true
rg -n --fixed-string "max-width: 480px" --glob '*.less' --glob '*.css' --glob '*.js' --glob '*.md' || true

echo
echo "== Occurrences of 425px =="
rg -n --fixed-string "425px" --glob '*.less' --glob '*.css' --glob '*.js' --glob '*.md' || true

echo
echo "== Context around responsive.less line 84 =="
sed -n '60,110p' src/assets/less/responsive.less

Repository: weDevsOfficial/wedocs-plugin

Length of output: 2536


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Occurrences of literal '480px' =="
rg -n --fixed-strings "480px" --glob '*.less' --glob '*.css' --glob '*.js' --glob '*.md' || true
rg -n --fixed-strings "max-width: 480px" --glob '*.less' --glob '*.css' --glob '*.js' --glob '*.md' || true

echo
echo "== Occurrences of literal '425px' =="
rg -n --fixed-strings "425px" --glob '*.less' --glob '*.css' --glob '*.js' --glob '*.md' || true

echo
echo "== Context around src/assets/less/responsive.less line 84 =="
sed -n '70,105p' src/assets/less/responsive.less

Repository: weDevsOfficial/wedocs-plugin

Length of output: 959


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for numeric breakpoint values involving 480 (without requiring 'px') =="
rg -n --hidden --glob '!*node_modules*' --glob '*.{php,js,ts,jsx,tsx,less,css}' '\b480\b' . || true
rg -n --hidden --glob '!*node_modules*' --glob '*.{php,js,ts,jsx,tsx,less,css}' '4[0-9]{2}\s*(px)?' . || true

echo
echo "== Locate getBreakpoints() implementation referenced in src/blocks/helpers/README.md =="
rg -n --hidden --glob '*.{php,js,ts}' 'function\s+getBreakpoints|getBreakpoints\s*\(' . || true

echo
echo "== Dump candidate breakpoint utility files (small) =="
fd -t f -e php -e js -e ts -a getBreakpoints . 2>/dev/null || true

Repository: weDevsOfficial/wedocs-plugin

Length of output: 50385


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== responsive.less: occurrences of search modal within file =="
rg -n "search-modal" src/assets/less/responsive.less || true
echo
echo "== responsive.less: show full 425px media query block (best-effort) =="
# Print from line with 425px through next closing brace at same indentation (approx).
# Keep output bounded.
start=$(rg -n "max-width:\s*425px" src/assets/less/responsive.less | head -n1 | cut -d: -f1)
if [[ -n "${start}" ]]; then
  end=$((start+140))
  sed -n "${start},${end}p" src/assets/less/responsive.less
else
  echo "No 425px block found."
fi

echo
echo "== block-helpers.js: getBreakpoints / mobile breakpoint mapping =="
rg -n "getBreakpoints|mobile:\s*480|isBreakpoint" src/blocks/helpers/block-helpers.js
echo
echo "== block-helpers.js: context around mobile: 480 =="
ln=$(rg -n "mobile:\s*480" src/blocks/helpers/block-helpers.js | head -n1 | cut -d: -f1)
if [[ -n "${ln}" ]]; then
  sed -n "$((ln-20)),$((ln+40))p" src/blocks/helpers/block-helpers.js
fi

Repository: weDevsOfficial/wedocs-plugin

Length of output: 2942


Align mobile breakpoint logic (425px CSS vs 480px JS)

src/assets/less/responsive.less applies the mobile-hiding and related spacing overrides only under @media ... (max-width: 425px) (including .wedocs-hide-mobile). Meanwhile src/blocks/helpers/block-helpers.js defines the mobile breakpoint as window.innerWidth <= 480. Devices ~426–480px can therefore be treated as “mobile” by JS but won’t receive these CSS overrides. Confirm the intended threshold and align the CSS/JS breakpoints (or add a 426–480px-specific rule) and test on those sizes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/assets/less/responsive.less` at line 84, The CSS media query in
responsive.less uses `@media` (max-width: 425px) while block-helpers.js treats
mobile as window.innerWidth <= 480, causing mismatched behavior for 426–480px;
update one side so they match: either change the responsive.less breakpoint to
`@media` (max-width: 480px) (affecting .wedocs-hide-mobile and related spacing
overrides) or adjust block-helpers.js mobile threshold to <= 425 to match CSS,
or alternatively add an explicit 426–480px rule in responsive.less to cover that
range; pick the consistent breakpoint and run the UI at widths ~426–480px to
verify .wedocs-hide-mobile and spacing behave as expected.

Comment on lines +21 to +28
const visibilityOptions = [
{ value: '0', label: __( 'Regular Doc', 'wedocs' ) },
{ value: '1', label: __( 'Dokan vendor doc', 'wedocs' ) },
];

const [ formError, setFormError ] = useState( false );
const [ selectedVisibility, setSelectedVisibility ] = useState( visibilityOptions[ 0 ] );
const [ isUpgradeOpen, setIsUpgradeOpen ] = useState( false );

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/components/AddDocModal.js"
echo "== File: $FILE =="
ls -la "$FILE" || true
echo

echo "== Lines 1-260 (context) =="
sed -n '1,260p' "$FILE" | nl -ba | sed -n '1,260p'

echo
echo "== Extract visibilityOptions / selectedVisibility occurrences =="
rg -n "visibilityOptions|selectedVisibility|onVisibilityChange|Listbox" "$FILE" || true

echo
echo "== Extract meta usage (_is_vendor_doc) =="
rg -n "_is_vendor_doc" "$FILE" || true

Repository: weDevsOfficial/wedocs-plugin

Length of output: 285


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/components/AddDocModal.js"
echo "== Quick head =="
sed -n '1,120p' "$FILE" | sed -n '1,120p'

echo
echo "== Visibility/Listbox-related block (look around 1-260) =="
sed -n '1,260p' "$FILE" | sed -n '1,260p'

echo
echo "== Exact line matches =="
rg -n "visibilityOptions|selectedVisibility|onVisibilityChange|Listbox|_is_vendor_doc" "$FILE" || true

echo
echo "== Show the Listbox component region =="
# Print some surrounding lines for the first Listbox occurrence
LINE=$(rg -n "Listbox" "$FILE" | head -n1 | cut -d: -f1 || true)
if [[ -n "${LINE:-}" ]]; then
  START=$((LINE-40)); END=$((LINE+60))
  (( START<1 )) && START=1
  sed -n "${START},${END}p" "$FILE"
fi

Repository: weDevsOfficial/wedocs-plugin

Length of output: 17837


🌐 Web query:

Headless UI Listbox value comparison by reference Object.is selected option

💡 Result:

By default, the Headless UI Listbox component determines if an option is selected by comparing the object provided to the value prop with the values of the ListboxOption components using strict equality (===) [1][2]. If you are working with objects that do not share the exact same memory reference—a common occurrence when data is fetched, transformed, or recreated during re-renders—the selection state will fail to track correctly [3][4]. To resolve this and avoid reliance on object reference equality, you should use the by prop [1][5]. The by prop allows you to define how items are compared [1][6]. 1. Comparing by a field: If your objects have a unique identifier (like an id), you can pass the key as a string to the by prop. The Listbox will then compare the objects based on that property [1][5]. ... 2. Custom comparison function: For more complex requirements, you can pass a function to the by prop that takes two arguments (the two objects to compare) and returns a boolean [1][5]. <Listbox value={selectedDepartment} by={(a, b) => a.id === b.id} onChange={onChange}>... Using the by prop is the recommended approach for handling objects in Headless UI, as it prevents bugs associated with object identity across re-renders [3][4]. Alternatively, you can use primitive values (like a string or number ID) as the value for the Listbox, which naturally support strict equality [7][4].

Citations:


Store selectedVisibility as a primitive ('0'|'1') for Listbox selection to stay in sync across renders.

File: src/components/AddDocModal.js
Lines: 21-28

  const visibilityOptions = [
    { value: '0', label: __( 'Regular Doc', 'wedocs' ) },
    { value: '1', label: __( 'Dokan vendor doc', 'wedocs' ) },
  ];

  const [ formError, setFormError ] = useState( false );
  const [ selectedVisibility, setSelectedVisibility ] = useState( visibilityOptions[ 0 ] );
  const [ isUpgradeOpen, setIsUpgradeOpen ] = useState( false );

visibilityOptions is recreated every render, but Listbox compares the value prop to each option using strict equality by default—so keeping selectedVisibility as an option object can break the selected/highlighted state after rerenders (even though the label may still display).

Also applies to: 194-234

💡 Suggested direction
- const [ selectedVisibility, setSelectedVisibility ] = useState( visibilityOptions[ 0 ] );
+ const [ selectedVisibility, setSelectedVisibility ] = useState( '0' );

- const onVisibilityChange = ( option ) => {
-   if ( option.value === '1' && isGated ) {
+ const onVisibilityChange = ( value ) => {
+   if ( value === '1' && isGated ) {
      setIsUpgradeOpen( true );
      return;
    }
-   setSelectedVisibility( option );
+   setSelectedVisibility( value );
  };

- <Listbox value={ selectedVisibility } onChange={ onVisibilityChange }>
+ <Listbox value={ selectedVisibility } onChange={ onVisibilityChange }>

- <span className="block truncate">{ selectedVisibility.label }</span>
+ <span className="block truncate">
+   { visibilityOptions.find( ( opt ) => opt.value === selectedVisibility )?.label }
+ </span>

- value={ option }
+ value={ option.value }

- meta: { _is_vendor_doc: selectedVisibility.value },
+ meta: { _is_vendor_doc: selectedVisibility },

Also update the reset after successful creation (setSelectedVisibility( visibilityOptions[0] )) to reset the primitive (e.g., '0').

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/AddDocModal.js` around lines 21 - 28, visibilityOptions is
recreated each render so selectedVisibility must be a primitive ('0'|'1')
instead of an option object to keep Listbox selection stable; change the
useState for selectedVisibility to initialize to '0'
(visibilityOptions[0].value), update all setSelectedVisibility calls to pass the
option.value instead of the whole option object, ensure the Listbox
value/selected comparison uses the primitive selectedVisibility against
option.value (or map options to provide value), and update the reset after
creation (the setSelectedVisibility(...) call) to reset to the primitive '0'
rather than visibilityOptions[0].

Comment thread src/components/DocActions.js
Comment thread src/hooks/useVendorDocGating.js
Comment thread templates/single-docs.php
Comment on lines 29 to +42
if (function_exists('wp_is_block_theme') && wp_is_block_theme()) {
/**
* Pre-render block header and footer before wp_head() so the Interactivity API
* import map and script modules are properly discovered and registered.
* This mirrors how template-canvas.php calls get_the_block_template_html() before <head>.
*/
ob_start();
block_header_area();
$block_header_html = ob_get_clean();

ob_start();
block_footer_area();
$block_footer_html = ob_get_clean();
?>
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>

<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>

<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<div class="wp-site-blocks">
<?php echo $block_header_html; ?>
<?php
} else {
get_header();
}
/**
* The template for displaying a single doc
*
* To customize this template, create a folder in your current theme named "wedocs" and copy it there.
*/
$skip_sidebar = (get_post_meta($post->ID, 'skip_sidebar', true) == 'yes') ? true : false;
<?php wp_body_open(); ?>
<div class="wp-site-blocks">
<?php block_header_area(); ?>
<?php

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the target file and print the relevant portions with line numbers
ls -la templates/single-docs.php || true
sed -n '1,260p' templates/single-docs.php | nl -ba | sed -n '1,260p'

# Also search for block_header_area/block_footer_area and any existing buffering
rg -n "block_header_area|block_footer_area|wp_head\\(|wp_footer\\(|ob_start\\(|ob_get_clean\\(|wp_body_open\\(" templates/single-docs.php templates -S || true

Repository: weDevsOfficial/wedocs-plugin

Length of output: 208


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== File head/tail with line numbers ==="
cat -n templates/single-docs.php | sed -n '1,140p'
cat -n templates/single-docs.php | sed -n '140,260p'

echo "=== Focused searches ==="
rg -n "block_header_area|block_footer_area|wp_head\\(|wp_footer\\(|ob_start\\(|ob_get_clean\\(|wp_body_open\\(" templates/single-docs.php || true

echo "=== Snippet around the suspected wrapper order ==="
cat -n templates/single-docs.php | sed -n '20,90p'
cat -n templates/single-docs.php | sed -n '170,230p'

Repository: weDevsOfficial/wedocs-plugin

Length of output: 15209


Render the block template parts before wp_head() so block-enqueued assets land in the current head.

In templates/single-docs.php (block-theme path), wp_head() runs at line 36 before block_header_area() (line 41) and before block_footer_area() (line 196). Any styles/script modules registered while those block template parts render occur too late for the already-printed <head>, leaving block-theme headers/footers unstyled or breaking interactive blocks on first load.

Proposed fix
 if (function_exists('wp_is_block_theme') && wp_is_block_theme()) {
+    ob_start();
+    block_header_area();
+    $block_header = ob_get_clean();
+
+    ob_start();
+    block_footer_area();
+    $block_footer = ob_get_clean();
     ?>
     <!DOCTYPE html>
     <html <?php language_attributes(); ?>>
     <head>
         <meta charset="<?php bloginfo( 'charset' ); ?>">
@@
     <body <?php body_class(); ?>>
     <?php wp_body_open(); ?>
     <div class="wp-site-blocks">
-        <?php block_header_area(); ?>
+        <?php echo $block_header; ?>
 <?php
 } else {
     get_header();
 }
@@
     // Close out based on theme type
     if (function_exists('wp_is_block_theme') && wp_is_block_theme()) {
         ?>
-            <?php block_footer_area(); ?>
+            <?php echo $block_footer; ?>
         </div><!-- .wp-site-blocks -->
         <?php wp_footer(); ?>
         </body>
         </html>
         <?php
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (function_exists('wp_is_block_theme') && wp_is_block_theme()) {
/**
* Pre-render block header and footer before wp_head() so the Interactivity API
* import map and script modules are properly discovered and registered.
* This mirrors how template-canvas.php calls get_the_block_template_html() before <head>.
*/
ob_start();
block_header_area();
$block_header_html = ob_get_clean();
ob_start();
block_footer_area();
$block_footer_html = ob_get_clean();
?>
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<div class="wp-site-blocks">
<?php echo $block_header_html; ?>
<?php
} else {
get_header();
}
/**
* The template for displaying a single doc
*
* To customize this template, create a folder in your current theme named "wedocs" and copy it there.
*/
$skip_sidebar = (get_post_meta($post->ID, 'skip_sidebar', true) == 'yes') ? true : false;
<?php wp_body_open(); ?>
<div class="wp-site-blocks">
<?php block_header_area(); ?>
<?php
if (function_exists('wp_is_block_theme') && wp_is_block_theme()) {
ob_start();
block_header_area();
$block_header = ob_get_clean();
ob_start();
block_footer_area();
$block_footer = ob_get_clean();
?>
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<div class="wp-site-blocks">
<?php echo $block_header; ?>
<?php
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@templates/single-docs.php` around lines 29 - 42, Move rendering of block
template parts so their enqueued head assets are printed before wp_head();
specifically, call block_header_area() (and ensure any block-footer rendering
like block_footer_area() if present near the bottom) before invoking wp_head()
in the template. Edit the template around the current wp_head() call to render
block_header_area() (and any top-level block template parts that register head
assets) immediately prior to wp_head(), and confirm block_footer_area() is
rendered in a location that allows its head-registered assets to be output
before the closing head if needed.

@iftakharul-islam iftakharul-islam self-assigned this Jun 19, 2026
VendorDashboard: Use a local $doc variable and set the global $post before including the vendor doc template. Call setup_postdata() so template tags and the_content filters run in the correct context, and wp_reset_postdata() afterwards to restore global state.

Frontend: Harden exclude_vendor_docs by handling post_type as a string or array (using in_array). Improve meta_query handling: if no clauses exist, set the exclusion as the sole clause; if clauses exist, wrap them and the exclusion in an explicit AND relation so pre-existing OR relations can't let vendor docs slip through. Uses wedocs_exclude_vendor_doc_meta_query() for the exclusion clause.
Listen to both added_postmeta and updated_postmeta so the vendor-doc flag is propagated when the meta row is created as well as when it's changed. Also ensure when a root is not a vendor doc we explicitly set _is_vendor_doc to '0' to clear stale flags (prevents reparented docs from retaining vendor visibility).
Increase single-doc content width to 80% for better layout. Add by="value" to the Listbox in AddDocModal to ensure correct item comparison/selection. Replace a span with a <button type="button"> for the vendor-doc toggle in DocActions to improve semantics and click behavior. Add a fallback (|| []) to getDocs() in useVendorDocGating to avoid errors when the docs selector returns undefined.
@iftakharul-islam iftakharul-islam merged commit 705d6fe into weDevsOfficial:develop Jun 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants