improvement/ux-overhaul up #61
@@ -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);
|
||||||
|
setSearching(true);
|
||||||
|
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
void (async () => {
|
||||||
|
setToastError('');
|
||||||
try {
|
try {
|
||||||
const res = await organizationApi.search(q);
|
const res = await organizationApi.search(q);
|
||||||
|
if (cancelled) return;
|
||||||
setSearchResults(res.data);
|
setSearchResults(res.data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
toast.showError(formatApiMessage(e));
|
if (cancelled) return;
|
||||||
|
showError(formatApiMessage(e));
|
||||||
setSearchResults([]);
|
setSearchResults([]);
|
||||||
} finally {
|
} finally {
|
||||||
setSearching(false);
|
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,19 +331,9 @@ 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
|
|
||||||
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' && (
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={clearSearchView}
|
onClick={clearSearchView}
|
||||||
@@ -335,13 +341,12 @@ export default function OrganizationsPage() {
|
|||||||
>
|
>
|
||||||
{t('backToList')}
|
{t('backToList')}
|
||||||
</button>
|
</button>
|
||||||
)}
|
) : undefined
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<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')}
|
||||||
|
|||||||
Reference in New Issue
Block a user