Skip to content

Commit 63784c4

Browse files
committed
Fixed: broken stuff, added styling, added tanstack-query and react-hook-form
1 parent a699ca2 commit 63784c4

26 files changed

+1222
-895
lines changed

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
NODE_ENV=development
22
AWS_S3_REGION=us-east-1
3-
AWS_S3_BUCKET_NAME=your-bucket-name
3+
NEXT_PUBLIC_AWS_S3_BUCKET_NAME=your-bucket-name
44
AWS_ACCESS_KEY_ID=key
55
AWS_SECRET_ACCESS_KEY=secret
66
AWS_CLOUDFRONT_DISTRIBUTION=abcdef12345678.cloudfront.net

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@
1111
},
1212
"dependencies": {
1313
"@aws-sdk/client-s3": "^3.633.0",
14+
"@tanstack/react-query": "^5.52.0",
15+
"clsx": "^2.1.1",
16+
"lucide-react": "^0.429.0",
1417
"next": "14.2.5",
1518
"react": "^18",
1619
"react-dom": "^18",
20+
"react-hook-form": "^7.52.2",
1721
"sharp": "^0.33.5",
18-
"sonner": "^1.5.0"
22+
"sonner": "^1.5.0",
23+
"tailwind-merge": "^2.5.2"
1924
},
2025
"devDependencies": {
2126
"@types/eslint": "^9.6.0",

pnpm-lock.yaml

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/api/delete-objects/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export async function DELETE(request: Request) {
2323
}
2424

2525
const deleteParams = {
26-
Bucket: process.env.AWS_S3_BUCKET_NAME!,
26+
Bucket: process.env.NEXT_PUBLIC_AWS_S3_BUCKET_NAME!,
2727
Delete: {
2828
Objects: keys.map((key) => ({ Key: key })),
2929
Quiet: true,

src/app/api/modify/route.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { type NextRequest, NextResponse } from "next/server";
2+
import sharp from "sharp";
3+
4+
interface ImageInfo {
5+
title: string;
6+
width: number | null;
7+
height: number | null;
8+
quality: number;
9+
format: string;
10+
raw: boolean;
11+
}
12+
13+
interface ProcessedImage {
14+
title: string;
15+
previewUrl: string;
16+
sizeKb: number;
17+
format: string;
18+
height: number;
19+
width: number;
20+
aspectRatio: number;
21+
raw: boolean;
22+
}
23+
24+
export async function POST(req: NextRequest) {
25+
try {
26+
const formData = await req.formData();
27+
const processedImages: ProcessedImage[] = [];
28+
29+
// Iterate through formData entries
30+
for (const [key, value] of formData.entries()) {
31+
if (key.startsWith("image")) {
32+
const index = key.replace("image", "");
33+
const imageFile = value as File;
34+
const imageInfo: ImageInfo = parseWithReviver(
35+
formData.get(`modification${index}`) as string,
36+
) as ImageInfo;
37+
38+
const processedImage = await processImage(imageFile, imageInfo);
39+
processedImages.push(processedImage);
40+
}
41+
}
42+
43+
return NextResponse.json(processedImages);
44+
} catch (error) {
45+
console.error("Error processing images:", error);
46+
return NextResponse.json(
47+
{ error: "Failed to process images" },
48+
{ status: 500 },
49+
);
50+
}
51+
}
52+
53+
async function processImage(
54+
imageFile: File,
55+
imageInfo: ImageInfo,
56+
): Promise<ProcessedImage> {
57+
const fileBuffer = await imageFile.arrayBuffer();
58+
const image = sharp(Buffer.from(fileBuffer), { animated: false });
59+
60+
const metadata = await image.metadata();
61+
const raw = imageInfo.raw;
62+
const outputTitle = imageInfo.title;
63+
let outputWidth;
64+
let outputHeight;
65+
let outputFormat;
66+
let quality;
67+
68+
if (raw) {
69+
outputHeight = metadata.height;
70+
outputWidth = metadata.width;
71+
outputFormat = metadata.format;
72+
quality = 100;
73+
} else {
74+
outputHeight = imageInfo.height ?? metadata.height;
75+
outputWidth = imageInfo.width ?? metadata.width;
76+
outputFormat = imageInfo.format ?? metadata.format;
77+
quality = imageInfo.quality;
78+
}
79+
80+
// Process image with sharp
81+
const processedImageBuffer = raw
82+
? await image.toBuffer()
83+
: await image
84+
.resize(outputWidth, outputHeight)
85+
.toFormat(outputFormat as keyof sharp.FormatEnum, {
86+
quality,
87+
})
88+
.toBuffer();
89+
90+
return {
91+
title: outputTitle,
92+
previewUrl: `data:image/${outputFormat};base64,${processedImageBuffer.toString("base64")}`,
93+
sizeKb: processedImageBuffer.length / 1024,
94+
format: outputFormat,
95+
height: outputHeight,
96+
width: outputWidth,
97+
aspectRatio: outputWidth / outputHeight,
98+
raw,
99+
};
100+
}
101+
102+
function parseWithReviver(jsonString: string) {
103+
return JSON.parse(jsonString, (key, value) => {
104+
if (key === "quality" || key === "width" || key === "height") {
105+
return value !== null ? Number(value) : null;
106+
}
107+
108+
return value as unknown;
109+
}) as unknown;
110+
}

src/app/api/objects/route.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// objects/route.ts
2-
31
import { NextResponse } from "next/server";
42
import { S3Client, ListObjectsV2Command } from "@aws-sdk/client-s3";
53

@@ -11,11 +9,25 @@ const s3Client = new S3Client({
119
},
1210
});
1311

14-
export async function GET() {
12+
export async function GET(request: Request) {
13+
const url = new URL(request.url);
14+
const type = url.searchParams.get("type") ?? "server";
15+
16+
let bucketName;
17+
let prefix;
18+
19+
if (type === "server") {
20+
bucketName = process.env.NEXT_PUBLIC_AWS_S3_BUCKET_NAME;
21+
prefix = "assets/";
22+
} else {
23+
bucketName = process.env.NEXT_PUBLIC_AWS_S3_STORAGE_BUCKET_NAME;
24+
prefix = "images/assets/";
25+
}
26+
1527
try {
1628
const params = {
17-
Bucket: process.env.AWS_S3_BUCKET_NAME!,
18-
Prefix: "assets/",
29+
Bucket: bucketName,
30+
Prefix: prefix,
1931
};
2032

2133
const data = await s3Client.send(new ListObjectsV2Command(params));
@@ -36,7 +48,10 @@ export async function GET() {
3648
: "Unknown date";
3749

3850
return {
39-
url: `https://${process.env.AWS_CLOUDFRONT_DISTRIBUTION}.cloudfront.net/${item.Key}`,
51+
url:
52+
type === "storage"
53+
? ""
54+
: `https://${process.env.AWS_CLOUDFRONT_DISTRIBUTION}.cloudfront.net/${item.Key}`,
4055
key: item.Key,
4156
sizeInKB,
4257
lastModified,

0 commit comments

Comments
 (0)