diff --git a/.gitignore b/.gitignore index 5ef6a52..45254b6 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +/app/generated/prisma diff --git a/Dockerfile b/Dockerfile index 05c40ef..530d907 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,7 @@ FROM base AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . +RUN npx prisma generate RUN npm run build FROM base AS runner @@ -19,6 +20,7 @@ ENV PORT=3000 ENV HOSTNAME=0.0.0.0 COPY --from=builder /app/public ./public +COPY --from=builder /app/prisma ./prisma COPY --from=builder /app/.next/standalone ./ COPY --from=builder /app/.next/static ./.next/static diff --git a/app/admin/leads/page.tsx b/app/admin/leads/page.tsx new file mode 100644 index 0000000..3e4593d --- /dev/null +++ b/app/admin/leads/page.tsx @@ -0,0 +1,56 @@ +import { prisma } from "@/lib/prisma"; + +export const dynamic = "force-dynamic"; + +export default async function AdminLeadsPage() { + const leads = await prisma.lead.findMany({ + orderBy: { createdAt: "desc" }, + }); + + return ( +
+
+

Заявки

+ +
+ + + + + + + + + + + + + {leads.map((lead) => ( + + + + + + + + + ))} + + {leads.length === 0 && ( + + + + )} + +
ДатаКомпанияТелефонСообщениеСтатусИсточник
+ {new Date(lead.createdAt).toLocaleString("ru-RU")} + {lead.company}{lead.phone} + {lead.message || "—"} + {lead.status}{lead.source}
+ Пока заявок нет +
+
+
+
+ ); +} \ No newline at end of file diff --git a/app/api/leads/route.ts b/app/api/leads/route.ts new file mode 100644 index 0000000..06c5dc7 --- /dev/null +++ b/app/api/leads/route.ts @@ -0,0 +1,58 @@ +import { NextResponse } from "next/server"; +import { prisma } from "@/lib/prisma"; + +type LeadPayload = { + company?: string; + phone?: string; + message?: string; +}; + +export async function POST(request: Request) { + try { + const body = (await request.json()) as LeadPayload; + + const company = body.company?.trim(); + const phone = body.phone?.trim(); + const message = body.message?.trim() || ""; + + if (!company || !phone) { + return NextResponse.json( + { error: "Компания и телефон обязательны" }, + { status: 400 } + ); + } + + const lead = await prisma.lead.create({ + data: { + company, + phone, + message, + source: "website", + }, + }); + + return NextResponse.json({ success: true, leadId: lead.id }, { status: 201 }); + } catch (error) { + console.error("POST /api/leads error:", error); + return NextResponse.json( + { error: "Не удалось сохранить заявку" }, + { 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 } + ); + } +} \ No newline at end of file diff --git a/app/api/test/route.ts b/app/api/test/route.ts new file mode 100644 index 0000000..1176f2c --- /dev/null +++ b/app/api/test/route.ts @@ -0,0 +1,10 @@ +import { prisma } from "@/lib/prisma"; + +export async function GET() { + const leads = await prisma.lead.findMany(); + + return Response.json({ + ok: true, + count: leads.length, + }); +} \ No newline at end of file diff --git a/app/page.tsx b/app/page.tsx index e505167..5f398f6 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,5 +1,6 @@ import Link from "next/link"; import Image from "next/image"; +import LeadForm from "@/components/lead-form"; import { ArrowRight, Camera, @@ -305,28 +306,8 @@ export default function Home() {

-
- - -