diff --git a/.env.development b/.env.development index ca8a0fb..4a2c8e5 100644 --- a/.env.development +++ b/.env.development @@ -2,11 +2,11 @@ NODE_ENV=development # API Configuration -NEXT_PUBLIC_API_URL=https://5wmfjjzm0i.execute-api.eu-central-1.amazonaws.com/dev +NEXT_PUBLIC_API_URL=https://api.filamenteka.rs/api -# AWS Configuration -AWS_REGION=eu-central-1 -DYNAMODB_TABLE_NAME=filamenteka-filaments-dev +# AWS Configuration (for reference - no longer used) +# AWS_REGION=eu-central-1 +# DYNAMODB_TABLE_NAME=filamenteka-filaments-dev # Admin credentials (development) # Username: admin diff --git a/.env.production b/.env.production index 3f6a2e3..5f36e9c 100644 --- a/.env.production +++ b/.env.production @@ -2,10 +2,8 @@ NODE_ENV=production # API Configuration -NEXT_PUBLIC_API_URL=https://5wmfjjzm0i.execute-api.eu-central-1.amazonaws.com/production +NEXT_PUBLIC_API_URL=https://api.filamenteka.rs/api -# AWS Configuration -AWS_REGION=eu-central-1 -DYNAMODB_TABLE_NAME=filamenteka-filaments - -# Admin credentials are stored in AWS Secrets Manager in production \ No newline at end of file +# AWS Configuration (for reference - no longer used) +# AWS_REGION=eu-central-1 +# DYNAMODB_TABLE_NAME=filamenteka-filaments \ No newline at end of file diff --git a/api/server.js b/api/server.js index 9d9a73a..f2cb9b1 100644 --- a/api/server.js +++ b/api/server.js @@ -19,10 +19,15 @@ app.use(cors({ origin: true, // Allow all origins in development credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], - allowedHeaders: ['Content-Type', 'Authorization'] + allowedHeaders: ['Content-Type', 'Authorization'], + exposedHeaders: ['Content-Length', 'Content-Type'], + maxAge: 86400 })); app.use(express.json()); +// Handle preflight requests +app.options('*', cors()); + // Health check route app.get('/', (req, res) => { res.json({ status: 'ok', service: 'Filamenteka API' }); @@ -34,11 +39,14 @@ const authenticateToken = (req, res, next) => { const token = authHeader && authHeader.split(' ')[1]; if (!token) { - return res.sendStatus(401); + return res.status(401).json({ error: 'Unauthorized' }); } jwt.verify(token, process.env.JWT_SECRET || 'your-secret-key', (err, user) => { - if (err) return res.sendStatus(403); + if (err) { + console.error('JWT verification error:', err); + return res.status(403).json({ error: 'Invalid token' }); + } req.user = user; next(); }); @@ -111,8 +119,9 @@ app.delete('/api/colors/:id', authenticateToken, async (req, res) => { } }); -// Filaments endpoints +// Filaments endpoints (PUBLIC - no auth required) app.get('/api/filaments', async (req, res) => { + console.log('Filaments request headers:', req.headers); try { const result = await pool.query('SELECT * FROM filaments ORDER BY created_at DESC'); res.json(result.rows); diff --git a/app/page.tsx b/app/page.tsx index 667740e..0bc0b4b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -42,9 +42,19 @@ export default function Home() { const filaments = await filamentService.getAll(); setFilaments(filaments); - } catch (err) { + } catch (err: any) { console.error('API Error:', err); - setError(err instanceof Error ? err.message : 'Greška pri učitavanju filamenata'); + + // More descriptive error messages + if (err.code === 'ERR_NETWORK') { + setError('Network Error - Unable to connect to API'); + } else if (err.response) { + setError(`Server error: ${err.response.status} - ${err.response.statusText}`); + } else if (err.request) { + setError('No response from server - check if API is running'); + } else { + setError(err.message || 'Greška pri učitavanju filamenata'); + } } finally { setLoading(false); } @@ -91,7 +101,7 @@ export default function Home() { className="p-2 bg-white/50 dark:bg-gray-700/50 backdrop-blur text-gray-800 dark:text-gray-200 rounded-full hover:bg-white/80 dark:hover:bg-gray-600/80 transition-all duration-200 hover:scale-110 shadow-md ml-2" title={darkMode ? 'Svetla tema' : 'Tamna tema'} > - {darkMode ? 'Svetla' : 'Tamna'} + {darkMode ? '☀️' : '🌙'} )} diff --git a/app/upadaj/colors/page.tsx b/app/upadaj/colors/page.tsx index c9ba2c2..84ffae8 100644 --- a/app/upadaj/colors/page.tsx +++ b/app/upadaj/colors/page.tsx @@ -2,8 +2,8 @@ import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; -import { colorService } from '../../../src/services/api'; -import '../../../src/styles/select.css'; +import { colorService } from '@/src/services/api'; +import '@/src/styles/select.css'; interface Color { id: string; @@ -170,7 +170,7 @@ export default function ColorsManagement() { className="px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 rounded hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors" title={darkMode ? 'Svetla tema' : 'Tamna tema'} > - {darkMode ? 'Svetla' : 'Tamna'} + {darkMode ? '☀️' : '🌙'} )} )}