feat: implement logout action
This commit is contained in:
parent
5acf3970a3
commit
7db38d3b67
@ -42,7 +42,7 @@ export const PopupModal = ({
|
|||||||
<DialogTitle className="relative flex justify-center">
|
<DialogTitle className="relative flex justify-center">
|
||||||
<button
|
<button
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className="absolute top-0 left-0 items-center lg:hidden"
|
className="absolute top-0 left-0 items-center sm:hidden"
|
||||||
>
|
>
|
||||||
<LeftArrow
|
<LeftArrow
|
||||||
width={50}
|
width={50}
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export const SuccessModal = ({ isOpen, onClose }: ModalProperties) => {
|
|||||||
<DialogTitle className="relative flex justify-center">
|
<DialogTitle className="relative flex justify-center">
|
||||||
<button
|
<button
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className="absolute top-0 left-0 items-center lg:hidden"
|
className="absolute top-0 left-0 items-center sm:hidden"
|
||||||
>
|
>
|
||||||
<LeftArrow
|
<LeftArrow
|
||||||
width={50}
|
width={50}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { APP } from '~/configs/meta'
|
|||||||
|
|
||||||
export const Banner = () => {
|
export const Banner = () => {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-[65px] lg:mx-10">
|
<div className="min-h-[65px] sm:mx-10">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Link
|
<Link
|
||||||
to="/#"
|
to="/#"
|
||||||
|
|||||||
@ -115,7 +115,7 @@ export const Carousel = (properties: TNews) => {
|
|||||||
<div>
|
<div>
|
||||||
<h3
|
<h3
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'mt-2 w-full font-bold lg:mt-0',
|
'mt-2 w-full font-bold sm:mt-0',
|
||||||
type === 'hero'
|
type === 'hero'
|
||||||
? 'text-2xl sm:text-4xl'
|
? 'text-2xl sm:text-4xl'
|
||||||
: 'text-xl sm:text-2xl',
|
: 'text-xl sm:text-2xl',
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Link, useRouteLoaderData } from 'react-router'
|
import { Link, useFetcher, useRouteLoaderData } from 'react-router'
|
||||||
|
|
||||||
import { Button } from '~/components/ui/button'
|
import { Button } from '~/components/ui/button'
|
||||||
import { APP } from '~/configs/meta'
|
import { APP } from '~/configs/meta'
|
||||||
@ -8,6 +8,7 @@ import type { loader } from '~/routes/_layout.news'
|
|||||||
export const HeaderTop = () => {
|
export const HeaderTop = () => {
|
||||||
const { setIsLoginOpen } = useNewsContext()
|
const { setIsLoginOpen } = useNewsContext()
|
||||||
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout.news')
|
const loaderData = useRouteLoaderData<typeof loader>('routes/_layout.news')
|
||||||
|
const fetcher = useFetcher()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -29,13 +30,28 @@ export const HeaderTop = () => {
|
|||||||
<Button className="h-8 w-auto rounded-none px-3 text-xs sm:h-[50px] sm:w-[150px] sm:text-lg">
|
<Button className="h-8 w-auto rounded-none px-3 text-xs sm:h-[50px] sm:w-[150px] sm:text-lg">
|
||||||
About Us
|
About Us
|
||||||
</Button>
|
</Button>
|
||||||
|
{loaderData?.userToken ? (
|
||||||
|
<fetcher.Form
|
||||||
|
method="POST"
|
||||||
|
action="/actions/news/logout"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
variant="newsSecondary"
|
||||||
|
className="hidden sm:block"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Logout
|
||||||
|
</Button>
|
||||||
|
</fetcher.Form>
|
||||||
|
) : (
|
||||||
<Button
|
<Button
|
||||||
variant="newsSecondary"
|
variant="newsSecondary"
|
||||||
className="hidden sm:block"
|
className="hidden sm:block"
|
||||||
onClick={() => setIsLoginOpen(true)}
|
onClick={() => setIsLoginOpen(true)}
|
||||||
>
|
>
|
||||||
{loaderData?.userToken ? 'Logout' : 'Masuk'}
|
Masuk
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export const NewsPage = () => {
|
|||||||
<Carousel {...SPOTLIGHT} />
|
<Carousel {...SPOTLIGHT} />
|
||||||
</Card>
|
</Card>
|
||||||
<div className="min-h-[400px] sm:min-h-[300px]">
|
<div className="min-h-[400px] sm:min-h-[300px]">
|
||||||
<Newsletter className="mr-0 lg:-ml-14" />
|
<Newsletter className="mr-0 sm:-ml-14" />
|
||||||
</div>
|
</div>
|
||||||
<Card>
|
<Card>
|
||||||
<Carousel {...BERITA} />
|
<Carousel {...BERITA} />
|
||||||
|
|||||||
25
app/root.tsx
25
app/root.tsx
@ -6,6 +6,7 @@ import {
|
|||||||
Outlet,
|
Outlet,
|
||||||
Scripts,
|
Scripts,
|
||||||
ScrollRestoration,
|
ScrollRestoration,
|
||||||
|
type ShouldRevalidateFunctionArgs,
|
||||||
} from 'react-router'
|
} from 'react-router'
|
||||||
|
|
||||||
import type { Route } from './+types/root'
|
import type { Route } from './+types/root'
|
||||||
@ -36,7 +37,17 @@ export const meta = ({ location }: Route.MetaArgs) => {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Layout({ children }: { children: ReactNode }) {
|
export const shouldRevalidate = ({
|
||||||
|
actionResult,
|
||||||
|
defaultShouldRevalidate,
|
||||||
|
}: ShouldRevalidateFunctionArgs) => {
|
||||||
|
if (actionResult?.success) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return defaultShouldRevalidate
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@ -57,11 +68,7 @@ export function Layout({ children }: { children: ReactNode }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function App() {
|
export const ErrorBoundary = ({ error }: Route.ErrorBoundaryProps) => {
|
||||||
return <Outlet />
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
|
|
||||||
let message = 'Oops!'
|
let message = 'Oops!'
|
||||||
let details = 'An unexpected error occurred.'
|
let details = 'An unexpected error occurred.'
|
||||||
let stack: string | undefined
|
let stack: string | undefined
|
||||||
@ -89,3 +96,9 @@ export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
|
|||||||
</main>
|
</main>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
return <Outlet />
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App
|
||||||
|
|||||||
22
app/routes/actions.news.logout.ts
Normal file
22
app/routes/actions.news.logout.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { data } from 'react-router'
|
||||||
|
|
||||||
|
import { setUserLogoutHeaders } from '~/libs/logout-header.server'
|
||||||
|
|
||||||
|
export const action = async () => {
|
||||||
|
try {
|
||||||
|
const responseHeaders = setUserLogoutHeaders()
|
||||||
|
|
||||||
|
return data(
|
||||||
|
{ success: true },
|
||||||
|
{ headers: responseHeaders, status: 200, statusText: 'OK' },
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
return data(
|
||||||
|
{
|
||||||
|
message: 'Something went wrong',
|
||||||
|
success: false,
|
||||||
|
},
|
||||||
|
{ status: 500 },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user