Skip to content

Commit 04417c8

Browse files
committed
feat: implement resume management API with CRUD operations and database schema
- Added API routes for creating, retrieving, updating, and deleting resumes. - Implemented database schema for resumes with necessary fields and policies. - Created a Supabase server client for handling requests in API routes. - Updated documentation to reflect new features and database setup instructions. - Included error handling and user authentication checks in API endpoints.
1 parent 2aa6e6a commit 04417c8

10 files changed

Lines changed: 1020 additions & 15 deletions

File tree

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

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { createRouteHandlerClient } from '@/lib/supabase-server'
2+
import { NextResponse } from 'next/server'
3+
import type { NextRequest } from 'next/server'
4+
5+
export async function GET(
6+
request: NextRequest,
7+
{ params }: { params: { id: string } }
8+
) {
9+
try {
10+
const supabase = createRouteHandlerClient(request)
11+
12+
// Get current user
13+
const { data: { user }, error: authError } = await supabase.auth.getUser()
14+
15+
if (authError || !user) {
16+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
17+
}
18+
19+
const { data: resume, error } = await supabase
20+
.from('resumes')
21+
.select('*')
22+
.eq('id', params.id)
23+
.eq('user_id', user.id)
24+
.single()
25+
26+
if (error) {
27+
console.error('Error fetching resume:', error)
28+
return NextResponse.json({ error: error.message }, { status: 404 })
29+
}
30+
31+
return NextResponse.json({ resume })
32+
} catch (error) {
33+
console.error('Unexpected error:', error)
34+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
35+
}
36+
}
37+
38+
export async function PUT(
39+
request: NextRequest,
40+
{ params }: { params: { id: string } }
41+
) {
42+
try {
43+
const supabase = createRouteHandlerClient(request)
44+
45+
// Get current user
46+
const { data: { user }, error: authError } = await supabase.auth.getUser()
47+
48+
if (authError || !user) {
49+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
50+
}
51+
52+
const body = await request.json()
53+
const {
54+
title,
55+
template,
56+
personalInfo,
57+
summary,
58+
experience,
59+
education,
60+
skills,
61+
certifications,
62+
sectionOrder,
63+
styleSettings,
64+
} = body
65+
66+
// Update resume
67+
const { data: resume, error } = await supabase
68+
.from('resumes')
69+
.update({
70+
title,
71+
template,
72+
personal_info: personalInfo,
73+
summary,
74+
experience,
75+
education,
76+
skills,
77+
certifications,
78+
section_order: sectionOrder,
79+
style_settings: styleSettings,
80+
})
81+
.eq('id', params.id)
82+
.eq('user_id', user.id)
83+
.select()
84+
.single()
85+
86+
if (error) {
87+
console.error('Error updating resume:', error)
88+
return NextResponse.json({ error: error.message }, { status: 500 })
89+
}
90+
91+
return NextResponse.json({ resume })
92+
} catch (error) {
93+
console.error('Unexpected error:', error)
94+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
95+
}
96+
}
97+
98+
export async function DELETE(
99+
request: NextRequest,
100+
{ params }: { params: { id: string } }
101+
) {
102+
try {
103+
const supabase = createRouteHandlerClient(request)
104+
105+
// Get current user
106+
const { data: { user }, error: authError } = await supabase.auth.getUser()
107+
108+
if (authError || !user) {
109+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
110+
}
111+
112+
const { error } = await supabase
113+
.from('resumes')
114+
.delete()
115+
.eq('id', params.id)
116+
.eq('user_id', user.id)
117+
118+
if (error) {
119+
console.error('Error deleting resume:', error)
120+
return NextResponse.json({ error: error.message }, { status: 500 })
121+
}
122+
123+
return NextResponse.json({ success: true })
124+
} catch (error) {
125+
console.error('Unexpected error:', error)
126+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
127+
}
128+
}

app/api/resumes/route.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { createRouteHandlerClient } from '@/lib/supabase-server'
2+
import { NextResponse } from 'next/server'
3+
import type { NextRequest } from 'next/server'
4+
5+
export async function GET(request: NextRequest) {
6+
try {
7+
const supabase = createRouteHandlerClient(request)
8+
9+
// Get current user
10+
const { data: { user }, error: authError } = await supabase.auth.getUser()
11+
12+
if (authError || !user) {
13+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
14+
}
15+
16+
// Fetch all resumes for the user
17+
const { data: resumes, error } = await supabase
18+
.from('resumes')
19+
.select('*')
20+
.eq('user_id', user.id)
21+
.order('updated_at', { ascending: false })
22+
23+
if (error) {
24+
console.error('Error fetching resumes:', error)
25+
return NextResponse.json({ error: error.message }, { status: 500 })
26+
}
27+
28+
return NextResponse.json({ resumes })
29+
} catch (error) {
30+
console.error('Unexpected error:', error)
31+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
32+
}
33+
}
34+
35+
export async function POST(request: NextRequest) {
36+
try {
37+
const supabase = createRouteHandlerClient(request)
38+
39+
// Get current user
40+
const { data: { user }, error: authError } = await supabase.auth.getUser()
41+
42+
if (authError || !user) {
43+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
44+
}
45+
46+
const body = await request.json()
47+
const {
48+
title,
49+
template,
50+
personalInfo,
51+
summary,
52+
experience,
53+
education,
54+
skills,
55+
certifications,
56+
sectionOrder,
57+
styleSettings,
58+
} = body
59+
60+
// Insert new resume
61+
const { data: resume, error } = await supabase
62+
.from('resumes')
63+
.insert({
64+
user_id: user.id,
65+
title,
66+
template,
67+
personal_info: personalInfo,
68+
summary,
69+
experience,
70+
education,
71+
skills,
72+
certifications,
73+
section_order: sectionOrder,
74+
style_settings: styleSettings,
75+
})
76+
.select()
77+
.single()
78+
79+
if (error) {
80+
console.error('Error creating resume:', error)
81+
return NextResponse.json({ error: error.message }, { status: 500 })
82+
}
83+
84+
return NextResponse.json({ resume })
85+
} catch (error) {
86+
console.error('Unexpected error:', error)
87+
return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
88+
}
89+
}

0 commit comments

Comments
 (0)