improvement/ux-overhaul up #61
@@ -48,6 +48,7 @@ export default function OrganizationsPage() {
|
||||
const { currentOrganization } = useAuth();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const toast = useToast();
|
||||
const { showError, setError: setToastError } = toast;
|
||||
|
||||
const formatApiMessage = useCallback(
|
||||
(err: unknown): string => getUserFacingError(err, tErrors, tCommon('errorGeneric')),
|
||||
@@ -122,29 +123,44 @@ export default function OrganizationsPage() {
|
||||
void loadList();
|
||||
}, []);
|
||||
|
||||
async function runSearch() {
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const q = query.trim();
|
||||
|
||||
if (!q) {
|
||||
setMode('existing');
|
||||
setSearchResults([]);
|
||||
setShowInviteForm(false);
|
||||
setSearching(false);
|
||||
return;
|
||||
}
|
||||
|
||||
setSearching(true);
|
||||
toast.setError('');
|
||||
setMode('search');
|
||||
setShowInviteForm(false);
|
||||
setSearching(true);
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
void (async () => {
|
||||
setToastError('');
|
||||
try {
|
||||
const res = await organizationApi.search(q);
|
||||
if (cancelled) return;
|
||||
setSearchResults(res.data);
|
||||
} catch (e) {
|
||||
toast.showError(formatApiMessage(e));
|
||||
if (cancelled) return;
|
||||
showError(formatApiMessage(e));
|
||||
setSearchResults([]);
|
||||
} finally {
|
||||
setSearching(false);
|
||||
}
|
||||
if (!cancelled) setSearching(false);
|
||||
}
|
||||
})();
|
||||
}, 300);
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}, [query, formatApiMessage, showError, setToastError]);
|
||||
|
||||
async function submitConnectionRequest(targetOrganizationId: string) {
|
||||
setPendingConnectionRowId(targetOrganizationId);
|
||||
@@ -315,19 +331,9 @@ export default function OrganizationsPage() {
|
||||
<SearchBar
|
||||
value={query}
|
||||
onChange={setQuery}
|
||||
onSubmit={() => void runSearch()}
|
||||
placeholder={t('searchPlaceholder', { counterpart: counterpart.toLowerCase() })}
|
||||
actions={
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => void runSearch()}
|
||||
disabled={searching}
|
||||
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')}
|
||||
</button>
|
||||
{mode === 'search' && (
|
||||
query.trim() ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={clearSearchView}
|
||||
@@ -335,13 +341,12 @@ export default function OrganizationsPage() {
|
||||
>
|
||||
{t('backToList')}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
|
||||
<OrganizationConnectionsMobileList
|
||||
loading={loading}
|
||||
loading={loading || searching}
|
||||
mode={mode}
|
||||
existingRows={existingRows}
|
||||
searchResults={searchResults}
|
||||
@@ -409,7 +414,7 @@ export default function OrganizationsPage() {
|
||||
}
|
||||
body={
|
||||
<>
|
||||
{loading ? (
|
||||
{loading || (mode === 'search' && searching) ? (
|
||||
<tr>
|
||||
<td colSpan={5} className="px-6 py-8 text-sm text-text-secondary">
|
||||
{tCommon('loadingEllipsis')}
|
||||
|
||||
Reference in New Issue
Block a user