== Changelog ==

Complete release history for Shop Manager for WooCommerce.

WordPress.org truncates the changelog in readme.txt at 5,000 words, so readme.txt
carries only the most recent releases and this file keeps every entry.

= 1.3.6 =
* 🐛 Fix: Changing an order's status could kill the request with a fatal "allowed memory size exhausted" error on a store with real history. Every status change re-runs the customer tagging rules, and those were gathered with four unbounded queries, one of which loaded every paid order that customer had ever placed as a full order object. On a customer with **12,500 orders** behind them that used more than 256MB and the change failed outright, from the order page and from the bulk action alike. The same five figures now come from one grouped query: the operation runs in **181ms at the normal WordPress memory baseline**, and the tags it produces are unchanged, including the exact boundary of the "recent orders" window.
* 🐛 Fix: The AI assistant panel was mounted on every page for every employee, even when the button that opens it was hidden because their role does not include AI access. It asked for the conversation list as soon as it mounted, so those staff saw "You are not allowed to access this resource" on each page load. The panel now follows the same rule as its button.
* 🐛 Fix: Printing shipping labels and using the Scan panel ignored the **Shipping & Tracking** permission. Any employee who could open the orders list could print labels and run the scanner, whatever their role said, and the Scan button had no permission check on it at all. The permission now decides, on the buttons and on the REST routes behind them, so hiding a button is not the only thing standing in the way. Reading a tracking number is unchanged and still comes with order access, because the number is printed on the order page beside the address: seeing it is part of seeing the order, while printing a label and scanning a parcel are warehouse work.
* 🐛 Fix: The customer list and customer profile could take close to a minute to load, or run out of memory entirely, on a store with a lot of orders. Both worked out each customer's order count and lifetime spend by fetching every order that customer had ever placed and then loading each one in full to read two fields. On a test store with **100,000 orders** the list took **57 seconds and 2.7GB** to draw ten rows; it now answers in **269ms** at the normal WordPress memory baseline, with the same figures, because the database does the counting. The refund count on a profile is queried directly rather than tallied by hand.
* 🐛 Fix: Product names containing an apostrophe or a quote appeared with raw HTML in the products list, so "Men's Classic Shirt" read as "Men&#8217;s Classic Shirt" and a size such as 10" as 10&#8243;. WordPress converts those characters when it formats a title, and the dashboard renders text rather than HTML, so the code was reaching the screen.
* ✨ Improvement: The analytics dashboard has been redesigned. The four headline figures now carry their own tinted icon and a change pill you can read at a glance, and the numbers use tabular figures so digits stay in line instead of jittering as the values update. Revenue is drawn as a soft gradient area rather than a bare line, with the Orders line in a contrasting teal instead of grey so the second series reads as data rather than as a disabled one, Orders by Status is a donut with the period's total in the middle, and Top Products reads as horizontal bars, because product names are words and words fit along a row far better than crammed under a column. The insight cards at the top are no longer four blocks of alert colour competing with the figures below: each is a clean card with a thin accent rule and a tinted icon. Every colour now comes from one palette built on translucent tints, so the whole page works in dark mode instead of glaring, and a chart series, a KPI card and a status tag can no longer drift apart.
* ✨ Improvement: Total Orders now shows what it leaves out, in figures: "11,114 cancelled · 11,112 refunded not counted". Cancelled, refunded and failed orders were always excluded from revenue and average order value, because money that was never kept is not revenue, but the count differing from All Orders on the orders page looked like a fault rather than a decision. Now it is stated under the number, for whichever period you are looking at.
* 🐛 Fix: The dashboard showed "Failed to load dashboard data" on stores with a lot of orders, and Lifetime was the worst affected. Every figure on the page was worked out by loading the matching orders into memory and adding them up one by one, and the status breakdown went further still, loading each order in full just to read its status. On a test store with **100,000 orders** that ran out of memory before it could answer. The same figures are now calculated by the database, which is what a database is for: memory use is flat at the WordPress baseline however large the shop, This Month went from **2.6 seconds to 0.14**, and Lifetime works again. Lifetime and This Year are also cached a little longer than the shorter views, since a lifetime total does not change meaningfully from one minute to the next.
* 🆕 New: Filter the orders list by **carrier**. Advanced Filters now offers the couriers you selected under Shipping → Carriers, so you can pull up everything going out with one courier, which is what you want when a courier calls about a batch or one of them is running late. It sits beside Shipping Method rather than inside it, because the two answer different questions: Shipping Method is what the customer chose at checkout (Flat rate, Free shipping), the carrier is who is actually carrying the parcel. Custom carrier is included.
* 🐛 Fix: The Shipping Method filter listed "Local pickup" twice. WooCommerce registers more than one method under that title, and the list was showing each of them.
* ✨ Improvement: Finding an order by its tracking number is now effectively instant, however large the store. The tracking numbers are kept in their own small index alongside the shipment record, so the search can jump straight to the match instead of reading every shipment in the database. Measured on a test store holding **100,000 orders**, 33,342 of them with tracking: the search went from about **520ms to 0.36ms**. The old approach got slower as a shop grew, this one does not. Scanning a label and the Scan panel's order lookup use the same index, so both got the same improvement.
* 🆕 New: Two more label sizes — **80 mm** and **58 mm thermal roll** — so the inexpensive receipt-style printers most shops already own can print shipping labels too, not just 4-inch desktop label printers. The layout tightens automatically for the narrower paper: smaller type, a barcode that still fills the width and stays scannable, and the delivery note marked with a rule instead of a background tint, because cheap thermal paper prints a pale tint as nothing. Roll lengths are kept short on purpose so you are not feeding and binning blank paper on every parcel.
* 🆕 New: Choose which couriers you actually ship with, under Shipping → Carriers. Most stores use two or three, so making your staff search a list of 151 every time is needless work — pick yours and the tracking form offers only those. Leave it empty and nothing changes: all 151 stay available. **Custom carrier** is never hidden, and an order already carrying a courier you later remove keeps it and can still be edited.
* 🆕 New: Barcode scanning. A **Scan** button on the orders list opens a panel built for a USB barcode scanner: point it at a shipping label and the order is found instantly. Choose what each scan does, either just find the order or move it to any status you like, including your own custom ones. Scan a whole trolley without touching the mouse; every parcel is listed as it goes through, with a running count of what worked and what did not, so at the end of a run you can see all thirty went out. Scanning the same parcel twice tells you it is already there instead of complaining, and an unknown barcode is reported on its own line without interrupting the next scan.
* 🆕 New: Order search now finds orders by **tracking number**. Paste or scan the number a customer quotes on the phone and their order comes straight up — previously the search only matched order numbers, names, emails and phone numbers.
* 🐛 Fix: Packing slips printed "Shipping method —" on every order created from the dashboard. Shop Manager does not add a WooCommerce shipping line when you create an order, so there was genuinely no method to show — but a dash told the packer nothing and read like a fault. The row is now left out when an order has no shipping method, and a method that a third-party plugin had hidden is recovered instead of being lost.
* 🆕 New: Packing slips now print the **carrier and tracking number**. As soon as you record tracking on an order it appears beside the payment and shipping method, so whoever packs the parcel — and whoever opens the box — can see who is carrying it. Switch it off under Print Order → Content → Carrier & Tracking No. Orders with several shipments list them on one line.
* 🆕 New: Shipping & tracking. Record the carrier and tracking number on any order — from the order page, from the row menu, or for a whole batch at once — and the dashboard shows a Tracking column so you can see at a glance which orders still need an AWB. **151 couriers across 55 countries** are built in, from FedEx, UPS, DHL and USPS to Royal Mail, Australia Post, Correios, Delhivery, Steadfast, J&T and Flash Express, each with the right tracking link already filled in. Nothing to sign up for, no API keys, no account: it works offline, in any country, on the day you install it. Shipping with someone who is not on the list? Pick "Custom carrier", type their name and their tracking link, and everything else works the same. Recording tracking never moves the order on its own: the form saves the parcel's facts and nothing else, so fixing a typo in a tracking number cannot quietly change where the order sits. When you do want both at once, the scan panel will change the status as you scan, using **your own** order statuses, custom ones included, so there is no second list of shipping states to maintain.
* 🆕 New: Shipping labels. A Label button on the order page, a Shipping Label row action, and a Print Labels bulk action open a print-ready label in a new tab and hand it to your browser's print dialog — no PDF plugin or Pro licence required. Each label carries a real scannable **Code 128 barcode** of the tracking number (or the order number, if you label parcels before the courier gives you an AWB), the delivery address with the recipient's name set large, your return address, the parcel contents as a picking list, and the delivery note your customer left at checkout. Choose A4, A5 or 4×6 inch thermal, and one or two labels per sheet.
* 🆕 New: Cash on delivery amounts on the label. Any order that has not been paid for yet prints the outstanding total in a boxed **Collect on delivery** band, so the rider knows exactly what to collect. It disappears by itself once payment is recorded — and it correctly treats a COD order sitting in Processing as still unpaid, which is where WooCommerce leaves them.
* 🆕 New: Tell customers where their parcel is. Once you record a tracking number it can be added to WooCommerce's order emails and to the customer's My Account order page automatically, with your own wording and a Track your parcel link. If you already run **Advanced Shipment Tracking**, Shop Manager hands the tracking number straight to it and stays quiet, so your customers are never told twice.
* 🆕 New: Shipping settings tab, with a live preview of the label as you change it. Set the label size, barcode, logo and return address — the address falls back to your WooCommerce store details when left blank, exactly like Invoice and Print Order — the same three colours and eight palette presets as the other two documents, and a switch for every element: carrier name, order number, tracking number, ship date, parcel weight (added up from your product weights, so there is nothing to type), amount due, contents list, SKUs, delivery note and footer.
* 🆕 New: "Shipping & Tracking" permission under Employees → Roles & Access, so warehouse staff can record tracking and print labels without invoice access. SM: Fulfillment Staff and SM: Store Manager get it automatically on update. Shipping & Tracking can also be switched off entirely from the Modules tab.
* ✨ Improvement: Bulk tracking entry is built around how a warehouse actually works. Choose the carrier and ship date once at the top, then type the tracking numbers against the order numbers — leave a row blank to skip that order. If one number is wrong, only that row is reported back; everything else you typed is saved.
* ✨ Improvement: Settings menu now runs Orders, Invoice, Print Order and Shipping in sequence and shows them as one connected group, and the Modules tab groups all four under "Order Management".

= 1.3.5 =
* 🔒 Security: Custom employee roles were treated as administrators by the frontend dashboard. A role created in Employees → Roles & Access — a "Driver" allowed only to view orders and change their status, say — saw the entire sidebar and every page, button and action in it, because only the four built-in roles were recognised as employee roles; anyone holding a custom role fell through to the "no restrictions" path. Custom roles are now recognised, so every role sees exactly what it was granted.
* 🔒 Security: The dashboard statistics endpoint (store revenue, order and customer counts, top products) was reachable by any employee role, whether or not that role was allowed to see the dashboard. It now requires dashboard or reports access, like the rest of the dashboard.
* 🔒 Security: The settings endpoint returned the complete plugin settings to every employee role, including the encrypted AI provider API key and the capability matrix of every role. Employees now receive only the settings the dashboard actually renders; administrators are unaffected.
* 🔒 Security: An employee's role is now resolved by matching against the Shop Manager roles rather than by reading whichever role happens to be first on the account, so an employee who also holds another WordPress role can no longer skip the employee permission checks.
* 🔒 Security: The WordPress admin bar is no longer shown to employees on the frontend. They were already redirected out of wp-admin, so it only offered links back to a screen they cannot open.
* 🐛 Fix: A role granted only "View Reports" had nowhere to go. Reports are widgets on the dashboard page, which is gated by "View Dashboard", so SM: Accountant — and any custom role set up the same way — landed on "Access Restricted" with an empty sidebar. Roles holding a reports capability now also have dashboard access, and Roles & Access nests View Reports and Export Reports underneath View Dashboard so the dead combination can no longer be created.
* 🐛 Fix: SM: Fulfillment Staff and SM: Store Manager held every order capability but got no Orders menu. The built-in roles carried the original coarse capabilities while the sidebar and routes check the newer per-section access capabilities. Updating grants the matching access capability to any role that needs it; the change only ever adds capabilities, so permissions you have edited yourself are left exactly as they are.
* 🐛 Fix: The customer name on the order details page opened the WordPress user editor in wp-admin, which sent you out of the dashboard entirely — and led employees to a screen they are redirected away from. It now opens that customer in the dashboard's own Customers section, and both it and the Order Count beside it now take their colour from your Appearance colour combination — the same way product names in the item list already did — with an arrow on the customer name, so it is clear which values in the card can be opened. On a guest order, or for a role without customer access, the name is shown as plain text instead of a dead link.
* 🐛 Fix: Roles & Access listed the built-in roles' permissions from a hardcoded copy instead of the roles themselves, so the checkboxes could disagree with the permissions actually in force — and because the editor saves every checkbox, opening and saving a role could silently strip a capability from it. The screen now reads the live role.
* ✨ Improvement: Order actions respond the moment you click them. Changing a status, or trashing, restoring or deleting an order, now puts the orders table into its loading state immediately; previously nothing at all happened on screen until the request came back, which on a status change that sends a customer email can be several seconds. (The remaining wait is WooCommerce sending that email inside the request — WooCommerce's own Deferred transactional emails feature, under WooCommerce → Settings → Advanced → Features, moves it to the background.)
* ✨ Improvement: The order details page now refreshes itself after a status change, with the same in-place loading overlay the orders table uses. Payment Details, Order Timeline, the status tag and the "updated by" line previously kept showing pre-change data until the page was reloaded, because only the status was patched in locally.
* ✨ Improvement: The order status tabs (All Orders, Processing, Completed and the rest) now recount after an action moves an order between statuses. They were loaded once per page view, so the numbers went stale as soon as you changed anything.
* ✨ Improvement: Changing an order's status writes the order once instead of twice, and a half-second delay that had been hardcoded into the move-to-trash action has been removed.

= 1.3.4 =
* 🆕 New: Print orders. A Print button on the order details page, a Print action in the orders list row menu, and a Print Orders bulk action open a clean, print-ready sheet in a new tab and hand it to your browser's print dialog — no PDF plugin or Pro licence required. Bulk printing puts one order per page in a single document.
* 🆕 New: Print settings tab. Choose the document title (Order, Packing Slip, Delivery Note), paper size, accent colour and logo; set your store name, address, phone and email — each falls back to your WordPress and WooCommerce settings when left blank; and toggle every section: order status, payment and shipping method, billing and shipping addresses, product images, SKU, item meta, prices, totals, customer note, internal notes and footer text. Turn prices off to print a packing slip with quantities only.
* 🆕 New: "Print Order" permission under Employees → Roles & Access, so you can let fulfilment staff print without granting invoice access. Order Printing can also be switched off entirely from the Modules tab.
* ✨ Improvement: Company details are asked for once, not twice. Invoice and Print Order both treat their company fields as *overrides* — leave one empty and it uses your WooCommerce store details, so an invoice and its packing slip can no longer drift apart. Each field's placeholder now shows the exact value that will be printed, with a link straight to your WooCommerce settings.
* ✨ Improvement: Print Order now offers the same three colours as invoices — Primary (heading, rules, section labels), Accent/Bg (table header background) and Body Text — plus the same eight palette presets, so a packing slip can carry the palette you already picked for invoices. An existing accent colour is carried over to Primary automatically.
* ✨ Improvement: The Invoice and Print Order settings screens now use the same tab names, icons and order (Company, General, Content, Colors, Footer), so what you learn on one applies to the other. Invoice adds a Template tab. Item-table options moved into Content, since they are part of what the document shows.
* ✨ Improvement: Settings menu reordered so related screens sit together — Orders, Invoice and Print Order now run in sequence and are visually connected in the sidebar, followed by Products, Customer and the rest. The Modules tab groups the same three under an "Order Management" heading.
* 🐛 Fix: Invoices printed "Your Company Name" and "123 Business St" to customers when the Invoice → Company section was left empty. Company name, address, phone and email now fall back to your WordPress site title and WooCommerce store details instead of placeholder text.
* 🆕 New: Invoices now carry a **Payment Status** tag, green for Paid and red for Unpaid, matching the tag the dashboard shows on the order screen, and it can be switched off under Invoice → Content. The invoice meta block was reordered to Order, Order Created, Payment Status, Payment Method, and then Payment Date on a settled order or Due Date on an outstanding one. All four templates show the same rows.
* 🐛 Fix: The invoice due date was hardcoded to 14 days after the order, whatever your terms said, so an invoice could read "payment is due within 30 days" and print a fourteen-day due date next to it. Days until due is now a setting under Invoice → General → Payment Terms (default 14, so nothing changes unless you change it).
* 🐛 Fix: Invoices printed bank-transfer details on orders that were already paid. Payment Information now appears only while an order still needs paying, controlled by Invoice → Footer → Show Payment Info (Only when unpaid / Always / Never). This is separate from the order's payment method, which has always been read from the order itself.
* ✨ Improvement: Payment Information left empty now uses the accounts from WooCommerce → Payments → Direct bank transfer, so your account number or IBAN is entered once, not twice.
* 🐛 Fix: Turning off "Product Add-ons & Options" in Invoice settings never stuck — the setting was dropped when saving, so it reappeared switched on after a reload and invoices kept printing the item details.

= 1.3.3 =
* 🆕 New: Product add-on and personalisation fields now show in order details. Any data a third-party add-on plugin writes to a line item — customer-entered names, uploaded artwork, selected options — appears in the order page, in the expandable row on the Orders list, and on the invoice PDF. Previously only variation attributes were shown, so everything else was dropped. This works with WooCommerce Product Add-Ons Ultimate, Gravity Forms Product Add-Ons, Checkout Field Editor and any other plugin that stores line item meta, because Shop Manager now renders it through WooCommerce's own formatter rather than a fixed list of keys.
* 🆕 New: "Product Add-ons & Options" toggle under Invoice → Columns controls whether those item details are printed on the invoice and packing slip. On by default.
* 🐛 Fix: Editing an order no longer destroys product add-on data. Saving an order from the dashboard — even a change to nothing but the shipping address — deleted and recreated every line item, which permanently discarded all add-on, personalisation and subscription meta attached to them. Line items are now updated in place, and only items you actually remove are deleted.
* 🐛 Fix: Line item details were hidden on simple products. The order page only rendered item meta for variable products, so personalised options on a simple product were invisible even when present.
* 🐛 Fix: Removing the discount from an order left an orphaned fee row behind in some cases; fee items are now removed through the order object so the change is written correctly.

= 1.3.2 =
* 🆕 New: Dashboard branding. Upload your own logo for the frontend dashboard from Appearance → Branding, with separate slots for light mode, dark mode and the collapsed sidebar icon. Each slot falls back to the Shop Manager logo when left empty, and the dark slot reuses your light logo if you only upload one.
* ✨ Improvement: Appearance tab reorganised. Settings are grouped into labelled cards (Branding, Layout Style, Color Combination, Dark Mode Style), and all three pickers now share one selection style with hover, focus and keyboard support.
* ✨ Improvement: The frontend sidebar header now shows your dashboard logo in place of the plugin name and version text.
* ✨ Improvement: AI Settings lists the current Claude models (Opus 5, Sonnet 5, Fable 5 and Haiku 4.5), with Claude Sonnet 5 as the default. A model you saved earlier is still listed, so an existing choice is never lost.
* ✨ Improvement: AI Chatbot settings are configurable without the Pro plugin. The screen is no longer replaced by an upgrade notice — access to the assistant itself is still controlled from the frontend dashboard.
* ✨ Improvement: Employee Management, AI Chatbot and AI Settings rebuilt on one shared layout — label and description on the left, control on the right, grouped into consistent cards — so every settings screen reads the same way.
* ✨ Improvement: Employee Management, AI Chatbot and AI Settings are now fully translatable; those screens previously contained hard-coded English text.
* 🐛 Fix: The WordPress admin settings panel no longer changes with the frontend dashboard's Color Combination, Preset or Dark Mode. Those settings style the frontend dashboard only; the admin screen now renders with a fixed theme. Previously, switching the frontend to dark mode also put wp-admin into a dark palette while its own styling stayed light.
* 🐛 Fix: SVG icons lost their viewBox during the build, so any icon rendered at a size other than its original was cropped instead of scaled. Most visible on the collapsed sidebar icon, which showed only a corner of the logo.
* 🐛 Fix: In dark mode on the frontend dashboard, the avatar dropdown chevron and the order status slider arrows kept a hard-coded light background.
* 🐛 Fix: Labels and controls on several settings screens were centred instead of left aligned, because a shared card style was missing its text-alignment reset.
* 🐛 Fix: The AI Chatbot settings rendered a form nested inside the main settings form, which is invalid markup; the redundant inner forms have been removed.
* 🐛 Fix: Clicking the company logo upload box in Invoice settings did nothing; the WordPress media library scripts were never loaded on the Shop Manager settings screen, so the media modal could not open.
* 🐛 Fix: The "Change" and "Remove" logo buttons in Invoice settings submitted the settings form and showed the "Settings saved successfully" message; they now only open the media library or clear the logo, and settings save exclusively via the Save Changes button.

= 1.3.1 =
* 🔒 Security: Fixed a broken function-level authorization flaw in the shop-manager/v1 REST API where any built-in Shop Manager employee role could reach every endpoint regardless of its assigned module permissions. Each customer, order, product, analytics, and employee route now enforces its specific per-role capability server-side (e.g. oxi_sm_view_customers, oxi_sm_edit_orders, oxi_sm_view_employees). A product-only employee can no longer read or modify customer, order, or employee-access data. Thanks to security researcher an7ln for the responsible disclosure.
* 🔒 Security: The global dashboard search endpoint (which returns order and customer data) now requires the "view orders" capability.
* 🔒 Security: Server-side REST capability checks now honor both the default roles' coarse capabilities and custom roles' granular per-section capabilities (categories, tags, brands, attributes, reviews, roles & access), matching the frontend permission model so that each employee sees exactly the pages and data their role allows — no more, no less.
* 🐛 Fix: Employees without dashboard access no longer land on an "Access Restricted" screen after logging in; the dashboard now redirects them to the first page their role can actually access (e.g. a product-only employee lands on Products).
* 🐛 Fix: Custom employee roles granted access to a specific product section (e.g. Categories) but not full product access could not load that section's data ("You are not allowed to access this resource"); section-level permissions are now correctly recognized by the REST API.

= 1.3.0 =
* 🆕 New: AI Chat Assistant, ask questions about your store in plain language and get real answers; the assistant uses live-data tools to report on orders, revenue, products, customers, and employee activity (Pro)
* 🆕 New: AI Assistant reachable from the dashboard header on every page; free users get the full chat experience with suggested questions and a preview of what Pro unlocks
* 🆕 New: AI Chatbot module added to the admin Modules tab, enabled by default for new and existing stores; toggle it on/off and open its settings via the Configure button
* 🆕 New: Role-based access for the AI Assistant, grant or revoke the "AI Chatbot" capability per employee role from Roles & Access; the header icon only appears for users who have access
* ✨ Improvement: Employee Management moved into the Modules tab as a card with its own Configure shortcut, consistent with every other module
* ✨ Improvement: Module cards now show a pill-shaped Configure button that jumps straight to that module's settings tab
* 🐛 Fix: Frontend dashboard showed a "No route was found" error toast on reload when the Pro plugin was inactive; the AI conversation endpoints are no longer requested in the free version
* 🐛 Fix: Disabling the Employee Management module in the backend now correctly hides it from the frontend dashboard sidebar (it was previously hard-coded as always on)
* 🐛 Fix: Disabling the AI Chatbot module now also hides the AI Assistant icon in the dashboard header
* 🐛 Fix: AI Assistant replies showed raw HTML entities (e.g. &#2547; instead of ৳) for currency; the symbol is now decoded before reaching the AI and the chat renderer decodes entities defensively (Pro)
* 🐛 Fix: Employee activity reports invented an order-status breakdown (e.g. reporting "Cancelled: 0" when an order was actually cancelled); the assistant now uses the real status-change counts from the activity log (Pro)

= 1.2.7 =
* ⚡ Improvement: Full WooCommerce HPOS (High-Performance Order Storage) compatibility declared via FeaturesUtil; WooCommerce admin warning banner removed
* 🐛 Fix: Export function trash-order query and search were using legacy wp_posts table and breaking on HPOS-enabled sites; both now use wc_get_orders() which works with both HPOS and traditional storage
* ✨ Improvement: HPOS detection updated to use the official OrderUtil::custom_orders_table_usage_is_enabled() API instead of reading a raw option value
* 🐛 Fix: Plugin API calls were using hardcoded /wp-json/ absolute paths, causing all API requests to fail on WordPress subdirectory installations (e.g. example.com/shop/); api.js now derives the correct prefix from rest_url() and patches fetch and axios globally
* 🐛 Fix: React Router basename was hardcoded as /sm-dashboard, breaking page routing on subdirectory WordPress installs; now reads the actual dashboard page path from PHP via wpkinSM.sm_dashboard_path
* 🐛 Fix: Two admin-side API calls in App.jsx and AiSettings.jsx had hardcoded /wp-json/ paths; updated to use wpkinSM.root which already contains the correct rest_url()
* 🔒 Security: Review counts query replaced with $wpdb->prepare() and %d placeholders for the IN() clause; all ID parameters (order_id, customer_id, attribute_id) now cast with absint() before use
* 🔒 Security: Exception message removed from the save-admin-settings API error response; error is now logged server-side via error_log() instead of being exposed to API clients
* 🔒 Pro: Employee Performance Summary card now gated behind a Pro license check; free users see a friendly upgrade prompt linking to the pricing page

= 1.2.5 =
* 🆕 New: Employee Performance Summary feature added, AI-generated weekly summary per employee showing orders processed, completed orders, cancellations, refunds triggered, and products edited, powered by the configured AI provider (Claude, OpenAI, or Gemini)
* 🆕 New: "Orders Today" stat card added to Employee Profile page showing how many orders the employee processed today
* ✨ Improvement: Employee Profile top stat cards updated: Orders Today, Orders This Week, Orders This Month, and Last Active; "Member Since" card removed
* ✨ Improvement: Performance Summary stat chips updated: separated Cancellations and Refunds Triggered into distinct metrics; "Today's orders" chip removed (moved to top stat cards)
* 🔒 Pro: Employee Performance Summary is gated behind a Pro license; free users see an upgrade prompt with a link to the pricing page

= 1.2.4 =
* ✨ Improvement: Products list: all columns now have explicit widths with `scroll={{ x: 940 }}` so the table fits within the desktop container without a horizontal scrollbar and scrolls correctly on mobile
* ✨ Improvement: Products list: Name column given explicit width (160 px) to prevent vertical letter-stacking on tablet and mobile when `table-layout: fixed` is active
* ✨ Improvement: Products / Add Product page headers replaced with flexbox layout (`sm-page-header`): action buttons stay right-aligned on desktop and stack below the title on mobile (≤ 768 px)
* ✨ Improvement: Dashboard period selector uses the same flexbox header pattern: stays right-aligned on desktop, stacks on mobile
* ✨ Improvement: All Products card now shows the total product count in the card title
* ✨ Improvement: Pagination spacing: 16 px top margin added above pagination across all tables
* 🐛 Fix: TinyMCE editor toolbar icons were blank rectangles, the `font-family: inherit` rule was scoped too broadly (universal selector under the plugin ID), overriding TinyMCE's `tinymce` icon font; now only applies to form elements that don't inherit by default
* 🐛 Fix: Persistent vertical scrollbar on All Products page, caused by `overflow-x: auto` on `.ant-table-wrapper` triggering a horizontal scroll (table wider than container), which reduced available height and added a vertical scrollbar; fixed by removing the outer-wrapper overflow rule and letting AntD's inner `scroll` prop handle horizontal overflow on `.ant-table-content`
* ✨ Improvement: Consistent card-based layout applied to all list pages: All Products, Categories, Tags, Brands, Attributes, Reviews, All Employees, and Roles & Access now follow the same design pattern as Orders: a header Card (title + action buttons) and a table Card (`bordered={false}`, `boxShadow: token.boxShadowTertiary`)
* ✨ Improvement: "Add Product" submenu removed from sidebar, route still accessible via the Add Product button on the All Products page
* ✨ Improvement: All Products page header uses the same Card + Row/Col pattern as Orders; "Add New" button renamed to "Add Product"
* ✨ Improvement: Attributes page action icons changed from bordered `size="small"` buttons to `type="text"` icon-only buttons (pencil, trash, tags) matching the Tags/Categories page style
* ✨ Improvement: Header item order changed: "Upgrade to Pro" button now appears before the dark mode toggle, which appears before the user avatar
* 🐛 Fix: Employee filter card had reduced padding (`12px 16px`) inconsistent with all other pages; now uses AntD default card body padding matching the Customers page
* ✨ Improvement: Admin header "Dashboard" button renamed to "Frontend Dashboard" for clarity
* ✨ Improvement: Admin Modules page responsive layout fixed: laptop screens (< 1600 px) now show 3 columns instead of 4, preventing card elongation and text wrapping; 4-column layout reserved for large desktop screens (≥ 1600 px)
* 🐛 Fix: Low Stock Alert insight card "View Products" link was navigating to the wrong page; now correctly navigates to the All Products page pre-filtered to low stock items
* 🆕 New: "Low Stock" added as a selectable option in the Stock Status filter on the All Products page, selecting it shows only products with stock below the configured low stock threshold
* 🐛 Fix: Selecting multiple stock status options including "Low Stock" was only showing low stock products, stock status conditions are now combined with OR so all matching products appear
* ✨ Improvement: Insight cache now clears automatically when a product is saved or its stock changes, not just on order events

= 1.2.3 =
* 🆕 New: Collapsible icon-only sidebar: desktop sidebar now has a toggle button at the top; click to shrink to icon-only mode (72 px) and click again to expand back to full width (240 px)
* 🆕 New: Appearance settings page, preset cards fully redesigned with SaaS-style browser chrome preview (sidebar, stat cards, and table) for accurate visual comparison
* 🆕 New: Dark mode preferred style: choose which dark mode style the frontend toggle switches to; saved as `preferredDark` in appearance settings
* 🆕 New: Employee Management admin page, redesigned with a SaaS-style notice banner and direct action buttons linking to the frontend dashboard Employee and Roles & Access pages
* ✨ Improvement: Dark mode toggle simplified to a single icon button (no dropdown); toggles between light and the configured preferred dark style
* ✨ Improvement: Full dark mode coverage: page background, header, footer, and sidebar all correctly respond to dark mode; fixed partial dark mode where some surfaces stayed light
* ✨ Improvement: Dark mode cards use a glass effect, subtle white-tint background, backdrop blur, and inset highlight border for card distinction on dark backgrounds
* ✨ Improvement: Sidebar background removed in dark mode, sidebar inherits the dark algorithm instead of overriding with white, giving a seamless dark layout
* ✨ Improvement: All color schemes use a consistent white sidebar background; tinted sidebar colors removed for a cleaner, uniform look
* ✨ Improvement: Sidebar width increased to 240 px (was 200 px); sidebar menu icons enlarged to 17 px for better readability
* ✨ Improvement: Footer background now correctly follows the active theme color via CSS custom property instead of a hardcoded value
* ✨ Improvement: Employee profile page redesigned with SaaS-style stat cards, activity summary, and a theme-aware left border that follows the active Color Combination
* ✨ Improvement: Roles & Access modal text and backgrounds are now dark-mode aware, all hardcoded hex colors replaced with AntD token values so the Create/Edit Role modal is fully readable in dark mode
* ✨ Improvement: Employee list filter row now has correct vertical spacing on mobile; action buttons stay on one line with `nowrap` enforcement
* ✨ Improvement: Inter font applied globally across the frontend dashboard, consistent SaaS typography regardless of the active WordPress theme
* ✨ Improvement: Frontend dashboard CSS fully scoped under `#wpkin-shop-manager-public`, prevents WP theme styles from leaking into the plugin UI
* 🐛 Fix: Appearance settings (preset, color scheme, preferred dark) were silently dropped on save, `wpkin_sanitize_settings_data()` now correctly preserves the `appearance` block
* 🐛 Fix: Activity Log Retention setting was not saving or repopulating, `employee_management` block added to `wpkin_sanitize_settings_data()` and deep-merged on save to preserve existing employee data

= 1.2.2 =
* 🆕 New: Employee Management module, role-based access control for frontend dashboard users
* 🆕 New: Custom employee roles, create roles with granular capability assignments (Pro)
* 🆕 New: "Create Role" button locked behind Pro license, shows lock icon and opens Pro upgrade modal for free users
* 🆕 New: Password set page for new employees, welcome email now sends a secure setup link instead of plain-text credentials
* 🆕 New: Lost password / password reset flow inside the frontend dashboard, no redirect to wp-login.php
* 🆕 New: Employee profile route always accessible to the logged-in employee themselves, even without the employees module capability
* ✨ Improvement: Header avatar now shows a caret badge; admins see "WordPress Dashboard" in the dropdown, employees see "My Profile"
* ✨ Improvement: Avatar size standardised to 40×40 px with a circular caret indicator at the bottom-right corner
* ✨ Improvement: Header dropdown now shows the human-readable role name instead of the internal role slug
* ✨ Improvement: Password fields in login and set-password forms now have an eye-icon toggle to show/hide the password
* ✨ Improvement: Custom roles (Pro) are automatically deactivated when the Pro license expires, employees with custom roles lose dashboard access and see a clear "Access Restricted" explanation page
* ✨ Improvement: Employees with expired custom roles still appear in the All Employees list so admins can reassign them
* ✨ Improvement: Employee list shows a lock icon and greyed-out role tag for any employee whose custom role is inactive due to an expired Pro license
* ✨ Improvement: Roles & Access table shows a "Pro Required" warning tag for custom roles when Pro license is not active
* 🐛 Fix: WordPress canonical redirect was stripping `sm_action`, `sm_key`, and `sm_login` query parameters, fixed by registering them as recognised query vars
* 🐛 Fix: Employee profile page was inaccessible to employees without the `oxi_sm_employees_access` capability, even for their own profile

= 1.2.1 =
* 🆕 New: PDF invoice generation, server-side PDF via mPDF with 4 templates (Modern, Classic, Bold, Minimal) matching the live preview pixel-for-pixel
* 🆕 New: Invoice button on Order Details page, opens PDF in a new browser tab for viewing, printing, or downloading
* 🆕 New: Bulk invoice generation, select multiple orders and generate a single merged PDF with one order per page
* 🆕 New: Resend Email button on Order Details page, choose email type from dropdown with confirmation modal before sending
* 🆕 New: Bulk Resend Email, select orders, pick email type from a modal, and send with one click
* 🆕 New: "Send PDF with Email" toggle in Invoice Settings > General, controls whether the invoice PDF is attached to order confirmation emails
* 🆕 New: Inter font embedded in PDF, matches the dashboard preview font exactly
* 🆕 New: Dynamic multi-script font support, Bengali ৳ renders via Noto Sans Bengali; Arabic, CJK, and other scripts use mPDF's built-in language-to-font mapping; all Latin currencies use Inter
* ✨ Improvement: PDF font colors now use the configured text color throughout, matching the live preview
* ✨ Improvement: Admin email (New Order) resend now works correctly using WooCommerce's own resend pattern including the required filter
* 🐛 Fix: Bold font weight in PDF item totals and grand total, mPDF requires font-weight:bold, not 600 or 700
* 🐛 Fix: "Send PDF with Email" setting was not saving due to missing field in both sanitization passes

= 1.2.0 =
* 🆕 New: AI Settings page, configure provider (Claude, OpenAI, Gemini), model, temperature, and max tokens from the admin dashboard
* 🆕 New: AI product content generator, one-click generation of product title, short description, and full description inside the Add/Edit Product form
* 🆕 New: Per-field AI buttons, generate only the field you need without running a full generation
* 🆕 New: Custom Instructions field in AI modal, guide the AI with your own prompt for full creative control
* 🆕 New: Tone selector, Professional, Casual & Friendly, Premium/Luxury, Playful & Fun, Minimalist
* 🆕 New: Multi-provider AI support, Anthropic Claude, OpenAI GPT, and Google Gemini
* 🔒 New: API keys encrypted with AES-256-CBC using WordPress secret keys; never exposed to the browser
* 🆕 New: Test Connection button in AI Settings to verify API key before saving
* 🆕 New: Customers page, full customer list with search, country filter, tag filter, order count, total spent, and last order date
* 🆕 New: Customer Profile page, billing & shipping address, order stats, order history, notes, and tag management
* 🆕 New: AI customer auto-tagging, automatically tags customers as vip, loyal, new, at_risk, big_spender, frequent, or inactive based on order behaviour
* 🆕 New: Auto-tags are event-driven, recalculated on order status change or new order; time-based tags use a 24h transient cache
* 🆕 New: Manual tags, add/remove custom tags on the Customer Profile; manual tags are never overwritten by the system
* 🆕 New: Guest order matching, customer metrics and tags include guest orders placed with the same billing email
* 🆕 New: Bulk tag refresh, recalculate tags for all customers at once from the customer list
* 🆕 New: Customer Settings admin tab, configure all auto-tagging thresholds and excluded roles; changing thresholds invalidates all cached tags automatically
* 🆕 New: Color presets added to order status edit/add modal, 15 built-in color combinations with visual swatch selector
* 🆕 New: Attributes page, create, edit, and delete WooCommerce product attributes and terms from the frontend
* 🆕 New: Subcategory hierarchy, categories and brands display with WooCommerce-style dash indentation in lists and dropdowns
* 🆕 New: CSV product export, download selected or all products as a CSV file directly from the product list
* 🆕 New: "View Product" button on Edit Product page, opens the product's frontend page in a new tab
* ✨ Improvement: Rebranded from WPKIN to Oxilab across all display text and frontend footer
* ✨ Improvement: Admin settings tab position now persists on page reload via URL hash
* 🐛 Fix: Attribute terms failing to load due to invalid orderby parameter
* 🐛 Fix: Sale price validation used string comparison, causing single-digit prices to incorrectly trigger a "greater than regular price" error
* 🐛 Fix: Brands, Attributes, and Reviews sidebar menu items now correctly stay active when those pages are visited
* 🐛 Fix: "View" action in product list now opens the product's frontend page instead of the WP admin edit screen
* 🐛 Fix: Hook names prefixed with wpkin_sm_ to avoid collisions with other plugins

= 1.0.5 =
* 🆕 New: Add Product and Edit Product pages
* 🆕 New: All Products list page
* 🆕 New: Categories, Tags, Brands, and Reviews pages

= 1.0.4 =
* 🐛 Fix: Data saving issue resolved

= 1.0.3 =
* 🆕 New: Translation support, full WordPress i18n throughout the plugin
* ✨ Improvement: Overhauled order management workflow

= 1.0.0 =
* 🎉 Initial release, frontend order dashboard with create, edit, delete, and status management
