コンテンツにスキップ

検索はプロダクションビルドでのみ利用可能です。 ローカルでテストするには、サイトをビルドしてプレビューしてください。

チャットルーム

チャットルームは店舗と顧客の1対1コミュニケーションの単位です。


フィールド説明
idUUID(内部 PK)
roomId{shopId}:{contactId} 形式のユニークキー
shopId店舗 ID
contactId連絡先 ID
lastMessage最新メッセージのプレビューテキスト
lastMessageAt最新メッセージの送信日時
lastUserMessageAt顧客からの最新メッセージ日時

ルーム作成は Upsert(存在すれば返却、なければ作成)で行います。

// roomId の生成
const roomId = `${shopId}:${contactId}`;
// DB への Upsert
await db
.insert(chatRoom)
.values({ id: uuid(), shopId, contactId, roomId })
.onConflictDoNothing({ target: chatRoom.roomId });
// 作成されたかを確認
const room = await db.query.chatRoom.findFirst({
where: { roomId }
});
トリガー処理
Counter で連絡先のチャットタブを開くcreateChatRoom({ shopId, contactId })
purelovers からのメッセージ送信initChatRoom({ shopId, contactId })
一括配信の送信対象連絡先のルームが自動作成

店舗スタッフは 顧客からメッセージが来たルーム のみ表示されます。

WHERE shopId = {shopId}
AND lastUserMessageAt IS NOT NULL
ORDER BY lastUserMessageAt DESC NULLS LAST

これにより、店舗側から一方的にメッセージを送っただけのルームは一覧に表示されません。

顧客は 何らかのメッセージがあるルーム が表示されます。

WHERE contactId = {contactId}
AND lastMessage IS NOT NULL
ORDER BY lastMessageAt DESC NULLS LAST

ルーム一覧はカーソルベースのページネーションを使用します。

// ソートキー: (lastMessageAt, createdAt, id)
// カーソル: 前回最後のルーム ID
const cursor = await db.query.chatRoom.findFirst({ where: { id: cursorId } });
// カーソル以降のレコードを取得
WHERE (lastMessageAt, createdAt, id) < (cursor.lastMessageAt, cursor.createdAt, cursor.id)
LIMIT {limit + 1} // hasMore 判定用に +1

ルーム一覧には以下の情報が付加されます。

情報取得方法
連絡先名chatRoom.contact リレーション
未読数fetchUnreadCounts() で一括取得
ブロック状態contactChatNg テーブルから判定
アバター連絡先の image フィールド

const room = await db.query.chatRoom.findFirst({
where: { id: roomId },
with: {
contact: {
with: {
purelovers: true,
chatNg: true
}
},
shop: {
with: {
purelovers: true
}
}
}
});
NGタイプ制限内容
SHOP_NG店舗によるブロック。双方向送信不可
USER_NG運営によるブロック。顧客→店舗の送信不可
NO_PURELOVERS_USERpurelovers 未連携。双方向送信不可

isBlocked フラグがルーム詳細に含まれ、UI でメッセージ入力を無効化します。


Fizz RPC: deleteChatRoom({ roomId })
Vintage RPC: deleteChatRoom({ roomId })

ルーム削除は物理削除です。関連するメッセージ、既読状態、添付ファイルもカスケードで削除されます。


┌─────────────────────────────────┐
│ チャット │
├──────────┬──────────────────────┤
│ ルーム一覧 │ メッセージ表示 │
│ │ │
│ [顧客A] │ メッセージ... │
│ [顧客B] │ メッセージ... │
│ [顧客C] │ │
│ │ ────────────── │
│ │ [メッセージ入力] │
├──────────┴──────────────────────┤
│ ボトムナビ │
└─────────────────────────────────┘
  • モバイル: ルーム一覧とメッセージ表示が画面遷移で切り替わる
  • デスクトップ: 2カラムレイアウトで同時表示