fix(landing): 인증 상태에 따라 CTA 경로 분기
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { copy } from '@/shared/i18n';
|
import { copy } from '@/shared/i18n';
|
||||||
|
import { AuthLandingLoginButton } from "@/features/auth/components/AuthLandingLoginButton";
|
||||||
import { AuthRedirectButton } from "@/features/auth/components/AuthRedirectButton";
|
import { AuthRedirectButton } from "@/features/auth/components/AuthRedirectButton";
|
||||||
import { Button } from "@/shared/ui/Button";
|
import { Button } from "@/shared/ui/Button";
|
||||||
|
|
||||||
@@ -19,7 +20,9 @@ export default function MarketingPage() {
|
|||||||
<nav className="hidden md:flex items-center gap-6 text-sm font-medium text-brand-dark/80">
|
<nav className="hidden md:flex items-center gap-6 text-sm font-medium text-brand-dark/80">
|
||||||
<Button variant="ghost" size="sm" href="#features">{landing.nav.features}</Button>
|
<Button variant="ghost" size="sm" href="#features">{landing.nav.features}</Button>
|
||||||
<Button variant="ghost" size="sm" href="#pricing">{landing.nav.pricing}</Button>
|
<Button variant="ghost" size="sm" href="#pricing">{landing.nav.pricing}</Button>
|
||||||
<Button variant="ghost" size="sm" href="/login">{landing.nav.login}</Button>
|
<AuthLandingLoginButton variant="ghost" size="sm">
|
||||||
|
{landing.nav.login}
|
||||||
|
</AuthLandingLoginButton>
|
||||||
<AuthRedirectButton variant="primary" size="md">{landing.nav.startFree}</AuthRedirectButton>
|
<AuthRedirectButton variant="primary" size="md">{landing.nav.startFree}</AuthRedirectButton>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
38
src/features/auth/components/AuthLandingLoginButton.tsx
Normal file
38
src/features/auth/components/AuthLandingLoginButton.tsx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import type { ReactNode } from 'react';
|
||||||
|
import { useAuthStore } from '@/entities/auth';
|
||||||
|
import { Button, type ButtonSize, type ButtonVariant } from '@/shared/ui/Button';
|
||||||
|
import { hasClientAuth } from '../model/hasClientAuth';
|
||||||
|
|
||||||
|
interface AuthLandingLoginButtonProps {
|
||||||
|
children: ReactNode;
|
||||||
|
className?: string;
|
||||||
|
size?: ButtonSize;
|
||||||
|
variant?: ButtonVariant;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function AuthLandingLoginButton({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
size = 'sm',
|
||||||
|
variant = 'ghost',
|
||||||
|
}: AuthLandingLoginButtonProps) {
|
||||||
|
const accessToken = useAuthStore((state) => state.accessToken);
|
||||||
|
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||||
|
|
||||||
|
if (
|
||||||
|
hasClientAuth({
|
||||||
|
accessToken,
|
||||||
|
isAuthenticated,
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button href="/login" variant={variant} size={size} className={className}>
|
||||||
|
{children}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import Cookies from 'js-cookie';
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { useAuthStore } from '@/entities/auth';
|
import { useAuthStore } from '@/entities/auth';
|
||||||
import { TOKEN_COOKIE_KEY } from '@/shared/config/authTokens';
|
|
||||||
import { Button, type ButtonSize, type ButtonVariant } from '@/shared/ui/Button';
|
import { Button, type ButtonSize, type ButtonVariant } from '@/shared/ui/Button';
|
||||||
|
import { hasClientAuth } from '../model/hasClientAuth';
|
||||||
|
|
||||||
interface AuthRedirectButtonProps {
|
interface AuthRedirectButtonProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
@@ -21,7 +20,7 @@ export function AuthRedirectButton({
|
|||||||
className,
|
className,
|
||||||
size = 'md',
|
size = 'md',
|
||||||
variant = 'primary',
|
variant = 'primary',
|
||||||
authenticatedHref = '/space',
|
authenticatedHref = '/app',
|
||||||
unauthenticatedHref = '/login',
|
unauthenticatedHref = '/login',
|
||||||
}: AuthRedirectButtonProps) {
|
}: AuthRedirectButtonProps) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -29,8 +28,14 @@ export function AuthRedirectButton({
|
|||||||
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
const isAuthenticated = useAuthStore((state) => state.isAuthenticated);
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
const hasAccessToken = isAuthenticated || Boolean(accessToken) || Boolean(Cookies.get(TOKEN_COOKIE_KEY));
|
router.push(
|
||||||
router.push(hasAccessToken ? authenticatedHref : unauthenticatedHref);
|
hasClientAuth({
|
||||||
|
accessToken,
|
||||||
|
isAuthenticated,
|
||||||
|
})
|
||||||
|
? authenticatedHref
|
||||||
|
: unauthenticatedHref,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
13
src/features/auth/model/hasClientAuth.ts
Normal file
13
src/features/auth/model/hasClientAuth.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Cookies from 'js-cookie';
|
||||||
|
import { TOKEN_COOKIE_KEY } from '@/shared/config/authTokens';
|
||||||
|
|
||||||
|
interface HasClientAuthInput {
|
||||||
|
accessToken: string | null;
|
||||||
|
isAuthenticated: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const hasClientAuth = ({ accessToken, isAuthenticated }: HasClientAuthInput) => {
|
||||||
|
return isAuthenticated || Boolean(accessToken) || Boolean(Cookies.get(TOKEN_COOKIE_KEY));
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user