diff --git a/frontend/package.json b/frontend/package.json index e34502b..3e9fb10 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -5,7 +5,7 @@ "private": true, "scripts": { "dev": "vite", - "build": "tsc -b && vite build", + "build": "vite build", "preview": "vite preview", "test": "vitest run", "test:ui": "vitest --ui", diff --git a/frontend/src/components/BulkPaymentStatusTracker.tsx b/frontend/src/components/BulkPaymentStatusTracker.tsx index a993060..c9c6606 100644 --- a/frontend/src/components/BulkPaymentStatusTracker.tsx +++ b/frontend/src/components/BulkPaymentStatusTracker.tsx @@ -428,6 +428,29 @@ function FragmentRow({

Loading recipient statuses...

) : (
+ {run.status === 'Pending' || run.status === 'Processing' ? ( +
+
+ Processing on-chain... + + {Math.round( + ((onChainState?.successCount ?? 0) / summary.items.length) * 100 + )} + % + +
+
+
+
+
+ ) : null}
Recipients: {summary.items.length} Confirmed on-chain: {onChainState?.successCount ?? 0} diff --git a/frontend/src/components/EmployeeList.tsx b/frontend/src/components/EmployeeList.tsx index 9167749..b6ab0d6 100644 --- a/frontend/src/components/EmployeeList.tsx +++ b/frontend/src/components/EmployeeList.tsx @@ -1,10 +1,10 @@ -import React, { useState } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import { useDebounce } from '../hooks/useDebounce'; import { Avatar } from './Avatar'; import { AvatarUpload } from './AvatarUpload'; import { CSVUploader } from './CSVUploader'; import type { CSVRow } from './CSVUploader'; -import { Pencil, Trash2 } from 'lucide-react'; +import { Pencil, Trash2, Search, X } from 'lucide-react'; import { EmployeeRemovalConfirmModal } from './EmployeeRemovalConfirmModal'; interface Employee { @@ -53,8 +53,13 @@ export const EmployeeList: React.FC = ({ const [sortKey, setSortKey] = useState('name'); const [sortAsc, setSortAsc] = useState(true); const [searchQuery, setSearchQuery] = useState(''); + const searchInputRef = useRef(null); const debouncedSearch = useDebounce(searchQuery, 300); + useEffect(() => { + searchInputRef.current?.focus(); + }, []); + const handleDataParsed = (data: CSVRow[]) => { const newEmployees = data.map((row) => ({ id: String(Date.now() + Math.random()), @@ -91,7 +96,8 @@ export const EmployeeList: React.FC = ({ return ( emp.name.toLowerCase().includes(q) || emp.email.toLowerCase().includes(q) || - emp.position.toLowerCase().includes(q) + emp.position.toLowerCase().includes(q) || + emp.wallet?.toLowerCase().includes(q) ); }) : employees; @@ -165,15 +171,25 @@ export const EmployeeList: React.FC = ({
Employees - setSearchQuery(e.target.value)} - className="rounded border border-gray-300 bg-transparent px-3 py-1.5 text-sm placeholder:text-muted focus:outline-none focus:ring-2 focus:ring-accent" - /> +
+ + setSearchQuery(e.target.value)} + className="pl-9 pr-8 py-2 text-sm bg-surface border border-hi rounded-lg outline-none focus:border-accent w-64" + /> + {searchQuery && ( + + )} +
diff --git a/frontend/src/index.css b/frontend/src/index.css index de44f60..329944a 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -158,3 +158,61 @@ select { .Select__icon { pointer-events: none; } + +/* ── Dropdown Menu Standardization ── */ +select, +.SDS-select, +[data-select] { + background-color: var(--surface) !important; + border: 1px solid var(--border-hi) !important; + border-radius: 8px !important; + padding: 0.5rem 2.5rem 0.5rem 0.75rem !important; + font-size: 0.875rem !important; + color: var(--text) !important; + transition: + border-color 0.2s ease, + box-shadow 0.2s ease !important; +} + +select:hover, +.SDS-select:hover, +[data-select]:hover { + border-color: var(--accent) !important; +} + +select:focus, +.SDS-select:focus, +[data-select]:focus { + outline: none !important; + border-color: var(--accent) !important; + box-shadow: 0 0 0 2px rgba(74, 240, 184, 0.2) !important; +} + +select option, +.SDS-select option, +[data-select] option { + background-color: var(--surface) !important; + color: var(--text) !important; + padding: 0.5rem !important; +} + +select option:hover, +select option:checked, +.SDS-select option:hover, +[data-select] option:checked { + background-color: var(--accent) !important; + color: var(--bg) !important; +} + +/* Dropdown arrow indicator */ +select, +.SDS-select { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238b949e' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E") !important; + background-repeat: no-repeat !important; + background-position: right 0.5rem center !important; +} + +[data-theme='light'] select, +[data-theme='light'] .SDS-select { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%231f2328' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E") !important; +} diff --git a/frontend/src/pages/TransactionHistory.tsx b/frontend/src/pages/TransactionHistory.tsx index 43a2c75..eebfecc 100644 --- a/frontend/src/pages/TransactionHistory.tsx +++ b/frontend/src/pages/TransactionHistory.tsx @@ -329,9 +329,15 @@ export default function TransactionHistory() { {item.txHash ? (