Fix Supabase env var names to match Vercel
This commit is contained in:
parent
ee8158993f
commit
bacca13be5
34
src/app/api/tasks/natural/route.ts
Normal file
34
src/app/api/tasks/natural/route.ts
Normal 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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
129
src/lib/server/taskParser.ts
Normal file
129
src/lib/server/taskParser.ts
Normal 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 };
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user