Skip to content

Commit

Permalink
Merge pull request #4 from KOH6/products_admin
Browse files Browse the repository at this point in the history
商品管理機能実装
  • Loading branch information
KOH6 authored Sep 8, 2023
2 parents 047551b + d8b2390 commit 4cc81bf
Show file tree
Hide file tree
Showing 25 changed files with 359 additions and 28 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'

# 環境変数
.env

# Ignore bundler config.
/.bundle

Expand Down
10 changes: 8 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,17 @@ gem 'bootsnap', require: false
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
gem 'image_processing', '~> 1.2'

# 論理削除用のgem
# 論理削除用
gem 'discard'

# 日本語訳用
gem 'rails-i18n'

# ローカルでの環境変数設定用
gem 'dotenv-rails'

group :production do
# AWSのS3用gem
# AWSのS3用
gem 'aws-sdk-s3', require: false
gem 'fog-aws'
end
Expand Down
9 changes: 9 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ GEM
diff-lcs (1.5.0)
discard (1.3.0)
activerecord (>= 4.2, < 8)
dotenv (2.8.1)
dotenv-rails (2.8.1)
dotenv (= 2.8.1)
railties (>= 3.2)
erubi (1.12.0)
erubis (2.7.0)
excon (0.102.0)
Expand Down Expand Up @@ -228,6 +232,9 @@ GEM
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
rails-i18n (7.0.8)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
rails_best_practices (1.23.2)
activesupport
code_analyzer (~> 0.5.5)
Expand Down Expand Up @@ -347,6 +354,7 @@ DEPENDENCIES
cssbundling-rails
debug
discard
dotenv-rails
factory_bot_rails
fog-aws
htmlbeautifier
Expand All @@ -356,6 +364,7 @@ DEPENDENCIES
pg (~> 1.1)
puma (~> 5.0)
rails (~> 7.0.0)
rails-i18n
rails_best_practices
rspec-rails
rubocop
Expand Down
70 changes: 70 additions & 0 deletions app/controllers/admin/products_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# frozen_string_literal: true

module Admin
class ProductsController < ApplicationController
before_action :basic_auth
before_action :set_product, only: %i[show update destroy]

def index
@products = Product.kept.order(updated_at: :desc)
end

def show; end

def edit
@product = Product.kept.find(params[:id])
end

def new
@product = Product.new
end

def create
@product = Product.new(product_params)
if @product.save
redirect_to admin_product_path(@product)
else
render :new
end
end

def update
@updated_product = Product.new(product_params)
# 画像が選択されている場合はその画像を使用。未選択の場合、元の画像を複製して添付する
product_params['image'] || @updated_product.image.attach(@product.image.blob)

# 履歴を保存するため、旧レコードをdiscardし更新後の情報を新レコードとして保存する
if @updated_product.save
@product.discard
redirect_to admin_product_path(@updated_product)
else
render :edit
end
end

def destroy
if @product.discard
flash[:success] = "#{@product.name}の削除が完了しました"
else
flash[:danger] = "#{@product.name}の削除に失敗しました"
end
redirect_to admin_products_path
end

private

def set_product
@product = Product.find(params[:id])
end

def product_params
params.require(:product).permit(%i[name sku description price stock image])
end

def basic_auth
authenticate_or_request_with_http_basic do |username, password|
username == ENV['BASIC_AUTH_USER'] && password == ENV['BASIC_AUTH_PASSWORD']
end
end
end
end
6 changes: 3 additions & 3 deletions app/controllers/products_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

class ProductsController < ApplicationController
def index
@products = Product.all
@products = Product.kept.order(updated_at: :desc)
end

def show
@product = Product.find(params[:id])
@recommended_products = Product.where.not(id: params[:id]).order(created_at: :desc).limit(4)
@product = Product.kept.find(params[:id])
@recommended_products = Product.kept.where.not(id: params[:id]).order(created_at: :desc).limit(4)
end
end
8 changes: 8 additions & 0 deletions app/models/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@ class Product < ApplicationRecord
include Discard::Model

has_one_attached :image

with_options presence: true do
validates :name
validates :sku
validates :price
validates :stock
validates :image, presence: { message: 'を選択してください' }
end
end
24 changes: 24 additions & 0 deletions app/views/admin/products/_card.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<div class="col mb-5">
<div class="card h-100">
<!-- Product image-->
<%= image_tag product.image %>
<!-- Product details-->
<div class="card-body p-4">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">
<%= link_to product.name, admin_product_path(product), class: "link-dark" %>
</h5>
<!-- Product price-->
<%= convert_to_jpy(product.price) %>
</div>
</div>
<!-- Product actions-->
<div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
<div class="text-center">
<%= link_to "編集", edit_admin_product_path(product), class: "btn btn-primary m-1" %>
<%= link_to "削除", admin_product_path(product), data: { turbo_method: :delete, turbo_confirm: "#{product.name}を削除してよろしいですか?" }, class: "btn btn-danger m-1" %>
</div>
</div>
</div>
</div>
32 changes: 32 additions & 0 deletions app/views/admin/products/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div class="container px-4 px-lg-5">
<%= form_with model: product, url: url, data: { turbo: false } do |f| %>
<div class="form-group my-3">
<%= f.label :name, class: "mb-2 block text-sm text-gray-600" %>
<%= f.text_field :name, class: "form-control" %>
</div>
<div class="form-group my-3">
<%= f.label :sku, class: "mb-2 block text-sm text-gray-600" %>
<%= f.text_field :sku, class: "form-control" %>
</div>
<div class="form-group my-3">
<%= f.label :description, class: "mb-2 block text-sm text-gray-600" %>
<%= f.text_area :description, class: "form-control" %>
</div>
<div class="form-group my-3">
<%= f.label :price, class: "mb-2 block text-sm text-gray-600" %>
<%= f.number_field :price, class: "form-control" %>
</div>
<div class="form-group my-3">
<%= f.label :stock, class: "mb-2 block text-sm text-gray-600" %>
<%= f.number_field :stock, class: "form-control" %>
</div>
<div class="form-group my-3">
<%= f.label :image, class: "mb-2 block text-sm text-gray-600" %>
<%= f.file_field :image, class: "form-control" %>
</div>
<div class="text-center">
<%= link_to "一覧へ戻る", admin_products_path, class: "btn btn-secondary mt-auto" %>
<button type="submit" class="btn btn-primary">保存</button>
</div>
<% end %>
</div>
9 changes: 9 additions & 0 deletions app/views/admin/products/_navigation.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<nav class="navbar navbar-expand-lg navbar-light bg-danger">
<div class="container px-4 px-lg-5">
<%= link_to "管理者用設定", admin_products_path, class: "navbar-brand" %>
<div class="justify-content-beetween">
<%= link_to "購入明細一覧", admin_products_path, class: "btn btn-primary mt-auto" %>
<%= link_to "新規作成", new_admin_product_path, class: "btn btn-primary mt-auto" %>
</div>
</div>
</nav>
28 changes: 28 additions & 0 deletions app/views/admin/products/edit.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>KOH's Shop</title>
</head>
<body>
<!-- Navigation-->
<%= render 'navigation' %>
<!-- ErrorMessages-->
<% if @updated_product %>
<%= render 'shared/error_messages', :resource => @updated_product %>
<% end %>
<!-- Header-->
<header class="py-4 text-center">
<h1 class="display-6 fw-bolder">商品編集</h1>
</header>
<!-- form-->
<%= render 'form', :product => @product, :url => admin_product_path(@product) %>
<!-- Footer-->
<footer class="py-5 bg-dark">
<div class="container">
<p class="m-0 text-center text-white">Copyright &copy; KOH's Shop 2023</p>
</div>
</footer>
</body>
</html>
34 changes: 34 additions & 0 deletions app/views/admin/products/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>KOH's Shop</title>
</head>
<body>
<!-- Navigation-->
<%= render 'navigation' %>
<!-- Flash-->
<%= render 'shared/flash' %>
<!-- Header-->
<header class="py-4 text-center">
<h1 class="display-6 fw-bolder">商品一覧</h1>
</header>
<!-- Section-->
<section>
<div class="container px-4 px-lg-5 mt-5">
<div class="row gx-4 gx-lg-5 row-cols-2 row-cols-md-3 row-cols-xl-4 justify-content-center">
<% @products.each do |product| %>
<%= render 'card', :product => product %>
<% end %>
</div>
</div>
</section>
<!-- Footer-->
<footer class="py-5 bg-dark">
<div class="container">
<p class="m-0 text-center text-white">Copyright &copy; KOH's Shop 2023</p>
</div>
</footer>
</body>
</html>
26 changes: 26 additions & 0 deletions app/views/admin/products/new.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>KOH's Shop</title>
</head>
<body>
<!-- Navigation-->
<%= render 'navigation' %>
<!-- ErrorMessages-->
<%= render 'shared/error_messages', :resource => @product %>
<!-- Header-->
<header class="py-4 text-center">
<h1 class="display-6 fw-bolder">商品作成</h1>
</header>
<!-- form-->
<%= render 'form', :product => @product, :url => admin_products_path %>
<!-- Footer-->
<footer class="py-5 bg-dark">
<div class="container">
<p class="m-0 text-center text-white">Copyright &copy; KOH's Shop 2023</p>
</div>
</footer>
</body>
</html>
43 changes: 43 additions & 0 deletions app/views/admin/products/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<title>KOH's Shop</title>
</head>
<body>
<!-- Navigation-->
<%= render 'navigation' %>
<!-- Display alert if product is discarded-->
<% if @product.discarded? %>
<p class="text-center alert alert-danger">削除済みの商品のため編集できません</p>
<% end %>
<!-- Product section-->
<section class="py-5">
<div class="container px-4 px-lg-5 my-5">
<div class="row gx-4 gx-lg-5 align-items-center">
<div class="col-md-6"><%= image_tag @product.image %></div>
<div class="col-md-6">
<div class="small mb-1"><%= @product.sku %></div>
<h1 class="display-5 fw-bolder"><%= @product.name %></h1>
<div class="fs-5 mb-5">
<span><%= convert_to_jpy(@product.price) %></span>
</div>
<p class="lead"><%= @product.description %></p>
<div class="fs-5">在庫数<%= @product.stock %></div>
<%= link_to "一覧へ戻る", admin_products_path, class: "btn btn-secondary mt-auto" %>
<% if @product.undiscarded? %>
<%= link_to "編集", edit_admin_product_path(@product), class: "btn btn-primary mt-auto" %>
<% end %>
</div>
</div>
</div>
</section>
<!-- Footer-->
<footer class="py-5 bg-dark">
<div class="container">
<p class="m-0 text-center text-white">Copyright &copy; KOH's Shop 2023</p>
</div>
</footer>
</body>
</html>
2 changes: 1 addition & 1 deletion app/views/products/_card.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">
<%= link_to product.name, "/products/#{product.id}", class: "link-dark" %>
<%= link_to product.name, product_path(product), class: "link-dark" %>
</h5>
<!-- Product price-->
<%= convert_to_jpy(product.price) %>
Expand Down
10 changes: 1 addition & 9 deletions app/views/products/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>KOH's Shop</title>
<!-- Favicon-->
<link rel="icon" type="image/x-icon" href="assets/favicon.ico" />
<!-- Bootstrap icons-->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css" rel="stylesheet" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="css/styles.css" rel="stylesheet" />
</head>
<body>
<!-- Navigation-->
Expand Down
Loading

0 comments on commit 4cc81bf

Please sign in to comment.