Files
app-admin/app/apps/page.tsx
2026-03-24 15:46:27 +03:00

265 lines
12 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { getApps, createApp, deleteApp } from "./actions";
import {
Smartphone,
Plus,
ArrowLeft,
Globe,
Apple,
Play,
Settings,
ShoppingBag,
SlidersHorizontal,
ExternalLink,
PackageSearch,
} from "lucide-react";
import Link from "next/link";
import { revalidatePath } from "next/cache";
import DeleteButton from "./DeleteButton";
export default async function AppsPage() {
const allApps = await getApps();
async function handleDelete(formData: FormData) {
"use server";
const id = Number(formData.get("id"));
await deleteApp(id);
revalidatePath("/apps");
}
return (
<div className="flex h-screen bg-zinc-50 dark:bg-black font-sans text-zinc-900 dark:text-zinc-100">
{/* Sidebar */}
<aside className="w-64 bg-white dark:bg-zinc-900 border-r border-zinc-200 dark:border-zinc-800 flex flex-col">
<div className="p-6 border-b border-zinc-200 dark:border-zinc-800 flex items-center gap-3">
<Link
href="/"
className="w-8 h-8 bg-black dark:bg-white rounded-lg flex items-center justify-center"
>
<span className="text-white dark:text-black font-bold text-lg">A</span>
</Link>
<span className="font-bold text-lg tracking-tight">AppAdmin</span>
</div>
<nav className="flex-1 p-4 space-y-1">
<Link
href="/"
className="flex items-center gap-3 px-3 py-2 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-lg text-sm font-medium transition-colors"
>
<Globe size={18} /> Dashboard
</Link>
<Link
href="/apps"
className="flex items-center gap-3 px-3 py-2 bg-zinc-100 dark:bg-zinc-800 rounded-lg text-sm font-medium"
>
<Smartphone size={18} /> Uygulamalar
</Link>
<div className="px-3 py-2 text-zinc-400 text-[10px] uppercase font-bold tracking-wider mt-4">
Sistem
</div>
<Link
href="/config"
className="flex items-center gap-3 px-3 py-2 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-lg text-sm font-medium transition-colors"
>
<SlidersHorizontal size={18} /> Remote Config
</Link>
</nav>
</aside>
<main className="flex-1 overflow-y-auto p-8">
<div className="max-w-5xl mx-auto space-y-8">
{/* Header */}
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold">Uygulama Yönetimi</h1>
<p className="text-zinc-500 mt-1">
Sisteme kayıtlı tüm mobil uygulamalarınızı buradan yönetin.
</p>
</div>
<Link
href="/"
className="flex items-center gap-2 text-sm text-zinc-500 hover:text-black dark:hover:text-white transition-colors"
>
<ArrowLeft size={16} /> Geri Dön
</Link>
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Yeni Uygulama Formu */}
<div className="lg:col-span-1">
<div className="bg-white dark:bg-zinc-900 p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 shadow-sm sticky top-8">
<h2 className="text-lg font-bold mb-4 flex items-center gap-2">
<Plus size={20} className="text-blue-500" /> Yeni Uygulama Ekle
</h2>
<form action={createApp} className="space-y-4">
<div>
<label className="block text-xs font-bold uppercase text-zinc-500 mb-1 ml-1">
Uygulama Adı
</label>
<input
name="name"
required
className="w-full px-4 py-2.5 rounded-xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-black text-sm focus:ring-2 focus:ring-black dark:focus:ring-white transition-all"
placeholder="Örn: X-Tracker Pro"
/>
</div>
<div>
<label className="block text-xs font-bold uppercase text-zinc-500 mb-1 ml-1">
Bundle ID
</label>
<input
name="bundleId"
required
className="w-full px-4 py-2.5 rounded-xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-black text-sm font-mono focus:ring-2 focus:ring-black dark:focus:ring-white transition-all"
placeholder="com.company.app"
/>
</div>
<div>
<label className="block text-xs font-bold uppercase text-zinc-500 mb-1 ml-1">
Platform
</label>
<select
name="platform"
className="w-full px-4 py-2.5 rounded-xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-black text-sm focus:ring-2 focus:ring-black dark:focus:ring-white transition-all"
>
<option value="ios">iOS (App Store)</option>
<option value="android">Android (Play Store)</option>
<option value="dual">Dual (Cross Platform)</option>
</select>
</div>
<div>
<label className="block text-xs font-bold uppercase text-zinc-500 mb-1 ml-1">
Apple App ID (Opsiyonel)
</label>
<input
name="appleId"
className="w-full px-4 py-2.5 rounded-xl border border-zinc-200 dark:border-zinc-800 bg-zinc-50 dark:bg-black text-sm focus:ring-2 focus:ring-black dark:focus:ring-white transition-all"
placeholder="123456789"
/>
</div>
<button
type="submit"
className="w-full py-3 bg-black dark:bg-white text-white dark:text-black rounded-xl font-bold text-sm hover:opacity-90 transition-opacity mt-2"
>
Uygulamayı Kaydet
</button>
</form>
</div>
</div>
{/* Uygulama Listesi */}
<div className="lg:col-span-2 space-y-4">
{allApps.length === 0 ? (
<div className="bg-white dark:bg-zinc-900 border-2 border-dashed border-zinc-200 dark:border-zinc-800 rounded-3xl p-12 text-center">
<div className="w-16 h-16 bg-zinc-100 dark:bg-zinc-800 rounded-full flex items-center justify-center mx-auto mb-4">
<PackageSearch className="text-zinc-400" size={32} />
</div>
<h3 className="text-lg font-bold">Henüz uygulama yok</h3>
<p className="text-zinc-500 text-sm max-w-xs mx-auto mt-2">
Sol taraftaki formu kullanarak ilk uygulamanızı sisteme kaydedin.
</p>
</div>
) : (
<div className="grid grid-cols-1 gap-4">
{allApps.map((app) => (
<div
key={app.id}
className="bg-white dark:bg-zinc-900 p-6 rounded-2xl border border-zinc-200 dark:border-zinc-800 shadow-sm hover:border-zinc-300 dark:hover:border-zinc-700 transition-all"
>
{/* App info row */}
<div className="flex items-center gap-5 mb-5">
<div
className={`w-14 h-14 rounded-2xl flex items-center justify-center shrink-0 ${
app.platform === "ios"
? "bg-zinc-100 dark:bg-white/5"
: "bg-green-50 dark:bg-green-900/10"
}`}
>
{app.platform === "ios" ? (
<Apple className="text-zinc-900 dark:text-white" size={28} />
) : (
<Play className="text-green-600" size={28} />
)}
</div>
<div className="flex-1 min-w-0">
<h3 className="text-lg font-bold leading-none mb-1 truncate">
{app.name}
</h3>
<div className="flex items-center gap-3 flex-wrap">
<span className="text-xs font-mono text-zinc-500 truncate">
{app.bundleId}
</span>
<span className="w-1 h-1 bg-zinc-300 rounded-full shrink-0" />
<span className="text-[10px] uppercase font-bold text-zinc-400 tracking-widest">
{app.platform}
</span>
{app.appleId && (
<>
<span className="w-1 h-1 bg-zinc-300 rounded-full shrink-0" />
<span className="text-[10px] font-mono text-zinc-400">
#{app.appleId}
</span>
</>
)}
</div>
</div>
</div>
{/* Action buttons row */}
<div className="flex items-center gap-2 flex-wrap pt-4 border-t border-zinc-100 dark:border-zinc-800">
{/* App Store */}
<Link
href={`/apps/${app.id}/store`}
className="flex items-center gap-1.5 px-3 py-2 bg-violet-50 dark:bg-violet-900/20 text-violet-700 dark:text-violet-400 border border-violet-200 dark:border-violet-800 rounded-xl text-xs font-bold hover:bg-violet-100 dark:hover:bg-violet-900/40 transition-colors"
>
<ShoppingBag size={13} /> App Store
</Link>
{/* Remote Config */}
<Link
href={`/apps/${app.id}/config`}
className="flex items-center gap-1.5 px-3 py-2 bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-400 border border-blue-200 dark:border-blue-800 rounded-xl text-xs font-bold hover:bg-blue-100 dark:hover:bg-blue-900/40 transition-colors"
>
<SlidersHorizontal size={13} /> Remote Config
</Link>
{/* Edit */}
<Link
href={`/apps/${app.id}/edit`}
className="flex items-center gap-1.5 px-3 py-2 bg-zinc-50 dark:bg-zinc-800 text-zinc-700 dark:text-zinc-300 border border-zinc-200 dark:border-zinc-700 rounded-xl text-xs font-bold hover:bg-zinc-100 dark:hover:bg-zinc-700 transition-colors"
>
<Settings size={13} /> Düzenle
</Link>
{/* Apple Store external link */}
{app.appleId && (
<a
href={`https://apps.apple.com/app/id${app.appleId}`}
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-1.5 px-3 py-2 bg-zinc-50 dark:bg-zinc-800 text-zinc-500 dark:text-zinc-400 border border-zinc-200 dark:border-zinc-700 rounded-xl text-xs font-bold hover:text-black dark:hover:text-white transition-colors"
>
<ExternalLink size={13} /> App Store'da Gör
</a>
)}
{/* Spacer */}
<div className="flex-1" />
{/* Delete */}
<DeleteButton
appId={app.id}
appName={app.name}
deleteAction={handleDelete}
/>
</div>
</div>
))}
</div>
)}
</div>
</div>
</div>
</main>
</div>
);
}