From 0a28708f33f2d783291536c6d008685b46066980 Mon Sep 17 00:00:00 2001 From: VivekArgSharma Date: Thu, 23 Apr 2026 22:17:55 +0530 Subject: [PATCH] fix: show actual filter values per project in OSS search results --- apps/api/src/services/project.service.ts | 8 +- .../src/components/ui/FiltersContainer.tsx | 2 +- apps/web/src/utils/converter.ts | 128 ++++++++++++------ packages/shared/types/projects.ts | 4 + 4 files changed, 101 insertions(+), 41 deletions(-) diff --git a/apps/api/src/services/project.service.ts b/apps/api/src/services/project.service.ts index 7ae4d5e9..4f816de5 100644 --- a/apps/api/src/services/project.service.ts +++ b/apps/api/src/services/project.service.ts @@ -23,7 +23,7 @@ export const projectService = { */ async fetchGithubProjects( filters: Partial = {}, - options: Partial = {} + options: Partial = {}, ): Promise { const queryParts: string[] = []; @@ -77,6 +77,10 @@ export const projectService = { primaryLanguage { name } + stargazerCount + forkCount + pushedAt + createdAt } } repositoryCount @@ -86,7 +90,7 @@ export const projectService = { { searchQuery: searchQueryString, first: options.per_page || 100, - } + }, ); return response.search.nodes; diff --git a/apps/web/src/components/ui/FiltersContainer.tsx b/apps/web/src/components/ui/FiltersContainer.tsx index 84c92feb..70b1ecdc 100644 --- a/apps/web/src/components/ui/FiltersContainer.tsx +++ b/apps/web/src/components/ui/FiltersContainer.tsx @@ -46,7 +46,7 @@ export default function FiltersContainer() { setProjectsNotFound(true); return; } - const modifiedProjects = convertApiOutputToUserOutput(projects, filters); + const modifiedProjects = convertApiOutputToUserOutput(projects); setData(modifiedProjects); setRenderProjects(true); resetFilters(); diff --git a/apps/web/src/utils/converter.ts b/apps/web/src/utils/converter.ts index 53a5c793..6bcc626b 100644 --- a/apps/web/src/utils/converter.ts +++ b/apps/web/src/utils/converter.ts @@ -4,16 +4,89 @@ import { FilterProps, RepositoryProps } from "@opensox/shared/types"; const getDateFromPast = (days: number): string => { const now = new Date(); const pastDate = new Date(now.getTime() - days * 24 * 60 * 60 * 1000); - const year = pastDate.getFullYear(); const month = String(pastDate.getMonth() + 1).padStart(2, "0"); const day = String(pastDate.getDate()).padStart(2, "0"); - return `${year}-${month}-${day}`; }; -// Usage: -// console.log(getDateFromPast(7)); // get the date of 7 days ago from today +const categorize = ( + value: number, + ranges: { [key: string]: { min?: string; max?: string } }, +): string => { + for (const [label, range] of Object.entries(ranges)) { + const min = range.min ? parseInt(range.min) : 0; + const max = range.max ? parseInt(range.max) : Infinity; + if (value >= min && value <= max) return label; + } + return "Very low"; +}; + +const computePopularity = (stars: number): string => { + const ranges: { [key: string]: { min?: string; max?: string } } = { + "Very low": { min: "10", max: "500" }, + Low: { min: "501", max: "1000" }, + Moderate: { min: "1001", max: "2000" }, + High: { min: "2001", max: "5000" }, + "Very high": { min: "5001" }, + }; + return categorize(stars, ranges); +}; + +const computeCompetition = (forks: number): string => { + const ranges: { [key: string]: { min?: string; max?: string } } = { + "Very low": { min: "0", max: "200" }, + Low: { min: "201", max: "500" }, + Moderate: { min: "501", max: "1000" }, + High: { min: "1001", max: "2000" }, + "Very high": { min: "2001" }, + }; + return categorize(forks, ranges); +}; + +const computeStage = (createdAt: string): string => { + const created = new Date(createdAt); + const now = new Date(); + const daysSinceCreation = Math.floor( + (now.getTime() - created.getTime()) / (1000 * 60 * 60 * 24), + ); + if (daysSinceCreation <= 180) return "Very early"; + if (daysSinceCreation <= 365) return "Early"; + if (daysSinceCreation <= 913) return "Emerging"; + return "Established"; +}; + +const computeActivity = (pushedAt: string): string => { + const pushed = new Date(pushedAt); + const now = new Date(); + const daysSincePush = Math.floor( + (now.getTime() - pushed.getTime()) / (1000 * 60 * 60 * 24), + ); + if (daysSincePush <= 0) return "Highest"; + if (daysSincePush <= 7) return "High"; + if (daysSincePush <= 30) return "Normal"; + return "Low"; +}; + +// // USER INPUT EXAMPLE + +// const userInput = { +// "Tech stack": "Python", +// Popularity: "Low", +// Competition: "High", +// Stage: "Very early", +// Activity: "Normal", +// }; + +// API INPUT EXAMPLE + +// const apiInput = { +// language: "python", +// stars: { min: "100", max: "2000" }, +// forks: { min: "50", max: "1000" }, +// pushed: ">=2024-12-08", +// created: ">=2024-12-12", +// }; interface Range { min?: string; @@ -73,41 +146,21 @@ const userInputValues: UserFilterObjProps = { "Very high": { min: "2001" }, }, Stage: { - "Very early": `>=${getDateFromPast(180)}`, // within 6 months - Early: `>=${getDateFromPast(365)}`, // within this year - Emerging: `>=${getDateFromPast(913)}`, // within this 2.5 years - Established: `>=${getDateFromPast(1825)}`, // within last 5 years + "Very early": `>=${getDateFromPast(180)}`, + Early: `>=${getDateFromPast(365)}`, + Emerging: `>=${getDateFromPast(913)}`, + Established: `>=${getDateFromPast(1825)}`, }, Activity: { - Highest: `>=${getDateFromPast(0)}`, // within today - High: `>=${getDateFromPast(7)}`, // within this week - Normal: `>=${getDateFromPast(30)}`, // within this month - Low: `>=${getDateFromPast(365)}`, // withing this year + Highest: `>=${getDateFromPast(0)}`, + High: `>=${getDateFromPast(7)}`, + Normal: `>=${getDateFromPast(30)}`, + Low: `>=${getDateFromPast(365)}`, }, }; -// // USER INPUT EXAMPLE - -// const userInput = { -// "Tech stack": "Python", -// Popularity: "Low", -// Competition: "High", -// Stage: "Very early", -// Activity: "Normal", -// }; - -// API INPUT EXAMPLE - -// const apiInput = { -// language: "python", -// stars: { min: "100", max: "2000" }, -// forks: { min: "50", max: "1000" }, -// pushed: ">=2024-12-08", -// created: ">=2024-12-12", -// }; - export const convertUserInputToApiInput = ( - filter: UserInputFilterProps + filter: UserInputFilterProps, ): FilterProps => { const data: Partial = {}; @@ -139,7 +192,6 @@ export const convertUserInputToApiInput = ( export const convertApiOutputToUserOutput = ( response: RepositoryProps[], - filters: UserInputFilterProps ): DashboardProjectsProps[] => { const data = response.map((item) => ({ id: item.id, @@ -149,10 +201,10 @@ export const convertApiOutputToUserOutput = ( avatarUrl: item.owner.avatarUrl, totalIssueCount: item.issues.totalCount, primaryLanguage: item.primaryLanguage?.name || "Other", - popularity: filters.Popularity ? filters.Popularity : "-", - stage: filters.Stage ? filters.Stage : "-", - competition: filters.Competition ? filters.Competition : "-", - activity: filters.Activity ? filters.Activity : "-", + popularity: computePopularity(item.stargazerCount), + stage: computeStage(item.createdAt), + competition: computeCompetition(item.forkCount), + activity: computeActivity(item.pushedAt), })); return data; }; diff --git a/packages/shared/types/projects.ts b/packages/shared/types/projects.ts index a4b7997a..17ed6039 100644 --- a/packages/shared/types/projects.ts +++ b/packages/shared/types/projects.ts @@ -19,6 +19,10 @@ export type RepositoryProps = { primaryLanguage: { name: string; }; + stargazerCount: number; + forkCount: number; + pushedAt: string; + createdAt: string; }; export type GraphQLResponseProps = {