Чат по заказу¶
Каждый заказ имеет чат (chats + messages) между клиентом и менеджером посредника. Чат используется только для коммуникации и уведомлений — приём оплаты в чат намеренно не вынесен.
Возможности¶
- Realtime через Laravel Reverb (приватный канал
order.{orderId}, авторизация по обоим guard'ам). СобытияOrderMessageSent/OrderMessageUpdated(broadcastAsmessage/message.updated). - Реакции (👍 ❤️ ✅ 😂) и редактирование своих несистемных сообщений — в
messages.meta(reactions,edited_at). - Ответ на сообщение (цитата
reply_to), прикрепление файлов (meta.file, дискpublic, скрепка 📎), смайл-пикер, поиск по чату (клиент-сайд). - Собеседники + онлайн-индикатор (по
last_seen_at< 5 мин). - «Сообщение не требует ответа» —
chats.client_can_reply=false; у клиента форма заменяется на «Продолжить диалог». - Автоподпись посредника (
agents.chat_signature). - Системные сообщения при действиях (выставление счёта, подтверждение оплаты, создание отгрузки, оплата доставки, приёмка).
Внутренняя переписка сотрудников¶
В композере посредника — селектор получателя: «Все (клиент)» или «{сотрудник} — внутр.». Выбор сотрудника → meta.internal=true + to_staff_id/to_name. Сообщение видно в общем чате (плашка «внутр. → Имя»), но клиенту не считается новым.
Непрочитанные¶
Метки прочтения по сторонам (chats.agent_read_at / client_read_at). Счётчик «Новые сообщения» в сайдбарах, фильтр заказов ?unread=1, бейдж у номера заказа. Внутренние сообщения исключаются из счётчика клиента.
Чат в карточке заказа
Чат вынесен в правый сайдбар карточки и свёрнут по умолчанию. Непрочитанные сбрасываются только при разворачивании (POST orders.read). При свёрнутом чате новое сообщение клиента растит бейдж (через Echo).
Автоперевод¶
Google Cloud Translation v2 (TranslateService / ChatService::translateChat). Чек-бокс «Автоперевод» (localStorage) → перевод кэшируется в messages.meta.tr[target]. Под оригиналом показывается «↳ перевод». Поскольку посредник может быть китайцем, а клиент русским — перевод работает в обе стороны.
Сервис¶
ChatService — единая точка: chatFor (get-or-create), post, system, edit, react, markRead, unreadTotalAgent/Client, unreadByOrder, participants, setClientCanReply, translateChat, wire (единый формат сообщения для фронта).
Грабли таймзоны
created_at сообщений теперь явно проставляется now() в ChatService::post — раньше бралось из DB useCurrent (таймзона MySQL = МСК), что ломало сброс непрочитанных (app TZ = UTC).