Skip to content

Commit

Permalink
Add companies filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
CalvinWalzel committed Sep 18, 2024
1 parent 14483a0 commit 2a51ea0
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 20 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,5 @@ gem "ruby-lsp-rspec", "~> 0.1.12", group: :development, require: false
gem "bullet", "~> 7.2", group: [:development, :test]

gem "friendly_id", "~> 5.5"

gem "filterameter", "~> 1.0"
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ GEM
railties (>= 5.0.0)
faker (3.4.2)
i18n (>= 1.8.11, < 2)
filterameter (1.0.0)
rails (>= 6.1)
friendly_id (5.5.1)
activerecord (>= 4.0.0)
globalid (1.2.1)
Expand Down Expand Up @@ -379,6 +381,7 @@ DEPENDENCIES
debug
factory_bot_rails (~> 6.4)
faker (~> 3.3)
filterameter (~> 1.0)
friendly_id (~> 5.5)
inertia_rails (~> 3.1)
jbuilder
Expand Down
23 changes: 13 additions & 10 deletions app/controllers/companies_controller.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
# frozen_string_literal: true

class CompaniesController < InertiaController
include Filterameter::DeclarativeFilters
include Pagy::Backend

default_sort name: :asc

filter :name, partial: true
filter :city, name: :id, association: :city
filter :region, name: :id, association: :region
filter :country, name: :id, association: :country
filter :continent, name: :id, association: :continent

def index
pagy, companies = pagy(company_scope.all)
companies = build_query_from_filters(Company.with_all_associations)
pagy, companies = pagy(companies)
@companies = CompanySerializer.many(companies)

paginate(pagy)
@pagination = inertia_pagination(pagy)
end

def show
company = company_scope.friendly.find(params[:id])
company = Company.with_all_associations.friendly.find(params[:id])
@company = CompanySerializer.one(company)
end

private

def company_scope
Company.includes(:technologies, :continent, :country, :region, :city)
end
end
4 changes: 2 additions & 2 deletions app/controllers/inertia_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ def set_default_inertia_rendering
inertia_render(inertia: true) unless performed?
end

def paginate(pagy)
def inertia_pagination(pagy)
pagination = pagy_metadata(pagy)
@pagination = PaginationSerializer.render(pagination)
PaginationSerializer.render(pagination)
end
end
11 changes: 4 additions & 7 deletions app/frontend/layouts/application.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import Footer from "@/layouts/application/footer";
import Header from "@/layouts/application/header";

interface Props {
children: React.ReactNode;
}

function Layout({ children }: Props) {
return (
<div className="min-h-screen bg-gray-100">
<header className="bg-white shadow">
<div className="container mx-auto py-6">
<h1 className="text-3xl font-bold text-red-600">Ruby Companies</h1>
</div>
</header>
<main>
<div className="min-h-screen bg-gray-100 flex flex-col">
<Header />
<main className="flex-grow">
<div className="container mx-auto pt-5 pb-10">{children}</div>
</main>
<Footer />
Expand Down
56 changes: 56 additions & 0 deletions app/frontend/layouts/application/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useForm, usePage } from "@inertiajs/react";
import { Search } from "lucide-react";

import Link from "@/components/link";
import { Input } from "@/components/ui/input";
import { Spinner } from "@/components/ui/spinner";

function Header() {
const { props } = usePage();

const { data, setData, get, processing } = useForm({
q: (props.q as string) || "",
});

const handleSearch = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
get("/companies", {
preserveState: true,
preserveScroll: true,
});
};

const Icon = processing ? Spinner : Search;

return (
<header className="bg-white shadow">
<div className="container mx-auto py-6">
<div className="flex flex-col sm:flex-row justify-between items-center">
<Link
href="/"
className="text-3xl font-bold text-red-600 mb-4 sm:mb-0"
>
Ruby Companies
</Link>
<form onSubmit={handleSearch} className="w-full sm:w-auto">
<div className="relative ml-auto flex-1 md:grow-0">
<Icon className="absolute left-2.5 top-3 h-4 w-4 text-muted-foreground" />
<Input
type="search"
placeholder="Search..."
className="w-full rounded-lg bg-background pl-8 md:w-[200px] lg:w-[336px]"
value={data.q}
onChange={(event) => setData("q", event.target.value)}
disabled={processing}
/>
</div>
</form>
</div>
</div>
</header>
);
}

Header.displayName = "layouts/application/header";

export default Header;
4 changes: 4 additions & 0 deletions app/models/company.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class Company < ApplicationRecord
validates :website, url: { no_local: true, public_suffix: true }
validates :careers_page, url: { no_local: true, public_suffix: true }, allow_blank: true
validates :slug, presence: true

Check failure on line 21 in app/models/company.rb

View workflow job for this annotation

GitHub Actions / lint

Layout/TrailingWhitespace: Trailing whitespace detected.
scope :with_technologies, -> { includes(:technologies) }
scope :with_locations, -> { includes(:continent, country: :continent, region: :country, city: :region) }
scope :with_all_associations, -> { with_technologies.with_locations }

private

Expand Down
4 changes: 4 additions & 0 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ def destroy_data!
CompanyTechnology.destroy_all
Technology.destroy_all
Company.destroy_all
City.destroy_all
Country.destroy_all
Region.destroy_all
Continent.destroy_all
end

def seed_geo_data
Expand Down
4 changes: 4 additions & 0 deletions spec/controllers/companies_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
expect_inertia.to(render_component("companies/index"))
expect(inertia.props[:companies]).to(be_serialized_many(companies))
end

it "has a valid filter declaration" do
expect(described_class.declarations_validator).to(be_valid)
end
end

describe "#show", inertia: true do
Expand Down
2 changes: 1 addition & 1 deletion spec/support/inertia.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
@actual_ids = actual&.map { |item| item[:id] }
@expected_ids = expected_scope&.map(&:id)

expect(@actual_ids).to(eq(@expected_ids))
expect(@actual_ids).to(contain_exactly(*@expected_ids))
end

failure_message do
Expand Down

0 comments on commit 2a51ea0

Please sign in to comment.