backup
This commit is contained in:
parent
db88626eeb
commit
c51ff09cdc
@ -2,17 +2,27 @@ import { prisma } from "@/lib/prisma";
|
|||||||
import { renderTemplate } from "@/lib/templates";
|
import { renderTemplate } from "@/lib/templates";
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
|
import { unstable_cache } from "next/cache";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
params: Promise<{ subdomain: string }>;
|
params: Promise<{ subdomain: string }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getMemorial = unstable_cache(
|
||||||
|
async (subdomain: string) => {
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { subdomain },
|
||||||
|
include: { images: { orderBy: { order: "asc" } } },
|
||||||
|
});
|
||||||
|
return user;
|
||||||
|
},
|
||||||
|
["memorial"],
|
||||||
|
{ revalidate: 3600, tags: ["memorial"] }
|
||||||
|
);
|
||||||
|
|
||||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||||
const { subdomain } = await params;
|
const { subdomain } = await params;
|
||||||
const user = await prisma.user.findUnique({
|
const user = await getMemorial(subdomain);
|
||||||
where: { subdomain },
|
|
||||||
include: { images: { orderBy: { order: "asc" } } },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!user || !user.published) {
|
if (!user || !user.published) {
|
||||||
return { title: "Спомен страницата не е пронајдена" };
|
return { title: "Спомен страницата не е пронајдена" };
|
||||||
@ -36,10 +46,7 @@ export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
|||||||
export default async function MemorialPage({ params }: Props) {
|
export default async function MemorialPage({ params }: Props) {
|
||||||
const { subdomain } = await params;
|
const { subdomain } = await params;
|
||||||
|
|
||||||
const user = await prisma.user.findUnique({
|
const user = await getMemorial(subdomain);
|
||||||
where: { subdomain },
|
|
||||||
include: { images: { orderBy: { order: "asc" } } },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!user || !user.published) {
|
if (!user || !user.published) {
|
||||||
notFound();
|
notFound();
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { auth } from "@clerk/nextjs/server";
|
import { prisma } from "@/lib/prisma";
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
const slug = req.nextUrl.searchParams.get("slug");
|
const slug = req.nextUrl.searchParams.get("slug");
|
||||||
@ -8,7 +8,10 @@ export async function GET(req: NextRequest) {
|
|||||||
return NextResponse.json({ available: false });
|
return NextResponse.json({ available: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { prisma } = await import("@/lib/prisma");
|
|
||||||
const existing = await prisma.user.findUnique({ where: { subdomain: slug } });
|
const existing = await prisma.user.findUnique({ where: { subdomain: slug } });
|
||||||
return NextResponse.json({ available: !existing });
|
|
||||||
|
return NextResponse.json(
|
||||||
|
{ available: !existing },
|
||||||
|
{ headers: { "Cache-Control": "no-store" } }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@ -1,17 +1,7 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
|
import { GetObjectCommand } from "@aws-sdk/client-s3";
|
||||||
|
import { Readable } from "stream";
|
||||||
const s3Client = new S3Client({
|
import { s3Client, S3_BUCKET } from "@/lib/s3";
|
||||||
endpoint: process.env.S3_ENDPOINT,
|
|
||||||
region: process.env.S3_REGION || "eu-2",
|
|
||||||
credentials: {
|
|
||||||
accessKeyId: process.env.S3_ACCESS_KEY_ID!,
|
|
||||||
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
|
|
||||||
},
|
|
||||||
forcePathStyle: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const S3_BUCKET = process.env.S3_BUCKET_NAME || "monuments-images";
|
|
||||||
|
|
||||||
export async function GET(req: NextRequest) {
|
export async function GET(req: NextRequest) {
|
||||||
const key = req.nextUrl.searchParams.get("key");
|
const key = req.nextUrl.searchParams.get("key");
|
||||||
@ -32,13 +22,16 @@ export async function GET(req: NextRequest) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const body = await result.Body!.transformToByteArray();
|
|
||||||
const contentType = result.ContentType || "application/octet-stream";
|
const contentType = result.ContentType || "application/octet-stream";
|
||||||
|
const contentLength = result.ContentLength;
|
||||||
|
|
||||||
return new NextResponse(Buffer.from(body), {
|
const stream = result.Body as Readable;
|
||||||
|
|
||||||
|
return new NextResponse(Readable.toWeb(stream) as ReadableStream, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": contentType,
|
"Content-Type": contentType,
|
||||||
"Cache-Control": "public, max-age=31536000, immutable",
|
"Cache-Control": "public, max-age=31536000, immutable",
|
||||||
|
...(contentLength && { "Content-Length": String(contentLength) }),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
|
||||||
import { prisma } from "@/lib/prisma";
|
|
||||||
|
|
||||||
export async function GET(
|
|
||||||
req: NextRequest,
|
|
||||||
{ params }: { params: Promise<{ subdomain: string }> }
|
|
||||||
) {
|
|
||||||
const { subdomain } = await params;
|
|
||||||
|
|
||||||
const user = await prisma.user.findUnique({
|
|
||||||
where: { subdomain },
|
|
||||||
include: { images: { orderBy: { order: "asc" } } },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!user || !user.published) {
|
|
||||||
return NextResponse.json({ error: "Monument not found" }, { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
return NextResponse.json({
|
|
||||||
id: user.id,
|
|
||||||
title: user.title,
|
|
||||||
description: user.description,
|
|
||||||
subdomain: user.subdomain,
|
|
||||||
templateId: user.templateId,
|
|
||||||
images: user.images,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { auth } from "@clerk/nextjs/server";
|
import { auth } from "@clerk/nextjs/server";
|
||||||
|
import { revalidateTag } from "next/cache";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { generateMonumentQR } from "@/lib/qrcode";
|
import { generateMonumentQR } from "@/lib/qrcode";
|
||||||
import { getPublicUrl } from "@/lib/upload";
|
import { getPublicUrl } from "@/lib/upload";
|
||||||
@ -39,6 +40,9 @@ export async function POST(req: NextRequest) {
|
|||||||
|
|
||||||
let user;
|
let user;
|
||||||
if (existingUser) {
|
if (existingUser) {
|
||||||
|
if (existingUser.subdomain !== subdomain) {
|
||||||
|
revalidateTag(`memorial-${existingUser.subdomain}`);
|
||||||
|
}
|
||||||
await prisma.image.deleteMany({ where: { userId: existingUser.id } });
|
await prisma.image.deleteMany({ where: { userId: existingUser.id } });
|
||||||
user = await prisma.user.update({
|
user = await prisma.user.update({
|
||||||
where: { clerkId: userId },
|
where: { clerkId: userId },
|
||||||
@ -83,6 +87,9 @@ export async function POST(req: NextRequest) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
revalidateTag("memorial");
|
||||||
|
revalidateTag(`memorial-${subdomain}`);
|
||||||
|
|
||||||
const qrCode = await generateMonumentQR(subdomain);
|
const qrCode = await generateMonumentQR(subdomain);
|
||||||
|
|
||||||
return NextResponse.json({
|
return NextResponse.json({
|
||||||
|
|||||||
@ -1,25 +1,9 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { auth } from "@clerk/nextjs/server";
|
import { auth } from "@clerk/nextjs/server";
|
||||||
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
|
import { PutObjectCommand } from "@aws-sdk/client-s3";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import { s3Client, S3_BUCKET, getPublicUrl } from "@/lib/s3";
|
||||||
const s3Client = new S3Client({
|
import { MAX_FILE_SIZE, ALLOWED_TYPES } from "@/lib/upload";
|
||||||
endpoint: process.env.S3_ENDPOINT,
|
|
||||||
region: process.env.S3_REGION || "eu-2",
|
|
||||||
credentials: {
|
|
||||||
accessKeyId: process.env.S3_ACCESS_KEY_ID!,
|
|
||||||
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
|
|
||||||
},
|
|
||||||
forcePathStyle: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const S3_BUCKET = process.env.S3_BUCKET_NAME || "monuments-images";
|
|
||||||
const MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
||||||
const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp", "image/gif"];
|
|
||||||
|
|
||||||
function getPublicUrl(key: string): string {
|
|
||||||
return `/api/image?key=${encodeURIComponent(key)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function POST(req: NextRequest) {
|
export async function POST(req: NextRequest) {
|
||||||
const { userId } = await auth();
|
const { userId } = await auth();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { auth } from "@clerk/nextjs/server";
|
import { auth } from "@clerk/nextjs/server";
|
||||||
|
import { revalidateTag } from "next/cache";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { deleteS3Object } from "@/lib/s3";
|
import { deleteS3Object } from "@/lib/s3";
|
||||||
|
|
||||||
@ -37,12 +38,17 @@ export async function DELETE(
|
|||||||
orderBy: { order: "asc" },
|
orderBy: { order: "asc" },
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 0; i < remainingImages.length; i++) {
|
await prisma.$transaction(
|
||||||
await prisma.image.update({
|
remainingImages.map((img, i) =>
|
||||||
where: { id: remainingImages[i].id },
|
prisma.image.update({
|
||||||
data: { order: i + 1 },
|
where: { id: img.id },
|
||||||
});
|
data: { order: i + 1 },
|
||||||
}
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
revalidateTag("memorial");
|
||||||
|
revalidateTag(`memorial-${image.user.subdomain}`);
|
||||||
|
|
||||||
return NextResponse.json({ success: true });
|
return NextResponse.json({ success: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
import { auth } from "@clerk/nextjs/server";
|
import { auth } from "@clerk/nextjs/server";
|
||||||
|
import { revalidateTag } from "next/cache";
|
||||||
import { prisma } from "@/lib/prisma";
|
import { prisma } from "@/lib/prisma";
|
||||||
import { deleteS3Object } from "@/lib/s3";
|
import { deleteS3Object } from "@/lib/s3";
|
||||||
|
|
||||||
@ -19,16 +20,19 @@ export async function DELETE(req: NextRequest) {
|
|||||||
return NextResponse.json({ error: "Споменот не е пронајден" }, { status: 404 });
|
return NextResponse.json({ error: "Споменот не е пронајден" }, { status: 404 });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const image of user.images) {
|
await Promise.all(
|
||||||
try {
|
user.images.map((image) =>
|
||||||
await deleteS3Object(image.key);
|
deleteS3Object(image.key).catch((e) =>
|
||||||
} catch (e) {
|
console.error("Не успеа бришењето на S3 објект:", image.key, e)
|
||||||
console.error("Не успеа бришењето на S3 објект:", image.key, e);
|
)
|
||||||
}
|
)
|
||||||
}
|
);
|
||||||
|
|
||||||
await prisma.user.delete({ where: { id: user.id } });
|
await prisma.user.delete({ where: { id: user.id } });
|
||||||
|
|
||||||
|
revalidateTag("memorial");
|
||||||
|
revalidateTag(`memorial-${user.subdomain}`);
|
||||||
|
|
||||||
return NextResponse.json({ success: true });
|
return NextResponse.json({ success: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Delete monument error:", error);
|
console.error("Delete monument error:", error);
|
||||||
@ -64,6 +68,9 @@ export async function PUT(req: NextRequest) {
|
|||||||
const body = await req.json();
|
const body = await req.json();
|
||||||
const { title, description, bornDate, passedDate, templateId, published } = body;
|
const { title, description, bornDate, passedDate, templateId, published } = body;
|
||||||
|
|
||||||
|
const existingUser = await prisma.user.findUnique({ where: { clerkId: userId } });
|
||||||
|
const oldSubdomain = existingUser?.subdomain;
|
||||||
|
|
||||||
const user = await prisma.user.update({
|
const user = await prisma.user.update({
|
||||||
where: { clerkId: userId },
|
where: { clerkId: userId },
|
||||||
data: {
|
data: {
|
||||||
@ -77,6 +84,12 @@ export async function PUT(req: NextRequest) {
|
|||||||
include: { images: { orderBy: { order: "asc" } } },
|
include: { images: { orderBy: { order: "asc" } } },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
revalidateTag("memorial");
|
||||||
|
revalidateTag(`memorial-${user.subdomain}`);
|
||||||
|
if (oldSubdomain && oldSubdomain !== user.subdomain) {
|
||||||
|
revalidateTag(`memorial-${oldSubdomain}`);
|
||||||
|
}
|
||||||
|
|
||||||
return NextResponse.json({ user });
|
return NextResponse.json({ user });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Update error:", error);
|
console.error("Update error:", error);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user