aethex-forge/client/api/opportunities.ts
sirpiglr 2ff1292bf6 Add ecosystem filtering to opportunities and update posting form
Adds an 'ecosystem' field to opportunities, enabling filtering on the OpportunitiesHub page and inclusion in the OpportunityPostForm. Also resolves a navigation import error in OpportunitiesHub.tsx.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 9203795e-937a-4306-b81d-b4d5c78c240e
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: c9ce4106-de8c-4aae-ad20-8c89a4901395
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7c94b7a0-29c7-4f2e-94ef-44b2153872b7/9203795e-937a-4306-b81d-b4d5c78c240e/aPpJgbb
Replit-Helium-Checkpoint-Created: true
2025-12-13 02:25:12 +00:00

119 lines
3.4 KiB
TypeScript

export interface OpportunityPoster {
id: string;
username: string;
avatar_url: string;
bio?: string;
}
export interface Opportunity {
id: string;
title: string;
description: string;
job_type: string;
salary_min: number;
salary_max: number;
experience_level: string;
arm_affiliation: string;
ecosystem?: string;
posted_by_id: string;
aethex_creators: OpportunityPoster;
status: string;
created_at: string;
updated_at?: string;
aethex_applications?: { count: number };
}
export interface OpportunitiesResponse {
data: Opportunity[];
pagination: {
page: number;
limit: number;
total: number;
pages: number;
};
}
export interface CreateOpportunityData {
title: string;
description: string;
job_type: string;
salary_min?: number;
salary_max?: number;
experience_level?: string;
arm_affiliation: string;
ecosystem?: string;
}
const API_BASE = import.meta.env.VITE_API_BASE || "";
export async function getOpportunities(filters?: {
arm?: string;
ecosystem?: string;
search?: string;
jobType?: string;
experienceLevel?: string;
sort?: "recent" | "oldest";
page?: number;
limit?: number;
}): Promise<OpportunitiesResponse> {
const params = new URLSearchParams();
if (filters?.arm) params.append("arm", filters.arm);
if (filters?.ecosystem) params.append("ecosystem", filters.ecosystem);
if (filters?.search) params.append("search", filters.search);
if (filters?.jobType) params.append("jobType", filters.jobType);
if (filters?.experienceLevel)
params.append("experienceLevel", filters.experienceLevel);
if (filters?.sort) params.append("sort", filters.sort);
if (filters?.page) params.append("page", String(filters.page));
if (filters?.limit) params.append("limit", String(filters.limit));
const response = await fetch(`${API_BASE}/api/opportunities?${params}`);
if (!response.ok) throw new Error("Failed to fetch opportunities");
return response.json();
}
export async function getOpportunityById(id: string): Promise<Opportunity> {
const response = await fetch(`${API_BASE}/api/opportunities/${id}`);
if (!response.ok) throw new Error("Opportunity not found");
return response.json();
}
export async function createOpportunity(
data: CreateOpportunityData,
): Promise<Opportunity> {
const response = await fetch(`${API_BASE}/api/opportunities`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error("Failed to create opportunity");
return response.json();
}
export async function updateOpportunity(
id: string,
data: Partial<CreateOpportunityData>,
): Promise<Opportunity> {
const response = await fetch(`${API_BASE}/api/opportunities/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error("Failed to update opportunity");
return response.json();
}
export async function closeOpportunity(id: string): Promise<void> {
const response = await fetch(`${API_BASE}/api/opportunities/${id}/close`, {
method: "POST",
});
if (!response.ok) throw new Error("Failed to close opportunity");
}
export async function getApplicationsForOpportunity(opportunityId: string) {
const response = await fetch(
`${API_BASE}/api/opportunities/${opportunityId}/applications`,
);
if (!response.ok) throw new Error("Failed to fetch applications");
return response.json();
}