diff --git a/app/assets/stylesheets/layout.css b/app/assets/stylesheets/layout.css
index c54d3ad..d8a70a2 100644
--- a/app/assets/stylesheets/layout.css
+++ b/app/assets/stylesheets/layout.css
@@ -6,6 +6,7 @@ body {
font-size: 1.1em;
margin: 0 auto;
max-width: 80em;
+ padding: 1em;
}
main {
diff --git a/app/controllers/tables_controller.rb b/app/controllers/tables_controller.rb
index a782914..2672e95 100644
--- a/app/controllers/tables_controller.rb
+++ b/app/controllers/tables_controller.rb
@@ -1,6 +1,61 @@
# frozen_string_literal: true
class TablesController < ApplicationController
+ before_action :set_table, only: [ :show, :edit, :update, :destroy ]
+
def index
+ @tables = Current.user.tables
end
+
+ def show
+ end
+
+ def new
+ @table = Table.new
+ end
+
+ def create
+ @table = Current.user.tables.new(table_params)
+ @table.slug = helpers.generate_slug_for(model: Table, string: @table.name)
+ if @table.save
+ redirect_to @table, notice: t(".success", name: @table.name)
+ else
+ flash.now[:alert] = t(".error")
+ render :new, status: :unprocessable_entity
+ end
+ end
+
+ def edit
+ end
+
+ def update
+ if @table.update(table_params)
+ redirect_to @table, notice: t(".success", name: @table.name)
+ else
+ flash.now[:alert] = t(".error")
+ render :edit, status: :unprocessable_entity
+ end
+ end
+
+ def destroy
+ if @table.destroy
+ redirect_to tables_path, notice: t(".success", name: @table.name)
+ else
+ flash[:alert] = t(".error", name: @table.name)
+ redirect_to tables_path
+ end
+ end
+
+ private
+
+ def set_table
+ @table = Current.user.tables.find(params[:id])
+ end
+
+ def table_params
+ params.require(:table).permit(
+ :name,
+ :game_system_id,
+ )
+ end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 15b06f0..d2a7d74 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,4 +1,8 @@
# frozen_string_literal: true
module ApplicationHelper
+ def generate_slug_for(model:, string:)
+ # TODO: Need to ensure this is unique for that model
+ string.parameterize
+ end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 34a68f1..619ea81 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2,6 +2,7 @@
class User < ApplicationRecord
has_and_belongs_to_many :site_roles
+ has_many :tables, foreign_key: :owner_id
has_secure_password
generates_token_for :password_reset, expires_in: 4.hours do
diff --git a/app/views/tables/_form.html.erb b/app/views/tables/_form.html.erb
new file mode 100644
index 0000000..d819d90
--- /dev/null
+++ b/app/views/tables/_form.html.erb
@@ -0,0 +1,11 @@
+<%# locals: (table:, button_text:) -%>
+
+<%= form_with model: @table do |f| %>
+ <%= f.label :name %>
+ <%= f.text_field :name %>
+
+ <%= f.label :game_system_id %>
+ <%= f.collection_select :game_system_id, GameSystem.all, :id, :name %>
+
+ <%= f.submit button_text %>
+<% end %>
diff --git a/app/views/tables/_table.html.erb b/app/views/tables/_table.html.erb
new file mode 100644
index 0000000..79499a4
--- /dev/null
+++ b/app/views/tables/_table.html.erb
@@ -0,0 +1,5 @@
+<%# locals: (table:) -%>
+
+
+
<%= link_to table.name, table %>
+
diff --git a/app/views/tables/edit.html.erb b/app/views/tables/edit.html.erb
new file mode 100644
index 0000000..d8b15c0
--- /dev/null
+++ b/app/views/tables/edit.html.erb
@@ -0,0 +1,8 @@
+<% content_for :title, t(".edit_table", name: @table.name) %>
+
+<%= t(".edit_table", name: @table.name) %>
+
+<%= link_to t(".delete_table", name: @table.name), table_path(@table),
+ data: { turbo_method: :delete, turbo_confirm: t(".delete_table_confirmation", name: @table.name) } %>
+<%= render partial: "tables/form",
+ locals: { table: @table, button_text: t(".update_table") } %>
diff --git a/app/views/tables/index.html.erb b/app/views/tables/index.html.erb
index d87d760..c90911c 100644
--- a/app/views/tables/index.html.erb
+++ b/app/views/tables/index.html.erb
@@ -1 +1,10 @@
-Hello
+<% content_for :title, t(".tables") %>
+
+<%= link_to t(".new_table"), new_table_path %>
+
+Your tables
+<% if @tables.any? %>
+ <%= render @tables %>
+<% else %>
+ You have no tables.
+<% end %>
diff --git a/app/views/tables/new.html.erb b/app/views/tables/new.html.erb
new file mode 100644
index 0000000..6a1480f
--- /dev/null
+++ b/app/views/tables/new.html.erb
@@ -0,0 +1,6 @@
+<% content_for :title, t(".new_table") %>
+
+<%= t(".new_table") %>
+
+<%= render partial: "tables/form",
+ locals: { table: @table, button_text: t(".create_table") } %>
diff --git a/app/views/tables/show.html.erb b/app/views/tables/show.html.erb
new file mode 100644
index 0000000..b748b1d
--- /dev/null
+++ b/app/views/tables/show.html.erb
@@ -0,0 +1,12 @@
+<% content_for :title, @table.name %>
+
+<%= @table.name %>
+
+<%= link_to t(".edit_table"), edit_table_path(@table) %>
+
+
+ - <%= t(".game_system") %>:
+ - <%= @table.game_system.name %>
+ - <%= t(".owner") %>:
+ - <%= @table.owner.username %>
+
diff --git a/config/locales/en.yml b/config/locales/en.yml
index e423344..963e275 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -56,6 +56,31 @@ en:
destroy:
log_out: Log out
success: "You have signed out."
+ tables:
+ index:
+ new_table: Create a table
+ tables: Tables
+ show:
+ edit_table: Edit table
+ game_system: Game system
+ owner: Owner
+ new:
+ new_table: New table
+ create_table: Create table
+ create:
+ success: Your table “%{name}” has been created.
+ error: Failed to create table
+ edit:
+ delete_table: Delete %{name}
+ delete_table_confirmation: Are you sure you want to delete %{name}?
+ edit_table: Edit %{name}
+ update_table: Update table
+ update:
+ success: Updated table “%{name}”.
+ error: Failed to update table.
+ destroy:
+ success: Deleted table “%{name}”.
+ error: Failed to delete table.
users:
validations:
email_format: "must be a valid email address"
diff --git a/config/routes.rb b/config/routes.rb
index bae428b..5d47767 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -12,7 +12,7 @@ Rails.application.routes.draw do
resources :account_verifications, only: [ :show ]
resources :sessions, only: [ :new, :create, :destroy ]
- resources :tables, only: [ :index ]
+ resources :tables
resources :admin, only: [ :index ]
namespace :admin do
diff --git a/test/controllers/tables_controller_test.rb b/test/controllers/tables_controller_test.rb
new file mode 100644
index 0000000..e891e9d
--- /dev/null
+++ b/test/controllers/tables_controller_test.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class TablesControllerTest < ActionDispatch::IntegrationTest
+ test "should get index" do
+ sign_in users(:trevor)
+ get tables_url
+ assert_response :success
+ end
+
+ test "should get show" do
+ sign_in users(:trevor)
+ get table_url(tables(:table))
+ assert_response :success
+ end
+
+ test "should get new" do
+ sign_in users(:trevor)
+ get new_table_url
+ assert_response :success
+ end
+
+ test "should create table" do
+ sign_in users(:trevor)
+ assert_changes("Table.count", +1) do
+ post(tables_url, params: { table: table_params })
+ end
+ assert_redirected_to table_path(Table.last)
+ end
+
+ test "should alert to invalid table" do
+ sign_in users(:trevor)
+ assert_no_changes("Table.count") do
+ post(tables_url, params: { table: { name: "new_table" } })
+ end
+ assert_response :unprocessable_entity
+ end
+
+ test "should get edit" do
+ sign_in users(:trevor)
+ get edit_table_url(tables(:table))
+ assert_response :success
+ end
+
+ test "should update table" do
+ sign_in users(:trevor)
+ patch table_url(tables(:table)), params: { table: { name: "new name" } }
+ assert_redirected_to table_path(tables(:table))
+ end
+
+ test "should destroy table" do
+ sign_in users(:trevor)
+ assert_difference("Table.count", -1) do
+ delete table_url(tables(:table))
+ end
+ assert_redirected_to tables_url
+ end
+
+ private
+
+ def table_params
+ {
+ name: "A new table",
+ game_system_id: game_systems(:dnd).id,
+ }
+ end
+end