const { useEffect, useMemo, useRef, useState } = React;
// Multi-store marketplace v1: customer hub, merchant applications, merchant admin, platform admin, shared delivery fleet.
// No external packages or CDN icon imports.
const PLATFORM_DEFAULTS = {
brandName: "Road Runner Local Hub",
brandLogo: "",
companyName: "Road Runner Company",
supportEmail: "support@roadrunner.local",
supportPhone: "28220 00000",
legalAddress: "Κίσσαμος, Χανιά",
subtitle: "Marketplace παραγγελιών για τοπικά καταστήματα",
platformPin: "9999",
serviceFee: 0.3,
deliveryFee: 1,
freeDeliveryFrom: 8,
minOrder: 3,
deliveryEnabled: true,
pickupEnabled: true,
payCashEnabled: true,
payCardDeliveryEnabled: true,
payStoreCardEnabled: true,
driverBaseEtaMinutes: 25,
driverBusyExtraMinutes: 8,
driverPickupPrepMinutes: 10,
liveDriverTrackingEnabled: true,
driverLocationMaxAgeMinutes: 10,
driverCommissionPercent: 40,
driverPlatformFeePercent: 60,
driverMinWithdraw: 300,
driverRewardEnabled: true,
driverRewardMinRating: 4.8,
driverRewardBonusPerOrder: 0.2,
loyaltyEnabled: true,
loyaltyEarnPoints: 1,
loyaltyEarnEuro: 1,
loyaltyRedeemEnabled: true,
loyaltyRedeemPoints: 100,
loyaltyRedeemEuro: 1,
loyaltyMinRedeemPoints: 100,
loyaltyMaxDiscountPercent: 100,
loyaltyApplyOnFees: true,
loyaltyTierSilver: 250,
loyaltyTierGold: 750,
loyaltyTierBlack: 1500,
loyaltyStreakBonusPoints: 15,
platformAnnouncement: "Ένα hub για καφέ, snacks, προσφορές και delivery από πολλά καταστήματα.",
contactText: `Επικοινωνία πλατφόρμας
Για υποστήριξη πελατών, καταστημάτων και διανομέων μπορείς να επικοινωνήσεις με την πλατφόρμα μέσω email ή τηλεφώνου.
Η πλατφόρμα διαχειρίζεται τεχνικά την παραγγελιοληψία, την εμφάνιση καταστημάτων, την καταχώρηση παραγγελιών, την επικοινωνία με τον πελάτη και τη ροή παράδοσης. Για θέματα ποιότητας προϊόντων, διαθεσιμότητας, συσκευασίας και φορολογικών παραστατικών, υπεύθυνο είναι το αντίστοιχο κατάστημα, εκτός αν υπάρχει διαφορετική γραπτή συμφωνία με την πλατφόρμα.`,
termsText: `Όροι χρήσης πλατφόρμας
1. Ρόλος πλατφόρμας
Η πλατφόρμα λειτουργεί ως τεχνολογικό σύστημα παραγγελιοληψίας, διαχείρισης παραγγελιών, προβολής συνεργαζόμενων καταστημάτων και, όπου είναι ενεργό, συντονισμού διανομής. Δεν υποκαθιστά το κατάστημα ως προς την ποιότητα, την προετοιμασία, τη διαθεσιμότητα, τη νομιμότητα προϊόντων, την έκδοση αποδείξεων/τιμολογίων και τη συμμόρφωση με υγειονομικούς ή φορολογικούς κανόνες.
2. Παραγγελίες
Ο πελάτης οφείλει να καταχωρεί σωστό όνομα, τηλέφωνο, διεύθυνση, όροφο/κουδούνι, οδηγίες παράδοσης και τρόπο πληρωμής. Λανθασμένα στοιχεία μπορεί να οδηγήσουν σε καθυστέρηση, ακύρωση ή αποτυχία παράδοσης.
3. Χρεώσεις πλατφόρμας
Σε κάθε παραγγελία μπορεί να υπάρχουν service fee, delivery fee ή άλλες εμφανείς χρεώσεις πλατφόρμας. Οι χρεώσεις εμφανίζονται πριν την ολοκλήρωση της παραγγελίας. Η πλατφόρμα διατηρεί το δικαίωμα να μεταβάλλει fees, ελάχιστη παραγγελία, free delivery όρια, loyalty κανόνες, delivery κανόνες και ποσοστά διανομής οποιαδήποτε στιγμή, με εμφάνιση των νέων τιμών στο checkout ή/και στους όρους.
4. Καταστήματα
Κάθε κατάστημα είναι υπεύθυνο για τα προϊόντα, τις τιμές προϊόντων, τη διαθεσιμότητα, την προετοιμασία, τη συσκευασία, την ακρίβεια των πληροφοριών και την έκδοση νόμιμων παραστατικών όπου απαιτείται.
5. Διανομείς
Οι διανομείς οφείλουν να ακολουθούν τους κανόνες παραλαβής/παράδοσης, να προστατεύουν τα προσωπικά δεδομένα πελατών, να μη χρησιμοποιούν στοιχεία πελατών εκτός της συγκεκριμένης παράδοσης και να χειρίζονται μετρητά με ακρίβεια.
6. Αποκλεισμοί και διαγραφή
Η πλατφόρμα μπορεί να αναστείλει, αποκλείσει ή διαγράψει λογαριασμό πελάτη, διανομέα ή καταστήματος σε περίπτωση παραβίασης κανόνων, κακής χρήσης, ψευδών στοιχείων, απάτης, επαναλαμβανόμενων προβλημάτων ή επιχειρησιακής ανάγκης. Τα καταστήματα μπορούν να αποκλείουν πελάτες μόνο από το δικό τους κατάστημα.
7. Αξιολογήσεις
Ο πελάτης μπορεί να αξιολογεί τον διανομέα μετά από ολοκληρωμένη παράδοση. Οι αξιολογήσεις χρησιμοποιούνται για ποιότητα υπηρεσίας, επιβράβευση, έλεγχο απόδοσης και πιθανή αναστολή συνεργασίας σε περιπτώσεις σοβαρών ή επαναλαμβανόμενων παραπόνων.
8. Αλλαγές όρων
Η συνέχιση χρήσης της πλατφόρμας μετά από αλλαγές στους όρους θεωρείται αποδοχή των ενημερωμένων όρων, εφόσον οι αλλαγές εμφανίζονται διαθέσιμες στην πλατφόρμα.`,
privacyText: `Πολιτική απορρήτου
1. Δεδομένα που συλλέγονται
Η πλατφόρμα μπορεί να αποθηκεύει όνομα, τηλέφωνο, email, διεύθυνση, όροφο/κουδούνι, σημειώσεις παράδοσης, ιστορικό παραγγελιών, στοιχεία καταστήματος, στοιχεία διανομέα, στοιχεία οχήματος, αξιολογήσεις, logs κατάστασης παραγγελιών, τεχνικά δεδομένα λειτουργίας και, όταν ο διανομέας έχει ενεργό GPS tracking, προσωρινή τοποθεσία διανομέα για την παρακολούθηση της ενεργής παράδοσης.
2. Σκοπός επεξεργασίας
Τα δεδομένα χρησιμοποιούνται για δημιουργία λογαριασμού, εκτέλεση παραγγελίας, επικοινωνία πελάτη-καταστήματος-διανομέα, υποστήριξη, πρόληψη κατάχρησης, λογιστικό/επιχειρησιακό έλεγχο, loyalty, αξιολογήσεις και βελτίωση υπηρεσίας.
3. Κοινοποίηση δεδομένων
Τα απαραίτητα στοιχεία πελάτη εμφανίζονται στο κατάστημα και στον διανομέα μόνο για την εκτέλεση της συγκεκριμένης παραγγελίας. Ο διανομέας βλέπει όνομα, τηλέφωνο, διεύθυνση, όροφο/κουδούνι, οδηγίες, τρόπο πληρωμής και περιεχόμενο παραγγελίας. Δεν επιτρέπεται χρήση αυτών των στοιχείων για άλλον σκοπό.
4. Δικαιώματα χρήστη
Ο χρήστης μπορεί να ζητήσει ενημέρωση, διόρθωση, περιορισμό, αντίρρηση ή διαγραφή προσωπικών δεδομένων, όπου αυτό επιτρέπεται από την ισχύουσα νομοθεσία και τις υποχρεώσεις τήρησης επιχειρησιακών/φορολογικών αρχείων.
5. Ασφάλεια
Η πλατφόρμα πρέπει να εφαρμόζει τεχνικά και οργανωτικά μέτρα όπως περιορισμένη πρόσβαση, ρόλους χρηστών, καταγραφή ενεργειών, ασφαλή αποθήκευση, προστασία από μη εξουσιοδοτημένη πρόσβαση και ελαχιστοποίηση δεδομένων.
6. Χρόνος τήρησης
Τα δεδομένα τηρούνται για όσο χρειάζεται για την παροχή της υπηρεσίας, την υποστήριξη, τον έλεγχο συναλλαγών και τις νόμιμες υποχρεώσεις. Δεδομένα που δεν χρειάζονται πλέον πρέπει να διαγράφονται ή να ανωνυμοποιούνται.`,
refundText: `Ακυρώσεις, παράπονα και επιστροφές
Οι παραγγελίες φαγητού/ροφημάτων είναι άμεσης εκτέλεσης και συχνά αφορούν προϊόντα που ετοιμάζονται κατά παραγγελία. Ακύρωση μπορεί να γίνει μόνο πριν την αποδοχή ή πριν την έναρξη προετοιμασίας από το κατάστημα, ανάλογα με την πολιτική της πλατφόρμας και του καταστήματος.
Αν υπάρχει λάθος προϊόν, ελλιπής παραγγελία, μεγάλη καθυστέρηση, πρόβλημα ποιότητας ή λάθος χρέωση, ο πελάτης πρέπει να επικοινωνεί άμεσα με την υποστήριξη. Η πλατφόρμα εξετάζει το αίτημα σε συνεργασία με το κατάστημα και, όπου υπάρχει διανομή, με τον διανομέα.
Η πλατφόρμα μπορεί να αποφασίσει επαναποστολή, μερική επιστροφή, πλήρη επιστροφή, κουπόνι/πίστωση ή απόρριψη αιτήματος, ανάλογα με τα στοιχεία της περίπτωσης.`,
merchantTermsText: `Όροι συνεργαζόμενων καταστημάτων
Το κατάστημα αποδέχεται ότι η πλατφόρμα μπορεί να εμφανίζει service fee, delivery fee ή άλλη χρέωση προς τον πελάτη. Αυτές οι χρεώσεις αφορούν τη χρήση της πλατφόρμας, την τεχνική λειτουργία, την παραγγελιοληψία και/ή τη διανομή, και μπορούν να αλλάξουν οποιαδήποτε στιγμή από τον Platform Admin.
Το κατάστημα παραμένει υπεύθυνο για προϊόντα, τιμές προϊόντων, ποιότητα, συσκευασία, χρόνους προετοιμασίας, φορολογικά παραστατικά, άδειες λειτουργίας, υγειονομική συμμόρφωση και σωστή ενημέρωση του μενού.
Το κατάστημα μπορεί να αποκλείει πελάτη μόνο από το δικό του κατάστημα. Η πλατφόρμα διατηρεί το δικαίωμα καθολικού αποκλεισμού χρήστη ή καταστήματος.`,
driverRulesText: `Κανόνες διανομέων
1. Ο διανομέας βλέπει τα στοιχεία πελάτη μόνο για τη συγκεκριμένη παράδοση.
2. Δεν επιτρέπεται αποθήκευση, κοινοποίηση ή προσωπική χρήση τηλεφώνου/διεύθυνσης πελάτη.
3. Πριν φύγει από το κατάστημα ελέγχει αριθμό παραγγελίας, σακούλες, ροφήματα, συνοδευτικά και ειδικές οδηγίες.
4. Σε πληρωμή με μετρητά εισπράττει το ποσό που εμφανίζει η παραγγελία και επιστρέφει σωστά ρέστα.
5. Σε πληρωμή με κάρτα στον διανομέα ακολουθείται η εγκεκριμένη διαδικασία POS/τερματικού.
6. Δεν παραδίδει παραγγελία σε λάθος άτομο ή λάθος διεύθυνση χωρίς τηλεφωνική επιβεβαίωση.
7. Ολοκληρώνει την παραγγελία μόνο μετά την πραγματική παράδοση στον πελάτη.
8. Χαμηλές αξιολογήσεις, ακυρώσεις, παράπονα ή κακή χρήση μπορούν να οδηγήσουν σε αναστολή ή αποκλεισμό.
9. Υψηλές αξιολογήσεις μπορούν να δίνουν bonus όταν είναι ενεργό το σύστημα επιβράβευσης.
10. Όταν ο διανομέας ενεργοποιεί GPS tracking, η ζωντανή τοποθεσία εμφανίζεται μόνο για επιχειρησιακό έλεγχο ενεργής διανομής σε πελάτη, κατάστημα και διαχείριση πλατφόρμας.`,
cashHandlingText: `Λειτουργία μετρητών
Σε παραγγελίες με μετρητά ο διανομέας πρέπει να βλέπει καθαρά το συνολικό ποσό, αν ο πελάτης ζητά ρέστα από συγκεκριμένο χαρτονόμισμα, και τις οδηγίες παράδοσης. Ο διανομέας παραδίδει την παραγγελία, εισπράττει το σωστό ποσό και επιστρέφει ρέστα όπου χρειάζεται. Διαφωνίες πληρωμής πρέπει να δηλώνονται στην πλατφόρμα.`,
deliveryFlowText: `Ροή παραλαβής και παράδοσης
Νέα παραγγελία → αποδοχή από κατάστημα → ετοιμασία → ανάθεση διανομέα → παραλαβή από κατάστημα → διαδρομή προς πελάτη → παράδοση → rating πελάτη.
Ο διανομέας πριν πατήσει "Παρέλαβα" πρέπει να έχει λάβει όλα τα προϊόντα. Πριν πατήσει "Ολοκλήρωση" πρέπει να έχει παραδώσει πραγματικά στον πελάτη ή σε εξουσιοδοτημένο πρόσωπο.`,
};
const DEFAULT_CATEGORIES = ["Προσφορές", "Καφέδες", "Ροφήματα", "Σφολιάτες", "Σάντουιτς", "Γλυκά", "Snacks"];
const statusSteps = [
{ key: "new", label: "Νέα", text: "Η παραγγελία καταχωρήθηκε", icon: "🧾" },
{ key: "accepted", label: "Αποδοχή", text: "Το κατάστημα την αποδέχτηκε", icon: "✅" },
{ key: "preparing", label: "Ετοιμασία", text: "Το κατάστημα ετοιμάζει την παραγγελία", icon: "🍳" },
{ key: "driver_assigned", label: "Ανάθεση", text: "Ανατέθηκε σε διανομέα", icon: "🛵" },
{ key: "picked_up", label: "Παραλαβή", text: "Ο διανομέας παρέλαβε από το κατάστημα", icon: "📦" },
{ key: "delivery", label: "Διανομή", text: "Ο διανομέας είναι καθ’ οδόν", icon: "🛵" },
{ key: "completed", label: "Ολοκληρώθηκε", text: "Παραδόθηκε στον πελάτη", icon: "🎉" },
];
const statusLabels = {
new: "Νέα παραγγελία",
accepted: "Αποδοχή από κατάστημα",
preparing: "Σε ετοιμασία",
driver_assigned: "Ανατέθηκε σε διανομέα",
picked_up: "Παραλήφθηκε από κατάστημα",
delivery: "Σε διανομή",
completed: "Ολοκληρώθηκε",
cancelled: "Ακυρώθηκε",
};
const UI_TEXT = {
el: {
merchant: "Merchant",
driver: "Driver",
platformAdmin: "Platform Admin",
login: "Login",
activeStores: "ενεργά καταστήματα",
products: "προϊόντα",
stores: "Καταστήματα",
allHub: "Όλο το hub",
marketplaceBadge: "Παραγγελίες · Προσφορές · Τοπικά καταστήματα · Delivery",
heroTitle: "Παράγγειλε εύκολα από τοπικά καταστήματα ή βάλε το κατάστημά σου στο δίκτυο.",
productsCap: "Προϊόντα",
driverFee: "Driver fee",
joinPlatform: "Για επαγγελματίες",
haveStore: "Έχεις κατάστημα;",
merchantPitch: "Κάνε αίτηση συνεργασίας και διαχειρίσου προϊόντα, προσφορές και παραγγελίες από το δικό σου portal.",
storeApply: "Αίτηση συνεργασίας",
searchPlaceholder: "Αναζήτηση καταστήματος ή προϊόντος...",
tracking: "Tracking",
seeProgress: "Δες πρόοδο",
topOffers: "Οι 3 καλύτερες προσφορές",
noOffers: "Προσφορές σύντομα",
optionsAdd: "Επιλογές / Προσθήκη",
favorite: "Αγαπημένο",
favorited: "Στα αγαπημένα",
emptyFilter: "Δεν υπάρχουν προϊόντα για αυτό το φίλτρο.",
cart: "Καλάθι",
emptyCart: "Άδειο καλάθι",
emptyCartText: "Πρόσθεσε προϊόντα από ένα κατάστημα.",
itemsTotal: "Προϊόντα",
pickup: "Παραλαβή",
fromStore: "Από κατάστημα",
free: "Δωρεάν",
serviceFee: "Service fee",
loyaltyFeeDiscount: "Loyalty έκπτωση στα fees",
total: "Σύνολο",
continue: "Συνέχεια",
minOrder: "Ελάχιστη παραγγελία",
},
en: {
merchant: "Merchant",
driver: "Driver",
platformAdmin: "Platform Admin",
login: "Login",
activeStores: "active stores",
products: "products",
stores: "Stores",
allHub: "Full hub",
marketplaceBadge: "Orders · Offers · Local stores · Delivery",
heroTitle: "Order easily from local stores or bring your store into the network.",
productsCap: "Products",
driverFee: "Driver fee",
joinPlatform: "For businesses",
haveStore: "Own a store?",
merchantPitch: "Apply as a partner and manage products, offers and orders from your own portal.",
storeApply: "Partner application",
searchPlaceholder: "Search store or product...",
tracking: "Tracking",
seeProgress: "Track order",
topOffers: "Top 3 offers",
noOffers: "Offers coming soon",
optionsAdd: "Options / Add",
favorite: "Favorite",
favorited: "Favorited",
emptyFilter: "No products for this filter.",
cart: "Cart",
emptyCart: "Empty cart",
emptyCartText: "Add products from one store.",
itemsTotal: "Products",
pickup: "Pickup",
fromStore: "From store",
free: "Free",
serviceFee: "Service fee",
loyaltyFeeDiscount: "Loyalty discount on fees",
total: "Total",
continue: "Continue",
minOrder: "Minimum order",
}
};
const AUTO_TRANSLATIONS = {
"Marketplace παραγγελιών για τοπικά καταστήματα": "Ordering marketplace for local stores",
"Ένα hub για καφέ, snacks, προσφορές και delivery από πολλά καταστήματα.": "One hub for coffee, snacks, offers and delivery from multiple stores.",
"Προσφορές": "Offers",
"Καφέδες": "Coffees",
"Ροφήματα": "Drinks",
"Σφολιάτες": "Pastries",
"Σάντουιτς": "Sandwiches",
"Γλυκά": "Desserts",
"Όλα": "All",
"Κίσσαμος": "Kissamos",
"Κέντρο Κισσάμου": "Kissamos Center",
"Παραλιακή Κισσάμου": "Kissamos Seafront",
"Καφέδες, ροφήματα, σφολιάτες και combos.": "Coffee, drinks, pastries and combos.",
"Σάντουιτς, χυμοί, γλυκά και γρήγορο brunch.": "Sandwiches, juices, desserts and quick brunch.",
"Freddo Espresso": "Freddo Espresso",
"Freddo Cappuccino": "Freddo Cappuccino",
"Energy Combo": "Energy Combo",
"Club Sandwich": "Club Sandwich",
"Φυσικός Χυμός": "Fresh Juice",
"Brunch Deal": "Brunch Deal",
"Διπλός espresso με πάγο και έντονο σώμα.": "Double espresso over ice with a strong body.",
"Κρύος cappuccino με πλούσια κρέμα.": "Cold cappuccino with rich foam.",
"Καφές + σφολιάτα σε ειδική τιμή.": "Coffee + pastry at a special price.",
"Κοτόπουλο, μπέικον, τυρί, ντομάτα και πατάτες.": "Chicken, bacon, cheese, tomato and fries.",
"Φρεσκοστυμμένος χυμός πορτοκάλι.": "Freshly squeezed orange juice.",
"Club sandwich + φυσικός χυμός.": "Club sandwich + fresh juice.",
"Σκέτος": "No sugar",
"Μέτριος": "Medium sugar",
"Γλυκός": "Sweet",
"Χωρίς γάλα": "No milk",
"Λίγο γάλα": "A little milk",
"Με γάλα": "With milk",
"Κανονικό": "Regular",
"Χωρίς έξτρα": "No extras",
"Ζεστή σφολιάτα": "Warm pastry",
"Με πατάτες": "With fries",
"Χωρίς πατάτες": "No fries",
"Με πάγο": "With ice",
"Χωρίς πάγο": "No ice",
"Χωρίς ζάχαρη": "No sugar"
};
const EN_PHRASES = {
"Επικοινωνία": "Contact",
"Όροι χρήσης": "Terms of Use",
"Πολιτική απορρήτου": "Privacy Policy",
"Ακυρώσεις / Επιστροφές": "Cancellations / Refunds",
"Όροι καταστημάτων": "Store Terms",
"Κανόνες διανομέων": "Driver Rules",
"Στοιχεία πλατφόρμας": "Platform details",
"Τηλέφωνο": "Phone",
"Έδρα": "Registered area",
"Πληροφορίες": "Information",
"Πελάτης": "Customer",
"Κατάστημα": "Store",
"Καταστήματα": "Stores",
"Προϊόντα": "Products",
"Παραγγελίες": "Orders",
"Παραγγελία": "Order",
"Όλες οι παραγγελίες": "All orders",
"Παραγγελίες καταστήματος": "Store orders",
"Δεν υπάρχουν παραγγελίες": "No orders found",
"Δεν υπάρχουν αιτήσεις": "No applications found",
"Δεν υπάρχουν διανομείς": "No drivers found",
"Δεν υπάρχουν διαθέσιμες παραγγελίες": "No available orders",
"Δεν έχεις ενεργή διανομή": "You have no active delivery",
"Δεν έχεις ενεργή παραγγελία": "You have no active order",
"Δεν υπάρχουν προϊόντα για αυτό το φίλτρο.": "No products match this filter.",
"Άδειο καλάθι": "Empty cart",
"Πρόσθεσε προϊόντα από ένα κατάστημα.": "Add products from one store.",
"Σύνολο": "Total",
"Σχόλιο προϊόντος": "Product note",
"Σχόλια παραγγελίας": "Order notes",
"Ειδικές οδηγίες": "Special instructions",
"Προσθήκη": "Add",
"Αφαίρεση": "Remove",
"Αποθήκευση": "Save",
"Αποθήκευση προφίλ": "Save profile",
"Αποθήκευση store setup": "Save store setup",
"Αποθήκευση κατηγοριών": "Save categories",
"Δημιουργία λογαριασμού": "Create account",
"Είσοδος": "Login",
"Είσοδος πελάτη": "Customer login",
"Εγγραφή πελάτη": "Customer registration",
"Εγγραφή διανομέα": "Driver registration",
"Είσοδος διανομέα": "Driver login",
"Αποστολή αίτησης": "Submit application",
"Αίτηση συμμετοχής καταστήματος": "Store application",
"Νέα αίτηση καταστήματος": "New store application",
"Έχω ήδη έγκριση / Login": "Already approved / Login",
"Έχω λογαριασμό": "I already have an account",
"Νέα εγγραφή": "New registration",
"Ονοματεπώνυμο": "Full name",
"Ιδιοκτήτης": "Owner",
"Τηλέφωνο ιδιοκτήτη / login": "Owner phone / login",
"Κωδικός": "Password",
"Κωδικός merchant": "Merchant password",
"Αριθμός ταυτότητας": "ID number",
"Ταυτότητα / άδεια": "ID / license",
"ΑΦΜ": "Tax number",
"Όνομα καταστήματος": "Store name",
"Τηλέφωνο καταστήματος": "Store phone",
"Διεύθυνση καταστήματος": "Store address",
"Περιοχή": "Area",
"Τύπος καταστήματος": "Store type",
"IBAN καταστήματος": "Store IBAN",
"Σημειώσεις": "Notes",
"Διεύθυνση": "Address",
"Διεύθυνση παράδοσης": "Delivery address",
"Διεύθυνση προαιρετικά": "Optional address",
"Όροφος": "Floor",
"Όροφος / κουδούνι": "Floor / doorbell",
"Ώρα παράδοσης / παραλαβής": "Delivery / pickup time",
"Άμεσα ή 18:30": "ASAP or 18:30",
"Τρόπος εξυπηρέτησης": "Service type",
"Πληρωμή": "Payment",
"Μετρητά": "Cash",
"Μετρητά στην παράδοση": "Cash on delivery",
"Κάρτα στον διανομέα": "Card to driver",
"Κάρτα στο κατάστημα": "Card at store",
"Delivery στην πόρτα": "Delivery to door",
"Παραλαβή από κατάστημα": "Pickup from store",
"Παραλαβή": "Pickup",
"Από κατάστημα": "From store",
"Δωρεάν": "Free",
"Ολοκλήρωση παραγγελίας": "Checkout",
"Αποστολή παραγγελίας": "Place order",
"Ελάχιστη παραγγελία": "Minimum order",
"Διαθέσιμοι πόντοι": "Available points",
"πόντοι": "points",
"πόντος": "point",
"έκπτωση μόνο στα fees": "discount only on fees",
"Loyalty επιβράβευση": "Loyalty rewards",
"Με αυτή την παραγγελία κερδίζεις περίπου": "With this order you earn about",
"πόντους από την αξία προϊόντων": "points from product value",
"Η εξαργύρωση αφαιρείται μόνο από service/delivery fees.": "Redemption is applied only to service/delivery fees.",
"Πόντοι για εξαργύρωση": "Points to redeem",
"Χρειάζονται τουλάχιστον": "At least",
"Η έκπτωση εφαρμόζεται μόνο μέχρι το ύψος των platform fees, όχι στα προϊόντα.": "The discount applies only up to platform fees, not products.",
"Γεια σου": "Hello",
"πελάτη": "customer",
"Προφίλ, ιστορικό, loyalty πόντοι, ενεργές παραγγελίες και αγαπημένα προϊόντα.": "Profile, history, loyalty points, active orders and favorite products.",
"Σύνοψη": "Overview",
"Προφίλ": "Profile",
"Αγαπημένα": "Favorites",
"Ενεργές": "Active",
"Loyalty πόντοι": "Loyalty points",
"Σύνολο αγορών": "Total spent",
"Γρήγορη σύνοψη": "Quick overview",
"Loyalty διαθέσιμοι πόντοι": "Available loyalty points",
"Καταστήματα που έχεις χρησιμοποιήσει": "Stores used",
"Ολοκληρωμένες παραγγελίες": "Completed orders",
"Ενεργές παραγγελίες": "Active orders",
"Ιστορικό παραγγελιών": "Order history",
"Κίνηση loyalty": "Loyalty activity",
"Συνολικά κερδισμένοι πόντοι": "Total points earned",
"Συνολικά εξαργυρωμένοι πόντοι": "Total points redeemed",
"Συνολική έκπτωση από loyalty στα fees": "Total loyalty discount on fees",
"Ελάχιστοι πόντοι εξαργύρωσης": "Minimum redeem points",
"Πού εφαρμόζεται": "Applies to",
"Μόνο σε service fee + delivery fee": "Only to service fee + delivery fee",
"Προφίλ πελάτη": "Customer profile",
"Αγαπημένα προϊόντα": "Favorite products",
"Δεν έχεις αγαπημένα ακόμα": "You have no favorites yet",
"Επανάληψη": "Reorder",
"Αξιολόγηση διανομέα": "Driver rating",
"Έδωσες": "You rated",
"Αν είναι πάνω από το όριο επιβράβευσης, ο διανομέας παίρνει bonus.": "If it meets the reward threshold, the driver receives a bonus.",
"αναμονή": "pending",
"Νέα παραγγελία": "New order",
"Αποδοχή από κατάστημα": "Accepted by store",
"Σε ετοιμασία": "Preparing",
"Ανατέθηκε σε διανομέα": "Assigned to driver",
"Παραλήφθηκε από κατάστημα": "Picked up from store",
"Σε διανομή": "Out for delivery",
"Ολοκληρώθηκε": "Completed",
"Ακυρώθηκε": "Cancelled",
"Νέα": "New",
"Αποδοχή": "Accepted",
"Ετοιμασία": "Preparing",
"Ανάθεση": "Assigned",
"Διανομή": "Delivery",
"Η παραγγελία καταχωρήθηκε": "The order was placed",
"Το κατάστημα την αποδέχτηκε": "The store accepted it",
"Το κατάστημα ετοιμάζει την παραγγελία": "The store is preparing the order",
"Ο διανομέας παρέλαβε από το κατάστημα": "The driver picked it up from the store",
"Ο διανομέας είναι καθ’ οδόν": "The driver is on the way",
"Παραδόθηκε στον πελάτη": "Delivered to the customer",
"Στοιχεία παραγγελίας": "Order details",
"Οδηγίες": "Instructions",
"Προορισμός": "Destination",
"Προγραμματισμός": "Scheduled time",
"Επικοινωνία με τηλέφωνο": "Phone contact",
"Επικοινωνία με μήνυμα": "Message contact",
"Μετρητά: εισπράττεις": "Cash: collect",
"από τον πελάτη": "from the customer",
"Ρέστα από": "Change from",
"Έλεγξε αν χρειάζονται ρέστα.": "Check if change is needed.",
"Ακολούθησε τη διαδικασία POS/καταστήματος.": "Follow the POS/store procedure.",
"Αποδοχή διανομής": "Accept delivery",
"Παρέλαβα από κατάστημα": "Picked up from store",
"Ξεκίνησα προς πελάτη": "Started toward customer",
"Ολοκλήρωση παράδοσης": "Complete delivery",
"Όχημα": "Vehicle",
"Μηχανάκι": "Motorbike",
"Αυτοκίνητο": "Car",
"Ποδήλατο": "Bicycle",
"Πινακίδα": "Plate number",
"Περιμένεις έγκριση Platform Admin": "Waiting for Platform Admin approval",
"Είσαι offline": "You are offline",
"Γίνε online για να βλέπεις διαθέσιμες παραγγελίες από όλα τα καταστήματα.": "Go online to see available orders from all stores.",
"Τρέχουσα διανομή": "Current delivery",
"Διαθέσιμες παραγγελίες όλων των καταστημάτων": "Available orders from all stores",
"Ο οδηγός παίρνει": "The driver receives",
"από κάθε delivery fee": "from each delivery fee",
"ανά ολοκληρωμένη αξιολογημένη διανομή": "per completed rated delivery",
"Κεντρική διαχείριση διανομέων": "Central driver management",
"Δεν υπάρχουν requests.": "No requests found.",
"Νέο προϊόν": "New product",
"Επεξεργασία προϊόντος": "Edit product",
"Ο Merchant ελέγχει προϊόντα, κατηγορίες, τιμές και προσφορές.": "The merchant manages products, categories, prices and offers.",
"Όνομα προϊόντος": "Product name",
"Φωτογραφία προϊόντος": "Product photo",
"Κατηγορία": "Category",
"Νέα κατηγορία": "New category",
"Τιμή": "Price",
"Παλιά τιμή": "Old price",
"Χρόνος": "Time",
"Περιγραφή": "Description",
"Γλυκύτητα": "Sweetness",
"Επιλογές": "Options",
"Επιλογή": "Option",
"Ενεργό": "Active",
"Προσφορά": "Offer",
"Προϊόντα καταστήματος": "Store products",
"Κεντρικός έλεγχος πλατφόρμας.": "Central platform control.",
"Κεντρικός έλεγχος για χρήστες, καταστήματα, delivery, fees, branding, νομικές σελίδες και αποκλεισμούς.": "Central control for users, stores, delivery, fees, branding, legal pages and bans.",
"Χρήστες": "Users",
"Αιτήσεις": "Applications",
"Σελίδες": "Pages",
"Οικονομικά πλατφόρμας": "Platform financials",
"Έλεγχος δεδομένων": "Data control",
"Ενεργοί χρήστες": "Active users",
"Banned/suspended χρήστες": "Banned/suspended users",
"Ακυρωμένες παραγγελίες": "Cancelled orders",
"Καταστήματα πλατφόρμας": "Platform stores",
"Κεντρικά fees πλατφόρμας": "Central platform fees",
"Branding & βασικές πληροφορίες πλατφόρμας": "Branding & basic platform information",
"Footer / Νομικές σελίδες": "Footer / Legal pages",
"Χρήστες / πελάτες πλατφόρμας": "Platform users / customers",
"Δεν υπάρχουν εγγεγραμμένοι χρήστες": "No registered users",
"Εγκεκριμένο": "Approved",
"Σε αναστολή": "Suspended",
"Μόνιμο ban": "Permanent ban",
"Απορρίφθηκε": "Rejected",
"Σε αναμονή": "Pending",
"Εγκεκριμένος": "Approved",
"Σε αναμονή έγκρισης": "Pending approval",
"Ενεργός": "Active",
"Αποκλεισμός από Merchant": "Blocked by Merchant",
"Αποκλεισμός από κατάστημα": "Blocked by store",
"Πελάτες καταστήματος & αποκλεισμοί": "Store customers & bans",
"Δεν υπάρχουν πελάτες ακόμα": "No customers yet",
"χωρίς email": "no email",
"Banned από αυτό το κατάστημα": "Banned from this store",
"Unban από κατάστημα": "Unban from store",
"Ban από κατάστημα": "Ban from store",
"Ενεργοί αποκλεισμοί": "Active bans",
"Store οικονομικά": "Store financials",
"Τζίρος προϊόντων καταστήματος": "Store product revenue",
"Μέσο order προϊόντων": "Average product order",
"Οι χρεώσεις service/delivery fees της πλατφόρμας εμφανίζονται στον πελάτη και μπορούν να αλλάξουν από την πλατφόρμα οποιαδήποτε στιγμή. Το κατάστημα βλέπει εδώ μόνο τα δικά του έσοδα προϊόντων.": "Platform service/delivery fees are shown to the customer and may change by the platform at any time. The store sees only its own product revenue here.",
"Το Merchant Admin είναι ξεχωριστό από το Platform Admin. Ο καταστηματάρχης διαχειρίζεται προϊόντα, κατηγορίες και orders μόνο του δικού του καταστήματος.": "Merchant Admin is separate from Platform Admin. The merchant manages products, categories and orders only for their own store.",
"Με την αίτηση αποδέχεσαι ότι η πλατφόρμα μπορεί να εφαρμόζει service/delivery fees προς τον πελάτη και να τα αλλάζει οποιαδήποτε στιγμή. Το κατάστημα βλέπει τα δικά του έσοδα προϊόντων, ενώ η πλατφόρμα διατηρεί τον κεντρικό έλεγχο κανόνων, fees και πρόσβασης.": "By applying, you accept that the platform may apply service/delivery fees to the customer and change them at any time. The store sees its own product revenue, while the platform keeps central control of rules, fees and access.",
"Οι διανομείς βλέπουν orders από όλα τα εγκεκριμένα καταστήματα και πρέπει να ακολουθούν κανόνες προσωπικών δεδομένων, παραλαβής, παράδοσης και διαχείρισης μετρητών.": "Drivers see orders from all approved stores and must follow personal-data, pickup, delivery and cash-handling rules.",
"Με την αίτηση αποδέχεσαι ότι τα στοιχεία πελατών χρησιμοποιούνται μόνο για την αντίστοιχη παράδοση, ότι η ολοκλήρωση πατιέται μόνο μετά την πραγματική παράδοση και ότι χαμηλές αξιολογήσεις ή παράπονα μπορούν να οδηγήσουν σε αναστολή.": "By applying, you accept that customer details are used only for the relevant delivery, completion is pressed only after real delivery, and low ratings or complaints may lead to suspension.",
"Όροι χρήσης πλατφόρμας": "Platform Terms of Use",
"Επικοινωνία πλατφόρμας": "Platform contact",
"Όροι συνεργαζόμενων καταστημάτων": "Partner Store Terms",
"Κανόνες διανομέων": "Driver rules",
"Λειτουργία μετρητών": "Cash handling",
"Ροή παραλαβής και παράδοσης": "Pickup and delivery flow",
"Ακυρώσεις, παράπονα και επιστροφές": "Cancellations, complaints and refunds",
"Δεδομένα που συλλέγονται": "Data collected",
"Σκοπός επεξεργασίας": "Purpose of processing",
"Κοινοποίηση δεδομένων": "Data sharing",
"Δικαιώματα χρήστη": "User rights",
"Ασφάλεια": "Security",
"Χρόνος τήρησης": "Retention period",
"Ρόλος πλατφόρμας": "Platform role",
"Χρεώσεις πλατφόρμας": "Platform fees",
"Διανομείς": "Drivers",
"Αποκλεισμοί και διαγραφή": "Bans and deletion",
"Αξιολογήσεις": "Ratings",
"Αλλαγές όρων": "Changes to terms"
};
function translateTextToEnglish(text) {
const original = String(text ?? "");
if (!original.trim()) return original;
const leadingLength = original.length - original.trimStart().length;
const trailingLength = original.length - original.trimEnd().length;
const leading = original.slice(0, leadingLength);
const trailing = trailingLength ? original.slice(original.length - trailingLength) : "";
let body = original.trim();
if (AUTO_TRANSLATIONS[body]) return `${leading}${AUTO_TRANSLATIONS[body]}${trailing}`;
if (EN_PHRASES[body]) return `${leading}${EN_PHRASES[body]}${trailing}`;
const sorted = Object.entries({ ...AUTO_TRANSLATIONS, ...EN_PHRASES }).sort((a, b) => b[0].length - a[0].length);
sorted.forEach(([el, en]) => {
if (body.includes(el)) body = body.split(el).join(en);
});
return `${leading}${body}${trailing}`;
}
function t(lang, key) {
return UI_TEXT[lang]?.[key] || UI_TEXT.el[key] || key;
}
function tx(value, lang = "el") {
if (lang !== "en") return value;
if (value && typeof value === "object" && !Array.isArray(value)) return value.en || translateTextToEnglish(value.el || "");
return translateTextToEnglish(value);
}
function translateDomTree(root) {
if (typeof window === "undefined" || !root) return;
const blocked = new Set(["SCRIPT", "STYLE", "TEXTAREA"]);
const filter = window.NodeFilter;
if (!filter) return;
const walker = document.createTreeWalker(root, filter.SHOW_TEXT, {
acceptNode(node) {
const parent = node.parentElement;
if (!parent || blocked.has(parent.tagName) || parent.closest("textarea")) return filter.FILTER_REJECT;
if (!node.nodeValue || !node.nodeValue.trim()) return filter.FILTER_REJECT;
return filter.FILTER_ACCEPT;
}
});
const nodes = [];
while (walker.nextNode()) nodes.push(walker.currentNode);
nodes.forEach((node) => {
const translated = translateTextToEnglish(node.nodeValue);
if (translated !== node.nodeValue) node.nodeValue = translated;
});
root.querySelectorAll?.("[placeholder], [title], [aria-label]").forEach((el) => {
["placeholder", "title", "aria-label"].forEach((attr) => {
const value = el.getAttribute(attr);
if (value) el.setAttribute(attr, translateTextToEnglish(value));
});
});
}
const formatEuro = (value, lang = "el") => new Intl.NumberFormat(lang === "en" ? "en-US" : "el-GR", { style: "currency", currency: "EUR" }).format(Number(value || 0));
const safeId = (prefix = "id") => `${prefix}-${Math.floor(100000 + Math.random() * 900000)}`;
const roundMoney = (value) => Math.round(Number(value || 0) * 100) / 100;
function readStorage(key, fallback) {
if (typeof window === "undefined") return fallback;
try {
const serverState = window.__RR_SERVER_STATE__ || {};
if (typeof RR_SYNC_KEYS !== "undefined" && RR_SYNC_KEYS.includes(key) && Object.prototype.hasOwnProperty.call(serverState, key)) {
try { localStorage.setItem(key, JSON.stringify(serverState[key])); } catch {}
return serverState[key] ?? fallback;
}
const parsed = JSON.parse(localStorage.getItem(key) || "null");
return parsed ?? fallback;
} catch {
return fallback;
}
}
function isInlineImageData(value) {
return typeof value === "string" && value.startsWith("data:image/");
}
function storageSafeImage(value) {
return isInlineImageData(value) ? "" : (value || "");
}
function compactOrderItemForStorage(item) {
return { ...item, image: storageSafeImage(item.image) };
}
function compactOrderForStorage(order) {
return {
...order,
storeSnapshot: order.storeSnapshot ? { ...order.storeSnapshot, logo: storageSafeImage(order.storeSnapshot.logo) } : order.storeSnapshot,
items: Array.isArray(order.items) ? order.items.map(compactOrderItemForStorage) : [],
statusHistory: Array.isArray(order.statusHistory) ? order.statusHistory.slice(-20) : [],
driverEvents: Array.isArray(order.driverEvents) ? order.driverEvents.slice(-20) : [],
};
}
function compactStorageValue(key, value) {
if (key === "rr_orders_v1") return Array.isArray(value) ? value.slice(0, 150).map(compactOrderForStorage) : [];
return value;
}
function saveStorage(key, value) {
if (typeof window === "undefined") return;
const compactValue = compactStorageValue(key, value);
try {
localStorage.setItem(key, JSON.stringify(compactValue));
} catch (error) {
console.warn(`Storage save skipped for ${key}`, error);
try {
localStorage.removeItem(key);
const emergencyValue = key === "rr_orders_v1" && Array.isArray(value) ? value.slice(0, 50).map(compactOrderForStorage) : compactValue;
localStorage.setItem(key, JSON.stringify(emergencyValue));
} catch (secondError) {
console.warn(`Storage emergency save failed for ${key}`, secondError);
}
}
queueServerStateSave(key, compactValue);
}
const RR_SYNC_KEYS = [
"rr_platform_v1",
"rr_stores_v1",
"rr_store_apps_v1",
"rr_users_v1",
"rr_drivers_v1",
"rr_driver_withdrawals_v1",
"rr_orders_v1",
];
function rrApiHeaders() {
return {
"Content-Type": "application/json",
"X-RR-Sync-Token": String(window.__RR_SYNC_TOKEN__ || ""),
};
}
function queueServerStateSave(key, value) {
if (typeof window === "undefined" || !window.__RR_API_ENABLED__) return;
if (!RR_SYNC_KEYS.includes(key)) return;
window.__RR_SAVE_TIMERS__ = window.__RR_SAVE_TIMERS__ || {};
if (window.__RR_SAVE_TIMERS__[key]) window.clearTimeout(window.__RR_SAVE_TIMERS__[key]);
window.__RR_SAVE_TIMERS__[key] = window.setTimeout(() => {
fetch("./api/state.php", {
method: "POST",
credentials: "same-origin",
headers: rrApiHeaders(),
body: JSON.stringify({ key, value }),
}).catch((error) => console.warn("Road Runner MySQL sync failed", key, error));
}, 350);
}
function sameJson(a, b) {
try { return JSON.stringify(a) === JSON.stringify(b); } catch { return false; }
}
function splitList(value) {
if (Array.isArray(value)) return value.filter(Boolean);
return String(value || "").split(",").map((item) => item.trim()).filter(Boolean);
}
function paymentLabel(value) {
if (value === "card_on_delivery") return "Κάρτα στον διανομέα";
if (value === "store_card") return "Κάρτα στο κατάστημα";
return "Μετρητά στην παράδοση";
}
function serviceLabel(value) {
return value === "pickup" ? "Παραλαβή από κατάστημα" : "Delivery";
}
function vehicleLabel(value) {
if (value === "car") return "Αυτοκίνητο";
if (value === "bicycle") return "Ποδήλατο";
if (value === "scooter") return "Scooter";
return "Μηχανάκι";
}
function normalizeLocation(location) {
if (!location) return null;
const lat = Number(location.lat ?? location.latitude);
const lng = Number(location.lng ?? location.longitude);
if (!Number.isFinite(lat) || !Number.isFinite(lng)) return null;
return {
lat: Math.round(lat * 1000000) / 1000000,
lng: Math.round(lng * 1000000) / 1000000,
accuracy: location.accuracy == null ? null : Math.round(Number(location.accuracy)),
heading: location.heading == null ? null : Math.round(Number(location.heading)),
speed: location.speed == null ? null : Math.round(Number(location.speed) * 10) / 10,
at: location.at || new Date().toISOString(),
};
}
function locationAgeText(location) {
if (!location?.at) return "χωρίς ενημέρωση";
const seconds = Math.max(0, Math.round((Date.now() - new Date(location.at).getTime()) / 1000));
if (seconds < 60) return `${seconds}s πριν`;
const minutes = Math.round(seconds / 60);
if (minutes < 60) return `${minutes} λεπτά πριν`;
return `${Math.round(minutes / 60)} ώρες πριν`;
}
function mapsUrl(location) {
const loc = normalizeLocation(location);
return loc ? `https://www.google.com/maps?q=${loc.lat},${loc.lng}` : "#";
}
function storeStatusLabel(status) {
if (status === "approved") return "Εγκεκριμένο";
if (status === "suspended") return "Σε αναστολή";
if (status === "banned") return "Μόνιμο ban";
if (status === "rejected") return "Απορρίφθηκε";
return "Σε αναμονή";
}
function driverStatusLabel(status) {
if (status === "approved") return "Εγκεκριμένος";
if (status === "suspended") return "Σε αναστολή";
if (status === "rejected") return "Απορρίφθηκε";
return "Σε αναμονή έγκρισης";
}
function userStatusLabel(status) {
if (status === "banned") return "Μόνιμο ban";
if (status === "suspended") return "Σε αναστολή";
return "Ενεργός";
}
function isUserGloballyBanned(user) {
return user?.status === "banned" || user?.status === "suspended";
}
function isCustomerBannedFromStore(user, store) {
if (!user || !store) return false;
return (store.customerBans || []).some((ban) => (ban.userId && ban.userId === user.id) || (ban.phone && ban.phone === user.phone));
}
function calculateExtraPriceFromChoices(choices) {
const text = [choices?.sweetness, choices?.milk, ...(choices?.extras || [])].join(" ");
const extraPricePattern = /[+]([0-9]+(?:[.][0-9]+)?)€/g;
const matches = Array.from(text.matchAll(extraPricePattern));
return roundMoney(matches.reduce((sum, match) => sum + Number(match[1] || 0), 0));
}
function readImageFile(file, onLoad) {
if (!file) return;
if (!file.type?.startsWith("image/")) return;
const reader = new FileReader();
reader.onload = () => {
const raw = String(reader.result || "");
const img = new Image();
img.onload = () => {
try {
const maxSide = 720;
const scale = Math.min(1, maxSide / Math.max(img.width || 1, img.height || 1));
const canvas = document.createElement("canvas");
canvas.width = Math.max(1, Math.round((img.width || 1) * scale));
canvas.height = Math.max(1, Math.round((img.height || 1) * scale));
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
const optimized = canvas.toDataURL("image/webp", 0.72);
onLoad(optimized.length < raw.length ? optimized : raw);
} catch {
onLoad(raw);
}
};
img.onerror = () => onLoad(raw);
img.src = raw;
};
reader.readAsDataURL(file);
}
function ImageUpload({ label, value, onChange, fallback = "🏪", hint = "PNG / JPG / WebP" }) {
return
Το loyalty πλέον δουλεύει σαν gamified wallet: tier progress, streak bonus, earn boost και καθαρή εξαργύρωση στα platform fees χωρίς να επηρεάζει τον τζίρο του καταστήματος.
Το live tracking λειτουργεί μέσω browser GPS. Χρειάζεται HTTPS, ανοιχτό browser, άδεια τοποθεσίας και ενεργό Online + GPS από τον διανομέα. Η θέση εμφανίζεται σε πελάτη, κατάστημα και Platform Admin όσο υπάρχει ενεργή διανομή.
{driver.trackingError &&
GPS error: {driver.trackingError}
}}{approved &&
Ο οδηγός παίρνει {platform.driverCommissionPercent}% από κάθε delivery fee. Αν delivery fee = 1€, wallet = {formatEuro(Number(platform.driverCommissionPercent || 40) / 100)}. Με rating τουλάχιστον {platform.driverRewardMinRating}/5 μπορεί να παίρνει bonus {formatEuro(platform.driverRewardBonusPerOrder)} ανά ολοκληρωμένη αξιολογημένη διανομή.
{cashPayment ? <>💶 Μετρητά: εισπράττεις {formatEuro(order.totals.total)} από τον πελάτη. {order.customer.changeFor ? `Ρέστα από ${order.customer.changeFor}.` : "Έλεγξε αν χρειάζονται ρέστα."}> : <>💳 Πληρωμή: {paymentLabel(order.paymentMethod)}. Ακολούθησε τη διαδικασία POS/καταστήματος.>}
Ο Merchant ελέγχει προϊόντα, orders και μπορεί να αποκλείει πελάτες μόνο από το δικό του κατάστημα.
{tabs.map(([key, label]) => (
))}
{tab === "overview" && (
Οι χρεώσεις service/delivery fees της πλατφόρμας εμφανίζονται στον πελάτη και μπορούν να αλλάξουν από την πλατφόρμα οποιαδήποτε στιγμή. Το κατάστημα βλέπει εδώ μόνο τα δικά του έσοδα προϊόντων.
)}
{tab === "orders" &&
🚨 Δυνατή ηχητική ειδοποίηση νέας παραγγελίας
Παίζει έντονο alarm για 5 δευτερόλεπτα σε κάθε νέα παραγγελία όταν το Order tab είναι ανοιχτό.