Fix Rails Form
The task at hand: Instructions
- To make a form look better. This is how it looks right now.
- Please keep all the admin items together.
- You do not need to change the stylesheet, simply use bootstrap and your creativity to present the form better to the end user.
Here is the form as it now stands. The layout needs improvement:
General Notes:
- Please infer the things that you need to do from the limited information you have below. I have provided some notes to help guide you:
Bootstrap
We are using bootstrap. Add this to your Gemfile: gem 'twitter-bootstrap-rails', :git => 'git://github.com/seyhunak/twitter-bootstrap-rails.git'
Models.
Give then form I am giving you, please infer the other models and relations that are required to make it work.
- We have a
quote.rb
model, and aline_item
model. Aquote
has manyline_items
. - We also have a user model. You needn’t worry about (devise)[https://github.com/plataformatec/devise] but you can if you want to. The main thing is that a user model must have a corresponding table with an email column and an ID column, and also an admin attribute. You could add the admin columns as a simple boolean on the users table.
- The
LineItemType
model has only one column: “Name”
The Main Schema
Here is the schema for the Line Items:
create_table "line_items", force: :cascade do |t|
t.integer "quote_id"
t.decimal "price", default: "0.0", null: false
t.decimal "po_value"
t.string "po_number"
t.text "scope_description"
t.date "delivery_date"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "delivery_time", limit: 400
t.decimal "hours", default: "0.0"
t.text "justification"
t.text "links"
t.integer "user_id"
t.text "approval_link"
t.boolean "was_sent", default: false
t.bigint "line_item_type_id"
t.string "invoice_state"
t.string "invoice_no"
t.string "issue_state"
t.integer "item_index"
t.index ["line_item_type_id"], name: "index_line_items_on_line_item_type_id"
t.index ["quote_id"], name: "index_line_items_on_quote_id"
end
The Form:
- I am using active storage on each line item. That why you can attach files to every line item.
<%= form_with(model: @line_item.new_record? ? [@quote, @line_item] : @line_item ) do |f| %>
<%= render 'shared/errors', object: @line_item %>
<%= f.label(:scope_description) %>
<%= f.text_area(:scope_description, class: "form-control") %> <br>
<div class="row">
<%= f.label(:hours, class: "col-sm-2 col-form-label") %>
<%= f.number_field(:hours, class: "col-sm-2") %>
<%= f.label(:delivery_time, class: "col-sm-2 col-form-label") %>
<%= f.text_field(:delivery_time, class: "col-sm-2") %>
</div>
<br>
<% if current_user.admin?%>
<h4> Admin Panel Items</h4>
<div class="form-group row">
<% if @line_item.user.role == 'basic' %>
<p> (You cannot overwrite the price that a basic_user has created. The price is calculated from the hours inputted) </p>
<% end %>
<%= f.label(:price, class: "col-sm-2 col-form-label") %>
<%= f.text_field(:price, class: "col-sm-2") %>
<%= f.label(:po_value, class: "col-sm-2 col-form-label") %>
<%= f.text_field(:po_value, class: "col-sm-2") %>
<%= f.label(:invoice_no, class: "col-sm-2 col-form-label") %>
<%= f.text_field(:invoice_no, class: "col-sm-2") %>
<%= f.label(:po_number, class: "col-sm-2 col-form-label") %>
<%= f.text_field(:po_number, class: "col-sm-2") %> <br>
<%= f.label(:justification) %>
<%= f.text_area(:justification, class: "form-control") %> <br>
</div>
<div class="actions form-group">
<p> <b> Do Not Use: Except in case an error was made: </b> </p>
<%= f.label(:invoice_state) %>
<%= f.select(:invoice_state, @line_item.invoice_states_for_select, {:selected => @line_item.invoice_state } ) %>
</div>
<div class="actions form-group">
<p> <b> Do Not Use: Except in case an error was made: </b> </p>
<%= f.label(:issue_state) %>
<%= f.select(:issue_state, @line_item.issue_states_for_select, {:selected => @line_item.issue_state } ) %>
</div>
<div class="form-group row">
<%= f.label(:approval_link) %>
<%= f.text_area(:approval_link, class: "form-control") %>
</div>
<div class="gorm-group row">
<%= f.select(:line_item_type_id, LineItemType.all.collect { |u| [u.name, u.id]}, {:include_blank => false, prompt: 'Please Choose Line Item Type', selected: @line_item.line_item_type_id }, class: "form-control", label:'users', :multiple => false )%>
</div>
<% else %>
<%= f.hidden_field :line_item_type_id, :value => @line_item.line_item_type.id %>
<% end %>
<%= f.label(:links) %>
<%= f.text_field(:links, class: "form-control") %> <br>
<% if current_user.role == "admin" %>
<%= f.label(:user) %> <br>
<%= f.select(:user_id, User.all.collect { |u| [u.email, u.id]}, {:include_blank => false, prompt: 'Please select detailer', selected: @line_item.user_id }, class: "form-control", label:'users', :multiple => false )%>
<% else %>
<% if @line_item.new_record? %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<% end %>
<% end %>
<br>
<p> You can select multiple files in a single upload:</p>
<%= f.file_field :files, multiple: true%>
<%= f.file_field :files, multiple: true %>
<br>
<br>
<div class="form-buttons">
<%= f.submit "Submit", class: "btn btn-primary btn-block" %> <br>
</div>
<% end %>
And here is the application.html.erb if you wanted to have a look:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= content_for?(:title) ? yield(:title) : "Quotes" %></title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= javascript_include_tag "application" %>
<!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.2/html5shiv.min.js" type="text/javascript"></script>
<![endif]-->
</head>
<body>
<%= render 'layouts/nav-bar' %>
<div class="container">
<%= bootstrap_flash %>
<%= yield %>
<!--/span-->
<footer>
<p>© Tek1 - <%= mail_to 'ben.chenathara@gmail.com', 'Ben Koshy' %> - Please email for Required Changes/Suggestions - Quotation App 2018 </p>
</footer>
</div>
<!-- /container -->
</body>
</html>
Written on October 14, 2019