Files
kovakyazilim/app/api/admin/media/list/route.ts
T
Ege Can Komur dbc55e7527 feat: MediaPicker — sürükle-bırak + progress bar + kütüphane modal
Mevcut sorun:
- Her görsel için medya sayfasına git, yükle, URL kopyala, forma yapıştır → 4 adım
- Sürükle-bırak yok, progress yok, hangi dosyanın yüklendiği belirsiz

Çözüm: MediaPicker component (tek/çoklu mode)

API route'ları:
- POST /api/admin/media/upload — session auth + Appwrite Storage upload
- GET /api/admin/media/list — kütüphane modal için dosya listesi

Component özellikleri:
- Sürükle-bırak drop zone (hover state ile)
- Multiple file upload (çoklu mode)
- XHR ile gerçek progress bar (%) — Server Action ile alınamazdı
- Görsel preview (single: aspect-video, multiple: aspect-square grid)
- Hover'da × ile kaldırma
- Multiple mode'da sırasını değiştirme
- 'Kütüphaneden seç' modal — daha önce yüklenmiş görselleri grid'de göster, tıklayınca seç
- Error handling (dosya boyutu, ağ hatası vb.)
- Başarılı yüklemeyi 2 saniye gösterip kaybetme

Form alanları → MediaPicker (URL field'ları kaldırıldı):
- Blog: cover_image, seo_image
- Hizmet: hero_image
- Proje: image_url (kapak), gallery (çoklu)
- Referans: image_url
- Sektör: hero_image
- Ekip: photo_url
- SEO sayfa: og_image
- SEO global: default_og_image
- Site Settings: client_logos (çoklu)

Backward compat: form data formatı aynı kalıyor — hidden input ile URL satır satır.
admin-actions değişmedi. URL elle yapıştırmak hala mümkün (kütüphaneden URL kopyala).
2026-05-20 04:11:41 +03:00

34 lines
874 B
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 { NextResponse } from "next/server";
import {
MEDIA_BUCKET_ID,
Q,
storage,
} from "@/lib/appwrite-rest";
import { requireSessionSecret } from "@/lib/auth";
export const runtime = "nodejs";
export async function GET() {
const secret = await requireSessionSecret();
try {
const res = await storage.listFiles(
MEDIA_BUCKET_ID,
[Q.orderDesc("$createdAt"), Q.limit(200)],
secret,
);
return NextResponse.json({
files: res.files.map((f) => ({
id: f.$id,
name: f.name,
size: f.sizeOriginal,
mimeType: f.mimeType,
url: storage.fileViewUrl(MEDIA_BUCKET_ID, f.$id),
createdAt: f.$createdAt,
})),
});
} catch (err) {
const msg = err instanceof Error ? err.message : "Liste alınamadı";
return NextResponse.json({ error: msg, files: [] }, { status: 500 });
}
}