Seth commited on
Commit ·
65a736f
1
Parent(s): e27778b
update
Browse files- frontend/src/pages/Contacts.jsx +16 -5
- frontend/src/pages/Deals.jsx +16 -5
- frontend/src/pages/Leads.jsx +14 -5
frontend/src/pages/Contacts.jsx
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
| 16 |
Sparkles,
|
| 17 |
Trash2,
|
| 18 |
Handshake,
|
| 19 |
-
|
| 20 |
} from 'lucide-react';
|
| 21 |
import { Input } from '@/components/ui/input';
|
| 22 |
import { Badge } from '@/components/ui/badge';
|
|
@@ -469,6 +469,12 @@ export default function Contacts() {
|
|
| 469 |
)
|
| 470 |
);
|
| 471 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 472 |
const SortHeader = ({ field, label, className = '' }) => {
|
| 473 |
const active = sortBy === field;
|
| 474 |
return (
|
|
@@ -612,7 +618,7 @@ export default function Contacts() {
|
|
| 612 |
aria-label="Select all on page"
|
| 613 |
/>
|
| 614 |
</th>
|
| 615 |
-
<th className="w-9 px-0 py-2" aria-label="
|
| 616 |
<SortHeader field="first_name" label="Name" />
|
| 617 |
<SortHeader field="email" label="Email" />
|
| 618 |
<SortHeader field="company" label="Company" />
|
|
@@ -786,10 +792,15 @@ export default function Contacts() {
|
|
| 786 |
variant="ghost"
|
| 787 |
size="icon"
|
| 788 |
className="h-8 w-8 text-slate-500 hover:text-violet-700"
|
| 789 |
-
onClick={() =>
|
| 790 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 791 |
>
|
| 792 |
-
<
|
| 793 |
</Button>
|
| 794 |
</td>
|
| 795 |
<td className="px-3 py-2 align-top">
|
|
|
|
| 16 |
Sparkles,
|
| 17 |
Trash2,
|
| 18 |
Handshake,
|
| 19 |
+
Pencil,
|
| 20 |
} from 'lucide-react';
|
| 21 |
import { Input } from '@/components/ui/input';
|
| 22 |
import { Badge } from '@/components/ui/badge';
|
|
|
|
| 469 |
)
|
| 470 |
);
|
| 471 |
|
| 472 |
+
const focusFirstEditableInRow = (tr) => {
|
| 473 |
+
if (!tr) return;
|
| 474 |
+
const el = tr.querySelector('input:not([type="checkbox"]):not([type="hidden"]), textarea');
|
| 475 |
+
el?.focus?.();
|
| 476 |
+
};
|
| 477 |
+
|
| 478 |
const SortHeader = ({ field, label, className = '' }) => {
|
| 479 |
const active = sortBy === field;
|
| 480 |
return (
|
|
|
|
| 618 |
aria-label="Select all on page"
|
| 619 |
/>
|
| 620 |
</th>
|
| 621 |
+
<th className="w-9 px-0 py-2" aria-label="Table edit" />
|
| 622 |
<SortHeader field="first_name" label="Name" />
|
| 623 |
<SortHeader field="email" label="Email" />
|
| 624 |
<SortHeader field="company" label="Company" />
|
|
|
|
| 792 |
variant="ghost"
|
| 793 |
size="icon"
|
| 794 |
className="h-8 w-8 text-slate-500 hover:text-violet-700"
|
| 795 |
+
onClick={(e) => {
|
| 796 |
+
e.stopPropagation();
|
| 797 |
+
focusFirstEditableInRow(
|
| 798 |
+
e.currentTarget.closest('tr')
|
| 799 |
+
);
|
| 800 |
+
}}
|
| 801 |
+
aria-label={`Edit fields in row for ${displayName}`}
|
| 802 |
>
|
| 803 |
+
<Pencil className="h-4 w-4" aria-hidden />
|
| 804 |
</Button>
|
| 805 |
</td>
|
| 806 |
<td className="px-3 py-2 align-top">
|
frontend/src/pages/Deals.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
import React, { useCallback, useEffect, useState } from 'react';
|
| 2 |
import { Link } from 'react-router-dom';
|
| 3 |
-
import { Search, Loader2, LayoutGrid,
|
| 4 |
import { Button } from '@/components/ui/button';
|
| 5 |
import { Select, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/select';
|
| 6 |
import AppShell from '@/components/layout/AppShell';
|
|
@@ -46,6 +46,12 @@ function isRowUiTarget(e) {
|
|
| 46 |
);
|
| 47 |
}
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
export default function Deals() {
|
| 50 |
const [deals, setDeals] = useState([]);
|
| 51 |
const [total, setTotal] = useState(0);
|
|
@@ -187,7 +193,7 @@ export default function Deals() {
|
|
| 187 |
<table className="w-full text-sm min-w-[960px]">
|
| 188 |
<thead>
|
| 189 |
<tr className="bg-slate-50 text-left text-slate-600 border-b border-slate-200">
|
| 190 |
-
<th className="px-2 py-2 w-[4.25rem]" aria-label="Select and
|
| 191 |
<th className="px-3 py-2 font-medium">Deal</th>
|
| 192 |
<th className="px-3 py-2 font-medium">Stage</th>
|
| 193 |
<th className="px-3 py-2 font-medium">Owner</th>
|
|
@@ -236,10 +242,15 @@ export default function Deals() {
|
|
| 236 |
variant="ghost"
|
| 237 |
size="icon"
|
| 238 |
className="h-7 w-7 text-slate-500 hover:text-violet-700"
|
| 239 |
-
onClick={() =>
|
| 240 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 241 |
>
|
| 242 |
-
<
|
| 243 |
</Button>
|
| 244 |
</div>
|
| 245 |
</td>
|
|
|
|
| 1 |
import React, { useCallback, useEffect, useState } from 'react';
|
| 2 |
import { Link } from 'react-router-dom';
|
| 3 |
+
import { Search, Loader2, LayoutGrid, Pencil } from 'lucide-react';
|
| 4 |
import { Button } from '@/components/ui/button';
|
| 5 |
import { Select, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/select';
|
| 6 |
import AppShell from '@/components/layout/AppShell';
|
|
|
|
| 46 |
);
|
| 47 |
}
|
| 48 |
|
| 49 |
+
function focusFirstEditableInRow(tr) {
|
| 50 |
+
if (!tr) return;
|
| 51 |
+
const el = tr.querySelector('input:not([type="checkbox"]):not([type="hidden"]), textarea');
|
| 52 |
+
el?.focus?.();
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
export default function Deals() {
|
| 56 |
const [deals, setDeals] = useState([]);
|
| 57 |
const [total, setTotal] = useState(0);
|
|
|
|
| 193 |
<table className="w-full text-sm min-w-[960px]">
|
| 194 |
<thead>
|
| 195 |
<tr className="bg-slate-50 text-left text-slate-600 border-b border-slate-200">
|
| 196 |
+
<th className="px-2 py-2 w-[4.25rem]" aria-label="Select and table edit" />
|
| 197 |
<th className="px-3 py-2 font-medium">Deal</th>
|
| 198 |
<th className="px-3 py-2 font-medium">Stage</th>
|
| 199 |
<th className="px-3 py-2 font-medium">Owner</th>
|
|
|
|
| 242 |
variant="ghost"
|
| 243 |
size="icon"
|
| 244 |
className="h-7 w-7 text-slate-500 hover:text-violet-700"
|
| 245 |
+
onClick={(e) => {
|
| 246 |
+
e.stopPropagation();
|
| 247 |
+
focusFirstEditableInRow(
|
| 248 |
+
e.currentTarget.closest('tr')
|
| 249 |
+
);
|
| 250 |
+
}}
|
| 251 |
+
aria-label={`Edit fields in row for ${deal.name || 'deal'}`}
|
| 252 |
>
|
| 253 |
+
<Pencil className="h-3.5 w-3.5" aria-hidden />
|
| 254 |
</Button>
|
| 255 |
</div>
|
| 256 |
</td>
|
frontend/src/pages/Leads.jsx
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
| 10 |
UserPlus,
|
| 11 |
Trash2,
|
| 12 |
Handshake,
|
| 13 |
-
|
| 14 |
} from 'lucide-react';
|
| 15 |
import { Button } from '@/components/ui/button';
|
| 16 |
import { Select, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/select';
|
|
@@ -46,6 +46,12 @@ function isRowUiTarget(e) {
|
|
| 46 |
);
|
| 47 |
}
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
export default function Leads() {
|
| 50 |
const navigate = useNavigate();
|
| 51 |
const [leads, setLeads] = useState([]);
|
|
@@ -416,7 +422,7 @@ export default function Leads() {
|
|
| 416 |
aria-label="Select all on page"
|
| 417 |
/>
|
| 418 |
</th>
|
| 419 |
-
<th className="w-9 px-0 py-2" aria-label="
|
| 420 |
<th className="px-3 py-2 font-medium">Lead</th>
|
| 421 |
<th className="px-3 py-2 font-medium">Status</th>
|
| 422 |
<th className="px-3 py-2 font-medium">Company</th>
|
|
@@ -469,10 +475,13 @@ export default function Leads() {
|
|
| 469 |
variant="ghost"
|
| 470 |
size="icon"
|
| 471 |
className="h-8 w-8 text-slate-500 hover:text-violet-700"
|
| 472 |
-
onClick={() =>
|
| 473 |
-
|
|
|
|
|
|
|
|
|
|
| 474 |
>
|
| 475 |
-
<
|
| 476 |
</Button>
|
| 477 |
</td>
|
| 478 |
<td className="px-3 py-2 align-top max-w-[200px]">
|
|
|
|
| 10 |
UserPlus,
|
| 11 |
Trash2,
|
| 12 |
Handshake,
|
| 13 |
+
Pencil,
|
| 14 |
} from 'lucide-react';
|
| 15 |
import { Button } from '@/components/ui/button';
|
| 16 |
import { Select, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/select';
|
|
|
|
| 46 |
);
|
| 47 |
}
|
| 48 |
|
| 49 |
+
function focusFirstEditableInRow(tr) {
|
| 50 |
+
if (!tr) return;
|
| 51 |
+
const el = tr.querySelector('input:not([type="checkbox"]):not([type="hidden"]), textarea');
|
| 52 |
+
el?.focus?.();
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
export default function Leads() {
|
| 56 |
const navigate = useNavigate();
|
| 57 |
const [leads, setLeads] = useState([]);
|
|
|
|
| 422 |
aria-label="Select all on page"
|
| 423 |
/>
|
| 424 |
</th>
|
| 425 |
+
<th className="w-9 px-0 py-2" aria-label="Table edit" />
|
| 426 |
<th className="px-3 py-2 font-medium">Lead</th>
|
| 427 |
<th className="px-3 py-2 font-medium">Status</th>
|
| 428 |
<th className="px-3 py-2 font-medium">Company</th>
|
|
|
|
| 475 |
variant="ghost"
|
| 476 |
size="icon"
|
| 477 |
className="h-8 w-8 text-slate-500 hover:text-violet-700"
|
| 478 |
+
onClick={(e) => {
|
| 479 |
+
e.stopPropagation();
|
| 480 |
+
focusFirstEditableInRow(e.currentTarget.closest('tr'));
|
| 481 |
+
}}
|
| 482 |
+
aria-label={`Edit fields in row for ${displayName}`}
|
| 483 |
>
|
| 484 |
+
<Pencil className="h-4 w-4" aria-hidden />
|
| 485 |
</Button>
|
| 486 |
</td>
|
| 487 |
<td className="px-3 py-2 align-top max-w-[200px]">
|