improvement/ux-overhaul up #61

Merged
rameen merged 24 commits from improvement/ux-overhaul into master 2026-07-14 22:46:19 +03:30
Showing only changes of commit 3b47aa9605 - Show all commits

View File

@@ -48,6 +48,7 @@ export default function OrganizationsPage() {
const { currentOrganization } = useAuth(); const { currentOrganization } = useAuth();
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const toast = useToast(); const toast = useToast();
const { showError, setError: setToastError } = toast;
const formatApiMessage = useCallback( const formatApiMessage = useCallback(
(err: unknown): string => getUserFacingError(err, tErrors, tCommon('errorGeneric')), (err: unknown): string => getUserFacingError(err, tErrors, tCommon('errorGeneric')),
@@ -122,29 +123,44 @@ export default function OrganizationsPage() {
void loadList(); void loadList();
}, []); }, []);
async function runSearch() { useEffect(() => {
let cancelled = false;
const q = query.trim(); const q = query.trim();
if (!q) { if (!q) {
setMode('existing'); setMode('existing');
setSearchResults([]); setSearchResults([]);
setShowInviteForm(false); setShowInviteForm(false);
setSearching(false);
return; return;
} }
setSearching(true);
toast.setError('');
setMode('search'); setMode('search');
setShowInviteForm(false); setShowInviteForm(false);
try { setSearching(true);
const res = await organizationApi.search(q);
setSearchResults(res.data); const timeout = setTimeout(() => {
} catch (e) { void (async () => {
toast.showError(formatApiMessage(e)); setToastError('');
setSearchResults([]); try {
} finally { const res = await organizationApi.search(q);
setSearching(false); if (cancelled) return;
} setSearchResults(res.data);
} } catch (e) {
if (cancelled) return;
showError(formatApiMessage(e));
setSearchResults([]);
} finally {
if (!cancelled) setSearching(false);
}
})();
}, 300);
return () => {
cancelled = true;
clearTimeout(timeout);
};
}, [query, formatApiMessage, showError, setToastError]);
async function submitConnectionRequest(targetOrganizationId: string) { async function submitConnectionRequest(targetOrganizationId: string) {
setPendingConnectionRowId(targetOrganizationId); setPendingConnectionRowId(targetOrganizationId);
@@ -315,33 +331,22 @@ export default function OrganizationsPage() {
<SearchBar <SearchBar
value={query} value={query}
onChange={setQuery} onChange={setQuery}
onSubmit={() => void runSearch()}
placeholder={t('searchPlaceholder', { counterpart: counterpart.toLowerCase() })} placeholder={t('searchPlaceholder', { counterpart: counterpart.toLowerCase() })}
actions={ actions={
<> query.trim() ? (
<button <button
type="button" type="button"
onClick={() => void runSearch()} onClick={clearSearchView}
disabled={searching} className="px-4 py-2 rounded-[var(--radius-sm)] text-sm font-medium border text-text-secondary border-border/40 hover:bg-background-card/70 hover:border-border"
className="px-4 py-2 rounded-[var(--radius-sm)] text-sm font-medium border bg-primary-soft text-primary border-primary/50 disabled:opacity-60"
> >
{tCommon('search')} {t('backToList')}
</button> </button>
{mode === 'search' && ( ) : undefined
<button
type="button"
onClick={clearSearchView}
className="px-4 py-2 rounded-[var(--radius-sm)] text-sm font-medium border text-text-secondary border-border/40 hover:bg-background-card/70 hover:border-border"
>
{t('backToList')}
</button>
)}
</>
} }
/> />
<OrganizationConnectionsMobileList <OrganizationConnectionsMobileList
loading={loading} loading={loading || searching}
mode={mode} mode={mode}
existingRows={existingRows} existingRows={existingRows}
searchResults={searchResults} searchResults={searchResults}
@@ -409,7 +414,7 @@ export default function OrganizationsPage() {
} }
body={ body={
<> <>
{loading ? ( {loading || (mode === 'search' && searching) ? (
<tr> <tr>
<td colSpan={5} className="px-6 py-8 text-sm text-text-secondary"> <td colSpan={5} className="px-6 py-8 text-sm text-text-secondary">
{tCommon('loadingEllipsis')} {tCommon('loadingEllipsis')}