diff --git a/.idea/tailwind_rails.iml b/.idea/tailwind_rails.iml
index de55e51..aea217d 100644
--- a/.idea/tailwind_rails.iml
+++ b/.idea/tailwind_rails.iml
@@ -37,6 +37,7 @@
+
diff --git a/Gemfile b/Gemfile
index 7338cc4..cd95528 100644
--- a/Gemfile
+++ b/Gemfile
@@ -36,6 +36,9 @@ gem "bootsnap", require: false
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
# gem "image_processing", "~> 1.2"
+# Ordering of SQL relations
+gem "acts_as_list"
+
group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri windows ], require: "debug/prelude"
diff --git a/Gemfile.lock b/Gemfile.lock
index 01242c2..e0a8421 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -71,6 +71,9 @@ GEM
minitest (>= 5.1)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
+ acts_as_list (1.2.2)
+ activerecord (>= 6.1)
+ activesupport (>= 6.1)
addressable (2.8.7)
public_suffix (>= 2.0.2, < 7.0)
ast (2.4.2)
@@ -313,6 +316,7 @@ PLATFORMS
x86_64-linux-musl
DEPENDENCIES
+ acts_as_list
bootsnap
brakeman
capybara
diff --git a/app/assets/images/hotel_images/a_tp_01_240808.jpg.webp b/app/assets/images/hotel_images/a_tp_01_240808.jpg.webp
new file mode 100644
index 0000000..b56dfd6
Binary files /dev/null and b/app/assets/images/hotel_images/a_tp_01_240808.jpg.webp differ
diff --git a/app/assets/images/hotel_images/a_tp_02_240808.jpg.webp b/app/assets/images/hotel_images/a_tp_02_240808.jpg.webp
new file mode 100644
index 0000000..308539d
Binary files /dev/null and b/app/assets/images/hotel_images/a_tp_02_240808.jpg.webp differ
diff --git a/app/assets/images/hotel_images/a_tp_03a_220622.jpg.webp b/app/assets/images/hotel_images/a_tp_03a_220622.jpg.webp
new file mode 100644
index 0000000..992d4ee
Binary files /dev/null and b/app/assets/images/hotel_images/a_tp_03a_220622.jpg.webp differ
diff --git a/app/assets/images/hotel_images/a_tpc01_190909.jpg.webp b/app/assets/images/hotel_images/a_tpc01_190909.jpg.webp
new file mode 100644
index 0000000..fc09f54
Binary files /dev/null and b/app/assets/images/hotel_images/a_tpc01_190909.jpg.webp differ
diff --git a/app/assets/images/hotel_images/b_ss1_02_240808.jpg.webp b/app/assets/images/hotel_images/b_ss1_02_240808.jpg.webp
new file mode 100644
index 0000000..8526e19
Binary files /dev/null and b/app/assets/images/hotel_images/b_ss1_02_240808.jpg.webp differ
diff --git a/app/assets/images/hotel_images/b_ss2_01_240808.jpg.webp b/app/assets/images/hotel_images/b_ss2_01_240808.jpg.webp
new file mode 100644
index 0000000..066f52a
Binary files /dev/null and b/app/assets/images/hotel_images/b_ss2_01_240808.jpg.webp differ
diff --git a/app/assets/images/hotel_images/b_ss3_01_240808.jpg.webp b/app/assets/images/hotel_images/b_ss3_01_240808.jpg.webp
new file mode 100644
index 0000000..c840f30
Binary files /dev/null and b/app/assets/images/hotel_images/b_ss3_01_240808.jpg.webp differ
diff --git a/app/assets/images/hotel_images/b_ss4_01_240808.jpg.webp b/app/assets/images/hotel_images/b_ss4_01_240808.jpg.webp
new file mode 100644
index 0000000..811382a
Binary files /dev/null and b/app/assets/images/hotel_images/b_ss4_01_240808.jpg.webp differ
diff --git a/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-blacktitanium.webp b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-blacktitanium.webp
new file mode 100644
index 0000000..0c6fe02
Binary files /dev/null and b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-blacktitanium.webp differ
diff --git a/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-bluetitanium.webp b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-bluetitanium.webp
new file mode 100644
index 0000000..43df853
Binary files /dev/null and b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-bluetitanium.webp differ
diff --git a/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-naturaltitanium.webp b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-naturaltitanium.webp
new file mode 100644
index 0000000..e229e2e
Binary files /dev/null and b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-naturaltitanium.webp differ
diff --git a/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-whitetitanium.webp b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-whitetitanium.webp
new file mode 100644
index 0000000..6c5e3c4
Binary files /dev/null and b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-1inch-whitetitanium.webp differ
diff --git a/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-blacktitanium.webp b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-blacktitanium.webp
new file mode 100644
index 0000000..32f1888
Binary files /dev/null and b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-blacktitanium.webp differ
diff --git a/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-bluetitanium.webp b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-bluetitanium.webp
new file mode 100644
index 0000000..a1c9c64
Binary files /dev/null and b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-bluetitanium.webp differ
diff --git a/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-naturaltitanium.webp b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-naturaltitanium.webp
new file mode 100644
index 0000000..0ba1b94
Binary files /dev/null and b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-naturaltitanium.webp differ
diff --git a/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-whitetitanium.webp b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-whitetitanium.webp
new file mode 100644
index 0000000..42c3e7a
Binary files /dev/null and b/app/assets/images/iphone_images/iphone-15-pro-finish-select-202309-6-7inch-whitetitanium.webp differ
diff --git a/app/controllers/features_controller.rb b/app/controllers/features_controller.rb
new file mode 100644
index 0000000..f3b794a
--- /dev/null
+++ b/app/controllers/features_controller.rb
@@ -0,0 +1,70 @@
+class FeaturesController < ApplicationController
+ before_action :set_feature, only: %i[ show edit update destroy ]
+
+ # GET /features or /features.json
+ def index
+ @features = Feature.all
+ end
+
+ # GET /features/1 or /features/1.json
+ def show
+ end
+
+ # GET /features/new
+ def new
+ @feature = Feature.new
+ end
+
+ # GET /features/1/edit
+ def edit
+ end
+
+ # POST /features or /features.json
+ def create
+ @feature = Feature.new(feature_params)
+
+ respond_to do |format|
+ if @feature.save
+ format.html { redirect_to feature_url(@feature), notice: "Feature was successfully created." }
+ format.json { render :show, status: :created, location: @feature }
+ else
+ format.html { render :new, status: :unprocessable_entity }
+ format.json { render json: @feature.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /features/1 or /features/1.json
+ def update
+ respond_to do |format|
+ if @feature.update(feature_params)
+ format.html { redirect_to feature_url(@feature), notice: "Feature was successfully updated." }
+ format.json { render :show, status: :ok, location: @feature }
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ format.json { render json: @feature.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /features/1 or /features/1.json
+ def destroy
+ @feature.destroy!
+
+ respond_to do |format|
+ format.html { redirect_to features_url, notice: "Feature was successfully destroyed." }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_feature
+ @feature = Feature.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def feature_params
+ params.require(:feature).permit(:tagline, :descrption, :category, :image_path, :position, :hotel_id)
+ end
+end
diff --git a/app/controllers/hotels/descriptions_controller.rb b/app/controllers/hotels/descriptions_controller.rb
deleted file mode 100644
index 4631116..0000000
--- a/app/controllers/hotels/descriptions_controller.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class Hotels::DescriptionsController < HotelBaseController
- before_action :set_hotel
- def show
- end
-
- private
-
- def set_hotel
- @hotel = Hotel.find(params[:hotel_id])
- end
-end
diff --git a/app/controllers/hotels/features_controller.rb b/app/controllers/hotels/features_controller.rb
new file mode 100644
index 0000000..371f8fe
--- /dev/null
+++ b/app/controllers/hotels/features_controller.rb
@@ -0,0 +1,16 @@
+class Hotels::FeaturesController < HotelBaseController
+ before_action :set_hotel
+ def index
+ @features = @hotel.topic_features.order(:position)
+ end
+
+ def room
+ @features = @hotel.room_features.order(:position)
+ end
+
+ private
+
+ def set_hotel
+ @hotel = Hotel.find(params[:hotel_id])
+ end
+end
diff --git a/app/controllers/iphones_controller.rb b/app/controllers/iphones_controller.rb
new file mode 100644
index 0000000..eebdc5f
--- /dev/null
+++ b/app/controllers/iphones_controller.rb
@@ -0,0 +1,19 @@
+class IphonesController < ApplicationController
+ layout "iphone"
+ before_action :set_iphone
+ def show
+ end
+
+ def create
+ @iphone.model = params[:model] if params[:model]
+ @iphone.color = params[:color] if params[:color]
+ redirect_to iphone_path
+ end
+
+ private
+
+ def set_iphone
+ session[:iphone] ||= {}
+ @iphone = Iphone.new(session[:iphone])
+ end
+end
diff --git a/app/helpers/features_helper.rb b/app/helpers/features_helper.rb
new file mode 100644
index 0000000..1a5e6b2
--- /dev/null
+++ b/app/helpers/features_helper.rb
@@ -0,0 +1,2 @@
+module FeaturesHelper
+end
diff --git a/app/javascript/controllers/image_switcher_controller.js b/app/javascript/controllers/image_switcher_controller.js
new file mode 100644
index 0000000..69edb15
--- /dev/null
+++ b/app/javascript/controllers/image_switcher_controller.js
@@ -0,0 +1,20 @@
+import { Controller } from "@hotwired/stimulus"
+
+// Connects to data-controller="image-switcher"
+export default class extends Controller {
+ static values = {iphone: Object}
+ static targets = ["colorText"]
+
+ connect() {
+ }
+
+ setColorTitle(event) {
+ const colorName = event.params.colorName
+ this.colorTextTargets.forEach(target => target.textContent = colorName)
+ }
+
+ resetColorTitle(event) {
+ this.colorTextTargets.forEach(target => target.textContent = this.iphoneValue.color_name)
+ }
+
+}
diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js
index d689252..42d7ff0 100644
--- a/app/javascript/controllers/index.js
+++ b/app/javascript/controllers/index.js
@@ -19,6 +19,9 @@ application.register("hamburger", HamburgerController)
import HelloController from "./hello_controller"
application.register("hello", HelloController)
+import ImageSwitcherController from "./image_switcher_controller"
+application.register("image-switcher", ImageSwitcherController)
+
import NavbarController from "./navbar_controller"
application.register("navbar", NavbarController)
diff --git a/app/models/feature.rb b/app/models/feature.rb
new file mode 100644
index 0000000..7515305
--- /dev/null
+++ b/app/models/feature.rb
@@ -0,0 +1,4 @@
+class Feature < ApplicationRecord
+ belongs_to :hotel
+ enum :category, [ :topic, :room, :restaurant, :service, :basic_info ]
+end
diff --git a/app/models/hotel.rb b/app/models/hotel.rb
index 7b5c8d7..5f69880 100644
--- a/app/models/hotel.rb
+++ b/app/models/hotel.rb
@@ -1,2 +1,5 @@
class Hotel < ApplicationRecord
+ has_many :features
+ has_many :topic_features, -> { where(category: :topic) }, class_name: "Feature"
+ has_many :room_features, -> { where(category: :room) }, class_name: "Feature"
end
diff --git a/app/models/iphone.rb b/app/models/iphone.rb
new file mode 100644
index 0000000..d56b8b7
--- /dev/null
+++ b/app/models/iphone.rb
@@ -0,0 +1,43 @@
+class Iphone
+ def initialize(iphone_session)
+ @iphone_session = iphone_session
+ end
+
+ def model=(string)
+ @iphone_session['model'] = string
+ end
+
+ def model
+ @iphone_session['model'] || "6-1inch"
+ end
+
+ def color=(string)
+ @iphone_session['color'] = string
+ end
+
+ def color
+ @iphone_session["color"] || "naturaltitanium"
+ end
+
+ def color_name
+ color_name_for_value(color)
+ end
+
+ def color_name_for_value(value)
+ table = {
+ "naturaltitanium" => "Color – Natural Titanium",
+ "bluetitanium" => "Color – Blue Titanium",
+ "whitetitanium" => "Color – White Titanium",
+ "blacktitanium" => "Color – Black Titanium",
+ }
+ table[value]
+ end
+
+ def image_path
+ "iphone_images/iphone-15-pro-finish-select-202309-#{model}-#{color}.webp"
+ end
+
+ def to_hash
+ {model:, color:, color_name:}
+ end
+end
diff --git a/app/views/features/_feature.html.erb b/app/views/features/_feature.html.erb
new file mode 100644
index 0000000..e9a6574
--- /dev/null
+++ b/app/views/features/_feature.html.erb
@@ -0,0 +1,32 @@
+
+
+ Tagline:
+ <%= feature.tagline %>
+
+
+
+ Descrption:
+ <%= feature.descrption %>
+
+
+
+ Category:
+ <%= feature.category %>
+
+
+
+ Image path:
+ <%= feature.image_path %>
+
+
+
+ Position:
+ <%= feature.position %>
+
+
+
+ Hotel:
+ <%= feature.hotel_id %>
+
+
+
diff --git a/app/views/features/_feature.json.jbuilder b/app/views/features/_feature.json.jbuilder
new file mode 100644
index 0000000..af080a7
--- /dev/null
+++ b/app/views/features/_feature.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! feature, :id, :tagline, :descrption, :category, :image_path, :position, :hotel_id, :created_at, :updated_at
+json.url feature_url(feature, format: :json)
diff --git a/app/views/features/_form.html.erb b/app/views/features/_form.html.erb
new file mode 100644
index 0000000..39f8273
--- /dev/null
+++ b/app/views/features/_form.html.erb
@@ -0,0 +1,47 @@
+<%= form_with(model: feature) do |form| %>
+ <% if feature.errors.any? %>
+
+
<%= pluralize(feature.errors.count, "error") %> prohibited this feature from being saved:
+
+
+ <% feature.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :tagline, style: "display: block" %>
+ <%= form.text_field :tagline %>
+
+
+
+ <%= form.label :descrption, style: "display: block" %>
+ <%= form.text_field :descrption %>
+
+
+
+ <%= form.label :category, style: "display: block" %>
+ <%= form.text_field :category %>
+
+
+
+ <%= form.label :image_path, style: "display: block" %>
+ <%= form.text_field :image_path %>
+
+
+
+ <%= form.label :position, style: "display: block" %>
+ <%= form.number_field :position %>
+
+
+
+ <%= form.label :hotel_id, style: "display: block" %>
+ <%= form.text_field :hotel_id %>
+
+
+
+ <%= form.submit %>
+
+<% end %>
diff --git a/app/views/features/edit.html.erb b/app/views/features/edit.html.erb
new file mode 100644
index 0000000..4ca88be
--- /dev/null
+++ b/app/views/features/edit.html.erb
@@ -0,0 +1,12 @@
+<% content_for :title, "Editing feature" %>
+
+Editing feature
+
+<%= render "form", feature: @feature %>
+
+
+
+
+ <%= link_to "Show this feature", @feature %> |
+ <%= link_to "Back to features", features_path %>
+
diff --git a/app/views/features/index.html.erb b/app/views/features/index.html.erb
new file mode 100644
index 0000000..5b2eb5d
--- /dev/null
+++ b/app/views/features/index.html.erb
@@ -0,0 +1,16 @@
+<%= notice %>
+
+<% content_for :title, "Features" %>
+
+Features
+
+
+ <% @features.each do |feature| %>
+ <%= render feature %>
+
+ <%= link_to "Show this feature", feature %>
+
+ <% end %>
+
+
+<%= link_to "New feature", new_feature_path %>
diff --git a/app/views/features/index.json.jbuilder b/app/views/features/index.json.jbuilder
new file mode 100644
index 0000000..9ecc33e
--- /dev/null
+++ b/app/views/features/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @features, partial: "features/feature", as: :feature
diff --git a/app/views/features/new.html.erb b/app/views/features/new.html.erb
new file mode 100644
index 0000000..4d031bd
--- /dev/null
+++ b/app/views/features/new.html.erb
@@ -0,0 +1,11 @@
+<% content_for :title, "New feature" %>
+
+New feature
+
+<%= render "form", feature: @feature %>
+
+
+
+
+ <%= link_to "Back to features", features_path %>
+
diff --git a/app/views/features/show.html.erb b/app/views/features/show.html.erb
new file mode 100644
index 0000000..9b4b6b1
--- /dev/null
+++ b/app/views/features/show.html.erb
@@ -0,0 +1,10 @@
+<%= notice %>
+
+<%= render @feature %>
+
+
+ <%= link_to "Edit this feature", edit_feature_path(@feature) %> |
+ <%= link_to "Back to features", features_path %>
+
+ <%= button_to "Destroy this feature", @feature, method: :delete %>
+
diff --git a/app/views/features/show.json.jbuilder b/app/views/features/show.json.jbuilder
new file mode 100644
index 0000000..d144cb7
--- /dev/null
+++ b/app/views/features/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "features/feature", feature: @feature
diff --git a/app/views/hotels/descriptions/show.html.erb b/app/views/hotels/descriptions/show.html.erb
deleted file mode 100644
index 8d4dc56..0000000
--- a/app/views/hotels/descriptions/show.html.erb
+++ /dev/null
@@ -1,16 +0,0 @@
-<%= turbo_frame_tag :slide_drawer do %>
-
-
-
-
-
-
-<% end %>
diff --git a/app/views/hotels/features/index.html.erb b/app/views/hotels/features/index.html.erb
new file mode 100644
index 0000000..4c01d71
--- /dev/null
+++ b/app/views/hotels/features/index.html.erb
@@ -0,0 +1,38 @@
+<%= turbo_frame_tag :slide_drawer do %>
+
+
+
+
+
+ <% @features[0..1].each do |feature| %>
+
+ <%= image_tag "hotel_images/#{feature.image_path}" %>
+
+
<%= feature.tagline %>
+
<%= sanitize feature.description %>
+
+
+ <% end %>
+
+ <% (@features[2..] || []).each do |feature| %>
+
+ <%= image_tag "hotel_images/#{feature.image_path}" %>
+
+
<%= feature.tagline %>
+
<%= sanitize feature.description %>
+
+
+ <% end %>
+
+
+
+
+<% end %>
diff --git a/app/views/hotels/features/room.html.erb b/app/views/hotels/features/room.html.erb
new file mode 100644
index 0000000..d2f87e2
--- /dev/null
+++ b/app/views/hotels/features/room.html.erb
@@ -0,0 +1,27 @@
+<%= turbo_frame_tag :slide_drawer do %>
+
+
+
+
+
+ <% @features.each do |feature| %>
+
+ <%= image_tag "hotel_images/#{feature.image_path}" %>
+
+
<%= feature.tagline %>
+
<%= sanitize feature.description %>
+
+
+ <% end %>
+
+
+
+<% end %>
diff --git a/app/views/hotels/show.html.erb b/app/views/hotels/show.html.erb
index a8fe752..e57b86b 100644
--- a/app/views/hotels/show.html.erb
+++ b/app/views/hotels/show.html.erb
@@ -42,7 +42,7 @@
>
<%= link_to "部屋・プラン", "",
class: "px-4 inline-block py-4 h-16 text-lg border-b-4 border-blue-500" %>
- <%= link_to "宿の紹介", hotel_description_path(@hotel),
+ <%= link_to "宿の紹介", hotel_features_path(@hotel),
data: {action: "click->drawer-trigger#show", turbo_frame: :slide_drawer},
class: "px-4 inline-block py-4 h-16 text-lg" %>
<%= link_to "クチコミ", "",
diff --git a/app/views/iphones/_color_option.html.erb b/app/views/iphones/_color_option.html.erb
new file mode 100644
index 0000000..c8a8186
--- /dev/null
+++ b/app/views/iphones/_color_option.html.erb
@@ -0,0 +1,13 @@
+<%# locals: (value:, color:, iphone:) %>
+<%= label_tag [:color, value].join('_'),
+ data: {
+ action: "mouseenter->image-switcher#setColorTitle mouseleave->image-switcher#resetColorTitle",
+ image_switcher_color_name_param: iphone.color_name_for_value(value)
+ },
+ class: "#{color} inline-block w-8 h-8 border-2 rounded-full cursor-pointer outline-2 outline outline-offset-0.5 outline-transparent has-[:checked]:outline-blue-500" do %>
+ <%= radio_button_tag :color, value, iphone.color == value,
+ class: "hidden",
+ onchange: "this.form.requestSubmit()"
+ %>
+
+<% end %>
diff --git a/app/views/iphones/_option.html.erb b/app/views/iphones/_option.html.erb
new file mode 100644
index 0000000..565c7eb
--- /dev/null
+++ b/app/views/iphones/_option.html.erb
@@ -0,0 +1,18 @@
+<%# locals: (name:, value:, selected: false, title:, subtitle: nil, pricing_lines:[]) %>
+<%= label_tag [name, value].join('_'), class: "mt-4 flex justify-between p-4 block border-2 rounded-lg w-full cursor-pointer has-[:checked]:border-blue-500" do %>
+ <%= radio_button_tag name, value, selected,
+ class: "hidden",
+ onchange: "this.form.requestSubmit()"
+ %>
+
+
<%= title %>
+ <% if subtitle %>
+
<%= subtitle %>
+ <% end %>
+
+
+ <% pricing_lines.each do |line| %>
+
<%= line %>
+ <% end %>
+
+<% end %>
diff --git a/app/views/iphones/show.html.erb b/app/views/iphones/show.html.erb
new file mode 100644
index 0000000..9493af3
--- /dev/null
+++ b/app/views/iphones/show.html.erb
@@ -0,0 +1,75 @@
+<% turbo_refreshes_with(method: :morph, scroll: :preserve) %>
+
+
+
Buy iPhone 15 Pro
+
From $1399 or $58.29/mo. for 24 mo.*
+
+
+<%= tag.div class: "flex" do %>
+
+ <% if @iphone.image_path %>
+ <%= image_tag @iphone.image_path,
+ class: "object-cover w-[592px] h-[460px] rounded-[20px]" %>
+ <% end %>
+
+
+
+
Model. Which is best for you?
+
+ <%= form_with url: iphone_path, method: :post do %>
+ <%= render 'option',
+ name: :model,
+ value: "6-1inch",
+ selected: @iphone.model == "6-1inch",
+ title: "iPhone 15 Pro",
+ subtitle: "6.1-inch display",
+ pricing_lines: ["From $999", "or $41.62/mo.", "for 24 mo."] %>
+ <%= render 'option',
+ name: :model,
+ value: "6-7inch",
+ selected: @iphone.model == "6-7inch",
+ title: "iPhone 15 Pro Max",
+ subtitle: "6.7-inch display",
+ pricing_lines: ["From $1199", "or $49.95/mo.", "for 24 mo."] %>
+ <% end %>
+
+
+
Need help choosing a model?
+
Explore the differences in screen size and battery life
+
+
+
+
+
+
+
+
Finish. Pick your favorite
+ <%= tag.div data: {controller: "image-switcher", image_switcher_iphone_value: @iphone} do %>
+
<%= @iphone.color_name %>
+
+ <%= form_with url: iphone_path, method: :post do %>
+ <%= render 'color_option',
+ value: "naturaltitanium",
+ color: "bg-gray-400",
+ iphone: @iphone %>
+ <%= render 'color_option',
+ value: "bluetitanium",
+ color: "bg-indigo-800",
+ iphone: @iphone %>
+ <%= render 'color_option',
+ value: "whitetitanium",
+ color: "bg-white",
+ iphone: @iphone %>
+ <%= render 'color_option',
+ value: "blacktitanium",
+ color: "bg-black",
+ iphone: @iphone %>
+ <% end %>
+ <% end %>
+
+
+<% end %>
diff --git a/app/views/layouts/iphone.html.erb b/app/views/layouts/iphone.html.erb
new file mode 100644
index 0000000..fe95937
--- /dev/null
+++ b/app/views/layouts/iphone.html.erb
@@ -0,0 +1,42 @@
+
+
+
+ <%= content_for(:title) || "Tailwind Rails" %>
+
+
+ <%= csrf_meta_tags %>
+ <%= csp_meta_tag %>
+
+ <%= yield :head %>
+
+
+
+
+
+ <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
+ <%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
+
+
+
+
+
+
<%= content_for(:breadcrumbs) %>
+ <%= yield %>
+
+
+
diff --git a/config/routes.rb b/config/routes.rb
index ca2a0d9..dc4ef49 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
+ resources :features
# 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.
@@ -14,14 +15,14 @@
resources :components, only: [ :index, :show ]
resources :hotels do
- resource :description, module: :hotels do
- member do
+ resources :features, module: :hotels do
+ collection do
get :room
get :restaurant
- get :amenities
+ get :service
get :basic_info
end
end
end
-
+ resource :iphone
end
diff --git a/db/migrate/20240907075950_create_features.rb b/db/migrate/20240907075950_create_features.rb
new file mode 100644
index 0000000..7b3f41a
--- /dev/null
+++ b/db/migrate/20240907075950_create_features.rb
@@ -0,0 +1,14 @@
+class CreateFeatures < ActiveRecord::Migration[7.2]
+ def change
+ create_table :features do |t|
+ t.string :tagline
+ t.string :description
+ t.string :category
+ t.string :image_path
+ t.integer :position
+ t.references :hotel, null: false, foreign_key: true
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 08819da..5670f3b 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,19 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.2].define(version: 2024_09_07_025333) do
+ActiveRecord::Schema[7.2].define(version: 2024_09_07_075950) do
+ create_table "features", force: :cascade do |t|
+ t.string "tagline"
+ t.string "description"
+ t.string "category"
+ t.string "image_path"
+ t.integer "position"
+ t.integer "hotel_id", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["hotel_id"], name: "index_features_on_hotel_id"
+ end
+
create_table "hotels", force: :cascade do |t|
t.string "name"
t.string "prefecture"
@@ -20,4 +32,6 @@
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
+
+ add_foreign_key "features", "hotels"
end
diff --git a/test/controllers/features_controller_test.rb b/test/controllers/features_controller_test.rb
new file mode 100644
index 0000000..791f128
--- /dev/null
+++ b/test/controllers/features_controller_test.rb
@@ -0,0 +1,48 @@
+require "test_helper"
+
+class FeaturesControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @feature = features(:one)
+ end
+
+ test "should get index" do
+ get features_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_feature_url
+ assert_response :success
+ end
+
+ test "should create feature" do
+ assert_difference("Feature.count") do
+ post features_url, params: { feature: { category: @feature.category, descrption: @feature.descrption, hotel_id: @feature.hotel_id, image_path: @feature.image_path, position: @feature.position, tagline: @feature.tagline } }
+ end
+
+ assert_redirected_to feature_url(Feature.last)
+ end
+
+ test "should show feature" do
+ get feature_url(@feature)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_feature_url(@feature)
+ assert_response :success
+ end
+
+ test "should update feature" do
+ patch feature_url(@feature), params: { feature: { category: @feature.category, descrption: @feature.descrption, hotel_id: @feature.hotel_id, image_path: @feature.image_path, position: @feature.position, tagline: @feature.tagline } }
+ assert_redirected_to feature_url(@feature)
+ end
+
+ test "should destroy feature" do
+ assert_difference("Feature.count", -1) do
+ delete feature_url(@feature)
+ end
+
+ assert_redirected_to features_url
+ end
+end
diff --git a/test/fixtures/features.yml b/test/fixtures/features.yml
new file mode 100644
index 0000000..1e35a5b
--- /dev/null
+++ b/test/fixtures/features.yml
@@ -0,0 +1,79 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+halekulani_topic1:
+ tagline: 天国の名にもっともふさわしい楽園へ
+ description:
+ ハワイの言葉で「天国にふさわしい館」を意味するハレクラニは、ワイキキビーチで100年以上にわたる歴史を重ね、世代を超えて多くのお客さまに愛されてきたホテルブランドです。その2つめのホテルとなるハレクラニ沖縄は、沖縄海岸国定公園として守られてきた恩納村の優雅な海辺で、新たな時代のラグジュアリーをご提供します。
+ category: topic
+ image_path: a_tpc01_190909.jpg.webp
+ position: 1
+ hotel: halekulani
+
+halekulani_topic2:
+ tagline: すべての客室がオーシャンビュー
+ description:
+ ハレクラニ沖縄では、ご滞在するすべてのお客様にオーシャンビューと沖縄の自然を満喫できる客室をご用意しております。
+ 全室50平米以上の白を基調としたリラックスした空間と、心地よい時間を過ごせるテラス付き。
+ ハレクラニのアイデンティティである「Seven Shades of White(7色の白)」のコンセプトを
+ 受け継ぎ、優美な白に満たされた滞在空間は、窓の外に広がる青く美しい世界をいっそう鮮やかに映し出します。
+ category: topic
+ image_path: a_tp_01_240808.jpg.webp
+ position: 2
+ hotel: halekulani
+
+halekulani_topic3:
+ tagline: 美しい空間デザイン
+ description:
+ リゾート内のあらゆる空間が、「ハレクラニ」の世界観をそのまま体現しています。陽気な楽園ムードに心が華やぐオールデイダイニング、落ち着きと風格を醸すステーキ&ワイン、ドラマティックなサンセットを満喫するバーなど、それぞれインテリアの趣は異なりますが、どの空間においても「優雅なおもてなし」を体感いただけるハレクラニスピリットが息づいています。
+ category: topic
+ image_path: a_tp_02_240808.jpg.webp
+ position: 3
+ hotel: halekulani
+
+halekulani_topic4:
+ tagline: スタッフの心からのホスピタリティ
+ description:
+ ハレクラニ沖縄で過ごすラグジュアリーな1日。この奇跡の楽園においては、あらゆるシーンに特別な時間が流れています。
+ ヴァカンス、ハネムーン、一人旅などお越しになる目的はさまざまでも、一貫して変わらないのは、スタッフの心からのホスピタリティ。ハレクラニの伝統的なおもてなしを大切にしながら、パーソナルでプロフェッショナルなサービスを体感いただけます。ハレクラニに愛着をもち、誇りと情熱を心に抱いて、お客さまをお迎えします。
+ category: topic
+ image_path: a_tp_03a_220622.jpg.webp
+ position: 4
+ hotel: halekulani
+
+halekulani_room1:
+ tagline: VILLAS
+ description:
+ 青い海が間近に広がるクリフトップには、プライベートプール(温水)と天然温泉を備えた5棟のヴィラがございます。
+ 頂点の贅沢を満喫しながら、まるで我が家のようなくつろぎを感じていただけます。
+ category: room
+ image_path: b_ss1_02_240808.jpg.webp
+ position: 1
+ hotel: halekulani
+
+halekulani_room2:
+ tagline: SUITES
+ description:
+ 絶佳の眺望を誇る広さ76平米のエグゼクティブオーシャン スイートから、贅沢の頂点を極めたペントハウスタイプのプライベートプールも備えた広さ294㎡のオーキッド スイートまで、まさに天国にふさわしい滞在をご提供します。
+ category: room
+ image_path: b_ss2_01_240808.jpg.webp
+ position: 2
+ hotel: halekulani
+
+halekulani_room3:
+ tagline: STANDARD ROOMS
+ description:
+ 新たなラグジュアリーのスタンダードとなるテラス付き広さ50平米のゲストルームは、ビーチフロントウイング、サンセットウイングに7つのタイプをご用意しました。お客さまの求める滞在スタイルに合わせて、お選びいただけます。
+ category: room
+ image_path: b_ss3_01_240808.jpg.webp
+ position: 3
+ hotel: halekulani
+
+halekulani_room4:
+ tagline: CLUB LOUNGE
+ description:
+ サンセットウィング5階には、クラブラウンジをご用意しました。プレミアクラブオーシャンフロント、ヴィラにご宿泊のお客さまが、ご利用いただけます。クラブラウンジレセプションには専任スタッフが常駐し、快適な滞在のお手伝いをいたします。
+ 心地よいテラス席も設けたラウンジ内では、終日シャンパンサービスをご堪能いただけます。また、朝食をお召し上がりいただけるほか、アフタヌーンティーやカクテルなどをご自由にお楽しみください。
+ category: room
+ image_path: b_ss4_01_240808.jpg.webp
+ position: 4
+ hotel: halekulani
diff --git a/test/fixtures/hotels.yml b/test/fixtures/hotels.yml
index ce16161..4e0d285 100644
--- a/test/fixtures/hotels.yml
+++ b/test/fixtures/hotels.yml
@@ -1,6 +1,6 @@
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
-haleclani:
+halekulani:
name: ハレクラニ沖縄
prefecture: 沖縄県
city: 恩納村
diff --git a/test/models/feature_test.rb b/test/models/feature_test.rb
new file mode 100644
index 0000000..f805a7f
--- /dev/null
+++ b/test/models/feature_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class FeatureTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/system/features_test.rb b/test/system/features_test.rb
new file mode 100644
index 0000000..f28a26e
--- /dev/null
+++ b/test/system/features_test.rb
@@ -0,0 +1,51 @@
+require "application_system_test_case"
+
+class FeaturesTest < ApplicationSystemTestCase
+ setup do
+ @feature = features(:one)
+ end
+
+ test "visiting the index" do
+ visit features_url
+ assert_selector "h1", text: "Features"
+ end
+
+ test "should create feature" do
+ visit features_url
+ click_on "New feature"
+
+ fill_in "Category", with: @feature.category
+ fill_in "Descrption", with: @feature.descrption
+ fill_in "Hotel", with: @feature.hotel_id
+ fill_in "Image path", with: @feature.image_path
+ fill_in "Position", with: @feature.position
+ fill_in "Tagline", with: @feature.tagline
+ click_on "Create Feature"
+
+ assert_text "Feature was successfully created"
+ click_on "Back"
+ end
+
+ test "should update Feature" do
+ visit feature_url(@feature)
+ click_on "Edit this feature", match: :first
+
+ fill_in "Category", with: @feature.category
+ fill_in "Descrption", with: @feature.descrption
+ fill_in "Hotel", with: @feature.hotel_id
+ fill_in "Image path", with: @feature.image_path
+ fill_in "Position", with: @feature.position
+ fill_in "Tagline", with: @feature.tagline
+ click_on "Update Feature"
+
+ assert_text "Feature was successfully updated"
+ click_on "Back"
+ end
+
+ test "should destroy Feature" do
+ visit feature_url(@feature)
+ click_on "Destroy this feature", match: :first
+
+ assert_text "Feature was successfully destroyed"
+ end
+end