diff --git a/app/controllers/companies_controller.rb b/app/controllers/companies_controller.rb
index 6808a0b..adac624 100644
--- a/app/controllers/companies_controller.rb
+++ b/app/controllers/companies_controller.rb
@@ -22,6 +22,11 @@ def index
@selected_technology = params[:technology]
end
+ # Filter by preferred status if provided
+ if params[:preferred].present?
+ @companies = @companies.where(preferred: params[:preferred] == "true")
+ end
+
# Skip sorting for tech_stack since it's aggregated data, but allow other columns
if params[:sort].present? && params[:sort] != "tech_stack"
direction = params[:direction] == "desc" ? "desc" : "asc"
@@ -103,7 +108,7 @@ def set_company
# Only allow a list of trusted parameters through.
def company_params
params.expect(company: [
- :name, :industry, :company_type, :location, :size, :website, :linkedin, :known_tech_stack,
+ :name, :industry, :company_type, :location, :size, :website, :linkedin, :known_tech_stack, :preferred,
:primary_product, :revenue_model, :funding_stage, :estimated_revenue, :estimated_employees,
:growth_signal, :product_maturity, :engineering_maturity, :process_maturity,
:market_position, :competitor_tier, :brand_signal_strength, :market_size_estimate
diff --git a/app/models/company.rb b/app/models/company.rb
index 50f6afa..0de5dc6 100644
--- a/app/models/company.rb
+++ b/app/models/company.rb
@@ -24,6 +24,8 @@ class Company < ApplicationRecord
Staffing: "Staffing"
}, validate: true
+ scope :preferred, -> { where(preferred: true) }
+
def tech_stack_summary
opportunities
.joins(:technologies)
diff --git a/app/services/role_focus_analyzer.rb b/app/services/role_focus_analyzer.rb
index 22e7746..233d31a 100644
--- a/app/services/role_focus_analyzer.rb
+++ b/app/services/role_focus_analyzer.rb
@@ -141,7 +141,6 @@ def generate_tech_insights_for_opportunities(opportunities, limit)
tech_data.each do |tech_name, count|
percentage = (count.to_f / total_opps * 100).round
- next if percentage < 15 # Only show technologies in 15%+ of jobs
tech = Technology.find_by(name: tech_name)
next unless tech
diff --git a/app/views/companies/_company.html.erb b/app/views/companies/_company.html.erb
index 0c194ee..c580cdb 100644
--- a/app/views/companies/_company.html.erb
+++ b/app/views/companies/_company.html.erb
@@ -4,6 +4,7 @@
<%= company.company_type || "—" %> |
<%= company.location %> |
<%= company.size.present? ? company.size : "—" %> |
+ <%= company.preferred? ? "✓" : "" %> |
<%= company.website %> |
<%= company.linkedin %> |
diff --git a/app/views/companies/_form.html.erb b/app/views/companies/_form.html.erb
index 73bd2d2..533a9a5 100644
--- a/app/views/companies/_form.html.erb
+++ b/app/views/companies/_form.html.erb
@@ -32,6 +32,14 @@
class: "form-select" %>
+
+
<%= form.label :location, class: "form-label" %>
<%= form.text_field :location, class: "form-input" %>
diff --git a/app/views/companies/index.html.erb b/app/views/companies/index.html.erb
index a17f10b..f6382a4 100644
--- a/app/views/companies/index.html.erb
+++ b/app/views/companies/index.html.erb
@@ -11,14 +11,14 @@
<%= form_with url: companies_path, method: :get, local: true, class: "opportunities-filter-form" do |f| %>
<%= hidden_field_tag :company_query, params[:company_query] %>
-
- <%= f.select :technology,
- options_from_collection_for_select(@technologies, :name, :name, @selected_technology),
- { include_blank: "All Technologies" },
- id: "technology_filter",
+
+ <%= f.select :preferred,
+ [["All Companies", ""], ["Preferred Only", "true"], ["Not Preferred Only", "false"]],
+ { selected: params[:preferred] || "" },
+ id: "preferred_filter",
class: "form-select opportunities-status-select" %>
<%= f.submit "Filter", class: "btn btn-primary" %>
- <% if @selected_technology.present? %>
+ <% if params[:preferred].present? %>
<%= link_to "Clear", companies_path(company_query: params[:company_query]), class: "btn btn-secondary" %>
<% end %>
<% end %>
@@ -48,6 +48,7 @@
<%= sortable_link :company_type, "Type" %> |
<%= sortable_link :location %> |
<%= sortable_link :size, "Size" %> |
+ <%= sortable_link :preferred, "Preferred" %> |
<%= sortable_link :website %> |
<%= sortable_link :linkedin %> |
Tech Stack |
diff --git a/app/views/opportunities/_form.html.erb b/app/views/opportunities/_form.html.erb
index 33ba811..6dd49ce 100644
--- a/app/views/opportunities/_form.html.erb
+++ b/app/views/opportunities/_form.html.erb
@@ -135,20 +135,25 @@
<%= form.label :source, style: "display: block" %>
<%= form.select :source,
options_for_select([
- ["LinkedIn", "linkedin"],
- ["JobrightAI", "jobrightai"],
- ["Y Combinator", "y_combinator"],
- ["Indeed", "indeed"],
- ["Company Website", "company_website"],
- ["Glassdoor", "glassdoor"],
["AngelList", "angellist"],
+ ["Braintrust", "braintrust"],
+ ["Company Website", "company_website"],
["Dice", "dice"],
- ["Monster", "monster"],
- ["ZipRecruiter", "ziprecruiter"],
- ["Referral", "referral"],
- ["Recruiter", "recruiter"],
+ ["Glassdoor", "glassdoor"],
+ ["gun.io", "gun.io"],
+ ["Indeed", "indeed"],
["Job Fair", "job_fair"],
- ["Other", "other"]
+ ["JobrightAI", "jobrightai"],
+ ["lemon.io", "lemon.io"],
+ ["LinkedIn", "linkedin"],
+ ["Other", "other"],
+ ["Recruiter", "recruiter"],
+ ["Referral", "referral"],
+ ["Toptal", "toptal"],
+ ["Upwork", "upwork"],
+ ["Wellfound", "wellfound"],
+ ["Y Combinator", "y_combinator"],
+ ["ZipRecruiter", "ziprecruiter"]
], opportunity.source),
{ prompt: "Select source" },
{ style: "display: block; width: 250px; height: 30px;" } %>
diff --git a/db/migrate/20260824213529_add_preferred_to_companies.rb b/db/migrate/20260824213529_add_preferred_to_companies.rb
new file mode 100644
index 0000000..0fbc93a
--- /dev/null
+++ b/db/migrate/20260824213529_add_preferred_to_companies.rb
@@ -0,0 +1,5 @@
+class AddPreferredToCompanies < ActiveRecord::Migration[8.0]
+ def change
+ add_column :companies, :preferred, :boolean, default: false, null: false
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 7052442..cfe7d56 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[8.0].define(version: 2026_05_21_090000) do
+ActiveRecord::Schema[8.0].define(version: 2026_08_24_213529) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@@ -94,6 +94,7 @@
t.integer "personal_upside_score"
t.integer "career_risk_score"
t.bigint "user_id", null: false
+ t.boolean "preferred", default: false, null: false
t.index "lower((name)::text)", name: "index_companies_on_lower_name", unique: true
t.index ["funding_stage"], name: "index_companies_on_funding_stage"
t.index ["growth_signal"], name: "index_companies_on_growth_signal"
diff --git a/spec/requests/dashboard_spec.rb b/spec/requests/dashboard_spec.rb
index 8f422a0..bcc9208 100644
--- a/spec/requests/dashboard_spec.rb
+++ b/spec/requests/dashboard_spec.rb
@@ -82,5 +82,22 @@
expect(response.body).to match(/Companies That Interviewed Me.*? 2<\/div>/m)
expect(response.body).to include("66.7% of applications submitted")
end
+
+ it "renders the tech skills widget when skills are sparse across opportunities" do
+ 7.times do |index|
+ opportunity = Opportunity.create!(
+ company: company,
+ position_title: "Distinct Tech Role #{index}",
+ role_type: "software_engineer"
+ )
+ technology = Technology.create!(name: "Distinct Tech #{index}", category: "Backend")
+ OpportunityTechnology.create!(opportunity: opportunity, technology: technology)
+ end
+
+ get dashboard_path
+
+ expect(response).to have_http_status(:ok)
+ expect(response.body).to include("Top 4 Tech Skills to Focus On")
+ end
end
end
diff --git a/spec/requests/opportunities_spec.rb b/spec/requests/opportunities_spec.rb
index ce03489..f764aa9 100644
--- a/spec/requests/opportunities_spec.rb
+++ b/spec/requests/opportunities_spec.rb
@@ -84,4 +84,19 @@
expect(response.body).not_to include("Interviewing Role")
end
end
+
+ describe "GET /opportunities/new" do
+ it "renders the current opportunity source options" do
+ get new_opportunity_path
+
+ expect(response).to have_http_status(:ok)
+ expect(response.body).to include("Wellfound")
+ expect(response.body).to include("Toptal")
+ expect(response.body).to include("lemon.io")
+ expect(response.body).to include("Braintrust")
+ expect(response.body).to include("gun.io")
+ expect(response.body).to include("Upwork")
+ expect(response.body).not_to include(">Monster<")
+ end
+ end
end
|