fix: bos reklam aramalarinda Apify getirme akisi
This commit is contained in:
@@ -6,6 +6,7 @@ import { maskAdForPlan } from "@/lib/locked-response";
|
|||||||
import { planFromUser } from "@/lib/plans";
|
import { planFromUser } from "@/lib/plans";
|
||||||
import { Card } from "@/components/ui/card";
|
import { Card } from "@/components/ui/card";
|
||||||
import { AdCreativeMedia } from "@/components/ad-creative-media";
|
import { AdCreativeMedia } from "@/components/ad-creative-media";
|
||||||
|
import { ApifyEmptySearch } from "@/components/ads/apify-empty-search";
|
||||||
|
|
||||||
export default async function AdsPage({ searchParams }: { searchParams: Promise<Record<string, string | undefined>> }) {
|
export default async function AdsPage({ searchParams }: { searchParams: Promise<Record<string, string | undefined>> }) {
|
||||||
const user = await requireUser();
|
const user = await requireUser();
|
||||||
@@ -45,6 +46,13 @@ export default async function AdsPage({ searchParams }: { searchParams: Promise<
|
|||||||
{["Week's biggest winners", "US winners", "Dropship Ads", "Supplements", "Top Branded"].map((x) => <span key={x} className="rounded-full bg-violet-50 px-3 py-1 text-sm font-semibold text-violet-800">{x}</span>)}
|
{["Week's biggest winners", "US winners", "Dropship Ads", "Supplements", "Top Branded"].map((x) => <span key={x} className="rounded-full bg-violet-50 px-3 py-1 text-sm font-semibold text-violet-800">{x}</span>)}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
|
<div className="grid gap-5 md:grid-cols-2 xl:grid-cols-3">
|
||||||
|
{q && masked.length === 0 && isAdmin && <ApifyEmptySearch query={q} />}
|
||||||
|
{q && masked.length === 0 && !isAdmin && (
|
||||||
|
<div className="rounded-3xl border border-dashed border-slate-200 bg-white p-8 text-center md:col-span-2 xl:col-span-3">
|
||||||
|
<h2 className="text-xl font-black">“{q}” için sonuç bulunamadı</h2>
|
||||||
|
<p className="mt-2 text-sm text-slate-500">Yeni reklamların içe aktarılması için yöneticinizle iletişime geçin.</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
{masked.map((ad: any) => (
|
{masked.map((ad: any) => (
|
||||||
<Card key={ad.id} className="relative overflow-hidden">
|
<Card key={ad.id} className="relative overflow-hidden">
|
||||||
{ad.isLocked && <div className="absolute inset-0 z-10 grid place-items-center bg-white/70 backdrop-blur-[2px]"><Link href="/pricing" className="rounded-2xl bg-violet-700 px-5 py-3 font-black text-white">Start now — Unlock winners</Link></div>}
|
{ad.isLocked && <div className="absolute inset-0 z-10 grid place-items-center bg-white/70 backdrop-blur-[2px]"><Link href="/pricing" className="rounded-2xl bg-violet-700 px-5 py-3 font-black text-white">Start now — Unlock winners</Link></div>}
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
|
||||||
|
const RESULT_LIMIT = 10;
|
||||||
|
const MAX_COST_USD = 0.1;
|
||||||
|
|
||||||
|
export function ApifyEmptySearch({ query }: { query: string }) {
|
||||||
|
const router = useRouter();
|
||||||
|
const [busy, setBusy] = useState(false);
|
||||||
|
const [message, setMessage] = useState("");
|
||||||
|
const [error, setError] = useState(false);
|
||||||
|
|
||||||
|
async function importFromApify() {
|
||||||
|
if (!window.confirm(`“${query}” için Apify'dan en fazla ${RESULT_LIMIT} reklam getirilsin mi? Harcama üst sınırı $${MAX_COST_USD.toFixed(2)}.`)) return;
|
||||||
|
|
||||||
|
setBusy(true);
|
||||||
|
setMessage("");
|
||||||
|
try {
|
||||||
|
const response = await fetch("/api/admin/ingest/apify", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
searchTerms: [query],
|
||||||
|
country: "ALL",
|
||||||
|
adActiveStatus: "ACTIVE",
|
||||||
|
mediaType: "ALL",
|
||||||
|
maxResults: RESULT_LIMIT,
|
||||||
|
maxCostUsd: MAX_COST_USD,
|
||||||
|
scrapeAdDetails: true,
|
||||||
|
includeAboutPage: false
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const data = await response.json().catch(() => ({}));
|
||||||
|
if (!response.ok) throw new Error(data.error || "APIFY_INGEST_FAILED");
|
||||||
|
|
||||||
|
setError(false);
|
||||||
|
setMessage(`${data.imported} reklam işlendi. Sonuçlar yenileniyor…`);
|
||||||
|
router.refresh();
|
||||||
|
} catch (caught) {
|
||||||
|
setError(true);
|
||||||
|
setMessage(caught instanceof Error ? caught.message : "Apify içe aktarması başarısız oldu.");
|
||||||
|
} finally {
|
||||||
|
setBusy(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="rounded-3xl border border-dashed border-violet-200 bg-violet-50/60 p-8 text-center md:col-span-2 xl:col-span-3">
|
||||||
|
<h2 className="text-xl font-black">“{query}” için kayıtlı reklam bulunamadı</h2>
|
||||||
|
<p className="mx-auto mt-2 max-w-2xl text-sm text-slate-600">
|
||||||
|
Bu arama önce WinningHunter veritabanını kontrol eder. Yeni Meta reklamlarını Apify üzerinden getirip aynı aramaya ekleyebilirsiniz.
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
disabled={busy}
|
||||||
|
onClick={importFromApify}
|
||||||
|
className="mt-5 rounded-2xl bg-violet-700 px-5 py-3 font-black text-white disabled:cursor-wait disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{busy ? "Apify'dan getiriliyor…" : "Apify'dan 10 reklam getir"}
|
||||||
|
</button>
|
||||||
|
<p className="mt-2 text-xs text-slate-500">Harcama üst sınırı: $0.10 · Yalnızca yöneticiler</p>
|
||||||
|
{message && <p className={`mt-3 text-sm font-semibold ${error ? "text-rose-600" : "text-emerald-700"}`}>{message}</p>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user