feat: sase.tr v2 full application implementation

Complete rewrite of sase.tr VIN lookup platform with modern stack:

Backend (NestJS 10 + Drizzle ORM + PostgreSQL + Redis + BullMQ):
- 34 DB models (core + PL24 + EMEX schemas)
- Auth via Better Auth (email/password + social)
- Brands, Plans, Subscriptions, Payments (iyzico + EFT)
- VIN decode orchestration (Corgi + PL24 + EMEX + NHTSA)
- Interactive schema viewer backend (MinIO storage)
- EMEX scraping integration (Puppeteer + BullMQ workers)
- Translation module (EN→TR automotive dictionary)
- Admin dashboard API (stats, user mgmt, payment approval)
- Rate limiting, Helmet security, file upload validation

Frontend (Next.js 15 + Tailwind v4 + shadcn/ui + TanStack Query + Zustand):
- 20 routes: auth, dashboard, VIN search, schema viewer, admin
- Interactive schema viewer with zoom/pan/hotspot highlighting
- Subscription management with brand selector
- Payment flow (iyzico 3D Secure + EFT with receipt upload)
- i18n support (TR/EN)
- Error boundaries, loading skeletons, 404 page

Infrastructure:
- 85 tests (52 backend + 33 frontend, Vitest)
- CI/CD (GitHub Actions: lint, typecheck, test, build, deploy)
- Zero-downtime deploy script (PM2)
- Env validation script

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sase Dev
2026-02-12 02:03:56 +00:00
parent 7fc47ce9cc
commit 56a3c8bfaa
215 changed files with 25043 additions and 0 deletions

View File

@@ -0,0 +1,267 @@
{
"common": {
"save": "Save",
"saving": "Saving...",
"cancel": "Cancel",
"confirm": "Confirm",
"delete": "Delete",
"edit": "Edit",
"close": "Close",
"back": "Back",
"next": "Next",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"copy": "Copy",
"copied": "Copied!",
"search": "Search",
"filter": "Filter",
"all": "All",
"noData": "No data found.",
"yes": "Yes",
"no": "No",
"or": "or",
"monthly": "Monthly",
"yearly": "Yearly",
"trySymbol": "₺",
"perMonth": "/mo",
"perYear": "/yr"
},
"nav": {
"search": "Search",
"history": "History",
"subscription": "Subscription",
"billing": "Billing",
"settings": "Settings",
"admin": "Admin Panel",
"logout": "Log Out"
},
"auth": {
"login": "Log In",
"register": "Sign Up",
"loginTitle": "Log In",
"loginDescription": "Sign in to your Sase.tr account",
"registerTitle": "Sign Up",
"registerDescription": "Create a new Sase.tr account",
"email": "Email",
"password": "Password",
"name": "Full Name",
"forgotPassword": "Forgot Password",
"noAccount": "Don't have an account?",
"hasAccount": "Already have an account?",
"loginWithGoogle": "Log in with Google",
"loggingIn": "Logging in...",
"registering": "Registering...",
"loginFailed": "Login failed. Invalid email or password.",
"registerFailed": "Registration failed. Please try again.",
"resetPassword": "Reset Password",
"resetPasswordDescription": "We'll send a password reset link to your email.",
"sendResetLink": "Send Reset Link",
"resetLinkSent": "Password reset link sent to your email.",
"newPassword": "New Password",
"confirmPassword": "Confirm Password",
"currentPassword": "Current Password",
"passwordChanged": "Password changed successfully.",
"passwordChangeFailed": "Password change failed.",
"passwordsDoNotMatch": "Passwords do not match."
},
"subscription": {
"title": "Subscription",
"noSubscription": "You don't have an active subscription.",
"choosePlan": "Choose Plan",
"subscribe": "Subscribe",
"currentPlan": "Current Plan",
"cancelSubscription": "Cancel Subscription",
"cancelling": "Cancelling...",
"cancelConfirmTitle": "Cancel Subscription",
"cancelConfirmDescription": "Are you sure you want to cancel your subscription? You'll retain access until the end of the current period.",
"cancelled": "Subscription cancelled. It will end at the end of the current period.",
"resumeSubscription": "Resume Subscription",
"resuming": "Resuming...",
"resumed": "Subscription resumed.",
"accessibleBrands": "Accessible Brands",
"endDate": "End Date",
"startDate": "Start Date",
"status": "Status",
"billingPeriod": "Billing Period",
"planComparison": "Plan Comparison",
"selectBrands": "Select Brands",
"selectBrandsDescription": "Choose the brands you want to include in your plan.",
"brandsSelected": "brands selected",
"allBrandsSelected": "All selected",
"maxBrandsReached": "Maximum number of brands reached.",
"features": {
"vinSearch": "Unlimited VIN search",
"partsCatalog": "Parts catalog",
"schemaViewer": "Schema viewer",
"prioritySupport": "Priority support",
"oemSearch": "OEM parts search",
"allBrands": "All brands"
},
"plans": {
"brand1": {
"name": "1 Brand",
"description": "Spare parts access for a single brand"
},
"brand2": {
"name": "2 Brands",
"description": "Access for two different brands"
},
"brand3": {
"name": "3 Brands",
"description": "Comprehensive access for three brands"
},
"full": {
"name": "Full Package",
"description": "Unlimited access to all brands"
}
},
"statusLabels": {
"active": "Active",
"pending": "Pending",
"cancelled": "Cancelled",
"expired": "Expired"
},
"popular": "Popular"
},
"payment": {
"title": "Payment",
"summary": "Summary",
"selectedPlan": "Selected Plan",
"selectedBrands": "Selected Brands",
"totalAmount": "Total Amount",
"paymentMethod": "Payment Method",
"creditCard": "Credit Card (iyzico)",
"eftTransfer": "EFT/Wire Transfer",
"payWithCard": "Pay with Card",
"paying": "Processing payment...",
"bankDetails": "Bank Details",
"bankName": "Bank Name",
"accountHolder": "Account Holder",
"iban": "IBAN",
"description": "Description",
"paymentDescription": "Sase.tr Subscription Payment",
"uploadReceipt": "Upload Receipt",
"uploadReceiptDescription": "Upload your receipt after EFT/Wire transfer.",
"dragDrop": "Drag and drop a file or click to browse",
"supportedFormats": "PNG, JPG, or PDF (max 5MB)",
"uploading": "Uploading...",
"receiptUploaded": "Receipt uploaded successfully. Waiting for approval.",
"uploadFailed": "Receipt upload failed.",
"paymentStatus": "Payment Status",
"waitingApproval": "Waiting for Approval",
"approved": "Approved",
"step1": "Plan & Brands",
"step2": "Payment",
"step3": "Confirmation",
"confirmation": "Payment received!",
"confirmationDescription": "Your subscription has been activated successfully.",
"eftConfirmationDescription": "Your EFT/Wire receipt has been received. Your subscription will be activated after approval.",
"goToDashboard": "Go to Dashboard",
"initializeFailed": "Payment initialization failed. Please try again.",
"processingPayment": "Processing payment..."
},
"billing": {
"title": "Billing History",
"payments": "Payments",
"noPayments": "No payment records yet.",
"date": "Date",
"plan": "Plan",
"amount": "Amount",
"method": "Method",
"status": "Status",
"downloadReceipt": "Download Receipt",
"filterByStatus": "Filter by Status",
"filterByMethod": "Filter by Method",
"statusLabels": {
"completed": "Completed",
"pending": "Pending",
"failed": "Failed",
"refunded": "Refunded"
},
"methodLabels": {
"iyzico": "Credit Card",
"eft": "EFT/Wire"
}
},
"settings": {
"title": "Settings",
"tabs": {
"profile": "Profile",
"security": "Security",
"connections": "Connections",
"referral": "Referral",
"account": "Account"
},
"profile": {
"title": "Profile Information",
"description": "Update your personal information.",
"name": "Full Name",
"email": "Email",
"phone": "Phone",
"phonePlaceholder": "+90 5xx xxx xx xx",
"updated": "Profile updated.",
"updateFailed": "Failed to update profile."
},
"security": {
"title": "Change Password",
"description": "Change your password regularly for account security.",
"currentPassword": "Current Password",
"newPassword": "New Password",
"confirmPassword": "New Password (Confirm)",
"changePassword": "Change Password",
"changing": "Changing..."
},
"connections": {
"title": "Connected Accounts",
"description": "Manage your third-party account connections.",
"google": "Google Account",
"linked": "Linked",
"notLinked": "Not Linked",
"link": "Link",
"unlink": "Unlink",
"linkSuccess": "Google account linked successfully.",
"unlinkSuccess": "Google account unlinked.",
"linkFailed": "Account linking failed."
},
"referral": {
"title": "Referral Code",
"description": "Invite your friends and earn rewards.",
"yourCode": "Your Referral Code",
"noCode": "Your referral code has not been generated yet.",
"shareLink": "Invite Link",
"totalReferrals": "Total Referrals",
"rewardDays": "Days Earned",
"stats": "Referral Statistics",
"codeCopied": "Code copied!",
"linkCopied": "Link copied!"
},
"account": {
"title": "Account Management",
"description": "Permanently delete your account.",
"deleteAccount": "Delete Account",
"deleteConfirmTitle": "Are You Sure You Want to Delete Your Account?",
"deleteConfirmDescription": "This action cannot be undone. All your data, subscription, and history will be permanently deleted.",
"deleting": "Deleting...",
"deleted": "Your account has been deleted.",
"deleteFailed": "Account deletion failed.",
"typeConfirm": "Type 'DELETE' to confirm",
"confirmWord": "DELETE"
}
},
"errors": {
"generic": "An error occurred. Please try again.",
"network": "Connection error. Check your internet connection.",
"unauthorized": "Your session has expired. Please log in again.",
"forbidden": "You don't have permission for this action.",
"notFound": "The page you're looking for was not found.",
"validation": "Please fill in all fields correctly.",
"fileTooBig": "File size too large. Maximum 5MB allowed.",
"invalidFileType": "Invalid file type."
},
"language": {
"tr": "Türkçe",
"en": "English",
"switchLanguage": "Switch Language"
}
}

View File

@@ -0,0 +1,267 @@
{
"common": {
"save": "Kaydet",
"saving": "Kaydediliyor...",
"cancel": "İptal",
"confirm": "Onayla",
"delete": "Sil",
"edit": "Düzenle",
"close": "Kapat",
"back": "Geri",
"next": "İleri",
"loading": "Yükleniyor...",
"error": "Hata",
"success": "Başarılı",
"copy": "Kopyala",
"copied": "Kopyalandı!",
"search": "Ara",
"filter": "Filtrele",
"all": "Tümü",
"noData": "Veri bulunamadı.",
"yes": "Evet",
"no": "Hayır",
"or": "veya",
"monthly": "Aylık",
"yearly": "Yıllık",
"trySymbol": "₺",
"perMonth": "/ay",
"perYear": "/yıl"
},
"nav": {
"search": "Arama",
"history": "Geçmiş",
"subscription": "Abonelik",
"billing": "Fatura",
"settings": "Ayarlar",
"admin": "Admin Panel",
"logout": ıkış Yap"
},
"auth": {
"login": "Giriş Yap",
"register": "Kayıt Ol",
"loginTitle": "Giriş Yap",
"loginDescription": "Sase.tr hesabınıza giriş yapın",
"registerTitle": "Kayıt Ol",
"registerDescription": "Yeni bir Sase.tr hesabı oluşturun",
"email": "E-posta",
"password": "Şifre",
"name": "Ad Soyad",
"forgotPassword": "Şifremi Unuttum",
"noAccount": "Hesabınız yok mu?",
"hasAccount": "Zaten hesabınız var mı?",
"loginWithGoogle": "Google ile Giriş Yap",
"loggingIn": "Giriş yapılıyor...",
"registering": "Kayıt yapılıyor...",
"loginFailed": "Giriş başarısız. E-posta veya şifre hatalı.",
"registerFailed": "Kayıt başarısız. Lütfen tekrar deneyin.",
"resetPassword": "Şifre Sıfırla",
"resetPasswordDescription": "E-posta adresinize şifre sıfırlama bağlantısı göndereceğiz.",
"sendResetLink": "Sıfırlama Bağlantısı Gönder",
"resetLinkSent": "Şifre sıfırlama bağlantısı e-posta adresinize gönderildi.",
"newPassword": "Yeni Şifre",
"confirmPassword": "Şifre Tekrar",
"currentPassword": "Mevcut Şifre",
"passwordChanged": "Şifre başarıyla değiştirildi.",
"passwordChangeFailed": "Şifre değiştirme başarısız.",
"passwordsDoNotMatch": "Şifreler eşleşmiyor."
},
"subscription": {
"title": "Abonelik",
"noSubscription": "Aktif aboneliğiniz yok.",
"choosePlan": "Plan Seç",
"subscribe": "Abone Ol",
"currentPlan": "Mevcut Plan",
"cancelSubscription": "Aboneliği İptal Et",
"cancelling": "İptal ediliyor...",
"cancelConfirmTitle": "Aboneliği İptal Et",
"cancelConfirmDescription": "Aboneliğinizi iptal etmek istediğinizden emin misiniz? Dönem sonuna kadar erişiminiz devam edecek.",
"cancelled": "Abonelik iptal edildi. Dönem sonunda sona erecek.",
"resumeSubscription": "Aboneliği Devam Ettir",
"resuming": "Devam ettiriliyor...",
"resumed": "Abonelik devam ettirildi.",
"accessibleBrands": "Erişim Sağlanan Markalar",
"endDate": "Bitiş Tarihi",
"startDate": "Başlangıç Tarihi",
"status": "Durum",
"billingPeriod": "Fatura Dönemi",
"planComparison": "Plan Karşılaştırması",
"selectBrands": "Marka Seçin",
"selectBrandsDescription": "Planınıza dahil etmek istediğiniz markaları seçin.",
"brandsSelected": "marka seçildi",
"allBrandsSelected": "Tümü seçildi",
"maxBrandsReached": "Maksimum marka sayısına ulaştınız.",
"features": {
"vinSearch": "Sınırsız VIN arama",
"partsCatalog": "Parça kataloğu",
"schemaViewer": "Şema görüntüleyici",
"prioritySupport": "Öncelikli destek",
"oemSearch": "OEM parça arama",
"allBrands": "Tüm markalar"
},
"plans": {
"brand1": {
"name": "1 Marka",
"description": "Tek marka için yedek parça erişimi"
},
"brand2": {
"name": "2 Marka",
"description": "İki farklı marka için erişim"
},
"brand3": {
"name": "3 Marka",
"description": "Üç marka için kapsamlı erişim"
},
"full": {
"name": "Full Paket",
"description": "Tüm markalara sınırsız erişim"
}
},
"statusLabels": {
"active": "Aktif",
"pending": "Bekliyor",
"cancelled": "İptal Edildi",
"expired": "Süresi Doldu"
},
"popular": "Popüler"
},
"payment": {
"title": "Ödeme",
"summary": "Özet",
"selectedPlan": "Seçilen Plan",
"selectedBrands": "Seçilen Markalar",
"totalAmount": "Toplam Tutar",
"paymentMethod": "Ödeme Yöntemi",
"creditCard": "Kredi Kartı (iyzico)",
"eftTransfer": "EFT/Havale",
"payWithCard": "Kartla Öde",
"paying": "Ödeme yapılıyor...",
"bankDetails": "Banka Bilgileri",
"bankName": "Banka Adı",
"accountHolder": "Hesap Sahibi",
"iban": "IBAN",
"description": "Açıklama",
"paymentDescription": "Sase.tr Abonelik Ödemesi",
"uploadReceipt": "Dekont Yükle",
"uploadReceiptDescription": "EFT/Havale sonrası dekontunuzu yükleyin.",
"dragDrop": "Dosyayı sürükleyip bırakın veya tıklayın",
"supportedFormats": "PNG, JPG veya PDF (maks. 5MB)",
"uploading": "Yükleniyor...",
"receiptUploaded": "Dekont başarıyla yüklendi. Onay bekleniyor.",
"uploadFailed": "Dekont yükleme başarısız.",
"paymentStatus": "Ödeme Durumu",
"waitingApproval": "Onay Bekleniyor",
"approved": "Onaylandı",
"step1": "Plan ve Markalar",
"step2": "Ödeme",
"step3": "Onay",
"confirmation": "Ödemeniz alındı!",
"confirmationDescription": "Aboneliğiniz başarıyla aktifleştirildi.",
"eftConfirmationDescription": "EFT/Havale dekontunuz alındı. Onay sonrası aboneliğiniz aktifleştirilecektir.",
"goToDashboard": "Panele Git",
"initializeFailed": "Ödeme başlatılamadı. Lütfen tekrar deneyin.",
"processingPayment": "Ödeme işleniyor..."
},
"billing": {
"title": "Fatura Geçmişi",
"payments": "Ödemeler",
"noPayments": "Henüz ödeme kaydı yok.",
"date": "Tarih",
"plan": "Plan",
"amount": "Tutar",
"method": "Yöntem",
"status": "Durum",
"downloadReceipt": "Dekontu İndir",
"filterByStatus": "Duruma Göre Filtrele",
"filterByMethod": "Yönteme Göre Filtrele",
"statusLabels": {
"completed": "Tamamlandı",
"pending": "Bekliyor",
"failed": "Başarısız",
"refunded": "İade"
},
"methodLabels": {
"iyzico": "Kredi Kartı",
"eft": "EFT/Havale"
}
},
"settings": {
"title": "Ayarlar",
"tabs": {
"profile": "Profil",
"security": "Güvenlik",
"connections": "Bağlantılar",
"referral": "Referans",
"account": "Hesap"
},
"profile": {
"title": "Profil Bilgileri",
"description": "Kişisel bilgilerinizi güncelleyin.",
"name": "Ad Soyad",
"email": "E-posta",
"phone": "Telefon",
"phonePlaceholder": "+90 5xx xxx xx xx",
"updated": "Profil güncellendi.",
"updateFailed": "Profil güncellenirken hata oluştu."
},
"security": {
"title": "Şifre Değiştir",
"description": "Hesap güvenliğiniz için şifrenizi düzenli olarak değiştirin.",
"currentPassword": "Mevcut Şifre",
"newPassword": "Yeni Şifre",
"confirmPassword": "Yeni Şifre (Tekrar)",
"changePassword": "Şifre Değiştir",
"changing": "Değiştiriliyor..."
},
"connections": {
"title": "Bağlı Hesaplar",
"description": "Üçüncü parti hesap bağlantılarınızı yönetin.",
"google": "Google Hesabı",
"linked": "Bağlı",
"notLinked": "Bağlı Değil",
"link": "Bağla",
"unlink": "Bağlantıyı Kaldır",
"linkSuccess": "Google hesabı başarıyla bağlandı.",
"unlinkSuccess": "Google hesabı bağlantısı kaldırıldı.",
"linkFailed": "Hesap bağlama başarısız."
},
"referral": {
"title": "Referans Kodu",
"description": "Arkadaşlarınızı davet edin ve ödüller kazanın.",
"yourCode": "Referans Kodunuz",
"noCode": "Referans kodunuz henüz oluşturulmamış.",
"shareLink": "Davet Bağlantısı",
"totalReferrals": "Toplam Davetler",
"rewardDays": "Kazanılan Gün",
"stats": "Referans İstatistikleri",
"codeCopied": "Kod kopyalandı!",
"linkCopied": "Bağlantı kopyalandı!"
},
"account": {
"title": "Hesap Yönetimi",
"description": "Hesabınızı kalıcı olarak silin.",
"deleteAccount": "Hesabı Sil",
"deleteConfirmTitle": "Hesabınızı Silmek İstediğinize Emin Misiniz?",
"deleteConfirmDescription": "Bu işlem geri alınamaz. Tüm verileriniz, aboneliğiniz ve geçmişiniz kalıcı olarak silinecektir.",
"deleting": "Siliniyor...",
"deleted": "Hesabınız silindi.",
"deleteFailed": "Hesap silme başarısız.",
"typeConfirm": "Onaylamak için 'SİL' yazın",
"confirmWord": "SİL"
}
},
"errors": {
"generic": "Bir hata oluştu. Lütfen tekrar deneyin.",
"network": "Bağlantı hatası. İnternet bağlantınızı kontrol edin.",
"unauthorized": "Oturumunuz sona erdi. Lütfen tekrar giriş yapın.",
"forbidden": "Bu işlem için yetkiniz yok.",
"notFound": "Aradığınız sayfa bulunamadı.",
"validation": "Lütfen tüm alanları doğru şekilde doldurun.",
"fileTooBig": "Dosya boyutu çok büyük. Maksimum 5MB yükleyebilirsiniz.",
"invalidFileType": "Geçersiz dosya türü."
},
"language": {
"tr": "Türkçe",
"en": "English",
"switchLanguage": "Dil Değiştir"
}
}