Skip to content

Commit

Permalink
management of client projects
Browse files Browse the repository at this point in the history
  • Loading branch information
fermion committed Jan 31, 2024
1 parent e25cb8a commit a9e2c93
Show file tree
Hide file tree
Showing 13 changed files with 381 additions and 123 deletions.
51 changes: 17 additions & 34 deletions app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
@@ -1,60 +1,43 @@
class ProjectsController < ApplicationController
before_action :require_user!
before_action :set_project, only: %i[ show edit update destroy ]
before_action :set_project, only: %i[ show edit update ]

# GET /projects or /projects.json
def index
@projects = Project.includes(:company). all
end

# GET /projects/1 or /projects/1.json
def show
end

# GET /projects/new
def new
@project = Project.new
@client = Client.find_by(id: params[:client_id]) # optional
@project = Project.new(
client_id: params[:client_id],

# TODO: make these configurable?
status: Project::PROPOSED,
payment_frequency: Project::MONTHLY
)
end

# GET /projects/1/edit
def edit
end

# POST /projects or /projects.json
def create
@project = Project.new(project_params)

respond_to do |format|
if @project.save
format.html { redirect_to project_url(@project), notice: "Project was successfully created." }
format.json { render :show, status: :created, location: @project }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @project.errors, status: :unprocessable_entity }
end
if @project.save
redirect_to project_url(@project), notice: "Project was successfully created."
else
render :new, status: :unprocessable_entity
end
end

# PATCH/PUT /projects/1 or /projects/1.json
def update
respond_to do |format|
if @project.update(project_params)
format.html { redirect_to project_url(@project), notice: "Project was successfully updated." }
format.json { render :show, status: :ok, location: @project }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: @project.errors, status: :unprocessable_entity }
end
end
end

# DELETE /projects/1 or /projects/1.json
def destroy
@project.destroy!

respond_to do |format|
format.html { redirect_to projects_url, notice: "Project was successfully destroyed." }
format.json { head :no_content }
if @project.update(project_params)
redirect_to project_url(@project), notice: "Project was successfully updated."
else
render :edit, status: :unprocessable_entity
end
end

Expand Down
27 changes: 0 additions & 27 deletions app/views/clients/_client.html.erb

This file was deleted.

32 changes: 0 additions & 32 deletions app/views/clients/_form.html.erb

This file was deleted.

6 changes: 3 additions & 3 deletions app/views/clients/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0 1 15.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 0 1 3 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 0 0-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 0 1-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 0 0 3 15h-.75M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm3 0h.008v.008H18V10.5Zm-12 0h.008v.008H6V10.5Z" />
</svg>
<% end
end
breadcrumbs_component.with_breadcrumb(title: @client.name, last: true)
end %>
end
breadcrumbs_component.with_breadcrumb(title: @client.name, last: true)
end %>
</div>

<div class="bg-white p-4 mt-4">
Expand Down
13 changes: 12 additions & 1 deletion app/views/clients/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
breadcrumbs_component.with_breadcrumb(title: "Clients", link: clients_path, first: true) do |clients_icon|
clients_icon.with_svg do %>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="flex-shrink-0 w-6 h-6 inline">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0 1 15.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 0 1 3 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 0 0-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 0 1-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 0 0 3 15h-.75M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm3 0h.008v.008H18V10.5Zm-12 0h.008v.008H6V10.5Z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M20.25 14.15v4.25c0 1.094-.787 2.036-1.872 2.18-2.087.277-4.216.42-6.378.42s-4.291-.143-6.378-.42c-1.085-.144-1.872-1.086-1.872-2.18v-4.25m16.5 0a2.18 2.18 0 0 0 .75-1.661V8.706c0-1.081-.768-2.015-1.837-2.175a48.114 48.114 0 0 0-3.413-.387m4.5 8.006c-.194.165-.42.295-.673.38A23.978 23.978 0 0 1 12 15.75c-2.648 0-5.195-.429-7.577-1.22a2.016 2.016 0 0 1-.673-.38m0 0A2.18 2.18 0 0 1 3 12.489V8.706c0-1.081.768-2.015 1.837-2.175a48.111 48.111 0 0 1 3.413-.387m7.5 0V5.25A2.25 2.25 0 0 0 13.5 3h-3a2.25 2.25 0 0 0-2.25 2.25v.894m7.5 0a48.667 48.667 0 0 0-7.5 0M12 12.75h.008v.008H12v-.008Z" />
</svg>
<% end
end
Expand Down Expand Up @@ -37,6 +37,17 @@
<dt class="text-sm font-medium leading-6 text-gray-900">Projects</dt>
<dd class="mt-2 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
<ul role="list" class="divide-y divide-gray-100 rounded-md border border-gray-200">
<li class="flex items-center justify-between py-4 pl-4 pr-5 text-sm leading-6">
<div class="flex w-0 flex-1 items-center">
<%= link_to new_project_path(client_id: @client.id), class: "inline-flex items-center gap-x-1.5 rounded-md bg-indigo-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" do %>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="-ml-0.5 h-5 w-5">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
</svg>

New Project
<% end %>
</div>
</li>
<% @client.projects.each do |project| %>
<li class="flex items-center justify-between py-4 pl-4 pr-5 text-sm leading-6">
<div class="flex w-0 flex-1 items-center">
Expand Down
2 changes: 0 additions & 2 deletions app/views/projects/_project.json.jbuilder

This file was deleted.

101 changes: 96 additions & 5 deletions app/views/projects/edit.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,99 @@
<div class="mx-auto md:w-2/3 w-full">
<h1 class="font-bold text-4xl">Editing project</h1>
<div class="border-b border-gray-200 sm:flex sm:items-center sm:justify-between">
<%= render(Settings::BreadcrumbsComponent.new) do |breadcrumbs_component|
breadcrumbs_component.with_breadcrumb(title: "Clients", link: clients_path, first: true) do |breadcumb|
breadcumb.with_svg do %>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="flex-shrink-0 w-6 h-6 inline">
<path stroke-linecap="round" stroke-linejoin="round" d="M20.25 14.15v4.25c0 1.094-.787 2.036-1.872 2.18-2.087.277-4.216.42-6.378.42s-4.291-.143-6.378-.42c-1.085-.144-1.872-1.086-1.872-2.18v-4.25m16.5 0a2.18 2.18 0 0 0 .75-1.661V8.706c0-1.081-.768-2.015-1.837-2.175a48.114 48.114 0 0 0-3.413-.387m4.5 8.006c-.194.165-.42.295-.673.38A23.978 23.978 0 0 1 12 15.75c-2.648 0-5.195-.429-7.577-1.22a2.016 2.016 0 0 1-.673-.38m0 0A2.18 2.18 0 0 1 3 12.489V8.706c0-1.081.768-2.015 1.837-2.175a48.111 48.111 0 0 1 3.413-.387m7.5 0V5.25A2.25 2.25 0 0 0 13.5 3h-3a2.25 2.25 0 0 0-2.25 2.25v.894m7.5 0a48.667 48.667 0 0 0-7.5 0M12 12.75h.008v.008H12v-.008Z" />
</svg>
<% end
end

<%= render "form", project: @project %>
breadcrumbs_component.with_breadcrumb(title: @project.client.name, link: client_path(@project.client))
breadcrumbs_component.with_breadcrumb(title: @project.name, link: project_path(@project))
breadcrumbs_component.with_breadcrumb(title: "Edit project", last: true)
end %>

<%= link_to "Show this project", @project, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
<%= link_to "Back to projects", projects_path, class: "ml-2 rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
<div class="mt-3 sm:ml-4 sm:mt-0">
<%= link_to "Edit", edit_project_path(@project), class: "ml-3 inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" %>
</div>
</div>

<div class="bg-white p-4 mt-4">
<%= form_for @project, url: project_path(@project), data: {turbo: false} do |f| %>
<div class="space-y-12 sm:space-y-16">
<div>
<h2 class="text-base font-semibold leading-7 text-gray-900">Edit project</h2>

<% if @project.errors.any? %>
<div class="rounded-md bg-red-50 p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-red-800">There were <%= pluralize(@project.errors.count, "error") %> with adding the user to your company</h3>
<div class="mt-2 text-sm text-red-700">
<ul role="list" class="list-disc space-y-1 pl-5">
<% @project.errors.full_messages.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
</div>
</div>
</div>
</div>
<% end %>

<div class="mt-10 space-y-8 border-b border-gray-900/10 pb-12 sm:space-y-0 sm:divide-y sm:divide-gray-900/10 sm:border-t sm:pb-0">
<div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:py-6">
<label for="country" class="block text-sm font-medium leading-6 text-gray-900 sm:pt-1.5">Client</label>
<div class="mt-2 sm:col-span-2 sm:mt-0">
<select id="project_client_id" name="project[client_id]" class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6">
<%= options_from_collection_for_select current_company.clients.active.all, 'id', 'name', @project.client_id %>
</select>
</div>
</div>

<div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:py-6">
<%= f.label :name, "Project name", class: "block text-sm font-medium leading-6 text-gray-900 sm:pt-1.5" %>
<div class="mt-2 sm:col-span-2 sm:mt-0">
<%= f.text_field :name, class: "block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6" %>
</div>
</div>

<div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:py-6">
<%= f.label :status, "Status", class: "block text-sm font-medium leading-6 text-gray-900 sm:pt-1.5" %>
<div class="mt-2 sm:col-span-2 sm:mt-0">
<select id="project_status" name="project[status]" class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6">
<%= options_for_select(Project::VALID_STATUSES, @project.status) %>
</select>
</div>
</div>

<div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:py-6">
<%= f.label :cost, "Estimated cost", class: "block text-sm font-medium leading-6 text-gray-900 sm:pt-1.5" %>
<div class="mt-2 sm:col-span-2 sm:mt-0">
<%= f.text_field :cost, class: "block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-md sm:text-sm sm:leading-6" %>
</div>
</div>

<div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:py-6">
<%= f.label :payment_frequency, "Payment frequency", class: "block text-sm font-medium leading-6 text-gray-900 sm:pt-1.5" %>
<div class="mt-2 sm:col-span-2 sm:mt-0">
<select id="project_payment_frequency" name="project[payment_frequency]" class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6">
<%= options_for_select(Project::VALID_PAYMENT_FREQUENCIES, @project.payment_frequency) %>
</select>
</div>
</div>
</div>
</div>
</div>

<div class="mt-6 flex items-center justify-end gap-x-6">
<%= link_to "Cancel", project_path(@project), class: "text-sm font-semibold leading-6 text-gray-900" %>
<%= submit_tag "Save changes", data: {disable_with: "Please wait..."}, class: "rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" %>
</div>
<% end %>
</div>
1 change: 0 additions & 1 deletion app/views/projects/index.json.jbuilder

This file was deleted.

Loading

0 comments on commit a9e2c93

Please sign in to comment.