Added users support
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
class ApplicationController < ActionController::Base
|
||||
before_action :set_locale
|
||||
before_action :require_login
|
||||
|
||||
private
|
||||
|
||||
@@ -8,27 +9,37 @@ class ApplicationController < ActionController::Base
|
||||
session[:locale] = I18n.locale
|
||||
end
|
||||
|
||||
# Optional: Make locale persist across requests via URL helpers
|
||||
def default_url_options
|
||||
{ locale: I18n.locale }
|
||||
end
|
||||
|
||||
def set_company
|
||||
# This should be handled by your authentication system
|
||||
# But for now, we'll use a placeholder
|
||||
company_id = session[:company_id]
|
||||
|
||||
unless company_id && Company.exists?(company_id)
|
||||
# If no company in session or it doesn't exist, use the first company
|
||||
company_id = Company.first&.id
|
||||
session[:company_id] = company_id
|
||||
end
|
||||
|
||||
@company = Company.find(company_id) if company_id
|
||||
def current_user
|
||||
@current_user ||= User.find(session[:user_id]) if session[:user_id]
|
||||
end
|
||||
|
||||
|
||||
def logged_in?
|
||||
!!current_user
|
||||
end
|
||||
|
||||
def require_login
|
||||
return if logged_in?
|
||||
|
||||
flash[:alert] = t('sessions.login_required')
|
||||
redirect_to login_path
|
||||
end
|
||||
|
||||
def set_company
|
||||
return unless logged_in?
|
||||
|
||||
@company = current_user.company
|
||||
|
||||
return if @company
|
||||
|
||||
redirect_to companies_path, alert: 'No company found. Please create a company first.'
|
||||
end
|
||||
|
||||
def current_company
|
||||
@company
|
||||
end
|
||||
helper_method :current_company
|
||||
helper_method :current_user, :logged_in?, :current_company
|
||||
end
|
||||
|
||||
@@ -219,5 +219,10 @@ class ReservationsController < ApplicationController
|
||||
end
|
||||
|
||||
@company = Company.includes(:teams).find(company_id) if company_id
|
||||
|
||||
unless @company
|
||||
redirect_to companies_path, alert: 'No company found. Please create a company first.'
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
25
app/controllers/sessions_controller.rb
Normal file
25
app/controllers/sessions_controller.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
class SessionsController < ApplicationController
|
||||
skip_before_action :require_login, only: %i[new create]
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def create
|
||||
user = User.find_by_login(params[:login])
|
||||
|
||||
if user&.authenticate(params[:password])
|
||||
session[:user_id] = user.id
|
||||
session[:company_id] = user.company_id
|
||||
redirect_to root_path, notice: t('sessions.login_successful')
|
||||
else
|
||||
flash.now[:alert] = t('sessions.invalid_credentials')
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
session[:user_id] = nil
|
||||
session[:company_id] = nil
|
||||
redirect_to login_path, notice: t('sessions.logout_successful')
|
||||
end
|
||||
end
|
||||
@@ -2,4 +2,5 @@ class Company < ApplicationRecord
|
||||
has_many :customers, dependent: :destroy
|
||||
has_many :reservations, dependent: :destroy
|
||||
has_many :teams, dependent: :destroy
|
||||
has_many :users, dependent: :destroy
|
||||
end
|
||||
|
||||
23
app/models/user.rb
Normal file
23
app/models/user.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
class User < ApplicationRecord
|
||||
has_secure_password
|
||||
|
||||
belongs_to :company
|
||||
|
||||
validates :username, presence: true, uniqueness: { case_sensitive: false }
|
||||
validates :email, presence: true, uniqueness: { case_sensitive: false }, format: { with: URI::MailTo::EMAIL_REGEXP }
|
||||
validates :password, length: { minimum: 6 }, if: -> { new_record? || password.present? }
|
||||
validates :company_id, presence: true
|
||||
|
||||
before_save :downcase_username_and_email
|
||||
|
||||
def self.find_by_login(login)
|
||||
find_by(username: login.downcase) || find_by(email: login.downcase)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def downcase_username_and_email
|
||||
self.username = username.downcase.strip if username.present?
|
||||
self.email = email.downcase.strip if email.present?
|
||||
end
|
||||
end
|
||||
@@ -18,6 +18,15 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<% if logged_in? %>
|
||||
<div class="fixed top-4 right-4 text-sm text-gray-600 bg-white px-3 py-1 rounded-md shadow-sm border">
|
||||
<span class="lowercase"><%= current_user.username %></span>
|
||||
<span class="mx-2">|</span>
|
||||
<%= link_to t('sessions.logout_button'), logout_path, method: :delete,
|
||||
class: "text-blue-600 hover:text-blue-800" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<main class="container mx-auto mt-28 px-5 flex">
|
||||
<%= yield %>
|
||||
</main>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<div class="my-5">
|
||||
<%= form.label :team_id, t('reservations.form.team') %>
|
||||
<%= form.collection_select :team_id,
|
||||
@company.teams,
|
||||
@company&.teams || [],
|
||||
:id,
|
||||
:name,
|
||||
{ prompt: t('reservations.form.select_team') },
|
||||
|
||||
@@ -28,10 +28,12 @@
|
||||
<label for="team-filter" class="mr-2 font-medium"><%= t('.filter_by_team') %>:</label>
|
||||
<select id="team-filter" data-main-calendar-target="teamFilter" data-action="change->main-calendar#filterByTeam" class="rounded-md border-gray-300 shadow-sm px-3 py-1 bg-white">
|
||||
<option value="all"><%= t('.all_teams') %></option>
|
||||
<% @company.teams.each do |team| %>
|
||||
<option value="<%= team.id %>" style="background-color: <%= team_color(team.id) %>; color: #000000; padding-left: 10px;">
|
||||
<%= team.name %>
|
||||
</option>
|
||||
<% if @company&.teams %>
|
||||
<% @company.teams.each do |team| %>
|
||||
<option value="<%= team.id %>" style="background-color: <%= team_color(team.id) %>; color: #000000; padding-left: 10px;">
|
||||
<%= team.name %>
|
||||
</option>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
24
app/views/sessions/new.html.erb
Normal file
24
app/views/sessions/new.html.erb
Normal file
@@ -0,0 +1,24 @@
|
||||
<div class="max-w-md mx-auto mt-8 bg-white p-6 rounded-lg shadow-md">
|
||||
<h2 class="text-2xl font-bold text-center mb-6"><%= t('sessions.login') %></h2>
|
||||
|
||||
<%= form_with url: login_path, method: :post, local: true, class: "space-y-4" do |form| %>
|
||||
<div>
|
||||
<%= form.label :login, t('sessions.username_or_email'), class: "block text-sm font-medium text-gray-700 mb-1" %>
|
||||
<%= form.text_field :login, required: true,
|
||||
class: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",
|
||||
placeholder: t('sessions.username_or_email_placeholder') %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= form.label :password, t('sessions.password'), class: "block text-sm font-medium text-gray-700 mb-1" %>
|
||||
<%= form.password_field :password, required: true,
|
||||
class: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",
|
||||
placeholder: t('sessions.password_placeholder') %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= form.submit t('sessions.login_button'),
|
||||
class: "w-full bg-blue-600 text-white py-2 px-4 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition duration-200" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
Reference in New Issue
Block a user