Admin panelden yönetilen, çok müşterili ve kategorili fiyat takip sistemi.
Fiyat değişimlerinde müşterilere Telegram bildirimi gider. Ürünün adı
"Cheapo", logosu web/public/logo.png (site içinde Logo bileşeni ile
kullanılır); repo ve klasör adı geriye dönük uyumluluk için Price_Tracker_Bot
olarak kalıyor.
Price_Tracker_Bot/
├── bot/
│ ├── main.py Telegram botu (müşteri bağlama)
│ ├── checker.py Fiyat kontrolcüsü (fiyatı okur ve kaydeder)
│ ├── notifier.py Fiyat değişiminde Telegram bildirimi
│ ├── adapters/ Fiyat okuyucular (json_ld.py: düz HTTP; browser.py: gerçek tarayıcı, sırayla json_ld/next_data/data_testid/price_class dener)
│ ├── requirements.txt
│ └── .env Gizli anahtarlar (GitHub'a gitmez)
├── web/
│ ├── src/app/admin/ Admin sayfaları (giriş, talepler, müşteri talepleri, müşteriler, kategoriler, kaynaklar, ürünler, takipler, fiyat geçmişi, bildirimler)
│ ├── src/app/login/ Tek giriş sayfası (admin ve müşteri için)
│ ├── src/app/portal/ Müşteri portalı (ürünlerim, bildirimler, talepler, plan, rapor, kıyas, alışveriş listesi)
│ ├── src/app/page.tsx Herkese açık tanıtım sayfası (landing page)
│ ├── src/lib/supabase/ Supabase bağlantıları (tarayıcı ve sunucu)
│ ├── src/proxy.ts Giriş koruması
│ ├── src/components/ Ortak bileşenler (yan menü, butonlar, talep formu, logo)
│ ├── src/components/landing/ Landing page bölümleri (hero, 3 adımda hazır, kategoriler, SSS, planlar, talep)
│ └── .env.local Panel ayarları (GitHub'a gitmez)
└── supabase/ Veritabanı şema dosyaları (SQL)
| Parça | Seçim |
|---|---|
| Veritabanı ve giriş | Supabase |
| Admin panel | Next.js |
| Bot | Python 3.14 |
| Fiyat okuma | httpx (düz HTTP), Playwright (gerçek tarayıcı) |
| Bildirim | Telegram Bot API |
Admin panel ──► Supabase ◄── Bot ──► Telegram
(yönetim) (veritabanı) (fiyat (müşteriye
çeker) bildirim)
- Admin, panelden müşteri, kategori ve takip edilecek ürünleri tanımlar.
- Bot, Supabase'den aktif ürünleri okur ve her ürünün fiyatını kaynağından çeker.
- Fiyat geçmişe kaydedilir. Fiyat değiştiyse ürünü takip eden müşterilere Telegram'dan bildirim gider.
Bir ürünün fiyatı müşteri başına değil, ürün başına bir kez çekilir. Aynı ürünü birden çok müşteri takip etse de kaynağa tek istek gider.
Her ürünün kendi kontrol aralığı vardır (check_interval_minutes). Kontrolcü
ne kadar sık çalıştırılırsa çalıştırılsın, yalnızca aralığı dolan ürünlere
bakar.
Kontrol aralığı en az 5 dakikadır. Bir ürünün linki değiştirilirse eski fiyat sıfırlanır, böylece bot yeni sayfadaki fiyatı eski ürünle kıyaslayıp yanlış bildirim göndermez.
Admin panel /admin altındadır (/admin/login hariç, girişsiz erişilemez). Kök
adres (/) herkese açık tanıtım sayfasıdır (landing page).
Bir ürünün fiyatı bir önceki kontrole göre değiştiğinde, ürünü takip eden her müşteri için şu kurallara bakılır:
- Her değişimde bildir seçiliyse: her fiyat değişiminde bildirim gider.
- Hedef fiyat girilmişse: fiyat hedefin üstündeyken hedefe ya da altına inerse bildirim gider. Fiyat hedefin altında kaldığı sürece tekrar bildirim gitmez.
Ürünün ilk kez okunduğunda (önceki fiyat yokken) bildirim gitmez. Gönderilen
her bildirim notification_log tablosuna kaydedilir.
Her müşterinin panelde otomatik üretilen bir bağlama kodu vardır. Panelden
müşteri için bağlama linki kopyalanıp müşteriye gönderilir. Müşteri linke
tıklayıp Start'a bastığında (bot /start KOD komutunu alır) bot Telegram
chat ID'sini o müşteriye kaydeder.
Panele yalnızca tek bir admin hesabı girebilir. Giriş Supabase Auth ile
yapılır. Veritabanında her tabloda satır bazlı güvenlik (RLS) açıktır ve
kurallar is_admin() fonksiyonuna bağlıdır; bu fonksiyon yalnızca admin
hesabının kimliğini (UID) kabul eder. Başka bir hesap açılsa bile hiçbir veri
görülemez. Bot ise service_role ile çalışır ve bu kuralları atlar.
Giriş tek bir sayfadan (/login) yapılır. Giriş başarılı olunca sistem bu
hesabın customers tablosunda bir kaydı olup olmadığına bakar: varsa
müşteri portalına (/portal), yoksa admin panele (/admin) yönlendirir.
Her istekte bu kontrol tekrar yapılır, yani bir müşteri adres çubuğuna elle
/admin yazsa da otomatik olarak /portal'a geri gönderilir (ve tersi).
Müşteri çöp kutusuna atılmışsa (customers.deleted_at dolu) bu kontrol
"kayıt yok" saymaz; oturumu kapatılıp /login'e geri gönderilir — yoksa
"kayıt yoksa admindir" varsayımı yüzünden yanlışlıkla admin paneline
yönlendirilirdi.
Giriş sayfası koyu temalı, ortada bölünmüş kartlı bir tasarıma sahiptir
(components/login-showcase.tsx, components/login-showcase-data.ts).
Arka planda örnek ürün/fiyat kartları çapraz şeritler halinde sürekli akar
(saf CSS animasyonu, globals.css içindeki lg- ön ekli kurallar); bu
kartlardaki ürün/fiyat bilgileri sayfa herkese açık olduğu için tamamen
kurgusal örnek verilerdir, gerçek müşteri verisi değildir. Sağdaki form
e-posta/şifre alanları, şifre göster-gizle, "Beni hatırla" (şu an yalnızca
görsel, kalıcı bir davranışı yok) ve "Şifremi unuttum" (henüz pasif, ileride
eklenecek) içerir.
Ziyaretçi landing page'deki formu doldurup talep gönderir (leads tablosu).
Admin, Talepler sayfasından talebi inceler ve uygun bulursa e-posta/şifre
belirleyip hesap açar. Bu işlem Supabase Auth'ta yeni bir kullanıcı, ardından
customers tablosunda o kullanıcıya bağlı bir müşteri kaydı oluşturur ve
talebi otomatik "Tamamlandı" yapar.
Hesabı açılan müşteri /login'den giriş yapıp /portal'a yönlenir. Portal
koyu temalıdır, masaüstünde yan menü, telefonda alt sekmelerle çalışır
(components/portal-shell.tsx). Sayfalar:
- Ürünlerim: özet kutuları, hedefinin altına inen ürün için fırsat bandı, ürün kartları (fiyat grafiği, en düşük/en yüksek fiyat, değişim yüzdesi, hedefe yakınlık, favori yıldızı), arama, sıralama ve kart/liste görünümü. Sağ kolonda plan kartı, Telegram durumu ve son 3 bildirim.
- Favorilerim: "Ürünlerim"deki bir kartın yıldızına basılan ürünler
burada toplanır (
subscriptions.is_favorite). Ayrı, hafif bir takip katmanı değildir; sadece zaten takip edilen ürünler arasında hızlı erişim sağlar, bildirim ayarını etkilemez. - Bildirimlerim: Telegram'dan gelen bildirimlerin günlere göre kaydı.
- Talep gönder: kategori ve ürün seçerek talep. Plan sınırı seçim sırasında önizlenir ve aşılırsa gönderilmeden uyarılır. Taleplerin durumu adım adım izlenir (Gönderildi, İnceleniyor, Takibe eklendi).
- Planım: Ücretsiz ve Premium planın karşılaştırması.
- Hesap ayarları: profil adı, şifre değiştirme (Supabase Auth üzerinden,
mevcut şifre doğrulanır), Telegram bağlantısını kesme, ve "hesabı kaldır"
talebi gönderme (
customers.removal_requested_at; admin talebi görüp onaylarsa hesabı normal "sil" butonuyla çöp kutusuna atar). - Yardım & SSS: üstte üç hızlı rehber kartı (ilk ürünü takibe alma,
Telegram bağlama, ilk sepeti oluşturma; karta tıklayınca adımlar açılır),
altında kısa sorular (akordiyon). İçerik
components/portal-help.tsxiçinde sabit metindir, veritabanına bağlı değildir. - Alışveriş listesi (yalnızca Premium): market ürünlerinden sepet oluşturma ve satıcı bazında toplam kıyaslama.
- Haftalık rapor ve Ürün kıyası (yalnızca Premium): Ücretsiz müşteri kilitli önizleme görür.
Haftalık rapor, price_daily görünümündeki günlük son fiyatlardan ve bildirim
kayıtlarından hesaplanır (son 7 ya da 30 gün). Ürün kıyası, aynı ürünün farklı
satıcılardaki fiyatını yan yana gösterir: yönetici, aynı ürünün her satıcıdaki
kaydını admin panelinde ürün düzenlerken aynı karşılaştırma grubuna
(products.comparison_group, örn. coca-cola-1-5l) koyar. Müşteri bir ürünü
takip ettiğinde, o ürünün grubundaki tüm marketler kıyas sayfasında görünür.
"Destek al" ve "Premium için yaz" düğmeleri şimdilik yalnızca görünümdür.
Alışveriş listesi tek bir sepetten ibaret değildir: müşteri birden fazla
sepet oluşturabilir (basket_lists tablosu: customer_id, name,
category_id), her sepetin bir sektörü (kategorisi) vardır ve "Ürün ekle"
paneli o sepette sadece aynı sektördeki takip edilen ürünleri önerir. Sepetler
üstteki şeritte sekme gibi durur; sekmenin ⋮ menüsünden yeniden adlandırılabilir
ya da silinebilir (silinince içindeki ürünler de gider). Bir sepetin içindeki
ürünler basket_items tablosunda tutulur (list_id + product_id); "Ürün
ekle" panelinden eklenmeyen hiçbir ürün listede görünmez. Eklenen ürün bir
karşılaştırma grubuna bağlıysa, o gruptaki diğer satıcıların fiyatları da
otomatik olarak aynı satırda gösterilir ve satıcı bazında toplam hesaplanıp en
ucuz satıcı vurgulanır; tek satıcıdan takip edilen ürünler de eklenebilir,
sadece kıyaslama çıkmaz.
Farklı marka ama aynı ihtiyacı karşılayan ürünler (örn. bir markette Banvit
Tavuk Göğsü, başka markette Erpiliç Tavuk But) admin panelinde aynı
karşılaştırma grubuna konamaz, çünkü gerçekte aynı ürün değiller. Bunun için
müşteri, sepetindeki iki veya daha fazla ürünü elle "eşdeğer" olarak
eşleştirebilir: "Eşdeğer olarak eşleştir" ile seçim moduna girer, ürünleri
işaretler, bir grup ismi verir (basket_matches tablosu: customer_id,
name; basket_items.match_id bu gruba bağlanır). Eşleştirilen ürünler tek
satırda, her birinin hangi markette hangi ürün olduğu küçük bir alt yazıyla
birlikte gösterilir; eşleştirme istendiği an geri alınabilir.
Portalın veritabanı erişimi satır bazlı güvenlik (RLS) kurallarıyla sağlanır:
müşteri sadece kendi customers, subscriptions, customer_requests,
notification_log ve takip ettiği ürünlerin price_history satırlarını
okuyabilir; ayrıca aktif ürünleri ve aktif kaynakları okuyabilir. Hiçbir tabloya
yazma yetkisi yoktur (talep göndermek sunucu işleminden geçer).
Müşteri portaldan bir kategori ve o kategorideki ürünleri seçip talep
gönderir (customer_requests + customer_request_products). Admin, panelin
Müşteri talepleri sayfasından bu talepleri görür ve durumunu değiştirir
(Bekliyor / İnceleniyor / Tamamlandı / Reddedildi). Durum Tamamlandı
yapıldığında seçilen ürünler otomatik olarak müşterinin takiplerine
(subscriptions) eklenir; hedef fiyat ve bildirim kuralı boş kalır, admin
bunu Takipler sayfasından ayarlar.
Ücretsiz planda en fazla 1 kategori ve 3 ürün takip edilebilir (premium'da
sınır yok). Bu sınır, müşteri portaldan yeni talep gönderirken kontrol edilir;
sınır aşılıyorsa talep reddedilir ve mevcut kullanım anlaşılır bir mesajla
gösterilir. Sınırlar web/src/lib/plan-limits.ts dosyasında tanımlıdır.
Admin, Takipler sayfasından bu sınırın üstünde elle ekleme yapabilir.
Admin, Ürünler sayfasından bir ürüne "Şimdi kontrol et" diyebilir. Bu, ürünün
force_check_requested bayrağını işaretler. Bot en fazla 1 dakika içinde bu
bayrağı görüp ürünü hemen kontrol eder ve bayrağı sıfırlar; ürünün kendi
kontrol aralığını beklemesine gerek kalmaz.
Kök sayfa (/) bölümlere ayrılmıştır ve her bölüm web/src/components/landing/
altında ayrı bir dosyadır: hero (cihaz sahnesi ve kayan ürün duvarı), 3 adımda
hazır, kategoriler, Merak edilenler (bot sohbeti şeklinde), planlar ve talep
formu. Talep formu web/src/components/lead-form.tsx dosyasındadır ve
leads tablosuna kaydeder.
Renkler globals.css içindeki @theme bloğunda tanımlıdır. Animasyonlar
saf CSS ile yazılmıştır ve bölüme göre önek alır: hv- (hero), hiw- (3 adımda
hazır), pl- (planlar), pf- (SSS sohbeti), lf- (talep formu). Kaydırınca
başlayan animasyonlar küçük bir IntersectionObserver ile tetiklenir, ayarlarda
"hareketi azalt" seçiliyse tüm animasyonlar kapanır (prefers-reduced-motion).
Hero'daki cihaz ekranlarında görünen ürünler ve fiyatlar örnek veridir, gerçek takip verisi değildir.
Admin paneli koyu temalıdır ve müşteri portalından ayrıdır. web/src/app/admin/layout.tsx
içindeki force-dark sınıfı, globals.css'teki özel dark varyantı sayesinde
admin içindeki tüm dark: sınıflarını işletim sistemi temasından bağımsız açar;
giriş sayfası ve portal etkilenmez. Renkler yine globals.css'te, .force-dark
içinde gri ve yeşil paletin yeniden tanımlanmasıyla (koyu turkuaz) verilir.
- Yan menü (
sidebar.tsx): Gelenler, Katalog, Takip gruplarına ayrılmıştır. Talepler ve Müşteri talepleri yanında durumu "bekliyor" olan kayıtların sayısı kırmızı rozet olarak görünür (sayılaradmin/layout.tsx'te hesaplanır). - Üst çubuk ve arama (
admin-topbar.tsx,admin-nav.ts): sayfa başlığı ve Ctrl+K ile açılan sayfa arama penceresi. - Ana sayfa: "Dikkat gerektirenler" (okunamayan ürünler, bekleyen talepler, Telegram'a bağlanmamış müşteriler), istatistik kartları, son bildirimler ve ürün durumu. Hepsi Supabase'den gerçek veriyle gelir.
- Ürünler: arama, durum filtreleri (Hatalı, Sırada, Pasif), durum rozetleri
ve tek tıkla "şimdi kontrol et". Ürün ekleme ve düzenleme sağdan açılan
çekmecede yapılır (
product-drawer.tsx); aynı çekmecede ürünün karşılaştırma grubu da girilir. - Talepler ve Müşteri talepleri: gelen kutusu düzeni; durum filtreleri, arama ve renkli durum seçicisi. Talepler sayfasında "Hesap aç" kartın içinde açılır.
- Bildirimler: günlere göre gruplanmış akış, mesajlar Telegram balonu şeklinde, müşteri seçici ve arama.
- Fiyat geçmişi: her kaydın bir önceki kayda göre değişimi, ürün seçilince fiyat grafiği (güncel, en düşük, en yüksek, toplam değişim).
- Kategoriler ve Kaynaklar: kart görünümü; her kartta bağlı ürün (ve kategoride müşteri) sayısı. Bağlı ürünü olan kategori ya da kaynak silinemez.
- Takipler: müşteriye göre gruplu kartlar; her müşteride Telegram durumu (bağlı değilse bildirim gidemediği belirtilir), ürünün güncel fiyatı ve hedefe uzaklığı. Ekleme ve düzenleme sağdan açılan çekmecede yapılır.
- Müşteriler: kart görünümü; plan (Ücretsiz/Premium) düzenleme çekmecesinden değiştirilebilir, bağlı olmayan müşterinin bağlama linki karttan kopyalanır. Kartta kategoriler, takip sayısı ve müşterinin bildirimlerine kısayol vardır.
Tüm admin sayfaları yenilenmiştir.
- Python 3.10 veya üstü
- Git
- Bir Supabase projesi
- BotFather'dan alınmış bir Telegram bot tokenı
bot/.envdosyasını oluştur (GitHub'a gitmez):
TELEGRAM_BOT_TOKEN=
SUPABASE_URL=
SUPABASE_SERVICE_ROLE_KEY=
Service role anahtarı çok güçlüdür: sadece botta kullanılır, panele ve GitHub'a asla konmaz.
- Sanal ortamı kur ve kütüphaneleri yükle:
cd bot
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txtBotlara engel koyan siteleri (örn. Cloudflare kullananları) okumak için gerçek bir tarayıcı gerekir. Bunun için Playwright'ı ve Chromium'u bir kez kur:
pip install playwright
playwright install chromiumBu yalnızca kaynağın yöntemi Tarayıcı (Playwright) olan ürünler için kullanılır; diğer ürünler eskisi gibi düz HTTP ile okunur.
- Botu çalıştır:
python main.pypython main.py çalıştığı sürece bot hem Telegram'ı dinler hem arka planda her dakika hangi ürünlerin kontrol zamanı geldiğine bakar, ayrı bir komut gerekmez. python checker.py'yi elle bir kez çalıştırmak (tek seferlik test için) hâlâ mümkündür.
Yeni bir terminal açıldığında önce sanal ortam tekrar etkinleştirilir
(.venv\Scripts\Activate.ps1).
web/.env.localdosyasını oluştur (GitHub'a gitmez):
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=
TELEGRAM_BOT_USERNAME=
SUPABASE_SERVICE_ROLE_KEY=
TELEGRAM_BOT_USERNAME, müşteri bağlama linkini oluşturmak için botun
kullanıcı adıdır (başında @ olmadan).
Panelde yalnızca sb_publishable_ ile başlayan anahtar kullanılır.
Service role anahtarı panele asla konmaz.
SUPABASE_SERVICE_ROLE_KEY sadece hesap açma işleminde, sunucu tarafında
("use server" dosyasında) kullanılır ve tarayıcıya asla gönderilmez.
NEXT_PUBLIC_ öneki almadığından client koduna erişilemez.
- Paketleri kur ve çalıştır:
cd web
npm install
npm run devPanel http://localhost:3000 adresinde açılır.
- Supabase'de Authentication → Users bölümünden admin hesabını oluştur.
| Tablo | Amaç |
|---|---|
categories |
Market, E-ticaret, Uçak bileti vb. |
customers |
Müşteriler, Telegram chat ID, bağlama kodu |
customer_categories |
Müşteri - kategori eşleşmesi |
sources |
Fiyat kaynağı ve çekme yöntemi (api, json_ld, http, browser) |
products |
Takip edilen ürünler (ürün başına tek kayıt) |
subscriptions |
Müşteri - ürün takibi, hedef fiyat |
price_history |
Fiyat geçmişi |
notification_log |
Gönderilen bildirim kayıtları |
Ek olarak:
products.comparison_group: aynı grup adını taşıyan ürünler aynı ürünün farklı farklı satıcılardaki kayıtlarıdır (Ürün kıyası ve Alışveriş listesi bu alanı kullanır). Admin panelde Ürünler sayfasının liste/grup görünüm anahtarıyla bu gruplar kart halinde bir arada görülebilir.basket_lists: müşterinin oluşturduğu sepetler (customer_id,name,category_id). Her sepetin bir sektörü vardır; "Ürün ekle" paneli o sepette sadece aynı sektördeki ürünleri önerir.basket_items: bir sepete eklenen ürünler (list_id,product_id,match_id).basket_matches: müşterinin elle "eşdeğer" olarak birleştirdiği ürün grupları (customer_id,name).customers.removal_requested_at: müşteri "Hesap ayarları"ndan hesap kaldırma talebi gönderdiğinde dolar; admin talebi görüp uygun bulursa hesabı normal silme akışıyla çöp kutusuna atar.price_daily(görünüm):price_history'nin günlük son fiyat özeti (Türkiye saatine göre).security_invokerile çalışır, yani sorgulayan kullanıcının RLS izinleri geçerlidir.
Her kaynağın bir okuma yöntemi vardır (sources.method, panelde Kaynaklar
sayfası). Şu an iki yöntem gerçekten çalışır durumdadır; dropdown'da başka
seçenek yoktur (ileride resmi API sunan bir kaynak eklenirse yeni bir yöntem
olarak eklenir):
-
JSON-LD (sayfa verisi): düz HTTP isteği ile sayfadaki JSON-LD fiyat verisi okunur. Hızlıdır.
-
Tarayıcı (Playwright): headless Chromium ile sayfa açılır (
bot/adapters/browser.py). Cloudflare gibi bot korumasını geçmek için varsayılan "HeadlessChrome" kimliği yerine normal bir Chrome kimliği kullanılır. Sayfa açıldıktan sonra fiyat, sırayla dört ayrı ayrıştırıcıyla aranır, ilk bulan kazanır:- JSON-LD (
adapters/json_ld.py) — sayfanın kendi JSON-LD fiyat verisi. __NEXT_DATA__(adapters/next_data.py) — Next.js sitelerinin sayfaya gömdüğü JSON içindeki fiyat.data-testid(adapters/data_testid.py) — sayfanın düz HTML'indedata-testid="discountedPrice"etiketli fiyat kutusu.- CSS class'ı
normalPrice(adapters/price_class.py) — class adı "...normalPrice" ile biten fiyat kutusu.
Her sayfa birkaç saniye sürer. Kontrolcü tarayıcıyı yalnızca bu yöntemdeki ürünler için başlatır. Hangi alt yöntemin tuttuğu ürünün
last_statusalanına yazılır ("ok · next_data"gibi) ve panelde iki yerde görünür: admin Ürünler sayfasındaki Yöntem sütununda (ürün bazında, boşsa JSON-LD ile okunmuş demektir) ve Kaynaklar sayfasındaki kart üzerinde renkli bir rozet olarak (o kaynağın ürünlerinden en az biri hangi alt yöntemle okunduysa). Aynı kaynağın farklı ürünleri, sayfa şablonları farklıysa, birden fazla alt yöntemle okunabilir — bu bir hata değildir. - JSON-LD (
Yeni bir kaynak eklerken önce düz HTTP ile (JSON-LD) denenmelidir; site 403 veriyorsa kaynağın yöntemi "Tarayıcı (Playwright)" yapılır — bu durumda dört alt yöntemden hangisinin uyduğunu bot kendisi bulur, elle seçim yapılmaz. Sunucunun IP adresi bot koruması tarafından farklı değerlendirilebileceği için, canlıya alırken tarayıcı yöntemi orada da denenmelidir. Bazı siteler ürün sayfasını teslimat adresine göre kişiselleştirir; adres seçilmemiş bir oturumdan bazı ürünler gerçekte satışta olsa da 404 dönebilir — bu bot hatası değildir, ilgili ürün admin panelden pasif yapılabilir.
Admin panelde bir kayıt silindiğinde veritabanından hemen kaldırılmaz;
deleted_at sütunu doldurulur ("çöpe atılır") ve normal listelerden kaybolur.
Gerçek silme yalnızca Çöp kutusu sayfasından "Kalıcı olarak sil" ile,
onay istendikten sonra yapılır. Kapsam: products, sources, categories,
customers, subscriptions, leads, notification_log, price_history,
customer_requests — panelde silme işlemi olan her tablo.
Genel action'lar tek dosyada toplanmıştır (app/admin/trash/actions.ts):
softDelete, restoreFromTrash, permanentlyDelete; tablo adı parametre
olarak verilir. Mevcut "sil" butonlarının fonksiyon imzaları değişmedi, sadece
içleri artık gerçek delete yerine deleted_at güncelliyor. Çöp kutusu
sayfası (app/admin/trash/page.tsx) bu 9 tablodan deleted_at dolu olan
kayıtları tek bir listede toplar; arama ve tabloya göre filtre içerir. Sol
menüdeki "Çöp kutusu" rozeti, çöpteki toplam kayıt sayısını gösterir.
Bunun güvenli çalışması için birkaç yer özellikle düzeltildi:
- Admin panelindeki tüm ana listeleme sorgularına (
Ürünler,Kaynaklar,Kategoriler,Müşteriler,Takipler,Talepler,Bildirimler,Fiyat geçmişi,Müşteri talepleri)deleted_at is nullfiltresi eklendi. price_dailygörünümü de çöpteki fiyat kayıtlarını hesaba katmayacak şekilde güncellendi (haftalık/aylık rapor bunu kullanıyor).- Bot: çöpe atılmış bir ürün artık kontrol edilmiyor (
checker.py), çöpe atılmış bir aboneliğe/müşteriye bildirim gitmiyor (notifier.py), çöpe atılmış bir müşteri Telegram'ını bağlayamıyor (main.py). - Giriş mantığı: "müşteri kaydı yoksa admindir" varsayımı yüzünden,
çöpe atılmış bir müşteri basitçe filtrelenirse yanlışlıkla admin paneline
yönlendirilebilirdi. Bunun yerine
proxy.ts(asıl güvenlik sınırı) velogin/page.tsx, müşteri bulunduğu ama çöpe atılmış olduğu durumu ayrıca kontrol eder: oturum kapatılır,/login'e "hesap kaldırılmış" mesajıyla geri gönderilir.
Not: Müşteri portalındaki (customer-facing) bazı sorgular — ör. ürün kıyası,
alışveriş listesi, portal ana sayfası — henüz deleted_at filtresi almadı;
bu sayfalarda çöpe atılmış bir ürün/kategori kısa süreliğine görünmeye devam
edebilir. İleride ele alınacak bir sonraki adım.
- Supabase projesi ve veritabanı şeması (8 tablo)
- Telegram botu oluşturuldu
- Müşteri bağlama akışı (
/start KODile chat ID kaydı) - Bot -> müşteri Telegram bildirimi doğrulandı
- Fiyat okuyucu (JSON-LD): sayfadan fiyat ve stok bilgisi çekiyor
- Kontrolcü: aktif ürünlerin fiyatını okuyup geçmişe kaydediyor
- Fiyat değişiminde Telegram bildirimi (her değişimde ve hedef fiyata düşünce)
- Ürün bazlı kontrol aralığı (sırası gelmeyen ürün atlanıyor)
- Panel iskeleti: admin girişi/çıkışı ve giriş koruması
- Panel: yan menülü düzen ve özet kartlarıyla ana sayfa
- Panel: müşteri yönetimi (ekleme, satır içi düzenleme, silme, Telegram bağlama linki)
- Panel: kategori yönetimi (ekleme, satır içi düzenleme, silme)
- Panel: kaynak yönetimi (ekleme, satır içi düzenleme, silme)
- Panel: ürün yönetimi (ekleme, satır içi düzenleme, silme, kategori ve kaynak seçimi)
- Panel: takip yönetimi (müşteri-ürün eşleştirme, hedef fiyat ve bildirim kuralı)
- Panel: fiyat geçmişi (listeleme, ürüne göre filtreleme, kayıt silme)
- Panel: bildirim kayıtları (listeleme, müşteriye göre filtreleme, kayıt silme)
- Panel: müşteriye kategori atama (Market, E-ticaret, Uçak bileti vb.)
- Panel: admin sayfaları
/adminaltına taşındı, kök adres genel kullanım için ayrıldı - Veritabanı: müşteri hesabı bağlantısı (
auth_user_id), plan alanı,leadsvecustomer_requeststabloları - Landing page: tanıtım, plan karşılaştırması ve talep formu (leads tablosuna kaydediyor)
- Panel: Talepler sayfası (leads listeleme, durum değiştirme, silme)
- Panel: talepten müşteri hesabı açma (Supabase Auth + customers kaydı)
- Tek giriş sayfası (/login), hesap türüne göre /admin veya /portal'a yönlendirme(koyu temalı, çapraz akan ürün kartlı arka plan tasarımıyla yenilendi)
- Müşteri portalı: giriş, takip edilen ürünler ve fiyatları görme
- Müşteri portalı: yeni talep gönderme (kategori + ürün seçimi) ve kendi taleplerini görme
- Panel: Müşteri talepleri sayfası, Tamamlandı'da otomatik takip ekleme
- Ücretsiz plan sınırı (1 kategori, 3 ürün), müşteri talep gönderirken kontrol ediliyor
- Bot: Telegram hesabı başka müşteriye bağlıysa anlaşılır hata mesajı (çökmüyor)
- Bot sürekli çalışır: Telegram dinleme ve fiyat kontrolü tek süreçte (60 saniyede bir kontrol turu)
- Panel: "Şimdi kontrol et" düğmesi, bot en fazla 1 dakika içinde işliyor
- Landing page yenilendi: animasyonlu hero, 3 adımda hazır, kategoriler, planlar, SSS sohbeti ve talep formu
- Admin paneli yenilendi (1. aşama): koyu tema, gruplu menü ve rozetler, Ctrl+K arama, yeni ana sayfa, Ürünler sayfası ve düzenleme çekmecesi
- Admin paneli yenilendi (2. aşama): Talepler, Müşteri talepleri, Bildirimler, Fiyat geçmişi (grafikli), Kategoriler ve Kaynaklar sayfaları
- Admin paneli yenilendi (3. aşama): Takipler ve Müşteriler sayfaları, panelden müşteri planı değiştirme
- Müşteri portalı yenilendi: koyu tema, yan menü, geniş ürün sayfası, bildirimler, gelişmiş talep formu, Planım
- Premium: Haftalık ve aylık rapor ile Satıcılar arası ürün kıyası (aynı ürünün market kayıtları admin panelinde "Karşılaştırma grubu" ile bağlanır)
- Premium: Alışveriş listesi (sektöre göre birden fazla sepet oluşturma/yeniden adlandırma/silme, satıcı bazında toplam kıyaslama, farklı markaları elle "eşdeğer" olarak eşleştirme)
- Bot: gerçek tarayıcı (Playwright) ile okuma, Cloudflare korumalı siteler için; JSON-LD, NEXT_DATA, data-testid, CSS class fiyat kutusu olmak üzere 4 ayrı ayrıştırıcıyı sırayla dener
- Panel: Ürünler sayfasında hangi ayrıştırıcının kullanıldığını gösteren "Yöntem" sütunu, liste/grup (karşılaştırma grubuna göre) görünüm anahtarı
- Panel: uzun listelerde sayfalama (Fiyat geçmişi: sunucu taraflı, sayfa başına 25/50/100/200; Ürünler, Müşteri talepleri, Bildirimler: tarayıcı taraflı, sayfa başına seçilebilir) ve Takipler'de müşteri başına akordiyon (5'ten fazla takibi olan müşteriler varsayılan kapalı başlar)
- Panel: Çöp kutusu (soft delete) — 9 tabloda silme artık geri yüklenebilir, kalıcı silme onay ister; bot ve giriş mantığı çöpe atılmış kayıtları görmezden gelecek şekilde güncellendi
- Müşteri portalı: Hesap ayarları sayfası (profil adı, şifre değiştirme, Telegram bağlantısını kesme, hesap kaldırma talebi)
- Müşteri portalı: Favorilerim sayfası (takip edilen ürünlerden yıldızlananlar)
- Müşteri portalı: Yardım & SSS sayfası (rehber kartları + kısa SSS)
- Panel: ürünlere karşılaştırma grubu alanı