学生向けプログラミング入門 | 無料

学生向けにプログラミングを無料で解説。Java、C++、Ruby、PHP、データベース、Ruby on Rails, Python, Django

Rails7.1 | 仕事売買アプリ作成 | 36 | raty-js

↓↓クリックして頂けると励みになります。



35 | 仕事とリクエスト】 << 【ホーム】 >> 【37 | ActionText



raty-jsは、スター評価を作成するためのJavaScriptプラグインです。
Rails7.1でraty-jsを利用するには、以下のステップに従って設定を行う必要があります。


「star-on.png」「star-off.png」「star-half.png」の3ファイルを「app/assets/images」フォルダにコピーしておいてください。


画像は下記のリンクにあります。
github.com


「raty-js」をインストールします。

Rails6.1ではyarnを利用していましたが、Rails7.1ではimportmapを利用しまし。
しかしながら、使用するJQueryがimportmapでうまく動作しないため、raty-jsも「app/views/layouts/application.html.erb」ファイルのheadタグ内で直接CDNのスクリプトを読み込ませます。


記述追加 「app/views/layouts/application.html.erb」28行目

    <!-- JQuery 3.7.1 -->
    <script
    src="https://code.jquery.com/jquery-3.7.1.min.js"
    integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
    crossorigin="anonymous"></script>

    <!-- ratyjs 3.1.1 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/raty/3.1.1/jquery.raty.min.js" integrity="sha512-Isj3SyFm+B8u/cErwzYj2iEgBorGyWqdFVb934Y+jajNg9kiYQQc9pbmiIgq/bDcar9ijmw4W+bd72UK/tzcsA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>



記述追加 【app/views/layouts/application.html.erb】43行目

<!DOCTYPE html>
<html>
  <head>
    <title>GigHub7</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>

    <!-- noty3.1.4 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.4/noty.min.js" integrity="sha512-lOrm9FgT1LKOJRUXF3tp6QaMorJftUjowOWiDcG5GFZ/q7ukof19V0HKx/GWzXCdt9zYju3/KhBNdCLzK8b90Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.4/noty.min.css" integrity="sha512-0p3K0H3S6Q4bEWZ/WmC94Tgit2ular2/n0ESdfEX8l172YyQj8re1Wu9s/HT9T/T2osUw5Gx/6pAZNk3UKbESw==" crossorigin="anonymous" referrerpolicy="no-referrer" />

    <!-- Google Fonts -->
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Kaisei+Opti&family=Kosugi+Maru&family=Rampart+One&display=swap" rel="stylesheet">

    <!-- Font Awesome -->
    <script src="https://kit.fontawesome.com/dd8c589546.js" crossorigin="anonymous"></script>

    <!-- Dropzone5.5.1 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.js" integrity="sha512-jytq61HY3/eCNwWirBhRofDxujTCMFEiQeTe+kHR4eYLNTXrUq7kY2qQDKOUnsVAKN5XGBJjQ3TvNkIkW/itGw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/min/dropzone.min.css" integrity="sha512-zoIoZAaHj0iHEOwZZeQnGqpU8Ph4ki9ptyHZFPe+BmILwqAksvwm27hR9dYH4WXjYY/4/mz8YDBCgVqzc2+BJA==" crossorigin="anonymous" referrerpolicy="no-referrer" />

    <!-- JQuery 3.7.1 -->
    <script
    src="https://code.jquery.com/jquery-3.7.1.min.js"
    integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo="
    crossorigin="anonymous"></script>

    <!-- ratyjs 3.1.1 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/raty/3.1.1/jquery.raty.min.js" integrity="sha512-Isj3SyFm+B8u/cErwzYj2iEgBorGyWqdFVb934Y+jajNg9kiYQQc9pbmiIgq/bDcar9ijmw4W+bd72UK/tzcsA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

  </head>

  <body>

    <!-- ナビゲーションバー -->
    <%= render  "shared/navbar" %>

    <!-- noty -->
    <%= render 'shared/notification' %>

    <%= yield %>
  </body>
</html>


モデル



レビューモデルを作成します。


コマンド
一文です。
rails g model Review review:text stars:bigint order:references gig:references buyer:references seller:references


「db\migrate\20200710011458_create_reviews.rb」ファイルを以下のように更新します。


記述更新 db\migrate\20200710011458_create_reviews.rb
コードをコピーしてファイルの内容を置き換えて下さい。

class CreateReviews < ActiveRecord::Migration[7.1]
  def change
    create_table :reviews do |t|
      t.text :review
      t.integer :stars, default: 1
      t.references :order, null: false, foreign_key: true, type: :uuid
      t.references :gig, null: true, foreign_key: true
      t.references :buyer, foreign_key: { to_table: :users }
      t.references :seller, foreign_key: { to_table: :users }

      t.timestamps
    end
  end
end



コマンド マイグレーション適用
rails db:migrate


「app\models\review.rb」ファイルを以下のように編集します。


記述編集 app\models\review.rb

class Review < ApplicationRecord
  belongs_to :order
  belongs_to :gig, required: false
  belongs_to :buyer, class_name: "User"
  belongs_to :seller, class_name: "User"
end



「app\models\order.rb」ファイルに以下の記述を追加します。


記述追加 app\models\order.rb(8行目)

has_many :reviews



app\models\order.rb

class Order < ApplicationRecord
  belongs_to :gig, required: false
  belongs_to :request, required: false

  belongs_to :buyer, class_name: "User"
  belongs_to :seller, class_name: "User"

  has_many :reviews

  enum status: [:inprogress, :completed]
end



「app\models\gig.rb」ファイルに以下の記述を追加します。


1.記述追加 app\models\gig.rb(7行目)

has_many :reviews



2.記述追加 app\models\gig.rb(15行目)

  def average_rating
    reviews.count == 0 ? 0 : reviews.average(:stars).round(1)
  end



app\models\gig.rb

class Gig < ApplicationRecord
  belongs_to :user
  belongs_to :category

  has_many :pricings
  has_many :orders
  has_many :reviews
  
  has_many_attached :photos

  accepts_nested_attributes_for :pricings

  validates :title, presence: { message: '空白にはできません' }

  def average_rating
    reviews.count == 0 ? 0 : reviews.average(:stars).round(1)
  end
    
end


コントローラ



レビューコントローラーを作成します。
「app\controllers」フォルダに「reviews_controller.rb」ファイルを新規作成して下さい。


app\controllers\reviews_controller.rb(新規作成したファイル)

class ReviewsController < ApplicationController

    def create
        order = Order.find(review_params[:order_id])

        if order && current_user.id == order.buyer.id
            if Review.exists?(order_id: review_params[:order_id], buyer_id: current_user.id)
                flash[:alert] = "レビュー済みです。"
            else
                review = Review.new(review_params)
                review.gig = order.gig
                review.buyer = current_user
                review.seller = order.seller

                if review.save
                    flash[:notice] = "レビューを投稿しました。"
                else
                    flash[:alert] = "レビューできません"
                end
            end
        else
            flash[:alert] = "無効です"
        end
        redirect_to request.referrer
    end

    def destroy
        @review = Review.find(params[:id])
        @review.destroy
    
        redirect_back(fallback_location: request.referer, notice: "削除しました。")
    end

    private

    def review_params
        params.require(:review).permit(:stars, :review, :order_id)
    end
end



「app\controllers\users_controller.rb」ファイルに以下の記述を追加します。


showメソッドに記述を追加しています。
1.記述追加 app\controllers\users_controller.rb(6行目)

@reviews = Review.where(buyer_id: current_user.id).all.order("created_at desc")



2.記述追加 app\controllers\users_controller.rb(11行目)

@reviews = Review.where(seller_id: params[:id]).order("created_at desc")



app\controllers\users_controller.rb

class UsersController < ApplicationController
  
  before_action :authenticate_user!

  def dashboard
    @reviews = Review.where(buyer_id: current_user.id).all.order("created_at desc")
  end

  def show
    @user = User.find(params[:id])
    @reviews = Review.where(seller_id: params[:id]).order("created_at desc")
  end

  def update
    @user = current_user
    if @user.update(current_user_params)
      flash[:notice] = "保存しました"
    else
      flash[:alert] = "更新できません"
    end
    redirect_to dashboard_path
  end

  private

  def current_user_params
    params.require(:user).permit(:about, :status, :avatar)
  end

end


ルート設定



ルートの設定をします。


「config\routes.rb」ファイルに以下の記述を追加します。


1.記述追加 config\routes.rb(19行目)

 post '/reviews', to: 'reviews#create'

2.記述追加 config\routes.rb(35行目)

resources :reviews, only: [:create, :destroy]



config\routes.rb

Rails.application.routes.draw do

  # ルートを app\views\pages\home.html.erb に設定
  root 'pages#home'

  # get
  get 'pages/home'
  get '/dashboard', to: 'users#dashboard'
  get '/users/:id', to: 'users#show', as: 'user'
  get '/selling_orders', to: 'orders#selling_orders'
  get '/buying_orders', to: 'orders#buying_orders'
  get '/all_requests', to: 'requests#list'
  get '/request_offers/:id', to: 'requests#offers', as: 'request_offers'
  get '/my_offers', to: 'requests#my_offers'

  # post
  post '/users/edit', to: 'users#update'
  post '/offers', to: 'offers#create'
  post '/reviews', to: 'reviews#create'

  # put
  put '/orders/:id/complete', to: 'orders#complete', as: 'complete_order'
  put '/offers/:id/accept', to: 'offers#accept', as: 'accept_offer'
  put '/offers/:id/reject', to: 'offers#reject', as: 'reject_offer'

  resources :gigs do
    member do
      delete :delete_photo
      post :upload_photo
    end
    resources :orders, only: [:create]
  end

  resources :requests
  resources :reviews, only: [:create, :destroy]
  
  # device
  devise_for :users, 
    path: '', 
    path_names: {sign_up: 'register', sign_in: 'login', edit: 'profile', sign_out: 'logout'},
    controllers: {omniauth_callbacks: 'omniauth_callbacks', registrations: 'registrations'}
  # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html

  # Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
  # Can be used by load balancers and uptime monitors to verify that the app is live.
  get "up" => "rails/health#show", as: :rails_health_check

  # Defines the root path route ("/")
  # root "posts#index"
end


ビューを作成します。



「app/views」フォルダに「reviews」フォルダを新規作成します。
作成した「reviews」フォルダに「_form.html.erb」ファイルを新規作成します。



新規作成 【app/views/reviews/_form.html.erb】

<!-- Button trigger modal -->
<button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#exampleModal<%= o.id %>">
  <font style="font-size: 0.9rem;">レビュー</font>
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal<%= o.id %>" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
    <%= form_for Review.new do |f| %>
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="exampleModalLabel"><div id="stars_<%= o.id %>"></div></h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <%= f.text_area :review, class: "textarea", required: true, style: "width: 20rem; height: 10rem; margin-top: -1rem;" %>
        <%= f.hidden_field :order_id, value: o.id %>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">閉じる</button>
        <%= f.submit "レビューを投稿する", class: "btn btn-warning" %>
      </div>
    <% end %>
    </div>
  </div>
</div>


<script>
    $('#stars_<%= o.id %>').raty({
        path: '/assets',
        scoreName: 'review[stars]',
        score: 1
    });
</script>



仕事を購入したクライアントが仕事完了にした後、レビューできるようにボタンを実装します。
「app\views\orders\buying_orders.html.erb」ファイルに以下の記述を追加します。


記述追加 app\views\orders\buying_orders.html.erb(28行目)

<%= render partial: "reviews/form", locals: {o: o} %>



app\views\orders\buying_orders.html.erb

<div class="container mt-4">
    <div class="card">
        <div class="card-body">

            <h5 class="card-title text-danger h3 font1">依頼内容(クライアント)</h5>
            <% if @orders.blank? %>
                <h5 class="font1">表示できるオーダーはありません。</h5>
            <% end %>

            <% @orders.each do |o| %>
                <div class="card mt-4">
                    <div class="card-body">

                        <% if !o.request.nil? %>
                            <div class="badge bg-info mb-4">リクエスト</div>
                        <% else %>
                            <div class="badge bg-dark mb-4">購入済みの仕事</div>
                        <% end %>  

                        <div class="mt-2">                                    
                            <% if o.inprogress? %>
                                <span class="font1 alert alert-danger text-center">進行中</span>
                                <%= link_to complete_order_path(o), data: { turbo_method: :put, turbo_confirm: "完了にしてもよろしいですか?" } do %>
                                    <i class="fa fa-thumbs-up fa-lg" style="color: green;"></i><span class="badge bg-success">完了</span>
                                <% end %>
                            <% else %>
                                <span class="font1 alert alert-success text-center">完了</span>
                                <%= render partial: "reviews/form", locals: {o: o} %>
                            <% end %>
                        </div>
                        <ul class="list-group mt-4">

                            <li class="list-group-item" style="border: none;">
                                <span class="font1">依頼日:</span><%= I18n.l(o.created_at, format: :full_date) %>
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">フリーランサー</span>                            
                                <%= link_to user_path(o.seller), class: "tootip", style: "text-decoration: none;" do %>
                                    <span class="btn btn-light"><%= o.seller_name %></span>
                                <% end %>                                                                     
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">仕事名:</span>
                                <%= link_to o.title, gig_path(o.gig), class: "btn btn-light" if !o.gig.nil? %>
                                <%= link_to o.title, request_path(o.request), class: "btn btn-light" if !o.request.nil? %>   
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">期日:</span>   <%= I18n.l(o.due_date) %>                   
                            </li>
                            <li class="list-group-item" style="border: none;">
                                <span class="font1">価格:</span><%= number_to_currency(o.amount) %>
                            </li>                  
                        </ul>

                    </div>
                </div>
            <% end %>
        </div>
    </div>
</div>



ブラウザ確認
http://localhost:3000/buying_orders


ステータスが「完了」になると「レビューする」ボタンが表示されます。
レビューを投稿して確認します。

PCレイアウト
PCレイアウト


モバイルレイアウト
モバイルレイアウト



「app/views/reviews」フォルダに「_list.html.erb」ファイルを新規作成します。
作成した「_list.html.erb」ファイルを以下のように編集します。



新規作成 【app/views/reviews/_list.html.erb】

<% @reviews.each do |r| %>
    <div style="border: solid 1px #c0c0c0; margin-bottom: 0.3rem; border-radius: 5px;">
    <ul class="list-group list-group-horizontal">
        <li class="list-group-item bn" style="border:none;">
            <figure class="figure">
            <%= image_tag avatar_url(r.buyer), style: "width: 40px; position:relative; left: 1.3rem;", class: "figure-img img-fluid rounded-pill" %>
                <figcaption class="figure-caption">
                        <div class="font2"><%= r.buyer.full_name %></div>
                        <span><i class="fa fa-star" style="color: gold;"></i></span><span><%= r.stars %></span>
                </figcaption>
            </figure>
        </li>
        <li class="list-group-item bn" style="width: 80%; border:none">
            <span class="font2"><%= r.review %></span>
            <span class="text-secondary font2"><small><%= time_ago_in_words(r.created_at) %></small></span>
        </li>

        <% if (user_signed_in?) %>
            <% if current_user && current_user == r.buyer %>
            <li class="list-group-item bn" style="border:none;">
                <div>
                    <%= link_to r, data: { turbo_method: :delete, turbo_confirm: "コメントを削除してもよろしいですか?" }, class: "btn btn-light" do %>
                        <i class="fas fa-trash-alt" style="color: red;"></i>
                    <% end %>
                </div>
            </li>
            <% end %>
        <% end %>
                 
    </ul>
    </div>
    <% end %>



「app\views\users\show.html.erb」ファイルに以下の記述を追加します。


記述追加 app\views\users\show.html.erb
1.33行目に記述追加しています。

<%= render "reviews/list" %>



2.52行目に記述追加しています。

<span class="star-review"><i class="fa fa-star text-warning"></i>
    <%= gig.average_rating %>
    <span class="has-text-primary">(<%= gig.reviews.count %>)</span>
</span>       



app\views\users\show.html.erb

<div class="container mt-4 mb-4">
    <div class="row">
        <!-- 左側 -->
        <div class="col-md-4 mb-4">
            <div class="card">
                <div class="card-body">

                    <!-- ステータス -->
                    <div>
                        <% if @user.status %>
                            <span class="badge bg-success"><i class="fa-regular fa-bell"></i>オンライン</span>
                        <% else %>
                            <span class="btn btn-secondary"><i class="fa-regular fa-bell-slash"></i>オフライン</span>
                        <% end %>                                   
                    </div>                
                    <!-- アバター -->
                    <%= image_tag avatar_url(@user), class: "img-fluid img-thumbnail rounded-pill" %>
                    <h4 class="text-center"><%= @user.full_name %></h4>   
                    
                    <!-- 自己紹介 -->
                    <div class="h5 text-center"><%= @user.about %></div>                           
                </div>
            </div>       

        </div>
        <!-- 右側 -->
        <div class="col-md-8">

            <!-- レビュー -->
            <div class="card mb-2">           
                <div class="card-body">
                    <h5 class="card-title font1"><%= @user.full_name %>さんへのレビュー</h5>
                    <%= render "reviews/list" %>
                </div>
            </div>     

            <!-- 登録している仕事 -->
            <div class="card mb-2">
                <div class="card-body">
                    <h5 class="card-title font1"><%= @user.full_name %>さんが登録している仕事</h5>

                    <div class="row">
                        <% @user.gigs.each do |gig| %>
                            <% if gig.active? %>
                                <div class="col-md-4">
                                    <div class="card mb-2">
                                        <%= link_to gig_path(gig), data: { turbolinks: false} do %>
                                            <%= image_tag gig_cover(gig), style: "width: 100%;", class: "card-img-top" %>
                                        <% end %>                                    
                                        <div class="card-body">

                                            <span class="star-review"><i class="fa fa-star text-warning"></i>
                                                <%= gig.average_rating %>
                                                <span class="has-text-primary">(<%= gig.reviews.count %>)</span>
                                            </span>          

                                            <%= link_to gig_path(gig), data: { turbolinks: false} do %>
                                                <h5 class="card-title">
                                                    <span class="btn btn-light"><%= gig.title %></span>
                                                </h5>
                                                <div class="badge bg-primary">
                                                    <% if gig.has_single_pricing%>
                                                        シングルプランのみ
                                                    <% else %>
                                                        3プラン
                                                    <% end %>
                                                </div>
                                            <% end %>                        
                                        </div>
                                    </div>
                                </div>
                            <% end %>
                        <% end %>
                    </div>
                </div>  
            </div>
            <!-- 登録リクエスト -->
            <div class="card mt-2">
                <div class="card-body">
                    <h5 class="card-title font1"><%= @user.full_name %>さんが登録しているリクエスト</h5>

                    <div class="row">
                    <% @user.requests.each do |r| %>

                        <div class="col-md-4">
                            <div class="card mb-2">
                                <div class="card-body">
                                    <% if r.offers.count == 0 %>
                                        <span class="badge bg-secondary">まだ申し込みはありません</span>
                                    <% else %>
                                        <span class="badge bg-danger"><%= r.offers.count %>件の申し込みがあります</span>
                                    <% end %>     

                                    <ul class="list-group mt-4">
                                        <li class="list-group-item" style="border: none;">
                                            <span class="font1">リクエスト日:</span><%= I18n.l(r.created_at, format: :full_date) %>
                                        </li>
                                        <li class="list-group-item" style="border: none;">
                                            <span class="font1">リクエスト名:</span>
                                            <%= link_to r.title, request_path(r), class: "btn btn-light" %>
                                        </li>               
                                        <li class="list-group-item" style="border: none;">
                                            <span class="font1">期日:</span>   <%= r.delivery %></li>
                                        <li class="list-group-item" style="border: none;">
                                            <span class="font1">価格:</span><%= number_to_currency(r.budget) %>
                                        </li>
                                        <% if r.attachment_file.attached? %>
                                            <div class="mt-2">
                                                <%= link_to url_for(r.attachment_file), 
                                                                class: "badge bg-success",  
                                                                download: "Attachment_#{r.attachment_file.id}",
                                                                style: "text-decoration: none;" do %>
            
                                                    <i class="fas fa-paperclip fa-lg p-r-5"></i><span class="fs-6"><%= r.attachment_file.filename %></span>
            
                                                <% end %>
                                            </div>
                                        <% end %>                         
                                    </ul>
                                </div>
                            </div>
                        </div>
                    <% end %>
                </div>
            </div>
        </div>
    </div>
</div>



ブラウザ確認
http://localhost:3000/users/2

PCレイアウト
PCレイアウト


モバイルレイアウト
モバイルレイアウト



ダッシュボードを修正してレビューのスターを反映させます。
合わせてレビュー表示も行います。


記述追加 app\views\users\dashboard.html.erb(195行目)
1.100行目に以下の記述を追加します。

<span class="star-review"><i class="fa fa-star text-warning"></i>
           <%= gig.average_rating %>
           <span class="has-text-primary">(<%= gig.reviews.count %>)</span>
</span>      



2.185行目に以下の記述を追加します。

           <!-- レビュー -->
            <div class="card mb-2 mt-2">           
                <div class="card-body">
                    <h5 class="card-title font1">投稿したレビュー</h5>
                    <%= render "reviews/list" %>
                </div>
            </div>  



app\views\users\dashboard.html.erb

<div class="container mt-4 mb-4">
    <div class="row">
        <!-- 左側 -->
        <div class="col-md-4">
            <div class="card">
                <div class="card-body">
                    <!-- アバター -->
                    <%= image_tag avatar_url(current_user), class: "img-fluid img-thumbnail rounded-pill" %>
                    <h4 style="margin-left: 5.5rem;"><%= current_user.full_name %></h4>
                    <!-- 画像アップロードボタン -->
                    <button class="btn btn-dark text-light w-100" type="button" data-bs-toggle="collapse" data-bs-target="#collapse1" aria-expanded="false" aria-controls="collapse1">
                        <i class="fa-solid fa-cloud-arrow-up"></i>アバター画像アップロード
                    </button>
                    <div class="collapse" id="collapse1">
                    <div class="card card-body">
                        <%= form_for :user, url: users_edit_url(current_user), action: :update, method: :post do |f| %>
                            <%= f.file_field :avatar, class: "input-group-text", onchange: "this.form.submit();" %>
                        <% end %>   
                    </div>
                </div>
                <hr/>
                登録:<%= I18n.l(current_user.created_at, format: :full_date) %>
                <hr/>
                <div type="button" data-bs-toggle="collapse" data-bs-target="#collapse2" aria-expanded="false" aria-controls="collapse2">

                    <% if current_user.status %>
                        <span class="btn btn-success"><i class="toggle far fa-edit"></i>オンライン</span>
                    <% else %>
                        <span class="btn btn-secondary"><i class="toggle far fa-edit"></i>オフライン</span>
                    <% end %>                
                
                </div>
                <div class="collapse" id="collapse2">
                    <div class="card card-body">

                        <%= form_for :user, url: users_edit_url(current_user), action: :update, method: :post do |f| %>
                            <%= f.select(:status, options_for_select([["オンライン", true], ["オフライン", false]]), {}, {class: "custom-select"}) %>                        
                            <%= f.submit "保存", class: "btn btn-dark" %>
                        <% end %>

                    </div>
                </div>
                <hr/>
                <div class="h5"><%= current_user.about %></div>
                <button class="btn btn-secondary" type="button" data-bs-toggle="collapse" data-bs-target="#collapse3" aria-expanded="false" aria-controls="collapse3">
                    自己紹介編集
                </button>

                <div class="collapse" id="collapse3">
                    <div class="card card-body">
                        <%= form_for :user, url: users_edit_url(current_user), action: :update, method: :post do |f| %>
                            <div><%= f.text_area :about, autofocus: true, autocomplete: 'form'%></div>
                            <%= f.submit "保存", class: "btn btn-dark" %>
                        <% end %>                        
                    </div>
                </div>
                <hr />
                <!-- 電話番号 -->
                <div>
                    <% if !current_user.phone_number.blank? %>
                        <span class="pull-right icon-babu"><i class="far fa-check-circle" style="color:green;"></i></span>&nbsp;&nbsp;電話番号
                    <% else %>
                        <div class="text-danger">電話番号が登録されていません</div>
                        <%= link_to  "電話番号登録", edit_user_registration_path, class: "btn btn-danger" %>
                    <% end %>                    
                    </div>       
                    
                </div>
            </div>
        </div>
        <!-- 右側 -->
        <div class="col-md-8">

            <!-- お知らせ -->
            <div class="card">
                <div class="card-body">
                    <h5 class="card-title">お知らせ</h5>
                    <h6 class="card-subtitle mb-2 text-body-secondary">
                    </h6>
                    <p class="card-text">
                    </p>    
                </div>
            </div>

            <!-- 登録している仕事 -->
            <div class="card mt-2">
                <div class="card-body">
                    <h5 class="card-title">登録している仕事</h5>

                    <div class="row">
                        <% current_user.gigs.each do |gig| %>
                            <% if gig.active? %>
                                <div class="col-md-4">
                                    <div class="card mb-2">
                                    <%= link_to gig_path(gig), data: { turbolinks: false} do %>
                                        <%= image_tag gig_cover(gig), style: "width: 100%;", class: "card-img-top" %>
                                    <% end %>                                    
                                        <div class="card-body">

                                            <span class="star-review"><i class="fa fa-star text-warning"></i>
                                                <%= gig.average_rating %>
                                                <span class="has-text-primary">(<%= gig.reviews.count %>)</span>
                                            </span>          

                                            <%= link_to gig_path(gig), data: { turbolinks: false} do %>
                                                <h5 class="card-title">
                                                    <span class="btn btn-light"><%= gig.title %></span>
                                                </h5>
                                            <% end %>
                                            <div class="card-text" style="margin-left: 0.5rem;">
                                                <p><%= gig.summary %></p>          
                                                <%= link_to edit_gig_path(gig), class: "btn btn-outline-primary w-100 mb-4" do %>
                                                    登録内容編集
                                                <% end %>
                                              
                                            </div>                             
                                        </div>
                                    </div>
                                </div>
                            <% end %>
                        <% end %>
                    </div>
                </div>
            </div>
            <!-- 登録リクエスト -->
            <div class="card mt-2">
                <div class="card-body">
                    <h5 class="card-title">登録しているリクエスト</h5>

                    <div class="row">
                    <% current_user.requests.each do |r| %>

                        <div class="col-md-4">
                            <div class="card mb-2">
                                <div class="card-body">
                                    <div>
                                        <% if r.offers.count == 0 %>
                                            <span class="badge bg-secondary">まだオファーがありません</span>
                                        <% else %>
                                            <%= link_to request_offers_path(r) do %>
                                                <span class="badge bg-danger"><%= r.offers.count %>件のオファーが入りました</span>
                                            <% end %>
                                        <% end %>                                    
                                    </div>
                                    <ul class="list-group mt-4">
                                        <li class="list-group-item" style="border: none;">
                                            <span class="font1">リクエスト日:</span><%= I18n.l(r.created_at, format: :full_date) %>
                                        </li>
                                        <li class="list-group-item" style="border: none;">
                                            <span class="font1">リクエスト名:</span>
                                            <%= link_to r.title, request_path(r), class: "btn btn-light" %>
                                        </li>               
                                        <li class="list-group-item" style="border: none;">
                                            <span class="font1">期日:</span>   <%= r.delivery %></li>
                                        <li class="list-group-item" style="border: none;">
                                            <span class="font1">価格:</span><%= number_to_currency(r.budget) %>
                                        </li>
                                        <% if r.attachment_file.attached? %>
                                            <div class="mt-2">
                                                <%= link_to url_for(r.attachment_file), 
                                                                class: "badge bg-success",  
                                                                download: "Attachment_#{r.attachment_file.id}",
                                                                style: "text-decoration: none;" do %>
            
                                                    <i class="fas fa-paperclip fa-lg p-r-5"></i><span class="fs-6"><%= r.attachment_file.filename %></span>
            
                                                <% end %>
                                            </div>
                                        <% end %>
                                        <li class="list-group-item mt-4" style="border: none;">
                                        <%= link_to edit_request_path(r), class: "btn btn-outline-primary w-100 mb-4" do %>
                                            登録内容編集
                                        <% end %>
                                        </li>                                      
                                    </ul>
                                </div>
                            </div>
                        </div>
                    <% end %>
                    </div>
                </div>
            </div>

            <!-- レビュー -->
            <div class="card mb-2 mt-2">           
                <div class="card-body">
                    <h5 class="card-title font1">投稿したレビュー</h5>
                    <%= render "reviews/list" %>
                </div>
            </div>            
        </div>
    </div>
</div>



ブラウザ確認
http://localhost:3000/dashboard

PCレイアウト
PCレイアウト


モバイルレイアウト
モバイルレイアウト




35 | 仕事とリクエスト】 << 【ホーム】 >> 【37 | ActionText





↓↓クリックして頂けると励みになります。