diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 4eb57e0..10e5a25 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,7 +5,11 @@
-
+
+
+
+
+
@@ -154,7 +158,8 @@
-
+
+
diff --git a/Gemfile b/Gemfile
index 9efd3bf..d4bb5fa 100644
--- a/Gemfile
+++ b/Gemfile
@@ -45,6 +45,9 @@ gem "tzinfo-data", platforms: %i[ windows jruby ]
gem "bootsnap", require: false
+gem 'stimulus-rails'
+gem "hotwire_combobox"
+
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
# gem "image_processing", "~> 1.2"
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 09705d1..8b6a04c 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,2 +1,9 @@
class ApplicationController < ActionController::Base
+
+ private
+ def set_company
+ company_id = session.fetch(:company_id, Company.first&.id)
+ session[:company_id] = company_id
+ @company = Company.find(session[:company_id])
+ end
end
diff --git a/app/controllers/customers_controller.rb b/app/controllers/customers_controller.rb
new file mode 100644
index 0000000..4c7eadf
--- /dev/null
+++ b/app/controllers/customers_controller.rb
@@ -0,0 +1,72 @@
+class CustomersController < ApplicationController
+ before_action :set_company
+ before_action :set_customer, only: %i[ show edit update destroy ]
+
+ # GET /customers or /customers.json
+ def index
+ @customers = Customer.all
+ end
+
+ # GET /customers/1 or /customers/1.json
+ def show
+ end
+
+ # GET /customers/new
+ def new
+ @customer = Customer.new
+ end
+
+ # GET /customers/1/edit
+ def edit
+ end
+
+ # POST /customers or /customers.json
+ def create
+ @customer = Customer.new(customer_params)
+ @customer.company = @company
+
+ respond_to do |format|
+ if @customer.save
+ format.html { redirect_to customer_url(@customer), notice: "Customer was successfully created." }
+ format.json { render :show, status: :created, location: @customer }
+ else
+ format.html { render :new, status: :unprocessable_entity }
+ format.json { render json: @customer.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /customers/1 or /customers/1.json
+ def update
+ respond_to do |format|
+ if @customer.update(customer_params)
+ format.html { redirect_to customer_url(@customer), notice: "Customer was successfully updated." }
+ format.json { render :show, status: :ok, location: @customer }
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ format.json { render json: @customer.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /customers/1 or /customers/1.json
+ def destroy
+ @customer.destroy!
+
+ respond_to do |format|
+ format.html { redirect_to customers_url, notice: "Customer was successfully destroyed." }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_customer
+ @customer = Customer.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def customer_params
+ params.require(:customer).permit(:name, :phone, :notes, :email, :birthyear)
+ end
+end
diff --git a/app/controllers/places_controller.rb b/app/controllers/places_controller.rb
new file mode 100644
index 0000000..ed7d68c
--- /dev/null
+++ b/app/controllers/places_controller.rb
@@ -0,0 +1,72 @@
+class PlacesController < ApplicationController
+ before_action :set_company
+ before_action :set_place, only: %i[ show edit update destroy ]
+
+ # GET /places or /places.json
+ def index
+ @places = Place.all
+ end
+
+ # GET /places/1 or /places/1.json
+ def show
+ end
+
+ # GET /places/new
+ def new
+ @place = Place.new
+ end
+
+ # GET /places/1/edit
+ def edit
+ end
+
+ # POST /places or /places.json
+ def create
+ @place = Place.new(place_params)
+ @place.company = @company
+
+ respond_to do |format|
+ if @place.save
+ format.html { redirect_to place_url(@place), notice: "Place was successfully created." }
+ format.json { render :show, status: :created, location: @place }
+ else
+ format.html { render :new, status: :unprocessable_entity }
+ format.json { render json: @place.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /places/1 or /places/1.json
+ def update
+ respond_to do |format|
+ if @place.update(place_params)
+ format.html { redirect_to place_url(@place), notice: "Place was successfully updated." }
+ format.json { render :show, status: :ok, location: @place }
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ format.json { render json: @place.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /places/1 or /places/1.json
+ def destroy
+ @place.destroy!
+
+ respond_to do |format|
+ format.html { redirect_to places_url, notice: "Place was successfully destroyed." }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_place
+ @place = Place.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def place_params
+ params.require(:place).permit(:name, :company_id)
+ end
+end
diff --git a/app/controllers/reservations_controller.rb b/app/controllers/reservations_controller.rb
new file mode 100644
index 0000000..4012eb0
--- /dev/null
+++ b/app/controllers/reservations_controller.rb
@@ -0,0 +1,73 @@
+class ReservationsController < ApplicationController
+ before_action :set_company
+ before_action :set_reservation, only: %i[ show edit update destroy ]
+
+ # GET /reservations or /reservations.json
+ def index
+ @reservations = Reservation.all
+ end
+
+ # GET /reservations/1 or /reservations/1.json
+ def show
+ end
+
+ # GET /reservations/new
+ def new
+ @reservation = Reservation.new
+ @reservation.place = @company.places.first
+ end
+
+ # GET /reservations/1/edit
+ def edit
+ end
+
+ # POST /reservations or /reservations.json
+ def create
+ @reservation = Reservation.new(reservation_params)
+ @reservation.company = @company
+
+ respond_to do |format|
+ if @reservation.save
+ format.html { redirect_to reservation_url(@reservation), notice: "Reservation was successfully created." }
+ format.json { render :show, status: :created, location: @reservation }
+ else
+ format.html { render :new, status: :unprocessable_entity }
+ format.json { render json: @reservation.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /reservations/1 or /reservations/1.json
+ def update
+ respond_to do |format|
+ if @reservation.update(reservation_params)
+ format.html { redirect_to reservation_url(@reservation), notice: "Reservation was successfully updated." }
+ format.json { render :show, status: :ok, location: @reservation }
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ format.json { render json: @reservation.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /reservations/1 or /reservations/1.json
+ def destroy
+ @reservation.destroy!
+
+ respond_to do |format|
+ format.html { redirect_to reservations_url, notice: "Reservation was successfully destroyed." }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_reservation
+ @reservation = Reservation.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def reservation_params
+ params.require(:reservation).permit(:company_id, :customer_id, :place_id, :title, :description, :start_time, :end_time)
+ end
+end
diff --git a/app/helpers/customers_helper.rb b/app/helpers/customers_helper.rb
new file mode 100644
index 0000000..a07ce29
--- /dev/null
+++ b/app/helpers/customers_helper.rb
@@ -0,0 +1,2 @@
+module CustomersHelper
+end
diff --git a/app/helpers/places_helper.rb b/app/helpers/places_helper.rb
new file mode 100644
index 0000000..7d8d0ac
--- /dev/null
+++ b/app/helpers/places_helper.rb
@@ -0,0 +1,2 @@
+module PlacesHelper
+end
diff --git a/app/helpers/reservations_helper.rb b/app/helpers/reservations_helper.rb
new file mode 100644
index 0000000..f28b699
--- /dev/null
+++ b/app/helpers/reservations_helper.rb
@@ -0,0 +1,2 @@
+module ReservationsHelper
+end
diff --git a/app/models/company.rb b/app/models/company.rb
index a149860..baff233 100644
--- a/app/models/company.rb
+++ b/app/models/company.rb
@@ -1,2 +1,5 @@
class Company < ApplicationRecord
+ has_many :customers, dependent: :destroy
+ has_many :reservations, dependent: :destroy
+ has_many :places, dependent: :destroy
end
diff --git a/app/models/customer.rb b/app/models/customer.rb
new file mode 100644
index 0000000..ebc5777
--- /dev/null
+++ b/app/models/customer.rb
@@ -0,0 +1,7 @@
+class Customer < ApplicationRecord
+ belongs_to :company
+
+ validates :name, presence: true, uniqueness: { scope: :company_id }
+ validates :phone, presence: true
+ validates :company_id, presence: true
+end
diff --git a/app/models/place.rb b/app/models/place.rb
new file mode 100644
index 0000000..ab192e4
--- /dev/null
+++ b/app/models/place.rb
@@ -0,0 +1,3 @@
+class Place < ApplicationRecord
+ belongs_to :company
+end
diff --git a/app/models/reservation.rb b/app/models/reservation.rb
new file mode 100644
index 0000000..93c1b16
--- /dev/null
+++ b/app/models/reservation.rb
@@ -0,0 +1,9 @@
+class Reservation < ApplicationRecord
+ belongs_to :company
+ belongs_to :customer
+ belongs_to :place
+
+ validates :company_id, presence: true
+ validates :customer_id, presence: true
+ validates :place_id, presence: true
+end
diff --git a/app/views/customers/_customer.html.erb b/app/views/customers/_customer.html.erb
new file mode 100644
index 0000000..0957736
--- /dev/null
+++ b/app/views/customers/_customer.html.erb
@@ -0,0 +1,27 @@
+
+
+ Name:
+ <%= customer.name %>
+
+
+
+ Phone:
+ <%= customer.phone %>
+
+
+
+ Notes:
+ <%= customer.notes %>
+
+
+
+ Email:
+ <%= customer.email %>
+
+
+
+ Birthyear:
+ <%= customer.birthyear %>
+
+
+
diff --git a/app/views/customers/_customer.json.jbuilder b/app/views/customers/_customer.json.jbuilder
new file mode 100644
index 0000000..910c03d
--- /dev/null
+++ b/app/views/customers/_customer.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! customer, :id, :name, :phone, :notes, :email, :birthyear, :created_at, :updated_at
+json.url customer_url(customer, format: :json)
diff --git a/app/views/customers/_form.html.erb b/app/views/customers/_form.html.erb
new file mode 100644
index 0000000..63b5b59
--- /dev/null
+++ b/app/views/customers/_form.html.erb
@@ -0,0 +1,42 @@
+<%= form_with(model: customer, class: "contents") do |form| %>
+ <% if customer.errors.any? %>
+
+
<%= pluralize(customer.errors.count, "error") %> prohibited this customer from being saved:
+
+
+ <% customer.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :name %>
+ <%= form.text_field :name, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.label :phone %>
+ <%= form.text_field :phone, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.label :notes %>
+ <%= form.text_area :notes, rows: 4, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.label :email %>
+ <%= form.text_field :email, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.label :birthyear %>
+ <%= form.number_field :birthyear, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.submit class: "rounded-lg py-3 px-5 bg-blue-600 text-white inline-block font-medium cursor-pointer" %>
+
+<% end %>
diff --git a/app/views/customers/edit.html.erb b/app/views/customers/edit.html.erb
new file mode 100644
index 0000000..aab356b
--- /dev/null
+++ b/app/views/customers/edit.html.erb
@@ -0,0 +1,8 @@
+
+
Editing customer
+
+ <%= render "form", customer: @customer %>
+
+ <%= link_to "Show this customer", @customer, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+ <%= link_to "Back to customers", customers_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
diff --git a/app/views/customers/index.html.erb b/app/views/customers/index.html.erb
new file mode 100644
index 0000000..20d5c7d
--- /dev/null
+++ b/app/views/customers/index.html.erb
@@ -0,0 +1,21 @@
+
+ <% if notice.present? %>
+
<%= notice %>
+ <% end %>
+
+ <% content_for :title, "Customers" %>
+
+
+
Customers
+ <%= link_to "New customer", new_customer_path, class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %>
+
+
+
+ <% @customers.each do |customer| %>
+ <%= render customer %>
+
+ <%= link_to "Show this customer", customer, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
+ <% end %>
+
+
diff --git a/app/views/customers/index.json.jbuilder b/app/views/customers/index.json.jbuilder
new file mode 100644
index 0000000..328edbd
--- /dev/null
+++ b/app/views/customers/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @customers, partial: "customers/customer", as: :customer
diff --git a/app/views/customers/new.html.erb b/app/views/customers/new.html.erb
new file mode 100644
index 0000000..9f3026e
--- /dev/null
+++ b/app/views/customers/new.html.erb
@@ -0,0 +1,7 @@
+
+
New customer
+
+ <%= render "form", customer: @customer %>
+
+ <%= link_to "Back to customers", customers_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
diff --git a/app/views/customers/show.html.erb b/app/views/customers/show.html.erb
new file mode 100644
index 0000000..585ba4f
--- /dev/null
+++ b/app/views/customers/show.html.erb
@@ -0,0 +1,15 @@
+
+
+ <% if notice.present? %>
+
<%= notice %>
+ <% end %>
+
+ <%= render @customer %>
+
+ <%= link_to "Edit this customer", edit_customer_path(@customer), class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+ <%= link_to "Back to customers", customers_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
+ <%= button_to "Destroy this customer", @customer, method: :delete, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %>
+
+
+
diff --git a/app/views/customers/show.json.jbuilder b/app/views/customers/show.json.jbuilder
new file mode 100644
index 0000000..14cfc83
--- /dev/null
+++ b/app/views/customers/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "customers/customer", customer: @customer
diff --git a/app/views/places/_form.html.erb b/app/views/places/_form.html.erb
new file mode 100644
index 0000000..f51e1c7
--- /dev/null
+++ b/app/views/places/_form.html.erb
@@ -0,0 +1,22 @@
+<%= form_with(model: place, class: "contents") do |form| %>
+ <% if place.errors.any? %>
+
+
<%= pluralize(place.errors.count, "error") %> prohibited this place from being saved:
+
+
+ <% place.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :name %>
+ <%= form.text_field :name, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.submit class: "rounded-lg py-3 px-5 bg-blue-600 text-white inline-block font-medium cursor-pointer" %>
+
+<% end %>
diff --git a/app/views/places/_place.html.erb b/app/views/places/_place.html.erb
new file mode 100644
index 0000000..30aa3a9
--- /dev/null
+++ b/app/views/places/_place.html.erb
@@ -0,0 +1,12 @@
+
+
+ Name:
+ <%= place.name %>
+
+
+
+ Company:
+ <%= place.company_id %>
+
+
+
diff --git a/app/views/places/_place.json.jbuilder b/app/views/places/_place.json.jbuilder
new file mode 100644
index 0000000..ff5cba9
--- /dev/null
+++ b/app/views/places/_place.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! place, :id, :name, :company_id, :created_at, :updated_at
+json.url place_url(place, format: :json)
diff --git a/app/views/places/edit.html.erb b/app/views/places/edit.html.erb
new file mode 100644
index 0000000..b0ff29d
--- /dev/null
+++ b/app/views/places/edit.html.erb
@@ -0,0 +1,8 @@
+
+
Editing place
+
+ <%= render "form", place: @place %>
+
+ <%= link_to "Show this place", @place, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+ <%= link_to "Back to places", places_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
diff --git a/app/views/places/index.html.erb b/app/views/places/index.html.erb
new file mode 100644
index 0000000..3dfe864
--- /dev/null
+++ b/app/views/places/index.html.erb
@@ -0,0 +1,21 @@
+
+ <% if notice.present? %>
+
<%= notice %>
+ <% end %>
+
+ <% content_for :title, "Places" %>
+
+
+
Places
+ <%= link_to "New place", new_place_path, class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %>
+
+
+
+ <% @places.each do |place| %>
+ <%= render place %>
+
+ <%= link_to "Show this place", place, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
+ <% end %>
+
+
diff --git a/app/views/places/index.json.jbuilder b/app/views/places/index.json.jbuilder
new file mode 100644
index 0000000..f1d6b30
--- /dev/null
+++ b/app/views/places/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @places, partial: "places/place", as: :place
diff --git a/app/views/places/new.html.erb b/app/views/places/new.html.erb
new file mode 100644
index 0000000..c7048cf
--- /dev/null
+++ b/app/views/places/new.html.erb
@@ -0,0 +1,7 @@
+
+
New place
+
+ <%= render "form", place: @place %>
+
+ <%= link_to "Back to places", places_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
diff --git a/app/views/places/show.html.erb b/app/views/places/show.html.erb
new file mode 100644
index 0000000..117e226
--- /dev/null
+++ b/app/views/places/show.html.erb
@@ -0,0 +1,15 @@
+
+
+ <% if notice.present? %>
+
<%= notice %>
+ <% end %>
+
+ <%= render @place %>
+
+ <%= link_to "Edit this place", edit_place_path(@place), class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+ <%= link_to "Back to places", places_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
+ <%= button_to "Destroy this place", @place, method: :delete, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %>
+
+
+
diff --git a/app/views/places/show.json.jbuilder b/app/views/places/show.json.jbuilder
new file mode 100644
index 0000000..e038dff
--- /dev/null
+++ b/app/views/places/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "places/place", place: @place
diff --git a/app/views/reservations/_form.html.erb b/app/views/reservations/_form.html.erb
new file mode 100644
index 0000000..0335a9c
--- /dev/null
+++ b/app/views/reservations/_form.html.erb
@@ -0,0 +1,47 @@
+<%= form_with(model: reservation, class: "contents") do |form| %>
+ <% if reservation.errors.any? %>
+
+
<%= pluralize(reservation.errors.count, "error") %> prohibited this reservation from being saved:
+
+
+ <% reservation.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :customer_id %>
+ <%= form.collection_select :customer_id, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.label :place_id %>
+ <%= form.collection_select :place_id, @company.places, :id, :name, prompt: "Select a Place", class:"block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.label :title %>
+ <%= form.text_field :title, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.label :description %>
+ <%= form.text_area :description, rows: 4, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.label :start_time %>`
+ <%= form.datetime_field :start_time, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.label :end_time %>
+ <%= form.datetime_field :end_time, class: "block shadow rounded-md border border-gray-400 outline-none px-3 py-2 mt-2 w-full" %>
+
+
+
+ <%= form.submit class: "rounded-lg py-3 px-5 bg-blue-600 text-white inline-block font-medium cursor-pointer" %>
+
+<% end %>
diff --git a/app/views/reservations/_reservation.html.erb b/app/views/reservations/_reservation.html.erb
new file mode 100644
index 0000000..1187b42
--- /dev/null
+++ b/app/views/reservations/_reservation.html.erb
@@ -0,0 +1,37 @@
+
+
+ Company:
+ <%= reservation.company_id %>
+
+
+
+ Customer:
+ <%= reservation.customer_id %>
+
+
+
+ Place:
+ <%= reservation.place_id %>
+
+
+
+ Title:
+ <%= reservation.title %>
+
+
+
+ Description:
+ <%= reservation.description %>
+
+
+
+ Start time:
+ <%= reservation.start_time %>
+
+
+
+ End time:
+ <%= reservation.end_time %>
+
+
+
diff --git a/app/views/reservations/_reservation.json.jbuilder b/app/views/reservations/_reservation.json.jbuilder
new file mode 100644
index 0000000..83db571
--- /dev/null
+++ b/app/views/reservations/_reservation.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! reservation, :id, :company_id, :customer_id, :place_id, :title, :description, :start_time, :end_time, :created_at, :updated_at
+json.url reservation_url(reservation, format: :json)
diff --git a/app/views/reservations/edit.html.erb b/app/views/reservations/edit.html.erb
new file mode 100644
index 0000000..05edde3
--- /dev/null
+++ b/app/views/reservations/edit.html.erb
@@ -0,0 +1,8 @@
+
+
Editing reservation
+
+ <%= render "form", reservation: @reservation %>
+
+ <%= link_to "Show this reservation", @reservation, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+ <%= link_to "Back to reservations", reservations_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
diff --git a/app/views/reservations/index.html.erb b/app/views/reservations/index.html.erb
new file mode 100644
index 0000000..9410147
--- /dev/null
+++ b/app/views/reservations/index.html.erb
@@ -0,0 +1,21 @@
+
+ <% if notice.present? %>
+
<%= notice %>
+ <% end %>
+
+ <% content_for :title, "Reservations" %>
+
+
+
Reservations
+ <%= link_to "New reservation", new_reservation_path, class: "rounded-lg py-3 px-5 bg-blue-600 text-white block font-medium" %>
+
+
+
+ <% @reservations.each do |reservation| %>
+ <%= render reservation %>
+
+ <%= link_to "Show this reservation", reservation, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
+ <% end %>
+
+
diff --git a/app/views/reservations/index.json.jbuilder b/app/views/reservations/index.json.jbuilder
new file mode 100644
index 0000000..14b6b3c
--- /dev/null
+++ b/app/views/reservations/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @reservations, partial: "reservations/reservation", as: :reservation
diff --git a/app/views/reservations/new.html.erb b/app/views/reservations/new.html.erb
new file mode 100644
index 0000000..9c7b7c5
--- /dev/null
+++ b/app/views/reservations/new.html.erb
@@ -0,0 +1,7 @@
+
+
New reservation
+
+ <%= render "form", reservation: @reservation %>
+
+ <%= link_to "Back to reservations", reservations_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
diff --git a/app/views/reservations/show.html.erb b/app/views/reservations/show.html.erb
new file mode 100644
index 0000000..46c1665
--- /dev/null
+++ b/app/views/reservations/show.html.erb
@@ -0,0 +1,15 @@
+
+
+ <% if notice.present? %>
+
<%= notice %>
+ <% end %>
+
+ <%= render @reservation %>
+
+ <%= link_to "Edit this reservation", edit_reservation_path(@reservation), class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+ <%= link_to "Back to reservations", reservations_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
+
+ <%= button_to "Destroy this reservation", @reservation, method: :delete, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %>
+
+
+
diff --git a/app/views/reservations/show.json.jbuilder b/app/views/reservations/show.json.jbuilder
new file mode 100644
index 0000000..f6e6ba5
--- /dev/null
+++ b/app/views/reservations/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "reservations/reservation", reservation: @reservation
diff --git a/config/routes.rb b/config/routes.rb
index 373c702..073193e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,7 @@
Rails.application.routes.draw do
+ resources :reservations
+ resources :places
+ resources :customers
resources :companies
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
diff --git a/db/migrate/20240804052139_create_customers.rb b/db/migrate/20240804052139_create_customers.rb
new file mode 100644
index 0000000..7a59569
--- /dev/null
+++ b/db/migrate/20240804052139_create_customers.rb
@@ -0,0 +1,13 @@
+class CreateCustomers < ActiveRecord::Migration[7.1]
+ def change
+ create_table :customers do |t|
+ t.string :name
+ t.string :phone
+ t.text :notes
+ t.string :email
+ t.integer :birthyear
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20240804053208_add_company_id_to_customers.rb b/db/migrate/20240804053208_add_company_id_to_customers.rb
new file mode 100644
index 0000000..fcc0ce9
--- /dev/null
+++ b/db/migrate/20240804053208_add_company_id_to_customers.rb
@@ -0,0 +1,5 @@
+class AddCompanyIdToCustomers < ActiveRecord::Migration[7.1]
+ def change
+ add_column :customers, :company_id, :integer
+ end
+end
diff --git a/db/migrate/20240804060103_create_places.rb b/db/migrate/20240804060103_create_places.rb
new file mode 100644
index 0000000..2104f25
--- /dev/null
+++ b/db/migrate/20240804060103_create_places.rb
@@ -0,0 +1,10 @@
+class CreatePlaces < ActiveRecord::Migration[7.1]
+ def change
+ create_table :places do |t|
+ t.string :name
+ t.references :company, null: false, foreign_key: true
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20240804060112_create_reservations.rb b/db/migrate/20240804060112_create_reservations.rb
new file mode 100644
index 0000000..8298f92
--- /dev/null
+++ b/db/migrate/20240804060112_create_reservations.rb
@@ -0,0 +1,15 @@
+class CreateReservations < ActiveRecord::Migration[7.1]
+ def change
+ create_table :reservations do |t|
+ t.references :company, null: false, foreign_key: true
+ t.references :customer, null: false, foreign_key: true
+ t.references :place, null: false, foreign_key: true
+ t.string :title
+ t.text :description
+ t.datetime :start_time
+ t.datetime :end_time
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 44c6331..4269b72 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2024_05_18_200749) do
+ActiveRecord::Schema[7.1].define(version: 2024_08_04_060112) do
create_table "companies", force: :cascade do |t|
t.string "name"
t.string "id_number"
@@ -25,4 +25,42 @@ ActiveRecord::Schema[7.1].define(version: 2024_05_18_200749) do
t.datetime "updated_at", null: false
end
+ create_table "customers", force: :cascade do |t|
+ t.string "name"
+ t.string "phone"
+ t.text "notes"
+ t.string "email"
+ t.integer "birthyear"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.integer "company_id"
+ end
+
+ create_table "places", force: :cascade do |t|
+ t.string "name"
+ t.integer "company_id", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["company_id"], name: "index_places_on_company_id"
+ end
+
+ create_table "reservations", force: :cascade do |t|
+ t.integer "company_id", null: false
+ t.integer "customer_id", null: false
+ t.integer "place_id", null: false
+ t.string "title"
+ t.text "description"
+ t.datetime "start_time"
+ t.datetime "end_time"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["company_id"], name: "index_reservations_on_company_id"
+ t.index ["customer_id"], name: "index_reservations_on_customer_id"
+ t.index ["place_id"], name: "index_reservations_on_place_id"
+ end
+
+ add_foreign_key "places", "companies"
+ add_foreign_key "reservations", "companies"
+ add_foreign_key "reservations", "customers"
+ add_foreign_key "reservations", "places"
end
diff --git a/test/controllers/customers_controller_test.rb b/test/controllers/customers_controller_test.rb
new file mode 100644
index 0000000..b932686
--- /dev/null
+++ b/test/controllers/customers_controller_test.rb
@@ -0,0 +1,48 @@
+require "test_helper"
+
+class CustomersControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @customer = customers(:one)
+ end
+
+ test "should get index" do
+ get customers_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_customer_url
+ assert_response :success
+ end
+
+ test "should create customer" do
+ assert_difference("Customer.count") do
+ post customers_url, params: { customer: { birthyear: @customer.birthyear, email: @customer.email, name: @customer.name, notes: @customer.notes, phone: @customer.phone } }
+ end
+
+ assert_redirected_to customer_url(Customer.last)
+ end
+
+ test "should show customer" do
+ get customer_url(@customer)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_customer_url(@customer)
+ assert_response :success
+ end
+
+ test "should update customer" do
+ patch customer_url(@customer), params: { customer: { birthyear: @customer.birthyear, email: @customer.email, name: @customer.name, notes: @customer.notes, phone: @customer.phone } }
+ assert_redirected_to customer_url(@customer)
+ end
+
+ test "should destroy customer" do
+ assert_difference("Customer.count", -1) do
+ delete customer_url(@customer)
+ end
+
+ assert_redirected_to customers_url
+ end
+end
diff --git a/test/controllers/places_controller_test.rb b/test/controllers/places_controller_test.rb
new file mode 100644
index 0000000..1e8661b
--- /dev/null
+++ b/test/controllers/places_controller_test.rb
@@ -0,0 +1,48 @@
+require "test_helper"
+
+class PlacesControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @place = places(:one)
+ end
+
+ test "should get index" do
+ get places_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_place_url
+ assert_response :success
+ end
+
+ test "should create place" do
+ assert_difference("Place.count") do
+ post places_url, params: { place: { company_id: @place.company_id, name: @place.name } }
+ end
+
+ assert_redirected_to place_url(Place.last)
+ end
+
+ test "should show place" do
+ get place_url(@place)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_place_url(@place)
+ assert_response :success
+ end
+
+ test "should update place" do
+ patch place_url(@place), params: { place: { company_id: @place.company_id, name: @place.name } }
+ assert_redirected_to place_url(@place)
+ end
+
+ test "should destroy place" do
+ assert_difference("Place.count", -1) do
+ delete place_url(@place)
+ end
+
+ assert_redirected_to places_url
+ end
+end
diff --git a/test/controllers/reservations_controller_test.rb b/test/controllers/reservations_controller_test.rb
new file mode 100644
index 0000000..5060b13
--- /dev/null
+++ b/test/controllers/reservations_controller_test.rb
@@ -0,0 +1,48 @@
+require "test_helper"
+
+class ReservationsControllerTest < ActionDispatch::IntegrationTest
+ setup do
+ @reservation = reservations(:one)
+ end
+
+ test "should get index" do
+ get reservations_url
+ assert_response :success
+ end
+
+ test "should get new" do
+ get new_reservation_url
+ assert_response :success
+ end
+
+ test "should create reservation" do
+ assert_difference("Reservation.count") do
+ post reservations_url, params: { reservation: { company_id: @reservation.company_id, customer_id: @reservation.customer_id, description: @reservation.description, end_time: @reservation.end_time, place_id: @reservation.place_id, start_time: @reservation.start_time, title: @reservation.title } }
+ end
+
+ assert_redirected_to reservation_url(Reservation.last)
+ end
+
+ test "should show reservation" do
+ get reservation_url(@reservation)
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get edit_reservation_url(@reservation)
+ assert_response :success
+ end
+
+ test "should update reservation" do
+ patch reservation_url(@reservation), params: { reservation: { company_id: @reservation.company_id, customer_id: @reservation.customer_id, description: @reservation.description, end_time: @reservation.end_time, place_id: @reservation.place_id, start_time: @reservation.start_time, title: @reservation.title } }
+ assert_redirected_to reservation_url(@reservation)
+ end
+
+ test "should destroy reservation" do
+ assert_difference("Reservation.count", -1) do
+ delete reservation_url(@reservation)
+ end
+
+ assert_redirected_to reservations_url
+ end
+end
diff --git a/test/fixtures/customers.yml b/test/fixtures/customers.yml
new file mode 100644
index 0000000..c5ea622
--- /dev/null
+++ b/test/fixtures/customers.yml
@@ -0,0 +1,15 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+ phone: MyString
+ notes: MyText
+ email: MyString
+ birthyear: 1
+
+two:
+ name: MyString
+ phone: MyString
+ notes: MyText
+ email: MyString
+ birthyear: 1
diff --git a/test/fixtures/places.yml b/test/fixtures/places.yml
new file mode 100644
index 0000000..d01926e
--- /dev/null
+++ b/test/fixtures/places.yml
@@ -0,0 +1,9 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ name: MyString
+ company: one
+
+two:
+ name: MyString
+ company: two
diff --git a/test/fixtures/reservations.yml b/test/fixtures/reservations.yml
new file mode 100644
index 0000000..0756506
--- /dev/null
+++ b/test/fixtures/reservations.yml
@@ -0,0 +1,19 @@
+# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
+
+one:
+ company: one
+ customer: one
+ place: one
+ title: MyString
+ description: MyText
+ start_time: 2024-08-04 08:01:12
+ end_time: 2024-08-04 08:01:12
+
+two:
+ company: two
+ customer: two
+ place: two
+ title: MyString
+ description: MyText
+ start_time: 2024-08-04 08:01:12
+ end_time: 2024-08-04 08:01:12
diff --git a/test/models/customer_test.rb b/test/models/customer_test.rb
new file mode 100644
index 0000000..8c83c4d
--- /dev/null
+++ b/test/models/customer_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class CustomerTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/place_test.rb b/test/models/place_test.rb
new file mode 100644
index 0000000..9f5cd09
--- /dev/null
+++ b/test/models/place_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class PlaceTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/models/reservation_test.rb b/test/models/reservation_test.rb
new file mode 100644
index 0000000..1d04a16
--- /dev/null
+++ b/test/models/reservation_test.rb
@@ -0,0 +1,7 @@
+require "test_helper"
+
+class ReservationTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
diff --git a/test/system/customers_test.rb b/test/system/customers_test.rb
new file mode 100644
index 0000000..63885e5
--- /dev/null
+++ b/test/system/customers_test.rb
@@ -0,0 +1,49 @@
+require "application_system_test_case"
+
+class CustomersTest < ApplicationSystemTestCase
+ setup do
+ @customer = customers(:one)
+ end
+
+ test "visiting the index" do
+ visit customers_url
+ assert_selector "h1", text: "Customers"
+ end
+
+ test "should create customer" do
+ visit customers_url
+ click_on "New customer"
+
+ fill_in "Birthyear", with: @customer.birthyear
+ fill_in "Email", with: @customer.email
+ fill_in "Name", with: @customer.name
+ fill_in "Notes", with: @customer.notes
+ fill_in "Phone", with: @customer.phone
+ click_on "Create Customer"
+
+ assert_text "Customer was successfully created"
+ click_on "Back"
+ end
+
+ test "should update Customer" do
+ visit customer_url(@customer)
+ click_on "Edit this customer", match: :first
+
+ fill_in "Birthyear", with: @customer.birthyear
+ fill_in "Email", with: @customer.email
+ fill_in "Name", with: @customer.name
+ fill_in "Notes", with: @customer.notes
+ fill_in "Phone", with: @customer.phone
+ click_on "Update Customer"
+
+ assert_text "Customer was successfully updated"
+ click_on "Back"
+ end
+
+ test "should destroy Customer" do
+ visit customer_url(@customer)
+ click_on "Destroy this customer", match: :first
+
+ assert_text "Customer was successfully destroyed"
+ end
+end
diff --git a/test/system/places_test.rb b/test/system/places_test.rb
new file mode 100644
index 0000000..813cce5
--- /dev/null
+++ b/test/system/places_test.rb
@@ -0,0 +1,43 @@
+require "application_system_test_case"
+
+class PlacesTest < ApplicationSystemTestCase
+ setup do
+ @place = places(:one)
+ end
+
+ test "visiting the index" do
+ visit places_url
+ assert_selector "h1", text: "Places"
+ end
+
+ test "should create place" do
+ visit places_url
+ click_on "New place"
+
+ fill_in "Company", with: @place.company_id
+ fill_in "Name", with: @place.name
+ click_on "Create Place"
+
+ assert_text "Place was successfully created"
+ click_on "Back"
+ end
+
+ test "should update Place" do
+ visit place_url(@place)
+ click_on "Edit this place", match: :first
+
+ fill_in "Company", with: @place.company_id
+ fill_in "Name", with: @place.name
+ click_on "Update Place"
+
+ assert_text "Place was successfully updated"
+ click_on "Back"
+ end
+
+ test "should destroy Place" do
+ visit place_url(@place)
+ click_on "Destroy this place", match: :first
+
+ assert_text "Place was successfully destroyed"
+ end
+end
diff --git a/test/system/reservations_test.rb b/test/system/reservations_test.rb
new file mode 100644
index 0000000..a718d57
--- /dev/null
+++ b/test/system/reservations_test.rb
@@ -0,0 +1,53 @@
+require "application_system_test_case"
+
+class ReservationsTest < ApplicationSystemTestCase
+ setup do
+ @reservation = reservations(:one)
+ end
+
+ test "visiting the index" do
+ visit reservations_url
+ assert_selector "h1", text: "Reservations"
+ end
+
+ test "should create reservation" do
+ visit reservations_url
+ click_on "New reservation"
+
+ fill_in "Company", with: @reservation.company_id
+ fill_in "Customer", with: @reservation.customer_id
+ fill_in "Description", with: @reservation.description
+ fill_in "End time", with: @reservation.end_time
+ fill_in "Place", with: @reservation.place_id
+ fill_in "Start time", with: @reservation.start_time
+ fill_in "Title", with: @reservation.title
+ click_on "Create Reservation"
+
+ assert_text "Reservation was successfully created"
+ click_on "Back"
+ end
+
+ test "should update Reservation" do
+ visit reservation_url(@reservation)
+ click_on "Edit this reservation", match: :first
+
+ fill_in "Company", with: @reservation.company_id
+ fill_in "Customer", with: @reservation.customer_id
+ fill_in "Description", with: @reservation.description
+ fill_in "End time", with: @reservation.end_time
+ fill_in "Place", with: @reservation.place_id
+ fill_in "Start time", with: @reservation.start_time
+ fill_in "Title", with: @reservation.title
+ click_on "Update Reservation"
+
+ assert_text "Reservation was successfully updated"
+ click_on "Back"
+ end
+
+ test "should destroy Reservation" do
+ visit reservation_url(@reservation)
+ click_on "Destroy this reservation", match: :first
+
+ assert_text "Reservation was successfully destroyed"
+ end
+end