PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.4.19
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.4.19
1.4.19 1.4.18 1.4.17 1.4.16 1.4.15 1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.54 1.3.53 1.3.52 1.3.51 1.3.50 All 182 releases
disco / backend / views / components / Analytics / pages / Customers.jsx

Customers.jsx in Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO 1.4.19, at backend/views/components/Analytics/pages/Customers.jsx

118 lines 2.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import CustomersTable from '@/components/customers/CustomersTable';
2 import { useGetCustomersQuery } from '@/features/customers/customersApi';
3 import { selectDateRangeParams } from '@/features/dateRange/dateRangeSlice';
4 import useIsPro from '@/lib/useIsPro';
5 import { campaignsSort, fmt } from '@/lib/utils';
6 import { __ } from '@wordpress/i18n';
7 import { useState } from 'react';
8 import { useSelector } from 'react-redux';
9
10 const AVATAR_COLORS = [
11 '#06b6d4',
12 '#ec4899',
13 '#f59e0b',
14 '#f97316',
15 '#3b82f6',
16 '#84cc16',
17 '#8b5cf6',
18 '#ef4444',
19 '#a78bfa',
20 '#10b981',
21 ];
22
23 function getInitials(name) {
24 if (!name) return '?';
25 const parts = name.trim().split(/\s+/);
26 return (parts[0]?.[0] ?? '') + (parts[1]?.[0] ?? '');
27 }
28
29 const SORT_MAP = {
30 spent: 'total_spent',
31 orders: 'orders',
32 };
33
34 const Customers = () => {
35 const dateParams = useSelector(selectDateRangeParams);
36 const [page, setPage] = useState(1);
37 const [sortKey, setSortKey] = useState('spent');
38 const [sortDir, setSortDir] = useState('desc');
39 const [search, setSearch] = useState('');
40 const isPro = useIsPro();
41
42 const {
43 data: res,
44 isLoading,
45 isFetching,
46 } = useGetCustomersQuery({
47 ...dateParams,
48 limit: isPro ? 20 : 10,
49 sort_by: SORT_MAP[sortKey] ?? 'total_spent',
50 order: sortDir,
51 page,
52 ...(search ? { search } : {}),
53 });
54
55 const customers = (res?.data ?? []).map((c, index) => ({
56 id: c.id,
57 initials: getInitials(c.name).toUpperCase(),
58 color: AVATAR_COLORS[index % AVATAR_COLORS.length],
59 name: c.name || '—',
60 email: c.email || '—',
61 state: c.state || '—',
62 campaigns: campaignsSort([...c.campaigns]),
63 orders: c.orders,
64 spent: fmt(c.total_spent),
65 avatar: c.avatar,
66 }));
67
68 const total = res?.collection?.total ?? 0;
69 const totalPages = res?.collection?.total_pages ?? 1;
70 const count = res?.collection?.count ?? 0;
71
72 const handleSort = (key) => {
73 if (sortKey === key) setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'));
74 else {
75 setSortKey(key);
76 setSortDir('desc');
77 }
78 setPage(1);
79 };
80
81 const handleSearch = (value) => {
82 setSearch(value);
83 setPage(1);
84 };
85
86 return (
87 <div className="disco:min-h-screen disco:bg-[#f9fafb] disco:px-6 disco:py-2">
88 <div className="disco:mb-5">
89 <h1 className="disco:text-lg! disco:font-bold! disco:text-[#111827]! disco:tracking-tight">
90 {__('Customers', 'disco')}
91 </h1>
92 <p className="disco:text-xs! disco:text-[#9ca3af] disco:mt-0.5">
93 {__(
94 'Customers who used at least one Disco campaign',
95 'disco'
96 )}
97 </p>
98 </div>
99 <CustomersTable
100 customers={customers}
101 isLoading={isLoading || isFetching}
102 search={search}
103 onSearchChange={handleSearch}
104 sortKey={sortKey}
105 sortDir={sortDir}
106 onSort={handleSort}
107 page={page}
108 totalPages={totalPages}
109 total={total}
110 count={count}
111 onPageChange={setPage}
112 />
113 </div>
114 );
115 };
116
117 export default Customers;
118