diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 5353c21..ccf296d 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -49,5 +49,385 @@ "profile": "Profile", "@profile": {}, "sales_today": "Sales today", - "@sales_today": {} + "@sales_today": {}, + "order": "Order", + "@order": {}, + "sales": "Sales", + "@sales": {}, + "finance": "Finance", + "@finance": {}, + "product": "Product", + "@product": {}, + "form": "Form", + "@form": {}, + "schedule": "Schedule", + "@schedule": {}, + "inventory": "Inventory", + "@inventory": {}, + "customer": "Customer", + "@customer": {}, + "purchase": "Purchase", + "@purchase": {}, + "today_summary": "Today's Summary", + "@today_summary": {}, + "today": "Today", + "@today": {}, + "new_customer": "New Customer", + "@new_customer": {}, + "refund": "Refund", + "@refund": {}, + "void_text": "Void", + "@void_text": {}, + "increase": "Increase", + "@increase": {}, + "today_top_product": "Today's Top Product", + "@today_top_product": {}, + "rank": "Rank", + "@rank": {}, + "quantity_sold": "Quantity Sold", + "@quantity_sold": {}, + "total_orders": "Total Orders", + "@total_orders": {}, + "average_price": "Average Price", + "@average_price": {}, + "perfomance": "Performance", + "@perfomance": {}, + "total_sales": "Total Sales", + "@total_sales": {}, + "total_items": "Total Items", + "@total_items": {}, + "summary": "Summary", + "@summary": {}, + "net_sales": "Net Sales", + "@net_sales": {}, + "daily_breakdown": "Daily Breakdown", + "@daily_breakdown": {}, + "orders": "Orders", + "@orders": {}, + "items": "Items", + "@items": {}, + "tax": "Tax", + "@tax": {}, + "discount": "Discount", + "@discount": {}, + "total_purchase": "Total Purchase", + "@total_purchase": {}, + "pending_order": "Pending Order", + "@pending_order": {}, + "history_purchase": "History Purchase", + "@history_purchase": {}, + "all": "All", + "@all": {}, + "select_date_range": "Select Date Range", + "@select_date_range": {}, + "no_date_selected": "No date has been selected yet", + "@no_date_selected": {}, + "selected_date": "Selected Date", + "@selected_date": {}, + "select": "Select", + "@select": {}, + "cancel": "Cancel", + "@cancel": {}, + "total_revenue": "Total Revenue", + "@total_revenue": {}, + "total_expenditures": "Total Expenditures", + "@total_expenditures": {}, + "net_profit": "Net Profit", + "@net_profit": {}, + "margin_profit": "Margin Profit", + "@margin_profit": {}, + "cash_flow_analysis": "Cash Flow Analysis", + "@cash_flow_analysis": {}, + "cash_in": "Cash In", + "@cash_in": {}, + "cash_out": "Cash Out", + "@cash_out": {}, + "net_flow": "Net Flow", + "@net_flow": {}, + "cash_flow_chart": "Cash Flow Chart for {days} Last Days", + "@cash_flow_chart": { + "placeholders": { + "days": { + "type": "int", + "example": "7" + } + } + }, + "profit_loss_detail": "Profit & Loss Details", + "@profit_loss_detail": {}, + "gross_sales": "Gross Sales", + "@gross_sales": {}, + "return_text": "Return", + "@return_text": {}, + "cogs": "COGS", + "@cogs": {}, + "cost_of_goods_sold": "Cost of goods sold", + "@cost_of_goods_sold": {}, + "gross_profit": "Gross Profit", + "@gross_profit": {}, + "operating_costs": "Operating Costs", + "@operating_costs": {}, + "sales_category": "Sales Category", + "@sales_category": {}, + "unit": "Unit", + "@unit": {}, + "category_no_data": "There are no data categories yet", + "@category_no_data": {}, + "category_no_data_desc": "Sales category data will appear here", + "@category_no_data_desc": {}, + "product_analytic": "Product Analytic", + "@product_analytic": {}, + "view_all": "View All", + "@view_all": {}, + "sold": "Sold", + "@sold": {}, + "revenue": "Revenue", + "@revenue": {}, + "cost": "Cost", + "@cost": {}, + "profit_per_unit": "Profit per unit", + "@profit_per_unit": {}, + "total_sold": "Total Sold", + "@total_sold": {}, + "ingredients": "Ingredients", + "@ingredients": {}, + "low_stock": "Low Stock", + "@low_stock": {}, + "zero_stock": "Zero Stock", + "@zero_stock": {}, + "stock": "Stock", + "@stock": {}, + "price": "Price", + "@price": {}, + "out_of_stock": "Out of stock", + "@out_of_stock": {}, + "out_of_stock_desc": "Product not available for sale", + "@out_of_stock_desc": {}, + "in_text": "In", + "@in_text": {}, + "out_text": "Out", + "@out_text": {}, + "available": "Available", + "@available": {}, + "total_products": "Total Products", + "@total_products": {}, + "total_ingredients": "Total Ingredients", + "@total_ingredients": {}, + "products": "Products", + "@products": {}, + "value_text": "Value", + "@value_text": {}, + "low_stock_desc": "Immediately reorder at least {stock} pcs", + "@low_stock_desc": { + "placeholders": { + "stock": { + "type": "String", + "example": "0" + } + } + }, + "joined": "Joined", + "@joined": {}, + "ago": "ago", + "@ago": {}, + "active": "Active", + "@active": {}, + "inactive": "Inactive", + "@inactive": {}, + "total_amount": "Total Amount", + "@total_amount": {}, + "table": "Table", + "@table": {}, + "remaining": "Remaining", + "@remaining": {}, + "payment": "Payment", + "@payment": {}, + "completed": "Completed", + "@completed": {}, + "pending": "Pending", + "@pending": {}, + "no_order_with_status": "No {status} orders found", + "@no_order_with_status": { + "placeholders": { + "status": { + "type": "String", + "example": "pending" + } + } + }, + "order_details": "Order Details", + "@order_details": {}, + "order_number": "Order Number", + "@order_number": {}, + "order_status": "Order Status", + "@order_status": {}, + "order_information": "Order Information", + "@order_information": {}, + "order_type": "Order Type", + "@order_type": {}, + "payment_status": "Payment Status", + "@payment_status": {}, + "created": "Created", + "@created": {}, + "order_item": "Order Item", + "@order_item": {}, + "item": "Item", + "@item": {}, + "each": "Each", + "@each": {}, + "total_item": "Total Item", + "@total_item": {}, + "payment_summary": "Payment Summary", + "@payment_summary": {}, + "subtotal": "Subtotal", + "@subtotal": {}, + "paid": "Paid", + "@paid": {}, + "total": "Total", + "@total": {}, + "payment_method": "Payment Method", + "@payment_method": {}, + "dine_in": "Dine In", + "@dine_in": {}, + "dine_in_experience": "Dine In Experience", + "@dine_in_experience": {}, + "note": "Note", + "@note": {}, + "sales_chart": "Sales Chart", + "@sales_chart": {}, + "no_data_available": "No Data Avaiable", + "@no_data_available": {}, + "total_days_overview": "{days} days overview", + "@total_days_overview": { + "placeholders": { + "days": { + "type": "int", + "example": "0" + } + } + }, + "sales_data": "Sales Data", + "@sales_data": {}, + "no_sales_data": "No Sales Data", + "@no_sales_data": {}, + "no_sales_data_desc": "Sales data will appear here once transactions are recorded", + "@no_sales_data_desc": {}, + "payment_methods": "Payment Methods", + "@payment_methods": {}, + "payment_methods_desc": "Revenue breakdown by payment method ", + "@payment_methods_desc": {}, + "revenue_share": "Revenue Share", + "@revenue_share": {}, + "no_payment_methods": "No Payment Methods", + "@no_payment_methods": {}, + "no_payment_methods_desc": "Payment method data will appear here once transactions are made", + "@no_payment_methods_desc": {}, + "best_selling_products": "Best Selling Products", + "@best_selling_products": {}, + "highest_sales_ranking": "Highest sales ranking", + "@highest_sales_ranking": {}, + "best_seller": "Best Seller", + "@best_seller": {}, + "top_performer": "Top Performer", + "@top_performer": {}, + "account_information": "Account Information", + "@account_information": {}, + "member_since": "Member Since", + "@member_since": {}, + "edit_profile": "Edit Profile", + "@edit_profile": {}, + "edit_profile_desc": "Update your profile information", + "@edit_profile_desc": {}, + "change_password": "Change Password", + "@change_password": {}, + "change_password_desc": "Update your password", + "@change_password_desc": {}, + "business_settings": "Business Settings", + "@business_settings": {}, + "outlet_information": "Outlet Information", + "@outlet_information": {}, + "outlet_informatio_desc": "Manage your outlet details", + "@outlet_informatio_desc": {}, + "staff_management": "Staff Management", + "@staff_management": {}, + "staff_management_desc": "Manage your staff", + "@staff_management_desc": {}, + "manage_your_products": "Manage Your Products", + "@manage_your_products": {}, + "download_report": "Download Report", + "@download_report": {}, + "download_report_desc": "Download your sales report or inventory report", + "@download_report_desc": {}, + "app_settings": "App Settings", + "@app_settings": {}, + "language_desc": "Select your preferred language", + "@language_desc": {}, + "support": "Support", + "@support": {}, + "help_center": "Help Center", + "@help_center": {}, + "help_center_desc": "Get help from our support team", + "@help_center_desc": {}, + "about": "About", + "@about": {}, + "about_desc": "Learn more about our app", + "@about_desc": {}, + "logout": "Logout", + "@logout": {}, + "logout_desc": "Logout of your account", + "@logout_desc": {}, + "save": "Save", + "@save": {}, + "name": "Name", + "@name": {}, + "name_placeholder": "Please enter your name", + "@name_placeholder": {}, + "password_changed": "Password Changed", + "@password_changed": {}, + "current_password": "Current Password", + "@current_password": {}, + "current_password_placeholder": "Please enter your current password", + "@current_password_placeholder": {}, + "new_password": "New Password", + "@new_password": {}, + "new_password_placeholder": "Please enter your new password", + "@new_password_placeholder": {}, + "new_password_not_same": "New password cannot be same as current password", + "@new_password_not_same": {}, + "general_information": "General Information", + "@general_information": {}, + "address": "Address", + "@address": {}, + "phone_number": "Phone Number", + "@phone_number": {}, + "currency": "Currency", + "@currency": {}, + "tax_rate": "Tax Rate", + "@tax_rate": {}, + "status_text": "Status", + "@status_text": {}, + "coming_soon": "Coming Soon", + "@coming_soon": {}, + "coming_soon_desc": "Something amazing is brewing!\nStay tuned for the big reveal.", + "@coming_soon_desc": {}, + "transaction_report": "Transaction Report", + "@transaction_report": {}, + "transaction_report_desc": "Export all transaction data with detailed analytics", + "@transaction_report_desc": {}, + "invetory_report": "Inventory Report", + "@invetory_report": {}, + "invetory_report_desc": "Export inventory and stock data with trends", + "@invetory_report_desc": {}, + "about_app": "About App", + "@about_app": {}, + "app_information": "App Information", + "@app_information": {}, + "app_name": "App Name", + "@app_name": {}, + "build_number": "Build Number", + "@build_number": {}, + "package_name": "Package Name", + "@package_name": {}, + "device": "Device", + "@device": {} } diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index ed3af6d..601dd7d 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -49,5 +49,385 @@ "profile": "Profil", "@profile": {}, "sales_today": "Penjualan hari ini", - "@sales_today": {} + "@sales_today": {}, + "order": "Pesanan", + "@order": {}, + "sales": "Penjualan", + "@sales": {}, + "finance": "Keuangan", + "@finance": {}, + "product": "Produk", + "@product": {}, + "form": "Form", + "@form": {}, + "schedule": "Jadwal", + "@schedule": {}, + "inventory": "Inventaris", + "@inventory": {}, + "customer": "Pelanggan", + "@customer": {}, + "purchase": "Pembelian", + "@purchase": {}, + "today_summary": "Ringkasan Hari Ini", + "@today_summary": {}, + "today": "Hari ini", + "@today": {}, + "new_customer": "Pelanggan baru", + "@new_customer": {}, + "refund": "Pengembalian dana", + "@refund": {}, + "void_text": "Dibatalkan", + "@void_text": {}, + "increase": "Bertambah", + "@increase": {}, + "today_top_product": "Produk teratas hari ini", + "@today_top_product": {}, + "rank": "Pangkat", + "@rank": {}, + "quantity_sold": "Kuantiti Terjual", + "@quantity_sold": {}, + "total_orders": "Jumlah Pesanan", + "@total_orders": {}, + "average_price": "Harga Rata-rata", + "@average_price": {}, + "perfomance": "Performa", + "@perfomance": {}, + "total_sales": "Jumlah Penjualan", + "@total_sales": {}, + "total_items": "Jumlah Barang", + "@total_items": {}, + "summary": "Ringkasan", + "@summary": {}, + "net_sales": "Penjualan Bersih", + "@net_sales": {}, + "daily_breakdown": "Perincian Harian", + "@daily_breakdown": {}, + "orders": "Pesanan", + "@orders": {}, + "items": "Barang", + "@items": {}, + "tax": "Pajak", + "@tax": {}, + "discount": "Diskon", + "@discount": {}, + "total_purchase": "Jumlah Pembelian", + "@total_purchase": {}, + "pending_order": "Pesanan Menunggu", + "@pending_order": {}, + "history_purchase": "Riwayat Pembelian", + "@history_purchase": {}, + "all": "Semua", + "@all": {}, + "select_date_range": "Pilih Rentang Tanggal", + "@select_date_range": {}, + "no_date_selected": "Belum ada tanggal dipilih", + "@no_date_selected": {}, + "selected_date": "Tanggal Terpilih", + "@selected_date": {}, + "select": "Pilih", + "@select": {}, + "cancel": "Batal", + "@cancel": {}, + "total_revenue": "Jumlah Pendapatan", + "@total_revenue": {}, + "total_expenditures": "Jumlah Pengeluaran", + "@total_expenditures": {}, + "net_profit": "Keuntungan Bersih", + "@net_profit": {}, + "margin_profit": "Keuntungan Margin", + "@margin_profit": {}, + "cash_flow_analysis": "Analisis Arus Kas", + "@cash_flow_analysis": {}, + "cash_in": "Uang Masuk", + "@cash_in": {}, + "cash_out": "Uang Keluar", + "@cash_out": {}, + "net_flow": "Arus Bersih", + "@net_flow": {}, + "cash_flow_chart": "Grafik Cash Flow ${days} Hari Terakhir", + "@cash_flow_chart": { + "placeholders": { + "days": { + "type": "int", + "example": "7" + } + } + }, + "profit_loss_detail": "Detail Untung & Rugi", + "@profit_loss_detail": {}, + "gross_sales": "Penjualan Kotor", + "@gross_sales": {}, + "return_text": "Retur", + "@return_text": {}, + "cogs": "HPP", + "@cogs": {}, + "cost_of_goods_sold": "Harga Pokok Penjualan", + "@cost_of_goods_sold": {}, + "gross_profit": "Keuntungan Kotor", + "@gross_profit": {}, + "operating_costs": "Biaya Operasional", + "@operating_costs": {}, + "sales_category": "Kategori Penjualan", + "@sales_category": {}, + "unit": "Unit", + "@unit": {}, + "category_no_data": "Belum ada data kategori", + "@category_no_data": {}, + "category_no_data_desc": "Data kategori penjualan akan muncul di sini", + "@category_no_data_desc": {}, + "product_analytic": "Analisis Produk", + "@product_analytic": {}, + "view_all": "Lihat Semua", + "@view_all": {}, + "sold": "Terjual", + "@sold": {}, + "revenue": "Pendapatan", + "@revenue": {}, + "cost": "Biaya", + "@cost": {}, + "profit_per_unit": "Keuntungan per unit", + "@profit_per_unit": {}, + "total_sold": "Jumlah Terjual", + "@total_sold": {}, + "ingredients": "Bahan Baku", + "@ingredients": {}, + "low_stock": "Stok Rendah", + "@low_stock": {}, + "zero_stock": "Stok Kosong", + "@zero_stock": {}, + "stock": "Stok", + "@stock": {}, + "price": "Harga", + "@price": {}, + "out_of_stock": "Stok habis", + "@out_of_stock": {}, + "out_of_stock_desc": "Produk tidak tersedia untuk dijual", + "@out_of_stock_desc": {}, + "in_text": "Masuk", + "@in_text": {}, + "out_text": "Keluar", + "@out_text": {}, + "available": "Tersedia", + "@available": {}, + "total_products": "Jumlah Produk", + "@total_products": {}, + "total_ingredients": "Jumlah Bahan Baku", + "@total_ingredients": {}, + "products": "Produk", + "@products": {}, + "value_text": "Nilai", + "@value_text": {}, + "low_stock_desc": "Segera reorder minimal {stock} pcs", + "@low_stock_desc": { + "placeholders": { + "stock": { + "type": "String", + "example": "0" + } + } + }, + "joined": "Bergabung", + "@joined": {}, + "ago": "lalu", + "@ago": {}, + "active": "Aktif", + "@active": {}, + "inactive": "Tidak Aktif", + "@inactive": {}, + "total_amount": "Jumlah Total", + "@total_amount": {}, + "table": "Meja", + "@table": {}, + "remaining": "Sisa", + "@remaining": {}, + "payment": "Pembayaran", + "@payment": {}, + "completed": "Selesai", + "@completed": {}, + "pending": "Menunggu", + "@pending": {}, + "no_order_with_status": "Tidak ada pesanan {status} yang ditemukan", + "@no_order_with_status": { + "placeholders": { + "status": { + "type": "String", + "example": "pending" + } + } + }, + "order_details": "Detail Pesanan", + "@order_details": {}, + "order_number": "Nomor Pesanan", + "@order_number": {}, + "order_status": "Status Pesanan", + "@order_status": {}, + "order_information": "Informasi Pesanan", + "@order_information": {}, + "order_type": "Tipe Pesanan", + "@order_type": {}, + "payment_status": "Status Pembayaran", + "@payment_status": {}, + "created": "Dibuat", + "@created": {}, + "order_item": "Item Pesanan", + "@order_item": {}, + "item": "Item", + "@item": {}, + "each": "Setiap", + "@each": {}, + "total_item": "Jumlah Item", + "@total_item": {}, + "payment_summary": "Ringkasan Pembayaran", + "@payment_summary": {}, + "subtotal": "Subtotal", + "@subtotal": {}, + "paid": "Dibayar", + "@paid": {}, + "total": "Jumlah", + "@total": {}, + "payment_method": "Metode Pembayaran", + "@payment_method": {}, + "dine_in": "Makan di Tempat", + "@dine_in": {}, + "dine_in_experience": "Pengalaman Bersantap Di Tempat", + "@dine_in_experience": {}, + "note": "Catatan", + "@note": {}, + "sales_chart": "Bagan Penjualan", + "@sales_chart": {}, + "no_data_available": "Tidak Ada Data Tersedia", + "@no_data_available": {}, + "total_days_overview": "ikhtisar {days} hari", + "@total_days_overview": { + "placeholders": { + "days": { + "type": "int", + "example": "0" + } + } + }, + "sales_data": "Data Penjualan", + "@sales_data": {}, + "no_sales_data": "Tidak ada data penjualan", + "@no_sales_data": {}, + "no_sales_data_desc": "Data penjualan akan muncul di sini setelah transaksi dicatat", + "@no_sales_data_desc": {}, + "payment_methods": "Metode Pembayaran", + "@payment_methods": {}, + "payment_methods_desc": "Rincian pendapatan berdasarkan metode pembayaran ", + "@payment_methods_desc": {}, + "revenue_share": "Bagi Hasil", + "@revenue_share": {}, + "no_payment_methods": "Tidak Ada Metode Pembayaran", + "@no_payment_methods": {}, + "no_payment_methods_desc": "Data metode pembayaran akan muncul di sini setelah transaksi dilakukan", + "@no_payment_methods_desc": {}, + "best_selling_products": "Produk Terlaris", + "@best_selling_products": {}, + "highest_sales_ranking": "Ranking penjualan tertinggi", + "@highest_sales_ranking": {}, + "best_seller": "Penjual Terbaik", + "@best_seller": {}, + "top_performer": "Berkinerja Terbaik", + "@top_performer": {}, + "account_information": "Informasi Akun", + "@account_information": {}, + "member_since": "Member Sejak", + "@member_since": {}, + "edit_profile": "Ubah Profil", + "@edit_profile": {}, + "edit_profile_desc": "Update informasi profil Anda", + "@edit_profile_desc": {}, + "change_password": "Ubah Kata Sandi", + "@change_password": {}, + "change_password_desc": "Update kata sandi Anda", + "@change_password_desc": {}, + "business_settings": "Pengaturan Bisnis", + "@business_settings": {}, + "outlet_information": "Informasi Outlet", + "@outlet_information": {}, + "outlet_informatio_desc": "Kelola informasi outlet Anda", + "@outlet_informatio_desc": {}, + "staff_management": "Manajemen Staff", + "@staff_management": {}, + "staff_management_desc": "Kelola staff Anda", + "@staff_management_desc": {}, + "manage_your_products": "Kelola Produk Anda", + "@manage_your_products": {}, + "download_report": "Unduh Laporan", + "@download_report": {}, + "download_report_desc": "Unduh laporan penjualan atau stok", + "@download_report_desc": {}, + "app_settings": "Pengaturan Aplikasi", + "@app_settings": {}, + "language_desc": "Pilih bahasa aplikasi Anda", + "@language_desc": {}, + "support": "Dukungan", + "@support": {}, + "help_center": "Pusat Bantuan", + "@help_center": {}, + "help_center_desc": "Hubungi tim dukungan kami", + "@help_center_desc": {}, + "about": "Tentang", + "@about": {}, + "about_desc": "Tentang Aplikasi", + "@about_desc": {}, + "logout": "Keluar", + "@logout": {}, + "logout_desc": "Keluar dari akun Anda", + "@logout_desc": {}, + "save": "Simpan", + "@save": {}, + "name": "Nama", + "@name": {}, + "name_placeholder": "Masukkan nama Anda", + "@name_placeholder": {}, + "password_changed": "Kata Sandi Berubah", + "@password_changed": {}, + "current_password": "Kata Sandi Saat Ini", + "@current_password": {}, + "current_password_placeholder": "Masukkan kata sandi saat ini", + "@current_password_placeholder": {}, + "new_password": "Kata Sandi Baru", + "@new_password": {}, + "new_password_placeholder": "Masukkan kata sandi baru", + "@new_password_placeholder": {}, + "new_password_not_same": "Kata Sandi Baru Tidak Sama Dengan Kata Sandi Saat Ini", + "@new_password_not_same": {}, + "general_information": "Informasi Umum", + "@general_information": {}, + "address": "Alamat", + "@address": {}, + "phone_number": "Nomor Telepon", + "@phone_number": {}, + "currency": "Mata Uang", + "@currency": {}, + "tax_rate": "Tarif Pajak", + "@tax_rate": {}, + "status_text": "Status", + "@status_text": {}, + "coming_soon": "Segera Hadir", + "@coming_soon": {}, + "coming_soon_desc": "Sesuatu yang menakjubkan sedang terjadi!\nNantikan pengungkapan besarnya.", + "@coming_soon_desc": {}, + "transaction_report": "Laporan Transaksi", + "@transaction_report": {}, + "transaction_report_desc": "Ekspor semua data transaksi dengan analitik terperinci", + "@transaction_report_desc": {}, + "invetory_report": "Laporan Inventaris", + "@invetory_report": {}, + "invetory_report_desc": "Ekspor inventaris dan data stok dengan tren", + "@invetory_report_desc": {}, + "about_app": "Tentang Aplikasi", + "@about_app": {}, + "app_information": "Informasi Aplikasi", + "@app_information": {}, + "app_name": "Nama Aplikasi", + "@app_name": {}, + "build_number": "Nomor Build", + "@build_number": {}, + "package_name": "Nama Paket", + "@package_name": {}, + "device": "Perangkat", + "@device": {} } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index c03e6a4..2dd685d 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -244,6 +244,1062 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Sales today'** String get sales_today; + + /// No description provided for @order. + /// + /// In en, this message translates to: + /// **'Order'** + String get order; + + /// No description provided for @sales. + /// + /// In en, this message translates to: + /// **'Sales'** + String get sales; + + /// No description provided for @finance. + /// + /// In en, this message translates to: + /// **'Finance'** + String get finance; + + /// No description provided for @product. + /// + /// In en, this message translates to: + /// **'Product'** + String get product; + + /// No description provided for @form. + /// + /// In en, this message translates to: + /// **'Form'** + String get form; + + /// No description provided for @schedule. + /// + /// In en, this message translates to: + /// **'Schedule'** + String get schedule; + + /// No description provided for @inventory. + /// + /// In en, this message translates to: + /// **'Inventory'** + String get inventory; + + /// No description provided for @customer. + /// + /// In en, this message translates to: + /// **'Customer'** + String get customer; + + /// No description provided for @purchase. + /// + /// In en, this message translates to: + /// **'Purchase'** + String get purchase; + + /// No description provided for @today_summary. + /// + /// In en, this message translates to: + /// **'Today\'s Summary'** + String get today_summary; + + /// No description provided for @today. + /// + /// In en, this message translates to: + /// **'Today'** + String get today; + + /// No description provided for @new_customer. + /// + /// In en, this message translates to: + /// **'New Customer'** + String get new_customer; + + /// No description provided for @refund. + /// + /// In en, this message translates to: + /// **'Refund'** + String get refund; + + /// No description provided for @void_text. + /// + /// In en, this message translates to: + /// **'Void'** + String get void_text; + + /// No description provided for @increase. + /// + /// In en, this message translates to: + /// **'Increase'** + String get increase; + + /// No description provided for @today_top_product. + /// + /// In en, this message translates to: + /// **'Today\'s Top Product'** + String get today_top_product; + + /// No description provided for @rank. + /// + /// In en, this message translates to: + /// **'Rank'** + String get rank; + + /// No description provided for @quantity_sold. + /// + /// In en, this message translates to: + /// **'Quantity Sold'** + String get quantity_sold; + + /// No description provided for @total_orders. + /// + /// In en, this message translates to: + /// **'Total Orders'** + String get total_orders; + + /// No description provided for @average_price. + /// + /// In en, this message translates to: + /// **'Average Price'** + String get average_price; + + /// No description provided for @perfomance. + /// + /// In en, this message translates to: + /// **'Performance'** + String get perfomance; + + /// No description provided for @total_sales. + /// + /// In en, this message translates to: + /// **'Total Sales'** + String get total_sales; + + /// No description provided for @total_items. + /// + /// In en, this message translates to: + /// **'Total Items'** + String get total_items; + + /// No description provided for @summary. + /// + /// In en, this message translates to: + /// **'Summary'** + String get summary; + + /// No description provided for @net_sales. + /// + /// In en, this message translates to: + /// **'Net Sales'** + String get net_sales; + + /// No description provided for @daily_breakdown. + /// + /// In en, this message translates to: + /// **'Daily Breakdown'** + String get daily_breakdown; + + /// No description provided for @orders. + /// + /// In en, this message translates to: + /// **'Orders'** + String get orders; + + /// No description provided for @items. + /// + /// In en, this message translates to: + /// **'Items'** + String get items; + + /// No description provided for @tax. + /// + /// In en, this message translates to: + /// **'Tax'** + String get tax; + + /// No description provided for @discount. + /// + /// In en, this message translates to: + /// **'Discount'** + String get discount; + + /// No description provided for @total_purchase. + /// + /// In en, this message translates to: + /// **'Total Purchase'** + String get total_purchase; + + /// No description provided for @pending_order. + /// + /// In en, this message translates to: + /// **'Pending Order'** + String get pending_order; + + /// No description provided for @history_purchase. + /// + /// In en, this message translates to: + /// **'History Purchase'** + String get history_purchase; + + /// No description provided for @all. + /// + /// In en, this message translates to: + /// **'All'** + String get all; + + /// No description provided for @select_date_range. + /// + /// In en, this message translates to: + /// **'Select Date Range'** + String get select_date_range; + + /// No description provided for @no_date_selected. + /// + /// In en, this message translates to: + /// **'No date has been selected yet'** + String get no_date_selected; + + /// No description provided for @selected_date. + /// + /// In en, this message translates to: + /// **'Selected Date'** + String get selected_date; + + /// No description provided for @select. + /// + /// In en, this message translates to: + /// **'Select'** + String get select; + + /// No description provided for @cancel. + /// + /// In en, this message translates to: + /// **'Cancel'** + String get cancel; + + /// No description provided for @total_revenue. + /// + /// In en, this message translates to: + /// **'Total Revenue'** + String get total_revenue; + + /// No description provided for @total_expenditures. + /// + /// In en, this message translates to: + /// **'Total Expenditures'** + String get total_expenditures; + + /// No description provided for @net_profit. + /// + /// In en, this message translates to: + /// **'Net Profit'** + String get net_profit; + + /// No description provided for @margin_profit. + /// + /// In en, this message translates to: + /// **'Margin Profit'** + String get margin_profit; + + /// No description provided for @cash_flow_analysis. + /// + /// In en, this message translates to: + /// **'Cash Flow Analysis'** + String get cash_flow_analysis; + + /// No description provided for @cash_in. + /// + /// In en, this message translates to: + /// **'Cash In'** + String get cash_in; + + /// No description provided for @cash_out. + /// + /// In en, this message translates to: + /// **'Cash Out'** + String get cash_out; + + /// No description provided for @net_flow. + /// + /// In en, this message translates to: + /// **'Net Flow'** + String get net_flow; + + /// No description provided for @cash_flow_chart. + /// + /// In en, this message translates to: + /// **'Cash Flow Chart for {days} Last Days'** + String cash_flow_chart(int days); + + /// No description provided for @profit_loss_detail. + /// + /// In en, this message translates to: + /// **'Profit & Loss Details'** + String get profit_loss_detail; + + /// No description provided for @gross_sales. + /// + /// In en, this message translates to: + /// **'Gross Sales'** + String get gross_sales; + + /// No description provided for @return_text. + /// + /// In en, this message translates to: + /// **'Return'** + String get return_text; + + /// No description provided for @cogs. + /// + /// In en, this message translates to: + /// **'COGS'** + String get cogs; + + /// No description provided for @cost_of_goods_sold. + /// + /// In en, this message translates to: + /// **'Cost of goods sold'** + String get cost_of_goods_sold; + + /// No description provided for @gross_profit. + /// + /// In en, this message translates to: + /// **'Gross Profit'** + String get gross_profit; + + /// No description provided for @operating_costs. + /// + /// In en, this message translates to: + /// **'Operating Costs'** + String get operating_costs; + + /// No description provided for @sales_category. + /// + /// In en, this message translates to: + /// **'Sales Category'** + String get sales_category; + + /// No description provided for @unit. + /// + /// In en, this message translates to: + /// **'Unit'** + String get unit; + + /// No description provided for @category_no_data. + /// + /// In en, this message translates to: + /// **'There are no data categories yet'** + String get category_no_data; + + /// No description provided for @category_no_data_desc. + /// + /// In en, this message translates to: + /// **'Sales category data will appear here'** + String get category_no_data_desc; + + /// No description provided for @product_analytic. + /// + /// In en, this message translates to: + /// **'Product Analytic'** + String get product_analytic; + + /// No description provided for @view_all. + /// + /// In en, this message translates to: + /// **'View All'** + String get view_all; + + /// No description provided for @sold. + /// + /// In en, this message translates to: + /// **'Sold'** + String get sold; + + /// No description provided for @revenue. + /// + /// In en, this message translates to: + /// **'Revenue'** + String get revenue; + + /// No description provided for @cost. + /// + /// In en, this message translates to: + /// **'Cost'** + String get cost; + + /// No description provided for @profit_per_unit. + /// + /// In en, this message translates to: + /// **'Profit per unit'** + String get profit_per_unit; + + /// No description provided for @total_sold. + /// + /// In en, this message translates to: + /// **'Total Sold'** + String get total_sold; + + /// No description provided for @ingredients. + /// + /// In en, this message translates to: + /// **'Ingredients'** + String get ingredients; + + /// No description provided for @low_stock. + /// + /// In en, this message translates to: + /// **'Low Stock'** + String get low_stock; + + /// No description provided for @zero_stock. + /// + /// In en, this message translates to: + /// **'Zero Stock'** + String get zero_stock; + + /// No description provided for @stock. + /// + /// In en, this message translates to: + /// **'Stock'** + String get stock; + + /// No description provided for @price. + /// + /// In en, this message translates to: + /// **'Price'** + String get price; + + /// No description provided for @out_of_stock. + /// + /// In en, this message translates to: + /// **'Out of stock'** + String get out_of_stock; + + /// No description provided for @out_of_stock_desc. + /// + /// In en, this message translates to: + /// **'Product not available for sale'** + String get out_of_stock_desc; + + /// No description provided for @in_text. + /// + /// In en, this message translates to: + /// **'In'** + String get in_text; + + /// No description provided for @out_text. + /// + /// In en, this message translates to: + /// **'Out'** + String get out_text; + + /// No description provided for @available. + /// + /// In en, this message translates to: + /// **'Available'** + String get available; + + /// No description provided for @total_products. + /// + /// In en, this message translates to: + /// **'Total Products'** + String get total_products; + + /// No description provided for @total_ingredients. + /// + /// In en, this message translates to: + /// **'Total Ingredients'** + String get total_ingredients; + + /// No description provided for @products. + /// + /// In en, this message translates to: + /// **'Products'** + String get products; + + /// No description provided for @value_text. + /// + /// In en, this message translates to: + /// **'Value'** + String get value_text; + + /// No description provided for @low_stock_desc. + /// + /// In en, this message translates to: + /// **'Immediately reorder at least {stock} pcs'** + String low_stock_desc(String stock); + + /// No description provided for @joined. + /// + /// In en, this message translates to: + /// **'Joined'** + String get joined; + + /// No description provided for @ago. + /// + /// In en, this message translates to: + /// **'ago'** + String get ago; + + /// No description provided for @active. + /// + /// In en, this message translates to: + /// **'Active'** + String get active; + + /// No description provided for @inactive. + /// + /// In en, this message translates to: + /// **'Inactive'** + String get inactive; + + /// No description provided for @total_amount. + /// + /// In en, this message translates to: + /// **'Total Amount'** + String get total_amount; + + /// No description provided for @table. + /// + /// In en, this message translates to: + /// **'Table'** + String get table; + + /// No description provided for @remaining. + /// + /// In en, this message translates to: + /// **'Remaining'** + String get remaining; + + /// No description provided for @payment. + /// + /// In en, this message translates to: + /// **'Payment'** + String get payment; + + /// No description provided for @completed. + /// + /// In en, this message translates to: + /// **'Completed'** + String get completed; + + /// No description provided for @pending. + /// + /// In en, this message translates to: + /// **'Pending'** + String get pending; + + /// No description provided for @no_order_with_status. + /// + /// In en, this message translates to: + /// **'No {status} orders found'** + String no_order_with_status(String status); + + /// No description provided for @order_details. + /// + /// In en, this message translates to: + /// **'Order Details'** + String get order_details; + + /// No description provided for @order_number. + /// + /// In en, this message translates to: + /// **'Order Number'** + String get order_number; + + /// No description provided for @order_status. + /// + /// In en, this message translates to: + /// **'Order Status'** + String get order_status; + + /// No description provided for @order_information. + /// + /// In en, this message translates to: + /// **'Order Information'** + String get order_information; + + /// No description provided for @order_type. + /// + /// In en, this message translates to: + /// **'Order Type'** + String get order_type; + + /// No description provided for @payment_status. + /// + /// In en, this message translates to: + /// **'Payment Status'** + String get payment_status; + + /// No description provided for @created. + /// + /// In en, this message translates to: + /// **'Created'** + String get created; + + /// No description provided for @order_item. + /// + /// In en, this message translates to: + /// **'Order Item'** + String get order_item; + + /// No description provided for @item. + /// + /// In en, this message translates to: + /// **'Item'** + String get item; + + /// No description provided for @each. + /// + /// In en, this message translates to: + /// **'Each'** + String get each; + + /// No description provided for @total_item. + /// + /// In en, this message translates to: + /// **'Total Item'** + String get total_item; + + /// No description provided for @payment_summary. + /// + /// In en, this message translates to: + /// **'Payment Summary'** + String get payment_summary; + + /// No description provided for @subtotal. + /// + /// In en, this message translates to: + /// **'Subtotal'** + String get subtotal; + + /// No description provided for @paid. + /// + /// In en, this message translates to: + /// **'Paid'** + String get paid; + + /// No description provided for @total. + /// + /// In en, this message translates to: + /// **'Total'** + String get total; + + /// No description provided for @payment_method. + /// + /// In en, this message translates to: + /// **'Payment Method'** + String get payment_method; + + /// No description provided for @dine_in. + /// + /// In en, this message translates to: + /// **'Dine In'** + String get dine_in; + + /// No description provided for @dine_in_experience. + /// + /// In en, this message translates to: + /// **'Dine In Experience'** + String get dine_in_experience; + + /// No description provided for @note. + /// + /// In en, this message translates to: + /// **'Note'** + String get note; + + /// No description provided for @sales_chart. + /// + /// In en, this message translates to: + /// **'Sales Chart'** + String get sales_chart; + + /// No description provided for @no_data_available. + /// + /// In en, this message translates to: + /// **'No Data Avaiable'** + String get no_data_available; + + /// No description provided for @total_days_overview. + /// + /// In en, this message translates to: + /// **'{days} days overview'** + String total_days_overview(int days); + + /// No description provided for @sales_data. + /// + /// In en, this message translates to: + /// **'Sales Data'** + String get sales_data; + + /// No description provided for @no_sales_data. + /// + /// In en, this message translates to: + /// **'No Sales Data'** + String get no_sales_data; + + /// No description provided for @no_sales_data_desc. + /// + /// In en, this message translates to: + /// **'Sales data will appear here once transactions are recorded'** + String get no_sales_data_desc; + + /// No description provided for @payment_methods. + /// + /// In en, this message translates to: + /// **'Payment Methods'** + String get payment_methods; + + /// No description provided for @payment_methods_desc. + /// + /// In en, this message translates to: + /// **'Revenue breakdown by payment method '** + String get payment_methods_desc; + + /// No description provided for @revenue_share. + /// + /// In en, this message translates to: + /// **'Revenue Share'** + String get revenue_share; + + /// No description provided for @no_payment_methods. + /// + /// In en, this message translates to: + /// **'No Payment Methods'** + String get no_payment_methods; + + /// No description provided for @no_payment_methods_desc. + /// + /// In en, this message translates to: + /// **'Payment method data will appear here once transactions are made'** + String get no_payment_methods_desc; + + /// No description provided for @best_selling_products. + /// + /// In en, this message translates to: + /// **'Best Selling Products'** + String get best_selling_products; + + /// No description provided for @highest_sales_ranking. + /// + /// In en, this message translates to: + /// **'Highest sales ranking'** + String get highest_sales_ranking; + + /// No description provided for @best_seller. + /// + /// In en, this message translates to: + /// **'Best Seller'** + String get best_seller; + + /// No description provided for @top_performer. + /// + /// In en, this message translates to: + /// **'Top Performer'** + String get top_performer; + + /// No description provided for @account_information. + /// + /// In en, this message translates to: + /// **'Account Information'** + String get account_information; + + /// No description provided for @member_since. + /// + /// In en, this message translates to: + /// **'Member Since'** + String get member_since; + + /// No description provided for @edit_profile. + /// + /// In en, this message translates to: + /// **'Edit Profile'** + String get edit_profile; + + /// No description provided for @edit_profile_desc. + /// + /// In en, this message translates to: + /// **'Update your profile information'** + String get edit_profile_desc; + + /// No description provided for @change_password. + /// + /// In en, this message translates to: + /// **'Change Password'** + String get change_password; + + /// No description provided for @change_password_desc. + /// + /// In en, this message translates to: + /// **'Update your password'** + String get change_password_desc; + + /// No description provided for @business_settings. + /// + /// In en, this message translates to: + /// **'Business Settings'** + String get business_settings; + + /// No description provided for @outlet_information. + /// + /// In en, this message translates to: + /// **'Outlet Information'** + String get outlet_information; + + /// No description provided for @outlet_informatio_desc. + /// + /// In en, this message translates to: + /// **'Manage your outlet details'** + String get outlet_informatio_desc; + + /// No description provided for @staff_management. + /// + /// In en, this message translates to: + /// **'Staff Management'** + String get staff_management; + + /// No description provided for @staff_management_desc. + /// + /// In en, this message translates to: + /// **'Manage your staff'** + String get staff_management_desc; + + /// No description provided for @manage_your_products. + /// + /// In en, this message translates to: + /// **'Manage Your Products'** + String get manage_your_products; + + /// No description provided for @download_report. + /// + /// In en, this message translates to: + /// **'Download Report'** + String get download_report; + + /// No description provided for @download_report_desc. + /// + /// In en, this message translates to: + /// **'Download your sales report or inventory report'** + String get download_report_desc; + + /// No description provided for @app_settings. + /// + /// In en, this message translates to: + /// **'App Settings'** + String get app_settings; + + /// No description provided for @language_desc. + /// + /// In en, this message translates to: + /// **'Select your preferred language'** + String get language_desc; + + /// No description provided for @support. + /// + /// In en, this message translates to: + /// **'Support'** + String get support; + + /// No description provided for @help_center. + /// + /// In en, this message translates to: + /// **'Help Center'** + String get help_center; + + /// No description provided for @help_center_desc. + /// + /// In en, this message translates to: + /// **'Get help from our support team'** + String get help_center_desc; + + /// No description provided for @about. + /// + /// In en, this message translates to: + /// **'About'** + String get about; + + /// No description provided for @about_desc. + /// + /// In en, this message translates to: + /// **'Learn more about our app'** + String get about_desc; + + /// No description provided for @logout. + /// + /// In en, this message translates to: + /// **'Logout'** + String get logout; + + /// No description provided for @logout_desc. + /// + /// In en, this message translates to: + /// **'Logout of your account'** + String get logout_desc; + + /// No description provided for @save. + /// + /// In en, this message translates to: + /// **'Save'** + String get save; + + /// No description provided for @name. + /// + /// In en, this message translates to: + /// **'Name'** + String get name; + + /// No description provided for @name_placeholder. + /// + /// In en, this message translates to: + /// **'Please enter your name'** + String get name_placeholder; + + /// No description provided for @password_changed. + /// + /// In en, this message translates to: + /// **'Password Changed'** + String get password_changed; + + /// No description provided for @current_password. + /// + /// In en, this message translates to: + /// **'Current Password'** + String get current_password; + + /// No description provided for @current_password_placeholder. + /// + /// In en, this message translates to: + /// **'Please enter your current password'** + String get current_password_placeholder; + + /// No description provided for @new_password. + /// + /// In en, this message translates to: + /// **'New Password'** + String get new_password; + + /// No description provided for @new_password_placeholder. + /// + /// In en, this message translates to: + /// **'Please enter your new password'** + String get new_password_placeholder; + + /// No description provided for @new_password_not_same. + /// + /// In en, this message translates to: + /// **'New password cannot be same as current password'** + String get new_password_not_same; + + /// No description provided for @general_information. + /// + /// In en, this message translates to: + /// **'General Information'** + String get general_information; + + /// No description provided for @address. + /// + /// In en, this message translates to: + /// **'Address'** + String get address; + + /// No description provided for @phone_number. + /// + /// In en, this message translates to: + /// **'Phone Number'** + String get phone_number; + + /// No description provided for @currency. + /// + /// In en, this message translates to: + /// **'Currency'** + String get currency; + + /// No description provided for @tax_rate. + /// + /// In en, this message translates to: + /// **'Tax Rate'** + String get tax_rate; + + /// No description provided for @status_text. + /// + /// In en, this message translates to: + /// **'Status'** + String get status_text; + + /// No description provided for @coming_soon. + /// + /// In en, this message translates to: + /// **'Coming Soon'** + String get coming_soon; + + /// No description provided for @coming_soon_desc. + /// + /// In en, this message translates to: + /// **'Something amazing is brewing!\nStay tuned for the big reveal.'** + String get coming_soon_desc; + + /// No description provided for @transaction_report. + /// + /// In en, this message translates to: + /// **'Transaction Report'** + String get transaction_report; + + /// No description provided for @transaction_report_desc. + /// + /// In en, this message translates to: + /// **'Export all transaction data with detailed analytics'** + String get transaction_report_desc; + + /// No description provided for @invetory_report. + /// + /// In en, this message translates to: + /// **'Inventory Report'** + String get invetory_report; + + /// No description provided for @invetory_report_desc. + /// + /// In en, this message translates to: + /// **'Export inventory and stock data with trends'** + String get invetory_report_desc; + + /// No description provided for @about_app. + /// + /// In en, this message translates to: + /// **'About App'** + String get about_app; + + /// No description provided for @app_information. + /// + /// In en, this message translates to: + /// **'App Information'** + String get app_information; + + /// No description provided for @app_name. + /// + /// In en, this message translates to: + /// **'App Name'** + String get app_name; + + /// No description provided for @build_number. + /// + /// In en, this message translates to: + /// **'Build Number'** + String get build_number; + + /// No description provided for @package_name. + /// + /// In en, this message translates to: + /// **'Package Name'** + String get package_name; + + /// No description provided for @device. + /// + /// In en, this message translates to: + /// **'Device'** + String get device; } class _AppLocalizationsDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 07d2105..2883d3f 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -82,4 +82,540 @@ class AppLocalizationsEn extends AppLocalizations { @override String get sales_today => 'Sales today'; + + @override + String get order => 'Order'; + + @override + String get sales => 'Sales'; + + @override + String get finance => 'Finance'; + + @override + String get product => 'Product'; + + @override + String get form => 'Form'; + + @override + String get schedule => 'Schedule'; + + @override + String get inventory => 'Inventory'; + + @override + String get customer => 'Customer'; + + @override + String get purchase => 'Purchase'; + + @override + String get today_summary => 'Today\'s Summary'; + + @override + String get today => 'Today'; + + @override + String get new_customer => 'New Customer'; + + @override + String get refund => 'Refund'; + + @override + String get void_text => 'Void'; + + @override + String get increase => 'Increase'; + + @override + String get today_top_product => 'Today\'s Top Product'; + + @override + String get rank => 'Rank'; + + @override + String get quantity_sold => 'Quantity Sold'; + + @override + String get total_orders => 'Total Orders'; + + @override + String get average_price => 'Average Price'; + + @override + String get perfomance => 'Performance'; + + @override + String get total_sales => 'Total Sales'; + + @override + String get total_items => 'Total Items'; + + @override + String get summary => 'Summary'; + + @override + String get net_sales => 'Net Sales'; + + @override + String get daily_breakdown => 'Daily Breakdown'; + + @override + String get orders => 'Orders'; + + @override + String get items => 'Items'; + + @override + String get tax => 'Tax'; + + @override + String get discount => 'Discount'; + + @override + String get total_purchase => 'Total Purchase'; + + @override + String get pending_order => 'Pending Order'; + + @override + String get history_purchase => 'History Purchase'; + + @override + String get all => 'All'; + + @override + String get select_date_range => 'Select Date Range'; + + @override + String get no_date_selected => 'No date has been selected yet'; + + @override + String get selected_date => 'Selected Date'; + + @override + String get select => 'Select'; + + @override + String get cancel => 'Cancel'; + + @override + String get total_revenue => 'Total Revenue'; + + @override + String get total_expenditures => 'Total Expenditures'; + + @override + String get net_profit => 'Net Profit'; + + @override + String get margin_profit => 'Margin Profit'; + + @override + String get cash_flow_analysis => 'Cash Flow Analysis'; + + @override + String get cash_in => 'Cash In'; + + @override + String get cash_out => 'Cash Out'; + + @override + String get net_flow => 'Net Flow'; + + @override + String cash_flow_chart(int days) { + return 'Cash Flow Chart for $days Last Days'; + } + + @override + String get profit_loss_detail => 'Profit & Loss Details'; + + @override + String get gross_sales => 'Gross Sales'; + + @override + String get return_text => 'Return'; + + @override + String get cogs => 'COGS'; + + @override + String get cost_of_goods_sold => 'Cost of goods sold'; + + @override + String get gross_profit => 'Gross Profit'; + + @override + String get operating_costs => 'Operating Costs'; + + @override + String get sales_category => 'Sales Category'; + + @override + String get unit => 'Unit'; + + @override + String get category_no_data => 'There are no data categories yet'; + + @override + String get category_no_data_desc => 'Sales category data will appear here'; + + @override + String get product_analytic => 'Product Analytic'; + + @override + String get view_all => 'View All'; + + @override + String get sold => 'Sold'; + + @override + String get revenue => 'Revenue'; + + @override + String get cost => 'Cost'; + + @override + String get profit_per_unit => 'Profit per unit'; + + @override + String get total_sold => 'Total Sold'; + + @override + String get ingredients => 'Ingredients'; + + @override + String get low_stock => 'Low Stock'; + + @override + String get zero_stock => 'Zero Stock'; + + @override + String get stock => 'Stock'; + + @override + String get price => 'Price'; + + @override + String get out_of_stock => 'Out of stock'; + + @override + String get out_of_stock_desc => 'Product not available for sale'; + + @override + String get in_text => 'In'; + + @override + String get out_text => 'Out'; + + @override + String get available => 'Available'; + + @override + String get total_products => 'Total Products'; + + @override + String get total_ingredients => 'Total Ingredients'; + + @override + String get products => 'Products'; + + @override + String get value_text => 'Value'; + + @override + String low_stock_desc(String stock) { + return 'Immediately reorder at least $stock pcs'; + } + + @override + String get joined => 'Joined'; + + @override + String get ago => 'ago'; + + @override + String get active => 'Active'; + + @override + String get inactive => 'Inactive'; + + @override + String get total_amount => 'Total Amount'; + + @override + String get table => 'Table'; + + @override + String get remaining => 'Remaining'; + + @override + String get payment => 'Payment'; + + @override + String get completed => 'Completed'; + + @override + String get pending => 'Pending'; + + @override + String no_order_with_status(String status) { + return 'No $status orders found'; + } + + @override + String get order_details => 'Order Details'; + + @override + String get order_number => 'Order Number'; + + @override + String get order_status => 'Order Status'; + + @override + String get order_information => 'Order Information'; + + @override + String get order_type => 'Order Type'; + + @override + String get payment_status => 'Payment Status'; + + @override + String get created => 'Created'; + + @override + String get order_item => 'Order Item'; + + @override + String get item => 'Item'; + + @override + String get each => 'Each'; + + @override + String get total_item => 'Total Item'; + + @override + String get payment_summary => 'Payment Summary'; + + @override + String get subtotal => 'Subtotal'; + + @override + String get paid => 'Paid'; + + @override + String get total => 'Total'; + + @override + String get payment_method => 'Payment Method'; + + @override + String get dine_in => 'Dine In'; + + @override + String get dine_in_experience => 'Dine In Experience'; + + @override + String get note => 'Note'; + + @override + String get sales_chart => 'Sales Chart'; + + @override + String get no_data_available => 'No Data Avaiable'; + + @override + String total_days_overview(int days) { + return '$days days overview'; + } + + @override + String get sales_data => 'Sales Data'; + + @override + String get no_sales_data => 'No Sales Data'; + + @override + String get no_sales_data_desc => 'Sales data will appear here once transactions are recorded'; + + @override + String get payment_methods => 'Payment Methods'; + + @override + String get payment_methods_desc => 'Revenue breakdown by payment method '; + + @override + String get revenue_share => 'Revenue Share'; + + @override + String get no_payment_methods => 'No Payment Methods'; + + @override + String get no_payment_methods_desc => 'Payment method data will appear here once transactions are made'; + + @override + String get best_selling_products => 'Best Selling Products'; + + @override + String get highest_sales_ranking => 'Highest sales ranking'; + + @override + String get best_seller => 'Best Seller'; + + @override + String get top_performer => 'Top Performer'; + + @override + String get account_information => 'Account Information'; + + @override + String get member_since => 'Member Since'; + + @override + String get edit_profile => 'Edit Profile'; + + @override + String get edit_profile_desc => 'Update your profile information'; + + @override + String get change_password => 'Change Password'; + + @override + String get change_password_desc => 'Update your password'; + + @override + String get business_settings => 'Business Settings'; + + @override + String get outlet_information => 'Outlet Information'; + + @override + String get outlet_informatio_desc => 'Manage your outlet details'; + + @override + String get staff_management => 'Staff Management'; + + @override + String get staff_management_desc => 'Manage your staff'; + + @override + String get manage_your_products => 'Manage Your Products'; + + @override + String get download_report => 'Download Report'; + + @override + String get download_report_desc => 'Download your sales report or inventory report'; + + @override + String get app_settings => 'App Settings'; + + @override + String get language_desc => 'Select your preferred language'; + + @override + String get support => 'Support'; + + @override + String get help_center => 'Help Center'; + + @override + String get help_center_desc => 'Get help from our support team'; + + @override + String get about => 'About'; + + @override + String get about_desc => 'Learn more about our app'; + + @override + String get logout => 'Logout'; + + @override + String get logout_desc => 'Logout of your account'; + + @override + String get save => 'Save'; + + @override + String get name => 'Name'; + + @override + String get name_placeholder => 'Please enter your name'; + + @override + String get password_changed => 'Password Changed'; + + @override + String get current_password => 'Current Password'; + + @override + String get current_password_placeholder => 'Please enter your current password'; + + @override + String get new_password => 'New Password'; + + @override + String get new_password_placeholder => 'Please enter your new password'; + + @override + String get new_password_not_same => 'New password cannot be same as current password'; + + @override + String get general_information => 'General Information'; + + @override + String get address => 'Address'; + + @override + String get phone_number => 'Phone Number'; + + @override + String get currency => 'Currency'; + + @override + String get tax_rate => 'Tax Rate'; + + @override + String get status_text => 'Status'; + + @override + String get coming_soon => 'Coming Soon'; + + @override + String get coming_soon_desc => 'Something amazing is brewing!\nStay tuned for the big reveal.'; + + @override + String get transaction_report => 'Transaction Report'; + + @override + String get transaction_report_desc => 'Export all transaction data with detailed analytics'; + + @override + String get invetory_report => 'Inventory Report'; + + @override + String get invetory_report_desc => 'Export inventory and stock data with trends'; + + @override + String get about_app => 'About App'; + + @override + String get app_information => 'App Information'; + + @override + String get app_name => 'App Name'; + + @override + String get build_number => 'Build Number'; + + @override + String get package_name => 'Package Name'; + + @override + String get device => 'Device'; } diff --git a/lib/l10n/app_localizations_id.dart b/lib/l10n/app_localizations_id.dart index fd09556..bf1b641 100644 --- a/lib/l10n/app_localizations_id.dart +++ b/lib/l10n/app_localizations_id.dart @@ -82,4 +82,540 @@ class AppLocalizationsId extends AppLocalizations { @override String get sales_today => 'Penjualan hari ini'; + + @override + String get order => 'Pesanan'; + + @override + String get sales => 'Penjualan'; + + @override + String get finance => 'Keuangan'; + + @override + String get product => 'Produk'; + + @override + String get form => 'Form'; + + @override + String get schedule => 'Jadwal'; + + @override + String get inventory => 'Inventaris'; + + @override + String get customer => 'Pelanggan'; + + @override + String get purchase => 'Pembelian'; + + @override + String get today_summary => 'Ringkasan Hari Ini'; + + @override + String get today => 'Hari ini'; + + @override + String get new_customer => 'Pelanggan baru'; + + @override + String get refund => 'Pengembalian dana'; + + @override + String get void_text => 'Dibatalkan'; + + @override + String get increase => 'Bertambah'; + + @override + String get today_top_product => 'Produk teratas hari ini'; + + @override + String get rank => 'Pangkat'; + + @override + String get quantity_sold => 'Kuantiti Terjual'; + + @override + String get total_orders => 'Jumlah Pesanan'; + + @override + String get average_price => 'Harga Rata-rata'; + + @override + String get perfomance => 'Performa'; + + @override + String get total_sales => 'Jumlah Penjualan'; + + @override + String get total_items => 'Jumlah Barang'; + + @override + String get summary => 'Ringkasan'; + + @override + String get net_sales => 'Penjualan Bersih'; + + @override + String get daily_breakdown => 'Perincian Harian'; + + @override + String get orders => 'Pesanan'; + + @override + String get items => 'Barang'; + + @override + String get tax => 'Pajak'; + + @override + String get discount => 'Diskon'; + + @override + String get total_purchase => 'Jumlah Pembelian'; + + @override + String get pending_order => 'Pesanan Menunggu'; + + @override + String get history_purchase => 'Riwayat Pembelian'; + + @override + String get all => 'Semua'; + + @override + String get select_date_range => 'Pilih Rentang Tanggal'; + + @override + String get no_date_selected => 'Belum ada tanggal dipilih'; + + @override + String get selected_date => 'Tanggal Terpilih'; + + @override + String get select => 'Pilih'; + + @override + String get cancel => 'Batal'; + + @override + String get total_revenue => 'Jumlah Pendapatan'; + + @override + String get total_expenditures => 'Jumlah Pengeluaran'; + + @override + String get net_profit => 'Keuntungan Bersih'; + + @override + String get margin_profit => 'Keuntungan Margin'; + + @override + String get cash_flow_analysis => 'Analisis Arus Kas'; + + @override + String get cash_in => 'Uang Masuk'; + + @override + String get cash_out => 'Uang Keluar'; + + @override + String get net_flow => 'Arus Bersih'; + + @override + String cash_flow_chart(int days) { + return 'Grafik Cash Flow \$$days Hari Terakhir'; + } + + @override + String get profit_loss_detail => 'Detail Untung & Rugi'; + + @override + String get gross_sales => 'Penjualan Kotor'; + + @override + String get return_text => 'Retur'; + + @override + String get cogs => 'HPP'; + + @override + String get cost_of_goods_sold => 'Harga Pokok Penjualan'; + + @override + String get gross_profit => 'Keuntungan Kotor'; + + @override + String get operating_costs => 'Biaya Operasional'; + + @override + String get sales_category => 'Kategori Penjualan'; + + @override + String get unit => 'Unit'; + + @override + String get category_no_data => 'Belum ada data kategori'; + + @override + String get category_no_data_desc => 'Data kategori penjualan akan muncul di sini'; + + @override + String get product_analytic => 'Analisis Produk'; + + @override + String get view_all => 'Lihat Semua'; + + @override + String get sold => 'Terjual'; + + @override + String get revenue => 'Pendapatan'; + + @override + String get cost => 'Biaya'; + + @override + String get profit_per_unit => 'Keuntungan per unit'; + + @override + String get total_sold => 'Jumlah Terjual'; + + @override + String get ingredients => 'Bahan Baku'; + + @override + String get low_stock => 'Stok Rendah'; + + @override + String get zero_stock => 'Stok Kosong'; + + @override + String get stock => 'Stok'; + + @override + String get price => 'Harga'; + + @override + String get out_of_stock => 'Stok habis'; + + @override + String get out_of_stock_desc => 'Produk tidak tersedia untuk dijual'; + + @override + String get in_text => 'Masuk'; + + @override + String get out_text => 'Keluar'; + + @override + String get available => 'Tersedia'; + + @override + String get total_products => 'Jumlah Produk'; + + @override + String get total_ingredients => 'Jumlah Bahan Baku'; + + @override + String get products => 'Produk'; + + @override + String get value_text => 'Nilai'; + + @override + String low_stock_desc(String stock) { + return 'Segera reorder minimal $stock pcs'; + } + + @override + String get joined => 'Bergabung'; + + @override + String get ago => 'lalu'; + + @override + String get active => 'Aktif'; + + @override + String get inactive => 'Tidak Aktif'; + + @override + String get total_amount => 'Jumlah Total'; + + @override + String get table => 'Meja'; + + @override + String get remaining => 'Sisa'; + + @override + String get payment => 'Pembayaran'; + + @override + String get completed => 'Selesai'; + + @override + String get pending => 'Menunggu'; + + @override + String no_order_with_status(String status) { + return 'Tidak ada pesanan $status yang ditemukan'; + } + + @override + String get order_details => 'Detail Pesanan'; + + @override + String get order_number => 'Nomor Pesanan'; + + @override + String get order_status => 'Status Pesanan'; + + @override + String get order_information => 'Informasi Pesanan'; + + @override + String get order_type => 'Tipe Pesanan'; + + @override + String get payment_status => 'Status Pembayaran'; + + @override + String get created => 'Dibuat'; + + @override + String get order_item => 'Item Pesanan'; + + @override + String get item => 'Item'; + + @override + String get each => 'Setiap'; + + @override + String get total_item => 'Jumlah Item'; + + @override + String get payment_summary => 'Ringkasan Pembayaran'; + + @override + String get subtotal => 'Subtotal'; + + @override + String get paid => 'Dibayar'; + + @override + String get total => 'Jumlah'; + + @override + String get payment_method => 'Metode Pembayaran'; + + @override + String get dine_in => 'Makan di Tempat'; + + @override + String get dine_in_experience => 'Pengalaman Bersantap Di Tempat'; + + @override + String get note => 'Catatan'; + + @override + String get sales_chart => 'Bagan Penjualan'; + + @override + String get no_data_available => 'Tidak Ada Data Tersedia'; + + @override + String total_days_overview(int days) { + return 'ikhtisar $days hari'; + } + + @override + String get sales_data => 'Data Penjualan'; + + @override + String get no_sales_data => 'Tidak ada data penjualan'; + + @override + String get no_sales_data_desc => 'Data penjualan akan muncul di sini setelah transaksi dicatat'; + + @override + String get payment_methods => 'Metode Pembayaran'; + + @override + String get payment_methods_desc => 'Rincian pendapatan berdasarkan metode pembayaran '; + + @override + String get revenue_share => 'Bagi Hasil'; + + @override + String get no_payment_methods => 'Tidak Ada Metode Pembayaran'; + + @override + String get no_payment_methods_desc => 'Data metode pembayaran akan muncul di sini setelah transaksi dilakukan'; + + @override + String get best_selling_products => 'Produk Terlaris'; + + @override + String get highest_sales_ranking => 'Ranking penjualan tertinggi'; + + @override + String get best_seller => 'Penjual Terbaik'; + + @override + String get top_performer => 'Berkinerja Terbaik'; + + @override + String get account_information => 'Informasi Akun'; + + @override + String get member_since => 'Member Sejak'; + + @override + String get edit_profile => 'Ubah Profil'; + + @override + String get edit_profile_desc => 'Update informasi profil Anda'; + + @override + String get change_password => 'Ubah Kata Sandi'; + + @override + String get change_password_desc => 'Update kata sandi Anda'; + + @override + String get business_settings => 'Pengaturan Bisnis'; + + @override + String get outlet_information => 'Informasi Outlet'; + + @override + String get outlet_informatio_desc => 'Kelola informasi outlet Anda'; + + @override + String get staff_management => 'Manajemen Staff'; + + @override + String get staff_management_desc => 'Kelola staff Anda'; + + @override + String get manage_your_products => 'Kelola Produk Anda'; + + @override + String get download_report => 'Unduh Laporan'; + + @override + String get download_report_desc => 'Unduh laporan penjualan atau stok'; + + @override + String get app_settings => 'Pengaturan Aplikasi'; + + @override + String get language_desc => 'Pilih bahasa aplikasi Anda'; + + @override + String get support => 'Dukungan'; + + @override + String get help_center => 'Pusat Bantuan'; + + @override + String get help_center_desc => 'Hubungi tim dukungan kami'; + + @override + String get about => 'Tentang'; + + @override + String get about_desc => 'Tentang Aplikasi'; + + @override + String get logout => 'Keluar'; + + @override + String get logout_desc => 'Keluar dari akun Anda'; + + @override + String get save => 'Simpan'; + + @override + String get name => 'Nama'; + + @override + String get name_placeholder => 'Masukkan nama Anda'; + + @override + String get password_changed => 'Kata Sandi Berubah'; + + @override + String get current_password => 'Kata Sandi Saat Ini'; + + @override + String get current_password_placeholder => 'Masukkan kata sandi saat ini'; + + @override + String get new_password => 'Kata Sandi Baru'; + + @override + String get new_password_placeholder => 'Masukkan kata sandi baru'; + + @override + String get new_password_not_same => 'Kata Sandi Baru Tidak Sama Dengan Kata Sandi Saat Ini'; + + @override + String get general_information => 'Informasi Umum'; + + @override + String get address => 'Alamat'; + + @override + String get phone_number => 'Nomor Telepon'; + + @override + String get currency => 'Mata Uang'; + + @override + String get tax_rate => 'Tarif Pajak'; + + @override + String get status_text => 'Status'; + + @override + String get coming_soon => 'Segera Hadir'; + + @override + String get coming_soon_desc => 'Sesuatu yang menakjubkan sedang terjadi!\nNantikan pengungkapan besarnya.'; + + @override + String get transaction_report => 'Laporan Transaksi'; + + @override + String get transaction_report_desc => 'Ekspor semua data transaksi dengan analitik terperinci'; + + @override + String get invetory_report => 'Laporan Inventaris'; + + @override + String get invetory_report_desc => 'Ekspor inventaris dan data stok dengan tren'; + + @override + String get about_app => 'Tentang Aplikasi'; + + @override + String get app_information => 'Informasi Aplikasi'; + + @override + String get app_name => 'Nama Aplikasi'; + + @override + String get build_number => 'Nomor Build'; + + @override + String get package_name => 'Nama Paket'; + + @override + String get device => 'Perangkat'; } diff --git a/lib/presentation/components/bottom_sheet/date_range_bottom_sheet.dart b/lib/presentation/components/bottom_sheet/date_range_bottom_sheet.dart index cb22eae..4db02b2 100644 --- a/lib/presentation/components/bottom_sheet/date_range_bottom_sheet.dart +++ b/lib/presentation/components/bottom_sheet/date_range_bottom_sheet.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datepicker/datepicker.dart'; +import '../../../common/extension/extension.dart'; + class DateRangePickerBottomSheet { static Future show({ required BuildContext context, @@ -9,8 +11,8 @@ class DateRangePickerBottomSheet { DateTime? initialEndDate, DateTime? minDate, DateTime? maxDate, - String confirmText = 'Pilih', - String cancelText = 'Batal', + String? confirmText, + String? cancelText, Color primaryColor = Colors.blue, Function(DateTime? startDate, DateTime? endDate)? onChanged, }) async { @@ -26,8 +28,8 @@ class DateRangePickerBottomSheet { initialEndDate: initialEndDate, minDate: minDate, maxDate: maxDate, - confirmText: confirmText, - cancelText: cancelText, + confirmText: confirmText ?? context.lang.select, + cancelText: cancelText ?? context.lang.cancel, primaryColor: primaryColor, onChanged: onChanged, ), @@ -104,7 +106,7 @@ class _DateRangePickerBottomSheetState return _formatDate(range.startDate!); } } - return 'Belum ada tanggal dipilih'; + return context.lang.no_date_selected; } String _formatDate(DateTime date) { @@ -187,7 +189,7 @@ class _DateRangePickerBottomSheetState crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Tanggal Terpilih:', + '${context.lang.selected_date}:', style: TextStyle( fontSize: 12, fontWeight: FontWeight.w500, diff --git a/lib/presentation/components/field/date_range_picker_field.dart b/lib/presentation/components/field/date_range_picker_field.dart index bf495f9..9450368 100644 --- a/lib/presentation/components/field/date_range_picker_field.dart +++ b/lib/presentation/components/field/date_range_picker_field.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datepicker/datepicker.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../bottom_sheet/date_range_bottom_sheet.dart'; @@ -22,7 +23,7 @@ class DateRangePickerField extends StatefulWidget { final double height; const DateRangePickerField({ - Key? key, + super.key, this.label, this.placeholder = 'Pilih rentang tanggal', this.startDate, @@ -38,7 +39,7 @@ class DateRangePickerField extends StatefulWidget { this.placeholderStyle, this.decoration, this.height = 52.0, - }) : super(key: key); + }); @override State createState() => _DateRangePickerFieldState(); @@ -83,7 +84,7 @@ class _DateRangePickerFieldState extends State { final result = await DateRangePickerBottomSheet.show( context: context, - title: widget.label ?? 'Pilih Rentang Tanggal', + title: widget.label ?? context.lang.select_date_range, initialStartDate: widget.startDate, initialEndDate: widget.endDate, minDate: widget.minDate, @@ -294,7 +295,7 @@ class _DateRangePickerFieldOutlinedState final result = await DateRangePickerBottomSheet.show( context: context, - title: widget.label ?? 'Pilih Rentang Tanggal', + title: widget.label ?? context.lang.select_date_range, initialStartDate: widget.startDate, initialEndDate: widget.endDate, minDate: widget.minDate, @@ -412,120 +413,3 @@ class _DateRangePickerFieldOutlinedState ); } } - -// Usage Example Widget -class DateRangePickerExample extends StatefulWidget { - @override - _DateRangePickerExampleState createState() => _DateRangePickerExampleState(); -} - -class _DateRangePickerExampleState extends State { - DateTime? _startDate; - DateTime? _endDate; - DateTime? _startDate2; - DateTime? _endDate2; - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text('Date Range Picker Example'), - backgroundColor: AppColor.primary, - foregroundColor: AppColor.white, - ), - body: Padding( - padding: const EdgeInsets.all(20), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Default Style', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColor.textPrimary, - ), - ), - const SizedBox(height: 16), - - DateRangePickerField( - label: 'Periode Laporan', - placeholder: 'Pilih tanggal mulai - selesai', - startDate: _startDate, - endDate: _endDate, - primaryColor: AppColor.primary, - onChanged: (start, end) { - setState(() { - _startDate = start; - _endDate = end; - }); - }, - ), - - const SizedBox(height: 32), - - Text( - 'Outlined Style', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: AppColor.textPrimary, - ), - ), - const SizedBox(height: 16), - - DateRangePickerFieldOutlined( - label: 'Rentang Waktu', - placeholder: 'Pilih rentang tanggal', - startDate: _startDate2, - endDate: _endDate2, - primaryColor: AppColor.secondary, - onChanged: (start, end) { - setState(() { - _startDate2 = start; - _endDate2 = end; - }); - }, - ), - - const SizedBox(height: 24), - - // Display selected dates - if (_startDate != null || - _endDate != null || - _startDate2 != null || - _endDate2 != null) - Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: AppColor.background, - borderRadius: BorderRadius.circular(8), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Selected Dates:', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - ), - ), - const SizedBox(height: 8), - if (_startDate != null) - Text( - 'Default: ${_startDate!} - ${_endDate ?? 'Not selected'}', - ), - if (_startDate2 != null) - Text( - 'Outlined: ${_startDate2!} - ${_endDate2 ?? 'Not selected'}', - ), - ], - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/presentation/pages/about_app/about_app_page.dart b/lib/presentation/pages/about_app/about_app_page.dart index b98252f..9b42104 100644 --- a/lib/presentation/pages/about_app/about_app_page.dart +++ b/lib/presentation/pages/about_app/about_app_page.dart @@ -3,7 +3,9 @@ import 'package:auto_route/auto_route.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; +import '../../components/assets/assets.gen.dart'; @RoutePage() class AboutAppPage extends StatefulWidget { @@ -107,7 +109,7 @@ class _AboutAppPageState extends State return Opacity( opacity: _fadeAnimation.value, child: Text( - 'Tentang Aplikasi', + context.lang.about_app, style: AppStyle.lg.copyWith( color: AppColor.white, fontWeight: FontWeight.bold, @@ -142,7 +144,7 @@ class _AboutAppPageState extends State height: 100, decoration: BoxDecoration( color: AppColor.white, - borderRadius: BorderRadius.circular(25), + borderRadius: BorderRadius.circular(8), boxShadow: [ BoxShadow( color: AppColor.black.withOpacity(0.2), @@ -151,10 +153,9 @@ class _AboutAppPageState extends State ), ], ), - child: Icon( - Icons.mobile_friendly, - size: 50, - color: AppColor.primary, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Assets.images.logo.image(), ), ), const SizedBox(height: 16), @@ -247,7 +248,7 @@ class _AboutAppPageState extends State ), const SizedBox(width: 16), Text( - 'Informasi Aplikasi', + context.lang.app_information, style: AppStyle.h6.copyWith( fontWeight: FontWeight.bold, color: AppColor.primary, @@ -256,18 +257,24 @@ class _AboutAppPageState extends State ], ), const SizedBox(height: 20), - _buildInfoRow('Nama Aplikasi', packageInfo?.appName ?? 'Loading...'), - _buildInfoRow('Versi', packageInfo?.version ?? 'Loading...'), _buildInfoRow( - 'Build Number', + context.lang.app_name, + packageInfo?.appName ?? 'Loading...', + ), + _buildInfoRow( + context.lang.version, + packageInfo?.version ?? 'Loading...', + ), + _buildInfoRow( + context.lang.build_number, packageInfo?.buildNumber ?? 'Loading...', ), _buildInfoRow( - 'Package Name', + context.lang.package_name, packageInfo?.packageName ?? 'Loading...', ), _buildInfoRow( - 'Device', + context.lang.device, deviceInfo.isEmpty ? 'Loading...' : deviceInfo, ), ], diff --git a/lib/presentation/pages/coming_soon/coming_soon_page.dart b/lib/presentation/pages/coming_soon/coming_soon_page.dart index 4215c2d..8e309b1 100644 --- a/lib/presentation/pages/coming_soon/coming_soon_page.dart +++ b/lib/presentation/pages/coming_soon/coming_soon_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:auto_route/auto_route.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; @RoutePage() @@ -114,7 +115,7 @@ class _ComingSoonPageState extends State child: SlideTransition( position: _slideAnimation, child: Text( - 'Coming Soon', + context.lang.coming_soon, style: AppStyle.h1.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.bold, @@ -134,7 +135,7 @@ class _ComingSoonPageState extends State child: SlideTransition( position: _slideAnimation, child: Text( - 'Something amazing is brewing!\nStay tuned for the big reveal.', + context.lang.coming_soon_desc, style: AppStyle.lg.copyWith( color: AppColor.textWhite.withOpacity(0.9), height: 1.5, diff --git a/lib/presentation/pages/customer/customer_page.dart b/lib/presentation/pages/customer/customer_page.dart index 9b63756..a1e4e5f 100644 --- a/lib/presentation/pages/customer/customer_page.dart +++ b/lib/presentation/pages/customer/customer_page.dart @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:line_icons/line_icons.dart'; import '../../../application/customer/customer_loader/customer_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../../../domain/customer/customer.dart'; import '../../../injection.dart'; @@ -31,7 +32,7 @@ class CustomerPage extends StatefulWidget implements AutoRouteWrapper { class _CustomerPageState extends State with TickerProviderStateMixin { final TextEditingController _searchController = TextEditingController(); - ScrollController _scrollController = ScrollController(); + final ScrollController _scrollController = ScrollController(); bool _isGridView = false; @override @@ -72,7 +73,7 @@ class _CustomerPageState extends State floating: false, pinned: true, backgroundColor: AppColor.primary, - flexibleSpace: CustomAppBar(title: 'Pelanggan'), + flexibleSpace: CustomAppBar(title: context.lang.customer), actions: [ ActionIconButton(onTap: () {}, icon: LineIcons.search), ], @@ -148,7 +149,7 @@ class _CustomerPageState extends State crossAxisCount: 2, crossAxisSpacing: 16, mainAxisSpacing: 16, - childAspectRatio: 0.8, + childAspectRatio: 0.65, ), delegate: SliverChildBuilderDelegate((context, index) { final customer = customers[index]; diff --git a/lib/presentation/pages/customer/widgets/customer_card.dart b/lib/presentation/pages/customer/widgets/customer_card.dart index e11fe96..cb512ae 100644 --- a/lib/presentation/pages/customer/widgets/customer_card.dart +++ b/lib/presentation/pages/customer/widgets/customer_card.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/customer/customer.dart'; import '../../../components/spacer/spacer.dart'; @@ -175,78 +176,6 @@ class CustomerCard extends StatelessWidget { const SpaceHeight(12), ], - // Status Badge - Container( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 6, - ), - decoration: BoxDecoration( - color: customer.isActive - ? AppColor.success.withOpacity(0.1) - : AppColor.error.withOpacity(0.1), - borderRadius: BorderRadius.circular(16), - border: Border.all( - color: customer.isActive - ? AppColor.success.withOpacity(0.3) - : AppColor.error.withOpacity(0.3), - width: 1, - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 8, - height: 8, - decoration: BoxDecoration( - color: customer.isActive - ? AppColor.success - : AppColor.error, - shape: BoxShape.circle, - ), - ), - const SpaceWidth(6), - Text( - customer.isActive ? 'Active' : 'Inactive', - style: AppStyle.sm.copyWith( - color: customer.isActive - ? AppColor.success - : AppColor.error, - fontWeight: FontWeight.w600, - ), - ), - ], - ), - ), - - // Additional info if available - if (customer.address.isNotEmpty) ...[ - const SpaceHeight(8), - Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon( - Icons.location_on_outlined, - size: 14, - color: AppColor.textSecondary, - ), - const SpaceWidth(4), - Flexible( - child: Text( - customer.address, - style: AppStyle.xs.copyWith( - color: AppColor.textSecondary, - ), - textAlign: TextAlign.center, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ], - // Metadata info if (customer.metadata.isNotEmpty && _hasRelevantMetadata()) ...[ const SpaceHeight(8), @@ -284,7 +213,7 @@ class CustomerCard extends StatelessWidget { if (customer.createdAt.isNotEmpty) ...[ const SpaceHeight(8), Text( - 'Joined ${_formatDate(customer.createdAt)}', + '${context.lang.joined} ${_formatDate(context, customer.createdAt)}', style: AppStyle.xs.copyWith(color: AppColor.textSecondary), textAlign: TextAlign.center, ), @@ -335,7 +264,7 @@ class CustomerCard extends StatelessWidget { return colors[index]; } - String _formatDate(String dateStr) { + String _formatDate(BuildContext context, String dateStr) { try { final date = DateTime.parse(dateStr); final now = DateTime.now(); @@ -346,13 +275,13 @@ class CustomerCard extends StatelessWidget { } else if (difference == 1) { return 'yesterday'; } else if (difference < 30) { - return '${difference}d ago'; + return '${difference}d ${context.lang.ago}'; } else if (difference < 365) { final months = (difference / 30).floor(); - return '${months}mo ago'; + return '${months}mo ${context.lang.ago}'; } else { final years = (difference / 365).floor(); - return '${years}y ago'; + return '${years}y ${context.lang.ago}'; } } catch (e) { return dateStr; diff --git a/lib/presentation/pages/customer/widgets/customer_tile.dart b/lib/presentation/pages/customer/widgets/customer_tile.dart index 414967e..eb7edd8 100644 --- a/lib/presentation/pages/customer/widgets/customer_tile.dart +++ b/lib/presentation/pages/customer/widgets/customer_tile.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/customer/customer.dart'; import '../../../components/spacer/spacer.dart'; @@ -245,7 +246,9 @@ class CustomerTile extends StatelessWidget { ), const SpaceWidth(6), Text( - customer.isActive ? 'Active' : 'Inactive', + customer.isActive + ? context.lang.active + : context.lang.inactive, style: AppStyle.sm.copyWith( color: customer.isActive ? AppColor.success @@ -260,7 +263,7 @@ class CustomerTile extends StatelessWidget { // Created date if (customer.createdAt.isNotEmpty) Text( - 'Joined ${_formatDate(customer.createdAt)}', + '${context.lang.joined} ${_formatDate(context, customer.createdAt)}', style: AppStyle.xs.copyWith( color: AppColor.textSecondary, ), @@ -326,7 +329,7 @@ class CustomerTile extends StatelessWidget { return colors[index]; } - String _formatDate(String dateStr) { + String _formatDate(BuildContext context, String dateStr) { try { final date = DateTime.parse(dateStr); final now = DateTime.now(); @@ -337,13 +340,13 @@ class CustomerTile extends StatelessWidget { } else if (difference == 1) { return 'yesterday'; } else if (difference < 30) { - return '${difference}d ago'; + return '${difference}d ${context.lang.ago}'; } else if (difference < 365) { final months = (difference / 30).floor(); - return '${months}mo ago'; + return '${months}mo ${context.lang.ago}'; } else { final years = (difference / 365).floor(); - return '${years}y ago'; + return '${years}y ${context.lang.ago}'; } } catch (e) { return dateStr; diff --git a/lib/presentation/pages/download/download_report_page.dart b/lib/presentation/pages/download/download_report_page.dart index 3e02303..cbafb74 100644 --- a/lib/presentation/pages/download/download_report_page.dart +++ b/lib/presentation/pages/download/download_report_page.dart @@ -113,7 +113,7 @@ class _DownloadReportPageState extends State pinned: true, elevation: 0, backgroundColor: AppColor.primary, - flexibleSpace: CustomAppBar(title: 'Download Report'), + flexibleSpace: CustomAppBar(title: context.lang.download_report), ), // Content @@ -134,9 +134,8 @@ class _DownloadReportPageState extends State >( builder: (context, state) { return _ReportOptionCard( - title: 'Transaction Report', - subtitle: - 'Export all transaction data with detailed analytics', + title: context.lang.transaction_report, + subtitle: context.lang.transaction_report_desc, icon: Icons.receipt_long_outlined, gradient: const [ AppColor.primary, @@ -205,9 +204,8 @@ class _DownloadReportPageState extends State BlocBuilder( builder: (context, state) { return _ReportOptionCard( - title: 'Inventory Report', - subtitle: - 'Export inventory and stock data with trends', + title: context.lang.invetory_report, + subtitle: context.lang.invetory_report_desc, icon: Icons.inventory_2_outlined, gradient: const [ AppColor.secondary, @@ -479,7 +477,7 @@ class _ReportOptionCardState extends State<_ReportOptionCard> crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Select Date Range', + context.lang.select_date_range, style: AppStyle.md.copyWith( color: AppColor.white, fontWeight: FontWeight.w600, @@ -489,7 +487,7 @@ class _ReportOptionCardState extends State<_ReportOptionCard> // Date Range Picker Field Style DateRangePickerField( - placeholder: 'Select date range', + placeholder: context.lang.select_date_range, startDate: widget.startDate, endDate: widget.endDate, onChanged: widget.onDateRangeChanged, @@ -542,7 +540,7 @@ class _ReportOptionCardState extends State<_ReportOptionCard> ), const SizedBox(width: 8), Text( - 'Download Report', + context.lang.download_report, style: AppStyle.md.copyWith( color: widget.gradient.first, fontWeight: FontWeight.bold, diff --git a/lib/presentation/pages/finance/finance_page.dart b/lib/presentation/pages/finance/finance_page.dart index aa9f981..63beb84 100644 --- a/lib/presentation/pages/finance/finance_page.dart +++ b/lib/presentation/pages/finance/finance_page.dart @@ -126,7 +126,7 @@ class _FinancePageState extends State pinned: true, backgroundColor: AppColor.primary, elevation: 0, - flexibleSpace: CustomAppBar(title: 'Keuangan'), + flexibleSpace: CustomAppBar(title: context.lang.finance), ), // Header dengan filter periode @@ -221,7 +221,7 @@ class _FinancePageState extends State children: [ Expanded( child: FinanceSummaryCard( - title: 'Total Pendapatan', + title: context.lang.total_revenue, amount: summary.totalRevenue.currencyFormatRp, icon: LineIcons.arrowUp, color: AppColor.success, @@ -231,7 +231,7 @@ class _FinancePageState extends State const SizedBox(width: 12), Expanded( child: FinanceSummaryCard( - title: 'Total Pengeluaran', + title: context.lang.total_expenditures, amount: summary.totalCost.currencyFormatRp, icon: LineIcons.arrowDown, color: AppColor.error, @@ -245,7 +245,7 @@ class _FinancePageState extends State children: [ Expanded( child: FinanceSummaryCard( - title: 'Keuntungan Bersih', + title: context.lang.net_profit, amount: summary.netProfit.currencyFormatRp, icon: LineIcons.lineChart, color: AppColor.info, @@ -255,7 +255,7 @@ class _FinancePageState extends State const SizedBox(width: 12), Expanded( child: FinanceSummaryCard( - title: 'Margin Profit', + title: context.lang.margin_profit, amount: '${summary.profitabilityRatio.round()}%', icon: LineIcons.percent, color: AppColor.warning, @@ -304,14 +304,14 @@ class _FinancePageState extends State ), const SizedBox(width: 12), Text( - 'Analisis Produk', + context.lang.product_analytic, style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), ), const Spacer(), TextButton( onPressed: () {}, child: Text( - 'Lihat Semua', + context.lang.view_all, style: AppStyle.sm.copyWith(color: AppColor.primary), ), ), diff --git a/lib/presentation/pages/finance/widgets/cash_flow.dart b/lib/presentation/pages/finance/widgets/cash_flow.dart index fa11cbb..fa6e0cd 100644 --- a/lib/presentation/pages/finance/widgets/cash_flow.dart +++ b/lib/presentation/pages/finance/widgets/cash_flow.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; import 'package:intl/intl.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/analytic/analytic.dart'; @@ -57,7 +58,7 @@ class FinanceCashFlow extends StatelessWidget { ), const SizedBox(width: 12), Text( - 'Analisis Cash Flow', + context.lang.cash_flow_analysis, style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), ), ], @@ -78,7 +79,7 @@ class FinanceCashFlow extends StatelessWidget { children: [ Expanded( child: _buildCashFlowIndicator( - 'Cash In', + context.lang.cash_in, _formatCurrency(totalCashIn), LineIcons.arrowUp, AppColor.success, @@ -87,7 +88,7 @@ class FinanceCashFlow extends StatelessWidget { const SizedBox(width: 16), Expanded( child: _buildCashFlowIndicator( - 'Cash Out', + context.lang.cash_out, _formatCurrency(totalCashOut), LineIcons.arrowDown, AppColor.error, @@ -96,7 +97,7 @@ class FinanceCashFlow extends StatelessWidget { const SizedBox(width: 16), Expanded( child: _buildCashFlowIndicator( - 'Net Flow', + context.lang.net_flow, _formatCurrency(netFlow), LineIcons.equals, AppColor.info, @@ -119,7 +120,7 @@ class FinanceCashFlow extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Grafik Cash Flow ${dailyData.length} Hari Terakhir', + context.lang.cash_flow_chart(dailyData.length), style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w600, @@ -136,11 +137,11 @@ class FinanceCashFlow extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - _buildChartLegend('Cash In', AppColor.success), + _buildChartLegend(context.lang.cash_in, AppColor.success), const SizedBox(width: 20), - _buildChartLegend('Cash Out', AppColor.error), + _buildChartLegend(context.lang.cash_out, AppColor.error), const SizedBox(width: 20), - _buildChartLegend('Net Flow', AppColor.info), + _buildChartLegend(context.lang.net_flow, AppColor.info), ], ), ], diff --git a/lib/presentation/pages/finance/widgets/category.dart b/lib/presentation/pages/finance/widgets/category.dart index 747ffba..df21ac6 100644 --- a/lib/presentation/pages/finance/widgets/category.dart +++ b/lib/presentation/pages/finance/widgets/category.dart @@ -51,7 +51,7 @@ class FinanceCategory extends StatelessWidget { ), const SizedBox(width: 12), Text( - 'Kategori Penjualan', + context.lang.sales_category, style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), ), ], @@ -60,10 +60,11 @@ class FinanceCategory extends StatelessWidget { // Show empty state if no categories if (categories.isEmpty) - _buildEmptyState() + _buildEmptyState(context) else ...sortedCategories.asMap().entries.map( (entry) => _buildCategoryItem( + context, entry.value, _calculatePercentage(entry.value.totalRevenue, totalRevenue), _getCategoryColor(entry.key), @@ -75,6 +76,7 @@ class FinanceCategory extends StatelessWidget { } Widget _buildCategoryItem( + BuildContext context, CategoryAnalyticItem category, double percentage, Color color, @@ -111,7 +113,7 @@ class FinanceCategory extends StatelessWidget { ), const SizedBox(height: 2), Text( - '${category.productCount} produk • ${category.orderCount} pesanan', + '${category.productCount} ${context.lang.product} • ${category.orderCount} ${context.lang.orders}', style: AppStyle.xs.copyWith( color: AppColor.textSecondary, ), @@ -134,7 +136,7 @@ class FinanceCategory extends StatelessWidget { ), ), Text( - '${NumberFormat('#,###', 'id_ID').format(category.totalQuantity)} unit', + '${NumberFormat('#,###', 'id_ID').format(category.totalQuantity)} ${context.lang.unit}', style: AppStyle.xs.copyWith(color: AppColor.textSecondary), ), ], @@ -161,10 +163,10 @@ class FinanceCategory extends StatelessWidget { ); } - Widget _buildEmptyState() { + Widget _buildEmptyState(BuildContext context) { return EmptyWidget( - title: 'Belum ada data kategori', - message: 'Data kategori penjualan akan muncul di sini', + title: context.lang.category_no_data, + message: context.lang.category_no_data_desc, ); } diff --git a/lib/presentation/pages/finance/widgets/product.dart b/lib/presentation/pages/finance/widgets/product.dart index d545d82..7f41843 100644 --- a/lib/presentation/pages/finance/widgets/product.dart +++ b/lib/presentation/pages/finance/widgets/product.dart @@ -81,21 +81,21 @@ class ProfitLossProduct extends StatelessWidget { children: [ Expanded( child: _buildMetricColumn( - 'Pendapatan', + context.lang.revenue, product.revenue.currencyFormatRp, AppColor.success, ), ), Expanded( child: _buildMetricColumn( - 'Biaya', + context.lang.cost, product.cost.currencyFormatRp, AppColor.error, ), ), Expanded( child: _buildMetricColumn( - 'Laba Kotor', + context.lang.gross_profit, product.grossProfit.currencyFormatRp, AppColor.info, ), @@ -109,14 +109,14 @@ class ProfitLossProduct extends StatelessWidget { children: [ Expanded( child: _buildMetricColumn( - 'Harga Rata-rata', + context.lang.average_price, product.averagePrice.currencyFormatRp, AppColor.textSecondary, ), ), Expanded( child: _buildMetricColumn( - 'Laba per Unit', + context.lang.profit_per_unit, product.profitPerUnit.currencyFormatRp, AppColor.primary, ), diff --git a/lib/presentation/pages/finance/widgets/profit_loss.dart b/lib/presentation/pages/finance/widgets/profit_loss.dart index 8692aba..929c04e 100644 --- a/lib/presentation/pages/finance/widgets/profit_loss.dart +++ b/lib/presentation/pages/finance/widgets/profit_loss.dart @@ -46,7 +46,7 @@ class FinanceProfitLoss extends StatelessWidget { ), const SizedBox(width: 12), Text( - 'Detail Profit & Loss', + context.lang.profit_loss_detail, style: AppStyle.lg.copyWith(fontWeight: FontWeight.bold), ), ], @@ -55,7 +55,7 @@ class FinanceProfitLoss extends StatelessWidget { // Total Revenue (Penjualan Kotor) _buildPLItem( - 'Penjualan Kotor', + context.lang.gross_sales, data.totalRevenue.currencyFormatRp, AppColor.success, true, @@ -63,7 +63,7 @@ class FinanceProfitLoss extends StatelessWidget { // Discount (Diskon & Retur) _buildPLItem( - 'Diskon & Retur', + '${context.lang.discount} & ${context.lang.return_text}', '- ${data.totalDiscount.currencyFormatRp}', AppColor.error, false, @@ -73,7 +73,7 @@ class FinanceProfitLoss extends StatelessWidget { // Net Sales (Penjualan Bersih = Total Revenue - Discount) _buildPLItem( - 'Penjualan Bersih', + context.lang.net_sales, (data.totalRevenue - data.totalDiscount).currencyFormatRp, AppColor.textPrimary, true, @@ -84,7 +84,7 @@ class FinanceProfitLoss extends StatelessWidget { // Cost of Goods Sold (HPP) _buildPLItem( - 'HPP (Harga Pokok Penjualan)', + '${context.lang.cogs} (${context.lang.cost_of_goods_sold})', '- ${data.totalCost.currencyFormatRp}', AppColor.error, false, @@ -94,7 +94,7 @@ class FinanceProfitLoss extends StatelessWidget { // Gross Profit (Laba Kotor) _buildPLItem( - 'Laba Kotor', + context.lang.gross_profit, data.grossProfit.currencyFormatRp, AppColor.success, true, @@ -107,7 +107,7 @@ class FinanceProfitLoss extends StatelessWidget { // Operational Cost (Biaya Operasional) - calculated as difference _buildPLItem( - 'Biaya Operasional', + context.lang.operating_costs, '- ${_calculateOperationalCost().currencyFormatRp}', AppColor.error, false, @@ -117,7 +117,7 @@ class FinanceProfitLoss extends StatelessWidget { // Net Profit (Laba Bersih) _buildPLItem( - 'Laba Bersih', + context.lang.net_profit, data.netProfit.currencyFormatRp, AppColor.primary, true, diff --git a/lib/presentation/pages/home/widgets/feature.dart b/lib/presentation/pages/home/widgets/feature.dart index e9057a6..8295f6b 100644 --- a/lib/presentation/pages/home/widgets/feature.dart +++ b/lib/presentation/pages/home/widgets/feature.dart @@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../router/app_router.gr.dart'; import 'feature_tile.dart'; @@ -36,25 +37,25 @@ class HomeFeature extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ HomeFeatureTile( - title: 'Penjualan', + title: context.lang.sales, color: const Color(0xFF4CAF50), icon: LineIcons.receipt, onTap: () => context.router.push(SalesRoute()), ), HomeFeatureTile( - title: 'Pembelian', + title: context.lang.purchase, color: const Color(0xFF2196F3), icon: LineIcons.shoppingCart, onTap: () => context.router.push(PurchaseRoute()), ), HomeFeatureTile( - title: 'Keuangan', + title: context.lang.finance, color: const Color(0xFF8BC34A), icon: LineIcons.moneyCheck, onTap: () => context.router.push(FinanceRoute()), ), HomeFeatureTile( - title: 'Produk', + title: context.lang.product, color: const Color(0xFFFF9800), icon: LineIcons.box, onTap: () => context.router.push(ProductAnalyticRoute()), @@ -66,25 +67,25 @@ class HomeFeature extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ HomeFeatureTile( - title: 'Form', + title: context.lang.form, color: const Color(0xFFE91E63), icon: LineIcons.fileAlt, onTap: () => context.router.push(DailyTasksFormRoute()), ), HomeFeatureTile( - title: 'Jadwal', + title: context.lang.schedule, color: const Color(0xFF9C27B0), icon: LineIcons.calendar, onTap: () => context.router.push(ScheduleRoute()), ), HomeFeatureTile( - title: 'Inventaris', + title: context.lang.inventory, color: const Color(0xFF00BCD4), icon: LineIcons.archive, onTap: () => context.router.push(InventoryRoute()), ), HomeFeatureTile( - title: 'Pelanggan', + title: context.lang.customer, color: const Color(0xFFFF5722), icon: LineIcons.userPlus, onTap: () => context.router.push(CustomerRoute()), diff --git a/lib/presentation/pages/home/widgets/stats.dart b/lib/presentation/pages/home/widgets/stats.dart index 6a1f612..1b91665 100644 --- a/lib/presentation/pages/home/widgets/stats.dart +++ b/lib/presentation/pages/home/widgets/stats.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/analytic/analytic.dart'; import '../../../components/spacer/spacer.dart'; @@ -21,30 +22,30 @@ class HomeStats extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - HomeTitle(title: 'Ringkasan Hari Ini'), + HomeTitle(title: context.lang.today_summary), const SpaceHeight(20), Row( children: [ Expanded( child: HomeStatsTile( - title: 'Pesanan', + title: context.lang.order, value: overview.totalOrders.toString(), icon: Icons.receipt_long_rounded, color: AppColor.info, - subtitle: 'Hari ini', + subtitle: context.lang.today, ), ), const SpaceWidth(16), Expanded( child: HomeStatsTile( - title: 'Pelanggan Baru', + title: context.lang.new_customer, value: overview.totalCustomers.toString(), icon: Icons.person_add_outlined, color: AppColor.primary, subtitle: overview.totalCustomers < 1 - ? 'Hari ini' - : 'bertambah', + ? context.lang.today + : context.lang.increase, ), ), ], @@ -54,21 +55,21 @@ class HomeStats extends StatelessWidget { children: [ Expanded( child: HomeStatsTile( - title: 'Refund', + title: context.lang.refund, value: overview.refundedOrders.toString(), icon: LineIcons.alternateExchange, color: AppColor.warning, - subtitle: 'Hari ini', + subtitle: context.lang.today, ), ), const SpaceWidth(16), Expanded( child: HomeStatsTile( - title: 'Void', + title: context.lang.void_text, value: overview.voidedOrders.toString(), icon: Icons.cancel_rounded, color: AppColor.error, - subtitle: 'Hari ini', + subtitle: context.lang.today, ), ), ], diff --git a/lib/presentation/pages/home/widgets/top_product.dart b/lib/presentation/pages/home/widgets/top_product.dart index 9e8f436..3500d3c 100644 --- a/lib/presentation/pages/home/widgets/top_product.dart +++ b/lib/presentation/pages/home/widgets/top_product.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/analytic/analytic.dart'; import '../../../components/spacer/spacer.dart'; @@ -19,12 +20,13 @@ class HomeTopProduct extends StatelessWidget { ).copyWith(bottom: 0), child: Column( children: [ - HomeTitle(title: 'Product Terlaris Hari Ini'), + HomeTitle(title: context.lang.today_top_product), SpaceHeight(20), ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: products.length, + padding: EdgeInsets.zero, itemBuilder: (context, index) { return HomeTopProductTile( product: products[index], diff --git a/lib/presentation/pages/home/widgets/top_product_tile.dart b/lib/presentation/pages/home/widgets/top_product_tile.dart index 841d68e..108163f 100644 --- a/lib/presentation/pages/home/widgets/top_product_tile.dart +++ b/lib/presentation/pages/home/widgets/top_product_tile.dart @@ -44,7 +44,7 @@ class HomeTopProductTile extends StatelessWidget { // Header Row - Ranking dan Revenue Row( children: [ - _buildRankingBadge(), + _buildRankingBadge(context), const Spacer(), _buildRevenueDisplay(), ], @@ -71,7 +71,7 @@ class HomeTopProductTile extends StatelessWidget { const SizedBox(height: 12), // Metrics dalam Grid 2x2 - _buildMetricsGrid(), + _buildMetricsGrid(context), ], ), ), @@ -80,7 +80,7 @@ class HomeTopProductTile extends StatelessWidget { ); } - Widget _buildRankingBadge() { + Widget _buildRankingBadge(BuildContext context) { Color badgeColor; IconData icon; @@ -115,7 +115,7 @@ class HomeTopProductTile extends StatelessWidget { Icon(icon, color: badgeColor, size: 16), const SizedBox(width: 6), Text( - 'Rank #$ranking', + '${context.lang.rank} #$ranking', style: AppStyle.sm.copyWith( color: badgeColor, fontWeight: FontWeight.bold, @@ -157,7 +157,7 @@ class HomeTopProductTile extends StatelessWidget { ); } - Widget _buildMetricsGrid() { + Widget _buildMetricsGrid(BuildContext context) { return Row( children: [ Expanded( @@ -165,14 +165,14 @@ class HomeTopProductTile extends StatelessWidget { children: [ _buildMetricCard( icon: Icons.shopping_cart_outlined, - label: 'Quantity Sold', + label: context.lang.quantity_sold, value: product.quantitySold.toString(), color: AppColor.info, ), const SizedBox(height: 8), _buildMetricCard( icon: Icons.attach_money, - label: 'Average Price', + label: context.lang.average_price, value: product.averagePrice.round().currencyFormatRp, color: AppColor.success, ), @@ -185,14 +185,14 @@ class HomeTopProductTile extends StatelessWidget { children: [ _buildMetricCard( icon: Icons.receipt_outlined, - label: 'Total Orders', + label: context.lang.total_orders, value: product.orderCount.toString(), color: AppColor.warning, ), const SizedBox(height: 8), _buildMetricCard( icon: Icons.trending_up, - label: 'Performance', + label: context.lang.perfomance, value: 'Top $ranking', color: AppColor.primary, ), diff --git a/lib/presentation/pages/inventory/inventory_page.dart b/lib/presentation/pages/inventory/inventory_page.dart index c864417..ce2a57c 100644 --- a/lib/presentation/pages/inventory/inventory_page.dart +++ b/lib/presentation/pages/inventory/inventory_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../application/analytic/inventory_analytic_loader/inventory_analytic_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../../../domain/analytic/analytic.dart'; import '../../../injection.dart'; @@ -95,11 +96,11 @@ class _InventoryPageState extends State String getStatusText(String status) { switch (status) { case 'available': - return 'Tersedia'; + return context.lang.available; case 'low_stock': - return 'Stok Rendah'; + return context.lang.low_stock; case 'out_of_stock': - return 'Habis'; + return context.lang.out_of_stock; default: return 'Unknown'; } @@ -189,7 +190,7 @@ class _InventoryPageState extends State padding: const EdgeInsets.symmetric( horizontal: 12, ), - child: const Row( + child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, @@ -199,7 +200,7 @@ class _InventoryPageState extends State size: 16, ), SizedBox(width: 6), - Text('Produk'), + Text(context.lang.product), ], ), ), @@ -210,7 +211,7 @@ class _InventoryPageState extends State padding: const EdgeInsets.symmetric( horizontal: 12, ), - child: const Row( + child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.center, @@ -220,7 +221,7 @@ class _InventoryPageState extends State size: 16, ), SizedBox(width: 6), - Text('Bahan'), + Text(context.lang.ingredients), ], ), ), @@ -254,7 +255,7 @@ class _InventoryPageState extends State pinned: true, elevation: 0, backgroundColor: AppColor.primary, - flexibleSpace: CustomAppBar(title: 'Inventaris'), + flexibleSpace: CustomAppBar(title: context.lang.inventory), ); } @@ -308,7 +309,7 @@ class _InventoryPageState extends State children: [ Expanded( child: _buildStatCard( - 'Total Produk', + context.lang.total_products, inventory.totalProducts.toString(), Icons.inventory_2_rounded, AppColor.primary, @@ -317,7 +318,7 @@ class _InventoryPageState extends State const SizedBox(width: 16), Expanded( child: _buildStatCard( - 'Produk Terjual', + context.lang.total_sold, inventory.totalSoldProducts.toString(), Icons.check_circle_rounded, AppColor.success, @@ -330,7 +331,7 @@ class _InventoryPageState extends State children: [ Expanded( child: _buildStatCard( - 'Stok Rendah', + context.lang.low_stock, inventory.lowStockProducts.toString(), Icons.warning_rounded, AppColor.warning, @@ -339,7 +340,7 @@ class _InventoryPageState extends State const SizedBox(width: 16), Expanded( child: _buildStatCard( - 'Stok Kosong', + context.lang.zero_stock, inventory.zeroStockProducts.toString(), Icons.error_rounded, AppColor.error, @@ -361,7 +362,7 @@ class _InventoryPageState extends State children: [ Expanded( child: _buildStatCard( - 'Total Bahan', + context.lang.total_ingredients, inventory.totalIngredients.toString(), Icons.restaurant_menu_rounded, AppColor.primary, @@ -370,7 +371,7 @@ class _InventoryPageState extends State const SizedBox(width: 16), Expanded( child: _buildStatCard( - 'Bahan Terjual', + context.lang.total_sold, inventory.totalSoldIngredients.toString(), Icons.check_circle_rounded, AppColor.success, @@ -383,7 +384,7 @@ class _InventoryPageState extends State children: [ Expanded( child: _buildStatCard( - 'Stok Kurang', + context.lang.low_stock, inventory.lowStockIngredients.toString(), Icons.warning_rounded, AppColor.warning, @@ -392,7 +393,7 @@ class _InventoryPageState extends State const SizedBox(width: 16), Expanded( child: _buildStatCard( - 'Habis', + context.lang.zero_stock, inventory.zeroStockIngredients.toString(), Icons.error_rounded, AppColor.error, diff --git a/lib/presentation/pages/inventory/widgets/product_tile.dart b/lib/presentation/pages/inventory/widgets/product_tile.dart index fe3a1e7..916fcf9 100644 --- a/lib/presentation/pages/inventory/widgets/product_tile.dart +++ b/lib/presentation/pages/inventory/widgets/product_tile.dart @@ -182,7 +182,11 @@ class InventoryProductTile extends StatelessWidget { ], ), child: Text( - _getStatusText(), + item.isZeroStock + ? context.lang.out_of_stock + : item.isLowStock + ? context.lang.low_stock + : context.lang.available, style: AppStyle.xs.copyWith( fontSize: 10, fontWeight: FontWeight.w700, @@ -202,7 +206,7 @@ class InventoryProductTile extends StatelessWidget { Expanded( child: _buildInfoItem( LineIcons.boxes, - 'Stok', + context.lang.stock, '${NumberFormat('#,###', 'id_ID').format(item.quantity)} pcs', _getQuantityColor(), ), @@ -212,7 +216,7 @@ class InventoryProductTile extends StatelessWidget { Expanded( child: _buildInfoItem( LineIcons.dollarSign, - 'Nilai', + context.lang.value_text, _formatCurrencyShort(item.totalValue), AppColor.info, ), @@ -259,14 +263,19 @@ class InventoryProductTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Stok Menipis', + context.lang.low_stock, style: AppStyle.sm.copyWith( fontWeight: FontWeight.w600, color: AppColor.warning, ), ), Text( - 'Segera reorder minimal ${NumberFormat('#,###', 'id_ID').format(item.reorderLevel)} pcs', + context.lang.low_stock_desc( + NumberFormat( + '#,###', + 'id_ID', + ).format(item.reorderLevel), + ), style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -301,14 +310,14 @@ class InventoryProductTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Stok Habis', + context.lang.out_of_stock, style: AppStyle.sm.copyWith( fontWeight: FontWeight.w600, color: AppColor.error, ), ), Text( - 'Produk tidak tersedia untuk dijual', + context.lang.out_of_stock_desc, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -330,7 +339,7 @@ class InventoryProductTile extends StatelessWidget { Expanded( child: _buildMovementInfo( LineIcons.arrowUp, - 'Masuk', + context.lang.in_text, '${NumberFormat('#,###', 'id_ID').format(item.totalIn)} pcs', AppColor.success, ), @@ -341,7 +350,7 @@ class InventoryProductTile extends StatelessWidget { Expanded( child: _buildMovementInfo( LineIcons.arrowDown, - 'Keluar', + context.lang.out_text, '${NumberFormat('#,###', 'id_ID').format(item.totalOut)} pcs', AppColor.error, ), @@ -476,12 +485,6 @@ class InventoryProductTile extends StatelessWidget { return AppColor.textPrimary; } - String _getStatusText() { - if (item.isZeroStock) return 'HABIS'; - if (item.isLowStock) return 'MINIM'; - return 'TERSEDIA'; - } - IconData _getCategoryIcon() { final category = item.categoryName.toLowerCase(); if (category.contains('elektronik') || category.contains('gadget')) { diff --git a/lib/presentation/pages/main/widgets/bottom_navbar.dart b/lib/presentation/pages/main/widgets/bottom_navbar.dart index 8ea33ff..3876d5c 100644 --- a/lib/presentation/pages/main/widgets/bottom_navbar.dart +++ b/lib/presentation/pages/main/widgets/bottom_navbar.dart @@ -33,8 +33,8 @@ class _MainBottomNavbarState extends State { ), BottomNavigationBarItem( icon: LineIcon(LineIcons.moneyBill), - label: 'Order', - tooltip: 'Order', + label: context.lang.order, + tooltip: context.lang.order, ), BottomNavigationBarItem( icon: LineIcon(LineIcons.barChart), diff --git a/lib/presentation/pages/order/order_detail/order_detail_page.dart b/lib/presentation/pages/order/order_detail/order_detail_page.dart index b13c89f..4fb774e 100644 --- a/lib/presentation/pages/order/order_detail/order_detail_page.dart +++ b/lib/presentation/pages/order/order_detail/order_detail_page.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:auto_route/auto_route.dart'; import 'dart:math' show cos, sin; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/order/order.dart'; import '../../../components/appbar/appbar.dart'; @@ -22,33 +23,33 @@ class OrderDetailPage extends StatelessWidget { expandedHeight: 120, pinned: true, backgroundColor: AppColor.primary, - flexibleSpace: const CustomAppBar(title: "Detail Pesanan"), + flexibleSpace: CustomAppBar(title: context.lang.order_details), elevation: 0, ), SliverToBoxAdapter( child: Column( children: [ // Order Status Card - _buildOrderStatusCard(), + _buildOrderStatusCard(context), const SizedBox(height: 16), // Table Visual Card (for dine-in) - if (_isDineIn()) _buildTableVisualCard(), + if (_isDineIn()) _buildTableVisualCard(context), // Order Info Card - _buildOrderInfoCard(), + _buildOrderInfoCard(context), const SizedBox(height: 16), // Order Items Section - _buildOrderItemsSection(), + _buildOrderItemsSection(context), const SizedBox(height: 16), // Payment Summary Card - _buildPaymentSummaryCard(), + _buildPaymentSummaryCard(context), const SizedBox(height: 16), // Payment Methods Section - _buildPaymentMethodsSection(), + _buildPaymentMethodsSection(context), const SizedBox(height: 24), ], ), @@ -58,7 +59,7 @@ class OrderDetailPage extends StatelessWidget { ); } - Widget _buildOrderStatusCard() { + Widget _buildOrderStatusCard(BuildContext context) { Color statusColor = _getStatusColor(order.status); return Container( margin: const EdgeInsets.all(16), @@ -123,7 +124,7 @@ class OrderDetailPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Order Number', + context.lang.order_number, style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -157,7 +158,7 @@ class OrderDetailPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Status Pesanan', + context.lang.order_status, style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -197,7 +198,7 @@ class OrderDetailPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - 'Total Amount', + context.lang.total_amount, style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -222,7 +223,7 @@ class OrderDetailPage extends StatelessWidget { ); } - Widget _buildTableVisualCard() { + Widget _buildTableVisualCard(BuildContext context) { return Container( margin: const EdgeInsets.fromLTRB(16, 0, 16, 16), height: 220, // Increased height @@ -284,14 +285,14 @@ class OrderDetailPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Makan di Tempat', + context.lang.dine_in, style: AppStyle.sm.copyWith( color: AppColor.white.withOpacity(0.9), fontWeight: FontWeight.w500, ), ), Text( - 'Dine In Experience', + context.lang.dine_in_experience, style: AppStyle.lg.copyWith( color: AppColor.white, fontWeight: FontWeight.bold, @@ -347,7 +348,7 @@ class OrderDetailPage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Text( - 'MEJA', + context.lang.table, style: AppStyle.xs.copyWith( color: AppColor.primary.withOpacity( 0.7, @@ -417,7 +418,7 @@ class OrderDetailPage extends StatelessWidget { ), const SizedBox(width: 6), Text( - '${order.orderItems.length} Items', + '${order.orderItems.length} ${context.lang.items}', style: AppStyle.sm.copyWith( color: AppColor.white, fontWeight: FontWeight.w500, @@ -470,7 +471,7 @@ class OrderDetailPage extends StatelessWidget { ); } - Widget _buildOrderInfoCard() { + Widget _buildOrderInfoCard(BuildContext context) { return Container( margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( @@ -517,7 +518,7 @@ class OrderDetailPage extends StatelessWidget { ), const SizedBox(width: 16), Text( - 'Informasi Pesanan', + context.lang.order_information, style: AppStyle.xl.copyWith( fontWeight: FontWeight.bold, color: AppColor.primary, @@ -527,24 +528,28 @@ class OrderDetailPage extends StatelessWidget { ), const SizedBox(height: 24), if (_shouldShowTableNumber()) - _buildInfoRow(Icons.table_restaurant, 'Meja', order.tableNumber), + _buildInfoRow( + Icons.table_restaurant, + context.lang.table, + order.tableNumber, + ), _buildInfoRow( Icons.delivery_dining, - 'Tipe Pesanan', + context.lang.order_type, order.orderType, ), _buildInfoRow( Icons.payment, - 'Status Pembayaran', + context.lang.payment_status, order.paymentStatus, ), _buildInfoRow( Icons.access_time, - 'Dibuat', + context.lang.created, _formatDateTime(order.createdAt), ), if (order.notes.isNotEmpty) - _buildInfoRow(Icons.note, 'Catatan', order.notes), + _buildInfoRow(Icons.note, context.lang.note, order.notes), ], ), ), @@ -590,7 +595,7 @@ class OrderDetailPage extends StatelessWidget { ); } - Widget _buildOrderItemsSection() { + Widget _buildOrderItemsSection(BuildContext context) { return Container( margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( @@ -612,7 +617,7 @@ class OrderDetailPage extends StatelessWidget { child: Row( children: [ Text( - 'Item Pesanan', + context.lang.order_item, style: AppStyle.lg.copyWith( fontWeight: FontWeight.bold, color: AppColor.textPrimary, @@ -629,7 +634,7 @@ class OrderDetailPage extends StatelessWidget { borderRadius: BorderRadius.circular(12), ), child: Text( - '${order.orderItems.length} Item', + '${order.orderItems.length} ${context.lang.item}', style: AppStyle.sm.copyWith( color: AppColor.primary, fontWeight: FontWeight.w600, @@ -647,7 +652,7 @@ class OrderDetailPage extends StatelessWidget { separatorBuilder: (context, index) => const Divider(height: 24), itemBuilder: (context, index) { final item = order.orderItems[index]; - return _buildOrderItemCard(item); + return _buildOrderItemCard(context, item); }, ), ], @@ -655,9 +660,9 @@ class OrderDetailPage extends StatelessWidget { ); } - Widget _buildOrderItemCard(OrderItem item) { + Widget _buildOrderItemCard(BuildContext context, OrderItem item) { // Assume we add status to OrderItem model or determine from order status - String itemStatus = _getItemStatus(item); + String itemStatus = _getItemStatus(context, item); Color itemStatusColor = _getItemStatusColor(itemStatus); return Container( @@ -786,7 +791,7 @@ class OrderDetailPage extends StatelessWidget { borderRadius: BorderRadius.circular(6), ), child: Text( - 'Diskon: -Rp ${_formatCurrency(item.discountAmount)}', + '${context.lang.discount}: -Rp ${_formatCurrency(item.discountAmount)}', style: AppStyle.xs.copyWith( color: AppColor.error, fontWeight: FontWeight.w600, @@ -811,7 +816,7 @@ class OrderDetailPage extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - 'Total Item', + context.lang.total_item, style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -845,7 +850,7 @@ class OrderDetailPage extends StatelessWidget { ); } - Widget _buildPaymentSummaryCard() { + Widget _buildPaymentSummaryCard(BuildContext context) { return Container( margin: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( @@ -866,26 +871,38 @@ class OrderDetailPage extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Ringkasan Pembayaran', + context.lang.payment_summary, style: AppStyle.lg.copyWith( fontWeight: FontWeight.bold, color: AppColor.primary, ), ), const SizedBox(height: 16), - _buildSummaryRow('Subtotal', order.subtotal), + _buildSummaryRow(context.lang.subtotal, order.subtotal), if (order.discountAmount > 0) _buildSummaryRow( - 'Diskon', + context.lang.discount, -order.discountAmount, isDiscount: true, ), - _buildSummaryRow('Pajak', order.taxAmount), + _buildSummaryRow(context.lang.tax, order.taxAmount), const Divider(height: 24), - _buildSummaryRow('Total', order.totalAmount, isTotal: true), - _buildSummaryRow('Dibayar', order.totalPaid, isSuccess: true), + _buildSummaryRow( + context.lang.total, + order.totalAmount, + isTotal: true, + ), + _buildSummaryRow( + context.lang.paid, + order.totalPaid, + isSuccess: true, + ), if (order.remainingAmount > 0) - _buildSummaryRow('Sisa', order.remainingAmount, isError: true), + _buildSummaryRow( + context.lang.remaining, + order.remainingAmount, + isError: true, + ), ], ), ), @@ -930,7 +947,7 @@ class OrderDetailPage extends StatelessWidget { ); } - Widget _buildPaymentMethodsSection() { + Widget _buildPaymentMethodsSection(BuildContext context) { if (order.payments.isEmpty) return const SizedBox(); return Container( @@ -952,7 +969,7 @@ class OrderDetailPage extends StatelessWidget { Padding( padding: const EdgeInsets.fromLTRB(20, 20, 20, 0), child: Text( - 'Metode Pembayaran', + context.lang.payment_method, style: AppStyle.lg.copyWith( fontWeight: FontWeight.bold, color: AppColor.textPrimary, @@ -1159,7 +1176,7 @@ class OrderDetailPage extends StatelessWidget { } } - String _getItemStatus(OrderItem item) { + String _getItemStatus(BuildContext context, OrderItem item) { // Logic untuk menentukan status item berdasarkan: // 1. Status order secara keseluruhan // 2. Jika ada field status di OrderItem model @@ -1167,26 +1184,24 @@ class OrderDetailPage extends StatelessWidget { switch (order.status.toLowerCase()) { case 'completed': - return 'Selesai'; + return context.lang.completed; case 'pending': - return 'Menunggu'; + return context.lang.pending; case 'cancelled': - return 'Dibatalkan'; + return context.lang.void_text; default: - return 'Menunggu'; + return context.lang.pending; } } Color _getItemStatusColor(String status) { switch (status.toLowerCase()) { - case 'selesai': + case 'completed': return AppColor.success; - case 'diproses': + case 'pending': return AppColor.warning; - case 'dibatalkan': + case 'cancelled': return AppColor.error; - case 'siap': - return AppColor.info; default: return AppColor.primary; } diff --git a/lib/presentation/pages/order/order_list/order_page.dart b/lib/presentation/pages/order/order_list/order_page.dart index 8e00948..6ae011b 100644 --- a/lib/presentation/pages/order/order_list/order_page.dart +++ b/lib/presentation/pages/order/order_list/order_page.dart @@ -3,15 +3,13 @@ import 'dart:developer'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:line_icons/line_icons.dart'; import 'package:shimmer/shimmer.dart'; import '../../../../application/order/order_loader/order_loader_bloc.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../injection.dart'; import '../../../components/appbar/appbar.dart'; -import '../../../components/button/button.dart'; -import '../../../components/spacer/spacer.dart'; import '../../../components/widgets/empty_widget.dart'; import '../../../router/app_router.gr.dart'; import 'widgets/filter_header_delegate.dart'; @@ -224,11 +222,10 @@ class _OrderPageState extends State with TickerProviderStateMixin { pinned: true, backgroundColor: AppColor.primary, centerTitle: false, - flexibleSpace: CustomAppBar(title: 'Order', isBack: false), - actions: [ - ActionIconButton(onTap: () {}, icon: LineIcons.filter), - SpaceWidth(8), - ], + flexibleSpace: CustomAppBar( + title: context.lang.orders, + isBack: false, + ), ), // Pinned Filter Section @@ -285,7 +282,7 @@ class _OrderPageState extends State with TickerProviderStateMixin { child: Row( children: [ Text( - '${state.orders.length} ${state.status.toLowerCase()} order${state.orders.length != 1 ? 's' : ''}', + '${state.orders.length} ${state.status.toLowerCase()} ${context.lang.orders}', style: TextStyle( color: AppColor.textSecondary, fontSize: 14, @@ -300,9 +297,10 @@ class _OrderPageState extends State with TickerProviderStateMixin { _buildShimmerList() else if (state.orders.isEmpty) EmptyWidget( - title: 'Order', - message: - 'No ${state.status.toLowerCase()} orders found', + title: context.lang.order, + message: context.lang.no_order_with_status( + state.status.toLowerCase(), + ), ) else ListView.builder( diff --git a/lib/presentation/pages/order/order_list/widgets/filter_header_delegate.dart b/lib/presentation/pages/order/order_list/widgets/filter_header_delegate.dart index 1d562fb..71aefc9 100644 --- a/lib/presentation/pages/order/order_list/widgets/filter_header_delegate.dart +++ b/lib/presentation/pages/order/order_list/widgets/filter_header_delegate.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import '../../../../../common/extension/extension.dart'; import '../../../../components/field/date_range_picker_field.dart'; import 'status_tile.dart'; @@ -36,7 +37,6 @@ class FilterHeaderDelegate extends SliverPersistentHeaderDelegate { double shrinkOffset, bool overlapsContent, ) { - print('FilterHeaderDelegate build called'); // Debug log return Container( color: backgroundColor, padding: padding, @@ -50,9 +50,6 @@ class FilterHeaderDelegate extends SliverPersistentHeaderDelegate { startDate: startDate, endDate: endDate, onChanged: (start, end) { - print( - 'onChanged called in FilterHeaderDelegate: $start - $end', - ); // Debug log onDateChanged(start, end); }, ), @@ -70,7 +67,11 @@ class FilterHeaderDelegate extends SliverPersistentHeaderDelegate { right: index < filterOptions.length - 1 ? 8 : 0, ), child: OrderStatusTile( - label: option, + label: option == "All" + ? context.lang.all + : option == "Completed" + ? context.lang.completed + : context.lang.pending, isSelected: option == selectedFilter, onSelected: (isSelected) { if (isSelected) { diff --git a/lib/presentation/pages/order/order_list/widgets/order_tile.dart b/lib/presentation/pages/order/order_list/widgets/order_tile.dart index 77311a7..c9ecbfd 100644 --- a/lib/presentation/pages/order/order_list/widgets/order_tile.dart +++ b/lib/presentation/pages/order/order_list/widgets/order_tile.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import '../../../../../common/extension/extension.dart'; import '../../../../../common/theme/theme.dart'; import '../../../../../domain/order/order.dart'; @@ -46,19 +47,19 @@ class OrderTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header Row - _buildHeaderRow(), + _buildHeaderRow(context), const SizedBox(height: 12), // Order Info - _buildOrderInfo(), + _buildOrderInfo(context), const SizedBox(height: 16), // Amount Section - _buildAmountSection(), + _buildAmountSection(context), const SizedBox(height: 16), // Footer with Actions - _buildFooterActions(), + _buildFooterActions(context), ], ), ), @@ -67,7 +68,7 @@ class OrderTile extends StatelessWidget { ); } - Widget _buildHeaderRow() { + Widget _buildHeaderRow(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -94,12 +95,12 @@ class OrderTile extends StatelessWidget { ), ], ), - _buildStatusChip(), + _buildStatusChip(context), ], ); } - Widget _buildStatusChip() { + Widget _buildStatusChip(BuildContext context) { Color statusColor; String statusText; IconData statusIcon; @@ -107,27 +108,34 @@ class OrderTile extends StatelessWidget { // Check isVoid and isRefund first for display if (order.isVoid) { statusColor = AppColor.error; - statusText = 'Void'; + statusText = context.lang.void_text; statusIcon = Icons.block; } else if (order.isRefund) { statusColor = AppColor.info; - statusText = 'Refunded'; + statusText = context.lang.refund; statusIcon = Icons.undo; } else { // Handle status values (only pending and completed) switch (order.status.toLowerCase()) { case 'completed': + statusColor = AppColor.success; + statusText = context.lang.completed; + statusIcon = Icons.check_circle; case 'paid': case 'finished': statusColor = AppColor.success; - statusText = 'Completed'; + statusText = context.lang.completed; statusIcon = Icons.check_circle; break; case 'pending': + statusColor = AppColor.warning; + statusText = context.lang.pending; + statusIcon = Icons.schedule; + break; case 'waiting': case 'processing': statusColor = AppColor.warning; - statusText = 'Pending'; + statusText = context.lang.pending; statusIcon = Icons.schedule; break; default: @@ -163,7 +171,7 @@ class OrderTile extends StatelessWidget { ); } - Widget _buildOrderInfo() { + Widget _buildOrderInfo(BuildContext context) { return Row( children: [ Expanded( @@ -177,7 +185,7 @@ class OrderTile extends StatelessWidget { const SizedBox(width: 6), Expanded( child: Text( - _getOrderInfoText(), + _getOrderInfoText(context), style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, @@ -198,7 +206,7 @@ class OrderTile extends StatelessWidget { ), const SizedBox(width: 6), Text( - '${order.orderItems.length} items', + '${order.orderItems.length} ${context.lang.items}', style: const TextStyle( fontSize: 13, color: AppColor.textSecondary, @@ -239,7 +247,7 @@ class OrderTile extends StatelessWidget { ); } - Widget _buildAmountSection() { + Widget _buildAmountSection(BuildContext context) { return Container( width: double.infinity, padding: const EdgeInsets.all(16), @@ -264,8 +272,8 @@ class OrderTile extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( - 'Total Amount', + Text( + context.lang.total_amount, style: TextStyle( fontSize: 14, color: AppColor.textWhite, @@ -274,7 +282,7 @@ class OrderTile extends StatelessWidget { ), const SizedBox(height: 4), Text( - 'Rp ${NumberFormat('#,###').format(order.totalAmount)}', + order.totalAmount.currencyFormatRp, style: const TextStyle( fontSize: 24, fontWeight: FontWeight.bold, @@ -284,7 +292,7 @@ class OrderTile extends StatelessWidget { if (order.remainingAmount > 0) ...[ const SizedBox(height: 4), Text( - 'Remaining: Rp ${NumberFormat('#,###').format(order.remainingAmount)}', + '${context.lang.remaining}: ${order.remainingAmount.currencyFormatRp}', style: const TextStyle( fontSize: 12, color: AppColor.textWhite, @@ -311,7 +319,7 @@ class OrderTile extends StatelessWidget { ); } - Widget _buildFooterActions() { + Widget _buildFooterActions(BuildContext context) { // Don't show anything if order is void or refunded if (order.isVoid || order.isRefund) { return const SizedBox.shrink(); @@ -326,7 +334,7 @@ class OrderTile extends StatelessWidget { if (order.payments.isNotEmpty) ...[ const SizedBox(height: 2), Text( - 'Payment: ${_getPaymentMethods()}', + '${context.lang.payment}: ${_getPaymentMethods()}', style: const TextStyle( fontSize: 11, color: AppColor.textLight, @@ -337,59 +345,10 @@ class OrderTile extends StatelessWidget { ], ), ), - if (order.status.toLowerCase() == 'completed') ...[ - _buildActionButton( - icon: Icons.print, - label: 'Print', - onPressed: onPrint, - color: AppColor.info, - ), - const SizedBox(width: 8), - _buildActionButton( - icon: Icons.undo, - label: 'Refund', - onPressed: onRefund, - color: AppColor.warning, - ), - ], ], ); } - Widget _buildActionButton({ - required IconData icon, - required String label, - required VoidCallback? onPressed, - required Color color, - }) { - return Material( - color: color.withOpacity(0.1), - borderRadius: BorderRadius.circular(8), - child: InkWell( - onTap: onPressed, - borderRadius: BorderRadius.circular(8), - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(icon, size: 16, color: color), - const SizedBox(width: 4), - Text( - label, - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.w600, - color: color, - ), - ), - ], - ), - ), - ), - ); - } - IconData _getOrderInfoIcon() { switch (order.orderType.toLowerCase()) { case 'dine in': @@ -406,11 +365,11 @@ class OrderTile extends StatelessWidget { } } - String _getOrderInfoText() { + String _getOrderInfoText(BuildContext context) { switch (order.orderType.toLowerCase()) { case 'dine in': case 'dine_in': - return 'Table ${order.tableNumber.isNotEmpty ? order.tableNumber : 'N/A'}'; + return '${context.lang.table} ${order.tableNumber.isNotEmpty ? order.tableNumber : 'N/A'}'; case 'takeaway': case 'take_away': case 'pickup': @@ -419,8 +378,8 @@ class OrderTile extends StatelessWidget { return 'Delivery Order'; default: return order.tableNumber.isNotEmpty - ? 'Table ${order.tableNumber}' - : 'Order ${order.orderNumber}'; + ? '${context.lang.table} ${order.tableNumber}' + : context.lang.order; } } diff --git a/lib/presentation/pages/outlet/outlet_information_page.dart b/lib/presentation/pages/outlet/outlet_information_page.dart index 49e122a..b33f925 100644 --- a/lib/presentation/pages/outlet/outlet_information_page.dart +++ b/lib/presentation/pages/outlet/outlet_information_page.dart @@ -3,10 +3,12 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../application/outlet/current_outlet_loader/current_outlet_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../../../domain/outlet/outlet.dart'; import '../../../injection.dart'; import '../../components/appbar/appbar.dart'; +import '../../components/spacer/spacer.dart'; // Outlet Information Page @RoutePage() @@ -79,14 +81,14 @@ class _OutletInformationPageState extends State expandedHeight: 120.0, floating: false, pinned: true, - flexibleSpace: CustomAppBar(title: 'Outlet Information'), + flexibleSpace: CustomAppBar(title: context.lang.outlet_information), ), SliverToBoxAdapter( child: FadeTransition( opacity: _fadeAnimation, child: SlideTransition( position: _slideAnimation, - child: _buildContent(), + child: _buildContent(context), ), ), ), @@ -95,7 +97,7 @@ class _OutletInformationPageState extends State ); } - Widget _buildContent() { + Widget _buildContent(BuildContext context) { return BlocBuilder( builder: (context, state) { return Padding( @@ -105,15 +107,11 @@ class _OutletInformationPageState extends State children: [ _buildHeaderCard(state.outlet), const SizedBox(height: 20), - _buildInfoSection(state.outlet), + _buildInfoSection(context, state.outlet), const SizedBox(height: 20), - _buildContactSection(state.outlet), + _buildBusinessSection(context, state.outlet), const SizedBox(height: 20), - _buildBusinessSection(state.outlet), - const SizedBox(height: 20), - _buildStatusSection(state.outlet), - const SizedBox(height: 20), - _buildTimestampSection(state.outlet), + _buildStatusSection(context, state.outlet), ], ), ); @@ -190,62 +188,65 @@ class _OutletInformationPageState extends State ); } - Widget _buildInfoSection(Outlet outlet) { + Widget _buildInfoSection(BuildContext context, Outlet outlet) { return _buildAnimatedCard( delay: 200, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildSectionTitle('General Information', Icons.info_outline), - const SizedBox(height: 16), - _buildInfoRow('Outlet ID', outlet.id, Icons.fingerprint), - _buildInfoRow( - 'Organization ID', - outlet.organizationId, - Icons.business, + _buildSectionTitle( + context.lang.outlet_information, + Icons.info_outline, + ), + SpaceHeight(20), + _buildInfoRow( + context.lang.address, + outlet.address, + Icons.location_on, + ), + _buildInfoRow( + context.lang.phone_number, + outlet.phoneNumber, + Icons.phone, ), - _buildInfoRow('Address', outlet.address, Icons.location_on), ], ), ); } - Widget _buildContactSection(Outlet outlet) { - return _buildAnimatedCard( - delay: 400, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildSectionTitle('Contact Information', Icons.contact_phone), - const SizedBox(height: 16), - _buildInfoRow('Phone Number', outlet.phoneNumber, Icons.phone), - ], - ), - ); - } - - Widget _buildBusinessSection(Outlet outlet) { + Widget _buildBusinessSection(BuildContext context, Outlet outlet) { return _buildAnimatedCard( delay: 600, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildSectionTitle('Business Settings', Icons.settings_applications), + _buildSectionTitle( + context.lang.business_settings, + Icons.settings_applications, + ), const SizedBox(height: 16), - _buildInfoRow('Currency', outlet.currency, Icons.monetization_on), - _buildInfoRow('Tax Rate', '${outlet.taxRate}%', Icons.percent), + _buildInfoRow( + context.lang.currency, + outlet.currency, + Icons.monetization_on, + ), + _buildInfoRow( + context.lang.tax_rate, + '${outlet.taxRate}%', + Icons.percent, + ), ], ), ); } - Widget _buildStatusSection(Outlet outlet) { + Widget _buildStatusSection(BuildContext context, Outlet outlet) { return _buildAnimatedCard( delay: 800, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildSectionTitle('Status', Icons.toggle_on), + _buildSectionTitle(context.lang.status_text, Icons.toggle_on), const SizedBox(height: 16), Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), @@ -272,7 +273,7 @@ class _OutletInformationPageState extends State ), const SizedBox(width: 12), Text( - outlet.isActive ? 'Active' : 'Inactive', + outlet.isActive ? context.lang.active : context.lang.inactive, style: AppStyle.md.copyWith( color: outlet.isActive ? AppColor.success : AppColor.error, fontWeight: FontWeight.w600, @@ -286,29 +287,6 @@ class _OutletInformationPageState extends State ); } - Widget _buildTimestampSection(Outlet outlet) { - return _buildAnimatedCard( - delay: 1000, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildSectionTitle('Timestamps', Icons.schedule), - const SizedBox(height: 16), - _buildInfoRow( - 'Created At', - _formatDateTime(outlet.createdAt), - Icons.add_circle_outline, - ), - _buildInfoRow( - 'Updated At', - _formatDateTime(outlet.updatedAt), - Icons.update, - ), - ], - ), - ); - } - Widget _buildAnimatedCard({required Widget child, required int delay}) { return TweenAnimationBuilder( duration: Duration(milliseconds: 600 + delay), @@ -396,8 +374,4 @@ class _OutletInformationPageState extends State ), ); } - - String _formatDateTime(DateTime dateTime) { - return '${dateTime.day}/${dateTime.month}/${dateTime.year} ${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}'; - } } diff --git a/lib/presentation/pages/product/product_analytic/product_analytic_page.dart b/lib/presentation/pages/product/product_analytic/product_analytic_page.dart index 853c4c2..33b0683 100644 --- a/lib/presentation/pages/product/product_analytic/product_analytic_page.dart +++ b/lib/presentation/pages/product/product_analytic/product_analytic_page.dart @@ -3,6 +3,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../application/analytic/product_analytic_loader/product_analytic_loader_bloc.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/analytic/analytic.dart'; import '../../../../injection.dart'; @@ -136,18 +137,7 @@ class _ProductAnalyticPageState extends State pinned: true, elevation: 0, backgroundColor: AppColor.primary, - flexibleSpace: FlexibleSpaceBar( - background: Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: AppColor.primaryGradient, - ), - ), - child: const CustomAppBar(title: "Analisis Produk"), - ), - ), + flexibleSpace: CustomAppBar(title: context.lang.product_analytic), ); } @@ -214,7 +204,7 @@ class _ProductAnalyticPageState extends State Expanded( child: _buildSummaryCard( icon: Icons.monetization_on, - title: 'Total Pendapatan', + title: context.lang.total_revenue, value: _formatCurrency(stats.totalRevenue), color: AppColor.success, ), @@ -223,7 +213,7 @@ class _ProductAnalyticPageState extends State Expanded( child: _buildSummaryCard( icon: Icons.shopping_cart, - title: 'Total Terjual', + title: context.lang.total_sold, value: _formatNumber(stats.totalQuantity), color: AppColor.info, ), @@ -236,7 +226,7 @@ class _ProductAnalyticPageState extends State Expanded( child: _buildSummaryCard( icon: Icons.receipt_long, - title: 'Total Pesanan', + title: context.lang.total_orders, value: _formatNumber(stats.totalOrders), color: AppColor.warning, ), @@ -245,7 +235,7 @@ class _ProductAnalyticPageState extends State Expanded( child: _buildSummaryCard( icon: Icons.trending_up, - title: 'Rata-rata Nilai', + title: context.lang.average_price, value: _formatCurrency(stats.averageOrderValue), color: AppColor.primary, ), @@ -541,7 +531,7 @@ class _ProductAnalyticPageState extends State Icon(Icons.trending_up, color: AppColor.success, size: 20), const SizedBox(width: 8), Text( - 'Pendapatan', + context.lang.revenue, style: _getTextStyle( AppStyle.sm, color: AppColor.success, @@ -552,7 +542,7 @@ class _ProductAnalyticPageState extends State ), const SizedBox(height: 8), Text( - _formatCurrency(product.revenue.toDouble()), + product.revenue.currencyFormatRp, style: _getTextStyle( AppStyle.xl, color: AppColor.success, @@ -570,14 +560,14 @@ class _ProductAnalyticPageState extends State _buildStatCard( icon: Icons.shopping_cart_outlined, value: '${product.quantitySold}', - label: 'Terjual', + label: context.lang.sold, color: AppColor.info, ), const SizedBox(height: 8), _buildStatCard( icon: Icons.receipt_outlined, value: '${product.orderCount}', - label: 'Pesanan', + label: context.lang.orders, color: AppColor.warning, ), ], @@ -645,7 +635,7 @@ class _ProductAnalyticPageState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - 'Harga Rata-rata', + context.lang.average_price, style: _getTextStyle( AppStyle.sm, color: AppColor.textSecondary, @@ -653,7 +643,7 @@ class _ProductAnalyticPageState extends State ), ), Text( - _formatCurrency(product.averagePrice), + product.averagePrice.round().currencyFormatRp, style: _getTextStyle( AppStyle.sm, color: _getCategoryColor(product.categoryName), diff --git a/lib/presentation/pages/product/product_list/product_page.dart b/lib/presentation/pages/product/product_list/product_page.dart index cc71457..0c4aa78 100644 --- a/lib/presentation/pages/product/product_list/product_page.dart +++ b/lib/presentation/pages/product/product_list/product_page.dart @@ -6,6 +6,7 @@ import 'package:shimmer/shimmer.dart'; import '../../../../application/category/category_loader/category_loader_bloc.dart'; import '../../../../application/product/product_loader/product_loader_bloc.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/category/category.dart'; import '../../../../domain/product/product.dart'; @@ -83,7 +84,7 @@ class _ProductPageState extends State child: CustomScrollView( controller: scrollController, slivers: [ - _buildSliverAppBar(), + _buildSliverAppBar(context), _buildCategoryFilter(), _buildProductContent(state), ], @@ -95,13 +96,13 @@ class _ProductPageState extends State ); } - Widget _buildSliverAppBar() { + Widget _buildSliverAppBar(BuildContext context) { return SliverAppBar( expandedHeight: 120.0, floating: false, pinned: true, elevation: 0, - flexibleSpace: CustomAppBar(title: 'Produk'), + flexibleSpace: CustomAppBar(title: context.lang.product), actions: [ ActionIconButton(onTap: () {}, icon: LineIcons.search), ActionIconButton( diff --git a/lib/presentation/pages/profile/pages/profile_change_password/profile_change_password_page.dart b/lib/presentation/pages/profile/pages/profile_change_password/profile_change_password_page.dart index b6c975f..9acc80d 100644 --- a/lib/presentation/pages/profile/pages/profile_change_password/profile_change_password_page.dart +++ b/lib/presentation/pages/profile/pages/profile_change_password/profile_change_password_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../../application/user/change_password_form/change_password_form_bloc.dart'; +import '../../../../../common/extension/extension.dart'; import '../../../../../common/theme/theme.dart'; import '../../../../../injection.dart'; import '../../../../components/appbar/appbar.dart'; @@ -39,7 +40,7 @@ class _ProfileChangePasswordPageState extends State { (f) => AppFlushbar.showUserFailureToast(context, f), (user) { if (context.mounted) { - AppFlushbar.showSuccess(context, 'Password changed'); + AppFlushbar.showSuccess(context, context.lang.password_changed); Future.delayed(const Duration(seconds: 2), () { context.router.back(); }); @@ -59,7 +60,7 @@ class _ProfileChangePasswordPageState extends State { pinned: true, elevation: 0, backgroundColor: AppColor.primary, - flexibleSpace: CustomAppBar(title: 'Change Password'), + flexibleSpace: CustomAppBar(title: context.lang.change_password), ), SliverToBoxAdapter( child: @@ -83,7 +84,7 @@ class _ProfileChangePasswordPageState extends State { ChangePasswordNewPassword(), SpaceHeight(24), AppElevatedButton( - text: 'Save', + text: context.lang.save, isLoading: state.isSubmitting, onPressed: () { context.read().add( diff --git a/lib/presentation/pages/profile/pages/profile_change_password/widgets/current_password.dart b/lib/presentation/pages/profile/pages/profile_change_password/widgets/current_password.dart index c3886ae..2422388 100644 --- a/lib/presentation/pages/profile/pages/profile_change_password/widgets/current_password.dart +++ b/lib/presentation/pages/profile/pages/profile_change_password/widgets/current_password.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:line_icons/line_icons.dart'; import '../../../../../../application/user/change_password_form/change_password_form_bloc.dart'; +import '../../../../../../common/extension/extension.dart'; import '../../../../../components/field/field.dart'; class ChangePasswordCurrentPassword extends StatelessWidget { @@ -11,9 +12,9 @@ class ChangePasswordCurrentPassword extends StatelessWidget { @override Widget build(BuildContext context) { return AppPasswordTextFormField( - title: 'Current Password', + title: context.lang.current_password, prefixIcon: LineIcons.lock, - hintText: 'Please enter your current password', + hintText: context.lang.current_password_placeholder, onChanged: (value) => context.read().add( ChangePasswordFormEvent.currentPasswordChanged(value), ), @@ -23,7 +24,7 @@ class ChangePasswordCurrentPassword extends StatelessWidget { .state .currentPassword .isEmpty) { - return 'Please enter your current password'; + return context.lang.current_password_placeholder; } return null; }, diff --git a/lib/presentation/pages/profile/pages/profile_change_password/widgets/new_password.dart b/lib/presentation/pages/profile/pages/profile_change_password/widgets/new_password.dart index 4d404be..ad133f6 100644 --- a/lib/presentation/pages/profile/pages/profile_change_password/widgets/new_password.dart +++ b/lib/presentation/pages/profile/pages/profile_change_password/widgets/new_password.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:line_icons/line_icons.dart'; import '../../../../../../application/user/change_password_form/change_password_form_bloc.dart'; +import '../../../../../../common/extension/extension.dart'; import '../../../../../components/field/field.dart'; class ChangePasswordNewPassword extends StatelessWidget { @@ -11,20 +12,20 @@ class ChangePasswordNewPassword extends StatelessWidget { @override Widget build(BuildContext context) { return AppPasswordTextFormField( - title: 'New Password', + title: context.lang.new_password, prefixIcon: LineIcons.lock, - hintText: 'Please enter your new password', + hintText: context.lang.new_password_placeholder, onChanged: (value) => context.read().add( ChangePasswordFormEvent.newPasswordChanged(value), ), validator: (value) { if (context.read().state.newPassword.isEmpty) { - return 'Please enter your new password'; + return context.lang.new_password_placeholder; } if (context.read().state.newPassword == context.read().state.currentPassword) { - return 'New password cannot be same as current password'; + return context.lang.new_password_not_same; } return null; }, diff --git a/lib/presentation/pages/profile/pages/profile_edit/profile_edit_page.dart b/lib/presentation/pages/profile/pages/profile_edit/profile_edit_page.dart index b19172e..53ff39d 100644 --- a/lib/presentation/pages/profile/pages/profile_edit/profile_edit_page.dart +++ b/lib/presentation/pages/profile/pages/profile_edit/profile_edit_page.dart @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../../application/auth/auth_bloc.dart'; import '../../../../../application/user/user_edit_form/user_edit_form_bloc.dart'; +import '../../../../../common/extension/extension.dart'; import '../../../../../common/theme/theme.dart'; import '../../../../../domain/user/user.dart'; import '../../../../../injection.dart'; @@ -64,7 +65,7 @@ class _ProfileEditPageState extends State { pinned: true, elevation: 0, backgroundColor: AppColor.primary, - flexibleSpace: CustomAppBar(title: 'Profile Edit'), + flexibleSpace: CustomAppBar(title: context.lang.edit_profile), ), SliverToBoxAdapter( child: BlocBuilder( @@ -85,7 +86,7 @@ class _ProfileEditPageState extends State { ProfileEditNameField(controller: nameController), SpaceHeight(24), AppElevatedButton( - text: 'Save', + text: context.lang.save, isLoading: state.isSubmitting, onPressed: () { context.read().add( diff --git a/lib/presentation/pages/profile/pages/profile_edit/widgets/name_field.dart b/lib/presentation/pages/profile/pages/profile_edit/widgets/name_field.dart index bce6ffd..9adbc51 100644 --- a/lib/presentation/pages/profile/pages/profile_edit/widgets/name_field.dart +++ b/lib/presentation/pages/profile/pages/profile_edit/widgets/name_field.dart @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:line_icons/line_icons.dart'; import '../../../../../../application/user/user_edit_form/user_edit_form_bloc.dart'; +import '../../../../../../common/extension/extension.dart'; import '../../../../../components/field/field.dart'; class ProfileEditNameField extends StatelessWidget { @@ -12,9 +13,9 @@ class ProfileEditNameField extends StatelessWidget { @override Widget build(BuildContext context) { return AppTextFormField( - title: 'Name', + title: context.lang.name, prefixIcon: LineIcons.user, - hintText: 'Please enter your name', + hintText: context.lang.name_placeholder, controller: controller, onChanged: (value) { context.read().add( @@ -23,7 +24,7 @@ class ProfileEditNameField extends StatelessWidget { }, validator: (value) { if (context.read().state.name.isEmpty) { - return 'Please enter your name'; + return context.lang.name_placeholder; } return null; diff --git a/lib/presentation/pages/profile/profile_page.dart b/lib/presentation/pages/profile/profile_page.dart index 3faeeff..48cbc92 100644 --- a/lib/presentation/pages/profile/profile_page.dart +++ b/lib/presentation/pages/profile/profile_page.dart @@ -6,6 +6,7 @@ import 'package:loader_overlay/loader_overlay.dart'; import '../../../application/auth/auth_bloc.dart'; import '../../../application/auth/logout_form/logout_form_bloc.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../../../injection.dart'; import '../../components/button/button.dart'; @@ -89,7 +90,7 @@ class ProfilePage extends StatelessWidget implements AutoRouteWrapper { MainAxisAlignment.spaceBetween, children: [ Text( - 'Profile', + context.lang.profile, style: AppStyle.xl.copyWith( fontWeight: FontWeight.w700, fontSize: 18, diff --git a/lib/presentation/pages/profile/widgets/account_info.dart b/lib/presentation/pages/profile/widgets/account_info.dart index 270e5db..70e3df1 100644 --- a/lib/presentation/pages/profile/widgets/account_info.dart +++ b/lib/presentation/pages/profile/widgets/account_info.dart @@ -34,7 +34,7 @@ class ProfileAccountInfo extends StatelessWidget { Padding( padding: EdgeInsets.all(16), child: Text( - 'Account Information', + context.lang.account_information, style: AppStyle.xl.copyWith( fontSize: 18, fontWeight: FontWeight.bold, @@ -45,7 +45,7 @@ class ProfileAccountInfo extends StatelessWidget { ProfileTile( icon: LineIcons.envelope, - title: 'Email', + title: context.lang.email, subtitle: user.email, showArrow: false, ), @@ -54,7 +54,7 @@ class ProfileAccountInfo extends StatelessWidget { ProfileTile( icon: LineIcons.calendarAlt, - title: 'Member Since', + title: context.lang.member_since, subtitle: user.createdAt.toDate, showArrow: false, ), @@ -62,15 +62,15 @@ class ProfileAccountInfo extends StatelessWidget { ProfileTile( icon: LineIcons.userEdit, - title: 'Ubah Profil', - subtitle: 'Ubah profil kamu', + title: context.lang.edit_profile, + subtitle: context.lang.edit_profile_desc, onTap: () => context.router.push(ProfileEditRoute(user: user)), ), ProfileDivider(), ProfileTile( icon: LineIcons.lock, - title: 'Change Password', - subtitle: 'Change your password', + title: context.lang.change_password, + subtitle: context.lang.change_password_desc, onTap: () => context.router.push(ProfileChangePasswordRoute()), ), ], diff --git a/lib/presentation/pages/profile/widgets/app_setting.dart b/lib/presentation/pages/profile/widgets/app_setting.dart index 8e623be..563ef57 100644 --- a/lib/presentation/pages/profile/widgets/app_setting.dart +++ b/lib/presentation/pages/profile/widgets/app_setting.dart @@ -1,6 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../router/app_router.gr.dart'; import 'profile_tile.dart'; @@ -37,7 +38,7 @@ class _ProfileAppSettingState extends State { Padding( padding: EdgeInsets.all(16), child: Text( - 'App Settings', + context.lang.app_settings, style: AppStyle.xl.copyWith( fontSize: 18, fontWeight: FontWeight.bold, @@ -74,8 +75,8 @@ class _ProfileAppSettingState extends State { // ProfileDivider(), ProfileTile( icon: Icons.language_outlined, - title: 'Language', - subtitle: 'English (US)', + title: context.lang.language, + subtitle: context.lang.language_desc, onTap: () => context.router.push(LanguageRoute()), ), ], diff --git a/lib/presentation/pages/profile/widgets/business_setting.dart b/lib/presentation/pages/profile/widgets/business_setting.dart index fee212a..d7789be 100644 --- a/lib/presentation/pages/profile/widgets/business_setting.dart +++ b/lib/presentation/pages/profile/widgets/business_setting.dart @@ -1,6 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../router/app_router.gr.dart'; import 'divider.dart'; @@ -30,7 +31,7 @@ class ProfileBusinessSetting extends StatelessWidget { Padding( padding: EdgeInsets.all(16), child: Text( - 'Business Settings', + context.lang.business_settings, style: AppStyle.xl.copyWith( fontSize: 18, fontWeight: FontWeight.bold, @@ -41,8 +42,8 @@ class ProfileBusinessSetting extends StatelessWidget { ProfileTile( icon: Icons.business_outlined, - title: 'Outlet Information', - subtitle: 'Manage your Outlet details', + title: context.lang.outlet_information, + subtitle: context.lang.outlet_informatio_desc, onTap: () => context.router.push(OutletInformationRoute()), ), @@ -50,8 +51,8 @@ class ProfileBusinessSetting extends StatelessWidget { ProfileTile( icon: Icons.people_outline, - title: 'Staff Management', - subtitle: 'Manage employees and permissions', + title: context.lang.staff_management, + subtitle: context.lang.staff_management_desc, onTap: () => context.router.push(ComingSoonRoute()), ), @@ -59,16 +60,16 @@ class ProfileBusinessSetting extends StatelessWidget { ProfileTile( icon: Icons.inventory_2_outlined, - title: 'Product', - subtitle: 'Manage your products', + title: context.lang.products, + subtitle: context.lang.manage_your_products, onTap: () => context.router.push(ProductRoute()), ), ProfileDivider(), ProfileTile( icon: Icons.download_outlined, - title: 'Download Report', - subtitle: 'Download your sales or inventory report', + title: context.lang.download_report, + subtitle: context.lang.download_report_desc, onTap: () => context.router.push(DownloadReportRoute()), ), ], diff --git a/lib/presentation/pages/profile/widgets/danger_zone.dart b/lib/presentation/pages/profile/widgets/danger_zone.dart index 9d8c873..e9d443c 100644 --- a/lib/presentation/pages/profile/widgets/danger_zone.dart +++ b/lib/presentation/pages/profile/widgets/danger_zone.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../application/auth/logout_form/logout_form_bloc.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; -import '../../../components/spacer/spacer.dart'; import 'profile_tile.dart'; class ProfileDangerZone extends StatelessWidget { @@ -28,27 +28,10 @@ class ProfileDangerZone extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Padding( - padding: const EdgeInsets.all(16), - child: Row( - children: [ - Icon(Icons.warning_outlined, color: AppColor.error, size: 20), - const SpaceWidth(8), - Text( - 'Danger Zone', - style: AppStyle.xl.copyWith( - fontWeight: FontWeight.bold, - color: AppColor.error, - ), - ), - ], - ), - ), - ProfileTile( icon: Icons.logout, - title: 'Logout', - subtitle: 'Sign out from your account', + title: context.lang.logout, + subtitle: context.lang.logout_desc, iconColor: AppColor.error, textColor: AppColor.error, onTap: () { diff --git a/lib/presentation/pages/profile/widgets/support.dart b/lib/presentation/pages/profile/widgets/support.dart index 42193fc..6b077a5 100644 --- a/lib/presentation/pages/profile/widgets/support.dart +++ b/lib/presentation/pages/profile/widgets/support.dart @@ -1,6 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; import '../../../router/app_router.gr.dart'; import 'divider.dart'; @@ -30,7 +31,7 @@ class ProfileSupport extends StatelessWidget { Padding( padding: EdgeInsets.all(16), child: Text( - 'Support', + context.lang.support, style: AppStyle.xl.copyWith( fontSize: 18, fontWeight: FontWeight.bold, @@ -41,8 +42,8 @@ class ProfileSupport extends StatelessWidget { ProfileTile( icon: Icons.help_outline, - title: 'Help Center', - subtitle: 'Get help and support', + title: context.lang.help_center, + subtitle: context.lang.help_center_desc, onTap: () => context.router.push(ComingSoonRoute()), ), @@ -60,8 +61,8 @@ class ProfileSupport extends StatelessWidget { ProfileTile( icon: Icons.info_outline, - title: 'About', - subtitle: 'App version and information', + title: context.lang.about, + subtitle: context.lang.about_desc, onTap: () => context.router.push(AboutAppRoute()), ), ], diff --git a/lib/presentation/pages/purchase/purchase_page.dart b/lib/presentation/pages/purchase/purchase_page.dart index 5775227..fa7558c 100644 --- a/lib/presentation/pages/purchase/purchase_page.dart +++ b/lib/presentation/pages/purchase/purchase_page.dart @@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../../components/appbar/appbar.dart'; import 'widgets/purchase_tile.dart'; @@ -93,7 +94,7 @@ class _PurchasePageState extends State elevation: 0, backgroundColor: AppColor.primary, - flexibleSpace: CustomAppBar(title: 'Pembelian'), + flexibleSpace: CustomAppBar(title: context.lang.purchase), ), // Stats Cards @@ -105,7 +106,7 @@ class _PurchasePageState extends State children: [ Expanded( child: PurchaseStatCard( - title: 'Total Pembelian', + title: context.lang.total_purchase, value: 'Rp 8.340.000', icon: LineIcons.shoppingCart, iconColor: AppColor.success, @@ -115,8 +116,8 @@ class _PurchasePageState extends State const SizedBox(width: 12), Expanded( child: PurchaseStatCard( - title: 'Pending Order', - value: '3 Orders', + title: context.lang.pending_order, + value: '3 ${context.lang.orders}', icon: LineIcons.clock, iconColor: AppColor.warning, cardAnimation: cardAnimation, @@ -139,7 +140,7 @@ class _PurchasePageState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - 'Riwayat Pembelian', + context.lang.history_purchase, style: AppStyle.lg.copyWith( fontWeight: FontWeight.w600, ), @@ -154,7 +155,7 @@ class _PurchasePageState extends State borderRadius: BorderRadius.circular(20), ), child: Text( - '${purchaseData.length} Orders', + '${purchaseData.length} ${context.lang.orders}', style: AppStyle.sm.copyWith( color: AppColor.textWhite, ), @@ -220,20 +221,6 @@ class _PurchasePageState extends State const SliverToBoxAdapter(child: SizedBox(height: 80)), ], ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () { - // Navigate to create new purchase - }, - backgroundColor: AppColor.secondary, - icon: const Icon(LineIcons.plus, color: AppColor.textWhite), - label: Text( - 'Buat Pembelian', - style: AppStyle.md.copyWith( - color: AppColor.textWhite, - fontWeight: FontWeight.w600, - ), - ), - ), ); } } diff --git a/lib/presentation/pages/purchase/widgets/purchase_tile.dart b/lib/presentation/pages/purchase/widgets/purchase_tile.dart index fa22bf2..e850031 100644 --- a/lib/presentation/pages/purchase/widgets/purchase_tile.dart +++ b/lib/presentation/pages/purchase/widgets/purchase_tile.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:line_icons/line_icons.dart'; +import '../../../../common/extension/extension.dart'; import '../../../../common/theme/theme.dart'; class PurchaseTile extends StatelessWidget { @@ -219,7 +220,7 @@ class PurchaseTile extends StatelessWidget { ), const SizedBox(width: 4), Text( - '${purchase['items']} items', + '${purchase['items']} ${context.lang.items}', style: AppStyle.xs.copyWith( color: AppColor.secondary, fontWeight: FontWeight.w600, @@ -241,7 +242,7 @@ class PurchaseTile extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Total Pembelian', + context.lang.total_purchase, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, diff --git a/lib/presentation/pages/report/report_page.dart b/lib/presentation/pages/report/report_page.dart index 64b99e8..d790f86 100644 --- a/lib/presentation/pages/report/report_page.dart +++ b/lib/presentation/pages/report/report_page.dart @@ -1,14 +1,13 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:line_icons/line_icons.dart'; import 'dart:math' as math; import '../../../application/analytic/dashboard_analytic_loader/dashboard_analytic_loader_bloc.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../../../injection.dart'; import '../../components/appbar/appbar.dart'; -import '../../components/button/button.dart'; import '../../components/field/date_range_picker_field.dart'; import '../../components/spacer/spacer.dart'; import 'widgets/payment_method.dart'; @@ -117,17 +116,17 @@ class _ReportPageState extends State with TickerProviderStateMixin { backgroundColor: AppColor.primary, centerTitle: false, flexibleSpace: CustomAppBar( - title: 'Laporan', + title: context.lang.report, isBack: false, ), - actions: [ - ActionIconButton( - onTap: () {}, - icon: LineIcons.download, - ), - ActionIconButton(onTap: () {}, icon: LineIcons.filter), - SpaceWidth(8), - ], + // actions: [ + // ActionIconButton( + // onTap: () {}, + // icon: LineIcons.download, + // ), + // ActionIconButton(onTap: () {}, icon: LineIcons.filter), + // SpaceWidth(8), + // ], ), SliverToBoxAdapter( diff --git a/lib/presentation/pages/report/widgets/payment_method.dart b/lib/presentation/pages/report/widgets/payment_method.dart index dcb1396..3a5e676 100644 --- a/lib/presentation/pages/report/widgets/payment_method.dart +++ b/lib/presentation/pages/report/widgets/payment_method.dart @@ -57,7 +57,7 @@ class ReportPaymentMethod extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Payment Methods', + context.lang.payment_methods, style: AppStyle.xl.copyWith( fontWeight: FontWeight.bold, color: AppColor.textPrimary, @@ -65,7 +65,7 @@ class ReportPaymentMethod extends StatelessWidget { ), const SizedBox(height: 4), Text( - 'Revenue breakdown by payment method', + context.lang.payment_methods_desc, style: AppStyle.sm.copyWith( color: AppColor.textSecondary, ), @@ -80,7 +80,7 @@ class ReportPaymentMethod extends StatelessWidget { // Payment Method List if (paymentMethods.isEmpty) - _buildEmptyState() + _buildEmptyState(context) else ListView.separated( shrinkWrap: true, @@ -190,12 +190,12 @@ class ReportPaymentMethod extends StatelessWidget { const SizedBox(height: 16), // Stats row with better spacing - _buildStatsSection(method), + _buildStatsSection(context, method), const SizedBox(height: 16), // Enhanced progress bar section - _buildProgressSection(method, index), + _buildProgressSection(context, method, index), ], ), ), @@ -410,7 +410,10 @@ class ReportPaymentMethod extends StatelessWidget { ); } - Widget _buildStatsSection(DashboardPaymentMethod method) { + Widget _buildStatsSection( + BuildContext context, + DashboardPaymentMethod method, + ) { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( @@ -426,7 +429,7 @@ class ReportPaymentMethod extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Total Revenue', + context.lang.total_revenue, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -457,7 +460,7 @@ class ReportPaymentMethod extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - 'Orders', + context.lang.orders, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -480,7 +483,11 @@ class ReportPaymentMethod extends StatelessWidget { ); } - Widget _buildProgressSection(DashboardPaymentMethod method, int index) { + Widget _buildProgressSection( + BuildContext context, + DashboardPaymentMethod method, + int index, + ) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -488,7 +495,7 @@ class ReportPaymentMethod extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - 'Revenue Share', + context.lang.revenue_share, style: AppStyle.sm.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w600, @@ -560,11 +567,10 @@ class ReportPaymentMethod extends StatelessWidget { ); } - Widget _buildEmptyState() { + Widget _buildEmptyState(BuildContext context) { return EmptyWidget( - title: 'No Payment Methods', - message: - 'Payment method data will appear here once transactions are made', + title: context.lang.no_payment_methods, + message: context.lang.no_payment_methods_desc, ); } diff --git a/lib/presentation/pages/report/widgets/quick_stats.dart b/lib/presentation/pages/report/widgets/quick_stats.dart index 49d847c..b99ac72 100644 --- a/lib/presentation/pages/report/widgets/quick_stats.dart +++ b/lib/presentation/pages/report/widgets/quick_stats.dart @@ -24,7 +24,7 @@ class ReportQuickStats extends StatelessWidget { return Transform.scale( scale: value, child: ReportStatTile( - title: 'Total Orders', + title: context.lang.total_orders, value: overview.totalOrders.toString(), icon: Icons.receipt_long, color: AppColor.info, @@ -43,7 +43,7 @@ class ReportQuickStats extends StatelessWidget { return Transform.scale( scale: value, child: ReportStatTile( - title: 'Average Order', + title: context.lang.average_price, value: overview.averageOrderValue .round() .currencyFormatRp, @@ -70,7 +70,7 @@ class ReportQuickStats extends StatelessWidget { return Transform.scale( scale: value, child: ReportStatTile( - title: 'Customers', + title: context.lang.customer, value: overview.totalCustomers.toString(), icon: Icons.people, color: AppColor.success, @@ -89,7 +89,8 @@ class ReportQuickStats extends StatelessWidget { return Transform.scale( scale: value, child: ReportStatTile( - title: 'Void + Refund', + title: + '${context.lang.void_text} + ${context.lang.refund}', value: (overview.voidedOrders + overview.refundedOrders) .toString(), diff --git a/lib/presentation/pages/report/widgets/revenue_summary.dart b/lib/presentation/pages/report/widgets/revenue_summary.dart index c3603d9..b3a020e 100644 --- a/lib/presentation/pages/report/widgets/revenue_summary.dart +++ b/lib/presentation/pages/report/widgets/revenue_summary.dart @@ -103,7 +103,7 @@ class ReportRevenueSummary extends StatelessWidget { ), const SpaceWidth(12), Text( - 'Total Pendapatan', + context.lang.total_revenue, style: AppStyle.lg.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w500, diff --git a/lib/presentation/pages/report/widgets/sales.dart b/lib/presentation/pages/report/widgets/sales.dart index 96b1d79..09f46c9 100644 --- a/lib/presentation/pages/report/widgets/sales.dart +++ b/lib/presentation/pages/report/widgets/sales.dart @@ -37,7 +37,7 @@ class ReportSales extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Sales Chart', + context.lang.sales_chart, style: AppStyle.xxl.copyWith( color: AppColor.textPrimary, fontWeight: FontWeight.bold, @@ -46,8 +46,8 @@ class ReportSales extends StatelessWidget { const SpaceHeight(4), Text( salesData.isEmpty - ? 'No data available' - : '${salesData.length} days overview', + ? context.lang.no_data_available + : context.lang.total_days_overview(salesData.length), style: AppStyle.md.copyWith(color: AppColor.textSecondary), ), ], @@ -71,13 +71,13 @@ class ReportSales extends StatelessWidget { // Sales Summary Cards if (salesData.isNotEmpty) ...[ - _buildSalesSummary(), + _buildSalesSummary(context), const SpaceHeight(20), ], // Chart Container salesData.isEmpty - ? _buildEmptyChart() + ? _buildEmptyChart(context) : Container( height: 300, padding: const EdgeInsets.all(16), @@ -105,14 +105,16 @@ class ReportSales extends StatelessWidget { if (salesData.isNotEmpty) Row( mainAxisAlignment: MainAxisAlignment.center, - children: [_buildLegendItem('Sales Data', AppColor.primary)], + children: [ + _buildLegendItem(context.lang.sales_data, AppColor.primary), + ], ), ], ), ); } - Widget _buildSalesSummary() { + Widget _buildSalesSummary(BuildContext context) { final totalSales = salesData.fold(0, (sum, item) => sum + item.sales); final totalOrders = salesData.fold( 0, @@ -137,7 +139,7 @@ class ReportSales extends StatelessWidget { children: [ Expanded( child: _buildSummaryItem( - 'Total Sales', + context.lang.total_sales, totalSales.currencyFormatRp, Icons.attach_money, AppColor.success, @@ -151,7 +153,7 @@ class ReportSales extends StatelessWidget { ), Expanded( child: _buildSummaryItem( - 'Net Sales', + context.lang.net_sales, totalNetSales.currencyFormatRp, Icons.trending_up, AppColor.primary, @@ -164,7 +166,7 @@ class ReportSales extends StatelessWidget { children: [ Expanded( child: _buildSummaryItem( - 'Total Orders', + context.lang.total_orders, totalOrders.toString(), Icons.shopping_cart, AppColor.info, @@ -178,7 +180,7 @@ class ReportSales extends StatelessWidget { ), Expanded( child: _buildSummaryItem( - 'Total Items', + context.lang.total_items, totalItems.toString(), Icons.inventory, AppColor.warning, @@ -204,11 +206,15 @@ class ReportSales extends StatelessWidget { children: [ Icon(icon, size: 16, color: color), const SpaceWidth(6), - Text( - label, - style: AppStyle.xs.copyWith( - color: AppColor.textSecondary, - fontWeight: FontWeight.w500, + Expanded( + child: Text( + label, + style: AppStyle.xs.copyWith( + color: AppColor.textSecondary, + fontWeight: FontWeight.w500, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, ), ), ], @@ -395,10 +401,10 @@ class ReportSales extends StatelessWidget { ); } - Widget _buildEmptyChart() { + Widget _buildEmptyChart(BuildContext context) { return EmptyWidget( - title: 'No Sales Data', - message: 'Sales data will appear here once transactions are recorded', + title: context.lang.no_sales_data, + message: context.lang.no_sales_data_desc, emptyIcon: Icons.show_chart, ); } diff --git a/lib/presentation/pages/report/widgets/top_product.dart b/lib/presentation/pages/report/widgets/top_product.dart index 7e914d9..0f4bd81 100644 --- a/lib/presentation/pages/report/widgets/top_product.dart +++ b/lib/presentation/pages/report/widgets/top_product.dart @@ -34,7 +34,7 @@ class ReportTopProduct extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Produk Terlaris', + context.lang.best_selling_products, style: AppStyle.xxl.copyWith( color: AppColor.textPrimary, fontWeight: FontWeight.bold, @@ -42,7 +42,7 @@ class ReportTopProduct extends StatelessWidget { ), const SpaceHeight(4), Text( - 'Ranking penjualan tertinggi', + context.lang.highest_sales_ranking, style: AppStyle.md.copyWith(color: AppColor.textSecondary), ), ], @@ -66,7 +66,11 @@ class ReportTopProduct extends StatelessWidget { shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { - return _buildEnhancedProductItem(products[index], index + 1); + return _buildEnhancedProductItem( + context, + products[index], + index + 1, + ); }, itemCount: products.length, ), @@ -75,7 +79,11 @@ class ReportTopProduct extends StatelessWidget { ); } - Widget _buildEnhancedProductItem(DashboardTopProduct product, int rank) { + Widget _buildEnhancedProductItem( + BuildContext context, + DashboardTopProduct product, + int rank, + ) { final isFirst = rank == 1; final isTopThree = rank <= 3; @@ -320,7 +328,7 @@ class ReportTopProduct extends StatelessWidget { const SpaceWidth(3), Flexible( child: Text( - 'Revenue', + context.lang.revenue, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -364,7 +372,7 @@ class ReportTopProduct extends StatelessWidget { children: [ Flexible( child: Text( - 'Avg. Price', + context.lang.average_price, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -423,7 +431,7 @@ class ReportTopProduct extends StatelessWidget { const SpaceWidth(3), Flexible( child: Text( - 'Sold', + context.lang.sold, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -465,7 +473,7 @@ class ReportTopProduct extends StatelessWidget { children: [ Flexible( child: Text( - 'Orders', + context.lang.orders, style: AppStyle.xs.copyWith( color: AppColor.textSecondary, fontWeight: FontWeight.w500, @@ -543,7 +551,9 @@ class ReportTopProduct extends StatelessWidget { const SpaceWidth(5), Flexible( child: Text( - isFirst ? 'Best Seller' : 'Top Performer', + isFirst + ? context.lang.best_seller + : context.lang.top_performer, style: AppStyle.xs.copyWith( color: isFirst ? AppColor.warning diff --git a/lib/presentation/pages/sales/sales_page.dart b/lib/presentation/pages/sales/sales_page.dart index a54d53f..d5eed33 100644 --- a/lib/presentation/pages/sales/sales_page.dart +++ b/lib/presentation/pages/sales/sales_page.dart @@ -97,7 +97,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { floating: false, pinned: true, backgroundColor: AppColor.primary, - flexibleSpace: CustomAppBar(title: 'Penjualan'), + flexibleSpace: CustomAppBar(title: context.lang.sales), ), // Date Range Header @@ -138,7 +138,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Summary', + context.lang.summary, style: AppStyle.xxl.copyWith( fontWeight: FontWeight.bold, color: AppColor.textPrimary, @@ -177,7 +177,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { child: Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), child: Text( - 'Daily Breakdown', + context.lang.daily_breakdown, style: TextStyle( fontSize: 20, fontWeight: FontWeight.bold, @@ -412,7 +412,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { children: [ Expanded( child: _buildSummaryCard( - 'Total Sales', + context.lang.total_sales, state.sales.summary.totalSales.currencyFormatRp, Icons.trending_up, AppColor.success, @@ -422,7 +422,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { SpaceWidth(12), Expanded( child: _buildSummaryCard( - 'Total Orders', + context.lang.total_orders, state.sales.summary.totalOrders.toString(), Icons.shopping_cart, AppColor.info, @@ -446,7 +446,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { children: [ Expanded( child: _buildSummaryCard( - 'Avg Order Value', + context.lang.average_price, state.sales.summary.averageOrderValue .round() .currencyFormatRp, @@ -458,7 +458,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { SpaceWidth(12), Expanded( child: _buildSummaryCard( - 'Total Items', + context.lang.total_items, state.sales.summary.totalItems.toString(), Icons.inventory, AppColor.primary, @@ -530,7 +530,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - 'Net Sales', + context.lang.net_sales, style: TextStyle( color: AppColor.textWhite.withOpacity(0.9), fontSize: 14, @@ -668,7 +668,7 @@ class _SalesPageState extends State with TickerProviderStateMixin { borderRadius: BorderRadius.circular(20), ), child: Text( - '${dailySale.orders} orders', + '${dailySale.orders} ${context.lang.orders}', style: TextStyle( color: AppColor.info, fontWeight: FontWeight.w500, @@ -683,21 +683,21 @@ class _SalesPageState extends State with TickerProviderStateMixin { children: [ Expanded( child: _buildDetailItem( - 'Items', + context.lang.items, '${dailySale.items}', Icons.inventory_2, ), ), Expanded( child: _buildDetailItem( - 'Tax', + context.lang.tax, dailySale.tax.currencyFormatRp, Icons.receipt, ), ), Expanded( child: _buildDetailItem( - 'Discount', + context.lang.discount, dailySale.discount.currencyFormatRp, Icons.local_offer, ), diff --git a/lib/presentation/pages/schedule/schedule_page.dart b/lib/presentation/pages/schedule/schedule_page.dart index 89ae7bd..7aaeacc 100644 --- a/lib/presentation/pages/schedule/schedule_page.dart +++ b/lib/presentation/pages/schedule/schedule_page.dart @@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:table_calendar/table_calendar.dart'; +import '../../../common/extension/extension.dart'; import '../../../common/theme/theme.dart'; import '../../components/appbar/appbar.dart'; @@ -213,7 +214,7 @@ class _SchedulePageState extends State floating: false, pinned: true, backgroundColor: AppColor.primary, - flexibleSpace: CustomAppBar(title: 'Jadwal'), + flexibleSpace: CustomAppBar(title: context.lang.schedule), ); }