This commit is contained in:
2026-06-15 11:46:34 +03:00
parent c40dc0c711
commit c104277964
2 changed files with 54 additions and 3 deletions
+44 -3
View File
@@ -1,6 +1,6 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { createContext, useContext, useState } from "react";
import { login, logout, register } from "#/api/auth";
import { createContext, useContext, useEffect, useState } from "react";
import { getCurrentUser, login, logout, register } from "#/api/auth";
import type { AuthUser, LoginRequest, RegisterRequest } from "#/types/auth";
type AuthContextValue = {
@@ -21,6 +21,47 @@ export const authQueryKeys = {
export function AuthProvider({ children }: { children: React.ReactNode }) {
const queryClient = useQueryClient();
const [user, setUser] = useState<AuthUser | null>(() => readStoredUser());
const [isLoading, setIsLoading] = useState(() => readStoredUser() !== null);
const userId = user?.id;
useEffect(() => {
let cancelled = false;
if (!userId) {
setIsLoading(false);
return;
}
setIsLoading(true);
getCurrentUser()
.then((currentUser) => {
if (cancelled) {
return;
}
persistUser(currentUser);
setUser(currentUser);
queryClient.setQueryData(authQueryKeys.me, currentUser);
})
.catch(() => {
if (cancelled) {
return;
}
persistUser(null);
setUser(null);
queryClient.clear();
})
.finally(() => {
if (!cancelled) {
setIsLoading(false);
}
});
return () => {
cancelled = true;
};
}, [queryClient, userId]);
const loginMutation = useMutation({
mutationFn: login,
@@ -60,7 +101,7 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const value: AuthContextValue = {
user,
isLoading: false,
isLoading,
login: loginMutation.mutateAsync,
register: registerMutation.mutateAsync,
logout: logoutUser,
+10
View File
@@ -2,6 +2,7 @@ import { createFileRoute, Link, useNavigate } from "@tanstack/react-router";
import { CreditCard, ShoppingCart, Trash2 } from "lucide-react";
import { useMemo, useState } from "react";
import { toast } from "sonner";
import { ApiError } from "#/api/client";
import { AuthDialog } from "#/components/store/AuthDialog";
import { QuantityStepper } from "#/components/store/QuantityStepper";
import { SiteHeader } from "#/components/store/SiteHeader";
@@ -129,6 +130,15 @@ function CartPage() {
});
await navigate({ to: "/orders" });
} catch (error) {
if (error instanceof ApiError && error.status === 403) {
await logout();
setAuthMode("login");
toast.error("Sign in again", {
description: "Your session expired before checkout.",
});
return;
}
toast.error("Checkout failed", {
description:
error instanceof Error