はじめに
ポートフォリオ制作やっと一旦製作終えました!
今回は通知の未読カウントとDMの未読カウントを実装しました!
未読がある場合はアイコンバッチがつくようにしています
アウトプットとしてまとめます
※旅行やデートのプランを共有するアプリなので、
投稿機能はPostではなくPlanを使用しています!
通知機能の実装方法については、下記に記載しています
完成物
コントローラー
どの画面でもバッチをつけるために、application_controller.rbに記述します
class ApplicationController < ActionController::Base
before_action :set_unread_notifications_count
before_action :set_unread_chats_count
private
def set_unread_notifications_count
@unread_notifications_count = user_signed_in? ? current_user.notifications.where(read: false).count : 0
end
def set_unread_chats_count
if user_signed_in?
# current_userが参加している全てのルームを取得
room_ids = current_user.user_rooms.pluck(:room_id)
# ルーム内でcurrent_userが送信者ではない、未読のチャットをカウント
@unread_chats_count = Chat.where(room_id: room_ids, read: false).where.not(user_id: current_user.id).count
else
@unread_chats_count = 0
end
end
end
def set_unread_notifications_count
@unread_notifications_count = user_signed_in? ? current_user.notifications.where(read: false).count : 0
end
ユーザーがログインしている場合に、current_userの未読通知数を取得
ログインしていない時は0にする
def set_unread_chats_count
if user_signed_in?
# current_userが参加している全てのルームを取得
room_ids = current_user.user_rooms.pluck(:room_id)
# ルーム内でcurrent_userが送信者ではない、未読のチャットをカウント
@unread_chats_count = Chat.where(room_id: room_ids, read: false).where.not(user_id: current_user.id).count
else
@unread_chats_count = 0
end
end
チャット機能の実装方法は様々な方法があるため、実装方法によって変更してください
今回はuser_roomからroom_idを取得して、未読がどのルームで発生しているかを取得しています
チャットルーム一覧にも未読バッチをつけるためchats_controller.rbにも記述します
class Public::ChatsController < ApplicationController
# チャットルーム一覧
def index
@user_rooms = current_user.rooms.includes(:users).map do |room|
other_user = room.users.where.not(id: current_user.id).first
unread_chats_count = Chat.where(room_id: room.id, read: false).where.not(user_id: current_user.id).count
{ room: room, other_user: other_user, unread_chats_count: unread_chats_count }
end
end
end
ビュー
フッター
<li class="nav-item mx-3" style="position: relative;">
<%= link_to notifications_path, class: "menu-icon" do %>
<i class="fa-solid fa-bell fa-xl" style="color: #FFD43B;"></i>
<p class="text-center mt-3" style="color: #FFD43B; font-size: 10px;">通知</p>
<% if @unread_notifications_count.to_i > 0 %>
<span class="badge" style="position: absolute; top: -20px; right: -8px; background-color: red; color: #FFD43B; border-radius: 50%; padding: 2px 5px; font-size: 12px;">
<%= @unread_notifications_count %>
</span>
<% end %>
<% end %>
</li>
<li class="nav-item mx-3" style="position: relative;">
<%= link_to chats_path, class: "menu-icon" do %>
<i class="fa-solid fa-envelope fa-xl" style="color: #FFD43B;"></i>
<p class="text-center mt-3" style="color: #FFD43B; font-size: 10px;">DM</p>
<% if @unread_chats_count.to_i > 0 %>
<span class="badge" style="position: absolute; top: -20px; right: -8px; background-color: red; color: #FFD43B; border-radius: 50%; padding: 2px 5px; font-size: 12px;">
<%= @unread_chats_count %>
</span>
<% end %>
<% end %>
</li>
親要素である<li>
にposition: relative
を付与することで、
未読バッチの場所を通知ボタンから設定することができます
position: absolute; top: -20px; right: -8px;
で位置を調整
カラーやボタンのレイアウトなどはカスタマイズしてください!
チャットルーム一覧
<% if @user_rooms.present? %>
<% @user_rooms.each do |user_room| %>
<% room = user_room[:room] %>
<% other_user = user_room[:other_user] %>
<% unread_chats_count = user_room[:unread_chats_count] %>
<div class="row mb-3 bg-light p-3 rounded" style="position: relative;">
<% if unread_chats_count > 0 %>
<span class="badge" style="position: absolute; top: -8px; right: -8px; background-color: red; color: #FFD43B; border-radius: 50%; padding: 5px 10px; font-size: 20px;">
<%= unread_chats_count %>
</span>
<% end %>
<%= link_to user_path(other_user) do %>
<%= image_tag other_user.get_profile_image(90, 90), class: "rounded-circle mx-auto d-block" %>
<% end %>
<%= link_to other_user.name, chat_path(other_user), class: 'text-decoration-none' %>
<% end %>
<% else %>
チャットルームがありません
<% end %>
さいごに
ざっくりとですがこんな感じです
誤り等ありましたら教えていただけますと幸いです!
参照資料
参考にさせていただきました!
ありがとうございました!