diff --git a/src/App.test.tsx b/src/App.test.tsx
index ff9af23..cfe0d2e 100644
--- a/src/App.test.tsx
+++ b/src/App.test.tsx
@@ -402,6 +402,27 @@ describe('OTP verification and validation', () => {
await waitFor(() => expect(localStorage.getItem('token')).toBe('otp-token'));
expect(await screen.findByText('OTP validated successfully')).toBeInTheDocument();
+ await expectCodeVisible('UNUSED-CODE');
+ });
+
+ it('loads invites after 2FA even when no token is returned', async () => {
+ server.use(
+ http.post(`${API_HOST}/api/auth/login`, () =>
+ HttpResponse.json({ otp_enabled: true, otp_verified: true })
+ ),
+ http.post(`${API_HOST}/api/auth/otp/validate`, () => HttpResponse.json({}))
+ );
+
+ render();
+ fillLogin('twofa');
+ await waitFor(() =>
+ expect(screen.getByText('Two-Factor Authentication')).toBeInTheDocument()
+ );
+
+ fireEvent.change(screen.getByPlaceholderText('000000'), { target: { value: '123456' } });
+ fireEvent.click(screen.getByRole('button', { name: 'Validate' }));
+
+ await expectCodeVisible('UNUSED-CODE');
});
});
@@ -438,7 +459,7 @@ describe('used-by handle', () => {
expect(link).toHaveAttribute('href', 'https://bsky.app/profile/alice.bsky.social');
});
- it('falls back to a dash when the API returns no handle', async () => {
+ it('falls back to the DID when the API returns no handle', async () => {
const noHandle = [
{ ...didInvites[0], uses: [{ usedBy: 'did:plc:abc', usedAt: '2026-01-25T08:12:55.280Z' }] },
];
@@ -450,6 +471,8 @@ describe('used-by handle', () => {
await expectCodeVisible('DID-CODE');
expect(screen.queryByRole('link', { name: 'alice.bsky.social' })).not.toBeInTheDocument();
+ const link = screen.getAllByRole('link', { name: 'did:plc:abc' })[0];
+ expect(link).toHaveAttribute('href', 'https://bsky.app/profile/did:plc:abc');
});
});
diff --git a/src/App.tsx b/src/App.tsx
index 8c0e7df..6ed841b 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -415,9 +415,8 @@ function App() {
URL.revokeObjectURL(url);
};
- const isAdminPage = page === 'Admins';
useEffect(() => {
- if (!token) {
+ if (page !== 'Home' && page !== 'Admins') {
return;
}
let cancelled = false;
@@ -433,7 +432,7 @@ function App() {
return () => {
cancelled = true;
};
- }, [token, isAdminPage, fetchInvites, fetchAdmins]);
+ }, [page, fetchInvites, fetchAdmins]);
useEffect(() => {
if (!notice) {
@@ -836,7 +835,7 @@ function App() {
const status = getStatus(invite);
const usedAt = getUsedAt(invite);
const usedBy = getUsedBy(invite);
- const resolvedHandle = getUsedByHandle(invite);
+ const usedByLabel = getUsedByHandle(invite) || usedBy;
const accountStatus = getAccountStatus(invite);
return (
- {resolvedHandle ? (
+ {usedByLabel ? (
- {resolvedHandle}
+ {usedByLabel}
) : (
'-'
@@ -902,14 +901,9 @@ function App() {
{invite.uses?.[0]?.usedByEmail || '-'}
|
-
+ |
{usedBy ? (
-
- {usedBy}
-
+ {usedBy}
) : (
'-'
)}
@@ -942,7 +936,7 @@ function App() {
const status = getStatus(invite);
const usedAt = getUsedAt(invite);
const usedBy = getUsedBy(invite);
- const resolvedHandle = getUsedByHandle(invite);
+ const usedByLabel = getUsedByHandle(invite) || usedBy;
const accountStatus = getAccountStatus(invite);
return (
| |