Files
cozsweet-frontend-nextjs/src/router/use-app-navigator.ts
T

141 lines
3.5 KiB
TypeScript

"use client";
import { useRouter } from "next/navigation";
import { NavigationStorage } from "@/data/storage/navigation";
import { getDefaultPayChannelForCountryCode } from "@/lib/payment/default_pay_channel";
import { useAuthState } from "@/stores/auth/auth-context";
import { useUserState } from "@/stores/user/user-context";
import {
ROUTE_BUILDERS,
ROUTES,
type Route,
} from "./routes";
import {
isAuthenticatedUser as resolveIsAuthenticatedUser,
resolveAuthenticatedNavigation,
} from "./navigation-resolver";
import type {
OpenSubscriptionForPendingUnlockInput,
OpenSubscriptionInput,
StartMessageUnlockInput,
} from "./navigation-types";
export interface AppNavigator {
push: (href: string, options?: { scroll?: boolean }) => void;
replace: (href: string, options?: { scroll?: boolean }) => void;
openAuth: (redirectTo?: string) => void;
openSubscription: (input: OpenSubscriptionInput) => void;
startMessageUnlock: (input: StartMessageUnlockInput) => void;
openSubscriptionForPendingUnlock: (
input: OpenSubscriptionForPendingUnlockInput,
) => void;
getDefaultPayChannel: () => ReturnType<typeof getDefaultPayChannelForCountryCode>;
isAuthenticatedUser: boolean;
}
export function useAppNavigator(): AppNavigator {
const router = useRouter();
const authState = useAuthState();
const userState = useUserState();
const isAuthenticatedUser = resolveIsAuthenticatedUser(authState.loginStatus);
function push(href: string, options?: { scroll?: boolean }): void {
router.push(href, options);
}
function replace(href: string, options?: { scroll?: boolean }): void {
router.replace(href, options);
}
function openAuth(redirectTo: string = ROUTES.chat): void {
router.push(ROUTE_BUILDERS.authWithRedirect(redirectTo));
}
function getDefaultPayChannel() {
return getDefaultPayChannelForCountryCode(userState.currentUser?.countryCode);
}
function openSubscription({
type,
payChannel = getDefaultPayChannel(),
returnTo = null,
replace: shouldReplace = false,
}: OpenSubscriptionInput): void {
const target = ROUTE_BUILDERS.subscription(type, {
payChannel,
returnTo: returnTo ?? undefined,
});
const nextUrl = resolveAuthenticatedNavigation({
loginStatus: authState.loginStatus,
targetUrl: target,
});
if (shouldReplace) {
router.replace(nextUrl);
return;
}
router.push(nextUrl);
}
function startMessageUnlock({
messageId,
kind,
returnUrl,
stage = "auth",
onAuthenticated,
}: StartMessageUnlockInput): void {
if (isAuthenticatedUser) {
onAuthenticated();
return;
}
void (async () => {
await NavigationStorage.savePendingChatUnlock({
messageId,
kind,
returnUrl,
stage,
});
router.push(ROUTE_BUILDERS.authWithRedirect(returnUrl));
})();
}
function openSubscriptionForPendingUnlock({
messageId,
kind,
returnUrl,
type,
payChannel = getDefaultPayChannel(),
}: OpenSubscriptionForPendingUnlockInput): void {
void (async () => {
await NavigationStorage.savePendingChatUnlock({
messageId,
kind,
returnUrl,
stage: "payment",
});
openSubscription({
type,
payChannel,
returnTo: "chat",
});
})();
}
return {
push,
replace,
openAuth,
openSubscription,
startMessageUnlock,
openSubscriptionForPendingUnlock,
getDefaultPayChannel,
isAuthenticatedUser,
};
}
export type { Route };