veza/veza-backend-api/internal/services/notification_service.go
senke cc2ebae4dc feat: Visual masterpiece - true light mode & premium UI
🎨 **True Light/Dark Mode**
- Implemented proper light mode with inverted color scheme
- Smooth theme transitions (0.3s ease)
- Light mode colors: white backgrounds, dark text, vibrant accents
- System theme detection with proper class application

🌈 **Enhanced Theme System**
- 4 color themes work in both light and dark modes
- Cyber (cyan/magenta), Ocean (blue/teal), Forest (green/lime), Sunset (orange/purple)
- Theme-specific glassmorphism effects
- Proper contrast in light mode

 **Premium Animations**
- Float, glow-pulse, slide-in, scale-in, rotate-in animations
- Smooth page transitions
- Hover effects with depth (lift, glow, scale)
- Micro-interactions on all interactive elements

🎯 **Visual Polish**
- Enhanced glassmorphism for light/dark modes
- Custom scrollbar with theme colors
- Beautiful text selection
- Focus indicators for accessibility
- Premium utility classes

🔧 **Technical Improvements**
- Updated UIStore to properly apply light/dark classes
- Added data-theme attribute for CSS targeting
- Smooth scroll behavior
- Optimized transitions

The app is now a visual masterpiece with perfect light/dark mode support!
2026-01-11 02:32:21 +01:00

182 lines
4.4 KiB
Go

package services
import (
"context"
"fmt"
"github.com/google/uuid"
"veza-backend-api/internal/database"
"go.uber.org/zap"
)
// NotificationService handles notification operations
type NotificationService struct {
db *database.Database
logger *zap.Logger
}
// Notification represents a notification
type Notification struct {
ID uuid.UUID `json:"id" db:"id"`
UserID uuid.UUID `json:"user_id" db:"user_id"`
Type string `json:"type" db:"type"`
Title string `json:"title" db:"title"`
Content string `json:"content" db:"content"`
Link string `json:"link" db:"link"`
Read bool `json:"read" db:"read"`
CreatedAt string `json:"created_at" db:"created_at"`
}
// NewNotificationService creates a new notification service
func NewNotificationService(db *database.Database, logger *zap.Logger) *NotificationService {
return &NotificationService{
db: db,
logger: logger,
}
}
// CreateNotification creates a new notification
func (ns *NotificationService) CreateNotification(userID uuid.UUID, notificationType, title, content, link string) error {
ctx := context.Background()
_, err := ns.db.ExecContext(ctx, `
INSERT INTO notifications (user_id, type, title, content, link)
VALUES ($1, $2, $3, $4, $5)
`, userID, notificationType, title, content, link)
if err != nil {
return fmt.Errorf("failed to create notification: %w", err)
}
return nil
}
// GetNotifications retrieves notifications for a user
func (ns *NotificationService) GetNotifications(userID uuid.UUID, unreadOnly bool) ([]Notification, error) {
ctx := context.Background()
query := `
SELECT id, user_id, type, title, content, link, read, created_at
FROM notifications
WHERE user_id = $1
`
args := []interface{}{userID}
if unreadOnly {
query += " AND read = FALSE"
}
query += " ORDER BY created_at DESC LIMIT 50"
rows, err := ns.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, fmt.Errorf("failed to get notifications: %w", err)
}
defer rows.Close()
var notifications []Notification
for rows.Next() {
var notification Notification
if err := rows.Scan(
&notification.ID,
&notification.UserID,
&notification.Type,
&notification.Title,
&notification.Content,
&notification.Link,
&notification.Read,
&notification.CreatedAt,
); err != nil {
continue
}
notifications = append(notifications, notification)
}
return notifications, nil
}
// MarkAsRead marks a notification as read
func (ns *NotificationService) MarkAsRead(userID uuid.UUID, notificationID uuid.UUID) error {
ctx := context.Background()
_, err := ns.db.ExecContext(ctx, `
UPDATE notifications
SET read = TRUE
WHERE id = $1 AND user_id = $2
`, notificationID, userID)
if err != nil {
return fmt.Errorf("failed to mark notification as read: %w", err)
}
return nil
}
// MarkAllAsRead marks all notifications as read for a user
func (ns *NotificationService) MarkAllAsRead(userID uuid.UUID) error {
ctx := context.Background()
_, err := ns.db.ExecContext(ctx, `
UPDATE notifications
SET read = TRUE
WHERE user_id = $1 AND read = FALSE
`, userID)
if err != nil {
return fmt.Errorf("failed to mark all notifications as read: %w", err)
}
return nil
}
// GetUnreadCount returns the count of unread notifications
func (ns *NotificationService) GetUnreadCount(userID uuid.UUID) (int, error) {
ctx := context.Background()
var count int
err := ns.db.QueryRowContext(ctx, `
SELECT COUNT(*)
FROM notifications
WHERE user_id = $1 AND read = FALSE
`, userID).Scan(&count)
if err != nil {
return 0, fmt.Errorf("failed to get unread count: %w", err)
}
return count, nil
}
// DeleteNotification deletes a notification
func (ns *NotificationService) DeleteNotification(userID uuid.UUID, notificationID uuid.UUID) error {
ctx := context.Background()
_, err := ns.db.ExecContext(ctx, `
DELETE FROM notifications
WHERE id = $1 AND user_id = $2
`, notificationID, userID)
if err != nil {
return fmt.Errorf("failed to delete notification: %w", err)
}
return nil
}
// DeleteAllNotifications deletes all notifications for a user
func (ns *NotificationService) DeleteAllNotifications(userID uuid.UUID) error {
ctx := context.Background()
_, err := ns.db.ExecContext(ctx, `
DELETE FROM notifications
WHERE user_id = $1
`, userID)
if err != nil {
return fmt.Errorf("failed to delete all notifications: %w", err)
}
return nil
}