import React, { useState, useMemo, useEffect, useRef } from 'react'; import { Package, Truck, ShoppingCart, LayoutDashboard, Plus, Search, FileText, CheckCircle, Clock, Printer, Box, ArrowRightLeft, CreditCard, AlertCircle, UploadCloud, ChevronRight, MoreHorizontal, Bell, Filter, Download, Trash2, RefreshCcw, Globe, X, User as UserIcon, Scale, Ruler, ShieldAlert, ChevronLeft, FileSpreadsheet, Users, Edit, Save, TrendingUp, PieChart, BarChart3, Activity, Lock, Unlock, UserPlus, UserMinus, Menu, LogOut, Building2, Mail, Phone, MapPin, Globe2, FileBadge, KeyRound, Settings, Shield, StickyNote, Map, QrCode, Camera, PackageCheck, SearchX, Wallet, Receipt, FileCheck, Landmark, ChevronDown } from 'lucide-react'; // --- Custom CSS --- const CustomStyles = () => ( ); // --- Translations --- const TRANSLATIONS: Record = { fr: { app_name: 'NEOVORA WMS', dashboard: 'Tableau de bord', orders: 'Commandes', inventory: 'Inventaire', inbound: 'Arrivages', finance: 'Finance', reports: 'Rapports', settings: 'Paramètres', welcome: 'Bienvenue', login_title: 'Connexion NEOVORA', login_subtitle: 'Solution logistique d\'entreprise', username: 'Identifiant', password: 'Mot de passe', login_btn: 'Connexion sécurisée', login_error: 'Identifiants invalides', logout: 'Déconnexion', pending_orders: 'En attente', ready_to_ship: 'Prêt à expédier', low_stock: 'Stock faible', monthly_revenue: 'Revenus (Mois)', recent_activity: 'Activité récente', quick_actions: 'Actions rapides', bulk_upload: 'Import en masse', create_inbound: 'Créer arrivage', export_reports: 'Exporter', search_placeholder: 'Rechercher commande, SKU...', search_tracking: 'Scanner/Saisir suivi...', search_clients: 'Rechercher client...', status: 'Statut', actions: 'Actions', balance: 'Solde', new_shipment: 'Expédier', needs_action: 'Action requise', awaiting_pickup: 'En attente', available: 'Disponible', allocated: 'Alloué', location: 'Emplacement', all: 'Tous', out_of_stock: 'Rupture', print: 'Imprimer', ship: 'Expédier', selected: 'Sélectionné', client_list: 'Clients', back_to_clients: 'Retour', dimensions: 'Dim. (cm)', weight: 'Poids (kg)', fragile: 'Fragile', est_shipping: 'Frais est.', add_product: 'Ajouter produit', import_excel: 'Importer', upload_success: 'Importé avec succès', downloading: 'Génération du rapport...', client_balances: 'Soldes clients', analytics_dashboard: 'Analytique', total_orders: 'Total commandes', success_rate: 'Taux de succès', avg_ship_time: 'Délai moyen', pro_insight: 'Voir les rapports pour plus de détails.', edit: 'Éditer', delete: 'Supprimer', save: 'Enregistrer', cancel: 'Annuler', create: 'Créer', edit_product: 'Modifier produit', create_product: 'Nouveau produit', edit_order: 'Modifier commande', create_order: 'Saisir commande', edit_client: 'Modifier client', create_client: 'Nouveau client', stock_qty: 'Quantité', location_code: 'Code empl.', service_fee: 'Frais service (€)', shipping_fee: 'Frais port (€)', client_name: 'Nom client', account_status: 'Statut', please_select_orders: 'Veuillez sélectionner des commandes', revenue_trend: 'Tendances revenus', order_distribution: 'Distribution', top_products: 'Top 3 Produits', active: 'Actif', inactive: 'Inactif', total_fees: 'Frais totaux', admin_role: 'Administrateur', partner_role: 'Partenaire', client_role: 'Client', month_1: 'Jan', month_2: 'Fév', month_3: 'Mar', month_4: 'Avr', month_5: 'Mai', month_6: 'Juin', processing: 'Traitement', packed: 'Emballé', shipped: 'Expédié', cancelled: 'Annulé', cancel_requested: 'Demande annul.', modify_requested: 'Demande modif.', delete_requested: 'Demande suppr.', pending: 'En attente', product_updated: 'Produit mis à jour', order_updated: 'Commande mise à jour', client_updated: 'Client mis à jour', client_added: 'Client ajouté', client_deleted: 'Client supprimé', partner_added: 'Partenaire ajouté', partner_updated: 'Partenaire mis à jour', partner_deleted: 'Partenaire supprimé', order_deleted: 'Commande supprimée', view_history: 'Voir historique', history_unavailable: 'Historique indisponible en démo', advanced_filters: 'Filtres', parsing_file: 'Analyse...', import_now: 'Importer', no_inventory: 'Aucun stock', unassigned: 'Non assigné', standard: 'Standard', general: 'Général', request_delete: 'Demander suppression', request_modify: 'Demander modification', request_sent: 'Demande envoyée', approve: 'Approuver', reject: 'Rejeter', switch_role: 'Changer rôle', product_name: 'Nom produit', sku: 'SKU', manual_add: 'Ajout manuel', platform_order_id: 'Réf. Plateforme', quantity: 'Quantité', currency: 'Devise', add_client: 'Ajouter client', confirm_delete_client: 'Confirmer la suppression ?', confirm_delete_order: 'Supprimer cette commande ?', menu: 'Menu', company_name: 'Société', contact_person: 'Contact', email: 'Email', phone: 'Téléphone', country: 'Pays', address: 'Adresse', vat_number: 'N° TVA/EORI', client_credentials: 'Accès', set_username: 'Identifiant', set_password: 'Mot de passe', client_management: 'Gestion Clients', admin_management: 'Administration', my_account: 'Mon Compte', partner_management: 'Partenaires', create_partner: 'Ajouter partenaire', edit_partner: 'Modifier partenaire', partner_list: 'Liste partenaires', current_password: 'Mot de passe actuel', new_password: 'Nouveau mot de passe', password_changed: 'Mot de passe changé', permission_denied: 'Permission refusée', super_admin_only: 'Super Admin uniquement', client_login_info: 'Infos connexion', admin_name: 'Nom', note: 'Note', edit_note: 'Modifier note', only_note_editable: 'Seule la note est modifiable', price: 'Prix (€)', order_note: 'Note commande', confirm_title: 'Confirmation', confirm: 'Confirmer', bulk_ship_confirm: 'Confirmer l\'expédition groupée ? Les frais seront déduits.', confirm_delete_partner: 'Supprimer ce partenaire ?', confirm_request_modify: 'Envoyer demande de modification ?', confirm_request_delete: 'Envoyer demande de suppression ?', confirm_request_product_modify: 'Envoyer demande modif. produit ?', confirm_request_product_delete: 'Envoyer demande suppr. produit ?', view_warehouse_address: 'Adresse Entrepôt', warehouse_address_title: 'Adresse de Livraison', warehouse_address_tip: 'Veuillez impérativement ajouter votre ID client après le nom du destinataire.', tracking_number: 'N° Suivi', expected_qty: 'Attendu', actual_qty: 'Reçu', photos: 'Photos', confirm_arrival: 'Confirmer réception', stock_in: 'Mettre en stock', process_inbound: 'Traiter', upload_photos: 'Télécharger', customs: 'Douane', arrived: 'Arrivé', stocked: 'Stocké', inbound_success: 'Entrée en stock terminée', arrival_success: 'Réception confirmée', top_up: 'Recharger', top_up_amount: 'Montant (€)', top_up_success: 'Rechargement réussi', download_invoice: 'Facture PDF', invoice: 'FACTURE', invoice_preview: 'Aperçu Facture', deducted_from_balance: 'Déduit du solde', transaction_date: 'Date', transaction_client: 'Client', transaction_desc: 'Description', transaction_ref: 'Réf.', transaction_amount: 'Montant', transaction_invoice: 'Preuve', wire_transfer: 'Virement bancaire', fee_deduction: 'Frais de service', bill_to: 'Facturer à:', bill_from: 'De la part de:', invoice_no: 'Facture N°:', invoice_date: 'Date:', total_amount: 'Total:', item_desc: 'Description', item_qty: 'Qté', item_price: 'P.U.', item_total: 'Total', subtotal: 'Sous-total', tax: 'TVA', total: 'Total', bank_info: 'Coordonnées Bancaires', bank_name: 'Banque', account_holder: 'Titulaire', iban: 'IBAN', swift: 'BIC/SWIFT', invoice_note: 'Notes' }, en: { app_name: 'NEOVORA WMS', dashboard: 'Dashboard', orders: 'Orders', inventory: 'Inventory', inbound: 'Inbound', finance: 'Finance', reports: 'Reports', settings: 'Settings', welcome: 'Welcome Back', login_title: 'NEOVORA WMS Login', login_subtitle: 'Enterprise Logistics Solution', username: 'Username', password: 'Password', login_btn: 'Secure Login', login_error: 'Invalid credentials', logout: 'Logout', pending_orders: 'Pending', ready_to_ship: 'Ready to Ship', low_stock: 'Low Stock', monthly_revenue: 'Revenue (Mo)', recent_activity: 'Recent Activity', quick_actions: 'Quick Actions', bulk_upload: 'Bulk Upload', create_inbound: 'Create Inbound', export_reports: 'Export Data', search_placeholder: 'Search Order, SKU...', search_tracking: 'Scan/Enter Tracking...', search_clients: 'Search Clients...', status: 'Status', actions: 'Actions', balance: 'Balance', new_shipment: 'Ship', needs_action: 'Action Needed', awaiting_pickup: 'Awaiting Pickup', available: 'Available', allocated: 'Allocated', location: 'Location', all: 'All', out_of_stock: 'Out of Stock', print: 'Print Label', ship: 'Ship', selected: 'Selected', client_list: 'Clients', back_to_clients: 'Back', dimensions: 'Dims (cm)', weight: 'Weight (kg)', fragile: 'Fragile', est_shipping: 'Est. Shipping', add_product: 'Add Product', import_excel: 'Import', upload_success: 'Upload Success', downloading: 'Generating Report...', client_balances: 'Client Balances', analytics_dashboard: 'Analytics', total_orders: 'Total Orders', success_rate: 'Success Rate', avg_ship_time: 'Avg Ship Time', pro_insight: 'Check reports for details.', edit: 'Edit', delete: 'Delete', save: 'Save', cancel: 'Cancel', create: 'Create', edit_product: 'Edit Product', create_product: 'New Product', edit_order: 'Edit Order', create_order: 'Create Order', edit_client: 'Edit Client', create_client: 'New Client', stock_qty: 'Quantity', location_code: 'Location Code', service_fee: 'Service Fee (€)', shipping_fee: 'Shipping Fee (€)', client_name: 'Client Name', account_status: 'Status', please_select_orders: 'Please select orders', revenue_trend: 'Revenue Trend', order_distribution: 'Distribution', top_products: 'Top 3 Products', active: 'Active', inactive: 'Inactive', total_fees: 'Total Fees', admin_role: 'Admin', partner_role: 'Partner', client_role: 'Client', month_1: 'Jan', month_2: 'Feb', month_3: 'Mar', month_4: 'Apr', month_5: 'May', month_6: 'Jun', processing: 'Processing', packed: 'Packed', shipped: 'Shipped', cancelled: 'Cancelled', cancel_requested: 'Cancel Req.', modify_requested: 'Modify Req.', delete_requested: 'Delete Req.', pending: 'Pending', product_updated: 'Product Updated', order_updated: 'Order Updated', client_updated: 'Client Updated', client_added: 'Client Added', client_deleted: 'Client Deleted', partner_added: 'Partner Added', partner_updated: 'Partner Updated', partner_deleted: 'Partner Deleted', order_deleted: 'Order Deleted', view_history: 'View History', history_unavailable: 'History unavailable in demo', advanced_filters: 'Filters', parsing_file: 'Parsing...', import_now: 'Import', no_inventory: 'No Inventory', unassigned: 'Unassigned', standard: 'Standard', general: 'General', request_delete: 'Request Delete', request_modify: 'Request Modify', request_sent: 'Request Sent', approve: 'Approve', reject: 'Reject', switch_role: 'Switch Role', product_name: 'Product Name', sku: 'SKU', manual_add: 'Manual Add', platform_order_id: 'Platform ID', quantity: 'Qty', currency: 'Currency', add_client: 'Add Client', confirm_delete_client: 'Confirm delete?', confirm_delete_order: 'Delete this order?', menu: 'Menu', company_name: 'Company', contact_person: 'Contact', email: 'Email', phone: 'Phone', country: 'Country', address: 'Address', vat_number: 'VAT/EORI', client_credentials: 'Credentials', set_username: 'Username', set_password: 'Password', client_management: 'Client Mgmt', admin_management: 'Administration', my_account: 'My Account', partner_management: 'Partners', create_partner: 'Add Partner', edit_partner: 'Edit Partner', partner_list: 'Partner List', current_password: 'Current Password', new_password: 'New Password', password_changed: 'Password Changed', permission_denied: 'Permission Denied', super_admin_only: 'Super Admin Only', client_login_info: 'Login Info', admin_name: 'Name', note: 'Note', edit_note: 'Edit Note', only_note_editable: 'Only note is editable', price: 'Price (€)', order_note: 'Order Note', confirm_title: 'Confirmation', confirm: 'Confirm', bulk_ship_confirm: 'Confirm bulk ship? Fees will be deducted.', confirm_delete_partner: 'Delete this partner?', confirm_request_modify: 'Submit modification request?', confirm_request_delete: 'Submit delete request?', confirm_request_product_modify: 'Submit product mod request?', confirm_request_product_delete: 'Submit product del request?', view_warehouse_address: 'Warehouse Addr', warehouse_address_title: 'Shipping Address', warehouse_address_tip: 'Please add your Client ID after the recipient name.', tracking_number: 'Tracking #', expected_qty: 'Expected', actual_qty: 'Received', photos: 'Photos', confirm_arrival: 'Confirm Arrival', stock_in: 'Stock In', process_inbound: 'Process', upload_photos: 'Upload', customs: 'Customs', arrived: 'Arrived', stocked: 'Stocked', inbound_success: 'Inbound Success', arrival_success: 'Arrival Confirmed', top_up: 'Top Up', top_up_amount: 'Amount (€)', top_up_success: 'Top Up Success', download_invoice: 'Invoice PDF', invoice: 'INVOICE', invoice_preview: 'Invoice Preview', deducted_from_balance: 'Deducted from balance', transaction_date: 'Date', transaction_client: 'Client', transaction_desc: 'Description', transaction_ref: 'Ref', transaction_amount: 'Amount', transaction_invoice: 'Proof', wire_transfer: 'Wire Transfer', fee_deduction: 'Service Fee', bill_to: 'Bill To:', bill_from: 'Bill From:', invoice_no: 'Invoice #:', invoice_date: 'Date:', total_amount: 'Total:', item_desc: 'Description', item_qty: 'Qty', item_price: 'Price', item_total: 'Total', subtotal: 'Subtotal', tax: 'Tax', total: 'Total', bank_info: 'Bank Details', bank_name: 'Bank', account_holder: 'Holder', iban: 'IBAN', swift: 'BIC/SWIFT', invoice_note: 'Notes' }, de: { app_name: 'NEOVORA WMS', dashboard: 'Dashboard', orders: 'Bestellungen', inventory: 'Lagerbestand', inbound: 'Eingang', finance: 'Finanzen', reports: 'Berichte', settings: 'Einstellungen', welcome: 'Willkommen', login_title: 'NEOVORA WMS Login', login_subtitle: 'Enterprise Logistik Lösung', username: 'Benutzername', password: 'Passwort', login_btn: 'Login', status: 'Status', actions: 'Aktionen', edit: 'Bearbeiten', delete: 'Löschen', save: 'Speichern', cancel: 'Abbrechen', create: 'Erstellen', search_placeholder: 'Suche...', confirm: 'Bestätigen', admin_role: 'Administrator', client_role: 'Kunde', partner_role: 'Partner', month_1: 'Jan', month_2: 'Feb', month_3: 'Mär', month_4: 'Apr', month_5: 'Mai', month_6: 'Jun', // Fallback to English for deeper keys in demo }, es: { app_name: 'NEOVORA WMS', dashboard: 'Panel', orders: 'Pedidos', inventory: 'Inventario', inbound: 'Entrada', finance: 'Finanzas', reports: 'Informes', settings: 'Ajustes', welcome: 'Bienvenido', login_title: 'Acceso NEOVORA WMS', login_subtitle: 'Solución logística empresarial', username: 'Usuario', password: 'Contraseña', login_btn: 'Entrar', status: 'Estado', actions: 'Acciones', edit: 'Editar', delete: 'Eliminar', save: 'Guardar', cancel: 'Cancelar', create: 'Crear', search_placeholder: 'Buscar...', confirm: 'Confirmar', admin_role: 'Admin', client_role: 'Cliente', partner_role: 'Socio', month_1: 'Ene', month_2: 'Feb', month_3: 'Mar', month_4: 'Abr', month_5: 'May', month_6: 'Jun', }, it: { app_name: 'NEOVORA WMS', dashboard: 'Cruscotto', orders: 'Ordini', inventory: 'Inventario', inbound: 'In entrata', finance: 'Finanza', reports: 'Rapporti', settings: 'Impostazioni', welcome: 'Benvenuto', login_title: 'Accesso NEOVORA WMS', login_subtitle: 'Soluzione logistica aziendale', username: 'Nome utente', password: 'Password', login_btn: 'Accesso', status: 'Stato', actions: 'Azioni', edit: 'Modifica', delete: 'Elimina', save: 'Salva', cancel: 'Annulla', create: 'Creare', search_placeholder: 'Cerca...', confirm: 'Confermare', admin_role: 'Amministratore', client_role: 'Cliente', partner_role: 'Partner', month_1: 'Gen', month_2: 'Feb', month_3: 'Mar', month_4: 'Apr', month_5: 'Mag', month_6: 'Giu', }, zh: { app_name: 'NEOVORA WMS系统', dashboard: '概览', orders: '订单管理', inventory: '库存管理', inbound: '入库管理', finance: '财务总览', reports: '数据报表', settings: '系统设置', welcome: '欢迎回来', login_title: 'NEOVORA WMS系统 登录', login_subtitle: '企业级仓储物流解决方案', username: '账号', password: '密码', login_btn: '安全登录', login_error: '账号或密码错误', logout: '退出登录', pending_orders: '待处理订单', ready_to_ship: '待发货', low_stock: '库存预警', monthly_revenue: '本月营收', recent_activity: '业务动态', quick_actions: '快捷操作', bulk_upload: '批量导入', create_inbound: '创建入库', export_reports: '导出数据', search_placeholder: '搜索订单号、SKU...', search_tracking: '扫描/输入物流单号...', search_clients: '搜索客户...', status: '状态', actions: '操作', balance: '账户余额', new_shipment: '发货', needs_action: '需处理', awaiting_pickup: '待揽收', available: '可用', allocated: '占用', location: '库位', all: '全部', out_of_stock: '缺货', print: '打印面单', ship: '发货', selected: '已选', client_list: '客户中心', back_to_clients: '返回列表', dimensions: '体积 (cm)', weight: '重量 (kg)', fragile: '易碎', est_shipping: '预估运费', add_product: '新增商品', import_excel: '导入', upload_success: '数据导入成功', downloading: '正在生成报表...', client_balances: '客户余额', analytics_dashboard: '经营分析', total_orders: '总订单', success_rate: '履约率', avg_ship_time: '发货时效', pro_insight: '详细数据请点击“导出报表”查看。', edit: '编辑', delete: '删除', save: '保存更改', cancel: '取消', create: '立即创建', edit_product: '编辑商品', create_product: '新建商品档案', edit_order: '编辑订单', create_order: '录入订单', edit_client: '编辑客户', create_client: '新建客户档案', stock_qty: '库存', location_code: '库位', service_fee: '操作费 (€)', shipping_fee: '运费 (€)', client_name: '客户名称', account_status: '状态', please_select_orders: '请选择订单', revenue_trend: '营收趋势', order_distribution: '状态分布', top_products: '热销 TOP 3', active: '正常', inactive: '冻结', total_fees: '累计费用', admin_role: '管理员', partner_role: '合伙人', client_role: '客户', month_1: '1月', month_2: '2月', month_3: '3月', month_4: '4月', month_5: '5月', month_6: '6月', processing: '处理中', packed: '已打包', shipped: '已发货', cancelled: '已取消', cancel_requested: '取消申请', modify_requested: '修改申请', delete_requested: '删除申请', pending: '待处理', product_updated: '商品已更新', order_updated: '订单已更新', client_updated: '客户已更新', client_added: '客户已添加', client_deleted: '客户已删除', partner_added: '合伙人已添加', partner_updated: '合伙人已更新', partner_deleted: '合伙人已删除', order_deleted: '订单已删除', view_history: '流水详情', history_unavailable: '演示模式数据暂不可用', advanced_filters: '筛选', parsing_file: '解析中...', import_now: '导入', no_inventory: '暂无库存数据', unassigned: '未分配', standard: '标准', general: '通用', request_delete: '申请删除', request_modify: '申请修改', request_sent: '申请已提交', approve: '批准', reject: '拒绝', switch_role: '切换角色', product_name: '商品名称', sku: 'SKU', manual_add: '手动录入', platform_order_id: '平台单号', quantity: '数量', currency: '币种', add_client: '添加客户', confirm_delete_client: '此操作不可恢复,确认删除?', confirm_delete_order: '确认删除此订单?', menu: '导航', company_name: '公司名称', contact_person: '联系人', email: '邮箱', phone: '电话', country: '国家', address: '地址', vat_number: 'VAT/EORI', client_credentials: '登录凭证', set_username: '用户名', set_password: '密码', client_management: '客户管理', admin_management: '权限管理', my_account: '个人中心', partner_management: '合伙人', create_partner: '添加合伙人', edit_partner: '编辑信息', partner_list: '合伙人列表', current_password: '当前密码', new_password: '新密码', password_changed: '密码已修改', permission_denied: '权限不足', super_admin_only: '仅限超级管理员', client_login_info: '登录信息', admin_name: '姓名', note: '备注', edit_note: '编辑备注', only_note_editable: '仅备注可编辑', price: '价格 (€)', order_note: '订单备注', confirm_title: '确认操作', confirm: '确认执行', bulk_ship_confirm: '确认对选中订单进行发货处理?系统将自动扣费。', confirm_delete_partner: '确认删除此合伙人?', confirm_request_modify: '确认提交修改申请?', confirm_request_delete: '确认提交删除申请?', confirm_request_product_modify: '确认提交商品修改申请?', confirm_request_product_delete: '确认提交商品删除申请?', view_warehouse_address: '仓库地址', warehouse_address_title: '仓库收货信息', warehouse_address_tip: '请务必在收件人姓名后附上您的识别码 (ID)。', tracking_number: '物流单号', expected_qty: '预报', actual_qty: '实收', photos: '照片', confirm_arrival: '确认签收', stock_in: '入库上架', process_inbound: '处理', upload_photos: '上传', customs: '清关中', arrived: '已到货', stocked: '已上架', inbound_success: '入库完成', arrival_success: '签收成功', top_up: '充值', top_up_amount: '金额 (€)', top_up_success: '充值成功', download_invoice: '下载账单', invoice: 'INVOICE', invoice_preview: '账单预览', deducted_from_balance: '费用已扣除', transaction_date: '日期', transaction_client: '客户', transaction_desc: '项目', transaction_ref: '单号', transaction_amount: '金额', transaction_invoice: '凭证', wire_transfer: '银行转账', fee_deduction: '服务费', bill_to: 'Bill To:', bill_from: 'Bill From:', invoice_no: 'Invoice #:', invoice_date: 'Date:', total_amount: 'Total:', item_desc: 'Description', item_qty: 'Qty', item_price: 'Price', item_total: 'Total', subtotal: 'Subtotal', tax: 'Tax', total: 'Total', bank_info: 'Bank Details', bank_name: 'Bank', account_holder: 'Holder', iban: 'IBAN', swift: 'BIC/SWIFT', invoice_note: 'Notes' } }; const LANGUAGES = [ { code: 'fr', label: 'Français', flag: '🇫🇷' }, { code: 'en', label: 'English', flag: '🇬🇧' }, { code: 'de', label: 'Deutsch', flag: '🇩🇪' }, { code: 'es', label: 'Español', flag: '🇪🇸' }, { code: 'it', label: 'Italiano', flag: '🇮🇹' }, ]; // --- Interfaces & Mock Data --- type Role = 'admin' | 'partner' | 'client'; type OrderStatus = 'pending' | 'processing' | 'packed' | 'shipped' | 'delivered' | 'cancelled' | 'cancel_requested' | 'modify_requested' | 'delete_requested'; type InboundStatus = 'pending' | 'customs' | 'arrived' | 'stocked'; interface Product { id: string; sku: string; name: string; image: string; stock: number; allocated: number; location: string; weight: number; dimensions: string; isFragile: boolean; ownerId: string; category: string; note?: string; requestStatus?: 'modify_requested' | 'delete_requested' | null; } interface Order { id: string; platformOrderId: string; sku: string; quantity: number; status: OrderStatus; labelUrl: string; ownerId: string; createdAt: string; updatedAt: string; shippingFee: number; serviceFee: number; trackingNumber?: string; requestNote?: string; productName?: string; price?: number; note?: string; } interface Inbound { id: string; batchNo: string; trackingNumber: string; sku: string; quantity: number; receivedQty: number; status: InboundStatus; ownerId: string; createdAt: string; notes?: string; } interface User { id: string; name: string; avatar: string; role: Role; balance: number; currency: string; totalProducts?: number; status?: 'active' | 'inactive'; username?: string; password?: string; companyName?: string; contactPerson?: string; email?: string; phone?: string; country?: string; address?: string; vatNumber?: string; } interface Transaction { id: string; refId: string; amount: number; type: 'debit' | 'credit'; category: 'topup' | 'service_fee' | 'shipping_fee' | 'storage_fee'; description: string; date: string; status: 'completed' | 'pending'; ownerId?: string; } // --- Mock Data --- const MOCK_ADMIN: User = { id: 'a1', name: 'Super Admin', username: 'admin', password: 'password', avatar: 'AD', role: 'admin', balance: 0, currency: 'EUR', }; const MOCK_CLIENT_USER: User = { id: 'u1', name: '深圳跨境大卖', companyName: 'Shenzhen Global Seller Co., Ltd.', contactPerson: '张伟', email: 'zhangwei@example.com', phone: '+86 13800138000', country: 'China', address: '深圳市南山区科技园 88 号', vatNumber: 'CN123456789', username: 'client', password: 'password', avatar: 'SG', role: 'client', balance: 2450.50, currency: 'EUR', totalProducts: 4, status: 'active' }; const MOCK_CLIENTS_SEED: User[] = [ MOCK_CLIENT_USER, { id: 'u2', name: '义乌小商品', companyName: 'Yiwu Small Commodities', contactPerson: '李娜', username: 'yiwu01', password: '123', avatar: 'YT', role: 'client', balance: 120.00, currency: 'EUR', totalProducts: 12, status: 'active' }, ]; const INITIAL_PRODUCTS: Product[] = [ { id: 'p1', sku: 'VTG-DR-FLR-01', name: '法式复古碎花裙 (S码)', image: '👗', stock: 12, allocated: 1, location: 'A-01-02', weight: 0.35, dimensions: '30x25x2', isFragile: false, ownerId: 'u1', category: 'Apparel', note: 'S码畅销款' }, { id: 'p2', sku: 'HM-BAG-STR-02', name: '手工草编沙滩包', image: '👜', stock: 5, allocated: 0, location: 'B-03-01', weight: 0.8, dimensions: '40x30x15', isFragile: false, ownerId: 'u1', category: 'Accessories' }, ]; const INITIAL_ORDERS: Order[] = [ { id: 'o1', platformOrderId: '1213341231', sku: '12321321', quantity: 1, status: 'pending', labelUrl: '#', ownerId: 'u1', createdAt: '2025-11-26', updatedAt: '2025-11-26', shippingFee: 0, serviceFee: 2.5, productName: '示例商品', price: 10.0, note: '无' }, ]; const INITIAL_INBOUNDS: Inbound[] = [ { id: 'i1', batchNo: 'IB-231120-01', trackingNumber: 'SF1029384455CN', sku: 'VTG-DR-FLR-01', quantity: 20, receivedQty: 0, status: 'customs', ownerId: 'u1', createdAt: '2023-11-20' }, ]; const INITIAL_TRANSACTIONS: Transaction[] = [ { id: 't1', refId: '-', amount: 500.00, type: 'credit', category: 'topup', description: 'Wire Transfer Top-up', date: '2023-11-01', status: 'completed', ownerId: 'u1' }, ]; // --- Enterprise Components --- const EnterpriseCard = ({ children, className = '', onClick }: { children: React.ReactNode, className?: string, onClick?: () => void }) => (
{children}
); const Button = ({ children, variant = 'primary', className = '', onClick, disabled }: any) => { const variants: any = { primary: "bg-[#0f172a] text-white hover:bg-[#1e293b] shadow-sm", // Slate-900 to Slate-800 secondary: "bg-white text-slate-700 border border-slate-300 hover:bg-slate-50 shadow-sm", outline: "border border-slate-300 text-slate-600 hover:bg-slate-50", ghost: "text-slate-600 hover:bg-slate-100 hover:text-slate-900", danger: "bg-red-600 text-white hover:bg-red-700 shadow-sm", action_blue: "text-blue-600 hover:bg-blue-50 border border-transparent hover:border-blue-100", action_red: "text-red-600 hover:bg-red-50 border border-transparent hover:border-red-100", }; const baseStyle = "px-4 py-2 rounded-md font-medium text-sm transition-all duration-200 active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2 whitespace-nowrap"; return ( ); }; const StatusBadge = ({ status }: { status: string }) => { // Using French keys or fallback for display logic const t = TRANSLATIONS.fr; const styles: any = { pending: 'bg-amber-50 text-amber-700 border-amber-200', processing: 'bg-blue-50 text-blue-700 border-blue-200', packed: 'bg-indigo-50 text-indigo-700 border-indigo-200', shipped: 'bg-emerald-50 text-emerald-700 border-emerald-200', delivered: 'bg-slate-100 text-slate-700 border-slate-200', cancelled: 'bg-slate-50 text-slate-500 border-slate-200', cancel_requested: 'bg-red-50 text-red-600 border-red-200', modify_requested: 'bg-orange-50 text-orange-600 border-orange-200', delete_requested: 'bg-red-50 text-red-600 border-red-200', customs: 'bg-orange-50 text-orange-700 border-orange-200', arrived: 'bg-cyan-50 text-cyan-700 border-cyan-200', stocked: 'bg-teal-50 text-teal-700 border-teal-200', active: 'bg-emerald-50 text-emerald-700 border-emerald-200', inactive: 'bg-slate-50 text-slate-500 border-slate-200', }; const label = t[status] || status.toUpperCase(); return ( {label} ); }; const Toast = ({ message, type, onClose }: { message: string, type: 'success' | 'error', onClose: () => void }) => (
{type === 'success' ? : } {message}
); const EditModal = ({ isOpen, onClose, onSave, title, children, confirmText = "保存" }: any) => { if (!isOpen) return null; return (

{title}

{children}
{onSave && (
)}
); }; // --- Missing Components Restored & Styled --- const ConfirmModal = ({ isOpen, onClose, onConfirm, title, message, isDanger = false }: any) => { if (!isOpen) return null; return (
{isDanger ? : }

{title}

{message}

); }; const InvoiceModal = ({ isOpen, onClose, transaction, clients }: { isOpen: boolean, onClose: () => void, transaction: Transaction | null, clients: User[] }) => { if (!isOpen || !transaction) return null; const client = clients.find(c => c.id === transaction.ownerId) || { name: 'Unknown', companyName: '', address: '', vatNumber: '' } as User; // Keep invoice mostly static language or English/French standard const t = TRANSLATIONS.fr; const invoiceId = `INV-${transaction.id.substring(0, 8).toUpperCase()}`; const companyInfo = { name: 'NEOVORA WMS系统', address: '123 Logistics Blvd, Paris, France, 75001', vat: 'FR 123456789', email: 'accounting@neovora.com', bank: { name: 'BNP Paribas', holder: 'NEOVORA SAS', iban: 'FR76 3000 4000 5000 6000 7000 800', swift: 'BNPA FRPP XXX' } }; return (

{t['invoice_preview']}

NEOVORA WMS系统

{companyInfo.address}

VAT: {companyInfo.vat}

Email: {companyInfo.email}

{t['invoice']}

{invoiceId}

{t['bill_to']}

{client.companyName || client.name}

{client.contactPerson}

{client.address || '地址未填写'}

VAT: {client.vatNumber || 'N/A'}

Tel: {client.phone || 'N/A'}

{t['invoice_date']}

{transaction.date}

{t['total_amount']}

€{Math.abs(transaction.amount).toFixed(2)}

{t['item_desc']} {t['item_qty']} {t['item_price']} {t['item_total']}

{transaction.type === 'topup' ? t['top_up'] : t['fee_deduction']}

{transaction.description}

{transaction.refId !== '-' &&

Ref: {transaction.refId}

}
1 €{Math.abs(transaction.amount).toFixed(2)} €{Math.abs(transaction.amount).toFixed(2)}
{t['subtotal']}: €{Math.abs(transaction.amount).toFixed(2)}
{t['tax']} (0%): €0.00
{t['total']}: €{Math.abs(transaction.amount).toFixed(2)}

{t['bank_info']}

{t['bank_name']}: {companyInfo.bank.name}

{t['account_holder']}: {companyInfo.bank.holder}

{t['iban']}: {companyInfo.bank.iban}

{t['swift']}: {companyInfo.bank.swift}

{t['invoice_note']}

Payment is due within 30 days. Please include the invoice number in your payment reference.
感谢您的业务!如有疑问请联系客服。

); }; const AddressModal = ({ isOpen, onClose, user }: any) => { if (!isOpen) return null; return (

{TRANSLATIONS.zh.warehouse_address_title}

收件人: NEOVORA - {user?.username?.toUpperCase()}

地址: 123 Rue de la Logistique

城市: Paris

邮编: 75001

国家: France

电话: +33 1 23 45 67 89

{TRANSLATIONS.zh.warehouse_address_tip}
); } // --- Main App Logic --- export default function App() { const [isLoggedIn, setIsLoggedIn] = useState(false); const [user, setUser] = useState(null); const [loginUser, setLoginUser] = useState(''); const [loginPass, setLoginPass] = useState(''); const [loginError, setLoginError] = useState(false); const [activeTab, setActiveTab] = useState('orders'); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); // Default language set to French ('fr') const [currentLang, setCurrentLang] = useState('fr'); const [clients, setClients] = useState(MOCK_CLIENTS_SEED); const [adminUsers, setAdminUsers] = useState([MOCK_ADMIN]); const [selectedClientId, setSelectedClientId] = useState(null); const [products, setProducts] = useState(INITIAL_PRODUCTS); const [orders, setOrders] = useState(INITIAL_ORDERS); const [inbounds, setInbounds] = useState(INITIAL_INBOUNDS); const [transactions, setTransactions] = useState(INITIAL_TRANSACTIONS); const [selectedOrders, setSelectedOrders] = useState([]); const [searchQuery, setSearchQuery] = useState(''); const [clientSearchQuery, setClientSearchQuery] = useState(''); const [toast, setToast] = useState<{msg: string, type: 'success' | 'error'} | null>(null); const [inventoryClientSearch, setInventoryClientSearch] = useState(''); const [invoiceModal, setInvoiceModal] = useState<{isOpen: boolean, transaction: Transaction | null}>({isOpen: false, transaction: null}); const fileInputRef = useRef(null); const [uploadType, setUploadType] = useState<'products' | 'orders' | 'inbound' | null>(null); const [isEditModalOpen, setIsEditModalOpen] = useState(false); const [isAddressModalOpen, setIsAddressModalOpen] = useState(false); const [editingItem, setEditingItem] = useState(null); const [editType, setEditType] = useState<'product' | 'order' | 'client' | 'create_client' | 'create_order' | 'create_product' | 'create_partner' | 'edit_partner' | 'create_inbound' | 'process_inbound' | 'top_up' | null>(null); const [confirmation, setConfirmation] = useState<{ isOpen: boolean; type: any; data: any; title: string; message: string; isDanger: boolean; }>({ isOpen: false, type: null, data: null, title: '', message: '', isDanger: false }); const t = (key: string) => { // Fallback mechanism: Current Lang -> English -> Key itself return TRANSLATIONS[currentLang]?.[key] || TRANSLATIONS['en']?.[key] || key; }; // -- Logic Handlers -- const handleLogin = (e: React.FormEvent) => { e.preventDefault(); const foundAdmin = adminUsers.find(a => a.username === loginUser && a.password === loginPass); if (foundAdmin) { setUser(foundAdmin); setIsLoggedIn(true); setLoginError(false); return; } const foundClient = clients.find(c => c.username === loginUser && c.password === loginPass); if (foundClient) { setUser(foundClient); setIsLoggedIn(true); setLoginError(false); return; } setLoginError(true); }; const handleLogout = () => { setIsLoggedIn(false); setUser(null); setLoginUser(''); setLoginPass(''); setActiveTab('orders'); }; const filteredOrders = useMemo(() => { let baseOrders = orders; if (user?.role === 'client') baseOrders = orders.filter(o => o.ownerId === user.id); return baseOrders.filter(o => o.platformOrderId.toLowerCase().includes(searchQuery.toLowerCase()) || o.sku.toLowerCase().includes(searchQuery.toLowerCase()) || (o.productName && o.productName.toLowerCase().includes(searchQuery.toLowerCase()))); }, [orders, searchQuery, user]); const filteredClients = useMemo(() => { if (!clientSearchQuery) return clients; const q = clientSearchQuery.toLowerCase(); return clients.filter(c => c.name.toLowerCase().includes(q) || c.companyName?.toLowerCase().includes(q) || c.username?.toLowerCase().includes(q) || c.contactPerson?.toLowerCase().includes(q)); }, [clients, clientSearchQuery]); const stats = useMemo(() => { return { pendingOrders: orders.filter(o => o.status === 'pending').length, packedOrders: orders.filter(o => o.status === 'packed').length, lowStock: products.filter(p => p.stock < 5).length, monthlyRevenue: Math.abs(transactions.filter(t => t.type === 'debit' && t.date.startsWith('2023-11')).reduce((acc, curr) => acc + curr.amount, 0)), }; }, [orders, products, transactions]); const showToast = (msg: string, type: 'success' | 'error' = 'success') => { setToast({ msg, type }); setTimeout(() => setToast(null), 3000); }; // -- CRUD & Actions -- const handleBulkAction = (action: string) => { if (selectedOrders.length === 0) { showToast(t('please_select_orders'), 'error'); return; } if (action === 'print') { setOrders(orders.map(o => selectedOrders.includes(o.id) && o.status === 'pending' ? { ...o, status: 'processing' as OrderStatus } : o)); setSelectedOrders([]); showToast(`${t('print')} ${selectedOrders.length}`, 'success'); } else if (action === 'ship') { setConfirmation({ isOpen: true, type: 'bulk_ship', data: null, title: t('confirm_title'), message: t('bulk_ship_confirm'), isDanger: false }); } }; const openEditModal = (item: any, type: typeof editType) => { if (type === 'create_client') setEditingItem({ name: '', username: '', password: '', balance: 0, currency: 'EUR', status: 'active', companyName: '', contactPerson: '', email: '', phone: '', country: '', address: '', vatNumber: '' }); else if (type === 'create_order') setEditingItem({ platformOrderId: '', sku: '', quantity: 1, shippingFee: 0, serviceFee: 0, status: 'pending', productName: '', price: 0, note: '' }); else if (type === 'create_product') setEditingItem({ name: '', sku: '', stock: 0, weight: 0, dimensions: '', allocated: 0, location: '', isFragile: false, note: '' }); else if (type === 'create_partner') setEditingItem({ name: '', username: '', password: '', role: 'partner', status: 'active' }); else if (type === 'create_inbound') setEditingItem({ trackingNumber: '', sku: '', quantity: 1, notes: '' }); else if (type === 'process_inbound') setEditingItem({ ...item, actualQuantity: item.quantity, location: '' }); else if (type === 'top_up') setEditingItem({ ...item, amount: 0 }); else setEditingItem({...item}); setEditType(type); setIsEditModalOpen(true); }; const handleDeleteClient = (clientId: string) => { setConfirmation({ isOpen: true, type: 'delete_client', data: clientId, title: t('confirm_title'), message: t('confirm_delete_client'), isDanger: true }); }; const handleDeletePartner = (partnerId: string) => { setConfirmation({ isOpen: true, type: 'delete_partner', data: partnerId, title: t('confirm_title'), message: t('confirm_delete_partner'), isDanger: true }); }; const handleDeleteOrder = (order: Order) => { if (user?.role === 'admin' || user?.role === 'partner') setConfirmation({ isOpen: true, type: 'delete_order', data: order, title: t('confirm_title'), message: t('confirm_delete_order'), isDanger: true }); else handleRequestChange(order, 'delete'); }; const handleInboundArrival = (inbound: Inbound) => { setConfirmation({ isOpen: true, type: 'confirm_arrival', data: inbound, title: t('confirm_title'), message: `确认物流单号 ${inbound.trackingNumber} 已到达仓库?`, isDanger: false }); }; const handleRequestChange = (item: Order | Product, type: 'delete' | 'modify') => { const isDelete = type === 'delete'; const isOrder = 'platformOrderId' in item; let msgKey = ''; if (isOrder) msgKey = isDelete ? 'confirm_request_delete' : 'confirm_request_modify'; else msgKey = isDelete ? 'confirm_request_product_delete' : 'confirm_request_product_modify'; setConfirmation({ isOpen: true, type: isDelete ? 'request_delete' : 'request_modify', data: { item, type }, title: t('confirm_title'), message: t(msgKey), isDanger: isDelete }); }; const executeConfirmation = () => { const { type, data } = confirmation; if (type === 'delete_client') { setClients(clients.filter(c => c.id !== data)); showToast(t('client_deleted'), 'success'); } else if (type === 'delete_partner') { setAdminUsers(adminUsers.filter(a => a.id !== data)); showToast(t('partner_deleted'), 'success'); } else if (type === 'delete_order') { setOrders(orders.filter(o => o.id !== data.id)); showToast(t('order_deleted'), 'success'); } else if (type === 'bulk_ship') { const shippedOrders = orders.filter(o => selectedOrders.includes(o.id) && o.status === 'packed'); setOrders(orders.map(o => selectedOrders.includes(o.id) && o.status === 'packed' ? { ...o, status: 'shipped' as OrderStatus } : o)); const newTxns: Transaction[] = []; let updatedClients = [...clients]; shippedOrders.forEach(order => { const fee = (order.serviceFee || 0) + (order.shippingFee || 0); newTxns.push({ id: Math.random().toString(36), refId: order.platformOrderId, amount: -fee, type: 'debit' as const, category: 'service_fee' as const, description: `${t('fee_deduction')}: ${order.platformOrderId}`, date: new Date().toISOString().split('T')[0], status: 'completed' as const, ownerId: order.ownerId }); const clientIdx = updatedClients.findIndex(c => c.id === order.ownerId); if (clientIdx >= 0) { updatedClients[clientIdx] = { ...updatedClients[clientIdx], balance: updatedClients[clientIdx].balance - fee }; } }); setTransactions([...transactions, ...newTxns]); setClients(updatedClients); setSelectedOrders([]); showToast(t('deducted_from_balance'), 'success'); } else if (type === 'confirm_arrival') { setInbounds(inbounds.map(ib => ib.id === data.id ? { ...ib, status: 'arrived' } : ib)); showToast(t('arrival_success'), 'success'); } else if (type === 'request_delete' || type === 'request_modify') { const { item, type: reqType } = data; if ('platformOrderId' in item) { const statusVal = reqType === 'delete' ? 'cancel_requested' : 'modify_requested'; setOrders(orders.map(o => o.id === item.id ? { ...o, status: statusVal as OrderStatus } : o)); } else { const statusVal = reqType === 'delete' ? 'delete_requested' : 'modify_requested'; setProducts(products.map(p => p.id === item.id ? { ...p, requestStatus: statusVal as any } : p)); } showToast(t('request_sent'), 'success'); } }; const handleSaveEdit = () => { const currentOwnerId = user?.role === 'client' ? user.id : (selectedClientId || 'u1'); if (editType === 'product') { if (user?.role === 'client') setProducts(products.map(p => p.id === editingItem.id ? { ...p, note: editingItem.note } : p)); else setProducts(products.map(p => p.id === editingItem.id ? editingItem : p)); showToast(t('product_updated'), 'success'); } else if (editType === 'create_product') { setProducts([...products, { ...editingItem, id: Math.random().toString(36).substr(2, 9), image: '📦', ownerId: currentOwnerId, category: 'General' }]); showToast(t('product_updated'), 'success'); } else if (editType === 'order') { setOrders(orders.map(o => o.id === editingItem.id ? editingItem : o)); showToast(t('order_updated'), 'success'); } else if (editType === 'create_order') { setOrders([{ ...editingItem, id: Math.random().toString(36).substr(2, 9), ownerId: currentOwnerId, createdAt: new Date().toISOString().split('T')[0], updatedAt: new Date().toISOString().split('T')[0], labelUrl: '#' }, ...orders]); showToast(t('order_updated'), 'success'); } else if (editType === 'client') { setClients(clients.map(c => c.id === editingItem.id ? editingItem : c)); showToast(t('client_updated'), 'success'); } else if (editType === 'create_client') { setClients([...clients, { ...editingItem, id: Math.random().toString(36).substr(2, 9), avatar: editingItem.name.substring(0,2).toUpperCase(), role: 'client', totalProducts: 0 }]); showToast(t('client_added'), 'success'); } else if (editType === 'create_partner') { setAdminUsers([...adminUsers, { ...editingItem, id: Math.random().toString(36).substr(2, 9), avatar: editingItem.name.substring(0,2).toUpperCase() }]); showToast(t('partner_added'), 'success'); } else if (editType === 'edit_partner') { if (editingItem.id === user?.id) setUser({...user, ...editingItem}); setAdminUsers(adminUsers.map(u => u.id === editingItem.id ? editingItem : u)); showToast(t('partner_updated'), 'success'); } else if (editType === 'create_inbound') { setInbounds([{ id: Math.random().toString(36).substr(2, 9), batchNo: `IB-${Math.floor(Math.random()*1000)}`, trackingNumber: editingItem.trackingNumber, sku: editingItem.sku, quantity: Number(editingItem.quantity), receivedQty: 0, status: 'pending', ownerId: currentOwnerId, createdAt: new Date().toISOString().split('T')[0], notes: editingItem.notes }, ...inbounds]); showToast(t('upload_success'), 'success'); } else if (editType === 'process_inbound') { setInbounds(inbounds.map(ib => ib.id === editingItem.id ? { ...ib, status: 'stocked', receivedQty: Number(editingItem.actualQuantity) } : ib)); const existingProduct = products.find(p => p.sku === editingItem.sku && p.ownerId === editingItem.ownerId); if (existingProduct) setProducts(products.map(p => p.id === existingProduct.id ? { ...p, stock: p.stock + Number(editingItem.actualQuantity) } : p)); else setProducts([...products, { id: Math.random().toString(36).substr(2, 9), sku: editingItem.sku, name: '入库商品', image: '📦', stock: Number(editingItem.actualQuantity), allocated: 0, location: editingItem.location || 'IN-SORT', weight: 0.5, dimensions: '10x10x10', isFragile: false, ownerId: editingItem.ownerId, category: 'General' }]); showToast(t('inbound_success'), 'success'); } else if (editType === 'top_up') { const amount = Number(editingItem.amount); if (amount > 0) { setClients(clients.map(c => c.id === editingItem.id ? { ...c, balance: c.balance + amount } : c)); setTransactions([{ id: Math.random().toString(36), refId: '-', amount: amount, type: 'credit', category: 'topup', description: t('wire_transfer'), date: new Date().toISOString().split('T')[0], status: 'completed', ownerId: editingItem.id }, ...transactions]); showToast(t('top_up_success'), 'success'); } } setIsEditModalOpen(false); }; const triggerUpload = (type: 'products' | 'orders' | 'inbound') => { setUploadType(type); setTimeout(() => fileInputRef.current?.click(), 100); }; const handleFileUpload = (e: React.ChangeEvent) => { if (e.target.files && e.target.files.length > 0) { showToast(t('parsing_file'), 'success'); setTimeout(() => { showToast(t('upload_success'), 'success'); setUploadType(null); if (fileInputRef.current) fileInputRef.current.value = ''; }, 1000); } }; // --- Render Sections --- const SidebarItem = ({ id, label, icon: Icon, active, onClick }: any) => ( ); const renderLogin = () => (

{t('app_name')}

{currentLang === 'zh' ? '重新定义' : 'Redéfinir'}
{currentLang === 'zh' ? '您的供应链管理' : 'Votre Supply Chain'}

{t('login_subtitle')}

© 2024 NEOVORA Inc. Enterprise Edition.

{t('welcome')}

{t('login_subtitle')}

setLoginUser(e.target.value)} className="w-full px-4 py-3 rounded-lg border border-slate-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all" required placeholder="admin" />
setLoginPass(e.target.value)} className="w-full px-4 py-3 rounded-lg border border-slate-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-all" required placeholder="••••••••" />
{loginError &&
{t('login_error')}
}
); const KPICard = ({ title, value, icon: Icon, trend, onClick }: any) => (
{trend && +{trend}%}

{value}

{title}

); const renderDashboard = () => (
setActiveTab('orders')} /> setActiveTab('orders')} /> setActiveTab('inventory')} /> user?.role !== 'client' && setActiveTab('finance')} />

{t('recent_activity')}

{orders.slice(0, 5).map(order => ( ))}
ID{t('status')}Date
{order.platformOrderId} {order.createdAt}

{t('quick_actions')}

常用功能快捷入口

); const renderOrders = () => (
setSearchQuery(e.target.value)} placeholder={t('search_placeholder')} className="w-full pl-9 pr-4 py-2 bg-slate-50 border border-slate-200 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all placeholder:text-slate-400" />
{(user?.role === 'admin' || user?.role === 'partner') && selectedOrders.length > 0 && (
{selectedOrders.length} {t('selected')}
)}
{(user?.role === 'admin' || user?.role === 'partner') && } {filteredOrders.map(order => ( {(user?.role === 'admin' || user?.role === 'partner') && } ))}
0 && selectedOrders.length === filteredOrders.length} onChange={(e) => setSelectedOrders(e.target.checked ? filteredOrders.map(o => o.id) : [])} />{t('orders')}{t('status')}Date{t('actions')}
{ if (e.target.checked) setSelectedOrders([...selectedOrders, order.id]); else setSelectedOrders(selectedOrders.filter(id => id !== order.id)); }} />
{products.find(p => p.sku === order.sku)?.image || }
{order.platformOrderId} {order.note && }
{order.sku} | Qty: {order.quantity} {order.price && <> | €{order.price} }
{order.createdAt}
{user?.role === 'client' ? ( <> {(order.status !== 'cancel_requested' && order.status !== 'modify_requested' && order.status !== 'shipped') && (<>)} ) : ( <> )}
); const renderInventory = () => { if (!selectedClientId && (user?.role === 'admin' || user?.role === 'partner')) { const filteredInventoryClients = clients.filter(c => c.name.toLowerCase().includes(inventoryClientSearch.toLowerCase()) || c.username?.toLowerCase().includes(inventoryClientSearch.toLowerCase())); return (
setInventoryClientSearch(e.target.value)}/>
{filteredInventoryClients.length === 0 ?
No clients found
: (
{filteredInventoryClients.map(client => ( setSelectedClientId(client.id)}>
{client.avatar}

{client.name}

{client.companyName || 'No Company Info'}

{client.totalProducts || 0} SKU
))}
)}
); } const currentOwnerId = user?.role === 'client' ? user.id : selectedClientId; const displayProducts = products.filter(p => p.ownerId === currentOwnerId); return (
{(user?.role === 'admin' || user?.role === 'partner') && }

{t('inventory')}

{user?.role !== 'client' && }
{displayProducts.map(product => (
{product.image}

{product.name}

{product.sku}
{t('available')}{product.stock}
{t('location')}{product.location || '-'}
{product.note &&
{product.note}
}
))}
); }; // --- Restored Render Functions --- const renderInbound = () => { const userInbounds = user?.role === 'client' ? inbounds.filter(ib => ib.ownerId === user.id) : inbounds; return (

{t('inbound')}

{user?.role === 'client' && }
{user?.role !== 'client' && (
setSearchQuery(e.target.value)} />
)}
{userInbounds.filter(ib => !searchQuery || ib.trackingNumber.toLowerCase().includes(searchQuery.toLowerCase())).map(ib => ( ))}
{t('tracking_number')}SKU / {t('quantity')}{t('status')}{t('actions')}
{ib.trackingNumber}
{ib.sku}
{t('expected_qty')}: {ib.quantity} {ib.receivedQty ? `/ ${t('actual_qty')}: ${ib.receivedQty}` : ''}
{(user?.role === 'admin' || user?.role === 'partner') ? ( <> {ib.status === 'pending' && } {ib.status === 'arrived' && } {ib.status === 'stocked' && {t('stocked')}} ) : {ib.createdAt}}
); }; const renderClients = () => { if (!user?.role.includes('admin')) return null; return (

{t('client_list')}

setClientSearchQuery(e.target.value)} />
{filteredClients.map(client => (
{client.avatar}

{client.name}

{client.companyName || 'No Company'}

Username

{client.username}

Contact

{client.contactPerson || '-'}

))}
); }; const renderFinance = () => (

{t('client_balances')}

{clients.map(client => (
{client.avatar}

{client.name}

ID: {client.id}

{t('balance')}

€{client.balance.toFixed(2)}

))}

{t('recent_activity')}

{transactions.map(tx => ( ))}
{t('transaction_date')}{t('transaction_client')}{t('transaction_desc')}{t('transaction_ref')}{t('transaction_amount')}{t('actions')}
{tx.date} {clients.find(c => c.id === tx.ownerId)?.name || 'Unknown'} {tx.description} {tx.refId} {tx.type === 'credit' ? '+' : ''}€{Math.abs(tx.amount).toFixed(2)}
); const renderReports = () => (

{t('analytics_dashboard')}

{t('revenue_trend')}

Last 6 Months
{[65, 40, 75, 50, 90, 80].map((height, i) => (
{t(`month_${i+1}`)}
))}

{t('order_distribution')}

{[{ label: t('shipped'), val: 45, color: 'bg-emerald-500' }, { label: t('pending'), val: 30, color: 'bg-amber-500' }, { label: t('processing'), val: 15, color: 'bg-blue-500' }, { label: t('cancelled'), val: 10, color: 'bg-red-500' }].map((item, i) => (
{item.label}{item.val}%
))}
); const renderSettings = () => (

{t('admin_management')}

{t('my_account')}

{t('username')}: {user?.username}

Role: {user?.role.toUpperCase()}

{user?.role === 'admin' && (

{t('partner_management')}

{adminUsers.filter(u => u.role === 'partner').map(partner => ( ))}
{t('username')}{t('admin_name')}{t('actions')}
{partner.username} {partner.name}
)}
); // --- Layout Render --- if (!isLoggedIn) return renderLogin(); return (
{toast && setToast(null)} />} {/* Modals */} setConfirmation({ ...confirmation, isOpen: false })} onConfirm={executeConfirmation} /> setInvoiceModal({...invoiceModal, isOpen: false})} transaction={invoiceModal.transaction} clients={clients} /> setIsAddressModalOpen(false)} user={user} /> setIsEditModalOpen(false)} onSave={handleSaveEdit} title={editType === 'order' ? t('edit_order') : editType === 'product' ? t('edit_product') : editType === 'client' ? t('edit_client') : t('create')} confirmText={t('save')}>
{editingItem && Object.keys(editingItem).map((key) => { if(key === 'id' || key === 'createdAt' || key === 'updatedAt' || key === 'ownerId' || key === 'labelUrl' || key === 'receivedQty' || key === 'image' || key === 'requestStatus') return null; if(key === 'status' || key === 'role') return null; // Handle selects separately if needed return (
{key === 'note' || key === 'address' || key === 'notes' ?