Skip to content

Commit 1039bd6

Browse files
committed
Updated UI
1 parent e1ddf58 commit 1039bd6

File tree

24 files changed

+1845
-338
lines changed

24 files changed

+1845
-338
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { NextResponse } from "next/server";
2+
import { getServerSession } from "next-auth";
3+
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
4+
import prisma from "@/utils/db";
5+
6+
export async function GET(
7+
request: Request,
8+
{ params }: { params: { projectId: string } }
9+
) {
10+
try {
11+
const session = await getServerSession(authOptions);
12+
if (!session) {
13+
return new NextResponse("Unauthorized", { status: 401 });
14+
}
15+
16+
// Get project files from database
17+
const files = await prisma.projectfile.findMany({
18+
where: {
19+
projectId: params.projectId
20+
},
21+
orderBy: {
22+
uploadedAt: 'desc'
23+
}
24+
});
25+
26+
return NextResponse.json(files);
27+
} catch (error) {
28+
console.error("Error fetching project files:", error);
29+
return new NextResponse("Internal Server Error", { status: 500 });
30+
}
31+
}
32+
33+
export async function POST(
34+
request: Request,
35+
{ params }: { params: { projectId: string } }
36+
) {
37+
try {
38+
const session = await getServerSession(authOptions);
39+
if (!session) {
40+
return new NextResponse("Unauthorized", { status: 401 });
41+
}
42+
43+
const body = await request.json();
44+
const { filename, originalname, path, mimetype, size } = body;
45+
46+
// Create file record in database
47+
const file = await prisma.projectfile.create({
48+
data: {
49+
projectId: params.projectId,
50+
filename,
51+
originalname,
52+
path,
53+
mimetype,
54+
size,
55+
}
56+
});
57+
58+
return NextResponse.json(file);
59+
} catch (error) {
60+
console.error("Error creating project file:", error);
61+
return new NextResponse("Internal Server Error", { status: 500 });
62+
}
63+
}

app/api/contractor/projects/[projectId]/materials/[materialId]/route.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { NextResponse } from "next/server";
22
import { getServerSession } from "next-auth";
3-
import prisma from "@/utils/db";
43
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
4+
import prisma from "@/utils/db";
55

6-
// PUT /api/contractor/projects/[projectId]/materials/[materialId]
6+
// PUT handler: Update a material
77
export async function PUT(
88
request: Request,
99
{ params }: { params: { projectId: string; materialId: string } }
@@ -25,6 +25,7 @@ export async function PUT(
2525
return new NextResponse("Project not found", { status: 404 });
2626
}
2727

28+
// Parse the request body
2829
const body = await request.json();
2930
const { quantity } = body;
3031

@@ -58,7 +59,7 @@ export async function PUT(
5859
}
5960
}
6061

61-
// DELETE /api/contractor/projects/[projectId]/materials/[materialId]
62+
// DELETE handler: Delete a material
6263
export async function DELETE(
6364
request: Request,
6465
{ params }: { params: { projectId: string; materialId: string } }

app/api/contractor/projects/[projectId]/materials/route.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ export async function GET(
6969
});
7070

7171
// Transform the data to include name property
72-
const transformedMaterials = materials.map((material: ProjectProductWithProduct) => ({
72+
const transformedMaterials = materials.map((material: any) => ({
7373
...material,
74-
name: material.product.title,
74+
name: material.product?.title || "Unknown Material",
75+
unit: "piece", // Default unit
7576
}));
7677

7778
return NextResponse.json(transformedMaterials);
@@ -135,6 +136,7 @@ export async function POST(
135136
const transformedMaterial = {
136137
...material,
137138
name: material.product.title,
139+
unit: "piece",
138140
};
139141

140142
return NextResponse.json(transformedMaterial);

app/api/contractor/projects/[projectId]/recalculate/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { getServerSession } from "next-auth";
33
import prisma from "@/utils/db";
44
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
55

6-
// POST /api/contractor/projects/[projectId]/recalculate
6+
// POST handler: Recalculate project item count
77
export async function POST(
88
request: Request,
99
{ params }: { params: { projectId: string } }

app/api/contractor/projects/route.ts

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { getServerSession } from "next-auth";
22
import { NextResponse } from "next/server";
33
import prisma from "@/server/utills/db";
4+
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
5+
import { promises as fs } from "fs";
6+
import path from "path";
47

58
export async function GET() {
69
try {
@@ -18,7 +21,7 @@ export async function GET() {
1821
return new NextResponse("Unauthorized", { status: 401 });
1922
}
2023

21-
const projects = await prisma.Project.findMany({
24+
const projects = await prisma.project.findMany({
2225
where: { contractorId: user.id },
2326
orderBy: { createdAt: "desc" },
2427
});
@@ -32,44 +35,69 @@ export async function GET() {
3235

3336
export async function POST(req: Request) {
3437
try {
35-
const session = await getServerSession();
36-
console.log("[PROJECTS_POST] Session:", session);
37-
38-
if (!session?.user?.email) {
38+
const session = await getServerSession(authOptions);
39+
if (!session) {
3940
return new NextResponse("Unauthorized", { status: 401 });
4041
}
4142

42-
const user = await prisma.user.findUnique({
43-
where: { email: session.user.email },
43+
const { name, filePaths } = await req.json();
44+
45+
// Create project using backend API
46+
const projectResponse = await fetch("http://localhost:3001/api/projects", {
47+
method: "POST",
48+
headers: {
49+
"Content-Type": "application/json",
50+
},
51+
body: JSON.stringify({
52+
name,
53+
contractorId: session.user.id,
54+
}),
4455
});
45-
console.log("[PROJECTS_POST] User:", user);
4656

47-
if (!user) {
48-
return new NextResponse("Unauthorized", { status: 401 });
57+
if (!projectResponse.ok) {
58+
throw new Error("Failed to create project");
4959
}
5060

51-
const body = await req.json();
52-
console.log("[PROJECTS_POST] Request body:", body);
53-
const { name } = body;
61+
const project = await projectResponse.json();
5462

55-
if (!name) {
56-
return new NextResponse("Name is required", { status: 400 });
57-
}
63+
// If there are files, move them from temp to project directory
64+
if (filePaths && filePaths.length > 0) {
65+
// Create project directory
66+
const projectDir = path.join(process.cwd(), "server", "uploads", project.id);
67+
await fs.mkdir(projectDir, { recursive: true });
5868

59-
console.log("[PROJECTS_POST] Creating project with:", { name, contractorId: user.id });
60-
const project = await prisma.Project.create({
61-
data: {
62-
name,
63-
contractorId: user.id,
64-
},
65-
});
66-
console.log("[PROJECTS_POST] Created project:", project);
69+
// Move each file and create file records
70+
for (const tempPath of filePaths) {
71+
const fileName = path.basename(tempPath);
72+
const sourcePath = path.join(process.cwd(), "server", tempPath);
73+
const targetPath = path.join(projectDir, fileName);
74+
75+
// Move file from temp to project directory
76+
await fs.rename(sourcePath, targetPath);
77+
78+
// Create file record in database
79+
await fetch(`http://localhost:3001/api/projects/${project.id}/files`, {
80+
method: "POST",
81+
headers: {
82+
"Content-Type": "application/json",
83+
},
84+
body: JSON.stringify({
85+
filename: fileName,
86+
originalname: fileName.substring(37), // Remove UUID prefix
87+
path: `uploads/${project.id}/${fileName}`,
88+
mimetype: "application/pdf",
89+
size: (await fs.stat(targetPath)).size,
90+
}),
91+
});
92+
}
93+
}
6794

6895
return NextResponse.json(project);
6996
} catch (error) {
70-
console.error("[PROJECTS_POST] Error details:", error);
71-
// Return more specific error message if available
72-
const errorMessage = error instanceof Error ? error.message : "Internal error";
73-
return new NextResponse(errorMessage, { status: 500 });
97+
console.error("Error creating project:", error);
98+
return new NextResponse(
99+
error instanceof Error ? error.message : "Internal Server Error",
100+
{ status: 500 }
101+
);
74102
}
75103
}

app/api/contractor/projects/upload-material/route.ts

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { NextResponse } from "next/server";
22
import { getServerSession } from "next-auth";
33
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
4+
import fs from "fs";
5+
import path from "path";
46
import prisma from "@/server/utills/db";
57

68
interface Material {
@@ -23,19 +25,41 @@ export async function POST(req: Request) {
2325
}
2426

2527
try {
26-
const materials: Material[] = [];
27-
28-
for (const material of materials) {
29-
await prisma.projectProduct.create({
30-
data: {
31-
projectId: projectId,
32-
productId: material.productId,
33-
quantity: material.quantity,
34-
},
35-
});
28+
// Verify the project exists and belongs to the user
29+
const project = await prisma.project.findUnique({
30+
where: { id: projectId },
31+
});
32+
33+
if (!project) {
34+
return new NextResponse("Project not found", { status: 404 });
35+
}
36+
37+
// Check if file exists
38+
const fullFilePath = path.join(process.cwd(), filePath);
39+
const fileExists = await fs.promises.access(fullFilePath)
40+
.then(() => true)
41+
.catch(() => false);
42+
43+
if (!fileExists) {
44+
return new NextResponse("File not found", { status: 404 });
3645
}
3746

38-
return NextResponse.json({ message: "Materials uploaded successfully" });
47+
// In a real implementation, you would parse the PDF here
48+
// and extract materials list
49+
50+
// Create a placeholder material for demo purposes
51+
const newMaterial = await prisma.projectProduct.create({
52+
data: {
53+
projectId,
54+
productId: "placeholder-product-id", // You would determine this from the file
55+
quantity: 1,
56+
},
57+
});
58+
59+
return NextResponse.json({
60+
message: "Materials uploaded successfully",
61+
material: newMaterial
62+
});
3963
} catch (error) {
4064
console.error("Error uploading materials:", error);
4165
return new NextResponse("Internal Server Error", { status: 500 });

app/api/contractor/projects/uploaded-files/route.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@ export async function GET() {
66
const uploadDir = path.join(process.cwd(), "server", "uploads");
77

88
try {
9+
// Create the uploads directory if it doesn't exist
10+
await fs.promises.mkdir(uploadDir, { recursive: true });
11+
12+
// Check if directory exists before reading
13+
const dirExists = await fs.promises.access(uploadDir)
14+
.then(() => true)
15+
.catch(() => false);
16+
17+
if (!dirExists) {
18+
return NextResponse.json([]);
19+
}
20+
921
const files = await fs.promises.readdir(uploadDir);
1022
const pdfFiles = files
1123
.filter((file) => file.endsWith(".pdf"))
@@ -17,6 +29,7 @@ export async function GET() {
1729
return NextResponse.json(pdfFiles);
1830
} catch (error) {
1931
console.error("Error reading upload directory:", error);
20-
return new NextResponse("Internal Server Error", { status: 500 });
32+
// Return empty array instead of error when directory doesn't exist or can't be read
33+
return NextResponse.json([]);
2134
}
2235
}

0 commit comments

Comments
 (0)