source-code/
portofolio-neo-gruv
Public
codeCodeinfoIssues 0call_splitPull Requestsplay_circleActions
portofolio-neo-gruv/src/app/actions/auth.ts
typescript54 lines1.4 KB
"use server";

import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

export async function loginAction(prevState: { error: string } | null, formData: FormData) {
  const email = formData.get('email');
  const password = formData.get('password');

  if (!email || !password) {
    return { error: 'Email and password are required' };
  }

  try {
    const baseUrl = process.env.API_URL || process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
    const res = await fetch(`${baseUrl}/auth/login`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ email, password }),
    });

    if (!res.ok) {
      return { error: 'Invalid credentials' };
    }

    const data = await res.json();
    const token = data.access_token;

    // Set HTTP-Only cookie
    const cookieStore = await cookies();
    cookieStore.set('jwt_token', token, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
      maxAge: 60 * 60 * 24 * 7, // 1 week
    });

  } catch (error) {
    return { error: 'Failed to connect to authentication server' };
  }

  // Redirect must be called outside of try/catch
  redirect('/dashboard');
}

export async function logoutAction() {
  const cookieStore = await cookies();
  cookieStore.delete('jwt_token');
  redirect('/nre-masuk');
}

About

Custom portfolio frontend designed using retro Neo-Brutalist styling. Features server-rendered pages, persistent codebase layout, interactive file explorer tree, and Shiki code syntax highlighting.

TypeScriptNext.jsReact 19Tailwind CSSShiki

Contributors

1