import { getAppById } from "../../actions"; import { getAppDetails, getAppStoreVersions, getLatestBuilds, getBetaGroups, getCustomerReviews, } from "../../../asc/actions"; import { ArrowLeft, Star, Package, Users, TestTube2, Globe, ShoppingBag, AlertCircle, CheckCircle2, Clock, XCircle, ChevronRight, ExternalLink, Apple, } from "lucide-react"; import Link from "next/link"; import { notFound } from "next/navigation"; import LocalizationEditor from "./LocalizationEditor"; import ReviewCard from "./ReviewCard"; import ScreenshotManager from "./ScreenshotManager"; // ─── Helpers ──────────────────────────────────────────────────────────────── function stateColor(state: string) { const map: Record = { READY_FOR_SALE: "text-emerald-400 bg-emerald-400/10 border-emerald-400/20", IN_REVIEW: "text-yellow-400 bg-yellow-400/10 border-yellow-400/20", WAITING_FOR_REVIEW: "text-blue-400 bg-blue-400/10 border-blue-400/20", PENDING_DEVELOPER_RELEASE: "text-violet-400 bg-violet-400/10 border-violet-400/20", PREPARE_FOR_SUBMISSION: "text-slate-400 bg-slate-400/10 border-slate-400/20", REJECTED: "text-red-400 bg-red-400/10 border-red-400/20", DEVELOPER_REJECTED: "text-orange-400 bg-orange-400/10 border-orange-400/20", METADATA_REJECTED: "text-orange-400 bg-orange-400/10 border-orange-400/20", }; return map[state] ?? "text-slate-400 bg-slate-400/10 border-slate-400/20"; } function stateIcon(state: string) { if (state === "READY_FOR_SALE") return ; if (state === "REJECTED" || state === "DEVELOPER_REJECTED") return ; if (state?.includes("REVIEW")) return ; return ; } function stateLabel(state: string) { const map: Record = { READY_FOR_SALE: "Satışta", IN_REVIEW: "İncelemede", WAITING_FOR_REVIEW: "İnceleme Bekliyor", PENDING_DEVELOPER_RELEASE: "Geliştirici Yayını Bekliyor", PREPARE_FOR_SUBMISSION: "Gönderime Hazırlanıyor", REJECTED: "Reddedildi", DEVELOPER_REJECTED: "Geliştirici Reddetti", METADATA_REJECTED: "Metadata Reddedildi", }; return map[state] ?? state; } function processingBadge(state: string) { if (state === "VALID") return ✓ Geçerli; if (state === "PROCESSING") return ⟳ İşleniyor; if (state === "FAILED") return ✗ Başarısız; return {state}; } function StarRating({ rating }: { rating: number }) { return (
{[1, 2, 3, 4, 5].map((s) => ( ))}
); } // ─── Page ──────────────────────────────────────────────────────────────────── export default async function AppStorePage({ params, searchParams, }: { params: Promise<{ id: string }>; searchParams: Promise<{ versionId?: string }>; }) { const { id } = await params; const { versionId } = await searchParams; const appId = parseInt(id); if (isNaN(appId)) notFound(); const app = await getAppById(appId); if (!app) notFound(); const hasAppleId = !!app.appleId; // Paralel fetch const [detailsRes, versionsRes, buildsRes, betaRes, reviewsRes] = await Promise.all([ hasAppleId ? getAppDetails(app.appleId!) : Promise.resolve({ data: null, error: null }), hasAppleId ? getAppStoreVersions(app.appleId!) : Promise.resolve({ data: null, error: null }), hasAppleId ? getLatestBuilds(app.appleId!) : Promise.resolve({ data: null, error: null }), hasAppleId ? getBetaGroups(app.appleId!) : Promise.resolve({ data: null, error: null }), hasAppleId ? getCustomerReviews(app.appleId!) : Promise.resolve({ data: null, error: null }), ]); const versions: any[] = versionsRes.data?.data ?? []; const liveVersion = versions[0]; // Use the versionId from the query string if provided, otherwise fall back to the first (live) version const selectedVersion = versionId ? (versions.find((v: any) => v.id === versionId) ?? liveVersion) : liveVersion; const builds: any[] = buildsRes.data?.data ?? []; const betaGroups: any[] = betaRes.data?.data ?? []; const reviews: any[] = reviewsRes.data?.data ?? []; const appInfo = detailsRes.data?.data; // Avg rating const avgRating = reviews.length > 0 ? reviews.reduce((s: number, r: any) => s + (r.attributes?.rating ?? 0), 0) / reviews.length : null; return (
{/* Header */}

{app.name}

{app.bundleId}

{/* Tabs */}
{[ { href: `/apps/${appId}/config`, label: "Remote Config" }, { href: `/apps/${appId}/store`, label: "App Store", active: true }, ].map((tab) => ( {tab.label} ))}
{/* No Apple ID warning */} {!hasAppleId && (

Apple ID Tanımlı Değil

App Store Connect verilerini çekebilmek için bu uygulamaya bir Apple ID ekleyin.

Düzenle
)} {/* ── KPIs ─────────────────────────────────────────────────────── */}
{/* Live Version */}
Canlı Sürüm
{liveVersion ? ( <>

{liveVersion.attributes?.versionString ?? "—"}

{stateIcon(liveVersion.attributes?.appStoreState)} {stateLabel(liveVersion.attributes?.appStoreState)} ) : (

)}
{/* Avg Rating */}
Ortalama Puan
{avgRating !== null ? ( <>

{avgRating.toFixed(1)}

{reviews.length} yorum

) : (

)}
{/* Builds */}
Son Build
{builds[0] ? ( <>

{builds[0].attributes?.version ?? "—"}

{processingBadge(builds[0].attributes?.processingState)}

{builds[0].attributes?.uploadedDate ? new Date(builds[0].attributes.uploadedDate).toLocaleDateString("tr-TR") : ""}

) : (

)}
{/* Beta Testers */}
TestFlight Grup

{betaGroups.length}

aktif grup

{/* ── Main Grid ────────────────────────────────────────────────── */}
{/* LEFT: Versions + Localizations */}
{/* Sürümler */}

App Store Sürümleri

{versions.length === 0 ? (
Sürüm bulunamadı.
) : (
{versions.map((v: any) => { const isSelected = selectedVersion?.id === v.id; return (

v{v.attributes?.versionString} {isSelected && ( Seçili )}

{v.attributes?.createdDate ? new Date(v.attributes.createdDate).toLocaleDateString("tr-TR", { year: "numeric", month: "long", day: "numeric", }) : ""} {v.attributes?.copyright && ` · ${v.attributes.copyright}`}

{stateIcon(v.attributes?.appStoreState)} {stateLabel(v.attributes?.appStoreState)} {/* Localization Link */} Metadata
); })}
)}
{/* Localization Editor — shows selected version (or live version) */} {selectedVersion && ( )} {/* Screenshot Manager (iPhone 6.5") */} {selectedVersion && ( )} {/* Builds */}

Son Buildler

{builds.length === 0 ? (
Build bulunamadı.
) : (
{builds.map((b: any) => (

Build {b.attributes?.version}

iOS {b.attributes?.minOsVersion}+ {b.attributes?.uploadedDate ? ` · ${new Date(b.attributes.uploadedDate).toLocaleDateString("tr-TR")}` : ""}

{processingBadge(b.attributes?.processingState)}
))}
)}
{/* RIGHT: Reviews + TestFlight */}
{/* Yorumlar */}

Kullanıcı Yorumları

{avgRating !== null && ( {avgRating.toFixed(1)} ★ )}
{reviews.length === 0 ? (
{hasAppleId ? "Yorum bulunamadı." : "Apple ID gerekli."}
) : (
{reviews.map((r: any) => ( ))}
)}
{/* TestFlight Grupları */}

TestFlight Grupları

{betaGroups.length === 0 ? (
{hasAppleId ? "Grup bulunamadı." : "Apple ID gerekli."}
) : (
{betaGroups.map((g: any) => (

{g.attributes?.name}

{g.attributes?.isInternalGroup ? "İç Grup" : "Dış Grup"}

{g.attributes?.publicLinkEnabled && ( Link )}
{g.attributes?.publicLinkLimitEnabled && (

Limit: {g.attributes.publicLinkLimit} kişi

)}
))}
)}
{/* App Store Link */} {appInfo && (
App Store'da Görüntüle
)}
); }