Реализация центра уведомлений (Notification Center) на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация центра уведомлений (Notification Center) на сайте
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Реализация центра уведомлений

Центр уведомлений — компонент, показывающий историю уведомлений пользователя с отметкой прочитанных. Обновляется в реальном времени через WebSocket без перезагрузки страницы.

Структура БД

CREATE TABLE notifications (
    id         UUID         PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id    INTEGER      NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    type       VARCHAR(100) NOT NULL,
    icon       VARCHAR(50),
    title      VARCHAR(255),
    body       TEXT,
    url        VARCHAR(500),
    data       JSONB        NOT NULL DEFAULT '{}',
    read_at    TIMESTAMPTZ,
    created_at TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

CREATE INDEX ON notifications(user_id, read_at, created_at DESC);

Laravel: API эндпоинты

class NotificationController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $notifications = auth()->user()->notifications()
            ->latest()
            ->limit(50)
            ->get();

        return response()->json([
            'notifications' => NotificationResource::collection($notifications),
            'unread_count'  => $notifications->whereNull('read_at')->count(),
        ]);
    }

    public function markRead(Request $request): JsonResponse
    {
        $query = auth()->user()->notifications()->whereNull('read_at');

        if ($request->id) {
            $query->where('id', $request->id);
        }

        $query->update(['read_at' => now()]);

        return response()->json(['success' => true]);
    }

    // Laravel Broadcasting: отправить в реальном времени
    public function send(User $user, array $data): void
    {
        $notification = $user->notifications()->create($data);
        broadcast(new NotificationCreatedEvent($user->id, $notification))->toOthers();
    }
}

Laravel Echo + WebSocket

// hooks/useNotifications.ts
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

window.Pusher = Pusher;
const echo = new Echo({
  broadcaster: 'pusher',
  key: import.meta.env.VITE_PUSHER_KEY,
  cluster: import.meta.env.VITE_PUSHER_CLUSTER,
  forceTLS: true,
});

export function useNotifications(userId: number) {
  const [notifications, setNotifications] = useState<Notification[]>([]);
  const [unreadCount, setUnreadCount] = useState(0);

  useEffect(() => {
    // Загрузить начальные данные
    api.get('/api/notifications').then(({ data }) => {
      setNotifications(data.notifications);
      setUnreadCount(data.unread_count);
    });

    // Подписаться на новые
    const channel = echo.private(`notifications.${userId}`)
      .listen('.NotificationCreated', (event: { notification: Notification }) => {
        setNotifications(prev => [event.notification, ...prev].slice(0, 50));
        setUnreadCount(c => c + 1);

        // Браузерное уведомление
        if (Notification.permission === 'granted') {
          new Notification(event.notification.title ?? 'Новое уведомление', {
            body: event.notification.body ?? undefined,
            icon: '/icon-192.png',
          });
        }
      });

    return () => channel.stopListening('.NotificationCreated');
  }, [userId]);

  const markAllRead = async () => {
    await api.post('/api/notifications/mark-read');
    setNotifications(prev => prev.map(n => ({ ...n, read_at: new Date().toISOString() })));
    setUnreadCount(0);
  };

  return { notifications, unreadCount, markAllRead };
}

React: UI компонент

function NotificationBell({ userId }: { userId: number }) {
  const { notifications, unreadCount, markAllRead } = useNotifications(userId);
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="notification-bell">
      <button
        onClick={() => setIsOpen(!isOpen)}
        aria-label={`${unreadCount} непрочитанных уведомлений`}
        aria-expanded={isOpen}
        aria-haspopup="true"
      >
        🔔
        {unreadCount > 0 && (
          <span className="badge" aria-hidden>{unreadCount > 99 ? '99+' : unreadCount}</span>
        )}
      </button>

      {isOpen && (
        <div className="notification-panel" role="dialog" aria-label="Уведомления">
          <header>
            <h2>Уведомления</h2>
            {unreadCount > 0 && (
              <button onClick={markAllRead}>Прочитать все</button>
            )}
          </header>

          <ul>
            {notifications.length === 0 && <li className="empty">Нет уведомлений</li>}
            {notifications.map(notification => (
              <li key={notification.id} className={notification.read_at ? 'read' : 'unread'}>
                {notification.url ? (
                  <a href={notification.url}>{notification.title}</a>
                ) : (
                  <span>{notification.title}</span>
                )}
                <time dateTime={notification.created_at}>{timeAgo(notification.created_at)}</time>
                {notification.body && <p>{notification.body}</p>}
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

Срок реализации

Центр уведомлений с WebSocket (Laravel Echo + Pusher), API и React UI: 2–3 дня. Self-hosted (Soketi или Laravel Reverb вместо Pusher): +1 день.