added "members" for an event that help the admins to moderate. members must be invited via email.

This commit is contained in:
Codex Agent
2025-11-09 22:24:40 +01:00
parent 082b78cd43
commit 7ec3db9c59
23 changed files with 836 additions and 101 deletions

View File

@@ -10,7 +10,7 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useAuth } from '../auth/context';
import { ADMIN_DEFAULT_AFTER_LOGIN_PATH } from '../constants';
import { ADMIN_DEFAULT_AFTER_LOGIN_PATH, ADMIN_EVENTS_PATH } from '../constants';
import { encodeReturnTo, resolveReturnTarget } from '../lib/returnTo';
import { useMutation } from '@tanstack/react-query';
@@ -48,7 +48,7 @@ type LoginResponse = {
}
export default function LoginPage(): JSX.Element {
const { status, applyToken } = useAuth();
const { status, applyToken, abilities } = useAuth();
const { t } = useTranslation('auth');
const location = useLocation();
const navigate = useNavigate();
@@ -56,7 +56,15 @@ export default function LoginPage(): JSX.Element {
const searchParams = React.useMemo(() => new URLSearchParams(location.search), [location.search]);
const rawReturnTo = searchParams.get('return_to');
const fallbackTarget = ADMIN_DEFAULT_AFTER_LOGIN_PATH;
const computeDefaultAfterLogin = React.useCallback(
(abilityList?: string[]) => {
const source = abilityList ?? abilities;
return source.includes('tenant-admin') ? ADMIN_DEFAULT_AFTER_LOGIN_PATH : ADMIN_EVENTS_PATH;
},
[abilities],
);
const fallbackTarget = computeDefaultAfterLogin();
const { finalTarget } = React.useMemo(
() => resolveReturnTarget(rawReturnTo, fallbackTarget),
[rawReturnTo, fallbackTarget]
@@ -82,7 +90,9 @@ export default function LoginPage(): JSX.Element {
onSuccess: async (data) => {
setError(null);
await applyToken(data.token, data.abilities ?? []);
navigate(finalTarget, { replace: true });
const postLoginFallback = computeDefaultAfterLogin(data.abilities ?? []);
const { finalTarget: successTarget } = resolveReturnTarget(rawReturnTo, postLoginFallback);
navigate(successTarget, { replace: true });
},
});