From 34c8d16c7d9c41d8a8bd3cec8dd70a3039138d3d Mon Sep 17 00:00:00 2001 From: Stavros Date: Fri, 30 May 2025 18:14:33 +0300 Subject: [PATCH] fix: fix loading states in forms --- frontend/src/index.css | 2 +- frontend/src/pages/continue-page.tsx | 28 ++++++++++++++---------- frontend/src/pages/login-page.tsx | 8 ++++++- frontend/src/pages/not-found-page.tsx | 9 +++++++- frontend/src/pages/totp-page.tsx | 12 +++++++--- frontend/src/pages/unauthorized-page.tsx | 9 +++++++- internal/utils/utils.go | 10 ++++----- 7 files changed, 54 insertions(+), 24 deletions(-) diff --git a/frontend/src/index.css b/frontend/src/index.css index c80b837..450e642 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -136,7 +136,7 @@ h4 { } p { - @apply leading-7 [&:not(:first-child)]:mt-6; + @apply leading-6 [&:not(:first-child)]:mt-6; } blockquote { diff --git a/frontend/src/pages/continue-page.tsx b/frontend/src/pages/continue-page.tsx index 8b932db..cc4d432 100644 --- a/frontend/src/pages/continue-page.tsx +++ b/frontend/src/pages/continue-page.tsx @@ -12,6 +12,7 @@ import { isValidUrl } from "@/lib/utils"; import { Trans, useTranslation } from "react-i18next"; import { Navigate, useLocation, useNavigate } from "react-router"; import DOMPurify from "dompurify"; +import { useState } from "react"; export const ContinuePage = () => { const { isLoggedIn } = useUserContext(); @@ -22,6 +23,7 @@ export const ContinuePage = () => { const { domain, disableContinue } = useAppContext(); const { search } = useLocation(); + const [loading, setLoading] = useState(false); const searchParams = new URLSearchParams(search); const redirectURI = searchParams.get("redirect_uri"); @@ -34,10 +36,15 @@ export const ContinuePage = () => { return ; } - if (disableContinue) { + const handleRedirect = () => { + setLoading(true); window.location.href = DOMPurify.sanitize(redirectURI); } + if (disableContinue) { + handleRedirect(); + } + const { t } = useTranslation(); const navigate = useNavigate(); @@ -63,14 +70,13 @@ export const ContinuePage = () => { - @@ -97,14 +103,13 @@ export const ContinuePage = () => { - @@ -120,9 +125,8 @@ export const ContinuePage = () => { diff --git a/frontend/src/pages/login-page.tsx b/frontend/src/pages/login-page.tsx index 642d59b..9f048f5 100644 --- a/frontend/src/pages/login-page.tsx +++ b/frontend/src/pages/login-page.tsx @@ -126,6 +126,8 @@ export const LoginPage = () => { icon={} className="w-full" onClick={() => oauthMutation.mutate("google")} + loading={oauthMutation.isPending && oauthMutation.variables === "google"} + disabled={oauthMutation.isPending || loginMutation.isPending} /> )} {configuredProviders.includes("github") && ( @@ -134,6 +136,8 @@ export const LoginPage = () => { icon={} className="w-full" onClick={() => oauthMutation.mutate("github")} + loading={oauthMutation.isPending && oauthMutation.variables === "github"} + disabled={oauthMutation.isPending || loginMutation.isPending} /> )} {configuredProviders.includes("generic") && ( @@ -142,6 +146,8 @@ export const LoginPage = () => { icon={} className="w-full" onClick={() => oauthMutation.mutate("generic")} + loading={oauthMutation.isPending && oauthMutation.variables === "generic"} + disabled={oauthMutation.isPending || loginMutation.isPending} /> )} @@ -152,7 +158,7 @@ export const LoginPage = () => { {userAuthConfigured && ( loginMutation.mutate(values)} - loading={loginMutation.isPending} + loading={loginMutation.isPending || oauthMutation.isPending} /> )} {configuredProviders.length == 0 && ( diff --git a/frontend/src/pages/not-found-page.tsx b/frontend/src/pages/not-found-page.tsx index 8f0c051..f0d82f8 100644 --- a/frontend/src/pages/not-found-page.tsx +++ b/frontend/src/pages/not-found-page.tsx @@ -6,12 +6,19 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import { useState } from "react"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router"; export const NotFoundPage = () => { const { t } = useTranslation(); const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + + const handleRedirect = () => { + setLoading(true); + navigate("/"); + }; return ( @@ -20,7 +27,7 @@ export const NotFoundPage = () => { {t("notFoundSubtitle")} - + ); diff --git a/frontend/src/pages/totp-page.tsx b/frontend/src/pages/totp-page.tsx index 09a16ee..e04fb2f 100644 --- a/frontend/src/pages/totp-page.tsx +++ b/frontend/src/pages/totp-page.tsx @@ -8,18 +8,24 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import { useUserContext } from "@/context/user-context"; import { TotpSchema } from "@/schemas/totp-schema"; import { useMutation } from "@tanstack/react-query"; import axios from "axios"; import { useId } from "react"; import { useTranslation } from "react-i18next"; -import { useLocation, useNavigate } from "react-router"; +import { Navigate, useLocation } from "react-router"; import { toast } from "sonner"; export const TotpPage = () => { + const { totpPending } = useUserContext(); + + if (!totpPending) { + return ; + } + const { t } = useTranslation(); const { search } = useLocation(); - const navigate = useNavigate(); const formId = useId(); const searchParams = new URLSearchParams(search); @@ -34,7 +40,7 @@ export const TotpPage = () => { }); setTimeout(() => { - navigate( + window.location.replace( `/continue?redirect_uri=${encodeURIComponent(redirectUri ?? "")}`, ); }, 500); diff --git a/frontend/src/pages/unauthorized-page.tsx b/frontend/src/pages/unauthorized-page.tsx index 1dbbd66..e41cad8 100644 --- a/frontend/src/pages/unauthorized-page.tsx +++ b/frontend/src/pages/unauthorized-page.tsx @@ -6,6 +6,7 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import { useState } from "react"; import { Trans, useTranslation } from "react-i18next"; import { Navigate, useLocation, useNavigate } from "react-router"; @@ -23,6 +24,12 @@ export const UnauthorizedPage = () => { const { t } = useTranslation(); const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + + const handleRedirect = () => { + setLoading(true); + navigate("/login"); + }; let i18nKey = "unauthorizedLoginSubtitle"; @@ -53,7 +60,7 @@ export const UnauthorizedPage = () => { - diff --git a/internal/utils/utils.go b/internal/utils/utils.go index 9c2a6ab..e7957c2 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -255,16 +255,16 @@ func ParseUser(user string) (types.User, error) { // Check if the user has a totp secret if len(userSplit) == 2 { return types.User{ - Username: userSplit[0], - Password: userSplit[1], + Username: strings.TrimSpace(userSplit[0]), + Password: strings.TrimSpace(userSplit[1]), }, nil } // Return the user struct return types.User{ - Username: userSplit[0], - Password: userSplit[1], - TotpSecret: userSplit[2], + Username: strings.TrimSpace(userSplit[0]), + Password: strings.TrimSpace(userSplit[1]), + TotpSecret: strings.TrimSpace(userSplit[2]), }, nil }