Project initialize

This commit is contained in:
Zin Bo Thit
2026-01-28 09:53:14 +06:30
commit e8380c6e23
139 changed files with 4599 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
<h1>Departments#create</h1>
<p>Find me in app/views/departments/create.html.erb</p>

View File

@@ -0,0 +1,2 @@
<h1>Departments#destroy</h1>
<p>Find me in app/views/departments/destroy.html.erb</p>

View File

@@ -0,0 +1,31 @@
<h1>Edit Department</h1>
<%= form_with(model: @department, local: true) do |form| %>
<% if @department.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@department.errors.count, "error") %> prohibited this department from being saved:</h2>
<ul>
<% @department.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, placeholder: "Department name..." %>
</div>
<div class="field">
<%= form.label :description %>
<%= form.text_area :description, placeholder: "Department description...", rows: 4 %>
</div>
</div>
<div class="actions">
<%= form.submit "Update Department", class: "submit-btn" %>
<%= link_to "Cancel", @department, class: "cancel-btn" %>
</div>
<% end %>

View File

@@ -0,0 +1,36 @@
<h1>Departments</h1>
<% if flash[:notice] %>
<div class="notice"><%= flash[:notice] %></div>
<% end %>
<div class="departments-grid">
<% if @departments.empty? %>
<p class="empty-state">No departments found.</p>
<% else %>
<% @departments.each do |department| %>
<div class="department-card">
<h3><%= link_to department.name, department_path(department) %></h3>
<p><%= department.description %></p>
<div class="department-stats">
<div class="stat">
<strong>Users:</strong> <%= department.user_count %>
</div>
<div class="stat">
<strong>Tasks:</strong> <%= department.task_count %>
</div>
<div class="stat">
<strong>Open:</strong> <%= department.incomplete_task_count %>
</div>
</div>
</div>
<% end %>
<% end %>
</div>
<div class="actions-section">
<% if current_user&.admin? %>
<%= link_to 'New Department', new_department_path, class: 'action-btn primary' %>
<% end %>
</div>

View File

@@ -0,0 +1,31 @@
<h1>New Department</h1>
<%= form_with(model: @department, local: true) do |form| %>
<% if @department.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@department.errors.count, "error") %> prohibited this department from being saved:</h2>
<ul>
<% @department.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, placeholder: "Department name..." %>
</div>
<div class="field">
<%= form.label :description %>
<%= form.text_area :description, placeholder: "Department description...", rows: 4 %>
</div>
</div>
<div class="actions">
<%= form.submit "Create Department", class: "submit-btn" %>
<%= link_to "Cancel", departments_path, class: "cancel-btn" %>
</div>
<% end %>

View File

@@ -0,0 +1,40 @@
<h1><%= @department.name %></h1>
<div class="department-info">
<p><%= @department.description %></p>
<div class="department-stats">
<h3>Department Statistics</h3>
<div class="stats-grid">
<div class="stat-item">
<strong>Total Users:</strong> <%= @department.user_count %>
</div>
<div class="stat-item">
<strong>Total Tasks:</strong> <%= @department.task_count %>
</div>
<div class="stat-item">
<strong>Open Tasks:</strong> <%= @department.incomplete_task_count %>
</div>
</div>
</div>
</div>
<div class="tasks-section">
<h2>Department Tasks</h2>
<% if @tasks.empty? %>
<p class="empty-state">No tasks in this department yet.</p>
<% else %>
<div class="tasks-list">
<% @tasks.each do |task| %>
<%= render 'tasks/task', task: task %>
<% end %>
</div>
<% end %>
</div>
<div class="department-actions">
<%= link_to 'Back to All Departments', departments_path, class: 'action-btn secondary' %>
<% if current_user&.can_manage_department?(@department) %>
<%= link_to 'Edit Department', edit_department_path(@department), class: 'action-btn primary' %>
<% end %>
</div>

View File

@@ -0,0 +1,2 @@
<h1>Departments#update</h1>
<p>Find me in app/views/departments/update.html.erb</p>

View File

@@ -0,0 +1,16 @@
<h2>Resend confirmation instructions</h2>
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) %>
</div>
<div class="actions">
<%= f.submit "Resend confirmation instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>

View File

@@ -0,0 +1,5 @@
<p>Welcome <%= @email %>!</p>
<p>You can confirm your account email through the link below:</p>
<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>

View File

@@ -0,0 +1,7 @@
<p>Hello <%= @email %>!</p>
<% if @resource.try(:unconfirmed_email?) %>
<p>We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.</p>
<% else %>
<p>We're contacting you to notify you that your email has been changed to <%= @resource.email %>.</p>
<% end %>

View File

@@ -0,0 +1,3 @@
<p>Hello <%= @resource.email %>!</p>
<p>We're contacting you to notify you that your password has been changed.</p>

View File

@@ -0,0 +1,8 @@
<p>Hello <%= @resource.email %>!</p>
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
<p>If you didn't request this, please ignore this email.</p>
<p>Your password won't change until you access the link above and create a new one.</p>

View File

@@ -0,0 +1,7 @@
<p>Hello <%= @resource.email %>!</p>
<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
<p>Click the link below to unlock your account:</p>
<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>

View File

@@ -0,0 +1,25 @@
<h2>Change your password</h2>
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<%= f.hidden_field :reset_password_token %>
<div class="field">
<%= f.label :password, "New password" %><br />
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em><br />
<% end %>
<%= f.password_field :password, autofocus: true, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation, "Confirm new password" %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="actions">
<%= f.submit "Change my password" %>
</div>
<% end %>
<%= render "devise/shared/links" %>

View File

@@ -0,0 +1,16 @@
<h2>Forgot your password?</h2>
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="actions">
<%= f.submit "Send me reset password instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>

View File

@@ -0,0 +1,43 @@
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
<% end %>
<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "new-password" %>
<% if @minimum_password_length %>
<br />
<em><%= @minimum_password_length %> characters minimum</em>
<% end %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
<%= f.password_field :current_password, autocomplete: "current-password" %>
</div>
<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>
<h3>Cancel my account</h3>
<div>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?", turbo_confirm: "Are you sure?" }, method: :delete %></div>
<%= link_to "Back", :back %>

View File

@@ -0,0 +1,48 @@
<div class="auth-container">
<h2>Register New Account</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { class: "auth-form" }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :name %>
<%= f.text_field :name, autofocus: true, autocomplete: "name" %>
</div>
<div class="field">
<%= f.label :email %>
<%= f.email_field :email, autocomplete: "email" %>
</div>
<% if current_user&.admin? || !current_user %>
<div class="field">
<%= f.label :role %>
<%= f.select :role, User.roles.keys, { prompt: "Select Role" } %>
</div>
<div class="field">
<%= f.label :department_id %>
<%= f.collection_select :department_id, Department.ordered, :id, :name, { prompt: "Select Department" } %>
</div>
<% end %>
<div class="field">
<%= f.label :password %>
<% if @minimum_password_length %>
<em>(<%= @minimum_password_length %> characters minimum)</em>
<% end %>
<%= f.password_field :password, autocomplete: "new-password" %>
</div>
<div class="field">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="actions">
<%= f.submit "Sign up", class: "auth-submit-btn" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
</div>

View File

@@ -0,0 +1,30 @@
<div class="auth-container">
<h2>Sign In</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name), html: { class: "auth-form" }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %>
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :password %>
<%= f.password_field :password, autocomplete: "current-password" %>
</div>
<% if devise_mapping.rememberable? %>
<div class="field checkbox-field">
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
</div>
<% end %>
<div class="actions">
<%= f.submit "Log in", class: "auth-submit-btn" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
</div>

View File

@@ -0,0 +1,15 @@
<% if resource.errors.any? %>
<div id="error_explanation" data-turbo-cache="false">
<h2>
<%= I18n.t("errors.messages.not_saved",
count: resource.errors.count,
resource: resource.class.model_name.human.downcase)
%>
</h2>
<ul>
<% resource.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>

View File

@@ -0,0 +1,25 @@
<%- if controller_name != 'sessions' %>
<%= link_to "Log in", new_session_path(resource_name) %><br />
<% end %>
<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
<%= link_to "Sign up", new_registration_path(resource_name) %><br />
<% end %>
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
<% end %>
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
<% end %>
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
<% end %>
<%- if devise_mapping.omniauthable? %>
<%- resource_class.omniauth_providers.each do |provider| %>
<%= button_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), data: { turbo: false } %><br />
<% end %>
<% end %>

View File

@@ -0,0 +1,16 @@
<h2>Resend unlock instructions</h2>
<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="actions">
<%= f.submit "Resend unlock instructions" %>
</div>
<% end %>
<%= render "devise/shared/links" %>

View File

@@ -0,0 +1,49 @@
<!DOCTYPE html>
<html>
<head>
<title>Project Management System</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<% if user_signed_in? %>
<nav class="main-nav">
<div class="nav-container">
<div class="nav-brand">
<%= link_to 'Project Manager', root_path, class: 'brand-link' %>
</div>
<div class="nav-menu">
<%= link_to 'Dashboard', dashboard_path, class: 'nav-link' %>
<%= link_to 'Tasks', tasks_path, class: 'nav-link' %>
<% if current_user.admin? || current_user.manager? %>
<%= link_to 'Departments', departments_path, class: 'nav-link' %>
<% end %>
<% if current_user.admin? %>
<%= link_to 'Users', new_user_registration_path, class: 'nav-link' %>
<% end %>
</div>
<div class="nav-user">
<span class="user-info">
<%= current_user.name %> (<%= current_user.role.humanize %>)
</span>
<%= link_to 'Sign Out', destroy_user_session_path, method: :delete, class: 'nav-link sign-out' %>
</div>
</div>
</nav>
<% end %>
<% if flash[:notice] %>
<div class="notice"><%= flash[:notice] %></div>
<% end %>
<% if flash[:alert] %>
<div class="alert"><%= flash[:alert] %></div>
<% end %>
<%= yield %>
</body>
</html>

View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
/* Email styles need to be inline */
</style>
</head>
<body>
<%= yield %>
</body>
</html>

View File

@@ -0,0 +1 @@
<%= yield %>

View File

@@ -0,0 +1,71 @@
<% if task.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(task.errors.count, "error") %> prohibited this task from being saved:</h2>
<ul>
<% task.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-row">
<div class="field-group">
<div class="field">
<%= form.label :title %>
<%= form.text_field :title, placeholder: "Task title...", class: "title-field" %>
</div>
</div>
</div>
<div class="form-row">
<div class="field-group">
<div class="field">
<%= form.label :priority %>
<%= form.select :priority, Task.priorities.keys.map { |p| [p.humanize, p] }, { prompt: "Select Priority" }, class: "priority-select" %>
</div>
<% if accessible_departments.count > 1 || current_user&.admin? %>
<div class="field">
<%= form.label :department_id %>
<%= form.collection_select :department_id, accessible_departments, :id, :name, { prompt: "Select Department" }, class: "department-select" %>
</div>
<% end %>
</div>
</div>
<div class="form-row">
<div class="field-group">
<% if current_user&.admin? || current_user&.manager? %>
<div class="field">
<%= form.label :assignee_id %>
<%= form.collection_select :assignee_id, accessible_users, :id, :name, { prompt: "Select Assignee" }, class: "assignee-select" %>
</div>
<% end %>
<div class="field">
<%= form.label :status %>
<%= form.select :status, Task.statuses.keys.map { |s| [s.humanize, s] }, { prompt: "Select Status" }, class: "status-select" %>
</div>
</div>
</div>
<div class="description-section">
<div class="description-toggle" onclick="toggleDescription()">
<span id="toggle-text">+ Add Description</span>
</div>
<div id="description-field" class="description-field" style="display: none;">
<%= form.text_area :description, placeholder: "Add a detailed description...", rows: 4, class: "description-textarea" %>
</div>
</div>
<% if form.object.new_record? %>
<div class="actions">
<%= form.submit "Create Task", class: "submit-btn" %>
</div>
<% else %>
<div class="actions">
<%= form.submit "Update Task", class: "submit-btn" %>
<%= link_to "Cancel", task, class: "cancel-btn" %>
</div>
<% end %>

View File

@@ -0,0 +1,58 @@
<div id="task_<%= task.id %>" class="task <%= 'completed' if task.status == 'completed' %>">
<div class="task-header">
<div class="task-priority" style="color: <%= task.priority_color %>">
<%= task.priority_icon %> <%= task.priority.humanize %>
</div>
<div class="task-status-badge" style="background-color: <%= task.status_badge[:color] %>">
<%= task.status_badge[:text] %>
</div>
</div>
<%= form_with(model: task, local: false, method: :patch, class: "toggle-form") do |form| %>
<div class="task-content">
<%= form.check_box :status, { checked: task.status == 'completed', onchange: "this.form.submit();" }, { class: "task-checkbox" } %>
<div class="task-info">
<span class="task-title"
title="<%= task.description&.truncate(100) || 'No description' %>"
data-description="<%= task.description || '' %>">
<%= task.title %>
</span>
<% if task.description.present? %>
<span class="description-indicator">📝</span>
<% end %>
</div>
</div>
<% end %>
<div class="task-meta">
<% if task.department %>
<span class="department-tag">
<%= task.department.name %>
</span>
<% end %>
<% if task.assignee %>
<span class="assignee-tag">
Assigned to: <%= task.assignee.name %>
</span>
<% end %>
<span class="created-tag">
Created: <%= task.created_at.strftime('%m/%d/%Y') %>
</span>
</div>
<div class="task-actions">
<%= link_to 'View', task, class: 'details-btn' %>
<% if task.updateable_by?(current_user) %>
<%= link_to 'Edit', edit_task_path(task), class: 'edit-btn' %>
<% end %>
<% if task.assign?(current_user) && !task.assignee %>
<%= link_to 'Assign', assign_task_path(task), method: :patch, class: 'assign-btn' %>
<% end %>
<% if task.updateable_by?(current_user) || current_user.admin? %>
<%= link_to 'Delete', task, method: :delete, data: { confirm: 'Are you sure?' }, class: 'delete-btn' %>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,2 @@
<h1>Tasks#create</h1>
<p>Find me in app/views/tasks/create.html.erb</p>

View File

@@ -0,0 +1,128 @@
<div class="dashboard-container">
<div class="dashboard-header">
<h1>Company Dashboard</h1>
<div class="user-welcome">
Welcome back, <%= current_user.name %>!
<span class="user-role">(<%= current_user.role.humanize %>)</span>
<% if current_user.department %>
<span class="user-department">- <%= current_user.department.name %> Department</span>
<% end %>
</div>
</div>
<div class="dashboard-content">
<div class="stats-section">
<h2>Statistics</h2>
<% case current_user.role %>
<% when 'admin' %>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-number"><%= @total_tasks %></div>
<div class="stat-label">Total Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number"><%= @open_tasks %></div>
<div class="stat-label">Open Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number"><%= @urgent_tasks %></div>
<div class="stat-label">Urgent Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number"><%= @departments.count %></div>
<div class="stat-label">Departments</div>
</div>
</div>
<div class="departments-overview">
<h3>Departments Overview</h3>
<% @departments.each do |department| %>
<div class="dept-card">
<h4><%= department.name %></h4>
<div class="dept-stats">
<span><strong>Users:</strong> <%= department.users.count %></span>
<span><strong>Tasks:</strong> <%= department.tasks.count %></span>
<span><strong>Open:</strong> <%= department.tasks.open.count %></span>
</div>
</div>
<% end %>
</div>
<% when 'manager' %>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-number"><%= @dept_tasks.count %></div>
<div class="stat-label">Department Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number"><%= @open_tasks %></div>
<div class="stat-label">Open Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number"><%= @urgent_tasks %></div>
<div class="stat-label">Urgent Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number"><%= @team_members.count %></div>
<div class="stat-label">Team Members</div>
</div>
</div>
<div class="team-overview">
<h3>Team Overview - <%= current_user.department.name %></h3>
<% @team_members.each do |member| %>
<div class="member-card">
<div class="member-name"><%= member.name %></div>
<div class="member-stats">
<span><strong>Assigned:</strong> <%= member.assigned_tasks.count %></span>
<span><strong>Open:</strong> <%= member.assigned_tasks.open.count %></span>
</div>
</div>
<% end %>
</div>
<% when 'employee' %>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-number"><%= @my_tasks.count %></div>
<div class="stat-label">My Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number"><%= @open_tasks %></div>
<div class="stat-label">Open Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number"><%= @urgent_tasks %></div>
<div class="stat-label">Urgent Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number"><%= @my_tasks.complete.count %></div>
<div class="stat-label">Completed</div>
</div>
</div>
<% end %>
</div>
<div class="recent-tasks-section">
<h2>Recent Tasks</h2>
<% if @recent_tasks.empty? %>
<p class="empty-state">No recent tasks found.</p>
<% else %>
<div class="tasks-list">
<% @recent_tasks.each do |task| %>
<%= render 'task', task: task %>
<% end %>
</div>
<% end %>
</div>
</div>
<div class="dashboard-actions">
<%= link_to 'View All Tasks', tasks_path, class: 'action-btn primary' %>
<%= link_to 'Create New Task', new_task_path, class: 'action-btn success' %>
<% if current_user.admin? || current_user.manager? %>
<%= link_to 'Manage Departments', departments_path, class: 'action-btn secondary' %>
<% end %>
</div>
</div>

View File

@@ -0,0 +1,2 @@
<h1>Tasks#destroy</h1>
<p>Find me in app/views/tasks/destroy.html.erb</p>

View File

@@ -0,0 +1,16 @@
<h1>Edit Task</h1>
<% if flash[:notice] %>
<div class="notice"><%= flash[:notice] %></div>
<% end %>
<div class="edit-task">
<%= form_with(model: @task, local: true, class: "task-form edit-form") do |form| %>
<%= render 'form', task: @task, form: form %>
<% end %>
</div>
<div class="back-link">
<%= link_to '← Back to Task', @task %> |
<%= link_to '← Back to List', tasks_path %>
</div>

View File

@@ -0,0 +1,94 @@
<div class="dashboard-header">
<h1>Task Management</h1>
<% if current_user %>
<div class="user-info">
<span class="user-role">
<%= current_user.name %> - <%= current_user.role.humanize %>
<% if current_user.department %>
( <%= current_user.department.name %> )
<% end %>
</span>
</div>
<% end %>
</div>
<% if flash[:notice] %>
<div class="notice"><%= flash[:notice] %></div>
<% end %>
<div class="content-layout">
<div class="sidebar">
<div class="filter-section">
<h3>Filters</h3>
<% if accessible_departments.count > 1 %>
<div class="filter-group">
<label>Department</label>
<%= form_with(url: tasks_path, method: :get, local: true, class: "filter-form") do |f| %>
<%= f.select :department_id,
options_for_select([[ "All Departments", "" ]] + accessible_departments.map { |d| [d.name, d.id] },
params[:department_id]),
{ onchange: "this.form.submit();" },
{ class: "filter-select" } %>
<% end %>
</div>
<% end %>
<div class="filter-group">
<label>Priority</label>
<%= form_with(url: tasks_path, method: :get, local: true, class: "filter-form") do |f| %>
<%= f.select :priority,
options_for_select([[ "All Priorities", "" ]] + Task.priorities.keys.map { |p| [p.humanize, p] },
params[:priority]),
{ onchange: "this.form.submit();" },
{ class: "filter-select" } %>
<% end %>
</div>
<div class="filter-group">
<label>Status</label>
<%= form_with(url: tasks_path, method: :get, local: true, class: "filter-form") do |f| %>
<%= f.select :status,
options_for_select([[ "All Statuses", "" ]] + Task.statuses.keys.map { |s| [s.humanize, s] },
params[:status]),
{ onchange: "this.form.submit();" },
{ class: "filter-select" } %>
<% end %>
</div>
</div>
<div class="actions-section">
<h3>Actions</h3>
<%= link_to 'Dashboard', dashboard_path, class: 'action-btn' %>
<%= link_to 'My Tasks', my_tasks_path, class: 'action-btn' if current_user.employee? %>
<%= link_to 'Departments', departments_path, class: 'action-btn' if current_user.admin? || current_user.manager? %>
<% if current_user.admin? %>
<%= link_to 'New User', new_user_registration_path, class: 'action-btn' %>
<% end %>
</div>
</div>
<div class="main-content">
<div class="new-task-section">
<h2>Create New Task</h2>
<%= form_with(model: @task, local: true, class: "task-form") do |form| %>
<%= render 'form', task: @task, form: form %>
<% end %>
</div>
<div class="tasks-section">
<h2>Tasks (<%= @tasks.count %>)</h2>
<% if @tasks.empty? %>
<p class="empty-state">No tasks found with current filters.</p>
<% else %>
<div class="tasks-list">
<% @tasks.each do |task| %>
<%= render 'task', task: task %>
<% end %>
</div>
<% end %>
</div>
</div>
</div>

View File

@@ -0,0 +1,41 @@
<div class="task-detail" id="task_detail_<%= @task.id %>">
<div class="task-header">
<h1 class="task-title <%= 'completed' if @task.completed %>">
<%= @task.title %>
</h1>
<div class="task-meta">
<span class="status-badge <%= @task.completed ? 'completed' : 'pending' %>">
<%= @task.completed ? '✓ Completed' : '○ Pending' %>
</span>
<span class="created-date">
Created: <%= @task.created_at.strftime('%B %d, %Y at %I:%M %p') %>
</span>
</div>
</div>
<div class="task-description">
<h2>Description</h2>
<% if @task.description.present? %>
<div class="description-content">
<%= simple_format(@task.description) %>
</div>
<% else %>
<p class="no-description">No description provided.</p>
<% end %>
</div>
<div class="task-actions">
<%= form_with(model: @task, local: false, method: :patch, class: "toggle-status-form") do |form| %>
<%= form.hidden_field :completed, value: !@task.completed %>
<%= form.submit @task.completed ? 'Mark as Pending' : 'Mark as Completed',
class: "status-toggle-btn #{@task.completed ? 'pending' : 'completed'}" %>
<% end %>
<%= link_to 'Edit Task', edit_task_path(@task), class: 'edit-btn' %>
<%= link_to 'Back to List', tasks_path, class: 'back-btn' %>
<%= link_to 'Delete', @task, method: :delete,
data: { confirm: 'Are you sure you want to delete this task?' },
class: 'delete-btn' %>
</div>
</div>

View File

@@ -0,0 +1,2 @@
<h1>Tasks#update</h1>
<p>Find me in app/views/tasks/update.html.erb</p>

View File

@@ -0,0 +1,22 @@
// Update task list if on index page to preserve sorting
var tasksList = document.querySelector('.tasks-list');
if (tasksList) {
<% @tasks = Task.ordered %>
tasksList.innerHTML = '<%= j render partial: "task", collection: @tasks, as: :task %>';
// Handle empty state if necessary
var emptyState = document.querySelector('.empty-state');
if (emptyState) {
if (<%= @tasks.any? %>) {
emptyState.style.display = 'none';
} else {
emptyState.style.display = 'block';
}
}
}
// Update task detail page if present
var taskDetail = document.getElementById('task_detail_<%= @task.id %>');
if (taskDetail) {
taskDetail.outerHTML = '<%= j render template: "tasks/show", formats: [:html], layout: false %>';
}