Create /api/gameforge/sprint endpoint
cgen-a9bf50fc08a54a73971f02028a847099
This commit is contained in:
parent
5aa9356e12
commit
e9441535ae
13 changed files with 721 additions and 0 deletions
50
api/devlink/opportunities.ts
Normal file
50
api/devlink/opportunities.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: opportunities, error } = await supabase
|
||||||
|
.from("devlink_opportunities")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
budget,
|
||||||
|
type,
|
||||||
|
status,
|
||||||
|
skills_required,
|
||||||
|
created_at
|
||||||
|
`)
|
||||||
|
.eq("status", "open")
|
||||||
|
.eq("type", "roblox")
|
||||||
|
.order("created_at", { ascending: false });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Opportunities fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(opportunities || []), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
76
api/devlink/profile.ts
Normal file
76
api/devlink/profile.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: profile, error } = await supabase
|
||||||
|
.from("devlink_profiles")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
user_id,
|
||||||
|
username,
|
||||||
|
profile_views,
|
||||||
|
creations,
|
||||||
|
experiences,
|
||||||
|
certifications,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
`)
|
||||||
|
.eq("user_id", userData.user.id)
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (error && error.code !== "PGRST116") {
|
||||||
|
console.error("Profile fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!profile) {
|
||||||
|
// Create default profile if it doesn't exist
|
||||||
|
const { data: newProfile, error: createError } = await supabase
|
||||||
|
.from("devlink_profiles")
|
||||||
|
.insert([
|
||||||
|
{
|
||||||
|
user_id: userData.user.id,
|
||||||
|
username: userData.user.user_metadata?.username || userData.user.email?.split("@")[0],
|
||||||
|
profile_views: 0,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.select()
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (createError) {
|
||||||
|
console.error("Profile creation error:", createError);
|
||||||
|
return new Response(JSON.stringify({ error: createError.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(newProfile), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(profile), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
53
api/devlink/teams.ts
Normal file
53
api/devlink/teams.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: teams, error } = await supabase
|
||||||
|
.from("devlink_teams")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
members_count,
|
||||||
|
created_at,
|
||||||
|
members:devlink_team_members(
|
||||||
|
id,
|
||||||
|
user_id,
|
||||||
|
role,
|
||||||
|
full_name,
|
||||||
|
avatar_url
|
||||||
|
)
|
||||||
|
`)
|
||||||
|
.contains("members", [{ user_id: userData.user.id }])
|
||||||
|
.order("created_at", { ascending: false });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Teams fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(teams || []), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
53
api/gameforge/sprint.ts
Normal file
53
api/gameforge/sprint.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: sprint, error } = await supabase
|
||||||
|
.from("gameforge_sprints")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
project_id,
|
||||||
|
title,
|
||||||
|
phase,
|
||||||
|
status,
|
||||||
|
start_date,
|
||||||
|
end_date,
|
||||||
|
deadline,
|
||||||
|
gdd,
|
||||||
|
scope
|
||||||
|
`)
|
||||||
|
.eq("user_id", userData.user.id)
|
||||||
|
.order("created_at", { ascending: false })
|
||||||
|
.limit(1)
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (error && error.code !== "PGRST116") {
|
||||||
|
console.error("Sprint fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(sprint || null), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
63
api/gameforge/tasks.ts
Normal file
63
api/gameforge/tasks.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const sprintId = url.searchParams.get("sprint_id");
|
||||||
|
|
||||||
|
let query = supabase
|
||||||
|
.from("gameforge_tasks")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
status,
|
||||||
|
assigned_to:assigned_to_id(
|
||||||
|
id,
|
||||||
|
full_name,
|
||||||
|
avatar_url
|
||||||
|
),
|
||||||
|
priority,
|
||||||
|
due_date,
|
||||||
|
created_at
|
||||||
|
`)
|
||||||
|
.eq("created_by_id", userData.user.id);
|
||||||
|
|
||||||
|
if (sprintId) {
|
||||||
|
query = query.eq("sprint_id", sprintId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: tasks, error } = await query.order("created_at", {
|
||||||
|
ascending: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Tasks fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(tasks || []), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
49
api/labs/bounties.ts
Normal file
49
api/labs/bounties.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: bounties, error } = await supabase
|
||||||
|
.from("labs_bounties")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
reward,
|
||||||
|
difficulty,
|
||||||
|
status,
|
||||||
|
research_track_id,
|
||||||
|
created_at
|
||||||
|
`)
|
||||||
|
.eq("status", "available")
|
||||||
|
.order("reward", { ascending: false });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Bounties fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(bounties || []), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
66
api/labs/ip-portfolio.ts
Normal file
66
api/labs/ip-portfolio.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user is admin in labs
|
||||||
|
const { data: labsAdmin, error: adminError } = await supabase
|
||||||
|
.from("labs_admin")
|
||||||
|
.select("id")
|
||||||
|
.eq("user_id", userData.user.id)
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (adminError && adminError.code !== "PGRST116") {
|
||||||
|
console.error("Admin check error:", adminError);
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAdmin = !!labsAdmin;
|
||||||
|
|
||||||
|
// Fetch IP portfolio (all projects' IP counts)
|
||||||
|
const { data: portfolio, error } = await supabase
|
||||||
|
.from("labs_ip_portfolio")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
patents_count,
|
||||||
|
trademarks_count,
|
||||||
|
trade_secrets_count,
|
||||||
|
copyrights_count,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
|
`)
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (error && error.code !== "PGRST116") {
|
||||||
|
console.error("IP portfolio fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
...portfolio,
|
||||||
|
is_admin: isAdmin,
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(result), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
48
api/labs/publications.ts
Normal file
48
api/labs/publications.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: publications, error } = await supabase
|
||||||
|
.from("labs_publications")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
status,
|
||||||
|
url,
|
||||||
|
published_date,
|
||||||
|
research_track_id,
|
||||||
|
created_at
|
||||||
|
`)
|
||||||
|
.order("published_date", { ascending: false });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Publications fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(publications || []), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
54
api/labs/research-tracks.ts
Normal file
54
api/labs/research-tracks.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: tracks, error } = await supabase
|
||||||
|
.from("labs_research_tracks")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
status,
|
||||||
|
progress,
|
||||||
|
lead_id,
|
||||||
|
lead:lead_id(
|
||||||
|
id,
|
||||||
|
full_name,
|
||||||
|
avatar_url
|
||||||
|
),
|
||||||
|
publications,
|
||||||
|
whitepaper_url,
|
||||||
|
created_at
|
||||||
|
`)
|
||||||
|
.order("created_at", { ascending: false });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Research tracks fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(tracks || []), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
52
api/staff/directory.ts
Normal file
52
api/staff/directory.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: directory, error } = await supabase
|
||||||
|
.from("staff_members")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
user_id,
|
||||||
|
full_name,
|
||||||
|
email,
|
||||||
|
role,
|
||||||
|
department,
|
||||||
|
employment_type,
|
||||||
|
avatar_url,
|
||||||
|
phone,
|
||||||
|
location,
|
||||||
|
username,
|
||||||
|
created_at
|
||||||
|
`)
|
||||||
|
.order("full_name", { ascending: true });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Directory fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(directory || []), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
50
api/staff/invoices.ts
Normal file
50
api/staff/invoices.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: invoices, error } = await supabase
|
||||||
|
.from("contractor_invoices")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
user_id,
|
||||||
|
invoice_number,
|
||||||
|
amount,
|
||||||
|
status,
|
||||||
|
date,
|
||||||
|
due_date,
|
||||||
|
description,
|
||||||
|
created_at
|
||||||
|
`)
|
||||||
|
.eq("user_id", userData.user.id)
|
||||||
|
.order("date", { ascending: false });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("Invoices fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(invoices || []), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
52
api/staff/me.ts
Normal file
52
api/staff/me.ts
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: staffMember, error } = await supabase
|
||||||
|
.from("staff_members")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
user_id,
|
||||||
|
full_name,
|
||||||
|
email,
|
||||||
|
employment_type,
|
||||||
|
department,
|
||||||
|
role,
|
||||||
|
start_date,
|
||||||
|
salary,
|
||||||
|
avatar_url,
|
||||||
|
created_at
|
||||||
|
`)
|
||||||
|
.eq("user_id", userData.user.id)
|
||||||
|
.single();
|
||||||
|
|
||||||
|
if (error && error.code !== "PGRST116") {
|
||||||
|
console.error("Staff member fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(staffMember || null), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
55
api/staff/okrs.ts
Normal file
55
api/staff/okrs.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { supabase } from "../_supabase";
|
||||||
|
|
||||||
|
export default async (req: Request) => {
|
||||||
|
if (req.method !== "GET") {
|
||||||
|
return new Response("Method not allowed", { status: 405 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const token = req.headers.get("Authorization")?.replace("Bearer ", "");
|
||||||
|
if (!token) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: userData } = await supabase.auth.getUser(token);
|
||||||
|
if (!userData.user) {
|
||||||
|
return new Response("Unauthorized", { status: 401 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data: okrs, error } = await supabase
|
||||||
|
.from("staff_okrs")
|
||||||
|
.select(`
|
||||||
|
id,
|
||||||
|
user_id,
|
||||||
|
objective,
|
||||||
|
description,
|
||||||
|
status,
|
||||||
|
quarter,
|
||||||
|
year,
|
||||||
|
key_results(
|
||||||
|
id,
|
||||||
|
title,
|
||||||
|
progress,
|
||||||
|
target_value
|
||||||
|
),
|
||||||
|
created_at
|
||||||
|
`)
|
||||||
|
.eq("user_id", userData.user.id)
|
||||||
|
.order("created_at", { ascending: false });
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error("OKRs fetch error:", error);
|
||||||
|
return new Response(JSON.stringify({ error: error.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Response(JSON.stringify(okrs || []), {
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
return new Response(JSON.stringify({ error: err.message }), {
|
||||||
|
status: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in a new issue