diff --git a/DASHBOARD_TWEAKS_TODO.md b/DASHBOARD_TWEAKS_TODO.md
new file mode 100644
index 0000000..f82c74f
--- /dev/null
+++ b/DASHBOARD_TWEAKS_TODO.md
@@ -0,0 +1,158 @@
+# Dashboard Tweaks TODO
+
+## Completed ✅
+
+### 1. Fix On-hold and Trash Color Conflict
+**Status:** ✅ DONE
+
+**Issue:** Both on-hold and trash used same gray color (#6b7280)
+
+**Solution:**
+- On-hold: `#64748b` (Slate 500)
+- Trash: `#475569` (Slate 600 - darker)
+
+**Files Updated:**
+- `includes/Api/AnalyticsController.php` (2 locations)
+
+---
+
+## Pending Tasks
+
+### 2. Add "No Data" State to Charts ⏳
+
+**Affected Charts:**
+- Revenue chart (Dashboard → Revenue submenu)
+- Orders chart (Dashboard → Orders submenu)
+- Coupon chart (Dashboard → Coupons submenu)
+
+**Current Behavior:**
+- Overview page shows "No data" message ✓
+- Submenu charts show empty/broken charts ✗
+
+**Required Implementation:**
+```tsx
+{chartData.length === 0 ? (
+
+
+
+
No data available
+
+ Data will appear once you have {type}
+
+
+
+) : (
+
+ {/* Chart */}
+
+)}
+```
+
+**Files to Update:**
+- `admin-spa/src/routes/Dashboard/Revenue.tsx`
+- `admin-spa/src/routes/Dashboard/Orders.tsx`
+- `admin-spa/src/routes/Dashboard/Coupons.tsx`
+
+---
+
+### 3. VIP Customer Settings ⏳
+
+**Requirement:** Add settings to configure VIP customer qualification
+
+**Proposed Location:** `/settings/customers` (new page)
+
+**Settings:**
+```tsx
+interface VIPSettings {
+ // Qualification Criteria
+ minTotalSpent: number; // e.g., $1000
+ minOrderCount: number; // e.g., 10 orders
+ timeframe: 'all' | '30' | '90' | '365'; // Days or all-time
+
+ // Optional Criteria
+ requireBoth: boolean; // Both spent AND count, or either?
+ excludeRefunded: boolean; // Exclude refunded orders?
+
+ // Benefits (for display/reference)
+ vipBenefits: string[]; // e.g., ["Free shipping", "10% discount"]
+}
+```
+
+**UI Design:**
+```
+Customer Settings
+├── VIP Qualification
+│ ├── Minimum Total Spent: $___
+│ ├── Minimum Order Count: ___
+│ ├── Timeframe: [All time | Last 30 days | Last 90 days | Last year]
+│ ├── ☐ Require both criteria (vs either one)
+│ └── ☐ Exclude refunded orders
+│
+└── VIP Benefits (optional reference)
+ └── [Add benefit] button
+```
+
+**Implementation Steps:**
+1. Create `admin-spa/src/routes/Settings/Customers.tsx`
+2. Add backend endpoint: `POST /settings/customers`
+3. Create `includes/Compat/CustomerSettingsProvider.php`
+4. Add to navigation tree
+5. Implement VIP badge logic in customer list
+
+**Backend Storage:**
+```php
+// WordPress options
+woonoow_vip_min_spent = 1000
+woonoow_vip_min_orders = 10
+woonoow_vip_timeframe = 'all'
+woonoow_vip_require_both = true
+woonoow_vip_exclude_refunded = true
+```
+
+**VIP Detection Query:**
+```php
+function is_vip_customer($customer_id) {
+ $settings = get_vip_settings();
+
+ $query_args = [
+ 'customer_id' => $customer_id,
+ 'status' => ['completed', 'processing'],
+ ];
+
+ if ($settings['timeframe'] !== 'all') {
+ $query_args['date_created'] = '>' . date('Y-m-d', strtotime("-{$settings['timeframe']} days"));
+ }
+
+ if ($settings['exclude_refunded']) {
+ $query_args['status'] = array_diff($query_args['status'], ['refunded']);
+ }
+
+ $orders = wc_get_orders($query_args);
+
+ $total_spent = array_sum(array_map(fn($o) => $o->get_total(), $orders));
+ $order_count = count($orders);
+
+ if ($settings['require_both']) {
+ return $total_spent >= $settings['min_spent']
+ && $order_count >= $settings['min_orders'];
+ } else {
+ return $total_spent >= $settings['min_spent']
+ || $order_count >= $settings['min_orders'];
+ }
+}
+```
+
+---
+
+## Summary
+
+**Completed:**
+- ✅ On-hold/Trash color conflict fixed
+
+**Pending:**
+- ⏳ No data state for Revenue/Orders/Coupons charts
+- ⏳ VIP customer settings page
+
+**Priority:**
+1. No data states (quick fix)
+2. VIP settings (new feature)
diff --git a/admin-spa/src/index.css b/admin-spa/src/index.css
index d457ffa..b5922db 100644
--- a/admin-spa/src/index.css
+++ b/admin-spa/src/index.css
@@ -72,6 +72,7 @@
a:active {
outline: none !important;
box-shadow: none !important;
+ color: inherit !important;
}
}
diff --git a/includes/Api/AnalyticsController.php b/includes/Api/AnalyticsController.php
index de73d95..210ff9f 100644
--- a/includes/Api/AnalyticsController.php
+++ b/includes/Api/AnalyticsController.php
@@ -371,13 +371,14 @@ class AnalyticsController {
// Format status distribution and calculate conversion rate
$formatted_status = [];
$status_colors = [
- 'wc-completed' => '#10b981',
- 'wc-processing' => '#3b82f6',
- 'wc-pending' => '#f59e0b',
- 'wc-on-hold' => '#6b7280',
- 'wc-cancelled' => '#ef4444',
- 'wc-refunded' => '#8b5cf6',
- 'wc-failed' => '#dc2626',
+ 'wc-completed' => '#10b981', // Green
+ 'wc-processing' => '#3b82f6', // Blue
+ 'wc-pending' => '#f59e0b', // Orange/Amber
+ 'wc-on-hold' => '#64748b', // Slate
+ 'wc-cancelled' => '#ef4444', // Red
+ 'wc-refunded' => '#8b5cf6', // Purple
+ 'wc-failed' => '#dc2626', // Dark Red
+ 'wc-trash' => '#475569', // Dark Slate
];
$total_all_orders = 0;
@@ -996,17 +997,18 @@ class AnalyticsController {
// Add color and percentage to status data - SORT BY IMPORTANCE
$status_colors = [
- 'completed' => '#10b981',
- 'processing' => '#3b82f6',
- 'pending' => '#f59e0b',
- 'cancelled' => '#ef4444',
- 'refunded' => '#8b5cf6',
- 'failed' => '#dc2626',
- 'on-hold' => '#6b7280',
+ 'completed' => '#10b981', // Green
+ 'processing' => '#3b82f6', // Blue
+ 'pending' => '#f59e0b', // Orange/Amber
+ 'cancelled' => '#ef4444', // Red
+ 'refunded' => '#8b5cf6', // Purple
+ 'failed' => '#dc2626', // Dark Red
+ 'on-hold' => '#64748b', // Slate (changed from gray)
+ 'trash' => '#475569', // Dark Slate (distinct from on-hold)
];
// Define sort order (most important first)
- $status_order = ['completed', 'processing', 'pending', 'on-hold', 'cancelled', 'refunded', 'failed'];
+ $status_order = ['completed', 'processing', 'pending', 'on-hold', 'cancelled', 'refunded', 'failed', 'trash'];
foreach ($formatted_status as &$status) {
$status['color'] = $status_colors[$status['status']] ?? '#6b7280';