Skip to content

Commit 3653915

Browse files
authored
Merge pull request #96 from design-sparx/feat/add-products-api
feat: added edit and delete product components
2 parents f2a7d42 + 33e3f29 commit 3653915

File tree

6 files changed

+550
-26
lines changed

6 files changed

+550
-26
lines changed

.changeset/strong-foxes-own.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"mantine-analytics-dashboard": patch
3+
---
4+
5+
feat: added edit and delete product components

app/api/auth/[...nextauth]/route.ts

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,46 @@ import CredentialsProvider from 'next-auth/providers/credentials';
66
// Helper function to refresh the token
77
async function refreshAccessToken(token: JWT) {
88
try {
9+
console.log('Token before refresh attempt:', token);
10+
11+
// Check if accessToken exists
12+
if (!token.accessToken) {
13+
console.error('No access token available for refresh');
14+
return {
15+
...token,
16+
error: 'RefreshAccessTokenError',
17+
};
18+
}
19+
920
const response = await fetch(
1021
`${process.env.NEXT_PUBLIC_API_URL}/api/auth/refresh-token`,
1122
{
1223
method: 'POST',
13-
headers: { 'Content-Type': 'application/json' },
24+
headers: {
25+
'Content-Type': 'application/json',
26+
Authorization: `Bearer ${token.accessToken}`,
27+
},
1428
body: JSON.stringify({
1529
token: token.accessToken,
1630
}),
1731
},
1832
);
1933

34+
// Handle error response properly
2035
if (!response.ok) {
21-
throw new Error('Failed to refresh token');
36+
const errorData = await response.json();
37+
console.error('Refresh token error:', errorData);
38+
return {
39+
...token,
40+
error: 'RefreshAccessTokenError',
41+
};
2242
}
2343

44+
// Only try to read the body if we haven't read it yet
2445
const refreshedTokens = await response.json();
46+
console.log('Refreshed tokens response:', refreshedTokens);
2547

26-
// Update permissions from new token if needed
48+
// Update permissions from a new token if needed
2749
let permissions = [];
2850
if (refreshedTokens.token) {
2951
try {
@@ -41,12 +63,11 @@ async function refreshAccessToken(token: JWT) {
4163
accessToken: refreshedTokens.token,
4264
expiration: refreshedTokens.expiration,
4365
permissions: permissions,
44-
roles: refreshedTokens.roles || token.roles, // Keep existing roles if not in response
66+
roles: refreshedTokens.roles || token.roles,
4567
};
4668
} catch (error) {
4769
console.error('Error refreshing token:', error);
4870

49-
// Return the original token with an expired flag
5071
return {
5172
...token,
5273
error: 'RefreshAccessTokenError',
@@ -138,15 +159,25 @@ export const authOptions: NextAuthOptions = {
138159
token.roles = user.roles;
139160
token.permissions = user.permissions;
140161
token.expiration = user.expiration;
141-
142162
return token;
143163
}
144164

145165
// Return the previous token if the access token has not expired yet
146166
if (token.expiration && new Date(token.expiration) > new Date()) {
167+
console.log('Token not expired, returning existing token');
147168
return token;
148169
}
149170

171+
if (!token.accessToken) {
172+
console.error('No access token available for refresh');
173+
return {
174+
...token,
175+
error: 'RefreshAccessTokenError',
176+
};
177+
}
178+
179+
console.log('Token expired, attempting refresh');
180+
150181
// Access token has expired, try to refresh it
151182
return refreshAccessToken(token);
152183
},
@@ -161,7 +192,7 @@ export const authOptions: NextAuthOptions = {
161192
// @ts-ignore
162193
session.roles = token.roles;
163194
// @ts-ignore
164-
session.permissions = token.permissions; // Add this line
195+
session.permissions = token.permissions;
165196
// @ts-ignore
166197
session.expiration = token.expiration;
167198

@@ -176,8 +207,6 @@ export const authOptions: NextAuthOptions = {
176207
},
177208
async signOut({ token }: any) {
178209
try {
179-
// You could add server-side logout logic here if needed
180-
// For example, invalidating the token on your backend
181210
if (token?.accessToken) {
182211
await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/auth/logout`, {
183212
method: 'POST',

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

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { NextResponse } from 'next/server';
2+
3+
export async function GET(
4+
request: Request,
5+
{ params }: { params: { id: string } },
6+
) {
7+
try {
8+
// Get the authorization header from the incoming request
9+
const authHeader = request.headers.get('authorization');
10+
11+
const headers: HeadersInit = {
12+
'Content-Type': 'application/json',
13+
};
14+
15+
// Add the authorization header if it exists
16+
if (authHeader) {
17+
headers['Authorization'] = authHeader;
18+
}
19+
20+
const response = await fetch(
21+
`${process.env.NEXT_PUBLIC_API_URL}/api/products/${params.id}`,
22+
{
23+
method: 'GET',
24+
headers,
25+
},
26+
);
27+
28+
const data = await response.json();
29+
return NextResponse.json(data);
30+
} catch (error) {
31+
return NextResponse.json(
32+
{ error: 'Failed to fetch product' },
33+
{ status: 500 },
34+
);
35+
}
36+
}
37+
38+
export async function PUT(
39+
request: Request,
40+
{ params }: { params: { id: string } },
41+
) {
42+
try {
43+
const body = await request.json();
44+
45+
// Get the authorization header from the incoming request
46+
const authHeader = request.headers.get('authorization');
47+
48+
const headers: HeadersInit = {
49+
'Content-Type': 'application/json',
50+
};
51+
52+
// Add the authorization header if it exists
53+
if (authHeader) {
54+
headers['Authorization'] = authHeader;
55+
}
56+
57+
const response = await fetch(
58+
`${process.env.NEXT_PUBLIC_API_URL}/api/products/${params.id}`,
59+
{
60+
method: 'PUT',
61+
headers,
62+
body: JSON.stringify(body),
63+
},
64+
);
65+
66+
const data = await response.json();
67+
68+
if (!response.ok) {
69+
return NextResponse.json(
70+
{ error: 'Failed to update product', details: data },
71+
{ status: response.status },
72+
);
73+
}
74+
75+
return NextResponse.json(data);
76+
} catch (error) {
77+
return NextResponse.json(
78+
{ error: 'Failed to update product' },
79+
{ status: 500 },
80+
);
81+
}
82+
}
83+
84+
export async function DELETE(
85+
request: Request,
86+
{ params }: { params: { id: string } },
87+
) {
88+
try {
89+
// Get the authorization header from the incoming request
90+
const authHeader = request.headers.get('authorization');
91+
92+
const headers: HeadersInit = {
93+
'Content-Type': 'application/json',
94+
};
95+
96+
// Add the authorization header if it exists
97+
if (authHeader) {
98+
headers['Authorization'] = authHeader;
99+
}
100+
101+
const response = await fetch(
102+
`${process.env.NEXT_PUBLIC_API_URL}/api/products/${params.id}`,
103+
{
104+
method: 'DELETE',
105+
headers,
106+
},
107+
);
108+
109+
if (!response.ok) {
110+
const data = await response.json();
111+
return NextResponse.json(
112+
{ error: 'Failed to delete product', details: data },
113+
{ status: response.status },
114+
);
115+
}
116+
117+
return NextResponse.json(
118+
{ message: 'Product deleted successfully' },
119+
{ status: 200 },
120+
);
121+
} catch (error) {
122+
return NextResponse.json(
123+
{ error: 'Failed to delete product' },
124+
{ status: 500 },
125+
);
126+
}
127+
}

0 commit comments

Comments
 (0)