Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 18 additions & 2 deletions src/app/api/daily-note/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,36 @@ export async function GET(req: NextRequest) {
yesterday.setDate(yesterday.getDate() - 1);
const yesterdayDate = yesterday.toISOString().split("T")[0];

const { data: todayData } = await supabaseAdmin
const { data: todayData, error: todayError } = await supabaseAdmin
.from("daily_notes")
.select("*")
.eq("user_id", userId)
.eq("date", todayDate)
.single();

const { data: yesterdayData } = await supabaseAdmin
if (todayError && todayError.code !== "PGRST116") {
console.error("Failed to fetch today's daily note:", todayError);
return NextResponse.json(
{ error: "Failed to fetch daily notes" },
{ status: 500 }
);
}

const { data: yesterdayData, error: yesterdayError } = await supabaseAdmin
.from("daily_notes")
.select("*")
.eq("user_id", userId)
.eq("date", yesterdayDate)
.single();

if (yesterdayError && yesterdayError.code !== "PGRST116") {
console.error("Failed to fetch yesterday's daily note:", yesterdayError);
return NextResponse.json(
{ error: "Failed to fetch daily notes" },
{ status: 500 }
);
}

return NextResponse.json({
todayNote: todayData?.note || "",
yesterdayNote: yesterdayData?.note || "",
Expand Down
7 changes: 6 additions & 1 deletion src/app/api/goals/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,18 @@ export async function GET() {
if (!user) return Response.json({ error: "User not found" }, { status: 404 });

// Added .limit() to bound the database payload and the subsequent Promise.all loop
const { data: goals } = await supabaseAdmin
const { data: goals, error } = await supabaseAdmin
.from("goals")
.select("*")
.eq("user_id", user.id)
.order("created_at", { ascending: false })
.limit(MAX_GOALS_PER_USER);

if (error) {
console.error("Failed to fetch goals:", error);
return Response.json({ error: "Failed to fetch goals" }, { status: 500 });
}

// Reset progress if we're in a new period
const processedGoals = await Promise.all(
(goals ?? []).map(async (goal: Goal) => {
Expand Down
12 changes: 10 additions & 2 deletions src/app/api/integrations/jira/credentials/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,20 @@ export async function GET(req: NextRequest) {
const result = await requireUser();
if ("error" in result) return result.error;

const { data: credentials } = await supabaseAdmin
const { data: credentials, error } = await supabaseAdmin
.from("jira_credentials")
.select("id, jira_domain, email, project_key, is_active, created_at")
.eq("user_id", result.user.id);

return Response.json({ credentials: credentials || [] });
if (error) {
console.error("Failed to fetch Jira credentials:", error);
return Response.json(
{ error: "Failed to fetch Jira credentials" },
{ status: 500 }
);
}

return Response.json({ credentials: credentials ?? [] });
}

export async function POST(req: NextRequest) {
Expand Down
12 changes: 10 additions & 2 deletions src/app/api/local-coding/keys/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,21 @@ export async function GET() {
const user = await resolveAppUser(session.githubId, session.githubLogin);
if (!user) return Response.json({ error: "User not found" }, { status: 404 });

const { data: keys } = await supabaseAdmin
const { data: keys, error } = await supabaseAdmin
.from("local_coding_api_keys")
.select("id, name, last_used_at, created_at")
.eq("user_id", user.id)
.order("created_at", { ascending: false });

return Response.json({ keys: keys || [] });
if (error) {
console.error("Failed to fetch local coding API keys:", error);
return Response.json(
{ error: "Failed to fetch API keys" },
{ status: 500 }
);
}

return Response.json({ keys: keys ?? [] });
}

export async function POST(req: NextRequest) {
Expand Down
11 changes: 5 additions & 6 deletions src/app/api/local-coding/stats/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,11 @@ export async function GET(req: NextRequest) {
.order("date", { ascending: false });

if (error) {
// Table may not exist in all deployments — degrade gracefully
return Response.json({
dailyData: [],
totals: { totalSeconds: 0, totalDays: 0, avgSecondsPerDay: 0 },
hasData: false,
});
console.error("Failed to fetch local coding stats:", error);
return Response.json(
{ error: "Failed to fetch local coding stats" },
{ status: 500 }
);
}

if (!sessions || sessions.length === 0) {
Expand Down
12 changes: 10 additions & 2 deletions src/app/api/local-coding/sync/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,20 @@ export async function GET(req: NextRequest) {
fromDate.setDate(fromDate.getDate() - days);
const fromDateStr = fromDate.toISOString().slice(0, 10);

const { data: sessions } = await supabaseAdmin
const { data: sessions, error } = await supabaseAdmin
.from("local_coding_sessions")
.select("*")
.eq("user_id", userId)
.gte("date", fromDateStr)
.order("date", { ascending: false });

return Response.json({ sessions: sessions || [] });
if (error) {
console.error("Failed to fetch local coding sessions:", error);
return Response.json(
{ error: "Failed to fetch sessions" },
{ status: 500 }
);
}

return Response.json({ sessions: sessions ?? [] });
}
14 changes: 10 additions & 4 deletions src/app/api/notifications/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ export async function GET() {
.limit(10);

if (error) {
// Table may not exist in all deployments — degrade gracefully
return NextResponse.json({ notifications: [], unreadCount: 0 });
console.error("Failed to fetch notifications:", error);
return NextResponse.json(
{ error: "Failed to fetch notifications" },
{ status: 500 }
);
}

const unreadCount = (data ?? []).filter((n) => !n.read).length;
Expand Down Expand Up @@ -92,8 +95,11 @@ export async function PATCH() {
.eq("read", false);

if (error) {
// Table may not exist — degrade gracefully
return NextResponse.json({ success: true });
console.error("Failed to mark notifications as read:", error);
return NextResponse.json(
{ error: "Failed to update notifications" },
{ status: 500 }
);
}

return NextResponse.json({ success: true });
Expand Down
7 changes: 5 additions & 2 deletions src/app/api/user/github-accounts/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ export async function GET() {
.order("added_at", { ascending: true });

if (error) {
// Table may not exist in all deployments — return empty accounts
return NextResponse.json({ accounts: [] });
console.error("Failed to fetch linked GitHub accounts:", error);
return NextResponse.json(
{ error: "Failed to fetch accounts" },
{ status: 500 }
);
}

return NextResponse.json({
Expand Down
13 changes: 12 additions & 1 deletion src/app/api/user/pinned-repos/details/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,18 @@ export async function GET() {
.eq("github_id", session.githubId)
.single();

if (error || !userRow) {
if (error) {
if (error.code === "PGRST116") {
return Response.json({ pinnedRepos: [] });
}
console.error("Failed to fetch pinned repos from database:", error);
return Response.json(
{ error: "Failed to load pinned repositories" },
{ status: 500 }
);
}

if (!userRow) {
return Response.json({ pinnedRepos: [] });
}

Expand Down
33 changes: 28 additions & 5 deletions src/app/api/wakatime/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,23 @@ export async function GET() {
}

try {
const { data: user } = await supabaseAdmin
const { data: user, error: userError } = await supabaseAdmin
.from("users")
.select("id, wakatime_api_key_encrypted")
.eq("github_id", session.githubId)
.single();

if (userError) {
if (userError.code === "PGRST116") {
return NextResponse.json({ hasData: false, not_configured: true });
}
console.error("Failed to fetch user for Wakatime stats:", userError);
return NextResponse.json(
{ error: "Failed to fetch Wakatime stats" },
{ status: 500 }
);
}

if (!user) {
return NextResponse.json({ hasData: false, not_configured: true });
}
Expand All @@ -31,14 +42,22 @@ export async function GET() {
date7DaysAgo.setDate(date7DaysAgo.getDate() - 7);
const dateStr = date7DaysAgo.toISOString().split("T")[0];

const { data: stats, error } = await supabaseAdmin
const { data: stats, error: statsError } = await supabaseAdmin
.from("wakatime_stats")
.select("*")
.eq("user_id", user.id)
.gte("date", dateStr)
.order("date", { ascending: true });

if (error || !stats || stats.length === 0) {
if (statsError) {
console.error("Failed to fetch Wakatime stats:", statsError);
return NextResponse.json(
{ error: "Failed to fetch Wakatime stats" },
{ status: 500 }
);
}

if (!stats || stats.length === 0) {
return NextResponse.json({ hasData: false });
}

Expand Down Expand Up @@ -78,7 +97,11 @@ export async function GET() {
topLanguage: getTop(languagesMap),
topProject: getTop(projectsMap),
});
} catch {
return NextResponse.json({ hasData: false });
} catch (err) {
console.error("Unexpected error in Wakatime GET:", err);
return NextResponse.json(
{ error: "Failed to fetch Wakatime stats" },
{ status: 500 }
);
}
}
12 changes: 10 additions & 2 deletions src/app/api/webhooks/custom/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,21 @@ export async function GET(req: NextRequest) {
const result = await requireUser();
if ("error" in result) return result.error;

const { data: webhooks } = await supabaseAdmin
const { data: webhooks, error } = await supabaseAdmin
.from("webhook_configs")
.select("id, name, url, events, is_enabled, created_at, updated_at")
.eq("user_id", result.user.id)
.order("created_at", { ascending: false });

return Response.json({ webhooks: webhooks || [] });
if (error) {
console.error("Failed to fetch webhooks:", error);
return Response.json(
{ error: "Failed to fetch webhooks" },
{ status: 500 }
);
}

return Response.json({ webhooks: webhooks ?? [] });
}

export async function POST(req: NextRequest) {
Expand Down
Loading