Fix Supabase env var names to match Vercel

This commit is contained in:
OpenClaw Bot 2026-02-21 15:37:21 -06:00
parent ee8158993f
commit bacca13be5
4 changed files with 168 additions and 5 deletions

View File

@ -0,0 +1,34 @@
import { NextRequest, NextResponse } from "next/server";
import { addTaskToGantt, parseTaskInput } from "@/lib/server/taskParser";
export async function POST(req: NextRequest) {
try {
const { text } = await req.json();
if (!text || typeof text !== "string") {
return NextResponse.json({ error: "Missing text" }, { status: 400 });
}
const result = await addTaskToGantt(text);
if (!result.success) {
return NextResponse.json({ error: result.error }, { status: 500 });
}
const parsed = parseTaskInput(text);
return NextResponse.json({
success: true,
task: result.task,
parsed: {
title: parsed.title,
assignee: parsed.assigneeId === "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9" ? "Matt" : "Max",
priority: parsed.priority,
dueDate: parsed.dueDate,
},
});
} catch (err: any) {
console.error("Error parsing task:", err);
return NextResponse.json({ error: err.message }, { status: 500 });
}
}

View File

@ -24,8 +24,8 @@ interface UserRow {
} }
function getPublicSupabase() { function getPublicSupabase() {
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL; const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || process.env.SUPABASE_ANON_KEY;
if (!supabaseUrl || !supabaseAnonKey) { if (!supabaseUrl || !supabaseAnonKey) {
throw new Error("Missing Supabase public environment variables"); throw new Error("Missing Supabase public environment variables");
} }

View File

@ -0,0 +1,129 @@
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!;
const supabaseKey = process.env.SUPABASE_SERVICE_ROLE_KEY!;
const supabase = createClient(supabaseUrl, supabaseKey);
// Matt's user ID
const MATT_USER_ID = "0a3e400c-3932-48ae-9b65-f3f9c6f26fe9";
const MAX_USER_ID = "9c29cc99-81a1-4e75-8dff-cd7cc5ceb5aa";
interface ParsedTask {
title: string;
description?: string;
assigneeId: string;
priority: "low" | "medium" | "high";
dueDate?: string;
projectId?: string;
}
export function parseTaskInput(input: string): ParsedTask {
const lower = input.toLowerCase();
// Extract assignee
let assigneeId = MATT_USER_ID;
if (lower.includes("assign to max") || lower.includes("for max")) {
assigneeId = MAX_USER_ID;
}
// Extract priority
let priority: "low" | "medium" | "high" = "medium";
if (lower.includes("urgent") || lower.includes("asap") || lower.includes("high priority")) {
priority = "high";
} else if (lower.includes("low priority") || lower.includes("whenever") || lower.includes("eventually")) {
priority = "low";
}
// Extract due date phrases
let dueDate: string | undefined;
const today = new Date();
if (lower.includes("tomorrow")) {
const d = new Date(today);
d.setDate(d.getDate() + 1);
dueDate = d.toISOString().split("T")[0];
} else if (lower.includes("next week")) {
const d = new Date(today);
d.setDate(d.getDate() + 7);
dueDate = d.toISOString().split("T")[0];
} else if (lower.includes("by friday") || lower.includes("this friday")) {
const d = new Date(today);
const daysUntilFriday = (5 - d.getDay() + 7) % 7 || 7;
d.setDate(d.getDate() + daysUntilFriday);
dueDate = d.toISOString().split("T")[0];
} else if (lower.includes("by monday") || lower.includes("this monday")) {
const d = new Date(today);
const daysUntilMonday = (1 - d.getDay() + 7) % 7 || 7;
d.setDate(d.getDate() + daysUntilMonday);
dueDate = d.toISOString().split("T")[0];
}
// Clean up the title - remove assignee/priority/due date phrases
let title = input
.replace(/assign to (max|matt)/gi, "")
.replace(/for (max|matt)/gi, "")
.replace(/urgent|asap|high priority|low priority/gi, "")
.replace(/tomorrow|next week|by friday|this friday|by monday|this monday/gi, "")
.replace(/\s+/g, " ")
.trim();
// If it starts with "add task" or similar, remove that
title = title.replace(/^(add|create|new)\s+(task|todo|item)\s*[:\-]?\s*/i, "");
// Capitalize first letter
title = title.charAt(0).toUpperCase() + title.slice(1);
return {
title,
assigneeId,
priority,
dueDate,
};
}
export async function addTaskToGantt(input: string): Promise<{ success: boolean; task?: any; error?: string }> {
try {
const parsed = parseTaskInput(input);
// Get default project (first one) or use a specific project
const { data: projects } = await supabase
.from("projects")
.select("id")
.order("created_at", { ascending: true })
.limit(1);
const projectId = projects?.[0]?.id;
if (!projectId) {
return { success: false, error: "No projects found in gantt board" };
}
// Create the task
const { data: task, error } = await supabase
.from("tasks")
.insert({
title: parsed.title,
description: parsed.description || null,
status: "todo",
priority: parsed.priority,
assignee_id: parsed.assigneeId,
created_by: MATT_USER_ID,
project_id: projectId,
due_date: parsed.dueDate || null,
start_date: new Date().toISOString().split("T")[0],
end_date: parsed.dueDate || new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split("T")[0],
})
.select()
.single();
if (error) {
console.error("Error adding task:", error);
return { success: false, error: error.message };
}
return { success: true, task };
} catch (err: any) {
console.error("Failed to add task:", err);
return { success: false, error: err.message };
}
}

View File

@ -1,8 +1,8 @@
import { createClient } from '@supabase/supabase-js'; import { createClient } from '@supabase/supabase-js';
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL; const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL;
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || process.env.SUPABASE_ANON_KEY;
const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY; const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
if (!supabaseUrl || !supabaseAnonKey) { if (!supabaseUrl || !supabaseAnonKey) {
throw new Error( throw new Error(