Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions apps/api/src/services/project.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const projectService = {
*/
async fetchGithubProjects(
filters: Partial<FilterProps> = {},
options: Partial<OptionsTypesProps> = {}
options: Partial<OptionsTypesProps> = {},
): Promise<RepositoryProps[]> {
const queryParts: string[] = [];

Expand Down Expand Up @@ -77,6 +77,10 @@ export const projectService = {
primaryLanguage {
name
}
stargazerCount
forkCount
pushedAt
createdAt
}
}
repositoryCount
Expand All @@ -86,7 +90,7 @@ export const projectService = {
{
searchQuery: searchQueryString,
first: options.per_page || 100,
}
},
);

return response.search.nodes;
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/ui/FiltersContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
128 changes: 90 additions & 38 deletions apps/web/src/utils/converter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<FilterProps> = {};

Expand Down Expand Up @@ -139,7 +192,6 @@ export const convertUserInputToApiInput = (

export const convertApiOutputToUserOutput = (
response: RepositoryProps[],
filters: UserInputFilterProps
): DashboardProjectsProps[] => {
const data = response.map((item) => ({
id: item.id,
Expand All @@ -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;
};
4 changes: 4 additions & 0 deletions packages/shared/types/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export type RepositoryProps = {
primaryLanguage: {
name: string;
};
stargazerCount: number;
forkCount: number;
pushedAt: string;
createdAt: string;
};

export type GraphQLResponseProps = {
Expand Down