Skip to main content

Overview

The notification system provides real-time alerts for important events in the Ai Studio application. Notifications are categorized by type (order, reservation, general) and stored locally with read/unread status tracking.

Notification Interface

types.ts
export interface Notification {
    id: string;
    message: string;
    type: 'order' | 'reservation' | 'general';
    relatedId?: string;
    createdAt: string;
    isRead: boolean;
}

Configuration Parameters

id
string
required
Unique identifier for the notificationAuto-generated in format: NOTIF-{timestamp}-{random}Example: "NOTIF-1709654321-xyz789"
message
string
required
The notification message to display to the userExample: "New order received from John Doe"
type
'order' | 'reservation' | 'general'
required
Notification category
  • order: Related to order events (new orders, status changes)
  • reservation: Related to reservation events (new bookings, cancellations)
  • general: System notifications and other events
ID of the related entity (order ID, reservation ID, etc.)Used to prevent duplicate notifications and link to source data.Example: "ORD-1709654321-abc123"
createdAt
string
required
ISO timestamp of when the notification was createdAuto-generated on creation.Example: "2026-03-10T15:30:00.000Z"
isRead
boolean
required
Whether the notification has been marked as readDefaults to false on creation.

Creating Notifications

Add a New Notification

Create a notification with automatic deduplication:
import { addNotification } from './services/notificationService';

const notification = addNotification({
  message: 'New order #1234 received',
  type: 'order',
  relatedId: 'ORD-1709654321-abc123'
});

if (notification) {
  console.log('Notification created:', notification.id);
} else {
  console.log('Duplicate notification prevented');
}
If a notification with the same relatedId already exists, addNotification() returns null to prevent duplicates.

Notification Examples

Order Notification:
addNotification({
  message: `Order #${orderId} is ready for pickup`,
  type: 'order',
  relatedId: orderId
});
Reservation Notification:
addNotification({
  message: `New reservation for ${customerName} at ${time}`,
  type: 'reservation',
  relatedId: reservationId
});
General Notification:
addNotification({
  message: 'System maintenance scheduled for tonight',
  type: 'general'
  // No relatedId for general notifications
});

Retrieving Notifications

Get All Notifications

Retrieve all notifications sorted by creation date (newest first):
import { getNotifications } from './services/notificationService';

const notifications = getNotifications();
console.log(`Total notifications: ${notifications.length}`);

notifications.forEach(notif => {
  console.log(`[${notif.type}] ${notif.message} - Read: ${notif.isRead}`);
});
The service automatically sorts notifications:
notificationService.ts
export const getNotifications = (): Notification[] => {
  try {
    const notificationsJson = localStorage.getItem(NOTIFICATIONS_STORAGE_KEY);
    const notifications = notificationsJson ? JSON.parse(notificationsJson) as Notification[] : [];
    return notifications.sort((a, b) => 
      new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
    );
  } catch (error) {
    console.error("Failed to parse notifications from localStorage", error);
    return [];
  }
};

Get Unread Count

Get the number of unread notifications:
import { getUnreadCount } from './services/notificationService';

const unreadCount = getUnreadCount();
console.log(`You have ${unreadCount} unread notifications`);

// Update UI badge
document.getElementById('notif-badge').textContent = unreadCount.toString();

Filter by Type

Filter notifications by category:
import { getNotifications } from './services/notificationService';

const allNotifications = getNotifications();

const orderNotifications = allNotifications.filter(n => n.type === 'order');
const reservationNotifications = allNotifications.filter(n => n.type === 'reservation');
const generalNotifications = allNotifications.filter(n => n.type === 'general');

console.log(`Orders: ${orderNotifications.length}`);
console.log(`Reservations: ${reservationNotifications.length}`);
console.log(`General: ${generalNotifications.length}`);

Managing Read Status

Mark Single Notification as Read

Mark a specific notification as read:
import { markAsRead } from './services/notificationService';

const notificationId = 'NOTIF-1709654321-xyz789';
markAsRead(notificationId);

console.log('Notification marked as read');

Mark All Notifications as Read

Mark all notifications as read at once:
import { markAllAsRead } from './services/notificationService';

markAllAsRead();
console.log('All notifications marked as read');
Useful when implementing a “Mark all as read” button:
function handleMarkAllRead() {
  markAllAsRead();
  
  // Refresh UI
  const unreadCount = getUnreadCount();
  updateNotificationBadge(unreadCount);
}

Deleting Notifications

Delete Single Notification

Remove a specific notification:
import { deleteNotification } from './services/notificationService';

const notificationId = 'NOTIF-1709654321-xyz789';
deleteNotification(notificationId);

console.log('Notification deleted');

Clear All Notifications

Delete all notifications:
import { clearAllNotifications } from './services/notificationService';

clearAllNotifications();
console.log('All notifications cleared');
clearAllNotifications() permanently removes all notifications. This action cannot be undone.

Notification Lifecycle

Automatic Management

The notification system includes automatic features: Duplicate Prevention:
notificationService.ts
export const addNotification = (notificationData: Omit<Notification, 'id' | 'createdAt' | 'isRead'>): Notification | null => {
  const existingNotifications = getNotifications();

  // Prevent duplicate notifications for the same event
  if (notificationData.relatedId && existingNotifications.some(n => n.relatedId === notificationData.relatedId)) {
    return null;
  }
  
  // ... create notification
};
Maximum Limit (50 notifications):
notificationService.ts
const updatedNotifications = [newNotification, ...existingNotifications].slice(0, 50);
persistNotifications(updatedNotifications);
Older notifications are automatically removed when the limit is reached.

Storage Details

Notifications are stored in browser localStorage:
const NOTIFICATIONS_STORAGE_KEY = 'pizzeria-notifications';

Persistence

All notification operations persist to localStorage:
notificationService.ts
const persistNotifications = (notifications: Notification[]): void => {
  try {
    localStorage.setItem(NOTIFICATIONS_STORAGE_KEY, JSON.stringify(notifications));
  } catch (error) {
    console.error("Failed to save notifications to localStorage", error);
  }
};
Notifications are stored locally and will be cleared if the user clears browser data. Consider implementing server-side storage for critical notifications.

Real-Time Integration

Integrate notifications with order and reservation systems:

Order Status Changes

import { addNotification } from './services/notificationService';
import type { Order } from './types';

function onOrderStatusChange(order: Order) {
  const statusMessages = {
    'Confirmado': `Order #${order.id} confirmed`,
    'En Preparación': `Order #${order.id} is being prepared`,
    'Listo para Retirar/Entregar': `Order #${order.id} is ready`,
    'Completado (Entregado)': `Order #${order.id} completed`,
  };
  
  const message = statusMessages[order.status];
  if (message) {
    addNotification({
      message,
      type: 'order',
      relatedId: order.id
    });
  }
}

New Reservations

import { addNotification } from './services/notificationService';
import type { Reservation } from './types';

function onNewReservation(reservation: Reservation) {
  addNotification({
    message: `New reservation: ${reservation.customerName} for ${reservation.guests} guests`,
    type: 'reservation',
    relatedId: reservation.id
  });
}

UI Implementation Example

Example notification list component:
import { getNotifications, markAsRead, deleteNotification } from './services/notificationService';
import { useEffect, useState } from 'react';

function NotificationList() {
  const [notifications, setNotifications] = useState(getNotifications());
  
  useEffect(() => {
    // Refresh every 5 seconds
    const interval = setInterval(() => {
      setNotifications(getNotifications());
    }, 5000);
    
    return () => clearInterval(interval);
  }, []);
  
  const handleRead = (id: string) => {
    markAsRead(id);
    setNotifications(getNotifications());
  };
  
  const handleDelete = (id: string) => {
    deleteNotification(id);
    setNotifications(getNotifications());
  };
  
  return (
    <div>
      {notifications.map(notif => (
        <div key={notif.id} className={notif.isRead ? 'read' : 'unread'}>
          <span className={`badge badge-${notif.type}`}>{notif.type}</span>
          <p>{notif.message}</p>
          <small>{new Date(notif.createdAt).toLocaleString()}</small>
          {!notif.isRead && (
            <button onClick={() => handleRead(notif.id)}>Mark Read</button>
          )}
          <button onClick={() => handleDelete(notif.id)}>Delete</button>
        </div>
      ))}
    </div>
  );
}

Best Practices

Craft notification messages that provide clear, actionable information:
// Good
addNotification({
  message: 'Order #1234 from Table 5 is ready to serve',
  type: 'order',
  relatedId: orderId
});

// Avoid
addNotification({
  message: 'Order ready',
  type: 'order'
});
This enables duplicate prevention and linking:
addNotification({
  message: `Reservation confirmed for ${name}`,
  type: 'reservation',
  relatedId: reservation.id // Always include for tracking
});
Enhance user experience with audio or visual cues:
function notifyWithSound(notificationData) {
  const notification = addNotification(notificationData);
  
  if (notification && notification.type === 'order') {
    // Play sound for important notifications
    const audio = new Audio('/notification-sound.mp3');
    audio.play();
  }
  
  return notification;
}
While the system limits to 50 notifications, implement custom cleanup:
function cleanupOldNotifications(daysToKeep: number = 7) {
  const notifications = getNotifications();
  const cutoffDate = new Date();
  cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);
  
  const recentNotifications = notifications.filter(n => 
    new Date(n.createdAt) > cutoffDate
  );
  
  // Save filtered list
  localStorage.setItem('pizzeria-notifications', JSON.stringify(recentNotifications));
}

Error Handling

The notification service includes built-in error handling:
// Safe retrieval with fallback
const notifications = getNotifications(); // Returns [] on error

// Check for null on add (duplicate prevention)
const notification = addNotification({ ... });
if (!notification) {
  console.log('Notification was not created (duplicate)');
}
All localStorage operations are wrapped in try-catch blocks to prevent crashes from quota exceeded or other storage errors.

Build docs developers (and LLMs) love