feat(shopping): mağazalar, zahmet skoru ve ürünler (marka/paket, dönüşüm, görseller)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-06 11:48:04 +03:00
parent 8e7e374778
commit f0b570284e
23 changed files with 1893 additions and 1 deletions
+152
View File
@@ -66,6 +66,7 @@ export const tr = {
contacts: "Cari hesaplar",
savings: "Birikim",
stock: "Ev stoğu",
stores: "Mağazalar",
shopping: "Alışveriş",
reports: "Raporlar",
settings: "Ayarlar",
@@ -1196,6 +1197,157 @@ export const tr = {
open: "Ev stoğuna git",
},
},
stores: {
title: "Mağazalar",
description:
"Alışveriş yaptığınız marketler, online platformlar ve pazarlar. Uzaklık ve taşıma güçlüğünden zahmet skoru hesaplanır; alışveriş önerisi bunu dikkate alır.",
new: "Yeni mağaza",
createTitle: "Yeni mağaza",
editTitle: "Mağazayı düzenle",
empty: "Henüz mağaza yok. “Yeni mağaza” ile ekleyin.",
readOnly: "İzleyici rolündesiniz; mağazaları değiştiremezsiniz.",
sort: "Sırala",
sorts: {
name: "Ada göre",
nearest: "En yakın",
farthest: "En uzak",
effort: "En zahmetli",
},
showArchived: "Arşivi göster",
archived: "Arşivli",
kinds: {
market: "Fiziksel market",
online: "Online platform",
bazaar: "Pazar",
},
kindShort: {
market: "Market",
online: "Online",
bazaar: "Pazar",
},
fields: {
name: "Ad",
namePlaceholder: "ör. Migros, A101, Semt pazarı",
kind: "Tür",
branch: "Şube",
branchPlaceholder: "ör. Kadıköy",
distance: "Eve uzaklık (km)",
distanceHint: "ör. 1,5. Online mağazada gerekmez.",
carry: "Taşıma güçlüğü",
carryHint: "1 = kolay (kapının önü), 5 = çok zor (uzak, yokuş, araç gerekir).",
deliveryFee: "Teslimat ücreti",
freeDeliveryMin: "Ücretsiz teslimat alt limiti",
mealCard: "Yemek kartı geçerli",
mealCardProviders: "Geçerli yemek kartları",
note: "Not",
},
carryLevels: {
1: "Kolay",
2: "Rahat",
3: "Orta",
4: "Zor",
5: "Çok zor",
} as Record<number, string>,
effort: "Zahmet",
effortLevels: { low: "Düşük", medium: "Orta", high: "Yüksek" },
effortValue: (score: number) => `Zahmet ${score}/100`,
effortHint:
"Zahmet skoru 0–100: uzaklık (20 km'ye kadar) ve taşıma güçlüğü eşit ağırlıkla. Online mağazada uzaklık sayılmaz.",
distanceUnknown: "Uzaklık girilmedi",
delivery: (fee: string) => `Teslimat ${fee}`,
freeDeliveryFrom: (min: string) => `${min} üzeri ücretsiz`,
freeDelivery: "Ücretsiz teslimat",
mealCardBadge: "Yemek kartı",
actions: {
edit: "Düzenle",
archive: "Arşivle",
unarchive: "Arşivden çıkar",
more: "Mağaza işlemleri",
},
archiveTitle: "Mağaza arşivlensin mi?",
archiveDescription: (name: string) =>
`“${name}” yeni fiyat ve alışverişlerde seçilemez. Geçmiş kayıtları silinmez.`,
toast: {
saved: "Mağaza kaydedildi.",
archived: "Mağaza arşivlendi.",
unarchived: "Mağaza arşivden çıkarıldı.",
},
validation: {
distance: "Geçerli bir uzaklık girin (ör. 2,5)",
carry: "1 ile 5 arasında seçin",
providers: "En az bir yemek kartı seçin",
duplicate: "Bu ad ve şubeyle bir mağaza zaten var.",
archived: "Mağaza arşivli.",
},
},
products: {
title: "Ürünler",
description:
"Marka ve paket düzeyinde ürünler (ör. “Ariel Matik 5 kg”). Her ürün bir ürün tipine bağlıdır; stok ürün tipinde tutulur, fiyatlar üründe.",
catalogLink: "Ürün kataloğu",
back: "Ev stoğuna dön",
new: "Yeni ürün",
createTitle: "Yeni ürün",
editTitle: "Ürünü düzenle",
sectionTitle: "Ürünler (marka / paket)",
sectionDescription:
"Bu ürün tipinin markaları ve paketleri. Fiyatlar ve birim fiyat karşılaştırması bu ürünler üzerinden yapılır.",
empty: "Henüz ürün yok.",
emptyType: "Bu ürün tipine henüz marka/paket eklenmedi.",
search: "Marka, tanım veya barkod ara",
noMatch: "Aramaya uyan ürün yok.",
showArchived: "Arşivi göster",
archived: "Arşivli",
barcode: (code: string) => `Barkod ${code}`,
images: (n: number) => `${n} görsel`,
conversionMissing: "Dönüşüm gerekli",
conversionMissingHint:
"Ürün tipinin birimi değişti; bu paketin karşılığını girmeden fiyatı karşılaştırılamaz.",
fields: {
productType: "Ürün tipi",
brand: "Marka",
brandPlaceholder: "ör. Ariel, Fairy, Yayla",
name: "Tanım",
namePlaceholder: "ör. Matik Dağ Esintisi",
barcode: "Barkod",
barcodeHint: "İsteğe bağlı, 8–14 rakam.",
packageQuantity: "Paket miktarı",
packageUnit: "Paket birimi",
typeQuantity: (unit: string) => `Bir paket kaç ${unit}?`,
typeQuantityHint: (pkg: string, unit: string) =>
`${pkg} ürün tipinin birimine (${unit}) kendiliğinden çevrilemiyor; ör. 5 kg = 50 yıkama.`,
autoConversion: (pkg: string) => `Bir paket = ${pkg}`,
images: "Ürün görselleri",
addImage: "Görsel ekle",
imagesHint: "Ambalajın önü, arkası veya raf etiketi",
note: "Not",
},
actions: {
edit: "Düzenle",
archive: "Arşivle",
unarchive: "Arşivden çıkar",
more: "Ürün işlemleri",
},
archiveTitle: "Ürün arşivlensin mi?",
archiveDescription: (name: string) =>
`“${name}” yeni fiyat ve alışveriş listelerinde seçilemez. Görselleri ve geçmişi silinmez.`,
toast: {
saved: "Ürün kaydedildi.",
archived: "Ürün arşivlendi.",
unarchived: "Ürün arşivden çıkarıldı.",
},
validation: {
productType: "Aktif bir ürün tipi seçin",
barcode: "Barkod 8–14 rakam olmalı",
barcodeTaken: "Bu barkod başka bir üründe kayıtlı.",
packageQuantity: "Geçerli bir paket miktarı girin (ör. 5 veya 0,5)",
packageUnit: "Paket birimi 1–20 karakter olmalı",
typeQuantity: "Geçerli bir miktar girin",
conversionRequired: (pkgUnit: string, typeUnit: string) =>
`${pkgUnit} → ${typeUnit} dönüşümünü girin (bir paket kaç ${typeUnit}?).`,
archived: "Ürün arşivli.",
},
},
prices: {
title: "Fiyat tablosu",
description: