Matt 683a65c1fd
All checks were successful
Build and Push Docker Images / docker (push) Successful in 2m15s
Implement Modern Maritime admin panel design with Monaco background
🎨 Complete UI redesign of admin panel with professional color scheme:

## New Modern Maritime Color Palette
- Deep Sea Blue (#1D2939) - Sidebar background
- Sail White (#F8F9FA) - Main background
- Maritime Teal (#008B8B) - Primary accent
- Sea Green (#1E8449) - Success/environmental theme
- Muted Gold (#D68910) - Revenue highlights
- Royal Purple (#884EA0) - Brand accent
- Off-White (#EAECEF) - Text on dark backgrounds

## Admin Panel Features
-  JWT-based authentication system
-  Protected routes with middleware
-  Elegant sidebar navigation with Puffin logo
-  Dashboard with stat cards (Orders, CO₂, Revenue, Fulfillment)
-  Monaco harbor image background on login page
-  Responsive glassmorphism design
-  WCAG AA contrast compliance

## New Files
- app/admin/ - Admin pages (login, dashboard, orders)
- app/api/admin/ - Auth API routes (login, logout, verify)
- components/admin/ - AdminSidebar component
- lib/auth.ts - JWT authentication utilities
- public/monaco_high_res.jpg - Luxury background image

## Updated
- tailwind.config.js - Custom maritime color palette
- package.json - Added jsonwebtoken dependency
- app/layout.tsx - RootLayoutClient integration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 09:35:43 +01:00

60 lines
1.4 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { verifyCredentials, generateToken } from '@/lib/admin/auth';
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { username, password } = body;
// Validate input
if (!username || !password) {
return NextResponse.json(
{ error: 'Username and password are required' },
{ status: 400 }
);
}
// Verify credentials
const isValid = verifyCredentials(username, password);
if (!isValid) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
);
}
// Generate JWT token
const token = generateToken({
username,
isAdmin: true,
});
// Create response with token in cookie
const response = NextResponse.json({
success: true,
user: {
username,
isAdmin: true,
},
});
// Set HTTP-only cookie with JWT token
response.cookies.set('admin-token', token, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: 60 * 60 * 24, // 24 hours
path: '/',
});
return response;
} catch (error) {
console.error('Login error:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}