- `
+ `Nytt meddelande: ${conversation.subject}`,
+ sender.full_name,
+ sender.email,
+ sender.mobile,
+ sender.personnummer,
+ content,
+ if (!user) {
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ }
+
+ const { id } = await params;
+
+ const [convRows] = await pool.query(
+ `SELECT * FROM conversations WHERE id = ?`,
+ [id]
);
+
+ if (convRows.length === 0) {
+ return NextResponse.json({ error: 'Conversation not found' }, { status: 404 });
+ }
+
+ const conversation = convRows[0];
+
+ // Only admin can delete completely, customers can only delete their own
+ if (user.role !== 'admin' && conversation.user_id !== user.userId) {
+ return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
+ }
+
+ // Delete the conversation (cascades to messages)
+ await pool.query(`DELETE FROM conversations WHERE id = ?`, [id]);
+
+ return NextResponse.json({ success: true, message: 'Conversation deleted' });
+ } catch (error) {
+ console.error('Error deleting conversation:', error);
+ return NextResponse.json({ error: 'Server error' }, { status: 500 });
}
}
- }
- return NextResponse.json({ success: true });
- } catch (error) {
- console.error('Error sending message:', error);
- return NextResponse.json({ error: 'Server error' }, { status: 500 });
- }
-}
+ // PATCH /api/conversations/[id] - Resolve conversation (admin only)
+ export async function PATCH(request: NextRequest, { params }: RouteParams) {
+ try {
+ const user = getUserFromRequest(request);
+ if (!user) {
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
+ }
-// DELETE /api/conversations/[id] - Delete conversation
-export async function DELETE(request: NextRequest, { params }: RouteParams) {
- try {
- const user = getUserFromRequest(request);
- if (!user) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
- }
+ if (user.role !== 'admin') {
+ return NextResponse.json({ error: 'Admin only' }, { status: 403 });
+ }
- const { id } = await params;
+ const { id } = await params;
+ const body = await request.json();
+ const { action } = body;
- const [convRows] = await pool.query(
- `SELECT * FROM conversations WHERE id = ?`,
- [id]
- );
-
- if (convRows.length === 0) {
- return NextResponse.json({ error: 'Conversation not found' }, { status: 404 });
- }
-
- const conversation = convRows[0];
-
- // Only admin can delete completely, customers can only delete their own
- if (user.role !== 'admin' && conversation.user_id !== user.userId) {
- return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
- }
-
- // Delete the conversation (cascades to messages)
- await pool.query(`DELETE FROM conversations WHERE id = ?`, [id]);
-
- return NextResponse.json({ success: true, message: 'Conversation deleted' });
- } catch (error) {
- console.error('Error deleting conversation:', error);
- return NextResponse.json({ error: 'Server error' }, { status: 500 });
- }
-}
-
-// PATCH /api/conversations/[id] - Resolve conversation (admin only)
-export async function PATCH(request: NextRequest, { params }: RouteParams) {
- try {
- const user = getUserFromRequest(request);
- if (!user) {
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
- }
-
- if (user.role !== 'admin') {
- return NextResponse.json({ error: 'Admin only' }, { status: 403 });
- }
-
- const { id } = await params;
- const body = await request.json();
- const { action } = body;
-
- if (action === 'resolve') {
- // Get conversation info for email
- const [convRows] = await pool.query(
- `SELECT c.*, u.email as user_email, u.full_name as user_name
+ if (action === 'resolve') {
+ // Get conversation info for email
+ const [convRows] = await pool.query(
+ `SELECT c.*, u.email as user_email, u.full_name as user_name
FROM conversations c
JOIN users u ON c.user_id = u.id
WHERE c.id = ?`,
- [id]
- );
+ [id]
+ );
- if (convRows.length === 0) {
- return NextResponse.json({ error: 'Conversation not found' }, { status: 404 });
- }
+ if (convRows.length === 0) {
+ return NextResponse.json({ error: 'Conversation not found' }, { status: 404 });
+ }
- const conversation = convRows[0];
+ const conversation = convRows[0];
- // Update status to closed
- await pool.query(
- `UPDATE conversations SET status = 'closed' WHERE id = ?`,
- [id]
- );
+ // Update status to closed
+ await pool.query(
+ `UPDATE conversations SET status = 'closed' WHERE id = ?`,
+ [id]
+ );
- // Send resolution email to customer
- await sendEmail(
- conversation.user_email,
- `Ärende löst: ${conversation.subject}`,
- `
+ // Send resolution email to customer
+ await sendEmail(
+ conversation.user_email,
+ `Ärende löst: ${conversation.subject}`,
+ `
Ditt ärende har markerats som löst
Hej ${conversation.user_name || 'kund'},
Vi har markerat ditt ärende "${conversation.subject}" som löst.
Om du fortfarande har frågor eller känner att ärendet inte är helt löst, tveka inte att kontakta oss igen.
Med vänliga hälsningar, Nordic Storium Support
`
- );
+ );
- return NextResponse.json({ success: true, message: 'Conversation resolved' });
- }
+ return NextResponse.json({ success: true, message: 'Conversation resolved' });
+ }
- return NextResponse.json({ error: 'Invalid action' }, { status: 400 });
- } catch (error) {
- console.error('Error resolving conversation:', error);
- return NextResponse.json({ error: 'Server error' }, { status: 500 });
- }
-}
+ return NextResponse.json({ error: 'Invalid action' }, { status: 400 });
+ } catch (error) {
+ console.error('Error resolving conversation:', error);
+ return NextResponse.json({ error: 'Server error' }, { status: 500 });
+ }
+ }
diff --git a/src/app/messages/page.tsx b/src/app/messages/page.tsx
index ffbb905..291665d 100644
--- a/src/app/messages/page.tsx
+++ b/src/app/messages/page.tsx
@@ -3,6 +3,7 @@
import { useState, useEffect, useRef, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import { useAuth } from '@/context/AuthContext';
+import { useNotification } from '@/context/NotificationContext';
import { useToast } from '@/components/Toast';
import { Loader2, Send, MessageCircle, Plus, Trash2, CheckCircle, AlertTriangle } from 'lucide-react';
import '@/styles/Messages.css';
@@ -35,6 +36,7 @@ export default function MessagesPage() {
const { user, loading: authLoading } = useAuth();
const router = useRouter();
const { showToast } = useToast();
+ const { refreshUnreadCount } = useNotification();
const [conversations, setConversations] = useState([]);
const [activeConversation, setActiveConversation] = useState(null);
@@ -102,6 +104,8 @@ export default function MessagesPage() {
setConversations(prev => prev.map(c =>
c.id === convId ? { ...c, unread_count: 0 } : c
));
+ // Refresh global navbar count
+ refreshUnreadCount();
}
}
} catch (err) {
diff --git a/src/components/CookieConsentModal.tsx b/src/components/CookieConsentModal.tsx
index 8ab05fd..52f2463 100644
--- a/src/components/CookieConsentModal.tsx
+++ b/src/components/CookieConsentModal.tsx
@@ -118,7 +118,7 @@ export default function CookieConsentModal() {
Vi värdesätter transparens. Genom att klicka på "Godkänn alla" samtycker du till användningen av alla cookies. Du kan när som helst ändra dina val eller återkalla ditt samtycke under "Anpassa" eller via länken i sidfoten.
- Personuppgiftsansvarig: Nordic Storium (Org.nr 559287-3612).
+ Personuppgiftsansvarig: Nordic Storium
Läs mer om dina rättigheter i vår Integritetspolicy och Köpvillkor.
diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx
index aa4e404..dc59e98 100644
--- a/src/components/Navbar.tsx
+++ b/src/components/Navbar.tsx
@@ -8,6 +8,7 @@ import { User, MessageCircle } from "lucide-react";
import logo from "../assets/logo-main.png";
import "../styles/components/Navbar.css";
import { useAuth } from "../context/AuthContext";
+import { useNotification } from "../context/NotificationContext";
import NavbarSearch from "./NavbarSearch";
@@ -42,7 +43,7 @@ export default function Navbar() {