feat(shopping): alışveriş listeleri, stok eşiği önerileri ve akıllı mağaza önerisi motoru
- shoppingLists koleksiyonu (ürün tipi / marka / serbest metin kalemleri), migration 015 - planShopping saf fonksiyonu: paket yuvarlama, zahmet ve hacimli cezası, teslimat, yemek kartı önceliği, ek mağaza eşiği - eşik önerileri onay/red (red stok yenilenene kadar), ürün tipine hacimli işareti - fiyat servisinde ortak loadTypeOffers; seed listeleri ve testler Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+147
@@ -1012,6 +1012,7 @@ export const tr = {
|
||||
title: "Alınması önerilenler",
|
||||
description: "Kritik eşiğin altına düşen ürünler ve hedefe tamamlamak için gereken miktar.",
|
||||
empty: "Eşiğin altına düşen ürün yok.",
|
||||
toShopping: "Alışveriş listelerinde onayla veya reddet",
|
||||
suggested: (q: string) => `Öneri: ${q}`,
|
||||
wasteReduced: (purchases: number, pct: number) =>
|
||||
`Son ${purchases} alımda %${pct} fire, miktar azaltıldı.`,
|
||||
@@ -1055,6 +1056,9 @@ export const tr = {
|
||||
stepHint: "Hızlı azaltma düğmesinin düşeceği miktar.",
|
||||
countEveryDays: "Sayım sıklığı (gün)",
|
||||
countEveryDaysHint: "Boş bırakılırsa kategoriden devralınır.",
|
||||
bulky: "Ağır / hacimli",
|
||||
bulkyHint:
|
||||
"Su, deterjan gibi taşıması zor ürünler. Akıllı öneri bunları yakın ya da online mağazaya yönlendirir.",
|
||||
note: "Not",
|
||||
initialQuantity: "Evdeki mevcut miktar",
|
||||
initialHint: "Tahmini veya ambalaj üzerinden. Boş bırakılırsa 0 kabul edilir.",
|
||||
@@ -1352,6 +1356,149 @@ export const tr = {
|
||||
archived: "Ürün arşivli.",
|
||||
},
|
||||
},
|
||||
shopping: {
|
||||
title: "Alışveriş listeleri",
|
||||
description:
|
||||
"Aile üyeleri aynı listeleri kullanır. Stokta azalan ürünler öneri olarak gelir; akıllı öneri en uygun mağaza ve markayı seçer.",
|
||||
readOnly: "Görüntüleme yetkiniz var; listeleri değiştiremezsiniz.",
|
||||
newList: "Yeni liste",
|
||||
createTitle: "Yeni alışveriş listesi",
|
||||
editTitle: "Listeyi düzenle",
|
||||
active: "Aktif listeler",
|
||||
completed: "Tamamlanan alışverişler",
|
||||
emptyActive: "Aktif liste yok. Yeni bir liste açın.",
|
||||
itemCount: (n: number) => `${n} kalem`,
|
||||
checkedCount: (done: number, total: number) => `${done}/${total} alındı`,
|
||||
updated: (when: string) => `Güncellendi: ${when}`,
|
||||
completedAt: (when: string) => `Tamamlandı: ${when}`,
|
||||
emptyList: "Liste boş.",
|
||||
suggestionsBanner: (n: number) =>
|
||||
`Stokta eşiğin altına düşen ${n} ürün var. Bir listeyi açıp öneriyi onaylayın ya da reddedin.`,
|
||||
fields: {
|
||||
name: "Liste adı",
|
||||
namePlaceholder: "ör. Haftalık market, Ay başı toptan",
|
||||
note: "Not",
|
||||
kind: "Kalem türü",
|
||||
productType: "Ürün tipi",
|
||||
product: "Ürün (marka/paket)",
|
||||
text: "Kalem",
|
||||
textPlaceholder: "ör. Doğum günü mumu",
|
||||
quantity: "Miktar",
|
||||
packages: "Paket adedi",
|
||||
quantityHint: "Boş bırakılırsa en az bir paket.",
|
||||
unit: "Birim",
|
||||
unitPlaceholder: "ör. adet",
|
||||
itemNote: "Not",
|
||||
itemNotePlaceholder: "ör. laktozsuz olsun",
|
||||
},
|
||||
kinds: { type: "Ürün tipi", product: "Belirli marka", text: "Serbest metin" },
|
||||
kindHints: {
|
||||
type: "Markayı akıllı öneri seçer.",
|
||||
product: "Yalnızca bu ürün önerilir.",
|
||||
text: "Stokla ve fiyatlarla bağlanmaz.",
|
||||
},
|
||||
packageUnit: "paket",
|
||||
stockLine: (current: string, target: string) => `Evde ${current} / hedef ${target}`,
|
||||
fromSuggestion: "Stok önerisi",
|
||||
archivedRef: "Arşivlendi",
|
||||
actions: {
|
||||
more: "Diğer işlemler",
|
||||
addItem: "Kalem ekle",
|
||||
edit: "Düzenle",
|
||||
editList: "Listeyi düzenle",
|
||||
deleteList: "Listeyi sil",
|
||||
remove: "Listeden çıkar",
|
||||
moveTo: "Başka listeye taşı",
|
||||
goShopping: "Alışverişe çık",
|
||||
back: "Alışveriş listeleri",
|
||||
backToList: "Listeye dön",
|
||||
},
|
||||
editItemTitle: "Kalemi düzenle",
|
||||
addItemTitle: "Kalem ekle",
|
||||
moveTitle: "Başka listeye taşı",
|
||||
moveDescription: (name: string) => `"${name}" seçilen aktif listeye taşınır.`,
|
||||
moveTarget: "Hedef liste",
|
||||
noOtherLists: "Taşınabilecek başka aktif liste yok.",
|
||||
deleteTitle: "Liste silinsin mi?",
|
||||
deleteDescription: (name: string) => `"${name}" listesi ve kalemleri silinir.`,
|
||||
suggestions: {
|
||||
title: "Stok önerileri",
|
||||
description: "Eşiğin altına düşen ürünler. Onaylananlar önerilen miktarla listeye eklenir.",
|
||||
addAll: "Tümünü ekle",
|
||||
add: "Ekle",
|
||||
dismiss: "Reddet",
|
||||
dismissHint: "Stok yenilenene (yeni alım girilene) kadar önerilmez.",
|
||||
line: (current: string, target: string, pct: number | null) =>
|
||||
`Evde ${current} / hedef ${target}${pct === null ? "" : ` (%${pct})`}`,
|
||||
suggested: (q: string) => `Önerilen: ${q}`,
|
||||
},
|
||||
plan: {
|
||||
title: "Akıllı mağaza önerisi",
|
||||
description:
|
||||
"Son bilinen fiyatlarla. Uzaklık ve taşıma güçlüğü, online teslimat ücreti ve yemek kartı bakiyesi hesaba katılır.",
|
||||
recommended: "Önerilen dağılım",
|
||||
single: "Tek mağaza",
|
||||
singleBest: (store: string, total: string) => `Tek mağaza en iyi seçenek: ${store}, ${total}`,
|
||||
split: (parts: string, total: string) => `Önerilen dağılım: ${parts}: ${total}`,
|
||||
part: (store: string, n: number) => `${store} (${n} ürün)`,
|
||||
saving: (amount: string) => `${amount} tasarruf`,
|
||||
singleMissing: (n: number) => `Tek mağazada ${n} kalem bulunmuyor.`,
|
||||
threshold: (amount: string) =>
|
||||
`Ek mağaza ancak ${amount} üstü tasarruf sağlarsa önerilir (hane ayarı).`,
|
||||
mealCard: (amount: string) => `Yemek kartıyla ödenebilir: ${amount}`,
|
||||
mealCardBalance: (amount: string) => `Yemek kartı bakiyeniz: ${amount}`,
|
||||
delivery: (amount: string) => `Teslimat ${amount}`,
|
||||
freeDelivery: "Teslimat ücretsiz",
|
||||
subtotal: "Ara toplam",
|
||||
total: "Tahmini toplam",
|
||||
line: (packages: string, price: string) => `${packages} × ${price}`,
|
||||
unpriced: "Fiyatı bilinmeyenler",
|
||||
unpricedHint: "Bu kalemler için mağaza fiyatı girilmemiş.",
|
||||
cheapestAt: (store: string, unitPrice: string) =>
|
||||
`En ucuz birim fiyat: ${store}, ${unitPrice}`,
|
||||
empty: "Öneri için listede fiyatı bilinen ürün yok.",
|
||||
textItems: "Serbest metin kalemleri öneriye katılmaz.",
|
||||
missing: "Bu planda alınamayan",
|
||||
},
|
||||
mode: {
|
||||
title: "Alışveriş modu",
|
||||
progress: (done: number, total: number) => `${done}/${total} sepette`,
|
||||
other: "Diğer",
|
||||
otherHint: "Fiyatı bilinmeyen ve serbest metin kalemleri",
|
||||
inCart: "Sepette",
|
||||
allDone: "Hepsi sepette.",
|
||||
planChoice: "Plan",
|
||||
check: (label: string) => `${label}: sepete alındı olarak işaretle`,
|
||||
refreshed: "Liste güncellendi",
|
||||
},
|
||||
toast: {
|
||||
saved: "Liste kaydedildi.",
|
||||
deleted: "Liste silindi.",
|
||||
itemAdded: "Kalem eklendi.",
|
||||
itemSaved: "Kalem güncellendi.",
|
||||
itemRemoved: "Kalem listeden çıkarıldı.",
|
||||
moved: "Kalem taşındı.",
|
||||
suggestionsAdded: (n: number) => `${n} öneri listeye eklendi.`,
|
||||
dismissed: "Öneri reddedildi.",
|
||||
},
|
||||
validation: {
|
||||
quantity: "Geçerli bir miktar girin (ör. 2 veya 1,5)",
|
||||
productType: "Aktif bir ürün tipi seçin",
|
||||
product: "Aktif bir ürün seçin",
|
||||
text: "Kalem adını yazın",
|
||||
duplicate: "Bu ürün listede zaten var; miktarını düzenleyin.",
|
||||
duplicateIn: (name: string) => `Bu ürün "${name}" listesinde zaten var.`,
|
||||
notActive: "Bu liste tamamlandı; değiştirilemez.",
|
||||
sameList: "Kalem zaten bu listede.",
|
||||
suggestionGone: "Öneri artık geçerli değil (listede ya da stok yenilenmiş).",
|
||||
},
|
||||
dashboard: {
|
||||
title: "Alışveriş",
|
||||
empty: "Aktif liste yok.",
|
||||
open: "Listeleri aç",
|
||||
suggestions: (n: number) => `${n} stok önerisi bekliyor`,
|
||||
},
|
||||
},
|
||||
productPrices: {
|
||||
add: "Fiyat gir",
|
||||
addTitle: "Fiyat gir",
|
||||
|
||||
Reference in New Issue
Block a user