Skip to content

Commit 1678f3b

Browse files
committed
feat: Implement Jira-like project management features
- Added API routes for managing issues, sprints, and labels in the project. - Created database schema for issues, sprints, labels, comments, attachments, and more. - Implemented Row Level Security (RLS) policies for data access control. - Developed TypeScript types for enhanced type safety across the application. - Updated documentation for setup, API usage, and troubleshooting. - Introduced helper functions for sprint statistics and auto-generating issue keys. - Established a feature flag for enabling/disabling Supabase backend integration.
1 parent 6e60ab2 commit 1678f3b

11 files changed

Lines changed: 2432 additions & 20 deletions

File tree

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import { NextRequest, NextResponse } from "next/server"
2+
import { createClient } from "@/lib/supabase"
3+
4+
// GET /api/projects/[id]/issues/[issueId]/comments - List all comments for an issue
5+
export async function GET(
6+
request: NextRequest,
7+
{ params }: { params: Promise<{ id: string; issueId: string }> }
8+
) {
9+
try {
10+
const { issueId } = await params
11+
const supabase = createClient()
12+
13+
const { data: comments, error } = await supabase
14+
.from("issue_comments")
15+
.select(`
16+
id,
17+
body,
18+
created_at,
19+
updated_at,
20+
is_internal,
21+
author:author_id(id, email, name, avatar)
22+
`)
23+
.eq("issue_id", issueId)
24+
.order("created_at", { ascending: true })
25+
26+
if (error) {
27+
console.error("Error fetching comments:", error)
28+
return NextResponse.json(
29+
{ error: "Failed to fetch comments", details: error.message },
30+
{ status: 500 }
31+
)
32+
}
33+
34+
return NextResponse.json({
35+
success: true,
36+
data: comments || [],
37+
})
38+
} catch (error) {
39+
console.error("Unexpected error:", error)
40+
return NextResponse.json(
41+
{ error: "Internal server error" },
42+
{ status: 500 }
43+
)
44+
}
45+
}
46+
47+
// POST /api/projects/[id]/issues/[issueId]/comments - Add a comment to an issue
48+
export async function POST(
49+
request: NextRequest,
50+
{ params }: { params: Promise<{ id: string; issueId: string }> }
51+
) {
52+
try {
53+
const { issueId } = await params
54+
const supabase = createClient()
55+
56+
// Get current user
57+
const {
58+
data: { user },
59+
error: authError,
60+
} = await supabase.auth.getUser()
61+
62+
if (authError || !user) {
63+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
64+
}
65+
66+
// Parse request body
67+
const body = await request.json()
68+
const { body: commentBody, is_internal = false } = body
69+
70+
// Validate
71+
if (!commentBody || commentBody.trim() === "") {
72+
return NextResponse.json(
73+
{ error: "Comment body is required" },
74+
{ status: 400 }
75+
)
76+
}
77+
78+
// Create comment
79+
const { data: newComment, error: createError } = await supabase
80+
.from("issue_comments")
81+
.insert({
82+
issue_id: issueId,
83+
author_id: user.id,
84+
body: commentBody.trim(),
85+
is_internal,
86+
})
87+
.select(`
88+
id,
89+
body,
90+
created_at,
91+
updated_at,
92+
is_internal,
93+
author:author_id(id, email, name, avatar)
94+
`)
95+
.single()
96+
97+
if (createError) {
98+
console.error("Error creating comment:", createError)
99+
return NextResponse.json(
100+
{ error: "Failed to create comment", details: createError.message },
101+
{ status: 500 }
102+
)
103+
}
104+
105+
// Log activity
106+
await supabase.from("issue_activity").insert({
107+
issue_id: issueId,
108+
user_id: user.id,
109+
action: "commented",
110+
})
111+
112+
return NextResponse.json({
113+
success: true,
114+
data: newComment,
115+
}, { status: 201 })
116+
} catch (error) {
117+
console.error("Unexpected error:", error)
118+
return NextResponse.json(
119+
{ error: "Internal server error" },
120+
{ status: 500 }
121+
)
122+
}
123+
}

0 commit comments

Comments
 (0)