Repository navigation
Conversation
Date range control - Uses the shared DateRangePicker in a new confirm mode: a preset list, read-only Start/End fields, a two-month calendar, and a footer with the day count and Cancel/Apply. Future days are disabled. - A "Custom" item is active when the range matches no preset. Comparison control - A popover with Previous period, Previous year, Custom, and No comparison. Each option shows its dates. Custom shows a range calendar. - The footer shows "Compared with" the pending range. Shared DateRangePicker - New opt-in props: custom preset lists, confirm mode, and a custom trigger. The default behavior does not change. - New RangeFields and RangeFooter parts. The panel separators meet the panel edges. Other changes - Add a Customize button (no function yet). - Triggers use the white design-system background. Analytics colors are only for graphs. - Remove the currency filter from the frontend and the backend. All money metrics use base-currency columns, the response has no currencies list, and a currency parameter is ignored. - Sync the analytics-foundation specs into the main specs and add the analytics-date-controls OpenSpec change. Update docs/analytics.md.
- Merge the analytics-date-controls delta specs into the main specs:
- date-pickers: custom preset lists, confirm mode, and a custom trigger.
- analytics-page: the date range control, comparison control, Customize
button, and the rule that analytics colors are only for graphs. Remove
the currency control and the rounding note.
- analytics-metrics: remove the currency filter. The endpoint ignores a
currency parameter and returns no currencies list.
- Update the analytics-page Purpose so it does not mention a currency
control.
- Move the change to openspec/changes/archive/2026-10-18-analytics-date-controls.
- Put the change percent and the sparkline on one row in the key metric cards. - Add a text variant to ChangeBadge: colored text with no background and trending-up/down icons. The key metric cards use it; other cards keep the pill. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Draw the charts at the card's pixel width, so the axis text is not
stretched and the dots are circles.
- Y-axis: 5 round values from 0 in a short form ("$750", "$1K", "$110K").
- X-axis: one point for each day (1-31 days), week (32-186 days) or month
(more than 186 days). Label every Nth point from the first, with
N = ceil(points / 12), and a larger N when the labels do not fit the card.
- Tooltips show the full span of a point ("Oct 12 – Oct 18, 2026"). The API
adds span_label and previous_span_label to the series points.
- Total sales over time: filled area under the line and a dot on the last
point. Total sales, Average order value and Orders show a range legend.
- Show every change as colored text with trending-up/down icons, with no
background.
- Update docs/analytics.md and the PHP and frontend tests.
- Archive the OpenSpec changes analytics-time-series-charts and
analytics-chart-grouping-labels and sync their specs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Sales by product card on the analytics page now shows the stock status with the shared Badge component, with the same variants as the Top selling products card on the home dashboard: - Out of stock: destructive - Low stock: warning (was critical) - Tracked with stock left: default - In stock: success The analytics-page spec and the page test are updated to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Remove the comparison bar and the comparison value from each category row. - Show the change of net sales beside the amount with the ChangeBadge text. - Add a change field to the sales_by_category rows in the overview API, the same as the product rows. - Point the breakdown.bar color token at violet2 (#5A12FF). - Update the analytics-page, analytics-metrics and theme-primitives specs, the analytics docs, and the tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Average order value over time card now uses the line chart in place of the dot chart. The line has a dot on each current-period point and no filled area under it. The comparison line stays dashed with no dots. - Add the showPoints and showArea options to LineChart. The defaults keep the Total sales chart as before: a filled area and a dot on the last point only. - Remove DotChart and its "dot" legend sample, which nothing uses now. - Update the analytics-page spec and docs/analytics.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Draw the comparison range as a faded bar beside each current bar in the Orders over time chart, in place of the short comparison mark. - BarChart gets a showPreviousBars prop. When set, each point shows the previous bar (faded purple, left) and the current bar (dark purple, right), both with fully rounded ends. - The legend gets a matching pairedBar sample. - Other bar charts keep the stacked bars and the comparison mark. - Tests, the analytics-page spec and docs/analytics.md are updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Make the segmented bar 32px high, with a 1px gap between segments and rounded corners only at the two ends of the bar. - Show the delivered share in bold, with "delivered · M orders" beside it in a subdued color. - Show each status row with its color dot and name, the count in bold and the percent in a subdued, right-aligned column. - Update the page test, the analytics-page spec and docs/analytics.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restyle the New vs returning customers card to match the design: - Stack new customers (teal) under returning customers (purple) with a 2px gap, and round only the top of the highest segment. - Remove the comparison marks from the stacked bars and scale the y-axis to the current values only. The comparison values still show in the tooltip on hover or focus. - Show "N customers" in the headline through a new optional unit prop on CardHeadline. - Center the legend and show the totals as "New · N" and "Returning · N" with rounded square samples. Update the analytics-page spec, the analytics docs and the chart and page tests to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sales by coupon code now shows the top 5 codes by orders as horizontal bars. Each row shows the code, the orders count, the discount given as "$N off" in a subdued color and the change in orders against the comparison period. - Backend: each coupon row now has previous_orders and change. The coupon query moves to query_coupon_orders() so the comparison window uses the same query. - HBarList takes an optional subdued detail between the value and the change badge. - Tests: a PHP integration test for the coupon change and a page test for the new row. - Spec and docs describe the new card. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a full-width Orders by time of day card after the New vs returning customers and Sales by coupon code row. It shows a dot for each weekday (Mon to Sun) and hour (12am to 11pm) in the store time zone, with the day totals on the right. - Summary line: the busiest hour (such as "Fri 6pm–7pm"), the busiest day, and the share of orders from the start of the busiest hour to midnight (such as "After 6pm 38% of orders"). - "This period / Change" toggle, shown only with a comparison. In This period a bigger, darker dot means more orders. In Change the dot size is the absolute difference, purple for more orders and gray for fewer. - Each dot has a tooltip, an accessible name and a fixed-size circular outline on hover and focus. On narrow screens the grid keeps 640px and scrolls inside the card. - Backend: the overview endpoint returns orders_by_time_of_day with the 7 × 24 placed-order counts for the range and the comparison range. local_time_sql() now holds the store-time conversion that local_date_sql() uses. - Tests: PHP integration tests for the time zones, failed orders and comparison counts; Vitest tests for the summary helper and the card. - Specs, docs and the archived OpenSpec change describe the card. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ll-down Add a full-width Sales by location card after Orders by time of day. A world map colors each country by the selected "Sales / Orders / Customers" tab, and a list beside it shows the top 5 countries. - Map: d3-geo with the bundled world-atlas 110m geometry, loaded as a separate chunk with no remote request. Darker purple means a bigger value (square-root scale), gray means no value. The legend shows the metric, the lowest and highest value and "None". - Hover or focus on a country with a value shows its border and a tooltip with the value and change. There is no wheel zoom or drag pan. - A click on a country (on the map, with the keyboard, or on its list row) zooms the map to its largest land area, fades the others and lists its top 5 regions. "← All countries", Escape or a click on the sea zooms back out. The selection stays across a range change while the country still has a value. - Location is the shipping address, else the billing address. Sales is product net sales of paid orders, Orders is placed orders, Customers is different customers with a paid order. Orders with no state group into "Unknown region". - Backend: the overview returns sales_by_location with every country and its three metrics and changes. New GET /analytics/regions returns the top 5 regions of one country for all three metrics. - Tests: PHP integration tests for the location rules and the regions endpoint (and the missing cards in the response shape test); Vitest tests for the color scale, the ranking and the card. - Specs, docs and the archived OpenSpec change describe the card. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sales by payment method now shows the top 5 methods by Total sales as
horizontal bars. Each row shows the method name, the Total sales, the
order count ("209 orders") in a subdued color and the change in Total
sales against the comparison period.
- Backend: each payment method row now has
previous_total_sales_money_object and change. The payment method query
moves to query_payment_method_sales() so the comparison window uses the
same query.
- Frontend: the card uses HBarList, and the schema takes the two new
optional fields.
- Tests: PHP integration tests for the change and for a method with no
previous sales, and a page test for the new rows.
- Specs and docs describe the new card. The OpenSpec change is archived.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Taxes collected by region and Shipping charges by method cards now show the top 5 rows as horizontal bars, with the change against the comparison period on each row. - Backend: each tax region row gets previous_total_tax_money_object and change (on Total tax). Each shipping method row gets previous_shipping_charges_money_object and change (on Shipping charges). The queries move into query_region_taxes() and query_shipping_method_charges() so that the comparison window uses the same query. The change is empty with no comparison or a previous value of 0. - Frontend: both cards use HBarList. Shipping shows "N orders" next to the value. Taxes shows "Product $X · Shipping $Y" under the bar through a new optional HBarItem note. RankedList and RankedCardShell have no more users and are removed. - Tests: PHP integration tests for the change and the new-in-range case of both cards, and a page test for the bars, secondary data and badges. - Docs and specs: docs/analytics.md Cards rows, synced analytics-metrics and analytics-page specs, and the archived OpenSpec change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…live indicator - Show the out-of-stock, low-stock and in-stock counts as equal tiles with a light background. The out-of-stock count is red, the low-stock count is amber, and the status name shows under each count. - Show the variant list in a bordered box with row dividers. Each row shows the product, the variant and an "Out of stock" or "Low stock" badge instead of the quantity. The box is hidden when no variant needs attention. - List only tracked variants that are out of stock or low stock (up to 4, lowest stock first). In-stock variants no longer take a place in the list. - Add a green dot with a repeating ripple before "Live, not affected by the date range". The ripple stops when the user prefers reduced motion. - Add integration and page tests, update docs/analytics.md, sync the analytics-metrics and analytics-page specs, and archive the OpenSpec change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Analytics page waited for one overview response that calculated every
key metric and card. Now each part has its own request, so a card shows as
soon as its data is ready.
- Backend: GET /analytics/metrics/{key} replaces GET /analytics/overview.
The keys are kpis and the 15 card keys; an unknown key returns 404. Each
response is { meta, data }, where meta has range, compare, granularity,
base_currency_code and has_orders. AnalyticsQueryService::get_metric()
builds one key; only kpis and the 5 window-based cards collect the window
totals. AnalyticsOverviewRequest is renamed to AnalyticsMetricRequest.
- Frontend: useAnalyticsMetricQueries() runs one TanStack query per key with
useQueries. Each card slot shows its skeleton until its data comes, and a
card error with Try Again when its request fails. The key metrics row has
one error for the row. The page error shows only when every request fails.
Each card uses the meta of its own response.
- Tests: the PHP overview() helper assembles the old shape from every key,
and AnalyticsMetricsApiTest covers one key, kpis, every key, the 404 for
an unknown key and the removed route. Vitest covers the parallel queries,
a card that loads first, a card that fails and a retry of one card.
- Docs and specs: docs/analytics.md lists the endpoint, the keys, the
response shape and the request cost; analytics-metrics and analytics-page
specs are synced, and the OpenSpec change is archived.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Hide menu The Customize button now opens a "Customize analytics" sheet from the right. Merchants choose which key metrics and cards the page shows, and in which order. The choice is saved in the browser's local storage. Sheet component - New components/ui/sheet.tsx with the shadcn Sheet parts (Sheet, SheetTrigger, SheetClose, SheetContent with top/right/bottom/left sides, SheetHeader, SheetFooter, SheetTitle, SheetDescription) on Radix Dialog, styled with the design system. - New theme.zIndex.sheet layer so the sheet and its overlay cover the WordPress admin bar, while menus opened inside it stay on top. Customize sheet - "Key metrics" and "Cards" groups in StackedItems, each item with a drag handle and a checkbox. Items reorder in their own group only, with the pointer or the keyboard. Full cards show a "Full width" note. - Changes apply at once. "Reset to default" restores the first 4 key metrics and all cards in their first order. "Done" closes the sheet. - At least 1 key metric and 1 card stay on; the last one is locked. Page - Each key metric and card has a three-dots menu with one item, "Hide from page". The button shows on hover or focus, and always on touch devices. - Cards render from a registry in the saved order. A half card alone in its row fills the row. - The key metrics row shows 4 per row; extra key metrics go to the next row and keep a quarter of the width. - Hidden cards send no request. Key metrics API - GET /analytics/metrics/kpis now returns 11 key metrics: Net sales, Total sales, Items ordered, Discounts, New customers, Customers and Shipping charges are added, each with change and series. No new SQL; summarize() now carries items ordered per period for the Items ordered series. Also - Inventory health live indicator uses the text.success color. - docs/analytics.md covers the Customize sheet, the 11 key metrics, the saved layout and the per-browser storage gap. - OpenSpec: new sheet-primitive and analytics-customize specs; analytics-page and analytics-metrics updated; change archived. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Map: - A country with no data now shows the same hover border as a country with data, and a tooltip with its name and "No data". - A country with no data keeps the default cursor, does nothing on a click, and stays out of the keyboard order. - Each map shape has a key with the country name as a fallback, so shapes without an ID get their own hover state. Customize sheet: - The "Full width" note sits at the right edge of its row. - The row keeps its right padding after the note. The inline style set the padding on both sides and overrode it. Docs and specs: - docs/analytics.md and the analytics-page spec describe the new hover behavior. The OpenSpec change is archived. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RaqibSaruf
approved these changes
Oct 19, 2026
Comment on lines
+140
to
+156
| /** | ||
| * Check that a value is a real calendar day in Y-m-d format. | ||
| * | ||
| * @since 1.0.0 | ||
| * | ||
| * @param string $value Value to check. | ||
| * | ||
| * @return bool | ||
| */ | ||
| protected function is_date(string $value) | ||
| { | ||
| if (!preg_match('/^(\d{4})-(\d{2})-(\d{2})$/', $value, $parts)) { | ||
| return false; | ||
| } | ||
|
|
||
| return checkdate((int) $parts[2], (int) $parts[3], (int) $parts[1]); | ||
| } |
Collaborator
There was a problem hiding this comment.
we can use date_format rule instead of this method
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds the Analytics page to the admin app. Merchants see key metrics and 15 cards for a date range and an optional comparison period. They can choose which metrics and cards show, and in which order.
Backend
GET /analytics/metrics/{key}returns one part of the page:kpisor one of the 15 card keys. An unknown key returns 404. Each response is{ meta, data }.metahas the range, the comparison, the granularity, the base currency andhas_orders.kpisreturns 11 key metrics with change and series: Gross sales, Orders, Average order value, Returning customer rate, Net sales, Total sales, Items ordered, Discounts, New customers, Customers and Shipping charges.GET /analytics/regionsreturns the top 5 regions of one country for Sales, Orders and Customers.Frontend
components/ui/sheet.tsx(shadcn Sheet on Radix Dialog). Its z-index layer covers the WordPress admin bar.Docs and specs
docs/analytics.mddescribes the page, the endpoints, the cards, the Customize sheet and where this differs from WooCommerce Analytics.Test plan
npm run typechecknpm testinresources/app/(1940 tests)openspec validate(144 specs)