add crm auth, email, status update and search
All checks were successful
Auto Deploy / deploy (push) Successful in 1m7s
All checks were successful
Auto Deploy / deploy (push) Successful in 1m7s
This commit is contained in:
38
app/api/admin/login/route.ts
Normal file
38
app/api/admin/login/route.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { createSessionToken, getAdminCredentials, getSessionCookieName } from "@/lib/auth";
|
||||
|
||||
type LoginPayload = {
|
||||
email?: string;
|
||||
password?: string;
|
||||
};
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const body = (await request.json()) as LoginPayload;
|
||||
const email = body.email?.trim().toLowerCase() || "";
|
||||
const password = body.password?.trim() || "";
|
||||
|
||||
const admin = getAdminCredentials();
|
||||
|
||||
if (email !== admin.email.toLowerCase() || password !== admin.password) {
|
||||
return NextResponse.json({ error: "Неверный email или пароль" }, { status: 401 });
|
||||
}
|
||||
|
||||
const token = await createSessionToken(email);
|
||||
const response = NextResponse.json({ success: true });
|
||||
|
||||
response.cookies.set({
|
||||
name: getSessionCookieName(),
|
||||
value: token,
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
maxAge: 60 * 60 * 24 * 7,
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch {
|
||||
return NextResponse.json({ error: "Ошибка авторизации" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
18
app/api/admin/logout/route.ts
Normal file
18
app/api/admin/logout/route.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { getSessionCookieName } from "@/lib/auth";
|
||||
|
||||
export async function POST() {
|
||||
const response = NextResponse.json({ success: true });
|
||||
|
||||
response.cookies.set({
|
||||
name: getSessionCookieName(),
|
||||
value: "",
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
maxAge: 0,
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
43
app/api/leads/[id]/route.ts
Normal file
43
app/api/leads/[id]/route.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
|
||||
const allowedStatuses = [
|
||||
"NEW",
|
||||
"IN_PROGRESS",
|
||||
"CALL_SCHEDULED",
|
||||
"WON",
|
||||
"LOST",
|
||||
] as const;
|
||||
|
||||
type LeadStatus = (typeof allowedStatuses)[number];
|
||||
|
||||
type PatchPayload = {
|
||||
status?: LeadStatus;
|
||||
};
|
||||
|
||||
export async function PATCH(
|
||||
request: Request,
|
||||
context: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const { id } = await context.params;
|
||||
const body = (await request.json()) as PatchPayload;
|
||||
|
||||
if (!body.status || !allowedStatuses.includes(body.status)) {
|
||||
return NextResponse.json({ error: "Некорректный статус" }, { status: 400 });
|
||||
}
|
||||
|
||||
const lead = await prisma.lead.update({
|
||||
where: { id },
|
||||
data: { status: body.status },
|
||||
});
|
||||
|
||||
return NextResponse.json({ success: true, lead });
|
||||
} catch (error) {
|
||||
console.error("PATCH /api/leads/[id] error:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Не удалось обновить статус" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { prisma } from "@/lib/prisma";
|
||||
type LeadPayload = {
|
||||
company?: string;
|
||||
phone?: string;
|
||||
email?: string;
|
||||
message?: string;
|
||||
};
|
||||
|
||||
@@ -13,11 +14,12 @@ export async function POST(request: Request) {
|
||||
|
||||
const company = body.company?.trim();
|
||||
const phone = body.phone?.trim();
|
||||
const email = body.email?.trim().toLowerCase();
|
||||
const message = body.message?.trim() || "";
|
||||
|
||||
if (!company || !phone) {
|
||||
if (!company || !phone || !email) {
|
||||
return NextResponse.json(
|
||||
{ error: "Компания и телефон обязательны" },
|
||||
{ error: "Компания, телефон и email обязательны" },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
@@ -26,6 +28,7 @@ export async function POST(request: Request) {
|
||||
data: {
|
||||
company,
|
||||
phone,
|
||||
email,
|
||||
message,
|
||||
source: "website",
|
||||
},
|
||||
@@ -39,20 +42,4 @@ export async function POST(request: Request) {
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const leads = await prisma.lead.findMany({
|
||||
orderBy: { createdAt: "desc" },
|
||||
});
|
||||
|
||||
return NextResponse.json(leads);
|
||||
} catch (error) {
|
||||
console.error("GET /api/leads error:", error);
|
||||
return NextResponse.json(
|
||||
{ error: "Не удалось получить заявки" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user