Skip to content

Commit 38bca77

Browse files
authored
Merge pull request #94 from design-sparx/feat/add-products-api
feat/add-products-api
2 parents 6728f7d + 7d0940c commit 38bca77

File tree

18 files changed

+995
-55
lines changed

18 files changed

+995
-55
lines changed

app/api/product-categories/route.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { NextResponse } from 'next/server';
2+
3+
export async function GET(request: Request) {
4+
try {
5+
// Get the authorization header from the incoming request
6+
const authHeader = request.headers.get('authorization');
7+
8+
const headers: HeadersInit = {
9+
'Content-Type': 'application/json',
10+
};
11+
12+
// Add the authorization header if it exists
13+
if (authHeader) {
14+
headers['Authorization'] = authHeader;
15+
}
16+
17+
const response = await fetch(
18+
process.env.NEXT_PUBLIC_API_URL + '/api/product-categories',
19+
{
20+
method: 'GET',
21+
headers,
22+
},
23+
);
24+
25+
const data = await response.json();
26+
return NextResponse.json(data);
27+
} catch (error) {
28+
return NextResponse.json(
29+
{ error: 'Failed to fetch product categories' },
30+
{ status: 500 },
31+
);
32+
}
33+
}
34+
35+
export async function POST(request: Request) {
36+
try {
37+
const body = await request.json();
38+
39+
// Get the authorization header from the incoming request
40+
const authHeader = request.headers.get('authorization');
41+
42+
const headers: HeadersInit = {
43+
'Content-Type': 'application/json',
44+
};
45+
46+
// Add the authorization header if it exists
47+
if (authHeader) {
48+
headers['Authorization'] = authHeader;
49+
}
50+
51+
const response = await fetch(
52+
process.env.NEXT_PUBLIC_API_URL + '/api/product-categories',
53+
{
54+
method: 'POST',
55+
headers,
56+
body: JSON.stringify(body),
57+
},
58+
);
59+
60+
const data = await response.json();
61+
62+
if (!response.ok) {
63+
return NextResponse.json(
64+
{ error: 'Failed to create product category', details: data },
65+
{ status: response.status },
66+
);
67+
}
68+
69+
return NextResponse.json(data);
70+
} catch (error) {
71+
return NextResponse.json(
72+
{ error: 'Failed to create product category' },
73+
{ status: 500 },
74+
);
75+
}
76+
}

app/api/products/route.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { NextResponse } from 'next/server';
2+
3+
export async function GET(request: Request) {
4+
try {
5+
// Get the authorization header from the incoming request
6+
const authHeader = request.headers.get('authorization');
7+
8+
const headers: HeadersInit = {
9+
'Content-Type': 'application/json',
10+
};
11+
12+
// Add the authorization header if it exists
13+
if (authHeader) {
14+
headers['Authorization'] = authHeader;
15+
}
16+
17+
const response = await fetch(
18+
process.env.NEXT_PUBLIC_API_URL + '/api/products',
19+
{
20+
method: 'GET',
21+
headers,
22+
},
23+
);
24+
25+
const data = await response.json();
26+
return NextResponse.json(data);
27+
} catch (error) {
28+
return NextResponse.json(
29+
{ error: 'Failed to fetch products' },
30+
{ status: 500 },
31+
);
32+
}
33+
}
34+
35+
export async function POST(request: Request) {
36+
try {
37+
const body = await request.json();
38+
39+
// Get the authorization header from the incoming request
40+
const authHeader = request.headers.get('authorization');
41+
42+
const headers: HeadersInit = {
43+
'Content-Type': 'application/json',
44+
};
45+
46+
// Add the authorization header if it exists
47+
if (authHeader) {
48+
headers['Authorization'] = authHeader;
49+
}
50+
51+
const response = await fetch(
52+
process.env.NEXT_PUBLIC_API_URL + '/api/products',
53+
{
54+
method: 'POST',
55+
headers,
56+
body: JSON.stringify(body),
57+
},
58+
);
59+
60+
const data = await response.json();
61+
62+
if (!response.ok) {
63+
return NextResponse.json(
64+
{ error: 'Failed to create product', details: data },
65+
{ status: response.status },
66+
);
67+
}
68+
69+
return NextResponse.json(data);
70+
} catch (error) {
71+
return NextResponse.json(
72+
{ error: 'Failed to create product' },
73+
{ status: 500 },
74+
);
75+
}
76+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
'use client';
2+
3+
import { useState } from 'react';
4+
5+
import {
6+
Button,
7+
Drawer,
8+
DrawerProps,
9+
LoadingOverlay,
10+
Stack,
11+
TextInput,
12+
Textarea,
13+
} from '@mantine/core';
14+
import { isNotEmpty, useForm } from '@mantine/form';
15+
import { notifications } from '@mantine/notifications';
16+
17+
import { useAuth } from '@/hooks/useAuth';
18+
19+
type NewCategoryDrawerProps = Omit<DrawerProps, 'title' | 'children'> & {
20+
onCategoryCreated?: () => void;
21+
};
22+
23+
export const NewCategoryDrawer = ({
24+
onCategoryCreated,
25+
...drawerProps
26+
}: NewCategoryDrawerProps) => {
27+
const { user, accessToken } = useAuth();
28+
const [loading, setLoading] = useState(false);
29+
30+
const form = useForm({
31+
mode: 'controlled',
32+
initialValues: {
33+
title: '',
34+
description: '',
35+
},
36+
validate: {
37+
title: isNotEmpty('Category title cannot be empty'),
38+
},
39+
});
40+
41+
const handleSubmit = async (values: typeof form.values) => {
42+
setLoading(true);
43+
try {
44+
const payload = {
45+
...values,
46+
createdById: user?.id,
47+
};
48+
49+
const response = await fetch('/api/product-categories', {
50+
method: 'POST',
51+
headers: {
52+
Authorization: 'Bearer ' + accessToken,
53+
'Content-Type': 'application/json',
54+
},
55+
body: JSON.stringify(payload),
56+
});
57+
58+
const data = await response.json();
59+
60+
if (!response.ok) {
61+
throw new Error(data.error || 'Failed to create category');
62+
}
63+
64+
notifications.show({
65+
title: 'Success',
66+
message: 'Category created successfully',
67+
color: 'green',
68+
});
69+
70+
form.reset();
71+
72+
if (drawerProps.onClose) {
73+
drawerProps.onClose();
74+
}
75+
76+
if (onCategoryCreated) {
77+
onCategoryCreated();
78+
}
79+
} catch (error) {
80+
notifications.show({
81+
title: 'Error',
82+
message:
83+
error instanceof Error ? error.message : 'Failed to create category',
84+
color: 'red',
85+
});
86+
} finally {
87+
setLoading(false);
88+
}
89+
};
90+
91+
return (
92+
<Drawer {...drawerProps} title="Create a new product category">
93+
<LoadingOverlay visible={loading} />
94+
<form onSubmit={form.onSubmit(handleSubmit)}>
95+
<Stack>
96+
<TextInput
97+
label="Title"
98+
placeholder="Category title"
99+
key={form.key('title')}
100+
{...form.getInputProps('title')}
101+
required
102+
/>
103+
<Textarea
104+
label="Description"
105+
placeholder="Category description"
106+
key={form.key('description')}
107+
{...form.getInputProps('description')}
108+
/>
109+
<Button type="submit" mt="md" loading={loading}>
110+
Create Category
111+
</Button>
112+
</Stack>
113+
</form>
114+
</Drawer>
115+
);
116+
};
117+
118+
export default NewCategoryDrawer;

0 commit comments

Comments
 (0)