feat(landing): login register
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(npm run typecheck:*)"
|
||||||
|
],
|
||||||
|
"deny": [],
|
||||||
|
"ask": []
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,3 +22,4 @@ export async function fetchPostSignin({
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { CommunitySection } from '../_components/community-section';
|
||||||
|
import { CTASection } from '../_components/cta-section';
|
||||||
|
import { HeroSection } from '../_components/hero-section';
|
||||||
|
import { TestimonialSection } from '../_components/testimonial-section';
|
||||||
|
export default function Page() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<HeroSection />
|
||||||
|
<CommunitySection />
|
||||||
|
<TestimonialSection />
|
||||||
|
<CTASection />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import { CommunitySection } from './_components/community-section';
|
|
||||||
import { CTASection } from './_components/cta-section';
|
|
||||||
import { HeroSection } from './_components/hero-section';
|
|
||||||
import { TestimonialSection } from './_components/testimonial-section';
|
|
||||||
export default function Page() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<HeroSection />
|
|
||||||
<CommunitySection />
|
|
||||||
<TestimonialSection />
|
|
||||||
<CTASection />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import { LogoSimple } from '@/app/_components/logo';
|
import { LogoSimple } from '@/app/_components/logo';
|
||||||
import NAVIGATIONS from '@/data/navigations.json';
|
import NAVIGATIONS from '@/data/navigations.json';
|
||||||
|
import { useAuth } from '@/hooks/use-auth';
|
||||||
import { Button } from '@components';
|
import { Button } from '@components';
|
||||||
import { cn } from '@utils';
|
import { cn } from '@utils';
|
||||||
import { AnimatePresence, motion } from 'framer-motion';
|
import { AnimatePresence, motion } from 'framer-motion';
|
||||||
@@ -13,6 +14,7 @@ import { LuMenu, LuX } from 'react-icons/lu';
|
|||||||
export function Header() {
|
export function Header() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
const { isAuthenticated } = useAuth();
|
||||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -30,6 +32,13 @@ export function Header() {
|
|||||||
setMobileMenuOpen(false);
|
setMobileMenuOpen(false);
|
||||||
}, [pathname]);
|
}, [pathname]);
|
||||||
|
|
||||||
|
const handleLogout = () => {
|
||||||
|
document.cookie = '__imphnen_access_token__=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
|
||||||
|
document.cookie = '__imphnen_refresh_token__=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
|
||||||
|
router.push('/');
|
||||||
|
window.location.reload();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="sticky top-0 w-full z-50 bg-background/70">
|
<header className="sticky top-0 w-full z-50 bg-background/70">
|
||||||
<div className="container flex h-20 items-center justify-between">
|
<div className="container flex h-20 items-center justify-between">
|
||||||
@@ -62,19 +71,31 @@ export function Header() {
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div className="hidden md:flex items-center gap-x-3">
|
<div className="hidden md:flex items-center gap-x-3">
|
||||||
<Button
|
{isAuthenticated ? (
|
||||||
onClick={() => router.push('/signin')}
|
<Button
|
||||||
className="px-5 py-2 text-sm font-medium"
|
onClick={handleLogout}
|
||||||
>
|
variant="bordered"
|
||||||
Masuk
|
className="px-5 py-2 text-sm font-medium"
|
||||||
</Button>
|
>
|
||||||
<Button
|
Keluar
|
||||||
variant="bordered"
|
</Button>
|
||||||
onClick={() => router.push('/signup')}
|
) : (
|
||||||
className="px-5 py-2 text-sm font-medium shadow-lg shadow-primary/20 hover:shadow-primary/30"
|
<>
|
||||||
>
|
<Button
|
||||||
Daftar
|
onClick={() => router.push('/signin')}
|
||||||
</Button>
|
className="px-5 py-2 text-sm font-medium"
|
||||||
|
>
|
||||||
|
Masuk
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="bordered"
|
||||||
|
onClick={() => router.push('/signup')}
|
||||||
|
className="px-5 py-2 text-sm font-medium shadow-lg shadow-primary/20 hover:shadow-primary/30"
|
||||||
|
>
|
||||||
|
Daftar
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@@ -144,25 +165,40 @@ export function Header() {
|
|||||||
animate={{ y: 0, opacity: 1 }}
|
animate={{ y: 0, opacity: 1 }}
|
||||||
transition={{ delay: 0.2 }}
|
transition={{ delay: 0.2 }}
|
||||||
>
|
>
|
||||||
<Button
|
{isAuthenticated ? (
|
||||||
onClick={() => {
|
<Button
|
||||||
setMobileMenuOpen(false);
|
onClick={() => {
|
||||||
router.push('/signin');
|
setMobileMenuOpen(false);
|
||||||
}}
|
handleLogout();
|
||||||
className="w-full py-4 text-base"
|
}}
|
||||||
>
|
variant="bordered"
|
||||||
Masuk
|
className="w-full py-4 text-base"
|
||||||
</Button>
|
>
|
||||||
<Button
|
Keluar
|
||||||
variant="bordered"
|
</Button>
|
||||||
onClick={() => {
|
) : (
|
||||||
setMobileMenuOpen(false);
|
<>
|
||||||
router.push('/signup');
|
<Button
|
||||||
}}
|
onClick={() => {
|
||||||
className="w-full py-4 text-base shadow-lg shadow-primary/20"
|
setMobileMenuOpen(false);
|
||||||
>
|
router.push('/signin');
|
||||||
Daftar
|
}}
|
||||||
</Button>
|
className="w-full py-4 text-base"
|
||||||
|
>
|
||||||
|
Masuk
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="bordered"
|
||||||
|
onClick={() => {
|
||||||
|
setMobileMenuOpen(false);
|
||||||
|
router.push('/signup');
|
||||||
|
}}
|
||||||
|
className="w-full py-4 text-base shadow-lg shadow-primary/20"
|
||||||
|
>
|
||||||
|
Daftar
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export function useAuth() {
|
||||||
|
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);
|
||||||
|
const [cookie, setCookie] = useState<string | null>(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkAuth = () => {
|
||||||
|
const accessToken = document.cookie
|
||||||
|
.split('; ')
|
||||||
|
.find(row => row.startsWith('__imphnen_access_token__='))
|
||||||
|
?.split('=')[1];
|
||||||
|
|
||||||
|
setIsAuthenticated(!!accessToken);
|
||||||
|
setCookie(accessToken || null)
|
||||||
|
};
|
||||||
|
|
||||||
|
checkAuth();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function getToken (){
|
||||||
|
if(isAuthenticated) return cookie
|
||||||
|
}
|
||||||
|
|
||||||
|
return { isAuthenticated, getToken };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user