Compare commits

...

2 Commits

Author SHA1 Message Date
Flatlogic Bot
da3c00f31c MICRA 1.0 2026-06-29 06:18:56 +00:00
Flatlogic Bot
0c89516ec1 MICRA 1.0 2026-06-29 05:34:01 +00:00
82 changed files with 2712 additions and 982 deletions

View File

@ -0,0 +1,483 @@
{
"language": {
"id": "Bahasa Indonesia",
"en-GB": "English UK"
},
"app": {
"title": "Aquaculture Ops CRUD",
"description": "Multi-tenant aquaculture operations and marketplace CRUD with RBAC, orders, transactions, audit logs, and APIs."
},
"pages": {
"dashboard": {
"pageTitle": "Dashboard",
"overview": "Overview",
"loadingWidgets": "Loading widgets...",
"loading": "Loading..."
},
"login": {
"pageTitle": "Login",
"sampleCredentialsAdmin": "Use {{email}} / {{password}} to log in as Administrator",
"sampleCredentialsUser": "Use {{email}} / {{password}} to log in as User",
"form": {
"loginLabel": "Login",
"loginHelp": "Please enter your login",
"passwordLabel": "Password",
"passwordHelp": "Please enter your password",
"remember": "Remember",
"forgotPassword": "Forgot password?",
"loginButton": "Login",
"loading": "Loading...",
"noAccountYet": "Dont have an account yet?",
"newAccount": "New account"
},
"pexels": {
"photoCredit": "Photo by {{photographer}} on Pexels",
"videoCredit": "Video by {{name}} on Pexels",
"videoUnsupported": "Your browser does not support the video tag."
},
"footer": {
"copyright": "© {{year}} {{title}}. All rights reserved",
"privacy": "Privacy Policy"
}
}
},
"components": {
"widgetCreator": {
"title": "Create chart or widget",
"helpText": "Describe your new widget or chart in natural language. For example: \"Number of admin users\" OR \"red chart with number of closed contracts grouped by month\"",
"settingsTitle": "Widget Creator settings",
"settingsDescription": "What role are we showing and creating widgets for?",
"doneButton": "Done",
"loading": "Loading..."
},
"search": {
"placeholder": "Search",
"required": "Required",
"minLength": "Minimum length: {{count}} characters"
}
},
"labels": {
"overview": "Overview",
"dashboard": "Dashboard",
"farm_ops_command_center": "Farm Ops Command Centre",
"multi_tenant_aquaculture_workflow": "Multi-tenant aquaculture workflow",
"record_feed_monitor_appetite_and_keep_the_farm_team_aligned": "Record feed, monitor appetite, and keep the farm team aligned.",
"a_focused_daily_operations_slice_built_on_top_of_your_generated_crud_entities_batches_feed_products_and_feeding_logs": "A focused daily operations slice built on top of your generated CRUD entities: batches, feed products, and feeding logs.",
"fed_today": "Fed today",
"active_batches": "Active batches",
"latest_appetite": "Latest appetite",
"quick_feed_entry": "Quick feed entry",
"record_the_most_common_daily_farm_action_without_leaving_the_operations_context": "Record the most common daily farm action without leaving the operations context.",
"saving": "Saving...",
"loading_farm_data": "Loading farm data...",
"recent_activity": "Recent activity",
"latest_feeding_logs_from_the_generated_crud_api": "Latest feeding logs from the generated CRUD API.",
"record_snapshot": "Record snapshot",
"detail": "Detail",
"batch_context": "Batch context",
"daily_rhythm": "Daily rhythm",
"marketplace_ready": "Marketplace ready",
"every_record_is_tied_to_generated_batch_crud_for_traceability": "Every record is tied to generated batch CRUD for traceability.",
"fast_input_supports_the_staff_workflow_farmers_repeat_every_shift": "Fast input supports the staff workflow farmers repeat every shift.",
"operational_records_are_one_step_away_from_harvest_listing_order_and_transaction_flows": "Operational records are one step away from harvest, listing, order, and transaction flows.",
"no_feeding_logs_yet": "No feeding logs yet",
"use_the_quick_entry_form_to_create_the_first_daily_operation_record": "Use the quick entry form to create the first daily operation record.",
"select_a_feeding_log_to_inspect_its_farm_ready_details": "Select a feeding log to inspect its farm-ready details.",
"no_notes_added_for_this_operation": "No notes added for this operation.",
"team_member": "Team member",
"unassigned_batch": "Unassigned batch",
"not_specified": "Not specified",
"not_scheduled": "Not scheduled",
"batch_before_recording_feed": "Choose a batch before recording feed.",
"add_the_feeding_time": "Add the feeding time.",
"feed_quantity_must_be_greater_than_0_kg": "Feed quantity must be greater than 0 kg.",
"feeding_record_saved_the_latest_activity_list_has_been_refreshed": "Feeding record saved. The latest activity list has been refreshed.",
"could_not_load_the_farm_operations_workspace_please_refresh_or_check_your_permissions": "Could not load the farm operations workspace. Please refresh or check your permissions.",
"could_not_save_the_feeding_record_please_check_the_values_and_try_again": "Could not save the feeding record. Please check the values and try again.",
"you_can_view_existing_data_but_need_create_feeding_logs_permission_to_save_new_records": "You can view existing data, but need Create Feeding Logs permission to save new records.",
"create_your_first_batch_before_recording_feed": "Create your first batch before recording feed.",
"select_a_batch": "Select a batch",
"select_feed_product_optional": "Select feed product (optional)",
"optional_notes_for_the_next_shift": "Optional notes for the next shift",
"page": "Page",
"of": "of",
"please_confirm": "Please confirm",
"are_you_sure_you_want_to_delete_this_item": "Are you sure you want to delete this item?",
"allowed_formats": "Allowed formats: {{formats}}",
"click_to_upload": "Click to upload",
"or_drag_and_drop": "or drag and drop",
"switch_to_table": "Switch to table",
"switch_to_cards": "Switch to cards",
"users_widgets": "{{role}}'s widgets",
"no_data": "No data",
"matches_with": "Matches with: {{query}}",
"no_matches": "No matches",
"quick_input": "Quick input",
"log_a_feeding": "Log a feeding",
"capture_the_minimum_operational_data_and_confirm_it_immediately": "Capture the minimum operational data and confirm it immediately.",
"loading_batches_and_feed_products": "Loading batches and feed products...",
"no_batches_available_yet": "No batches available yet.",
"create_a_batch_first_then_return_here_to_record_daily_feeding_activity": "Create a batch first, then return here to record daily feeding activity.",
"optional_observation_e_g_fish_surfaced_quickly_mild_leftovers_weather_change": "Optional observation, e.g. fish surfaced quickly, mild leftovers, weather change...",
"your_role_can_view_feeding_logs_but_cannot_create_new_records": "Your role can view feeding logs but cannot create new records.",
"activity_stream": "Activity stream",
"latest_feeding_logs": "Latest feeding logs",
"loading_latest_records": "Loading latest records...",
"use_the_quick_input_form_to_create_the_first_daily_operation_record": "Use the quick input form to create the first daily operation record.",
"by": "by",
"recorded": "Recorded",
"feed": "Feed",
"method": "Method",
"choose_a_batch_before_recording_feed": "Choose a batch before recording feed.",
"login": "Login",
"password": "Password",
"please_enter_your_login": "Please enter your login",
"please_enter_your_password": "Please enter your password",
"remember": "Remember",
"loading": "Loading..."
},
"crud": {
"actions": {
"new": "New",
"view": "View",
"edit": "Edit",
"delete": "Delete",
"submit": "Submit",
"reset": "Reset",
"cancel": "Cancel",
"confirm": "Confirm",
"filter": "Filter",
"apply": "Apply",
"download_csv": "Download CSV",
"upload_csv": "Upload CSV",
"new_item": "New item",
"open_full_crud": "Open full CRUD",
"open_detail": "Open detail",
"marketplace": "Marketplace",
"delete_rows": "Delete {{count}} row(s)",
"deleting": "Deleting...",
"select_value": "Select value",
"from": "From",
"to": "To",
"contains": "Contains",
"contained": "Contained",
"value": "Value",
"action": "Action",
"create_batch": "Create batch",
"save_feeding_record": "Save feeding record",
"advanced_form": "Advanced form",
"refresh": "Refresh"
}
},
"fields": {
"id": "ID",
"name": "Name",
"first_name": "First name",
"lastname": "Last name",
"last_name": "Last name",
"phone_number": "Phone number",
"email": "Email",
"disabled": "Disabled",
"password": "Password",
"provider": "Provider",
"custom_permissions": "Custom permissions",
"custom_permissions_filter": "Custom permissions filter",
"email_verified": "Email verified",
"email_verification_token": "Email verification token",
"email_verification_token_expires_at": "Email verification token expires at",
"password_reset_token": "Password reset token",
"password_reset_token_expires_at": "Password reset token expires at",
"app_role": "App role",
"avatar": "Avatar",
"created_by": "Created by",
"updated_by": "Updated by",
"created_at": "Created at",
"updated_at": "Updated at",
"organizations": "Organisations",
"organization": "Organisation",
"tenant": "Tenant",
"location": "Location",
"pond": "Pond",
"batch": "Batch",
"species": "Species",
"user": "User",
"role": "Role",
"permissions": "Permissions",
"permission": "Permission",
"pond_name": "Pond name",
"pond_type": "Pond type",
"area_sq_m": "Area (sq m)",
"average_depth_m": "Average depth (m)",
"avg_depth_m": "Average depth (m)",
"notes": "Notes",
"status": "Status",
"species_name": "Species name",
"scientific_name": "Scientific name",
"typical_harvest_size": "Typical harvest size",
"batch_code": "Batch code",
"stocked_at": "Stocked at",
"initial_count": "Initial count",
"initial_avg_weight_g": "Initial average weight (g)",
"initial_average_weight_g": "Initial average weight (g)",
"batch_status": "Batch status",
"expected_harvest_at": "Expected harvest at",
"product_name": "Product name",
"brand": "Brand",
"feed_type": "Feed type",
"protein_percent": "Protein %",
"fat_percent": "Fat %",
"pellet_size_mm": "Pellet size (mm)",
"fed_at": "Fed at",
"quantity_kg": "Quantity (kg)",
"feeding_method": "Feeding method",
"appetite": "Appetite",
"recorded_by": "Recorded by",
"sampled_at": "Sampled at",
"temperature_c": "Temperature (°C)",
"ph": "pH",
"dissolved_oxygen_mg_l": "Dissolved oxygen (mg/L)",
"salinity_ppt": "Salinity (ppt)",
"ammonia_mg_l": "Ammonia (mg/L)",
"nitrite_mg_l": "Nitrite (mg/L)",
"nitrate_mg_l": "Nitrate (mg/L)",
"turbidity_ntu": "Turbidity (NTU)",
"observed_at": "Observed at",
"event_type": "Event type",
"severity": "Severity",
"mortality_count": "Mortality count",
"symptoms": "Symptoms",
"treatment": "Treatment",
"resolution_status": "Resolution status",
"resolved_at": "Resolved at",
"reported_by": "Reported by",
"attachments": "Attachments",
"item_category": "Item category",
"item_name": "Item name",
"sku": "SKU",
"unit": "Unit",
"quantity_on_hand": "Quantity on hand",
"reorder_level": "Reorder level",
"unit_cost": "Unit cost",
"inventory_item": "Inventory item",
"feed_product": "Feed product",
"movement_type": "Movement type",
"quantity": "Quantity",
"moved_at": "Moved at",
"reference": "Reference",
"source": "Source",
"destination": "Destination",
"harvested_at": "Harvested at",
"total_weight_kg": "Total weight (kg)",
"total_count": "Total count",
"avg_weight_g": "Average weight (g)",
"grade": "Grade",
"listing_title": "Listing title",
"description": "Description",
"product_form": "Product form",
"available_quantity_kg": "Available quantity (kg)",
"price_per_kg": "Price per kg",
"currency": "Currency",
"available_from": "Available from",
"expires_at": "Expires at",
"listing_status": "Listing status",
"seller_tenant": "Seller tenant",
"buyer_tenant": "Buyer tenant",
"farm_tenant": "Farm tenant",
"investor_tenant": "Investor tenant",
"harvest": "Harvest",
"fulfillment_location": "Fulfilment location",
"photos": "Photos",
"order_number": "Order number",
"ordered_at": "Ordered at",
"order_status": "Order status",
"subtotal_amount": "Subtotal amount",
"tax_amount": "Tax amount",
"shipping_amount": "Shipping amount",
"total_amount": "Total amount",
"delivery_address": "Delivery address",
"buyer_notes": "Buyer notes",
"expected_delivery_at": "Expected delivery at",
"listing": "Listing",
"order": "Order",
"unit_price": "Unit price",
"line_total": "Line total",
"transaction_type": "Transaction type",
"transaction_status": "Transaction status",
"amount": "Amount",
"provider_reference": "Provider reference",
"processed_at": "Processed at",
"failure_reason": "Failure reason",
"shipment_status": "Shipment status",
"carrier": "Carrier",
"tracking_number": "Tracking number",
"status_at": "Status at",
"status_details": "Status details",
"investment_name": "Investment name",
"instrument_type": "Instrument type",
"amount_committed": "Amount committed",
"amount_funded": "Amount funded",
"committed_at": "Committed at",
"funded_at": "Funded at",
"investment_status": "Investment status",
"to_email": "To email",
"subject": "Subject",
"template_key": "Template key",
"payload": "Payload",
"send_status": "Send status",
"sent_at": "Sent at",
"recipient_user": "Recipient user",
"action": "Action",
"entity_name": "Entity name",
"entity_reference": "Entity reference",
"occurred_at": "Occurred at",
"ip_address": "IP address",
"user_agent": "User agent",
"change_summary": "Change summary",
"actor_user": "Actor user",
"key_name": "Key name",
"key_prefix": "Key prefix",
"access_level": "Access level",
"last_used_at": "Last used at",
"is_revoked": "Is revoked",
"endpoint_name": "Endpoint name",
"url": "URL",
"secret": "Secret",
"is_enabled": "Is enabled",
"event_types": "Event types",
"last_delivery_at": "Last delivery at",
"endpoint": "Endpoint",
"event_reference": "Event reference",
"delivered_at": "Delivered at",
"delivery_status": "Delivery status",
"http_status": "HTTP status",
"request_payload": "Request payload",
"response_body": "Response body",
"attempt_count": "Attempt count",
"job_type": "Job type",
"job_status": "Job status",
"total_rows": "Total rows",
"processed_rows": "Processed rows",
"error_rows": "Error rows",
"error_report": "Error report",
"started_at": "Started at",
"finished_at": "Finished at",
"requested_by": "Requested by",
"source_file": "Source file",
"result_file": "Result file",
"membership_status": "Membership status",
"joined_at": "Joined at",
"tenant_name": "Tenant name",
"slug": "Slug",
"tenant_type": "Tenant type",
"contact_email": "Contact email",
"contact_phone": "Contact phone",
"billing_address": "Billing address",
"subscription_status": "Subscription status",
"trial_ends_at": "Trial ends at",
"location_name": "Location name",
"address": "Address",
"latitude": "Latitude",
"longitude": "Longitude",
"timezone": "Time zone",
"is_primary": "Is primary",
"role_customization": "Role customisation",
"global_access": "Global access",
"permissions_filter": "Permissions filter",
"multi_text": "Multi text"
},
"entities": {
"dashboard": "Dashboard",
"farm_ops": "Farm Ops",
"users": "Users",
"user": "User",
"roles": "Roles",
"role": "Role",
"permissions": "Permissions",
"permission": "Permission",
"organizations": "Organisations",
"organization": "Organisation",
"tenants": "Tenants",
"tenant": "Tenant",
"user_memberships": "User memberships",
"user_membership": "User membership",
"tenant_locations": "Tenant locations",
"tenant_location": "Tenant location",
"ponds": "Ponds",
"pond": "Pond",
"species": "Species",
"batches": "Batches",
"batch": "Batch",
"feed_products": "Feed products",
"feed_product": "Feed product",
"feeding_logs": "Feeding logs",
"feeding_log": "Feeding log",
"water_quality_logs": "Water quality logs",
"water_quality_log": "Water quality log",
"health_events": "Health events",
"health_event": "Health event",
"inventory_items": "Inventory items",
"inventory_item": "Inventory item",
"inventory_movements": "Inventory movements",
"inventory_movement": "Inventory movement",
"harvests": "Harvests",
"harvest": "Harvest",
"marketplace_listings": "Marketplace listings",
"marketplace_listing": "Marketplace listing",
"orders": "Orders",
"order": "Order",
"order_items": "Order items",
"order_item": "Order item",
"payment_transactions": "Payment transactions",
"payment_transaction": "Payment transaction",
"shipment_updates": "Shipment updates",
"shipment_update": "Shipment update",
"investments": "Investments",
"investment": "Investment",
"email_notifications": "Email notifications",
"email_notification": "Email notification",
"audit_logs": "Audit logs",
"audit_log": "Audit log",
"api_keys": "API keys",
"api_key": "API key",
"webhook_endpoints": "Webhook endpoints",
"webhook_endpoint": "Webhook endpoint",
"webhook_deliveries": "Webhook deliveries",
"webhook_delivery": "Webhook delivery",
"csv_jobs": "CSV jobs",
"csv_job": "CSV job"
},
"enums": {
"active": "Active",
"inactive": "Inactive",
"maintenance": "Maintenance",
"planned": "Planned",
"harvested": "Harvested",
"closed": "Closed",
"lost": "Lost",
"manual": "Manual",
"auto_feeder": "Auto feeder",
"broadcast": "Broadcast",
"tray": "Tray",
"low": "Low",
"normal": "Normal",
"high": "High",
"pending": "Pending",
"confirmed": "Confirmed",
"packed": "Packed",
"shipped": "Shipped",
"delivered": "Delivered",
"canceled": "Cancelled",
"refunded": "Refunded",
"draft": "Draft",
"paused": "Paused",
"sold_out": "Sold out",
"expired": "Expired",
"removed": "Removed",
"earthen": "Earthen",
"lined": "Lined",
"tank": "Tank",
"cage": "Cage",
"raceway": "Raceway",
"other": "Other"
}
}

View File

@ -0,0 +1,484 @@
{
"language": {
"id": "Bahasa Indonesia",
"en-GB": "English UK"
},
"app": {
"title": "CRUD Operasi Akuakultur",
"description": "CRUD operasi akuakultur dan marketplace multi-tenant dengan RBAC, pesanan, transaksi, log audit, dan API."
},
"pages": {
"dashboard": {
"pageTitle": "Dasbor",
"overview": "Ringkasan",
"loadingWidgets": "Memuat widget...",
"loading": "Memuat..."
},
"login": {
"pageTitle": "Masuk",
"sampleCredentialsAdmin": "Gunakan {{email}} / {{password}} untuk masuk sebagai Administrator",
"sampleCredentialsUser": "Gunakan {{email}} / {{password}} untuk masuk sebagai Pengguna",
"form": {
"loginLabel": "Login",
"loginHelp": "Masukkan login Anda",
"passwordLabel": "Kata sandi",
"passwordHelp": "Masukkan kata sandi Anda",
"remember": "Ingat saya",
"forgotPassword": "Lupa kata sandi?",
"loginButton": "Masuk",
"loading": "Memuat...",
"noAccountYet": "Belum punya akun?",
"newAccount": "Akun baru"
},
"pexels": {
"photoCredit": "Foto oleh {{photographer}} di Pexels",
"videoCredit": "Video oleh {{name}} di Pexels",
"videoUnsupported": "Browser Anda tidak mendukung tag video."
},
"footer": {
"copyright": "© {{year}} {{title}}. Semua hak dilindungi",
"privacy": "Kebijakan Privasi"
}
}
},
"components": {
"widgetCreator": {
"title": "Buat grafik atau widget",
"helpText": "Jelaskan widget atau grafik baru dengan bahasa natural. Contoh: \"Jumlah pengguna admin\" ATAU \"grafik merah berisi jumlah kontrak selesai dikelompokkan per bulan\"",
"settingsTitle": "Pengaturan pembuat widget",
"settingsDescription": "Widget ditampilkan dan dibuat untuk peran apa?",
"doneButton": "Selesai",
"loading": "Memuat..."
},
"search": {
"placeholder": "Cari",
"required": "Wajib",
"minLength": "Panjang minimum: {{count}} karakter"
}
},
"labels": {
"overview": "Ringkasan",
"dashboard": "Dasbor",
"farm_ops_command_center": "Pusat Komando Operasi Tambak",
"multi_tenant_aquaculture_workflow": "Alur kerja akuakultur multi-tenant",
"record_feed_monitor_appetite_and_keep_the_farm_team_aligned": "Catat pakan, pantau nafsu makan, dan selaraskan tim tambak.",
"a_focused_daily_operations_slice_built_on_top_of_your_generated_crud_entities_batches_feed_products_and_feeding_logs": "Bagian operasi harian yang fokus, dibangun di atas entitas CRUD yang sudah dibuat: batch, produk pakan, dan log pemberian pakan.",
"fed_today": "Pakan hari ini",
"active_batches": "Batch aktif",
"latest_appetite": "Nafsu makan terbaru",
"quick_feed_entry": "Input pakan cepat",
"record_the_most_common_daily_farm_action_without_leaving_the_operations_context": "Catat aktivitas harian tambak yang paling umum tanpa keluar dari konteks operasi.",
"saving": "Menyimpan...",
"loading_farm_data": "Memuat data tambak...",
"recent_activity": "Aktivitas terbaru",
"latest_feeding_logs_from_the_generated_crud_api": "Log pemberian pakan terbaru dari API CRUD yang sudah dibuat.",
"record_snapshot": "Ringkasan catatan",
"detail": "Detail",
"batch_context": "Konteks batch",
"daily_rhythm": "Ritme harian",
"marketplace_ready": "Siap marketplace",
"every_record_is_tied_to_generated_batch_crud_for_traceability": "Setiap catatan terhubung ke CRUD batch untuk keterlacakan.",
"fast_input_supports_the_staff_workflow_farmers_repeat_every_shift": "Input cepat mendukung alur kerja staf yang diulang petani setiap shift.",
"operational_records_are_one_step_away_from_harvest_listing_order_and_transaction_flows": "Catatan operasi selangkah lagi dari alur panen, listing, pesanan, dan transaksi.",
"no_feeding_logs_yet": "Belum ada log pemberian pakan",
"use_the_quick_entry_form_to_create_the_first_daily_operation_record": "Gunakan formulir input cepat untuk membuat catatan operasi harian pertama.",
"select_a_feeding_log_to_inspect_its_farm_ready_details": "Pilih log pemberian pakan untuk melihat detail siap pakai di tambak.",
"no_notes_added_for_this_operation": "Belum ada catatan untuk operasi ini.",
"team_member": "Anggota tim",
"unassigned_batch": "Batch belum ditetapkan",
"not_specified": "Belum ditentukan",
"not_scheduled": "Belum dijadwalkan",
"batch_before_recording_feed": "Pilih batch sebelum mencatat pakan.",
"add_the_feeding_time": "Tambahkan waktu pemberian pakan.",
"feed_quantity_must_be_greater_than_0_kg": "Jumlah pakan harus lebih dari 0 kg.",
"feeding_record_saved_the_latest_activity_list_has_been_refreshed": "Catatan pakan tersimpan. Daftar aktivitas terbaru telah diperbarui.",
"could_not_load_the_farm_operations_workspace_please_refresh_or_check_your_permissions": "Tidak dapat memuat ruang kerja operasi tambak. Silakan muat ulang atau periksa izin Anda.",
"could_not_save_the_feeding_record_please_check_the_values_and_try_again": "Tidak dapat menyimpan catatan pakan. Periksa nilai yang diisi lalu coba lagi.",
"you_can_view_existing_data_but_need_create_feeding_logs_permission_to_save_new_records": "Anda dapat melihat data yang ada, tetapi perlu izin Buat Log Pemberian Pakan untuk menyimpan catatan baru.",
"create_your_first_batch_before_recording_feed": "Buat batch pertama sebelum mencatat pakan.",
"select_a_batch": "Pilih batch",
"select_feed_product_optional": "Pilih produk pakan (opsional)",
"optional_notes_for_the_next_shift": "Catatan opsional untuk shift berikutnya",
"page": "Halaman",
"of": "dari",
"please_confirm": "Mohon konfirmasi",
"are_you_sure_you_want_to_delete_this_item": "Apakah Anda yakin ingin menghapus item ini?",
"allowed_formats": "Format yang diizinkan: {{formats}}",
"click_to_upload": "Klik untuk mengunggah",
"or_drag_and_drop": "atau seret dan lepas",
"switch_to_table": "Beralih ke tabel",
"switch_to_cards": "Beralih ke kartu",
"users_widgets": "Widget milik {{role}}",
"no_data": "Tidak ada data",
"matches_with": "Cocok dengan: {{query}}",
"no_matches": "Tidak ada hasil",
"quick_input": "Input cepat",
"log_a_feeding": "Catat pemberian pakan",
"capture_the_minimum_operational_data_and_confirm_it_immediately": "Isi data operasi minimum dan konfirmasi langsung.",
"loading_batches_and_feed_products": "Memuat batch dan produk pakan...",
"no_batches_available_yet": "Belum ada batch.",
"create_a_batch_first_then_return_here_to_record_daily_feeding_activity": "Buat batch terlebih dahulu, lalu kembali ke sini untuk mencatat aktivitas pakan harian.",
"optional_observation_e_g_fish_surfaced_quickly_mild_leftovers_weather_change": "Observasi opsional, mis. ikan cepat naik, sedikit sisa pakan, perubahan cuaca...",
"your_role_can_view_feeding_logs_but_cannot_create_new_records": "Peran Anda dapat melihat log pakan, tetapi tidak dapat membuat catatan baru.",
"activity_stream": "Alur aktivitas",
"latest_feeding_logs": "Log pakan terbaru",
"loading_latest_records": "Memuat catatan terbaru...",
"use_the_quick_input_form_to_create_the_first_daily_operation_record": "Gunakan formulir input cepat untuk membuat catatan operasi harian pertama.",
"by": "oleh",
"recorded": "Dicatat",
"feed": "Pakan",
"method": "Metode",
"choose_a_batch_before_recording_feed": "Pilih batch sebelum mencatat pakan.",
"login": "Masuk",
"password": "Kata sandi",
"please_enter_your_login": "Masukkan login Anda",
"please_enter_your_password": "Masukkan kata sandi Anda",
"remember": "Ingat saya",
"loading": "Memuat..."
},
"crud": {
"actions": {
"new": "Buat",
"view": "Lihat",
"edit": "Edit",
"delete": "Hapus",
"submit": "Simpan",
"reset": "Reset",
"cancel": "Batal",
"confirm": "Konfirmasi",
"filter": "Filter",
"apply": "Terapkan",
"download_csv": "Unduh CSV",
"upload_csv": "Unggah CSV",
"new_item": "Item baru",
"open_full_crud": "Buka CRUD lengkap",
"open_detail": "Buka detail",
"marketplace": "Marketplace",
"delete_rows": "Hapus {{count}} baris",
"deleting": "Menghapus...",
"select_value": "Pilih nilai",
"from": "Dari",
"to": "Sampai",
"contains": "Berisi",
"contained": "Berisi",
"value": "Nilai",
"action": "Aksi",
"create_batch": "Buat batch",
"save_feeding_record": "Simpan catatan pakan",
"advanced_form": "Form lanjutan",
"refresh": "Segarkan"
}
},
"fields": {
"id": "ID",
"name": "Nama",
"first_name": "Nama depan",
"firstname": "Nama depan",
"last_name": "Nama belakang",
"lastname": "Nama belakang",
"phone_number": "Nomor telepon",
"email": "Email",
"disabled": "Dinonaktifkan",
"password": "Kata sandi",
"provider": "Penyedia",
"custom_permissions": "Izin khusus",
"custom_permissions_filter": "Filter izin khusus",
"email_verified": "Email terverifikasi",
"email_verification_token": "Token verifikasi email",
"email_verification_token_expires_at": "Token verifikasi email kedaluwarsa pada",
"password_reset_token": "Token reset kata sandi",
"password_reset_token_expires_at": "Token reset kata sandi kedaluwarsa pada",
"app_role": "Peran aplikasi",
"avatar": "Avatar",
"created_by": "Dibuat oleh",
"updated_by": "Diperbarui oleh",
"created_at": "Dibuat pada",
"updated_at": "Diperbarui pada",
"organizations": "Organisasi",
"organization": "Organisasi",
"tenant": "Tenant",
"location": "Lokasi",
"pond": "Kolam",
"batch": "Batch",
"species": "Spesies",
"user": "Pengguna",
"role": "Peran",
"permissions": "Izin",
"permission": "Izin",
"pond_name": "Nama kolam",
"pond_type": "Tipe kolam",
"area_sq_m": "Luas (m²)",
"average_depth_m": "Kedalaman rata-rata (m)",
"avg_depth_m": "Kedalaman rata-rata (m)",
"notes": "Catatan",
"status": "Status",
"species_name": "Nama spesies",
"scientific_name": "Nama ilmiah",
"typical_harvest_size": "Ukuran panen umum",
"batch_code": "Kode batch",
"stocked_at": "Tanggal tebar",
"initial_count": "Jumlah awal",
"initial_avg_weight_g": "Bobot rata-rata awal (g)",
"initial_average_weight_g": "Bobot rata-rata awal (g)",
"batch_status": "Status batch",
"expected_harvest_at": "Perkiraan panen pada",
"product_name": "Nama produk",
"brand": "Merek",
"feed_type": "Jenis pakan",
"protein_percent": "Protein %",
"fat_percent": "Lemak %",
"pellet_size_mm": "Ukuran pelet (mm)",
"fed_at": "Waktu pemberian pakan",
"quantity_kg": "Jumlah (kg)",
"feeding_method": "Metode pemberian pakan",
"appetite": "Nafsu makan",
"recorded_by": "Dicatat oleh",
"sampled_at": "Waktu sampel",
"temperature_c": "Suhu (°C)",
"ph": "pH",
"dissolved_oxygen_mg_l": "Oksigen terlarut (mg/L)",
"salinity_ppt": "Salinitas (ppt)",
"ammonia_mg_l": "Amonia (mg/L)",
"nitrite_mg_l": "Nitrit (mg/L)",
"nitrate_mg_l": "Nitrat (mg/L)",
"turbidity_ntu": "Kekeruhan (NTU)",
"observed_at": "Diamati pada",
"event_type": "Jenis kejadian",
"severity": "Tingkat keparahan",
"mortality_count": "Jumlah kematian",
"symptoms": "Gejala",
"treatment": "Penanganan",
"resolution_status": "Status penyelesaian",
"resolved_at": "Diselesaikan pada",
"reported_by": "Dilaporkan oleh",
"attachments": "Lampiran",
"item_category": "Kategori item",
"item_name": "Nama item",
"sku": "SKU",
"unit": "Satuan",
"quantity_on_hand": "Stok tersedia",
"reorder_level": "Batas pemesanan ulang",
"unit_cost": "Biaya satuan",
"inventory_item": "Item inventaris",
"feed_product": "Produk pakan",
"movement_type": "Jenis pergerakan",
"quantity": "Jumlah",
"moved_at": "Dipindahkan pada",
"reference": "Referensi",
"source": "Sumber",
"destination": "Tujuan",
"harvested_at": "Dipanen pada",
"total_weight_kg": "Berat total (kg)",
"total_count": "Jumlah total",
"avg_weight_g": "Bobot rata-rata (g)",
"grade": "Grade",
"listing_title": "Judul listing",
"description": "Deskripsi",
"product_form": "Bentuk produk",
"available_quantity_kg": "Jumlah tersedia (kg)",
"price_per_kg": "Harga per kg",
"currency": "Mata uang",
"available_from": "Tersedia mulai",
"expires_at": "Kedaluwarsa pada",
"listing_status": "Status listing",
"seller_tenant": "Tenant penjual",
"buyer_tenant": "Tenant pembeli",
"farm_tenant": "Tenant tambak",
"investor_tenant": "Tenant investor",
"harvest": "Panen",
"fulfillment_location": "Lokasi pemenuhan",
"photos": "Foto",
"order_number": "Nomor pesanan",
"ordered_at": "Dipesan pada",
"order_status": "Status pesanan",
"subtotal_amount": "Subtotal",
"tax_amount": "Pajak",
"shipping_amount": "Biaya pengiriman",
"total_amount": "Total",
"delivery_address": "Alamat pengiriman",
"buyer_notes": "Catatan pembeli",
"expected_delivery_at": "Perkiraan pengiriman pada",
"listing": "Listing",
"order": "Pesanan",
"unit_price": "Harga satuan",
"line_total": "Total baris",
"transaction_type": "Jenis transaksi",
"transaction_status": "Status transaksi",
"amount": "Jumlah",
"provider_reference": "Referensi penyedia",
"processed_at": "Diproses pada",
"failure_reason": "Alasan gagal",
"shipment_status": "Status pengiriman",
"carrier": "Kurir",
"tracking_number": "Nomor resi",
"status_at": "Status pada",
"status_details": "Detail status",
"investment_name": "Nama investasi",
"instrument_type": "Jenis instrumen",
"amount_committed": "Jumlah komitmen",
"amount_funded": "Jumlah didanai",
"committed_at": "Dikomitmenkan pada",
"funded_at": "Didanai pada",
"investment_status": "Status investasi",
"to_email": "Email tujuan",
"subject": "Subjek",
"template_key": "Kunci template",
"payload": "Payload",
"send_status": "Status kirim",
"sent_at": "Dikirim pada",
"recipient_user": "Pengguna penerima",
"action": "Aksi",
"entity_name": "Nama entitas",
"entity_reference": "Referensi entitas",
"occurred_at": "Terjadi pada",
"ip_address": "Alamat IP",
"user_agent": "User agent",
"change_summary": "Ringkasan perubahan",
"actor_user": "Pengguna pelaku",
"key_name": "Nama kunci",
"key_prefix": "Awalan kunci",
"access_level": "Level akses",
"last_used_at": "Terakhir digunakan pada",
"is_revoked": "Dicabut",
"endpoint_name": "Nama endpoint",
"url": "URL",
"secret": "Rahasia",
"is_enabled": "Aktif",
"event_types": "Jenis event",
"last_delivery_at": "Pengiriman terakhir pada",
"endpoint": "Endpoint",
"event_reference": "Referensi event",
"delivered_at": "Dikirim pada",
"delivery_status": "Status pengiriman",
"http_status": "Status HTTP",
"request_payload": "Payload permintaan",
"response_body": "Isi respons",
"attempt_count": "Jumlah percobaan",
"job_type": "Jenis pekerjaan",
"job_status": "Status pekerjaan",
"total_rows": "Total baris",
"processed_rows": "Baris diproses",
"error_rows": "Baris error",
"error_report": "Laporan error",
"started_at": "Dimulai pada",
"finished_at": "Selesai pada",
"requested_by": "Diminta oleh",
"source_file": "File sumber",
"result_file": "File hasil",
"membership_status": "Status keanggotaan",
"joined_at": "Bergabung pada",
"tenant_name": "Nama tenant",
"slug": "Slug",
"tenant_type": "Jenis tenant",
"contact_email": "Email kontak",
"contact_phone": "Telepon kontak",
"billing_address": "Alamat penagihan",
"subscription_status": "Status langganan",
"trial_ends_at": "Masa uji coba berakhir pada",
"location_name": "Nama lokasi",
"address": "Alamat",
"latitude": "Lintang",
"longitude": "Bujur",
"timezone": "Zona waktu",
"is_primary": "Utama",
"role_customization": "Kustomisasi peran",
"global_access": "Akses global",
"permissions_filter": "Filter izin",
"multi_text": "Teks tambahan"
},
"entities": {
"dashboard": "Dasbor",
"farm_ops": "Operasi Tambak",
"users": "Pengguna",
"user": "Pengguna",
"roles": "Peran",
"role": "Peran",
"permissions": "Izin",
"permission": "Izin",
"organizations": "Organisasi",
"organization": "Organisasi",
"tenants": "Tenant",
"tenant": "Tenant",
"user_memberships": "Keanggotaan Pengguna",
"user_membership": "Keanggotaan Pengguna",
"tenant_locations": "Lokasi Tenant",
"tenant_location": "Lokasi Tenant",
"ponds": "Kolam",
"pond": "Kolam",
"species": "Spesies",
"batches": "Batch",
"batch": "Batch",
"feed_products": "Produk Pakan",
"feed_product": "Produk Pakan",
"feeding_logs": "Log Pemberian Pakan",
"feeding_log": "Log Pemberian Pakan",
"water_quality_logs": "Log Kualitas Air",
"water_quality_log": "Log Kualitas Air",
"health_events": "Kejadian Kesehatan",
"health_event": "Kejadian Kesehatan",
"inventory_items": "Item Inventaris",
"inventory_item": "Item Inventaris",
"inventory_movements": "Pergerakan Inventaris",
"inventory_movement": "Pergerakan Inventaris",
"harvests": "Panen",
"harvest": "Panen",
"marketplace_listings": "Listing Marketplace",
"marketplace_listing": "Listing Marketplace",
"orders": "Pesanan",
"order": "Pesanan",
"order_items": "Item Pesanan",
"order_item": "Item Pesanan",
"payment_transactions": "Transaksi Pembayaran",
"payment_transaction": "Transaksi Pembayaran",
"shipment_updates": "Pembaruan Pengiriman",
"shipment_update": "Pembaruan Pengiriman",
"investments": "Investasi",
"investment": "Investasi",
"email_notifications": "Notifikasi Email",
"email_notification": "Notifikasi Email",
"audit_logs": "Log Audit",
"audit_log": "Log Audit",
"api_keys": "Kunci API",
"api_key": "Kunci API",
"webhook_endpoints": "Endpoint Webhook",
"webhook_endpoint": "Endpoint Webhook",
"webhook_deliveries": "Pengiriman Webhook",
"webhook_delivery": "Pengiriman Webhook",
"csv_jobs": "Pekerjaan CSV",
"csv_job": "Pekerjaan CSV"
},
"enums": {
"active": "Aktif",
"inactive": "Tidak aktif",
"maintenance": "Perawatan",
"planned": "Direncanakan",
"harvested": "Dipanen",
"closed": "Ditutup",
"lost": "Hilang",
"manual": "Manual",
"auto_feeder": "Pemberi pakan otomatis",
"broadcast": "Sebar",
"tray": "Tray",
"low": "Rendah",
"normal": "Normal",
"high": "Tinggi",
"pending": "Menunggu",
"confirmed": "Dikonfirmasi",
"packed": "Dikemas",
"shipped": "Dikirim",
"delivered": "Terkirim",
"canceled": "Dibatalkan",
"refunded": "Dikembalikan dana",
"draft": "Draf",
"paused": "Dijeda",
"sold_out": "Habis terjual",
"expired": "Kedaluwarsa",
"removed": "Dihapus",
"earthen": "Tanah",
"lined": "Berlapis",
"tank": "Tangki",
"cage": "Keramba",
"raceway": "Raceway",
"other": "Lainnya"
}
}

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureApi_keysCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
`api_keys`, `api_keys`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleApi_keys = ({ filterItems, setFilterItems, filters, showGrid })
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'key_name', field: 'key_name',
headerName: 'KeyName', headerName: translateCrudLabel('KeyName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -80,7 +81,7 @@ export const loadColumns = async (
{ {
field: 'key_prefix', field: 'key_prefix',
headerName: 'KeyPrefix', headerName: translateCrudLabel('KeyPrefix'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -95,7 +96,7 @@ export const loadColumns = async (
{ {
field: 'access_level', field: 'access_level',
headerName: 'AccessLevel', headerName: translateCrudLabel('AccessLevel'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -110,7 +111,7 @@ export const loadColumns = async (
{ {
field: 'last_used_at', field: 'last_used_at',
headerName: 'LastUsedAt', headerName: translateCrudLabel('LastUsedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -128,7 +129,7 @@ export const loadColumns = async (
{ {
field: 'expires_at', field: 'expires_at',
headerName: 'ExpiresAt', headerName: translateCrudLabel('ExpiresAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -146,7 +147,7 @@ export const loadColumns = async (
{ {
field: 'is_revoked', field: 'is_revoked',
headerName: 'IsRevoked', headerName: translateCrudLabel('IsRevoked'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -7,6 +7,8 @@ import AsideMenuList from './AsideMenuList'
import { MenuAsideItem } from '../interfaces' import { MenuAsideItem } from '../interfaces'
import { useAppSelector } from '../stores/hooks' import { useAppSelector } from '../stores/hooks'
import { useRouter } from 'next/router' import { useRouter } from 'next/router'
import { useTranslation } from 'react-i18next'
import { translateCrudLabel } from '../helpers/translateCrudLabel'
type Props = { type Props = {
item: MenuAsideItem item: MenuAsideItem
@ -14,6 +16,7 @@ type Props = {
} }
const AsideMenuItem = ({ item, isDropdownList = false }: Props) => { const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
const { t } = useTranslation('common')
const [isLinkActive, setIsLinkActive] = useState(false) const [isLinkActive, setIsLinkActive] = useState(false)
const [isDropdownActive, setIsDropdownActive] = useState(false) const [isDropdownActive, setIsDropdownActive] = useState(false)
@ -50,7 +53,7 @@ const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
item.menu ? '' : 'pr-12' item.menu ? '' : 'pr-12'
} ${activeClassAddon}`} } ${activeClassAddon}`}
> >
{item.label} {translateCrudLabel(item.label, t)}
</span> </span>
{item.menu && ( {item.menu && (
<BaseIcon <BaseIcon

View File

@ -3,12 +3,12 @@ import { mdiLogout, mdiClose } from '@mdi/js'
import BaseIcon from './BaseIcon' import BaseIcon from './BaseIcon'
import AsideMenuList from './AsideMenuList' import AsideMenuList from './AsideMenuList'
import { MenuAsideItem } from '../interfaces' import { MenuAsideItem } from '../interfaces'
import { useAppSelector } from '../stores/hooks' import { useAppDispatch, useAppSelector } from '../stores/hooks'
import Link from 'next/link'; import Link from 'next/link';
import { useAppDispatch } from '../stores/hooks';
import { createAsyncThunk } from '@reduxjs/toolkit'; import { createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios'; import axios from 'axios';
import { useTranslation } from 'react-i18next';
type Props = { type Props = {
@ -18,6 +18,7 @@ type Props = {
} }
export default function AsideMenuLayer({ menu, className = '', ...props }: Props) { export default function AsideMenuLayer({ menu, className = '', ...props }: Props) {
const { t } = useTranslation('common');
const corners = useAppSelector((state) => state.style.corners); const corners = useAppSelector((state) => state.style.corners);
const asideStyle = useAppSelector((state) => state.style.asideStyle) const asideStyle = useAppSelector((state) => state.style.asideStyle)
const asideBrandStyle = useAppSelector((state) => state.style.asideBrandStyle) const asideBrandStyle = useAppSelector((state) => state.style.asideBrandStyle)
@ -68,7 +69,7 @@ export default function AsideMenuLayer({ menu, className = '', ...props }: Props
> >
<div className="text-center flex-1 lg:text-left lg:pl-6 xl:text-center xl:pl-0"> <div className="text-center flex-1 lg:text-left lg:pl-6 xl:text-center xl:pl-0">
<b className="font-black">Aquaculture Ops CRUD</b> <b className="font-black">{t('app.title')}</b>
{organizationName && <p>{organizationName}</p>} {organizationName && <p>{organizationName}</p>}

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureAudit_logsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
`audit_logs`, `audit_logs`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleAudit_logs = ({ filterItems, setFilterItems, filters, showGrid
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'actor_user', field: 'actor_user',
headerName: 'ActorUser', headerName: translateCrudLabel('ActorUser'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'action', field: 'action',
headerName: 'Action', headerName: translateCrudLabel('Action'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -102,7 +103,7 @@ export const loadColumns = async (
{ {
field: 'entity_name', field: 'entity_name',
headerName: 'EntityName', headerName: translateCrudLabel('EntityName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -117,7 +118,7 @@ export const loadColumns = async (
{ {
field: 'entity_reference', field: 'entity_reference',
headerName: 'EntityReference', headerName: translateCrudLabel('EntityReference'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -132,7 +133,7 @@ export const loadColumns = async (
{ {
field: 'occurred_at', field: 'occurred_at',
headerName: 'OccurredAt', headerName: translateCrudLabel('OccurredAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -150,7 +151,7 @@ export const loadColumns = async (
{ {
field: 'ip_address', field: 'ip_address',
headerName: 'IPAddress', headerName: translateCrudLabel('IPAddress'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -165,7 +166,7 @@ export const loadColumns = async (
{ {
field: 'user_agent', field: 'user_agent',
headerName: 'UserAgent', headerName: translateCrudLabel('UserAgent'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -180,7 +181,7 @@ export const loadColumns = async (
{ {
field: 'change_summary', field: 'change_summary',
headerName: 'ChangeSummary', headerName: translateCrudLabel('ChangeSummary'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -4,6 +4,8 @@ import { getButtonColor } from '../colors'
import BaseIcon from './BaseIcon' import BaseIcon from './BaseIcon'
import type { ColorButtonKey } from '../interfaces' import type { ColorButtonKey } from '../interfaces'
import { useAppSelector } from '../stores/hooks'; import { useAppSelector } from '../stores/hooks';
import { useTranslation } from 'react-i18next';
import { translateCrudLabel } from '../helpers/translateCrudLabel';
type Props = { type Props = {
label?: string label?: string
@ -42,7 +44,9 @@ export default function BaseButton({
roundedFull = false, roundedFull = false,
onClick, onClick,
}: Props) { }: Props) {
const { t } = useTranslation('common');
const corners = useAppSelector((state) => state.style.corners); const corners = useAppSelector((state) => state.style.corners);
const translatedLabel = label ? translateCrudLabel(label, t) : '';
const componentClass = [ const componentClass = [
'inline-flex', 'inline-flex',
'justify-center', 'justify-center',
@ -76,7 +80,7 @@ export default function BaseButton({
const componentChildren = ( const componentChildren = (
<> <>
{icon && <BaseIcon path={icon} size={iconSize} className={iconClassName} />} {icon && <BaseIcon path={icon} size={iconSize} className={iconClassName} />}
{label && <span className={small && icon ? 'px-1' : 'px-2'}>{label}</span>} {label && <span className={small && icon ? 'px-1' : 'px-2'}>{translatedLabel}</span>}
</> </>
) )

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -20,11 +21,13 @@ import {dataGridStyles} from "../../styles";
import KanbanBoard from '../KanbanBoard/KanbanBoard'; import KanbanBoard from '../KanbanBoard/KanbanBoard';
import axios from 'axios'; import axios from 'axios';
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -213,7 +216,7 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
`batches`, `batches`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -310,7 +313,7 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -324,7 +327,7 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -334,7 +337,7 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -344,12 +347,12 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -359,22 +362,22 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -389,12 +392,12 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -402,11 +405,11 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -416,11 +419,11 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -428,7 +431,7 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -469,7 +472,7 @@ const TableSampleBatches = ({ filterItems, setFilterItems, filters, showGrid })
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'pond', field: 'pond',
headerName: 'Pond', headerName: translateCrudLabel('Pond'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'species', field: 'species',
headerName: 'Species', headerName: translateCrudLabel('Species'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -109,7 +110,7 @@ export const loadColumns = async (
{ {
field: 'batch_code', field: 'batch_code',
headerName: 'BatchCode', headerName: translateCrudLabel('BatchCode'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -124,7 +125,7 @@ export const loadColumns = async (
{ {
field: 'stocked_at', field: 'stocked_at',
headerName: 'StockedAt', headerName: translateCrudLabel('StockedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -142,7 +143,7 @@ export const loadColumns = async (
{ {
field: 'initial_count', field: 'initial_count',
headerName: 'InitialCount', headerName: translateCrudLabel('InitialCount'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -158,7 +159,7 @@ export const loadColumns = async (
{ {
field: 'initial_avg_weight_g', field: 'initial_avg_weight_g',
headerName: 'InitialAverageWeightG', headerName: translateCrudLabel('InitialAverageWeightG'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -174,7 +175,7 @@ export const loadColumns = async (
{ {
field: 'batch_status', field: 'batch_status',
headerName: 'BatchStatus', headerName: translateCrudLabel('BatchStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -189,7 +190,7 @@ export const loadColumns = async (
{ {
field: 'expected_harvest_at', field: 'expected_harvest_at',
headerName: 'ExpectedHarvestAt', headerName: translateCrudLabel('ExpectedHarvestAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -207,7 +208,7 @@ export const loadColumns = async (
{ {
field: 'notes', field: 'notes',
headerName: 'Notes', headerName: translateCrudLabel('Notes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,6 @@
import React, { ReactNode } from 'react' import React, { ReactNode } from 'react'
import { useTranslation } from 'react-i18next'
import { translateCrudLabel } from '../helpers/translateCrudLabel'
type Props = { type Props = {
title: string title: string
@ -6,9 +8,11 @@ type Props = {
} }
const CardBoxComponentTitle = ({ title, children }: Props) => { const CardBoxComponentTitle = ({ title, children }: Props) => {
const { t } = useTranslation('common')
return ( return (
<div className="flex items-center justify-center mb-3"> <div className="flex items-center justify-center mb-3">
<h1 className="text-2xl">{title}</h1> <h1 className="text-2xl">{translateCrudLabel(title, t)}</h1>
{children} {children}
</div> </div>
) )

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -20,11 +21,13 @@ import {dataGridStyles} from "../../styles";
import KanbanBoard from '../KanbanBoard/KanbanBoard'; import KanbanBoard from '../KanbanBoard/KanbanBoard';
import axios from 'axios'; import axios from 'axios';
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -211,7 +214,7 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
`csv_jobs`, `csv_jobs`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -308,7 +311,7 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -322,7 +325,7 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -332,7 +335,7 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -342,12 +345,12 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -357,22 +360,22 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -387,12 +390,12 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -400,11 +403,11 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -414,11 +417,11 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -426,7 +429,7 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -467,7 +470,7 @@ const TableSampleCsv_jobs = ({ filterItems, setFilterItems, filters, showGrid })
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'job_type', field: 'job_type',
headerName: 'JobType', headerName: translateCrudLabel('JobType'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -80,7 +81,7 @@ export const loadColumns = async (
{ {
field: 'entity_name', field: 'entity_name',
headerName: 'EntityName', headerName: translateCrudLabel('EntityName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -95,7 +96,7 @@ export const loadColumns = async (
{ {
field: 'job_status', field: 'job_status',
headerName: 'JobStatus', headerName: translateCrudLabel('JobStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -110,7 +111,7 @@ export const loadColumns = async (
{ {
field: 'source_file', field: 'source_file',
headerName: 'SourceFile', headerName: translateCrudLabel('SourceFile'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -136,7 +137,7 @@ export const loadColumns = async (
{ {
field: 'result_file', field: 'result_file',
headerName: 'ResultFile', headerName: translateCrudLabel('ResultFile'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -162,7 +163,7 @@ export const loadColumns = async (
{ {
field: 'total_rows', field: 'total_rows',
headerName: 'TotalRows', headerName: translateCrudLabel('TotalRows'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -178,7 +179,7 @@ export const loadColumns = async (
{ {
field: 'processed_rows', field: 'processed_rows',
headerName: 'ProcessedRows', headerName: translateCrudLabel('ProcessedRows'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -194,7 +195,7 @@ export const loadColumns = async (
{ {
field: 'error_rows', field: 'error_rows',
headerName: 'ErrorRows', headerName: translateCrudLabel('ErrorRows'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -210,7 +211,7 @@ export const loadColumns = async (
{ {
field: 'error_report', field: 'error_report',
headerName: 'ErrorReport', headerName: translateCrudLabel('ErrorReport'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -225,7 +226,7 @@ export const loadColumns = async (
{ {
field: 'requested_by', field: 'requested_by',
headerName: 'RequestedBy', headerName: translateCrudLabel('RequestedBy'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -247,7 +248,7 @@ export const loadColumns = async (
{ {
field: 'started_at', field: 'started_at',
headerName: 'StartedAt', headerName: translateCrudLabel('StartedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -265,7 +266,7 @@ export const loadColumns = async (
{ {
field: 'finished_at', field: 'finished_at',
headerName: 'FinishedAt', headerName: translateCrudLabel('FinishedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,6 +1,7 @@
import React, { ChangeEvent, useEffect, useState } from 'react'; import React, { ChangeEvent, useEffect, useState } from 'react';
import BaseIcon from './BaseIcon'; import BaseIcon from './BaseIcon';
import { mdiFileUploadOutline } from '@mdi/js'; import { mdiFileUploadOutline } from '@mdi/js';
import { useTranslation } from 'react-i18next';
type Props = { type Props = {
file: File | null; file: File | null;
@ -9,6 +10,7 @@ type Props = {
}; };
const DragDropFilePicker = ({ file, setFile, formats = '' }: Props) => { const DragDropFilePicker = ({ file, setFile, formats = '' }: Props) => {
const { t } = useTranslation('common');
const [highlight, setHighlight] = useState(false); const [highlight, setHighlight] = useState(false);
const [errorMessage, setErrorMessage] = useState(''); const [errorMessage, setErrorMessage] = useState('');
const fileInput = React.createRef<HTMLInputElement>(); const fileInput = React.createRef<HTMLInputElement>();
@ -26,7 +28,7 @@ const DragDropFilePicker = ({ file, setFile, formats = '' }: Props) => {
setFile(newFile); setFile(newFile);
setErrorMessage(''); setErrorMessage('');
} else { } else {
setErrorMessage(`Allowed formats: ${formats}`); setErrorMessage(t('labels.allowed_formats', { formats }));
} }
} }
} }
@ -97,8 +99,7 @@ const DragDropFilePicker = ({ file, setFile, formats = '' }: Props) => {
) : ( ) : (
<> <>
<p className='mb-2 text-sm text-gray-500 dark:text-gray-400'> <p className='mb-2 text-sm text-gray-500 dark:text-gray-400'>
<span className='font-semibold'>Click to upload</span> or drag <span className='font-semibold'>{t('labels.click_to_upload')}</span> {t('labels.or_drag_and_drop')}
and drop
</p> </p>
{formats && ( {formats && (
<p className='text-xs text-gray-500 dark:text-gray-400'> <p className='text-xs text-gray-500 dark:text-gray-400'>

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureEmail_notificationsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
`email_notifications`, `email_notifications`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleEmail_notifications = ({ filterItems, setFilterItems, filters,
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'recipient_user', field: 'recipient_user',
headerName: 'RecipientUser', headerName: translateCrudLabel('RecipientUser'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'to_email', field: 'to_email',
headerName: 'ToEmail', headerName: translateCrudLabel('ToEmail'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -102,7 +103,7 @@ export const loadColumns = async (
{ {
field: 'subject', field: 'subject',
headerName: 'Subject', headerName: translateCrudLabel('Subject'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -117,7 +118,7 @@ export const loadColumns = async (
{ {
field: 'template_key', field: 'template_key',
headerName: 'TemplateKey', headerName: translateCrudLabel('TemplateKey'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -132,7 +133,7 @@ export const loadColumns = async (
{ {
field: 'payload', field: 'payload',
headerName: 'Payload', headerName: translateCrudLabel('Payload'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -147,7 +148,7 @@ export const loadColumns = async (
{ {
field: 'send_status', field: 'send_status',
headerName: 'SendStatus', headerName: translateCrudLabel('SendStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -162,7 +163,7 @@ export const loadColumns = async (
{ {
field: 'sent_at', field: 'sent_at',
headerName: 'SentAt', headerName: translateCrudLabel('SentAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -180,7 +181,7 @@ export const loadColumns = async (
{ {
field: 'failure_reason', field: 'failure_reason',
headerName: 'FailureReason', headerName: translateCrudLabel('FailureReason'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureFeed_productsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
`feed_products`, `feed_products`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleFeed_products = ({ filterItems, setFilterItems, filters, showGr
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'product_name', field: 'product_name',
headerName: 'ProductName', headerName: translateCrudLabel('ProductName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -80,7 +81,7 @@ export const loadColumns = async (
{ {
field: 'brand', field: 'brand',
headerName: 'Brand', headerName: translateCrudLabel('Brand'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -95,7 +96,7 @@ export const loadColumns = async (
{ {
field: 'feed_type', field: 'feed_type',
headerName: 'FeedType', headerName: translateCrudLabel('FeedType'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -110,7 +111,7 @@ export const loadColumns = async (
{ {
field: 'protein_percent', field: 'protein_percent',
headerName: 'ProteinPercent', headerName: translateCrudLabel('ProteinPercent'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -126,7 +127,7 @@ export const loadColumns = async (
{ {
field: 'fat_percent', field: 'fat_percent',
headerName: 'FatPercent', headerName: translateCrudLabel('FatPercent'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -142,7 +143,7 @@ export const loadColumns = async (
{ {
field: 'pellet_size_mm', field: 'pellet_size_mm',
headerName: 'PelletSizeMm', headerName: translateCrudLabel('PelletSizeMm'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -158,7 +159,7 @@ export const loadColumns = async (
{ {
field: 'notes', field: 'notes',
headerName: 'Notes', headerName: translateCrudLabel('Notes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,6 +17,7 @@ import {loadColumns} from "./configureFeeding_logsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
import BigCalendar from "../BigCalendar"; import BigCalendar from "../BigCalendar";
@ -25,6 +27,7 @@ import { SlotInfo } from 'react-big-calendar';
const perPage = 100 const perPage = 100
const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -183,7 +186,7 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
`feeding_logs`, `feeding_logs`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -280,7 +283,7 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -294,7 +297,7 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -304,7 +307,7 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -314,12 +317,12 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -329,22 +332,22 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -359,12 +362,12 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -372,11 +375,11 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -386,11 +389,11 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -398,7 +401,7 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -439,7 +442,7 @@ const TableSampleFeeding_logs = ({ filterItems, setFilterItems, filters, showGri
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'batch', field: 'batch',
headerName: 'Batch', headerName: translateCrudLabel('Batch'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'feed_product', field: 'feed_product',
headerName: 'FeedProduct', headerName: translateCrudLabel('FeedProduct'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -109,7 +110,7 @@ export const loadColumns = async (
{ {
field: 'fed_at', field: 'fed_at',
headerName: 'FedAt', headerName: translateCrudLabel('FedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -127,7 +128,7 @@ export const loadColumns = async (
{ {
field: 'quantity_kg', field: 'quantity_kg',
headerName: 'QuantityKg', headerName: translateCrudLabel('QuantityKg'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -143,7 +144,7 @@ export const loadColumns = async (
{ {
field: 'feeding_method', field: 'feeding_method',
headerName: 'FeedingMethod', headerName: translateCrudLabel('FeedingMethod'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -158,7 +159,7 @@ export const loadColumns = async (
{ {
field: 'appetite', field: 'appetite',
headerName: 'Appetite', headerName: translateCrudLabel('Appetite'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -173,7 +174,7 @@ export const loadColumns = async (
{ {
field: 'notes', field: 'notes',
headerName: 'Notes', headerName: translateCrudLabel('Notes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -188,7 +189,7 @@ export const loadColumns = async (
{ {
field: 'recorded_by', field: 'recorded_by',
headerName: 'RecordedBy', headerName: translateCrudLabel('RecordedBy'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,6 @@
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { useTranslation } from 'react-i18next'
import { translateCrudLabel } from '../helpers/translateCrudLabel'
type Props = { type Props = {
children: ReactNode children: ReactNode
@ -8,11 +10,13 @@ type Props = {
} }
const FormCheckRadio = (props: Props) => { const FormCheckRadio = (props: Props) => {
const { t } = useTranslation('common')
return ( return (
<label className={`${props.type} ${props.className}`}> <label className={`${props.type} ${props.className}`}>
{props.children} {props.children}
<span className="check" /> <span className="check" />
<span className="pl-2">{props.label}</span> <span className="pl-2">{translateCrudLabel(props.label, t)}</span>
</label> </label>
) )
} }

View File

@ -1,6 +1,8 @@
import { Children, cloneElement, ReactElement, ReactNode } from 'react' import { Children, cloneElement, ReactElement, ReactNode } from 'react'
import BaseIcon from './BaseIcon' import BaseIcon from './BaseIcon'
import { useAppSelector } from '../stores/hooks'; import { useAppSelector } from '../stores/hooks';
import { useTranslation } from 'react-i18next';
import { translateCrudLabel } from '../helpers/translateCrudLabel';
type Props = { type Props = {
label?: string label?: string
@ -18,6 +20,7 @@ type Props = {
} }
const FormField = ({ icons = [], ...props }: Props) => { const FormField = ({ icons = [], ...props }: Props) => {
const { t } = useTranslation('common')
const childrenCount = Children.count(props.children) const childrenCount = Children.count(props.children)
const bgColor = useAppSelector((state) => state.style.cardsColor); const bgColor = useAppSelector((state) => state.style.cardsColor);
const focusRing = useAppSelector((state) => state.style.focusRingColor); const focusRing = useAppSelector((state) => state.style.focusRingColor);
@ -50,7 +53,7 @@ const FormField = ({ icons = [], ...props }: Props) => {
htmlFor={props.labelFor} htmlFor={props.labelFor}
className={`block font-bold mb-2 ${props.labelFor ? 'cursor-pointer' : ''}`} className={`block font-bold mb-2 ${props.labelFor ? 'cursor-pointer' : ''}`}
> >
{props.label} {translateCrudLabel(props.label, t)}
</label> </label>
)} )}
<div className={`${elementWrapperClass}`}> <div className={`${elementWrapperClass}`}>
@ -71,7 +74,7 @@ const FormField = ({ icons = [], ...props }: Props) => {
))} ))}
</div> </div>
{props.help && ( {props.help && (
<div className='text-xs text-gray-500 dark:text-dark-600 mt-1'>{props.help}</div> <div className='text-xs text-gray-500 dark:text-dark-600 mt-1'>{translateCrudLabel(props.help, t)}</div>
)} )}
</div> </div>
) )

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureHarvestsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
`harvests`, `harvests`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleHarvests = ({ filterItems, setFilterItems, filters, showGrid })
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'batch', field: 'batch',
headerName: 'Batch', headerName: translateCrudLabel('Batch'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'harvested_at', field: 'harvested_at',
headerName: 'HarvestedAt', headerName: translateCrudLabel('HarvestedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -105,7 +106,7 @@ export const loadColumns = async (
{ {
field: 'total_weight_kg', field: 'total_weight_kg',
headerName: 'TotalWeightKg', headerName: translateCrudLabel('TotalWeightKg'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -121,7 +122,7 @@ export const loadColumns = async (
{ {
field: 'total_count', field: 'total_count',
headerName: 'TotalCount', headerName: translateCrudLabel('TotalCount'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -137,7 +138,7 @@ export const loadColumns = async (
{ {
field: 'avg_weight_g', field: 'avg_weight_g',
headerName: 'AverageWeightG', headerName: translateCrudLabel('AverageWeightG'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -153,7 +154,7 @@ export const loadColumns = async (
{ {
field: 'grade', field: 'grade',
headerName: 'Grade', headerName: translateCrudLabel('Grade'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -168,7 +169,7 @@ export const loadColumns = async (
{ {
field: 'notes', field: 'notes',
headerName: 'Notes', headerName: translateCrudLabel('Notes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -183,7 +184,7 @@ export const loadColumns = async (
{ {
field: 'recorded_by', field: 'recorded_by',
headerName: 'RecordedBy', headerName: translateCrudLabel('RecordedBy'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -20,11 +21,13 @@ import {dataGridStyles} from "../../styles";
import KanbanBoard from '../KanbanBoard/KanbanBoard'; import KanbanBoard from '../KanbanBoard/KanbanBoard';
import axios from 'axios'; import axios from 'axios';
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -211,7 +214,7 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
`health_events`, `health_events`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -308,7 +311,7 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -322,7 +325,7 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -332,7 +335,7 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -342,12 +345,12 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -357,22 +360,22 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -387,12 +390,12 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -400,11 +403,11 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -414,11 +417,11 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -426,7 +429,7 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -467,7 +470,7 @@ const TableSampleHealth_events = ({ filterItems, setFilterItems, filters, showGr
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'batch', field: 'batch',
headerName: 'Batch', headerName: translateCrudLabel('Batch'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'observed_at', field: 'observed_at',
headerName: 'ObservedAt', headerName: translateCrudLabel('ObservedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -105,7 +106,7 @@ export const loadColumns = async (
{ {
field: 'event_type', field: 'event_type',
headerName: 'EventType', headerName: translateCrudLabel('EventType'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -120,7 +121,7 @@ export const loadColumns = async (
{ {
field: 'severity', field: 'severity',
headerName: 'Severity', headerName: translateCrudLabel('Severity'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -135,7 +136,7 @@ export const loadColumns = async (
{ {
field: 'mortality_count', field: 'mortality_count',
headerName: 'MortalityCount', headerName: translateCrudLabel('MortalityCount'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -151,7 +152,7 @@ export const loadColumns = async (
{ {
field: 'symptoms', field: 'symptoms',
headerName: 'Symptoms', headerName: translateCrudLabel('Symptoms'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -166,7 +167,7 @@ export const loadColumns = async (
{ {
field: 'treatment', field: 'treatment',
headerName: 'Treatment', headerName: translateCrudLabel('Treatment'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -181,7 +182,7 @@ export const loadColumns = async (
{ {
field: 'attachments', field: 'attachments',
headerName: 'Attachments', headerName: translateCrudLabel('Attachments'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -207,7 +208,7 @@ export const loadColumns = async (
{ {
field: 'reported_by', field: 'reported_by',
headerName: 'ReportedBy', headerName: translateCrudLabel('ReportedBy'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -229,7 +230,7 @@ export const loadColumns = async (
{ {
field: 'resolution_status', field: 'resolution_status',
headerName: 'ResolutionStatus', headerName: translateCrudLabel('ResolutionStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -244,7 +245,7 @@ export const loadColumns = async (
{ {
field: 'resolved_at', field: 'resolved_at',
headerName: 'ResolvedAt', headerName: translateCrudLabel('ResolvedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureInventory_itemsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
`inventory_items`, `inventory_items`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleInventory_items = ({ filterItems, setFilterItems, filters, show
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'location', field: 'location',
headerName: 'Location', headerName: translateCrudLabel('Location'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'item_category', field: 'item_category',
headerName: 'ItemCategory', headerName: translateCrudLabel('ItemCategory'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -102,7 +103,7 @@ export const loadColumns = async (
{ {
field: 'item_name', field: 'item_name',
headerName: 'ItemName', headerName: translateCrudLabel('ItemName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -117,7 +118,7 @@ export const loadColumns = async (
{ {
field: 'sku', field: 'sku',
headerName: 'SKU', headerName: translateCrudLabel('SKU'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -132,7 +133,7 @@ export const loadColumns = async (
{ {
field: 'unit', field: 'unit',
headerName: 'Unit', headerName: translateCrudLabel('Unit'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -147,7 +148,7 @@ export const loadColumns = async (
{ {
field: 'quantity_on_hand', field: 'quantity_on_hand',
headerName: 'QuantityOnHand', headerName: translateCrudLabel('QuantityOnHand'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -163,7 +164,7 @@ export const loadColumns = async (
{ {
field: 'reorder_level', field: 'reorder_level',
headerName: 'ReorderLevel', headerName: translateCrudLabel('ReorderLevel'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -179,7 +180,7 @@ export const loadColumns = async (
{ {
field: 'unit_cost', field: 'unit_cost',
headerName: 'UnitCost', headerName: translateCrudLabel('UnitCost'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -195,7 +196,7 @@ export const loadColumns = async (
{ {
field: 'feed_product', field: 'feed_product',
headerName: 'FeedProduct', headerName: translateCrudLabel('FeedProduct'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureInventory_movementsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
`inventory_movements`, `inventory_movements`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleInventory_movements = ({ filterItems, setFilterItems, filters,
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'inventory_item', field: 'inventory_item',
headerName: 'InventoryItem', headerName: translateCrudLabel('InventoryItem'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'movement_type', field: 'movement_type',
headerName: 'MovementType', headerName: translateCrudLabel('MovementType'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -102,7 +103,7 @@ export const loadColumns = async (
{ {
field: 'quantity', field: 'quantity',
headerName: 'Quantity', headerName: translateCrudLabel('Quantity'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -118,7 +119,7 @@ export const loadColumns = async (
{ {
field: 'moved_at', field: 'moved_at',
headerName: 'MovedAt', headerName: translateCrudLabel('MovedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -136,7 +137,7 @@ export const loadColumns = async (
{ {
field: 'batch', field: 'batch',
headerName: 'Batch', headerName: translateCrudLabel('Batch'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -158,7 +159,7 @@ export const loadColumns = async (
{ {
field: 'reference', field: 'reference',
headerName: 'Reference', headerName: translateCrudLabel('Reference'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -173,7 +174,7 @@ export const loadColumns = async (
{ {
field: 'notes', field: 'notes',
headerName: 'Notes', headerName: translateCrudLabel('Notes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -20,11 +21,13 @@ import {dataGridStyles} from "../../styles";
import KanbanBoard from '../KanbanBoard/KanbanBoard'; import KanbanBoard from '../KanbanBoard/KanbanBoard';
import axios from 'axios'; import axios from 'axios';
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -211,7 +214,7 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
`investments`, `investments`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -308,7 +311,7 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -322,7 +325,7 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -332,7 +335,7 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -342,12 +345,12 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -357,22 +360,22 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -387,12 +390,12 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -400,11 +403,11 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -414,11 +417,11 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -426,7 +429,7 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -467,7 +470,7 @@ const TableSampleInvestments = ({ filterItems, setFilterItems, filters, showGrid
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'investor_tenant', field: 'investor_tenant',
headerName: 'InvestorTenant', headerName: translateCrudLabel('InvestorTenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'farm_tenant', field: 'farm_tenant',
headerName: 'FarmTenant', headerName: translateCrudLabel('FarmTenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'investment_name', field: 'investment_name',
headerName: 'InvestmentName', headerName: translateCrudLabel('InvestmentName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -102,7 +103,7 @@ export const loadColumns = async (
{ {
field: 'instrument_type', field: 'instrument_type',
headerName: 'InstrumentType', headerName: translateCrudLabel('InstrumentType'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -117,7 +118,7 @@ export const loadColumns = async (
{ {
field: 'amount_committed', field: 'amount_committed',
headerName: 'AmountCommitted', headerName: translateCrudLabel('AmountCommitted'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -133,7 +134,7 @@ export const loadColumns = async (
{ {
field: 'amount_funded', field: 'amount_funded',
headerName: 'AmountFunded', headerName: translateCrudLabel('AmountFunded'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -149,7 +150,7 @@ export const loadColumns = async (
{ {
field: 'currency', field: 'currency',
headerName: 'Currency', headerName: translateCrudLabel('Currency'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -164,7 +165,7 @@ export const loadColumns = async (
{ {
field: 'committed_at', field: 'committed_at',
headerName: 'CommittedAt', headerName: translateCrudLabel('CommittedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -182,7 +183,7 @@ export const loadColumns = async (
{ {
field: 'funded_at', field: 'funded_at',
headerName: 'FundedAt', headerName: translateCrudLabel('FundedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -200,7 +201,7 @@ export const loadColumns = async (
{ {
field: 'investment_status', field: 'investment_status',
headerName: 'InvestmentStatus', headerName: translateCrudLabel('InvestmentStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -215,7 +216,7 @@ export const loadColumns = async (
{ {
field: 'notes', field: 'notes',
headerName: 'Notes', headerName: translateCrudLabel('Notes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -6,6 +6,8 @@ import CardBoxModal from '../CardBoxModal';
import { AsyncThunk } from '@reduxjs/toolkit'; import { AsyncThunk } from '@reduxjs/toolkit';
import { useDrop } from 'react-dnd'; import { useDrop } from 'react-dnd';
import KanbanCard from './KanbanCard'; import KanbanCard from './KanbanCard';
import { useTranslation } from 'react-i18next';
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Props = { type Props = {
column: { id: string; label: string }; column: { id: string; label: string };
@ -33,6 +35,7 @@ const KanbanColumn = ({
deleteThunk, deleteThunk,
updateThunk, updateThunk,
}: Props) => { }: Props) => {
const { t, i18n } = useTranslation('common');
const [currentPage, setCurrentPage] = useState(0); const [currentPage, setCurrentPage] = useState(0);
const [count, setCount] = useState(0); const [count, setCount] = useState(0);
const [data, setData] = useState(null); const [data, setData] = useState(null);
@ -106,7 +109,7 @@ const KanbanColumn = ({
setLoading(false); setLoading(false);
}); });
}, },
[currentUser, column], [currentUser, column, i18n.language],
); );
useEffect(() => { useEffect(() => {
@ -165,7 +168,7 @@ const KanbanColumn = ({
} }
> >
<div className={'flex items-center justify-between p-3'}> <div className={'flex items-center justify-between p-3'}>
<p className={'uppercase'}>{column.label}</p> <p className={'uppercase'}>{translateCrudLabel(column.label, t)}</p>
<p>{count}</p> <p>{count}</p>
</div> </div>
<div <div
@ -188,7 +191,7 @@ const KanbanColumn = ({
</div> </div>
))} ))}
{!data?.length && ( {!data?.length && (
<p className={'text-center py-8 bg-gray-50 dark:bg-dark-800'}>No data</p> <p className={'text-center py-8 bg-gray-50 dark:bg-dark-800'}>{translateCrudLabel('No data', t)}</p>
)} )}
</div> </div>
</CardBox> </CardBox>
@ -200,7 +203,7 @@ const KanbanColumn = ({
onConfirm={onDeleteConfirm} onConfirm={onDeleteConfirm}
onCancel={() => setItemIdToDelete('')} onCancel={() => setItemIdToDelete('')}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>
</> </>
); );

View File

@ -1,15 +1,17 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import Select, { components, SingleValueProps, OptionProps } from 'react-select'; import Select, { components, SingleValueProps, OptionProps } from 'react-select';
import { useTranslation } from 'react-i18next';
type LanguageOption = { label: string; value: string }; type LanguageOption = { label: string; value: string };
const LANGS: LanguageOption[] = [ const LANGS: LanguageOption[] = [
{ value: 'en', label: '🇬🇧 EN' }, { value: 'id', label: '🇮🇩 ID' },
{ value: 'fr', label: '🇫🇷 FR' }, { value: 'en-GB', label: '🇬🇧 EN-UK' },
{ value: 'es', label: '🇪🇸 ES' },
{ value: 'de', label: '🇩🇪 DE' },
]; ];
const getLanguageOption = (language?: string) =>
LANGS.find((option) => option.value === language) || LANGS[0];
const Option = (props: OptionProps<LanguageOption, false>) => ( const Option = (props: OptionProps<LanguageOption, false>) => (
<components.Option {...props}> <components.Option {...props}>
<span className='flex items-center gap-1'>{props.data.label}</span> <span className='flex items-center gap-1'>{props.data.label}</span>
@ -23,22 +25,42 @@ const SingleVal = (props: SingleValueProps<LanguageOption, false>) => (
); );
const LanguageSwitcher: React.FC = () => { const LanguageSwitcher: React.FC = () => {
const { i18n } = useTranslation('common');
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
const [selected, setSelected] = useState<LanguageOption>(LANGS[0]); const [selected, setSelected] = useState<LanguageOption>(LANGS[0]);
useEffect(() => { useEffect(() => {
setMounted(true); setMounted(true);
}, []);
const handleChange = (opt: LanguageOption | null) => { const savedLanguage = typeof window !== 'undefined' ? window.localStorage.getItem('app_lang_') : null;
const selectedLanguage = getLanguageOption(savedLanguage || i18n.resolvedLanguage || i18n.language);
setSelected(selectedLanguage);
if (selectedLanguage.value !== i18n.language) {
i18n.changeLanguage(selectedLanguage.value);
}
const handleLanguageChanged = (language: string) => {
setSelected(getLanguageOption(language));
};
i18n.on('languageChanged', handleLanguageChanged);
return () => {
i18n.off('languageChanged', handleLanguageChanged);
};
}, [i18n]);
const handleChange = async (opt: LanguageOption | null) => {
if (!opt) return; if (!opt) return;
setSelected(opt); setSelected(opt);
window.localStorage.setItem('app_lang_', opt.value);
await i18n.changeLanguage(opt.value);
}; };
if (!mounted) return null; if (!mounted) return null;
return ( return (
<div style={{ width: 88 }}> <div style={{ width: 118 }}>
<Select <Select
value={selected} value={selected}
options={LANGS} options={LANGS}
@ -78,7 +100,7 @@ const LanguageSwitcher: React.FC = () => {
...base, ...base,
paddingTop: 4, paddingTop: 4,
paddingBottom: 4, paddingBottom: 4,
height: 26, height: 28,
fontSize: '0.875rem', fontSize: '0.875rem',
backgroundColor: state.isFocused ? '#f3f4f6' : 'white', backgroundColor: state.isFocused ? '#f3f4f6' : 'white',
color: '#111827', color: '#111827',

View File

@ -10,6 +10,8 @@ import {
} from '@mdi/js'; } from '@mdi/js';
import Popover from '@mui/material/Popover'; import Popover from '@mui/material/Popover';
import { IconButton } from '@mui/material'; import { IconButton } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { translateCrudLabel } from '../helpers/translateCrudLabel';
type Props = { type Props = {
@ -31,6 +33,7 @@ const ListActionsPopover = ({
pathEdit, pathEdit,
pathView, pathView,
}: Props) => { }: Props) => {
const { t } = useTranslation('common');
const [anchorEl, setAnchorEl] = React.useState(null); const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => { const handleClick = (event) => {
setAnchorEl(event.currentTarget); setAnchorEl(event.currentTarget);
@ -81,7 +84,7 @@ const ListActionsPopover = ({
href={linkView} href={linkView}
sx={{ justifyContent: "start" }} sx={{ justifyContent: "start" }}
> >
View {translateCrudLabel('View', t)}
</Button> </Button>
{hasUpdatePermission && ( {hasUpdatePermission && (
<Button <Button
@ -90,7 +93,7 @@ const ListActionsPopover = ({
href={linkEdit} href={linkEdit}
sx={{ justifyContent: "start" }} sx={{ justifyContent: "start" }}
> >
Edit {translateCrudLabel('Edit', t)}
</Button> </Button>
)} )}
{hasUpdatePermission && ( {hasUpdatePermission && (
@ -103,7 +106,7 @@ const ListActionsPopover = ({
}} }}
sx={{ justifyContent: "start" }} sx={{ justifyContent: "start" }}
> >
Delete {translateCrudLabel('Delete', t)}
</Button> </Button>
)} )}
</div> </div>

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -20,11 +21,13 @@ import {dataGridStyles} from "../../styles";
import KanbanBoard from '../KanbanBoard/KanbanBoard'; import KanbanBoard from '../KanbanBoard/KanbanBoard';
import axios from 'axios'; import axios from 'axios';
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -215,7 +218,7 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
`marketplace_listings`, `marketplace_listings`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -312,7 +315,7 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -326,7 +329,7 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -336,7 +339,7 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -346,12 +349,12 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -361,22 +364,22 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -391,12 +394,12 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -404,11 +407,11 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -418,11 +421,11 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -430,7 +433,7 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -471,7 +474,7 @@ const TableSampleMarketplace_listings = ({ filterItems, setFilterItems, filters,
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'seller_tenant', field: 'seller_tenant',
headerName: 'SellerTenant', headerName: translateCrudLabel('SellerTenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'harvest', field: 'harvest',
headerName: 'Harvest', headerName: translateCrudLabel('Harvest'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'species', field: 'species',
headerName: 'Species', headerName: translateCrudLabel('Species'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -109,7 +110,7 @@ export const loadColumns = async (
{ {
field: 'listing_title', field: 'listing_title',
headerName: 'ListingTitle', headerName: translateCrudLabel('ListingTitle'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -124,7 +125,7 @@ export const loadColumns = async (
{ {
field: 'description', field: 'description',
headerName: 'Description', headerName: translateCrudLabel('Description'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -139,7 +140,7 @@ export const loadColumns = async (
{ {
field: 'product_form', field: 'product_form',
headerName: 'ProductForm', headerName: translateCrudLabel('ProductForm'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -154,7 +155,7 @@ export const loadColumns = async (
{ {
field: 'available_quantity_kg', field: 'available_quantity_kg',
headerName: 'AvailableQuantityKg', headerName: translateCrudLabel('AvailableQuantityKg'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -170,7 +171,7 @@ export const loadColumns = async (
{ {
field: 'price_per_kg', field: 'price_per_kg',
headerName: 'PricePerKg', headerName: translateCrudLabel('PricePerKg'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -186,7 +187,7 @@ export const loadColumns = async (
{ {
field: 'currency', field: 'currency',
headerName: 'Currency', headerName: translateCrudLabel('Currency'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -201,7 +202,7 @@ export const loadColumns = async (
{ {
field: 'available_from', field: 'available_from',
headerName: 'AvailableFrom', headerName: translateCrudLabel('AvailableFrom'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -219,7 +220,7 @@ export const loadColumns = async (
{ {
field: 'expires_at', field: 'expires_at',
headerName: 'ExpiresAt', headerName: translateCrudLabel('ExpiresAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -237,7 +238,7 @@ export const loadColumns = async (
{ {
field: 'listing_status', field: 'listing_status',
headerName: 'ListingStatus', headerName: translateCrudLabel('ListingStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -252,7 +253,7 @@ export const loadColumns = async (
{ {
field: 'photos', field: 'photos',
headerName: 'Photos', headerName: translateCrudLabel('Photos'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -273,7 +274,7 @@ export const loadColumns = async (
{ {
field: 'fulfillment_location', field: 'fulfillment_location',
headerName: 'FulfillmentLocation', headerName: translateCrudLabel('FulfillmentLocation'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,6 +1,5 @@
import React, {useEffect, useRef} from 'react' import React, { useEffect, useRef, useState } from 'react'
import Link from 'next/link' import Link from 'next/link'
import { useState } from 'react'
import { mdiChevronUp, mdiChevronDown } from '@mdi/js' import { mdiChevronUp, mdiChevronDown } from '@mdi/js'
import BaseDivider from './BaseDivider' import BaseDivider from './BaseDivider'
import BaseIcon from './BaseIcon' import BaseIcon from './BaseIcon'

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureOrder_itemsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
`order_items`, `order_items`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleOrder_items = ({ filterItems, setFilterItems, filters, showGrid
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'order', field: 'order',
headerName: 'Order', headerName: translateCrudLabel('Order'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'listing', field: 'listing',
headerName: 'Listing', headerName: translateCrudLabel('Listing'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'quantity_kg', field: 'quantity_kg',
headerName: 'QuantityKg', headerName: translateCrudLabel('QuantityKg'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -103,7 +104,7 @@ export const loadColumns = async (
{ {
field: 'unit_price', field: 'unit_price',
headerName: 'UnitPrice', headerName: translateCrudLabel('UnitPrice'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -119,7 +120,7 @@ export const loadColumns = async (
{ {
field: 'line_total', field: 'line_total',
headerName: 'LineTotal', headerName: translateCrudLabel('LineTotal'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -135,7 +136,7 @@ export const loadColumns = async (
{ {
field: 'notes', field: 'notes',
headerName: 'Notes', headerName: translateCrudLabel('Notes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -20,11 +21,13 @@ import {dataGridStyles} from "../../styles";
import KanbanBoard from '../KanbanBoard/KanbanBoard'; import KanbanBoard from '../KanbanBoard/KanbanBoard';
import axios from 'axios'; import axios from 'axios';
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -217,7 +220,7 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
`orders`, `orders`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -314,7 +317,7 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -328,7 +331,7 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -338,7 +341,7 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -348,12 +351,12 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -363,22 +366,22 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -393,12 +396,12 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -406,11 +409,11 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -420,11 +423,11 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -432,7 +435,7 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -473,7 +476,7 @@ const TableSampleOrders = ({ filterItems, setFilterItems, filters, showGrid }) =
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'order_number', field: 'order_number',
headerName: 'OrderNumber', headerName: translateCrudLabel('OrderNumber'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -58,7 +59,7 @@ export const loadColumns = async (
{ {
field: 'buyer_tenant', field: 'buyer_tenant',
headerName: 'BuyerTenant', headerName: translateCrudLabel('BuyerTenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -80,7 +81,7 @@ export const loadColumns = async (
{ {
field: 'seller_tenant', field: 'seller_tenant',
headerName: 'SellerTenant', headerName: translateCrudLabel('SellerTenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -102,7 +103,7 @@ export const loadColumns = async (
{ {
field: 'ordered_at', field: 'ordered_at',
headerName: 'OrderedAt', headerName: translateCrudLabel('OrderedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -120,7 +121,7 @@ export const loadColumns = async (
{ {
field: 'order_status', field: 'order_status',
headerName: 'OrderStatus', headerName: translateCrudLabel('OrderStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -135,7 +136,7 @@ export const loadColumns = async (
{ {
field: 'subtotal_amount', field: 'subtotal_amount',
headerName: 'SubtotalAmount', headerName: translateCrudLabel('SubtotalAmount'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -151,7 +152,7 @@ export const loadColumns = async (
{ {
field: 'tax_amount', field: 'tax_amount',
headerName: 'TaxAmount', headerName: translateCrudLabel('TaxAmount'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -167,7 +168,7 @@ export const loadColumns = async (
{ {
field: 'shipping_amount', field: 'shipping_amount',
headerName: 'ShippingAmount', headerName: translateCrudLabel('ShippingAmount'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -183,7 +184,7 @@ export const loadColumns = async (
{ {
field: 'total_amount', field: 'total_amount',
headerName: 'TotalAmount', headerName: translateCrudLabel('TotalAmount'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -199,7 +200,7 @@ export const loadColumns = async (
{ {
field: 'currency', field: 'currency',
headerName: 'Currency', headerName: translateCrudLabel('Currency'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -214,7 +215,7 @@ export const loadColumns = async (
{ {
field: 'delivery_address', field: 'delivery_address',
headerName: 'DeliveryAddress', headerName: translateCrudLabel('DeliveryAddress'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -229,7 +230,7 @@ export const loadColumns = async (
{ {
field: 'buyer_notes', field: 'buyer_notes',
headerName: 'BuyerNotes', headerName: translateCrudLabel('BuyerNotes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -244,7 +245,7 @@ export const loadColumns = async (
{ {
field: 'expected_delivery_at', field: 'expected_delivery_at',
headerName: 'ExpectedDeliveryAt', headerName: translateCrudLabel('ExpectedDeliveryAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureOrganizationsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
`organizations`, `organizations`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'name', field: 'name',
headerName: 'Name', headerName: translateCrudLabel('Name'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configurePayment_transactionsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
`payment_transactions`, `payment_transactions`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSamplePayment_transactions = ({ filterItems, setFilterItems, filters,
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'order', field: 'order',
headerName: 'Order', headerName: translateCrudLabel('Order'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'buyer_tenant', field: 'buyer_tenant',
headerName: 'BuyerTenant', headerName: translateCrudLabel('BuyerTenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'seller_tenant', field: 'seller_tenant',
headerName: 'SellerTenant', headerName: translateCrudLabel('SellerTenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -109,7 +110,7 @@ export const loadColumns = async (
{ {
field: 'transaction_type', field: 'transaction_type',
headerName: 'TransactionType', headerName: translateCrudLabel('TransactionType'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -124,7 +125,7 @@ export const loadColumns = async (
{ {
field: 'transaction_status', field: 'transaction_status',
headerName: 'TransactionStatus', headerName: translateCrudLabel('TransactionStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -139,7 +140,7 @@ export const loadColumns = async (
{ {
field: 'amount', field: 'amount',
headerName: 'Amount', headerName: translateCrudLabel('Amount'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -155,7 +156,7 @@ export const loadColumns = async (
{ {
field: 'currency', field: 'currency',
headerName: 'Currency', headerName: translateCrudLabel('Currency'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -170,7 +171,7 @@ export const loadColumns = async (
{ {
field: 'provider', field: 'provider',
headerName: 'Provider', headerName: translateCrudLabel('Provider'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -185,7 +186,7 @@ export const loadColumns = async (
{ {
field: 'provider_reference', field: 'provider_reference',
headerName: 'ProviderReference', headerName: translateCrudLabel('ProviderReference'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -200,7 +201,7 @@ export const loadColumns = async (
{ {
field: 'processed_at', field: 'processed_at',
headerName: 'ProcessedAt', headerName: translateCrudLabel('ProcessedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -218,7 +219,7 @@ export const loadColumns = async (
{ {
field: 'failure_reason', field: 'failure_reason',
headerName: 'FailureReason', headerName: translateCrudLabel('FailureReason'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configurePermissionsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
`permissions`, `permissions`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'name', field: 'name',
headerName: 'Name', headerName: translateCrudLabel('Name'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -20,11 +21,13 @@ import {dataGridStyles} from "../../styles";
import KanbanBoard from '../KanbanBoard/KanbanBoard'; import KanbanBoard from '../KanbanBoard/KanbanBoard';
import axios from 'axios'; import axios from 'axios';
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -209,7 +212,7 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
`ponds`, `ponds`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -306,7 +309,7 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -320,7 +323,7 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -330,7 +333,7 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -340,12 +343,12 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -355,22 +358,22 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -385,12 +388,12 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -398,11 +401,11 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -412,11 +415,11 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -424,7 +427,7 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -465,7 +468,7 @@ const TableSamplePonds = ({ filterItems, setFilterItems, filters, showGrid }) =>
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'location', field: 'location',
headerName: 'Location', headerName: translateCrudLabel('Location'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'pond_name', field: 'pond_name',
headerName: 'PondName', headerName: translateCrudLabel('PondName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -102,7 +103,7 @@ export const loadColumns = async (
{ {
field: 'pond_type', field: 'pond_type',
headerName: 'PondType', headerName: translateCrudLabel('PondType'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -117,7 +118,7 @@ export const loadColumns = async (
{ {
field: 'area_sq_m', field: 'area_sq_m',
headerName: 'AreaSqM', headerName: translateCrudLabel('AreaSqM'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -133,7 +134,7 @@ export const loadColumns = async (
{ {
field: 'avg_depth_m', field: 'avg_depth_m',
headerName: 'AverageDepthM', headerName: translateCrudLabel('AverageDepthM'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -149,7 +150,7 @@ export const loadColumns = async (
{ {
field: 'notes', field: 'notes',
headerName: 'Notes', headerName: translateCrudLabel('Notes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -164,7 +165,7 @@ export const loadColumns = async (
{ {
field: 'status', field: 'status',
headerName: 'Status', headerName: translateCrudLabel('Status'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureRolesCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
`roles`, `roles`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'name', field: 'name',
headerName: 'Name', headerName: translateCrudLabel('Name'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -58,7 +59,7 @@ export const loadColumns = async (
{ {
field: 'permissions', field: 'permissions',
headerName: 'Permissions', headerName: translateCrudLabel('Permissions'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -78,7 +79,7 @@ export const loadColumns = async (
{ {
field: 'globalAccess', field: 'globalAccess',
headerName: 'Global Access', headerName: translateCrudLabel('Global Access'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,17 +1,19 @@
import React from 'react'; import React from 'react';
import CardBox from './CardBox'; import CardBox from './CardBox';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { humanize } from '../helpers/humanize'; import { useTranslation } from 'react-i18next';
import { translateCrudLabel } from '../helpers/translateCrudLabel';
const SearchResults = ({ searchResults, searchQuery }) => { const SearchResults = ({ searchResults, searchQuery }) => {
const router = useRouter(); const router = useRouter();
const { t } = useTranslation('common');
return ( return (
<> <>
<p className={'block font-bold mb-2'}>Matches with: {searchQuery}</p> <p className={'block font-bold mb-2'}>{t('labels.matches_with', { query: searchQuery })}</p>
{Object.keys(searchResults).map((tableName) => ( {Object.keys(searchResults).map((tableName) => (
<> <>
<p className={'block font-bold mb-2'}>{humanize(tableName)}</p> <p className={'block font-bold mb-2'}>{translateCrudLabel(tableName, t)}</p>
<CardBox <CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden' className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable hasTable
@ -30,7 +32,7 @@ const SearchResults = ({ searchResults, searchQuery }) => {
) { ) {
return ( return (
<th data-label={key} key={key}> <th data-label={key} key={key}>
{humanize(key)} {translateCrudLabel(key, t)}
</th> </th>
); );
} }
@ -68,13 +70,13 @@ const SearchResults = ({ searchResults, searchQuery }) => {
</table> </table>
</div> </div>
{!Object.keys(searchResults).length && ( {!Object.keys(searchResults).length && (
<div className={'text-center py-4'}>No data</div> <div className={'text-center py-4'}>{translateCrudLabel('No data', t)}</div>
)} )}
</CardBox> </CardBox>
</> </>
))} ))}
{!Object.keys(searchResults).length && ( {!Object.keys(searchResults).length && (
<div className={'py-4'}>No matches</div> <div className={'py-4'}>{translateCrudLabel('No matches', t)}</div>
)} )}
</> </>
); );

View File

@ -3,7 +3,8 @@ import React, { Children, ReactNode } from 'react'
import BaseButton from './BaseButton' import BaseButton from './BaseButton'
import BaseIcon from './BaseIcon' import BaseIcon from './BaseIcon'
import IconRounded from './IconRounded' import IconRounded from './IconRounded'
import { humanize } from '../helpers/humanize'; import { useTranslation } from 'react-i18next';
import { translateCrudLabel } from '../helpers/translateCrudLabel';
type Props = { type Props = {
icon: string icon: string
@ -13,14 +14,16 @@ type Props = {
} }
export default function SectionTitleLineWithButton({ icon, title, main = false, children }: Props) { export default function SectionTitleLineWithButton({ icon, title, main = false, children }: Props) {
const { t } = useTranslation('common')
const hasChildren = !!Children.count(children) const hasChildren = !!Children.count(children)
const translatedTitle = translateCrudLabel(title, t)
return ( return (
<section className={`${main ? '' : 'pt-6'} mb-6 flex items-center justify-between`}> <section className={`${main ? '' : 'pt-6'} mb-6 flex items-center justify-between`}>
<div className="flex items-center justify-start"> <div className="flex items-center justify-start">
{icon && main && <IconRounded icon={icon} color="light" className="mr-3" bg />} {icon && main && <IconRounded icon={icon} color="light" className="mr-3" bg />}
{icon && !main && <BaseIcon path={icon} className="mr-2" size="20" />} {icon && !main && <BaseIcon path={icon} className="mr-2" size="20" />}
<h1 className={`leading-tight ${main ? 'text-3xl' : 'text-2xl'}`}>{humanize(title)}</h1> <h1 className={`leading-tight ${main ? 'text-3xl' : 'text-2xl'}`}>{translatedTitle}</h1>
</div> </div>
{children} {children}
{!hasChildren && <BaseButton icon={mdiCog} color="whiteDark" />} {!hasChildren && <BaseButton icon={mdiCog} color="whiteDark" />}

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureShipment_updatesCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
`shipment_updates`, `shipment_updates`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleShipment_updates = ({ filterItems, setFilterItems, filters, sho
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'order', field: 'order',
headerName: 'Order', headerName: translateCrudLabel('Order'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'shipment_status', field: 'shipment_status',
headerName: 'ShipmentStatus', headerName: translateCrudLabel('ShipmentStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -80,7 +81,7 @@ export const loadColumns = async (
{ {
field: 'carrier', field: 'carrier',
headerName: 'Carrier', headerName: translateCrudLabel('Carrier'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -95,7 +96,7 @@ export const loadColumns = async (
{ {
field: 'tracking_number', field: 'tracking_number',
headerName: 'TrackingNumber', headerName: translateCrudLabel('TrackingNumber'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -110,7 +111,7 @@ export const loadColumns = async (
{ {
field: 'status_at', field: 'status_at',
headerName: 'StatusAt', headerName: translateCrudLabel('StatusAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -128,7 +129,7 @@ export const loadColumns = async (
{ {
field: 'status_details', field: 'status_details',
headerName: 'StatusDetails', headerName: translateCrudLabel('StatusDetails'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureSpeciesCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
`species`, `species`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleSpecies = ({ filterItems, setFilterItems, filters, showGrid })
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'species_name', field: 'species_name',
headerName: 'SpeciesName', headerName: translateCrudLabel('SpeciesName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -58,7 +59,7 @@ export const loadColumns = async (
{ {
field: 'scientific_name', field: 'scientific_name',
headerName: 'ScientificName', headerName: translateCrudLabel('ScientificName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -73,7 +74,7 @@ export const loadColumns = async (
{ {
field: 'typical_harvest_size', field: 'typical_harvest_size',
headerName: 'TypicalHarvestSize', headerName: translateCrudLabel('TypicalHarvestSize'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,6 +17,7 @@ import {loadColumns} from "./configureTenant_locationsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
import CardTenant_locations from './CardTenant_locations'; import CardTenant_locations from './CardTenant_locations';
@ -24,6 +26,7 @@ import CardTenant_locations from './CardTenant_locations';
const perPage = 10 const perPage = 10
const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -182,7 +185,7 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
`tenant_locations`, `tenant_locations`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -279,7 +282,7 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -293,7 +296,7 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -303,7 +306,7 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -313,12 +316,12 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -328,22 +331,22 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -358,12 +361,12 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -371,11 +374,11 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -385,11 +388,11 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -397,7 +400,7 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -438,7 +441,7 @@ const TableSampleTenant_locations = ({ filterItems, setFilterItems, filters, sho
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'location_name', field: 'location_name',
headerName: 'LocationName', headerName: translateCrudLabel('LocationName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -80,7 +81,7 @@ export const loadColumns = async (
{ {
field: 'address', field: 'address',
headerName: 'Address', headerName: translateCrudLabel('Address'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -95,7 +96,7 @@ export const loadColumns = async (
{ {
field: 'latitude', field: 'latitude',
headerName: 'Latitude', headerName: translateCrudLabel('Latitude'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -111,7 +112,7 @@ export const loadColumns = async (
{ {
field: 'longitude', field: 'longitude',
headerName: 'Longitude', headerName: translateCrudLabel('Longitude'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -127,7 +128,7 @@ export const loadColumns = async (
{ {
field: 'timezone', field: 'timezone',
headerName: 'Timezone', headerName: translateCrudLabel('Timezone'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -142,7 +143,7 @@ export const loadColumns = async (
{ {
field: 'is_primary', field: 'is_primary',
headerName: 'IsPrimary', headerName: translateCrudLabel('IsPrimary'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureTenantsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
`tenants`, `tenants`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleTenants = ({ filterItems, setFilterItems, filters, showGrid })
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant_name', field: 'tenant_name',
headerName: 'TenantName', headerName: translateCrudLabel('TenantName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -58,7 +59,7 @@ export const loadColumns = async (
{ {
field: 'slug', field: 'slug',
headerName: 'Slug', headerName: translateCrudLabel('Slug'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -73,7 +74,7 @@ export const loadColumns = async (
{ {
field: 'tenant_type', field: 'tenant_type',
headerName: 'TenantType', headerName: translateCrudLabel('TenantType'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -88,7 +89,7 @@ export const loadColumns = async (
{ {
field: 'contact_email', field: 'contact_email',
headerName: 'ContactEmail', headerName: translateCrudLabel('ContactEmail'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -103,7 +104,7 @@ export const loadColumns = async (
{ {
field: 'contact_phone', field: 'contact_phone',
headerName: 'ContactPhone', headerName: translateCrudLabel('ContactPhone'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -118,7 +119,7 @@ export const loadColumns = async (
{ {
field: 'billing_address', field: 'billing_address',
headerName: 'BillingAddress', headerName: translateCrudLabel('BillingAddress'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -133,7 +134,7 @@ export const loadColumns = async (
{ {
field: 'subscription_status', field: 'subscription_status',
headerName: 'SubscriptionStatus', headerName: translateCrudLabel('SubscriptionStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -148,7 +149,7 @@ export const loadColumns = async (
{ {
field: 'trial_ends_at', field: 'trial_ends_at',
headerName: 'TrialEndsAt', headerName: translateCrudLabel('TrialEndsAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -166,7 +167,7 @@ export const loadColumns = async (
{ {
field: 'is_enabled', field: 'is_enabled',
headerName: 'IsEnabled', headerName: translateCrudLabel('IsEnabled'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureUser_membershipsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
`user_memberships`, `user_memberships`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleUser_memberships = ({ filterItems, setFilterItems, filters, sho
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'user', field: 'user',
headerName: 'User', headerName: translateCrudLabel('User'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'role', field: 'role',
headerName: 'Role', headerName: translateCrudLabel('Role'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -109,7 +110,7 @@ export const loadColumns = async (
{ {
field: 'membership_status', field: 'membership_status',
headerName: 'MembershipStatus', headerName: translateCrudLabel('MembershipStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -124,7 +125,7 @@ export const loadColumns = async (
{ {
field: 'joined_at', field: 'joined_at',
headerName: 'JoinedAt', headerName: translateCrudLabel('JoinedAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureUsersCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
`users`, `users`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'firstName', field: 'firstName',
headerName: 'First Name', headerName: translateCrudLabel('First Name'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -58,7 +59,7 @@ export const loadColumns = async (
{ {
field: 'lastName', field: 'lastName',
headerName: 'Last Name', headerName: translateCrudLabel('Last Name'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -73,7 +74,7 @@ export const loadColumns = async (
{ {
field: 'phoneNumber', field: 'phoneNumber',
headerName: 'Phone Number', headerName: translateCrudLabel('Phone Number'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -88,7 +89,7 @@ export const loadColumns = async (
{ {
field: 'email', field: 'email',
headerName: 'E-Mail', headerName: translateCrudLabel('E-Mail'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -103,7 +104,7 @@ export const loadColumns = async (
{ {
field: 'disabled', field: 'disabled',
headerName: 'Disabled', headerName: translateCrudLabel('Disabled'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -119,7 +120,7 @@ export const loadColumns = async (
{ {
field: 'avatar', field: 'avatar',
headerName: 'Avatar', headerName: translateCrudLabel('Avatar'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -140,7 +141,7 @@ export const loadColumns = async (
{ {
field: 'app_role', field: 'app_role',
headerName: 'App Role', headerName: translateCrudLabel('App Role'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -162,7 +163,7 @@ export const loadColumns = async (
{ {
field: 'custom_permissions', field: 'custom_permissions',
headerName: 'Custom Permissions', headerName: translateCrudLabel('Custom Permissions'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -182,7 +183,7 @@ export const loadColumns = async (
{ {
field: 'organizations', field: 'organizations',
headerName: 'Organizations', headerName: translateCrudLabel('Organizations'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureWater_quality_logsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
`water_quality_logs`, `water_quality_logs`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleWater_quality_logs = ({ filterItems, setFilterItems, filters, s
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'pond', field: 'pond',
headerName: 'Pond', headerName: translateCrudLabel('Pond'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -87,7 +88,7 @@ export const loadColumns = async (
{ {
field: 'sampled_at', field: 'sampled_at',
headerName: 'SampledAt', headerName: translateCrudLabel('SampledAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -105,7 +106,7 @@ export const loadColumns = async (
{ {
field: 'temperature_c', field: 'temperature_c',
headerName: 'TemperatureC', headerName: translateCrudLabel('TemperatureC'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -121,7 +122,7 @@ export const loadColumns = async (
{ {
field: 'ph', field: 'ph',
headerName: 'pH', headerName: translateCrudLabel('pH'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -137,7 +138,7 @@ export const loadColumns = async (
{ {
field: 'dissolved_oxygen_mg_l', field: 'dissolved_oxygen_mg_l',
headerName: 'DissolvedOxygenMgL', headerName: translateCrudLabel('DissolvedOxygenMgL'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -153,7 +154,7 @@ export const loadColumns = async (
{ {
field: 'salinity_ppt', field: 'salinity_ppt',
headerName: 'SalinityPpt', headerName: translateCrudLabel('SalinityPpt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -169,7 +170,7 @@ export const loadColumns = async (
{ {
field: 'ammonia_mg_l', field: 'ammonia_mg_l',
headerName: 'AmmoniaMgL', headerName: translateCrudLabel('AmmoniaMgL'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -185,7 +186,7 @@ export const loadColumns = async (
{ {
field: 'nitrite_mg_l', field: 'nitrite_mg_l',
headerName: 'NitriteMgL', headerName: translateCrudLabel('NitriteMgL'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -201,7 +202,7 @@ export const loadColumns = async (
{ {
field: 'nitrate_mg_l', field: 'nitrate_mg_l',
headerName: 'NitrateMgL', headerName: translateCrudLabel('NitrateMgL'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -217,7 +218,7 @@ export const loadColumns = async (
{ {
field: 'turbidity_ntu', field: 'turbidity_ntu',
headerName: 'TurbidityNTU', headerName: translateCrudLabel('TurbidityNTU'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -233,7 +234,7 @@ export const loadColumns = async (
{ {
field: 'notes', field: 'notes',
headerName: 'Notes', headerName: translateCrudLabel('Notes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -248,7 +249,7 @@ export const loadColumns = async (
{ {
field: 'recorded_by', field: 'recorded_by',
headerName: 'RecordedBy', headerName: translateCrudLabel('RecordedBy'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureWebhook_deliveriesCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
`webhook_deliveries`, `webhook_deliveries`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleWebhook_deliveries = ({ filterItems, setFilterItems, filters, s
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'endpoint', field: 'endpoint',
headerName: 'Endpoint', headerName: translateCrudLabel('Endpoint'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'event_type', field: 'event_type',
headerName: 'EventType', headerName: translateCrudLabel('EventType'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -80,7 +81,7 @@ export const loadColumns = async (
{ {
field: 'event_reference', field: 'event_reference',
headerName: 'EventReference', headerName: translateCrudLabel('EventReference'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -95,7 +96,7 @@ export const loadColumns = async (
{ {
field: 'delivered_at', field: 'delivered_at',
headerName: 'DeliveredAt', headerName: translateCrudLabel('DeliveredAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -113,7 +114,7 @@ export const loadColumns = async (
{ {
field: 'delivery_status', field: 'delivery_status',
headerName: 'DeliveryStatus', headerName: translateCrudLabel('DeliveryStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -128,7 +129,7 @@ export const loadColumns = async (
{ {
field: 'http_status', field: 'http_status',
headerName: 'HTTPStatus', headerName: translateCrudLabel('HTTPStatus'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -144,7 +145,7 @@ export const loadColumns = async (
{ {
field: 'request_payload', field: 'request_payload',
headerName: 'RequestPayload', headerName: translateCrudLabel('RequestPayload'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -159,7 +160,7 @@ export const loadColumns = async (
{ {
field: 'response_body', field: 'response_body',
headerName: 'ResponseBody', headerName: translateCrudLabel('ResponseBody'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -174,7 +175,7 @@ export const loadColumns = async (
{ {
field: 'attempt_count', field: 'attempt_count',
headerName: 'AttemptCount', headerName: translateCrudLabel('AttemptCount'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useMemo } from 'react' import React, { useEffect, useState, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
@ -16,12 +17,14 @@ import {loadColumns} from "./configureWebhook_endpointsCols";
import _ from 'lodash'; import _ from 'lodash';
import dataFormatter from '../../helpers/dataFormatter' import dataFormatter from '../../helpers/dataFormatter'
import {dataGridStyles} from "../../styles"; import {dataGridStyles} from "../../styles";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
const perPage = 10 const perPage = 10
const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, showGrid }) => { const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, showGrid }) => {
const { t, i18n } = useTranslation('common');
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"}); const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@ -180,7 +183,7 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
`webhook_endpoints`, `webhook_endpoints`,
currentUser, currentUser,
).then((newCols) => setColumns(newCols)); ).then((newCols) => setColumns(newCols));
}, [currentUser]); }, [currentUser, i18n.language]);
@ -277,7 +280,7 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
return ( return (
<div key={filterItem.id} className="flex mb-4"> <div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Filter', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='selectedField' name='selectedField'
@ -291,7 +294,7 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
key={selectOption.title} key={selectOption.title}
value={`${selectOption.title}`} value={`${selectOption.title}`}
> >
{selectOption.label} {translateCrudLabel(selectOption.label, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -301,7 +304,7 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
)?.type === 'enum' ? ( )?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold"> <div className="text-gray-500 font-bold">
Value {translateCrudLabel('Value', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
@ -311,12 +314,12 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
> >
<option value="">Select Value</option> <option value="">{translateCrudLabel('Select Value', t)}</option>
{filters.find((filter) => {filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => ( )?.options?.map((option) => (
<option key={option} value={option}> <option key={option} value={option}>
{option} {translateCrudLabel(option, t)}
</option> </option>
))} ))}
</Field> </Field>
@ -326,22 +329,22 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
)?.number ? ( )?.number ? (
<div className="flex flex-row w-full mr-3"> <div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('From', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
/> />
</div> </div>
<div className="flex flex-col w-full"> <div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -356,12 +359,12 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
<div className='flex flex-row w-full mr-3'> <div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'> <div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'> <div className=' text-gray-500 font-bold'>
From {translateCrudLabel('From', t)}
</div> </div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueFrom' name='filterValueFrom'
placeholder='From' placeholder={translateCrudLabel('From', t)}
id='filterValueFrom' id='filterValueFrom'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''} value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +372,11 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
/> />
</div> </div>
<div className='flex flex-col w-full'> <div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div> <div className=' text-gray-500 font-bold'>{translateCrudLabel('To', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValueTo' name='filterValueTo'
placeholder='to' placeholder={translateCrudLabel('To', t)}
id='filterValueTo' id='filterValueTo'
type='datetime-local' type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''} value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +386,11 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
</div> </div>
) : ( ) : (
<div className="flex flex-col w-full mr-3"> <div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Contains', t)}</div>
<Field <Field
className={controlClasses} className={controlClasses}
name='filterValue' name='filterValue'
placeholder='Contained' placeholder={translateCrudLabel('Contained', t)}
id='filterValue' id='filterValue'
value={filterItem?.fields?.filterValue || ''} value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)} onChange={handleChange(filterItem.id)}
@ -395,7 +398,7 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">{translateCrudLabel('Action', t)}</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
@ -436,7 +439,7 @@ const TableSampleWebhook_endpoints = ({ filterItems, setFilterItems, filters, sh
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>{translateCrudLabel('Are you sure you want to delete this item?', t)}</p>
</CardBoxModal> </CardBoxModal>

View File

@ -14,6 +14,7 @@ import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover'; import ListActionsPopover from '../ListActionsPopover';
import {hasPermission} from "../../helpers/userPermissions"; import {hasPermission} from "../../helpers/userPermissions";
import { translateCrudLabel } from '../../helpers/translateCrudLabel';
type Params = (id: string) => void; type Params = (id: string) => void;
@ -43,7 +44,7 @@ export const loadColumns = async (
{ {
field: 'tenant', field: 'tenant',
headerName: 'Tenant', headerName: translateCrudLabel('Tenant'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -65,7 +66,7 @@ export const loadColumns = async (
{ {
field: 'endpoint_name', field: 'endpoint_name',
headerName: 'EndpointName', headerName: translateCrudLabel('EndpointName'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -80,7 +81,7 @@ export const loadColumns = async (
{ {
field: 'url', field: 'url',
headerName: 'URL', headerName: translateCrudLabel('URL'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -95,7 +96,7 @@ export const loadColumns = async (
{ {
field: 'secret', field: 'secret',
headerName: 'Secret', headerName: translateCrudLabel('Secret'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -110,7 +111,7 @@ export const loadColumns = async (
{ {
field: 'is_enabled', field: 'is_enabled',
headerName: 'IsEnabled', headerName: translateCrudLabel('IsEnabled'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -126,7 +127,7 @@ export const loadColumns = async (
{ {
field: 'event_types', field: 'event_types',
headerName: 'EventTypes', headerName: translateCrudLabel('EventTypes'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,
@ -141,7 +142,7 @@ export const loadColumns = async (
{ {
field: 'last_delivery_at', field: 'last_delivery_at',
headerName: 'LastDeliveryAt', headerName: translateCrudLabel('LastDeliveryAt'),
flex: 1, flex: 1,
minWidth: 120, minWidth: 120,
filterable: false, filterable: false,

View File

@ -0,0 +1,73 @@
import type { TFunction } from 'i18next'
import i18n from '../i18n'
import { humanize } from './humanize'
const splitCamelCase = (value: string) =>
value
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
export const crudLabelKey = (value?: string | null) => {
if (!value) return ''
return splitCamelCase(String(value))
.replace(/&/g, ' and ')
.replace(/[./]/g, ' ')
.replace(/[^A-Za-z0-9_\s-]/g, '')
.replace(/[-\s]+/g, '_')
.replace(/_+/g, '_')
.replace(/^_+|_+$/g, '')
.toLowerCase()
}
const fallbackLabel = (value: string) =>
humanize(splitCamelCase(value).replace(/_/g, ' '))
.replace(/\bApi\b/g, 'API')
.replace(/\bCsv\b/g, 'CSV')
.replace(/\bHttp\b/g, 'HTTP')
.replace(/\bId\b/g, 'ID')
.replace(/\bKg\b/g, 'kg')
.replace(/\bSq\b/g, 'sq')
.replace(/\bMg\b/g, 'mg')
.replace(/\bMm\b/g, 'mm')
.replace(/\bNtu\b/g, 'NTU')
.replace(/\bPh\b/g, 'pH')
export const translateCrudLabel = (value?: string | null, t?: TFunction<'common'>) => {
if (!value) return ''
const rawValue = String(value)
const key = crudLabelKey(rawValue)
const translate = t || i18n.t.bind(i18n)
const deleteRowsMatch = rawValue.match(/^Delete\s+(\d+)\s+(Row|Rows)$/i)
if (deleteRowsMatch) {
return translate('crud.actions.delete_rows', {
count: Number(deleteRowsMatch[1]),
defaultValue: fallbackLabel(rawValue),
})
}
const actionPhraseMatch = fallbackLabel(rawValue).match(/^(View|Edit|New)\s+(.+)$/i)
if (actionPhraseMatch) {
const actionKey = crudLabelKey(actionPhraseMatch[1])
const entityLabel = translateCrudLabel(actionPhraseMatch[2], t)
const actionLabel = translate(`crud.actions.${actionKey}`, {
defaultValue: actionPhraseMatch[1],
})
return `${actionLabel} ${entityLabel}`.trim()
}
const candidates = [
`labels.${key}`,
`crud.actions.${key}`,
`entities.${key}`,
`fields.${key}`,
`enums.${key}`,
]
const match = candidates.find((candidate) => i18n.exists(candidate))
return match ? translate(match) : fallbackLabel(rawValue)
}

View File

@ -1,21 +1,25 @@
import i18n from 'i18next'; import i18n from 'i18next';
import { initReactI18next } from 'react-i18next'; import { initReactI18next } from 'react-i18next';
import HttpApi from 'i18next-http-backend'; import idCommon from '../public/locales/id/common.json';
import LanguageDetector from 'i18next-browser-languagedetector'; import enGBCommon from '../public/locales/en-GB/common.json';
i18n i18n
.use(HttpApi)
.use(LanguageDetector)
.use(initReactI18next) .use(initReactI18next)
.init({ .init({
fallbackLng: 'en', lng: 'id',
detection: { fallbackLng: 'id',
order: ['localStorage', 'navigator'], supportedLngs: ['id', 'en-GB'],
lookupLocalStorage: 'app_lang_', resources: {
caches: ['localStorage'], id: {
common: idCommon,
}, },
backend: { 'en-GB': {
loadPath: '/locales/{{lng}}/{{ns}}.json', common: enGBCommon,
}, },
},
defaultNS: 'common',
ns: ['common'],
interpolation: { escapeValue: false }, interpolation: { escapeValue: false },
}); });
export default i18n;

View File

@ -1,5 +1,4 @@
import React, { ReactNode, useEffect } from 'react' import React, { ReactNode, useEffect, useState } from 'react'
import { useState } from 'react'
import jwt from 'jsonwebtoken'; import jwt from 'jsonwebtoken';
import { mdiForwardburger, mdiBackburger, mdiMenu } from '@mdi/js' import { mdiForwardburger, mdiBackburger, mdiMenu } from '@mdi/js'
import menuAside from '../menuAside' import menuAside from '../menuAside'

View File

@ -7,6 +7,12 @@ const menuAside: MenuAsideItem[] = [
icon: icon.mdiViewDashboardOutline, icon: icon.mdiViewDashboardOutline,
label: 'Dashboard', label: 'Dashboard',
}, },
{
href: '/farm-ops',
icon: 'mdiFishbowlOutline' in icon ? icon['mdiFishbowlOutline' as keyof typeof icon] : icon.mdiFish,
label: 'Farm Ops',
permissions: 'READ_FEEDING_LOGS'
},
{ {
href: '/users/users-list', href: '/users/users-list',

View File

@ -12,7 +12,6 @@ import { useRouter } from 'next/router';
import ErrorBoundary from "../components/ErrorBoundary"; import ErrorBoundary from "../components/ErrorBoundary";
import DevModeBadge from '../components/DevModeBadge'; import DevModeBadge from '../components/DevModeBadge';
import 'intro.js/introjs.css'; import 'intro.js/introjs.css';
import { appWithTranslation } from 'next-i18next';
import '../i18n'; import '../i18n';
import IntroGuide from '../components/IntroGuide'; import IntroGuide from '../components/IntroGuide';
import { appSteps, loginSteps, usersSteps, rolesSteps } from '../stores/introSteps'; import { appSteps, loginSteps, usersSteps, rolesSteps } from '../stores/introSteps';
@ -198,4 +197,4 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
) )
} }
export default appWithTranslation(MyApp); export default MyApp;

View File

@ -0,0 +1,543 @@
import {
mdiCalendarCheck,
mdiChartTimelineVariant,
mdiClipboardTextClock,
mdiFish,
mdiFoodDrumstick,
mdiStorefront,
mdiWaterPercent,
} from '@mdi/js'
import Head from 'next/head'
import React, { ReactElement, useEffect, useMemo, useState } from 'react'
import axios from 'axios'
import BaseButton from '../components/BaseButton'
import CardBox from '../components/CardBox'
import LayoutAuthenticated from '../layouts/Authenticated'
import SectionMain from '../components/SectionMain'
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton'
import BaseIcon from '../components/BaseIcon'
import { getPageTitle } from '../config'
import { hasPermission } from '../helpers/userPermissions'
import { useAppSelector } from '../stores/hooks'
import { useTranslation } from 'react-i18next'
import { translateCrudLabel } from '../helpers/translateCrudLabel'
type Option = {
id: string
label: string
}
type FeedLog = {
id: string
fed_at?: string
quantity_kg?: string | number
feeding_method?: string
appetite?: string
notes?: string
batch?: { id?: string; batch_code?: string }
feed_product?: { id?: string; product_name?: string }
recorded_by?: { firstName?: string; lastName?: string; email?: string }
createdAt?: string
}
type OpsForm = {
batch: string
feed_product: string
fed_at: string
quantity_kg: string
feeding_method: string
appetite: string
notes: string
}
const initialForm: OpsForm = {
batch: '',
feed_product: '',
fed_at: '',
quantity_kg: '',
feeding_method: 'manual',
appetite: 'normal',
notes: '',
}
const nowForDateTimeLocal = () => {
const date = new Date()
date.setMinutes(date.getMinutes() - date.getTimezoneOffset())
return date.toISOString().slice(0, 16)
}
const formatDateTime = (value?: string, locale = 'id', emptyLabel = 'Not scheduled') => {
if (!value) return emptyLabel
return new Intl.DateTimeFormat(locale, {
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: '2-digit',
}).format(new Date(value))
}
const formatQuantity = (value?: string | number, locale = 'id') => {
if (value === undefined || value === null || value === '') return '0 kg'
return `${Number(value).toLocaleString(locale, { maximumFractionDigits: 2 })} kg`
}
const getRecorder = (log?: FeedLog, fallback = 'Team member') => {
const firstName = log?.recorded_by?.firstName || ''
const lastName = log?.recorded_by?.lastName || ''
const fullName = `${firstName} ${lastName}`.trim()
return fullName || log?.recorded_by?.email || fallback
}
const statusStyles = {
low: 'bg-amber-100 text-amber-800 ring-amber-200',
normal: 'bg-emerald-100 text-emerald-800 ring-emerald-200',
high: 'bg-sky-100 text-sky-800 ring-sky-200',
}
const FarmOpsPage = () => {
const { t, i18n } = useTranslation('common')
const locale = i18n.resolvedLanguage || i18n.language || 'id'
const tr = (value: string) => translateCrudLabel(value, t)
const { currentUser } = useAppSelector((state) => state.auth)
const [logs, setLogs] = useState<FeedLog[]>([])
const [batchOptions, setBatchOptions] = useState<Option[]>([])
const [feedOptions, setFeedOptions] = useState<Option[]>([])
const [selectedLog, setSelectedLog] = useState<FeedLog | null>(null)
const [form, setForm] = useState<OpsForm>({ ...initialForm, fed_at: nowForDateTimeLocal() })
const [loading, setLoading] = useState(true)
const [saving, setSaving] = useState(false)
const [message, setMessage] = useState('')
const [error, setError] = useState('')
const canCreateFeedLog = currentUser && hasPermission(currentUser, 'CREATE_FEEDING_LOGS')
const totalFedToday = useMemo(() => {
const today = new Date().toDateString()
return logs
.filter((log) => log.fed_at && new Date(log.fed_at).toDateString() === today)
.reduce((sum, log) => sum + Number(log.quantity_kg || 0), 0)
}, [logs])
const activeBatchCount = useMemo(() => {
const ids = new Set(logs.map((log) => log.batch?.id).filter(Boolean))
return ids.size
}, [logs])
const latestAppetite = tr(logs[0]?.appetite || 'normal')
const fetchWorkspace = async () => {
setLoading(true)
setError('')
try {
const [feedLogResponse, batchResponse, feedProductResponse] = await Promise.all([
axios.get('/feeding_logs?limit=12&field=fed_at&sort=DESC'),
axios.get('/batches/autocomplete?limit=100'),
axios.get('/feed_products/autocomplete?limit=100'),
])
const latestLogs = Array.isArray(feedLogResponse.data?.rows) ? feedLogResponse.data.rows : []
const batches = Array.isArray(batchResponse.data) ? batchResponse.data : []
const feeds = Array.isArray(feedProductResponse.data) ? feedProductResponse.data : []
setLogs(latestLogs)
setBatchOptions(batches)
setFeedOptions(feeds)
setSelectedLog((current) => current || latestLogs[0] || null)
setForm((current) => ({
...current,
batch: current.batch || batches[0]?.id || '',
feed_product: current.feed_product || feeds[0]?.id || '',
}))
} catch (fetchError) {
console.error('Farm ops workspace failed to load', fetchError)
setError(tr('Could not load the farm operations workspace. Please refresh or check your permissions.'))
} finally {
setLoading(false)
}
}
useEffect(() => {
fetchWorkspace()
}, [])
const handleChange = (field: keyof OpsForm, value: string) => {
setForm((current) => ({ ...current, [field]: value }))
}
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
setError('')
setMessage('')
if (!form.batch) {
setError(tr('Choose a batch before recording feed.'))
return
}
if (!form.fed_at) {
setError(tr('Add the feeding time.'))
return
}
if (!form.quantity_kg || Number(form.quantity_kg) <= 0) {
setError(tr('Feed quantity must be greater than 0 kg.'))
return
}
setSaving(true)
try {
await axios.post('/feeding_logs', {
data: {
batch: form.batch,
feed_product: form.feed_product || null,
fed_at: new Date(form.fed_at).toISOString(),
quantity_kg: form.quantity_kg,
feeding_method: form.feeding_method,
appetite: form.appetite,
notes: form.notes,
recorded_by: currentUser?.id || null,
},
})
setMessage(tr('Feeding record saved. The latest activity list has been refreshed.'))
setForm({ ...initialForm, fed_at: nowForDateTimeLocal(), batch: form.batch, feed_product: form.feed_product })
await fetchWorkspace()
} catch (saveError) {
console.error('Farm ops feeding log save failed', saveError)
setError(tr('Could not save the feeding record. Please check the values and try again.'))
} finally {
setSaving(false)
}
}
return (
<>
<Head>
<title>{getPageTitle(tr('Farm Ops Command Center'))}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Farm Ops Command Center" main>
<BaseButton href="/feeding_logs/feeding_logs-list" label="Open full CRUD" color="whiteDark" />
</SectionTitleLineWithButton>
<section className="mb-6 overflow-hidden rounded-3xl bg-gradient-to-br from-[#042f2e] via-[#075985] to-[#0f766e] p-1 shadow-xl">
<div className="rounded-[1.35rem] bg-white/10 p-6 text-white backdrop-blur md:p-8">
<div className="grid gap-6 lg:grid-cols-[1.35fr_0.65fr] lg:items-end">
<div>
<p className="mb-3 inline-flex rounded-full bg-white/15 px-3 py-1 text-xs font-semibold uppercase tracking-[0.24em] text-cyan-100 ring-1 ring-white/20">
{tr('Multi-tenant aquaculture workflow')}
</p>
<h2 className="max-w-3xl text-3xl font-black tracking-tight md:text-5xl">
{tr('Record feed, monitor appetite, and keep the farm team aligned.')}
</h2>
<p className="mt-4 max-w-2xl text-sm leading-6 text-cyan-50 md:text-base">
{tr('A focused daily operations slice built on top of your generated CRUD entities: batches, feed products, and feeding logs.')}
</p>
</div>
<div className="grid grid-cols-3 gap-3 text-center">
<div className="rounded-2xl bg-white/15 p-4 ring-1 ring-white/20">
<div className="text-2xl font-black">{formatQuantity(totalFedToday, locale)}</div>
<div className="mt-1 text-xs text-cyan-100">{tr('Fed today')}</div>
</div>
<div className="rounded-2xl bg-white/15 p-4 ring-1 ring-white/20">
<div className="text-2xl font-black">{activeBatchCount}</div>
<div className="mt-1 text-xs text-cyan-100">{tr('Active batches')}</div>
</div>
<div className="rounded-2xl bg-white/15 p-4 ring-1 ring-white/20">
<div className="text-2xl font-black capitalize">{latestAppetite}</div>
<div className="mt-1 text-xs text-cyan-100">{tr('Latest appetite')}</div>
</div>
</div>
</div>
</div>
</section>
{(message || error) && (
<div
className={`mb-6 rounded-2xl px-4 py-3 text-sm ring-1 ${
error ? 'bg-rose-50 text-rose-800 ring-rose-200' : 'bg-emerald-50 text-emerald-800 ring-emerald-200'
}`}
>
{error || message}
</div>
)}
<div className="grid gap-6 xl:grid-cols-[0.9fr_1.1fr]">
<CardBox className="border-0 shadow-lg ring-1 ring-slate-200/80 dark:ring-dark-700">
<div className="mb-5 flex items-start justify-between gap-4">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-teal-600">{tr('Quick input')}</p>
<h3 className="mt-1 text-2xl font-bold text-slate-900 dark:text-white">{tr('Log a feeding')}</h3>
<p className="mt-1 text-sm text-slate-500">{tr('Capture the minimum operational data and confirm it immediately.')}</p>
</div>
<span className="rounded-2xl bg-teal-50 p-3 text-teal-700 ring-1 ring-teal-100">
<BaseIcon path={mdiFoodDrumstick} size="24" />
</span>
</div>
{loading ? (
<div className="rounded-2xl bg-slate-50 p-6 text-sm text-slate-500">{tr('Loading batches and feed products')}</div>
) : batchOptions.length === 0 ? (
<div className="rounded-2xl border border-dashed border-slate-300 bg-slate-50 p-6 text-sm text-slate-600">
<p className="font-semibold text-slate-900">{tr('No batches available yet')}</p>
<p className="mt-2">{tr('Create a batch first, then return here to record daily feeding activity')}</p>
<BaseButton href="/batches/batches-new" label="Create batch" color="info" className="mt-4" />
</div>
) : (
<form className="space-y-4" onSubmit={handleSubmit}>
<label className="block">
<span className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-200">{tr('Batch')}</span>
<select
className="h-11 w-full rounded-xl border border-slate-300 bg-white px-3 text-sm shadow-sm focus:border-teal-500 focus:outline-none focus:ring-2 focus:ring-teal-500/30 dark:border-dark-700 dark:bg-dark-800"
value={form.batch}
onChange={(event) => handleChange('batch', event.target.value)}
disabled={!canCreateFeedLog || saving}
>
{batchOptions.map((batch) => (
<option key={batch.id} value={batch.id}>
{batch.label}
</option>
))}
</select>
</label>
<div className="grid gap-4 md:grid-cols-2">
<label className="block">
<span className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-200">{tr('Fed at')}</span>
<input
className="h-11 w-full rounded-xl border border-slate-300 bg-white px-3 text-sm shadow-sm focus:border-teal-500 focus:outline-none focus:ring-2 focus:ring-teal-500/30 dark:border-dark-700 dark:bg-dark-800"
type="datetime-local"
value={form.fed_at}
onChange={(event) => handleChange('fed_at', event.target.value)}
disabled={!canCreateFeedLog || saving}
/>
</label>
<label className="block">
<span className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-200">{tr('QuantityKg')}</span>
<input
className="h-11 w-full rounded-xl border border-slate-300 bg-white px-3 text-sm shadow-sm focus:border-teal-500 focus:outline-none focus:ring-2 focus:ring-teal-500/30 dark:border-dark-700 dark:bg-dark-800"
min="0"
step="0.01"
type="number"
value={form.quantity_kg}
onChange={(event) => handleChange('quantity_kg', event.target.value)}
disabled={!canCreateFeedLog || saving}
/>
</label>
</div>
<div className="grid gap-4 md:grid-cols-3">
<label className="block md:col-span-1">
<span className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-200">{tr('Feed product')}</span>
<select
className="h-11 w-full rounded-xl border border-slate-300 bg-white px-3 text-sm shadow-sm focus:border-teal-500 focus:outline-none focus:ring-2 focus:ring-teal-500/30 dark:border-dark-700 dark:bg-dark-800"
value={form.feed_product}
onChange={(event) => handleChange('feed_product', event.target.value)}
disabled={!canCreateFeedLog || saving}
>
<option value="">{tr('Not specified')}</option>
{feedOptions.map((feed) => (
<option key={feed.id} value={feed.id}>
{feed.label}
</option>
))}
</select>
</label>
<label className="block md:col-span-1">
<span className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-200">{tr('Method')}</span>
<select
className="h-11 w-full rounded-xl border border-slate-300 bg-white px-3 text-sm shadow-sm focus:border-teal-500 focus:outline-none focus:ring-2 focus:ring-teal-500/30 dark:border-dark-700 dark:bg-dark-800"
value={form.feeding_method}
onChange={(event) => handleChange('feeding_method', event.target.value)}
disabled={!canCreateFeedLog || saving}
>
<option value="manual">{tr('manual')}</option>
<option value="auto_feeder">{tr('auto_feeder')}</option>
<option value="broadcast">{tr('broadcast')}</option>
<option value="tray">{tr('tray')}</option>
<option value="other">{tr('other')}</option>
</select>
</label>
<label className="block md:col-span-1">
<span className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-200">{tr('Appetite')}</span>
<select
className="h-11 w-full rounded-xl border border-slate-300 bg-white px-3 text-sm shadow-sm focus:border-teal-500 focus:outline-none focus:ring-2 focus:ring-teal-500/30 dark:border-dark-700 dark:bg-dark-800"
value={form.appetite}
onChange={(event) => handleChange('appetite', event.target.value)}
disabled={!canCreateFeedLog || saving}
>
<option value="low">{tr('low')}</option>
<option value="normal">{tr('normal')}</option>
<option value="high">{tr('high')}</option>
</select>
</label>
</div>
<label className="block">
<span className="mb-1 block text-sm font-medium text-slate-700 dark:text-slate-200">{tr('Notes')}</span>
<textarea
className="min-h-[104px] w-full rounded-xl border border-slate-300 bg-white px-3 py-3 text-sm shadow-sm focus:border-teal-500 focus:outline-none focus:ring-2 focus:ring-teal-500/30 dark:border-dark-700 dark:bg-dark-800"
placeholder={tr('Optional observation, e.g. fish surfaced quickly, mild leftovers, weather change')}
value={form.notes}
onChange={(event) => handleChange('notes', event.target.value)}
disabled={!canCreateFeedLog || saving}
/>
</label>
{!canCreateFeedLog && (
<p className="rounded-xl bg-amber-50 px-3 py-2 text-sm text-amber-800 ring-1 ring-amber-200">
{tr('Your role can view feeding logs but cannot create new records')}
</p>
)}
<div className="flex flex-wrap gap-3 pt-2">
<BaseButton
color="info"
disabled={!canCreateFeedLog || saving}
label={saving ? 'Saving' : 'Save feeding record'}
type="submit"
/>
<BaseButton color="whiteDark" href="/feeding_logs/feeding_logs-new" label="Advanced form" />
</div>
</form>
)}
</CardBox>
<div className="grid gap-6 lg:grid-cols-[1fr_0.85fr] xl:grid-cols-1 2xl:grid-cols-[1fr_0.85fr]">
<CardBox className="border-0 shadow-lg ring-1 ring-slate-200/80 dark:ring-dark-700">
<div className="mb-5 flex items-center justify-between gap-3">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-sky-600">{tr('Activity stream')}</p>
<h3 className="mt-1 text-2xl font-bold text-slate-900 dark:text-white">{tr('Latest feeding logs')}</h3>
</div>
<BaseButton color="whiteDark" label="Refresh" onClick={fetchWorkspace} small />
</div>
{loading ? (
<div className="rounded-2xl bg-slate-50 p-6 text-sm text-slate-500">{tr('Loading latest records')}</div>
) : logs.length === 0 ? (
<div className="rounded-2xl border border-dashed border-slate-300 bg-slate-50 p-8 text-center">
<BaseIcon path={mdiClipboardTextClock} size="40" className="mx-auto text-slate-400" />
<p className="mt-3 font-semibold text-slate-900">{tr('No feeding logs yet')}</p>
<p className="mt-1 text-sm text-slate-500">{tr('Use the quick input form to create the first daily operation record')}</p>
</div>
) : (
<div className="space-y-3">
{logs.map((log) => {
const isSelected = selectedLog?.id === log.id
const appetiteClass = statusStyles[log.appetite] || statusStyles.normal
return (
<button
key={log.id}
className={`w-full rounded-2xl border p-4 text-left transition hover:-translate-y-0.5 hover:shadow-md focus:outline-none focus:ring-2 focus:ring-teal-500/40 ${
isSelected ? 'border-teal-400 bg-teal-50/80' : 'border-slate-200 bg-white dark:border-dark-700 dark:bg-dark-900'
}`}
type="button"
onClick={() => setSelectedLog(log)}
>
<div className="flex items-start justify-between gap-3">
<div>
<p className="font-bold text-slate-900 dark:text-white">{log.batch?.batch_code || tr('Unassigned batch')}</p>
<p className="mt-1 text-sm text-slate-500">{formatDateTime(log.fed_at, locale, tr('Not scheduled'))} {tr(log.feeding_method || 'manual')}</p>
</div>
<span className={`rounded-full px-2.5 py-1 text-xs font-semibold capitalize ring-1 ${appetiteClass}`}>
{tr(log.appetite || 'normal')}
</span>
</div>
<div className="mt-4 grid grid-cols-2 gap-3 text-sm">
<div className="rounded-xl bg-slate-50 p-3 dark:bg-dark-800">
<span className="block text-xs uppercase tracking-wide text-slate-400">{tr('Quantity')}</span>
<strong>{formatQuantity(log.quantity_kg, locale)}</strong>
</div>
<div className="rounded-xl bg-slate-50 p-3 dark:bg-dark-800">
<span className="block text-xs uppercase tracking-wide text-slate-400">{tr('Feed')}</span>
<strong>{log.feed_product?.product_name || tr('Not specified')}</strong>
</div>
</div>
</button>
)
})}
</div>
)}
</CardBox>
<CardBox className="border-0 bg-slate-950 text-white shadow-lg ring-1 ring-slate-800">
<div className="mb-5 flex items-center justify-between gap-3">
<div>
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-cyan-300">{tr('Detail')}</p>
<h3 className="mt-1 text-2xl font-bold">{tr('Record snapshot')}</h3>
</div>
<span className="rounded-2xl bg-cyan-400/10 p-3 text-cyan-200 ring-1 ring-cyan-300/20">
<BaseIcon path={mdiWaterPercent} size="24" />
</span>
</div>
{selectedLog ? (
<div className="space-y-4">
<div className="rounded-2xl bg-white/10 p-4 ring-1 ring-white/10">
<p className="text-sm text-slate-300">{tr('Batch')}</p>
<p className="mt-1 text-2xl font-black">{selectedLog.batch?.batch_code || tr('Unassigned batch')}</p>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="rounded-2xl bg-white/10 p-4 ring-1 ring-white/10">
<p className="text-xs uppercase tracking-wide text-slate-400">{tr('Quantity')}</p>
<p className="mt-1 text-xl font-bold">{formatQuantity(selectedLog.quantity_kg, locale)}</p>
</div>
<div className="rounded-2xl bg-white/10 p-4 ring-1 ring-white/10">
<p className="text-xs uppercase tracking-wide text-slate-400">{tr('Appetite')}</p>
<p className="mt-1 text-xl font-bold capitalize">{tr(selectedLog.appetite || 'normal')}</p>
</div>
</div>
<div className="rounded-2xl bg-white/10 p-4 ring-1 ring-white/10">
<p className="text-xs uppercase tracking-wide text-slate-400">{tr('Recorded')}</p>
<p className="mt-1 font-semibold">{formatDateTime(selectedLog.fed_at, locale, tr('Not scheduled'))} {tr('by')} {getRecorder(selectedLog, tr('Team member'))}</p>
</div>
<div className="rounded-2xl bg-white/10 p-4 ring-1 ring-white/10">
<p className="text-xs uppercase tracking-wide text-slate-400">{tr('Notes')}</p>
<p className="mt-2 text-sm leading-6 text-slate-200">{selectedLog.notes || tr('No notes added for this operation')}</p>
</div>
<div className="flex flex-wrap gap-3 pt-2">
<BaseButton color="info" href={`/feeding_logs/${selectedLog.id}`} label="Open detail" />
<BaseButton color="whiteDark" href="/marketplace_listings/marketplace_listings-list" label="Marketplace" />
</div>
</div>
) : (
<div className="rounded-2xl border border-dashed border-white/20 p-8 text-center text-slate-300">
{tr('Select a feeding log to inspect its farm-ready details')}
</div>
)}
</CardBox>
</div>
</div>
<section className="mt-6 grid gap-4 md:grid-cols-3">
{[
{ icon: mdiFish, title: 'Batch context', text: 'Every record is tied to generated batch CRUD for traceability.' },
{ icon: mdiCalendarCheck, title: 'Daily rhythm', text: 'Fast input supports the staff workflow farmers repeat every shift.' },
{ icon: mdiStorefront, title: 'Marketplace ready', text: 'Operational records are one step away from harvest, listing, order, and transaction flows.' },
].map((item) => (
<div key={item.title} className="rounded-2xl bg-white p-5 shadow-sm ring-1 ring-slate-200 dark:bg-dark-900 dark:ring-dark-700">
<BaseIcon path={item.icon} size="28" className="text-teal-600" />
<h4 className="mt-3 font-bold text-slate-900 dark:text-white">{tr(item.title)}</h4>
<p className="mt-1 text-sm leading-6 text-slate-500">{tr(item.text)}</p>
</div>
))}
</section>
</SectionMain>
</>
)
}
FarmOpsPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated permission="READ_FEEDING_LOGS">{page}</LayoutAuthenticated>
}
export default FarmOpsPage

View File

@ -1,166 +1,138 @@
import React from 'react'
import type { ReactElement } from 'react'
import Head from 'next/head'
import Link from 'next/link'
import BaseButton from '../components/BaseButton'
import CardBox from '../components/CardBox'
import LayoutGuest from '../layouts/Guest'
import { getPageTitle } from '../config'
import React, { useEffect, useState } from 'react'; const metrics = [
import type { ReactElement } from 'react'; { value: '12+', label: 'aquaculture entities' },
import Head from 'next/head'; { value: '4', label: 'role-focused workspaces' },
import Link from 'next/link'; { value: 'CSV', label: 'import / export ready' },
import BaseButton from '../components/BaseButton'; ]
import CardBox from '../components/CardBox';
import SectionFullScreen from '../components/SectionFullScreen';
import LayoutGuest from '../layouts/Guest';
import BaseDivider from '../components/BaseDivider';
import BaseButtons from '../components/BaseButtons';
import { getPageTitle } from '../config';
import { useAppSelector } from '../stores/hooks';
import CardBoxComponentTitle from "../components/CardBoxComponentTitle";
import { getPexelsImage, getPexelsVideo } from '../helpers/pexels';
const workflows = [
'Ponds, species, batches, feeding, water quality, health, and harvests',
'Marketplace listings, buyer orders, payment transactions, and shipment statuses',
'Investor visibility, audit logs, REST API, webhooks, and email notifications',
]
export default function Starter() { export default function Starter() {
const [illustrationImage, setIllustrationImage] = useState({
src: undefined,
photographer: undefined,
photographer_url: undefined,
})
const [illustrationVideo, setIllustrationVideo] = useState({video_files: []})
const [contentType, setContentType] = useState('image');
const [contentPosition, setContentPosition] = useState('background');
const textColor = useAppSelector((state) => state.style.linkColor);
const title = 'Aquaculture Ops CRUD'
// Fetch Pexels image/video
useEffect(() => {
async function fetchData() {
const image = await getPexelsImage();
const video = await getPexelsVideo();
setIllustrationImage(image);
setIllustrationVideo(video);
}
fetchData();
}, []);
const imageBlock = (image) => (
<div
className='hidden md:flex flex-col justify-end relative flex-grow-0 flex-shrink-0 w-1/3'
style={{
backgroundImage: `${
image
? `url(${image?.src?.original})`
: 'linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5))'
}`,
backgroundSize: 'cover',
backgroundPosition: 'left center',
backgroundRepeat: 'no-repeat',
}}
>
<div className='flex justify-center w-full bg-blue-300/20'>
<a
className='text-[8px]'
href={image?.photographer_url}
target='_blank'
rel='noreferrer'
>
Photo by {image?.photographer} on Pexels
</a>
</div>
</div>
);
const videoBlock = (video) => {
if (video?.video_files?.length > 0) {
return ( return (
<div className='hidden md:flex flex-col justify-end relative flex-grow-0 flex-shrink-0 w-1/3'> <div className="min-h-screen bg-[#f6fbf9] text-slate-900">
<video
className='absolute top-0 left-0 w-full h-full object-cover'
autoPlay
loop
muted
>
<source src={video?.video_files[0]?.link} type='video/mp4'/>
Your browser does not support the video tag.
</video>
<div className='flex justify-center w-full bg-blue-300/20 z-10'>
<a
className='text-[8px]'
href={video?.user?.url}
target='_blank'
rel='noreferrer'
>
Video by {video.user.name} on Pexels
</a>
</div>
</div>)
}
};
return (
<div
style={
contentPosition === 'background'
? {
backgroundImage: `${
illustrationImage
? `url(${illustrationImage.src?.original})`
: 'linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5))'
}`,
backgroundSize: 'cover',
backgroundPosition: 'left center',
backgroundRepeat: 'no-repeat',
}
: {}
}
>
<Head> <Head>
<title>{getPageTitle('Starter Page')}</title> <title>{getPageTitle('Aquaculture Ops')}</title>
<meta
name="description"
content="Modern multi-tenant aquaculture operations, marketplace, and investor visibility SaaS."
/>
</Head> </Head>
<SectionFullScreen bg='violet'> <header className="sticky top-0 z-20 border-b border-teal-900/10 bg-white/85 backdrop-blur-xl">
<div <div className="mx-auto flex max-w-7xl items-center justify-between px-6 py-4">
className={`flex ${ <Link href="/" className="flex items-center gap-3 font-black tracking-tight">
contentPosition === 'right' ? 'flex-row-reverse' : 'flex-row' <span className="grid h-10 w-10 place-items-center rounded-2xl bg-teal-700 text-white shadow-lg shadow-teal-700/20">
} min-h-screen w-full`} AQ
> </span>
{contentType === 'image' && contentPosition !== 'background' <span>Aquaculture Ops</span>
? imageBlock(illustrationImage) </Link>
: null} <nav className="flex items-center gap-3 text-sm font-semibold">
{contentType === 'video' && contentPosition !== 'background' <Link className="hidden text-slate-600 transition hover:text-teal-700 sm:inline" href="/api-docs">
? videoBlock(illustrationVideo) REST API
: null} </Link>
<div className='flex items-center justify-center flex-col space-y-4 w-full lg:w-full'> <Link className="hidden text-slate-600 transition hover:text-teal-700 sm:inline" href="/farm-ops">
<CardBox className='w-full md:w-3/5 lg:w-2/3'> Farm Ops
<CardBoxComponentTitle title="Welcome to your Aquaculture Ops CRUD app!"/> </Link>
<BaseButton href="/login" label="Login" color="whiteDark" />
</nav>
</div>
</header>
<div className="space-y-3"> <main>
<p className='text-center text-gray-500'>This is a React.js/Node.js app generated by the <a className={`${textColor}`} href="https://flatlogic.com/generator">Flatlogic Web App Generator</a></p> <section className="relative overflow-hidden">
<p className='text-center text-gray-500'>For guides and documentation please check <div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,_rgba(20,184,166,0.22),_transparent_34%),radial-gradient(circle_at_85%_20%,_rgba(14,165,233,0.18),_transparent_30%)]" />
your local README.md and the <a className={`${textColor}`} href="https://flatlogic.com/documentation">Flatlogic documentation</a></p> <div className="relative mx-auto grid min-h-[calc(100vh-73px)] max-w-7xl gap-10 px-6 py-16 lg:grid-cols-[1.08fr_0.92fr] lg:items-center lg:py-24">
<div>
<p className="mb-5 inline-flex rounded-full bg-teal-100 px-4 py-2 text-xs font-black uppercase tracking-[0.24em] text-teal-800 ring-1 ring-teal-200">
Multi-tenant farm operations + marketplace
</p>
<h1 className="max-w-4xl text-5xl font-black leading-[0.95] tracking-tight text-slate-950 md:text-7xl">
Run smarter fish farms from pond to paid order.
</h1>
<p className="mt-6 max-w-2xl text-lg leading-8 text-slate-600">
A clean, data-first SaaS workspace for farmers, operators, buyers, investors, and admins built around daily records, fulfillment statuses, auditability, and role-based access.
</p>
<div className="mt-8 flex flex-wrap gap-3">
<BaseButton href="/farm-ops" label="Open Farm Ops workflow" color="info" roundedFull />
<BaseButton href="/login" label="Admin login" color="whiteDark" roundedFull />
</div>
<div className="mt-10 grid max-w-2xl grid-cols-3 gap-3">
{metrics.map((metric) => (
<div key={metric.label} className="rounded-3xl bg-white/80 p-5 shadow-sm ring-1 ring-slate-200 backdrop-blur">
<div className="text-3xl font-black text-teal-700">{metric.value}</div>
<div className="mt-1 text-xs font-semibold uppercase tracking-wide text-slate-500">{metric.label}</div>
</div>
))}
</div>
</div> </div>
<BaseButtons> <CardBox className="border-0 bg-slate-950 text-white shadow-2xl shadow-teal-900/20 ring-1 ring-slate-800">
<BaseButton <div className="rounded-3xl bg-gradient-to-br from-teal-400/20 via-sky-400/10 to-transparent p-5 ring-1 ring-white/10">
href='/login' <div className="flex items-center justify-between gap-4">
label='Login' <div>
color='info' <p className="text-sm text-cyan-200">Todays command center</p>
className='w-full' <h2 className="mt-1 text-3xl font-black">Feed Observe Sell</h2>
/> </div>
<span className="rounded-full bg-emerald-400/20 px-3 py-1 text-xs font-bold text-emerald-200 ring-1 ring-emerald-300/20">
Live MVP slice
</span>
</div>
</BaseButtons> <div className="mt-6 space-y-3">
{workflows.map((workflow, index) => (
<div key={workflow} className="flex gap-4 rounded-2xl bg-white/10 p-4 ring-1 ring-white/10">
<span className="grid h-8 w-8 shrink-0 place-items-center rounded-full bg-cyan-300 text-sm font-black text-slate-950">
{index + 1}
</span>
<p className="text-sm leading-6 text-slate-200">{workflow}</p>
</div>
))}
</div>
<div className="mt-6 rounded-2xl bg-white p-4 text-slate-900">
<div className="flex items-center justify-between">
<div>
<p className="text-xs font-bold uppercase tracking-[0.2em] text-teal-700">First workflow</p>
<p className="mt-1 font-black">Quick feeding log with confirmation, latest list, and detail view.</p>
</div>
<BaseButton href="/farm-ops" label="Launch" color="info" small />
</div>
</div>
</div>
</CardBox> </CardBox>
</div> </div>
</div> </section>
</SectionFullScreen> </main>
<div className='bg-black text-white flex flex-col text-center justify-center md:flex-row'>
<p className='py-6 text-sm'>© 2026 <span>{title}</span>. All rights reserved</p> <footer className="border-t border-teal-900/10 bg-white px-6 py-6">
<Link className='py-6 ml-4 text-sm' href='/privacy-policy/'> <div className="mx-auto flex max-w-7xl flex-col justify-between gap-3 text-sm text-slate-500 md:flex-row">
<p>© 2026 Aquaculture Ops. Built for modern, multi-tenant farming teams.</p>
<div className="flex gap-4">
<Link className="hover:text-teal-700" href="/privacy-policy/">
Privacy Policy Privacy Policy
</Link> </Link>
<Link className="hover:text-teal-700" href="/login">
Admin interface
</Link>
</div> </div>
</div> </div>
); </footer>
</div>
)
} }
Starter.getLayout = function getLayout(page: ReactElement) { Starter.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>; return <LayoutGuest>{page}</LayoutGuest>
}; }

View File

@ -21,8 +21,10 @@ import { useAppDispatch, useAppSelector } from '../stores/hooks';
import Link from 'next/link'; import Link from 'next/link';
import {toast, ToastContainer} from "react-toastify"; import {toast, ToastContainer} from "react-toastify";
import { getPexelsImage, getPexelsVideo } from '../helpers/pexels' import { getPexelsImage, getPexelsVideo } from '../helpers/pexels'
import { useTranslation } from 'react-i18next'
export default function Login() { export default function Login() {
const { t } = useTranslation('common')
const router = useRouter(); const router = useRouter();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const textColor = useAppSelector((state) => state.style.linkColor); const textColor = useAppSelector((state) => state.style.linkColor);
@ -44,7 +46,7 @@ export default function Login() {
password: '60277297', password: '60277297',
remember: true }) remember: true })
const title = 'Aquaculture Ops CRUD' const title = t('app.title')
// Fetch Pexels image/video // Fetch Pexels image/video
useEffect( () => { useEffect( () => {
@ -109,8 +111,7 @@ export default function Login() {
backgroundRepeat: 'no-repeat', backgroundRepeat: 'no-repeat',
}}> }}>
<div className="flex justify-center w-full bg-blue-300/20"> <div className="flex justify-center w-full bg-blue-300/20">
<a className="text-[8px]" href={image?.photographer_url} target="_blank" rel="noreferrer">Photo <a className="text-[8px]" href={image?.photographer_url} target="_blank" rel="noreferrer">{t('pages.login.pexels.photoCredit', { photographer: image?.photographer })}</a>
by {image?.photographer} on Pexels</a>
</div> </div>
</div> </div>
) )
@ -126,7 +127,7 @@ export default function Login() {
muted muted
> >
<source src={video.video_files[0]?.link} type='video/mp4'/> <source src={video.video_files[0]?.link} type='video/mp4'/>
Your browser does not support the video tag. {t('pages.login.pexels.videoUnsupported')}
</video> </video>
<div className='flex justify-center w-full bg-blue-300/20 z-10'> <div className='flex justify-center w-full bg-blue-300/20 z-10'>
<a <a
@ -135,7 +136,7 @@ export default function Login() {
target='_blank' target='_blank'
rel='noreferrer' rel='noreferrer'
> >
Video by {video.user.name} on Pexels {t('pages.login.pexels.videoCredit', { name: video.user.name })}
</a> </a>
</div> </div>
</div>) </div>)
@ -154,7 +155,7 @@ export default function Login() {
backgroundRepeat: 'no-repeat', backgroundRepeat: 'no-repeat',
} : {}}> } : {}}>
<Head> <Head>
<title>{getPageTitle('Login')}</title> <title>{getPageTitle(t('pages.login.pageTitle'))}</title>
</Head> </Head>
<SectionFullScreen bg='violet'> <SectionFullScreen bg='violet'>
@ -239,7 +240,7 @@ export default function Login() {
</FormCheckRadio> </FormCheckRadio>
<Link className={`${textColor} text-blue-600`} href={'/forgot'}> <Link className={`${textColor} text-blue-600`} href={'/forgot'}>
Forgot password? {t('pages.login.form.forgotPassword')}
</Link> </Link>
</div> </div>
@ -256,9 +257,9 @@ export default function Login() {
</BaseButtons> </BaseButtons>
<br /> <br />
<p className={'text-center'}> <p className={'text-center'}>
Dont have an account yet?{' '} {t('pages.login.form.noAccountYet')}{' '}
<Link className={`${textColor}`} href={'/register'}> <Link className={`${textColor}`} href={'/register'}>
New Account {t('pages.login.form.newAccount')}
</Link> </Link>
</p> </p>
</Form> </Form>
@ -268,9 +269,9 @@ export default function Login() {
</div> </div>
</SectionFullScreen> </SectionFullScreen>
<div className='bg-black text-white flex flex-col text-center justify-center md:flex-row'> <div className='bg-black text-white flex flex-col text-center justify-center md:flex-row'>
<p className='py-6 text-sm'>© 2026 <span>{title}</span>. © All rights reserved</p> <p className='py-6 text-sm'>{t('pages.login.footer.copyright', { year: 2026, title })}</p>
<Link className='py-6 ml-4 text-sm' href='/privacy-policy/'> <Link className='py-6 ml-4 text-sm' href='/privacy-policy/'>
Privacy Policy {t('pages.login.footer.privacy')}
</Link> </Link>
</div> </div>
<ToastContainer /> <ToastContainer />

View File

@ -1,9 +1,7 @@
import React, { ReactElement, useEffect, useState } from 'react'; import React, { ReactElement, useEffect, useState } from 'react';
import Head from 'next/head'; import Head from 'next/head';
import 'react-datepicker/dist/react-datepicker.css'; import 'react-datepicker/dist/react-datepicker.css';
import { useAppDispatch } from '../stores/hooks'; import { useAppDispatch, useAppSelector } from '../stores/hooks';
import { useAppSelector } from '../stores/hooks';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import LayoutAuthenticated from '../layouts/Authenticated'; import LayoutAuthenticated from '../layouts/Authenticated';