Skip to content

Commit 2f8031a

Browse files
projects added
1 parent cdfe3e1 commit 2f8031a

File tree

7 files changed

+904
-103
lines changed

7 files changed

+904
-103
lines changed

app/api/project/analyze/route.ts

Lines changed: 0 additions & 102 deletions
This file was deleted.

app/api/projects/[id]/route.ts

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { createClient } from '@supabase/supabase-js'
2+
import { NextRequest, NextResponse } from 'next/server'
3+
import { z } from 'zod'
4+
5+
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
6+
const supabaseServiceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY!
7+
8+
const supabase = createClient(supabaseUrl, supabaseServiceRoleKey)
9+
10+
const updateProjectSchema = z.object({
11+
name: z.string().min(1).max(50).optional(),
12+
description: z.string().max(200).optional(),
13+
visibility: z.enum(['private', 'public']).optional(),
14+
template: z.string().optional(),
15+
})
16+
17+
async function getUserFromAuth(request: NextRequest) {
18+
const authHeader = request.headers.get('authorization')
19+
if (!authHeader || !authHeader.startsWith('Bearer ')) {
20+
return null
21+
}
22+
23+
const token = authHeader.substring(7)
24+
const { data: { user }, error } = await supabase.auth.getUser(token)
25+
26+
if (error || !user) {
27+
return null
28+
}
29+
30+
return user
31+
}
32+
33+
// GET /api/projects/[id] - Get specific project
34+
export async function GET(
35+
request: NextRequest,
36+
{ params }: { params: { id: string } }
37+
) {
38+
try {
39+
const user = await getUserFromAuth(request)
40+
if (!user) {
41+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
42+
}
43+
44+
const { data: project, error } = await supabase
45+
.from('projects')
46+
.select('*')
47+
.eq('id', params.id)
48+
.eq('user_id', user.id)
49+
.single()
50+
51+
if (error) {
52+
if (error.code === 'PGRST116') {
53+
return NextResponse.json({ error: 'Project not found' }, { status: 404 })
54+
}
55+
console.error('Error fetching project:', error)
56+
return NextResponse.json({ error: 'Failed to fetch project' }, { status: 500 })
57+
}
58+
59+
return NextResponse.json({ project })
60+
} catch (error) {
61+
console.error('GET /api/projects/[id] error:', error)
62+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
63+
}
64+
}
65+
66+
// PUT /api/projects/[id] - Update project
67+
export async function PUT(
68+
request: NextRequest,
69+
{ params }: { params: { id: string } }
70+
) {
71+
try {
72+
const user = await getUserFromAuth(request)
73+
if (!user) {
74+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
75+
}
76+
77+
const body = await request.json()
78+
const validatedData = updateProjectSchema.parse(body)
79+
80+
const { data: project, error } = await supabase
81+
.from('projects')
82+
.update({
83+
...validatedData,
84+
updated_at: new Date().toISOString(),
85+
})
86+
.eq('id', params.id)
87+
.eq('user_id', user.id)
88+
.select()
89+
.single()
90+
91+
if (error) {
92+
if (error.code === 'PGRST116') {
93+
return NextResponse.json({ error: 'Project not found' }, { status: 404 })
94+
}
95+
console.error('Error updating project:', error)
96+
return NextResponse.json({ error: 'Failed to update project' }, { status: 500 })
97+
}
98+
99+
return NextResponse.json({ project })
100+
} catch (error) {
101+
if (error instanceof z.ZodError) {
102+
return NextResponse.json({ error: 'Invalid input', details: error.errors }, { status: 400 })
103+
}
104+
105+
console.error('PUT /api/projects/[id] error:', error)
106+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
107+
}
108+
}
109+
110+
// DELETE /api/projects/[id] - Delete project
111+
export async function DELETE(
112+
request: NextRequest,
113+
{ params }: { params: { id: string } }
114+
) {
115+
try {
116+
const user = await getUserFromAuth(request)
117+
if (!user) {
118+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
119+
}
120+
121+
const { error } = await supabase
122+
.from('projects')
123+
.delete()
124+
.eq('id', params.id)
125+
.eq('user_id', user.id)
126+
127+
if (error) {
128+
console.error('Error deleting project:', error)
129+
return NextResponse.json({ error: 'Failed to delete project' }, { status: 500 })
130+
}
131+
132+
return NextResponse.json({ success: true })
133+
} catch (error) {
134+
console.error('DELETE /api/projects/[id] error:', error)
135+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
136+
}
137+
}

app/api/projects/route.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import { createClient } from '@supabase/supabase-js'
2+
import { NextRequest, NextResponse } from 'next/server'
3+
import { z } from 'zod'
4+
5+
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
6+
const supabaseServiceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY!
7+
8+
const supabase = createClient(supabaseUrl, supabaseServiceRoleKey)
9+
10+
const createProjectSchema = z.object({
11+
name: z.string().min(1).max(50),
12+
description: z.string().max(200).optional(),
13+
visibility: z.enum(['private', 'public']),
14+
template: z.string().optional(),
15+
})
16+
17+
const updateProjectSchema = z.object({
18+
name: z.string().min(1).max(50).optional(),
19+
description: z.string().max(200).optional(),
20+
visibility: z.enum(['private', 'public']).optional(),
21+
template: z.string().optional(),
22+
})
23+
24+
async function getUserFromAuth(request: NextRequest) {
25+
const authHeader = request.headers.get('authorization')
26+
if (!authHeader || !authHeader.startsWith('Bearer ')) {
27+
return null
28+
}
29+
30+
const token = authHeader.substring(7)
31+
const { data: { user }, error } = await supabase.auth.getUser(token)
32+
33+
if (error || !user) {
34+
return null
35+
}
36+
37+
return user
38+
}
39+
40+
// GET /api/projects - Get user's projects
41+
export async function GET(request: NextRequest) {
42+
try {
43+
const user = await getUserFromAuth(request)
44+
if (!user) {
45+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
46+
}
47+
48+
const { data: projects, error } = await supabase
49+
.from('projects')
50+
.select('*')
51+
.eq('user_id', user.id)
52+
.order('updated_at', { ascending: false })
53+
54+
if (error) {
55+
console.error('Error fetching projects:', error)
56+
return NextResponse.json({ error: 'Failed to fetch projects' }, { status: 500 })
57+
}
58+
59+
return NextResponse.json({ projects })
60+
} catch (error) {
61+
console.error('GET /api/projects error:', error)
62+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
63+
}
64+
}
65+
66+
// POST /api/projects - Create new project
67+
export async function POST(request: NextRequest) {
68+
try {
69+
const user = await getUserFromAuth(request)
70+
if (!user) {
71+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
72+
}
73+
74+
const body = await request.json()
75+
const validatedData = createProjectSchema.parse(body)
76+
77+
const { data: project, error } = await supabase
78+
.from('projects')
79+
.insert({
80+
name: validatedData.name,
81+
description: validatedData.description,
82+
visibility: validatedData.visibility,
83+
template: validatedData.template,
84+
user_id: user.id,
85+
})
86+
.select()
87+
.single()
88+
89+
if (error) {
90+
console.error('Error creating project:', error)
91+
return NextResponse.json({ error: 'Failed to create project' }, { status: 500 })
92+
}
93+
94+
return NextResponse.json({ project }, { status: 201 })
95+
} catch (error) {
96+
if (error instanceof z.ZodError) {
97+
return NextResponse.json({ error: 'Invalid input', details: error.errors }, { status: 400 })
98+
}
99+
100+
console.error('POST /api/projects error:', error)
101+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
102+
}
103+
}

0 commit comments

Comments
 (0)