Compare commits

..

1043 Commits

Author SHA1 Message Date
Giovanni Gabriel Septriadi fce4d52214 Merge branch 'fix/laying-transition-logic-removal' into 'rc/00'
Fix/laying transition logic removal

See merge request mbugroup/lti-web-client!507
2026-06-05 02:41:10 +00:00
Giovanni Gabriel Septriadi e2354b5ea7 Merge branch 'feat/enable-edit-chick-in-date' into 'rc/00'
feat: add inline edit for chick-in date in chickin logs

See merge request mbugroup/lti-web-client!503
2026-06-04 16:53:13 +00:00
Giovanni Gabriel Septriadi 8f88677191 Merge branch 'feat/marketing-filter-range-date' into 'rc/00'
feat: add date range, filter by, and warehouse filter to marketing table

See merge request mbugroup/lti-web-client!504
2026-06-04 16:52:49 +00:00
ValdiANS 4151829cb8 fix: disabled deliver item button if is submitting and set the is loading prop 2026-06-03 14:24:39 +07:00
ValdiANS f167916a21 fix: replace throw error with axios error handling in SalesOrderService and MarketingExportService
All catch blocks in singleApproval, bulkApprovals (both classes), and
delivery now return error.response?.data for axios errors and undefined
otherwise, consistent with the BaseApiService pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 14:20:43 +07:00
ValdiANS 97acc17ca5 feat: add inline edit for chick-in date in chickin logs
- Add updateChickinDate method to ChickinService (PATCH /production/chickins/chick-in-date)
- Add pencil icon button next to each chickin date in ChickLogsView
- Clicking the icon toggles an inline DateInput with Simpan/Batal buttons
- Save button is disabled and shows loading state while request is in flight

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-03 14:05:06 +07:00
ValdiANS e73af7e252 feat: add date range, filter by, and warehouse filter to marketing table
- Add start_date and end_date range inputs to the marketing filter modal
  with validation that prevents end date from being earlier than start date
- Add 'Filter Berdasarkan' single-select radio (so_date / created_at)
  to let users choose which date field the range applies to
- Add single-select Gudang (warehouse) filter backed by WarehouseApi,
  serialized as warehouse_id query param
- Wire all three new filters into useTableFilter (paramMap, persist,
  excludeKeysFromUrl for label-only fields) and propagate through
  filterSubmitHandler, filterResetHandler, and marketingFilterInitialValues
  so filter state survives page refreshes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 13:22:01 +07:00
ValdiANS 7b4bd7605b fix: remove transition restriction for recording 2026-06-02 09:45:19 +07:00
Rivaldi A N S 9bd646294b Merge branch 'fix/laying-transition-logic-removal' into 'development'
[FIX/FE] Laying Transition Restrict Logic Removal

See merge request mbugroup/lti-web-client!499
2026-05-30 02:19:24 +00:00
ValdiANS 366260608f fix: remove transition restrict logic 2026-05-30 09:13:56 +07:00
Giovanni Gabriel Septriadi a1cb401a1c Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!498
2026-05-29 16:32:00 +00:00
Rivaldi A N S 3f1c1b62e2 Merge branch 'feat/purchase-po-pr-copy-paste' into 'development'
[FEAT/FE] Purchase PO & PR Number Copy Button

See merge request mbugroup/lti-web-client!497
2026-05-29 10:13:13 +00:00
ValdiANS 5c9fa12347 feat: add copy button for PR and PO number 2026-05-29 17:11:42 +07:00
Giovanni Gabriel Septriadi 2ea6e1a5a5 Merge branch 'development' into 'production'
feat: add server-side Excel export to PurchasesPerSupplierTab

See merge request mbugroup/lti-web-client!496
2026-05-25 08:16:37 +00:00
Rivaldi A N S aa935b8851 Merge branch 'feat/export-balance-monitoring' into 'development'
[FEAT/FE] Export Balance Monitoring

See merge request mbugroup/lti-web-client!495
2026-05-25 07:25:07 +00:00
ValdiANS b8419a3f69 feat: add Excel export to BalanceMonitoringTab
Add exportBalanceMonitoringToExcel to FinanceApiService (server-side
blob download hitting reports/balance-monitoring?export=excel). Wire it
into BalanceMonitoringTab via a Dropdown export button in the tab
actions. Wrap the handler in useCallback to prevent an infinite
setTabActions loop caused by a new function reference on every render.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 14:14:40 +07:00
Rivaldi A N S eaf70ead70 Merge branch 'feat/export-report-purchases-per-supplier' into 'development'
[FEAT/FE] Export Report Purchases Per Supplier

See merge request mbugroup/lti-web-client!494
2026-05-25 04:33:09 +00:00
ValdiANS 7e6f250864 feat: add server-side Excel export to PurchasesPerSupplierTab
Add exportToExcelSupplierPerSheet and exportToExcelGeneral methods to
LogisticApiService, hitting the existing purchase-supplier endpoint with
export=excel / export=excel-all query params and downloading the server
blob response. Replace the client-side Excel generation in
PurchasesPerSupplierTab with calls to these two service methods, and
split the single Export to Excel button into Export to Excel - Supplier
Per Sheet and Export to Excel - General.
2026-05-25 11:28:41 +07:00
Giovanni Gabriel Septriadi d7a98a77ea Merge branch 'development' into 'production'
refactor: optimize BalanceMonitoringTab with useTableFilter persistence pattern

See merge request mbugroup/lti-web-client!493
2026-05-25 04:04:15 +00:00
Rivaldi A N S 13eb0594a8 Merge branch 'hotfix/transfer-to-laying' into 'development'
[HOTFIX/FE] Transfer to Laying

See merge request mbugroup/lti-web-client!492
2026-05-25 03:39:13 +00:00
ValdiANS 22b3350e4a fix: set flock source and destination raw data accordingly 2026-05-25 10:37:41 +07:00
Rivaldi A N S 55424b272f Merge branch 'fix/depreciation-report' into 'development'
[FIX/FE] Depreciation Report

See merge request mbugroup/lti-web-client!491
2026-05-22 04:17:04 +00:00
ValdiANS 05138dbb6f feat: implement table filter state persist 2026-05-22 11:14:16 +07:00
ValdiANS b5a0614218 feat: implement url query param tab navigation 2026-05-22 11:13:52 +07:00
Rivaldi A N S 7ec46ffa8c Merge branch 'fix/transfer-stock' into 'development'
[FIX/FE] Transfer Stock

See merge request mbugroup/lti-web-client!490
2026-05-22 03:19:56 +00:00
ValdiANS 07dd2d26be fix: cache product stock 2026-05-22 10:17:04 +07:00
Rivaldi A N S 9a56bf732a Merge branch 'fix/purchase-filter' into 'development'
[FIX/FE] Purchase Filter

See merge request mbugroup/lti-web-client!489
2026-05-21 07:46:44 +00:00
ValdiANS 585918cc28 fix: update purchase type 2026-05-21 14:44:28 +07:00
ValdiANS 80e0bd5a8e fix: update table columns 2026-05-21 14:44:20 +07:00
ValdiANS a4e5116bef feat: add start_date, end_date, and filter_by input 2026-05-21 14:44:07 +07:00
ValdiANS 027668a1bf feat: add export to excel feature 2026-05-21 14:43:08 +07:00
Rivaldi A N S 7e1fab9a69 Merge branch 'feat/balance-monitoring-report' into 'development'
[FEAT/FE] Balance Monitoring Report

See merge request mbugroup/lti-web-client!488
2026-05-20 09:41:51 +00:00
ValdiANS ef56f87e45 feat: create report finance layout file 2026-05-20 16:35:43 +07:00
ValdiANS c4827bb810 feat: implement Query Param Tab Navigation 2026-05-20 16:35:26 +07:00
ValdiANS 9abb8b0b58 feat: add hide field in TabItem type 2026-05-20 16:34:53 +07:00
ValdiANS 8d014a8fea fix: adjust BalanceMonitoringRow type 2026-05-20 16:14:37 +07:00
ValdiANS 3d37fb2ecb fix: remove dummy data 2026-05-20 16:10:36 +07:00
ValdiANS d60877d391 refactor: optimize DebtSupplierTab with useTableFilter persistence pattern
Replace filterParams/currentPage/pageSize state with useTableFilter (persist:true),
switch SWR to httpClientFetcher with explicit type, store OptionType[] directly for
suppliers/filterBy, add formikResetHandler using resetFilter(), remove TabActions
component anti-pattern and handleFilterModalOpenRef, pass filterModal.openModal directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 16:10:19 +07:00
ValdiANS b3b60018bb refactor: optimize CustomerPaymentTab with useTableFilter persistence pattern
Replace filterParams/currentPage/pageSize state with useTableFilter (persist:true),
switch SWR to httpClientFetcher with explicit type, store OptionType[] directly for
customers/filterBy, add formikResetHandler using resetFilter(), remove enableReinitialize
and handleFilterModalOpenRef, pass filterModal.openModal directly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 16:10:10 +07:00
ValdiANS c98a51326f refactor: optimize BalanceMonitoringTab with useTableFilter persistence pattern
Replace single-select customerFilter/salesFilter with OptionType[] multi-select
(customers, salesPersons, filterBy), switch SWR to httpClientFetcher with explicit
type, remove PDF export, enableReinitialize, useRef modal hack, useMemo on data/meta,
and useCallback on trivial handlers. Add formikResetHandler using resetFilter().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-20 16:10:01 +07:00
ValdiANS 7437e2e584 fix: update pattern context 2026-05-20 16:08:19 +07:00
ValdiANS ac6f6ecf78 Merge branch 'development' into feat/balance-monitoring-report 2026-05-20 11:21:39 +07:00
Rivaldi A N S 7f961b2f8b Merge branch 'feat/debt-supplier-general-export' into 'development'
[FEAT/FE] Debt Supplier General Export

See merge request mbugroup/lti-web-client!487
2026-05-20 04:14:59 +00:00
ValdiANS a8c02243a4 feat: implement export general and server-side export 2026-05-20 11:13:50 +07:00
Rivaldi A N S 82dca3b57e Merge branch 'feat/debt-supplier-general-export' into 'development'
[FEAT/FE] Debt Supplier General Export

See merge request mbugroup/lti-web-client!486
2026-05-19 10:33:48 +00:00
ValdiANS 94d623d793 feat: update gitignore 2026-05-19 17:31:18 +07:00
ValdiANS f76b5b981c feat: create balance-monitoring type 2026-05-19 17:31:00 +07:00
ValdiANS 8df5af0124 feat: create getBalanceMonitoringReport method 2026-05-19 17:30:38 +07:00
ValdiANS 3c175d4586 feat: create BalanceMonitoringTab component 2026-05-19 17:30:28 +07:00
ValdiANS 9350a6bd3e fix: add Monitoring Saldo tab 2026-05-19 17:30:13 +07:00
ValdiANS 6668c7b1f9 feat: update .gitignore 2026-05-19 16:07:08 +07:00
ValdiANS ce4f50c92a feat: create Export to Excel - General button 2026-05-19 16:06:54 +07:00
ValdiANS 146192a5b3 feat: create exportToExcelGeneral method 2026-05-19 16:06:41 +07:00
Rivaldi A N S 27c24e7c82 Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist

See merge request mbugroup/lti-web-client!485
2026-05-19 07:47:51 +00:00
ValdiANS a99a399f09 fix: show kandang label even if its not loaded yet in kandang options 2026-05-19 14:44:12 +07:00
Giovanni Gabriel Septriadi a314a62f1f Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!484
2026-05-19 06:48:45 +00:00
Rivaldi A N S 37d0041a4f Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist

See merge request mbugroup/lti-web-client!483
2026-05-19 05:12:37 +00:00
ValdiANS 3647f1a1ea fix: make empty kandang end date required 2026-05-19 12:11:24 +07:00
ValdiANS 7b5049165a fix: add hasError props 2026-05-19 12:11:07 +07:00
Rivaldi A N S 3839b46edc Merge branch 'feat/server-side-sorting' into 'development'
[FEAT/FE] Server Side Sorting

See merge request mbugroup/lti-web-client!482
2026-05-19 04:54:47 +00:00
ValdiANS b7f2bca931 feat: add rtk filters.toml 2026-05-19 11:51:59 +07:00
ValdiANS 802bf77bc5 feat: add rtk instructions 2026-05-19 11:51:27 +07:00
ValdiANS fd7b49ab93 feat: implement server-side sorting in report expense 2026-05-19 11:51:17 +07:00
Rivaldi A N S 456070491f Merge branch 'fix/marketing' into 'development'
[FIX/FE] Marketing

See merge request mbugroup/lti-web-client!481
2026-05-18 07:43:05 +00:00
ValdiANS c12beca4d7 fix: recalculate qty if product change 2026-05-18 14:26:52 +07:00
ValdiANS 910981645b fix: remove unnecessary code 2026-05-18 14:25:19 +07:00
ValdiANS 82b5429d02 fix: update DeliveryOrderSchema validation, make all delivery_order should valid instead of some 2026-05-18 14:24:59 +07:00
ValdiANS 6c6f739fc0 fix: remove onAfterSubmit callback in useFormikErrorList 2026-05-18 14:20:30 +07:00
ValdiANS 001dafecb7 fix: adjust copywriting for approve button based on approval step number 2026-05-18 14:18:35 +07:00
Rivaldi A N S 4bb3ada779 Merge branch 'feat/server-side-sorting' into 'development'
[FEAT/FE] Server-Side Sorting

See merge request mbugroup/lti-web-client!480
2026-05-18 04:38:58 +00:00
ValdiANS 0b63dcb532 feat: implement server-side sorting in FinanceTable 2026-05-18 11:37:40 +07:00
Rivaldi A N S 23dd220b2f Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist

See merge request mbugroup/lti-web-client!479
2026-05-18 03:46:22 +00:00
ValdiANS 770c293257 fix: adjust empty_kandang type in BaseDailyChecklist 2026-05-18 10:25:27 +07:00
ValdiANS 3374ab4779 fix: show Tanggal Selesai Kandang Kosong if category is empty kandang 2026-05-18 10:25:10 +07:00
ValdiANS 7a668c0cf9 fix: adjust empty kandang condition check 2026-05-18 10:20:52 +07:00
Rivaldi A N S 14151f6f5a Merge branch 'feat/add-bank-name-in-supplier-customer' into 'development'
[FEAT/FE] Bank Name in Supplier & Customer

See merge request mbugroup/lti-web-client!478
2026-05-13 09:26:25 +00:00
ValdiANS 0275e66eda feat: add bank_name 2026-05-13 16:25:35 +07:00
ValdiANS 9bc5842493 feat: add bank name input 2026-05-13 16:25:25 +07:00
ValdiANS 4cad8aba64 feat: add bank name column 2026-05-13 16:25:13 +07:00
Rivaldi A N S 7b5af69dd1 Merge branch 'feat/server-side-sorting-purchasing-expense' into 'development'
[FEAT/FE] Server-Side Sorting Purchasing & Expense

See merge request mbugroup/lti-web-client!477
2026-05-13 08:49:54 +00:00
ValdiANS 2e179b74ba fix: add sort for PO number 2026-05-13 15:29:19 +07:00
ValdiANS fe2a2dfb43 fix: add loading state to approve modal 2026-05-13 15:29:03 +07:00
ValdiANS 910a36857e fix: pass the rest of secondaryButton props 2026-05-13 15:26:30 +07:00
ValdiANS 58ddd9b991 fix: set sortDescFirst false 2026-05-13 15:26:10 +07:00
Rivaldi A N S bb9c6ab969 Merge branch 'fix/marketing' into 'development'
[FIX/FE] Marketing

See merge request mbugroup/lti-web-client!476
2026-05-13 06:55:55 +00:00
ValdiANS ddffdd1b27 fix: adjust marketing_type default value 2026-05-13 13:46:59 +07:00
Rivaldi A N S f097620c4b Merge branch 'feat/server-side-sorting-purchasing-expense' into 'development'
[FEAT/FE] Server-Side Sorting Purchasing & Expense

See merge request mbugroup/lti-web-client!475
2026-05-13 04:18:52 +00:00
ValdiANS 280d790f0c fix: add created_at column 2026-05-13 10:51:46 +07:00
ValdiANS 3a2e74b559 feat: implement server-side sorting 2026-05-13 10:51:35 +07:00
Giovanni Gabriel Septriadi 2bf5f36a77 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!474
2026-05-12 09:31:27 +00:00
Giovanni Gabriel Septriadi b9ef0fa338 Merge branch 'fix/pay' into 'development'
fix bop

See merge request mbugroup/lti-web-client!473
2026-05-12 08:54:42 +00:00
MacBook Air M1 6d8cdeffe9 fix bop 2026-05-12 15:53:16 +07:00
Rivaldi A N S 2e36247a1a Merge branch 'fix/product-stock-optimization' into 'development'
[FIX/FE] Product Stock Optimization

See merge request mbugroup/lti-web-client!472
2026-05-12 07:41:58 +00:00
ValdiANS 37cd990b4f fix: add empty_kandang to CATEGORY_LABELS 2026-05-12 14:38:50 +07:00
ValdiANS bdc7ac4d22 feat: only fetch when user scroll to the component 2026-05-12 14:38:19 +07:00
ValdiANS b6c2f36dd1 feat: implement filter for stock log table 2026-05-12 14:36:31 +07:00
ValdiANS 10cc4bee72 feat: create StockLogFilterModal component 2026-05-12 14:36:13 +07:00
Rivaldi A N S ff6bcf019b Merge branch 'fix/transfer-to-laying' into 'development'
[FIX/FE] Transfer To Laying

See merge request mbugroup/lti-web-client!471
2026-05-12 05:04:56 +00:00
ValdiANS bb0508d456 fix: adjust BaseTransferToLaying.sources.product_warehouse type 2026-05-12 12:03:19 +07:00
ValdiANS d6dd5e6709 fix: adjust remaining chicken UI layout 2026-05-12 12:02:51 +07:00
Rivaldi A N S 3c75a7631a Merge branch 'feat/expense-enhancement' into 'development'
[FEAT] Expense Enhancement

See merge request mbugroup/lti-web-client!470
2026-05-12 04:12:45 +00:00
ValdiANS e3d3e744b0 fix: add is_paid to BaseExpense 2026-05-12 11:09:40 +07:00
ValdiANS 5767a078d9 feat: implement paid off expense feature 2026-05-12 11:09:25 +07:00
ValdiANS 67c7e85ba8 fix: adjust swr key to fetch expense detail 2026-05-12 11:09:03 +07:00
ValdiANS c5a5582147 feat: create setExpensePaidOff method 2026-05-12 10:26:57 +07:00
Rivaldi A N S 46cb8a7d61 Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist

See merge request mbugroup/lti-web-client!469
2026-05-11 09:54:31 +00:00
ValdiANS 0189733dec fix: add week and excess_days to BaseRecording type 2026-05-11 16:51:30 +07:00
ValdiANS d0c3581f57 fix: use checklistId param instead of date, kandang_id, and category when redirecting for edit 2026-05-11 16:51:14 +07:00
ValdiANS e7569b7448 fix: hit API when user click Simpan Draft/Submit and and empty kandang end date 2026-05-11 16:50:44 +07:00
ValdiANS 69b998a61a fix: update footer styling 2026-05-11 16:47:47 +07:00
ValdiANS c50c110005 fix: show excess day 2026-05-11 16:47:33 +07:00
Giovanni Gabriel Septriadi 989e30fbed Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!468
2026-05-11 08:32:23 +00:00
Rivaldi A N S 3775bb6093 Merge branch 'feat/marketing-table-order' into 'development'
[FEAT/FE] Marketing Table Order

See merge request mbugroup/lti-web-client!467
2026-05-09 03:57:29 +00:00
ValdiANS 3dc64d01db chore: update server-side sorting pattern context 2026-05-09 10:56:39 +07:00
ValdiANS 2ed8ecbbb7 fix: pass manualSorting to Table 2026-05-09 10:55:57 +07:00
ValdiANS e5f6ef8a85 fix: show document name and use document path from the API response 2026-05-09 10:55:38 +07:00
Rivaldi A N S 7ff0891ad5 Merge branch 'feat/stock-log-export' into 'development'
[FEAT/FE] Stock Log Export

See merge request mbugroup/lti-web-client!466
2026-05-08 11:59:06 +00:00
ValdiANS a9a5098a21 fix: set default map for pageSize to limit 2026-05-08 18:58:25 +07:00
ValdiANS 7f9bb8e11d chore: remove unnecessary code 2026-05-08 18:58:13 +07:00
ValdiANS bef3f365bb feat: add stock log permission 2026-05-08 18:58:02 +07:00
ValdiANS a0e8c60082 chore: adjust styling 2026-05-08 18:57:37 +07:00
ValdiANS e7f378823c feat: implement export product stock log 2026-05-08 18:57:21 +07:00
Rivaldi A N S ba3cb98e2c Merge branch 'feat/marketing-table-order' into 'development'
[FEAT/FE] Marketing Table Order

See merge request mbugroup/lti-web-client!465
2026-05-08 09:30:39 +00:00
ValdiANS 7643645643 feat: implement server-side sorting 2026-05-08 16:25:51 +07:00
ValdiANS 3b1e7e3b03 feat: add server-side sorting pattern 2026-05-08 16:16:16 +07:00
Rivaldi A N S 725111dc0c Merge branch 'fix/recording' into 'development'
[FIX/FE] Recording Form

See merge request mbugroup/lti-web-client!464
2026-05-08 08:28:17 +00:00
ValdiANS 073d7eee03 chore: prettier format 2026-05-08 15:25:58 +07:00
ValdiANS cce5a8df43 fix: set stocks quantity to usage_amount + pending_qty 2026-05-08 15:25:48 +07:00
M1 AIR 978067ac6c Update env not slash 2026-05-07 15:08:33 +07:00
M1 AIR 6255367366 Update env 2026-05-07 14:15:17 +07:00
Rivaldi A N S af9cb8ec6b Merge branch 'fix/inventory-product' into 'development'
[FIX/FE] Inventory Product

See merge request mbugroup/lti-web-client!463
2026-05-06 03:53:42 +00:00
ValdiANS e0a1922ed4 fix: implement table filter 2026-05-06 10:31:00 +07:00
ValdiANS 4b5ad0dcab fix: show total item data 2026-05-06 10:23:22 +07:00
Rivaldi A N S ca62b31aa6 Merge branch 'fix/expense' into 'development'
[FIX/FE] Expense

See merge request mbugroup/lti-web-client!462
2026-05-06 03:03:10 +00:00
ValdiANS 4ec32c51b2 Merge branch 'fix/expense' of https://gitlab.com/mbugroup/lti-web-client into fix/expense 2026-05-06 10:02:04 +07:00
ValdiANS cdee616e18 fix: remove realization_date validation 2026-05-06 10:01:35 +07:00
ValdiANS 50378a2ee2 fix: remote realization_date validation 2026-05-06 09:49:13 +07:00
Rivaldi A N S ab093467c4 Merge branch 'fix/production' into 'development'
[FIX/FE] Production

See merge request mbugroup/lti-web-client!461
2026-05-05 09:46:25 +00:00
ValdiANS 79e41d8a6f fix: implement table persist state in recording filter 2026-05-05 16:10:57 +07:00
ValdiANS 35001ff422 fix: make depletion and egg optional 2026-05-05 16:10:44 +07:00
Adnan Zahir 40139cd636 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!456
2026-05-05 14:12:28 +07:00
Rivaldi A N S 7026619249 Merge branch 'fix/production' into 'development'
[FIX/FE] Production

See merge request mbugroup/lti-web-client!460
2026-05-04 09:25:33 +00:00
ValdiANS 3945142966 fix: add formikFlockSource to useEffect dependencies to set flock source raw data 2026-05-04 16:24:21 +07:00
ValdiANS b19099cea2 fix: takeout export button 2026-05-04 16:23:35 +07:00
Rivaldi A N S f65593de25 Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist

See merge request mbugroup/lti-web-client!459
2026-05-04 07:20:16 +00:00
ValdiANS a5f1a6ea75 fix: order select input options in ascending manner 2026-05-04 14:19:14 +07:00
ValdiANS 4e58f20ba3 fix: set timeout to 1 minute 2026-05-04 14:15:57 +07:00
Rivaldi A N S dc41d6ce73 Merge branch 'fix/system' into 'development'
[FIX][FE]: adjust get detail recording

See merge request mbugroup/lti-web-client!458
2026-05-04 05:21:35 +00:00
MacBook Air M1 8869c9df2c adjust get detail recording 2026-05-04 12:20:20 +07:00
Rivaldi A N S f2b3f2b584 Merge branch 'fix/purchasing' into 'development'
[FIX/FE] Purchasing

See merge request mbugroup/lti-web-client!457
2026-05-04 03:18:07 +00:00
ValdiANS 31cea258a7 fix: adjust delete click handler 2026-05-04 09:48:46 +07:00
Rivaldi A N S 53d7439300 Merge branch 'fix/recording' into 'development'
[FIX/FE] Recording

See merge request mbugroup/lti-web-client!455
2026-05-02 10:06:00 +00:00
ValdiANS 28a1852de8 fix: adjust stock, depletion, and egg select input 2026-05-02 17:04:59 +07:00
Adnan Zahir 8c03f10043 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!454
2026-05-02 13:43:29 +07:00
Rivaldi A N S ff92073d19 Merge branch 'fix/persist-filter' into 'development'
[FIX/FE] Persist Filter

See merge request mbugroup/lti-web-client!453
2026-04-30 10:02:56 +00:00
ValdiANS 6ffc2c2806 fix: adjust date filter layout 2026-04-30 16:56:47 +07:00
ValdiANS 9e402e373c fix: adjust filter submit handler 2026-04-30 16:56:12 +07:00
Rivaldi A N S 2e4c19b714 Merge branch 'fix/finance' into 'development'
[FIX/FE] Finance

See merge request mbugroup/lti-web-client!452
2026-04-30 08:02:36 +00:00
ValdiANS 039c926e2d fix: implement table filter persist state 2026-04-30 15:01:21 +07:00
ValdiANS e52ba7b394 fix: search input value and change handler 2026-04-30 15:01:11 +07:00
Rivaldi A N S 90dc7c80f2 Merge branch 'fix/finance' into 'development'
[FIX/FE] Finance

See merge request mbugroup/lti-web-client!451
2026-04-30 04:40:54 +00:00
ValdiANS 15c883ca73 fix: add created at column 2026-04-30 11:40:16 +07:00
Rivaldi A N S 47f74b8842 Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist

See merge request mbugroup/lti-web-client!450
2026-04-30 04:20:13 +00:00
ValdiANS ef9009b304 fix: remove empty kandang date 2026-04-30 11:02:09 +07:00
Adnan Zahir 89a6e51b48 Merge branch 'development' into 'production'
Revert "fixing devops"

See merge request mbugroup/lti-web-client!449
2026-04-30 09:54:39 +07:00
M1 AIR ce25758a17 Revert "fixing devops"
This reverts commit 371b236e25.
2026-04-30 00:34:43 +07:00
M1 AIR 371b236e25 fixing devops 2026-04-30 00:21:44 +07:00
Rivaldi A N S a54dd1fa9e Merge branch 'fix/daily-marketing-export' into 'development'
[FIX/FE] Daily Marketing Export

See merge request mbugroup/lti-web-client!448
2026-04-29 08:56:11 +00:00
ValdiANS 31205a44f9 feat: add new context to CLAUDE.md 2026-04-29 15:55:22 +07:00
ValdiANS 3c9c55e049 fix: implement server-side export 2026-04-29 15:55:03 +07:00
Rivaldi A N S 7a4f93cf0c Merge branch 'fix/persist-filter' into 'development'
[FIX/FE] Persist Filter

See merge request mbugroup/lti-web-client!447
2026-04-29 08:13:19 +00:00
ValdiANS a738d58c37 feat: add new context to CLAUDE.md 2026-04-29 15:11:03 +07:00
ValdiANS 46daed8fc4 fix: persist table filter state in master data 2026-04-29 15:10:41 +07:00
ValdiANS 29347c24f4 fix: create TableFilterStateValue type 2026-04-29 15:10:25 +07:00
Adnan Zahir f6727dc4dc Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!446
2026-04-29 12:53:07 +07:00
Adnan Zahir a0f603b707 Merge branch 'feat/toggle-negative-usage' into 'development'
fix: missing useRef

See merge request mbugroup/lti-web-client!445
2026-04-29 12:18:21 +07:00
Adnan Zahir 631e3959cd fix: missing useRef 2026-04-29 12:15:02 +07:00
Adnan Zahir 2a340a26f9 Merge branch 'feat/toggle-negative-usage' into 'development'
fix: recording wont accept ovk

See merge request mbugroup/lti-web-client!444
2026-04-29 11:23:14 +07:00
Adnan Zahir e75246ff8d fix: recording wont accept ovk 2026-04-29 11:22:07 +07:00
Rivaldi A N S 64aee33452 Merge branch 'fix/project-flock-form' into 'development'
[FIX/FE] Project Flock Form

See merge request mbugroup/lti-web-client!443
2026-04-28 07:50:09 +00:00
ValdiANS 1851f0e12f fix: add periode to project flock form values 2026-04-28 14:34:19 +07:00
Adnan Zahir 8b3f44708d Merge branch 'feat/toggle-negative-usage' into 'development'
fix: show product options from master instead of warehouse of migration mode

See merge request mbugroup/lti-web-client!442
2026-04-28 13:57:04 +07:00
Adnan Zahir a5fd97a175 fix: show product options from master instead of warehouse of migration mode 2026-04-28 13:55:08 +07:00
Adnan Zahir 1284b22345 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!441
2026-04-28 13:43:32 +07:00
Adnan Zahir 2ee5d1f7bd Merge branch 'feat/toggle-negative-usage' into 'development'
feat: konfigurasi sistem toggle pemakaian pakan ovk negatif

See merge request mbugroup/lti-web-client!440
2026-04-28 11:23:28 +07:00
Adnan Zahir 6eb257705f feat: konfigurasi sistem toggle pemakaian pakan ovk negatif 2026-04-28 10:50:46 +07:00
Rivaldi A N S 9ea1d06972 Merge branch 'fix/project-flock-form' into 'development'
[FIX/FE] Project Flock Form

See merge request mbugroup/lti-web-client!439
2026-04-28 02:53:11 +00:00
ValdiANS ff8833b5b3 fix: adjust period change handler 2026-04-28 09:45:25 +07:00
Rivaldi A N S 2dd98fd7e3 Merge branch 'fix/project-flock-form' into 'development'
[FIX/FE] Project Flock Form

See merge request mbugroup/lti-web-client!438
2026-04-27 06:13:19 +00:00
ValdiANS 76fff98d9d fix: change NumberInput name from 'period' to 'periode' 2026-04-27 13:12:26 +07:00
Rivaldi A N S 18eeabd353 Merge branch 'fix/project-flock-form' into 'development'
[FIX/FE] Project Flock Form

See merge request mbugroup/lti-web-client!437
2026-04-27 05:04:26 +00:00
ValdiANS 06b5a97de3 chore: prettier format 2026-04-27 12:03:17 +07:00
ValdiANS 5cccc0b3c6 fix: set background color for shared image 2026-04-27 12:03:09 +07:00
ValdiANS 7ab9518a55 fix: change 'period' to 'periode' 2026-04-27 12:02:43 +07:00
Rivaldi A N S ac51229398 Merge branch 'fix/project-flock-form' into 'development'
[FIX/FE] Project Flock Form

See merge request mbugroup/lti-web-client!436
2026-04-27 04:02:09 +00:00
ValdiANS 5a2532a0fa Merge branch 'development' into fix/project-flock-form 2026-04-27 10:58:44 +07:00
ValdiANS f9d2a875e2 chore: prettier format 2026-04-27 10:49:07 +07:00
ValdiANS 6cf8e463c6 feat: create CLAUDE.md 2026-04-27 10:48:56 +07:00
ValdiANS 4206408db1 fix: enable custom period 2026-04-27 10:48:42 +07:00
ValdiANS ff2ed8757f fix: set fallback timeout to 30s 2026-04-27 10:43:30 +07:00
Adnan Zahir f73ea182ae Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!435
2026-04-26 00:13:15 +07:00
Adnan Zahir 0c5ee08f90 Merge branch 'codex/filter-improment' into 'development'
fix: nested modal

See merge request mbugroup/lti-web-client!434
2026-04-25 23:57:53 +07:00
Adnan Zahir bbf9581d3a fix: nested modal 2026-04-25 23:55:26 +07:00
Adnan Zahir 5830ab4c67 Merge branch 'codex/filter-improment' into 'development'
Codex/po date

See merge request mbugroup/lti-web-client!433
2026-04-25 22:50:31 +07:00
Adnan Zahir a1a0b71814 feat: editable po_date 2026-04-25 22:47:59 +07:00
Adnan Zahir 2b3b6b9549 feat: expose received_date in laporan pembelian 2026-04-25 22:24:39 +07:00
Adnan Zahir 047266b6d8 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!432
2026-04-25 14:46:53 +07:00
Adnan Zahir be3034a94e Merge branch 'codex/filter-improment' into 'development'
fix: pagination positioning

See merge request mbugroup/lti-web-client!431
2026-04-25 13:07:25 +07:00
Adnan Zahir a11d05e720 fix: pagination positioning 2026-04-25 13:06:44 +07:00
Rivaldi A N S cb454e7eb7 Merge branch 'feat/share-daily-checklist-to-wa' into 'development'
[FEAT/FE] Adjust Share Daily Checklist to Whatsapp

See merge request mbugroup/lti-web-client!429
2026-04-25 05:34:44 +00:00
Adnan Zahir a6d6c53069 Merge branch 'codex/filter-improment' into 'development'
feat: add more filters

See merge request mbugroup/lti-web-client!430
2026-04-25 12:27:49 +07:00
Adnan Zahir c875ebd951 feat: add more filters 2026-04-25 12:15:42 +07:00
ValdiANS a369386922 feat: add share to whatsapp after submitting daily checklist 2026-04-24 17:22:20 +07:00
ValdiANS b3198a44e9 uncomment pre-commit 2026-04-24 17:10:38 +07:00
ValdiANS b2dfb8fec6 fix: adjust share to whatsapp message 2026-04-24 17:10:11 +07:00
ValdiANS d4d77bb13a fix: add excluded fields in ButtonFilter 2026-04-24 16:22:46 +07:00
ValdiANS 7dfa5233f3 fix: adjust MarketingFilter type 2026-04-24 16:22:23 +07:00
ValdiANS 3d910f78db fix: set initial value to MarketingFilter 2026-04-24 16:22:15 +07:00
Rivaldi A N S 2dfac0be72 Merge branch 'feat/share-daily-checklist-to-wa' into 'development'
[FEAT/FE] Share Daily Checklist

See merge request mbugroup/lti-web-client!428
2026-04-24 05:35:32 +00:00
ValdiANS afe0d2161d feat: implement share daily checklist 2026-04-24 12:00:06 +07:00
ValdiANS 68c13c48c7 fix: adjust PurchaseFilter type 2026-04-23 16:38:31 +07:00
ValdiANS b9a1e94a29 fix: set timeout to 30s 2026-04-23 16:38:16 +07:00
ValdiANS d8c6a90c55 feat: add excludeKeysFromUrl to useTableFilter parameters 2026-04-23 16:38:02 +07:00
ValdiANS 4d01ad7d1d fix: hide phase selection, abk assignment, and activity checklist form when kandang is empty 2026-04-23 16:22:05 +07:00
ValdiANS c487e7f53e fix: persist purchase table and set initial value to PurchaseFilterModal 2026-04-23 16:21:45 +07:00
ValdiANS a316120a78 fix: add total selected items text to reject/approve button 2026-04-23 16:08:39 +07:00
ValdiANS 9af0537587 fix: change vendor column label to "Uraian" 2026-04-23 16:07:21 +07:00
ValdiANS f668bcecb8 fix: change "Kembali" button behavior from link to button 2026-04-23 16:06:48 +07:00
Adnan Zahir 6b95edfb72 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!427
2026-04-23 12:38:36 +07:00
Rivaldi A N S a12b09eb5f Merge branch 'feat/expense-export' into 'development'
[FEAT/FE] Expense Export

See merge request mbugroup/lti-web-client!426
2026-04-23 03:06:07 +00:00
ValdiANS cfb96c45c9 fix: uncomment pre-commit 2026-04-23 09:55:00 +07:00
ValdiANS 747b0f9c2c feat: implement export all in expense and report expense 2026-04-23 09:54:20 +07:00
Adnan Zahir ee2f530d81 Merge branch 'codex/filter-improment' into 'development'
feat: filter improvement

See merge request mbugroup/lti-web-client!425
2026-04-23 00:19:16 +07:00
Adnan Zahir 617124efe4 feat: filter improvement 2026-04-23 00:18:10 +07:00
Rivaldi A N S c0337f4d67 Merge branch 'fix/marketing-export' into 'development'
[FIX/FE] Marketing Export

See merge request mbugroup/lti-web-client!424
2026-04-22 16:34:37 +00:00
ValdiANS e5dcca3408 fix: adjust MarketingApi.exportToExcel method 2026-04-22 23:32:58 +07:00
Rivaldi A N S f2b05856bb Merge branch 'feat/purchase-export' into 'development'
[FEAT/FE] Purchase Export

See merge request mbugroup/lti-web-client!423
2026-04-22 16:21:33 +00:00
ValdiANS 5d6aaace86 feat: implement purchase export to excel 2026-04-22 23:20:31 +07:00
Rivaldi A N S 9dcb3d7269 Merge branch 'fix/daily-checklist-empty-kandang-flag' into 'development'
[FIX/FE] Daily Checklist Empty Kandang Flag

See merge request mbugroup/lti-web-client!422
2026-04-22 15:58:01 +00:00
ValdiANS e96bb46cfd fix: add empty_kandang value in CATEGORY_LABELS 2026-04-22 22:50:38 +07:00
ValdiANS 37edc957d2 fix: implement empty kandang in daily checklist 2026-04-22 16:04:39 +07:00
Rivaldi A N S 60df577cc6 Merge branch 'fix/purchase-form' into 'development'
[FIX/FE] Purchase Form & Expense Filter

See merge request mbugroup/lti-web-client!421
2026-04-22 07:01:46 +00:00
ValdiANS e0e2b0c406 fix: load more location and vendors and adjust reset handler 2026-04-22 13:58:25 +07:00
ValdiANS 244be32b59 fix: adjust ExpensesFilterSchema for location and vendor select input 2026-04-22 13:56:59 +07:00
ValdiANS 1080a26f93 fix: search in location select input 2026-04-22 13:55:29 +07:00
Adnan Zahir 4b62b02a13 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!420
2026-04-22 13:12:50 +07:00
Adnan Zahir c12bf92723 Merge branch 'schema/bulk-approve-marketings-expenses' into 'development'
Schema/bulk approve marketings expenses

See merge request mbugroup/lti-web-client!419
2026-04-22 11:49:45 +07:00
Adnan Zahir 5c5b49d0a9 fix: styling 2026-04-22 11:41:41 +07:00
Adnan Zahir b7f886b51e fix: mismatch dto marketings 2026-04-22 11:41:09 +07:00
Rivaldi A N S 587266e23d Merge branch 'feat/progress-input-export' into 'development'
[FEAT/FE] Progress Input Exporet

See merge request mbugroup/lti-web-client!418
2026-04-22 04:09:21 +00:00
ValdiANS 9293b6321f feat: implement purchase export progress input 2026-04-22 11:06:34 +07:00
ValdiANS ddfd1206a7 feat: implement recording export progress input 2026-04-22 11:06:15 +07:00
ValdiANS 75910960c5 feat: implement marketing export progress input 2026-04-22 11:06:03 +07:00
ValdiANS aae633edee feat: implement expense export progress input 2026-04-22 11:05:54 +07:00
Adnan Zahir f129329d52 Merge branch 'schema/bulk-approve-marketings-expenses' into 'development'
Schema/bulk approve marketings expenses

See merge request mbugroup/lti-web-client!417
2026-04-22 10:36:38 +07:00
Adnan Zahir 2afcc5d1c9 fix: styling 2026-04-22 10:36:03 +07:00
Adnan Zahir 7f578c5d03 fix: bulkApprovals method 2026-04-22 10:34:59 +07:00
Adnan Zahir 180b129550 Merge branch 'schema/bulk-approve-marketings-expenses' into 'development'
fix: schema update for bulk approve

See merge request mbugroup/lti-web-client!416
2026-04-22 10:14:25 +07:00
Adnan Zahir 8b2277c8c3 Merge branch 'development' into 'schema/bulk-approve-marketings-expenses'
# Conflicts:
#   src/services/api/expense.ts
2026-04-22 10:14:17 +07:00
Adnan Zahir 68f4562395 fix: schema update for bulk approve 2026-04-22 10:10:10 +07:00
Rivaldi A N S c374a4a4e9 Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist

See merge request mbugroup/lti-web-client!415
2026-04-22 02:41:14 +00:00
ValdiANS bda66381b8 fix: remove conditional rendering for delete button 2026-04-22 09:38:56 +07:00
Rivaldi A N S 28adeee7bd Merge branch 'feat/bulk-approve-expense' into 'development'
[FEAT/FE] Bulk Approve Expense

See merge request mbugroup/lti-web-client!414
2026-04-21 18:16:08 +00:00
ValdiANS 727ac8ccdb feat: implement bulk approval in expense 2026-04-22 01:14:16 +07:00
Rivaldi A N S b77a8ef56f Merge branch 'feat/bulk-approve-sales-order' into 'development'
[FEAT/FE] Bulk Approve Sales Order

See merge request mbugroup/lti-web-client!413
2026-04-21 17:12:12 +00:00
ValdiANS 50e0ccd9e4 feat: implement bulk approval for SO DO 2026-04-22 00:10:22 +07:00
Rivaldi A N S e43a25307f Merge branch 'fix/project-flock' into 'development'
[FIX/FE] Project Flock

See merge request mbugroup/lti-web-client!412
2026-04-21 09:01:14 +00:00
ValdiANS db4750217e feat: create TableFilterStore type 2026-04-21 15:57:35 +07:00
ValdiANS 19793cdcd4 feat: create useTableFilterStore 2026-04-21 15:57:26 +07:00
ValdiANS 15bddc43e2 fix: implement persist to storage in useTableFilter 2026-04-21 15:57:15 +07:00
ValdiANS 3b7c7bb13f fix: persist table filter 2026-04-21 15:52:36 +07:00
ValdiANS 633cece581 fix: use session storage for useUiStore 2026-04-21 13:30:51 +07:00
ValdiANS e455d203cc fix: set searchKey to 'search' in useSelect 2026-04-21 13:30:34 +07:00
ValdiANS d2a5229282 fix: set fallback value for searchKey in url search params 2026-04-21 13:20:49 +07:00
Rivaldi A N S 2391d6ceeb Merge branch 'feat/daily-checklist-bulk-actions' into 'development'
[FEAT/FE] Daily Checklist Bulk Actions

See merge request mbugroup/lti-web-client!411
2026-04-20 09:22:17 +00:00
ValdiANS 4bb57ed0a0 feat: create bulkApprove and bulkReject method 2026-04-20 16:21:28 +07:00
ValdiANS 5bf3d32636 feat: implement bulk approve & reject 2026-04-20 16:21:17 +07:00
Adnan Zahir 12a50c6100 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!410
2026-04-20 08:24:51 +07:00
Rivaldi A N S c5a0cfe118 Merge branch 'fix/marketing-report' into 'development'
[FIX/FE] Marketing Report

See merge request mbugroup/lti-web-client!409
2026-04-19 18:15:30 +00:00
ValdiANS 898bbd57ec fix: pass page and pageSize to Table component 2026-04-20 01:14:10 +07:00
ValdiANS 5b5113de6e fix: add page and pageSize 2026-04-20 01:13:51 +07:00
ValdiANS 267a6f37cc chore: remove unnecessary code 2026-04-20 01:13:32 +07:00
Rivaldi A N S 7d4898c266 Merge branch 'feat/depreciation-report' into 'development'
[FEAT/FE] Depreciation Report

See merge request mbugroup/lti-web-client!408
2026-04-19 17:31:02 +00:00
ValdiANS f49822d03d fix: adjust ReportDepreciation type 2026-04-20 00:30:07 +07:00
ValdiANS aa4da686c6 fix: move and rename report to expense-report.ts 2026-04-20 00:29:55 +07:00
ValdiANS 5a668c469f chore: update ReportExpenseApi import path 2026-04-20 00:29:34 +07:00
ValdiANS 2ca733de97 fix: adjust ReportDepreciationTab content 2026-04-20 00:29:15 +07:00
ValdiANS 8afc1a6381 feat: create ReportDepreciationFilterModal component 2026-04-20 00:28:41 +07:00
ValdiANS d47142153e Merge branch 'development' into feat/depreciation-report 2026-04-19 21:57:46 +07:00
Adnan Zahir 09537d84d0 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!407
2026-04-18 09:41:09 +07:00
Rivaldi A N S 188385b638 Merge branch 'fix/recording-export' into 'development'
[FIX/FE] Recording Export

See merge request mbugroup/lti-web-client!406
2026-04-17 07:34:52 +00:00
ValdiANS 08aa79a06b fix: adjust limit to get all recording data in exportToExcel method 2026-04-17 14:07:52 +07:00
ValdiANS 16741aaa46 feat: create ReportDepreciation and ReportDepreciationSearchParams type 2026-04-17 13:27:21 +07:00
ValdiANS 93083c7d2a fix: create ReportDepreciationTab component 2026-04-17 13:27:05 +07:00
ValdiANS 8333b5138a fix: adjust ReportExpenseSkeleton and ReportSkeletonColumn type 2026-04-17 13:25:18 +07:00
ValdiANS c0ee2013f3 feat: add Laporan Depresiasi tab 2026-04-17 13:24:26 +07:00
Rivaldi A N S 022656cd80 Merge branch 'fix/daily-checklist-kandang' into 'development'
[FIX/FE] Daily Checklist Master Data Kandang

See merge request mbugroup/lti-web-client!405
2026-04-16 06:44:51 +00:00
ValdiANS 9d3c22fcf3 chore: remove unnecessary code 2026-04-16 13:42:52 +07:00
Rivaldi A N S 11353809f0 Merge branch 'feat/expense-enhancement' into 'development'
[FEAT/FE] Expense Enhancement

See merge request mbugroup/lti-web-client!404
2026-04-15 09:43:06 +00:00
ValdiANS 6463b7a572 fix: set resetPage to false as default value in updateFilter function 2026-04-15 16:39:22 +07:00
ValdiANS 7a5ee2aca1 feat: implement return to url query param 2026-04-15 16:38:56 +07:00
ValdiANS 5e907d7e53 feat: create expense navigation helper function 2026-04-15 16:35:35 +07:00
Adnan Zahir 71edc9c68a Merge branch 'fix/recording' into 'development'
[FIX][FE]: adjust value query param get product warehouses

See merge request mbugroup/lti-web-client!403
2026-04-14 15:15:35 +07:00
MacBook Air M1 2a33fdbbbe adjust value query param get product warehouses 2026-04-14 15:05:08 +07:00
Adnan Zahir 178c659b58 Merge branch 'codex/uniformity-week-calculation' into 'development'
codex/fix: uniformity week calculation

See merge request mbugroup/lti-web-client!402
2026-04-14 14:33:04 +07:00
Rivaldi A N S c1d6436583 Merge branch 'fix/adjustment-issue-14-apr-26' into 'development'
[FIX/FE] Fix Unnecessary Error Label (OptionType) on Purchase Approval Form (Purchase)

See merge request mbugroup/lti-web-client!401
2026-04-14 06:59:11 +00:00
rstubryan 8dc62453bd fix(FE-form-object-missmatch): Refactor purchase item handling in
approval forms and schemas
2026-04-14 13:31:40 +07:00
Adnan Zahir 1aa2ca9b31 Merge branch 'development' into 'production'
refactor(FE-add-param): Update MarketingFilter to refine API calls and

See merge request mbugroup/lti-web-client!400
2026-04-14 13:20:27 +07:00
Adnan Zahir 244d800874 codex/fix: uniformity week calculation 2026-04-14 13:10:53 +07:00
Rivaldi A N S 52dd1613bb Merge branch 'fix/expense-report-filter' into 'development'
[FIX/FE] Expense Report Filter

See merge request mbugroup/lti-web-client!399
2026-04-13 09:32:29 +00:00
ValdiANS 57ea81fdf2 fix: change kandang_id to project_flock_kandang_id in report expense params 2026-04-13 16:30:57 +07:00
Rivaldi A N S 90742604cb Merge branch 'fix/expense-realization-detail' into 'development'
[FIX/FE] Expense Realization Detail

See merge request mbugroup/lti-web-client!398
2026-04-13 08:41:42 +00:00
ValdiANS 4b8853b766 fix: implement lazy loading in nontstock select input 2026-04-13 15:31:04 +07:00
ValdiANS 7168270527 fix: use isNaN to check valid kandang ID 2026-04-13 15:28:25 +07:00
Rivaldi A N S 47b186e195 Merge branch 'fix/adjustment-issue-13-apr-26' into 'development'
[FIX/FE] Adjustment Endpoint Kandang on Dashboard Filter (Project Flock Kandang) and Add Param has_marketing on Marketing Filter

See merge request mbugroup/lti-web-client!397
2026-04-13 07:58:19 +00:00
rstubryan ff39514b78 refactor(FE-endpoint-path): Fix customer API integration in
MarketingFilter
2026-04-13 14:55:00 +07:00
rstubryan f97b6fc218 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into fix/adjustment-issue-13-apr-26 2026-04-13 14:38:54 +07:00
rstubryan 62dc8235d4 refactor(FE-change-api): Refactor Kandang input handling in
DashboardProduction
2026-04-13 14:37:23 +07:00
rstubryan 73d05d6b4b refactor(FE-add-param): Update MarketingFilter to refine API calls and
options handling
2026-04-13 14:23:21 +07:00
Adnan Zahir c87107b4ee Merge branch 'development' into 'production'
refactor(FE-load-more-option): Add infinite scroll to location and

See merge request mbugroup/lti-web-client!396
2026-04-13 14:08:57 +07:00
Rivaldi A N S 3c44906a20 Merge branch 'fix/production-result-report-filter' into 'development'
[FIX/FE] Production Result Report

See merge request mbugroup/lti-web-client!395
2026-04-13 05:24:07 +00:00
ValdiANS e4b1deecdc fix: render one project flock kandang if kandang is selected 2026-04-13 12:19:38 +07:00
ValdiANS 12afa88f2c fix: make kandang_id optional 2026-04-13 12:19:08 +07:00
Adnan Zahir 0527155bb9 Merge branch 'fix/adjustment-issue-13-apr-26' into 'development'
[FIX/FE] Adjustment Load More Data (useSelect Biaya), Marketing Customer Issue and Remove Fetch Kandang at Dashboard

See merge request mbugroup/lti-web-client!394
2026-04-13 12:13:11 +07:00
rstubryan 34a45d084b refactor(FE-modal-close-when-reset): Close filter modal when resetting
dashboard filters
2026-04-13 11:57:31 +07:00
rstubryan 9de897dfbd Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into dev/restu 2026-04-13 11:51:01 +07:00
rstubryan 907f6664e1 refactor(FE-remove-kandang-fetch): Refactor Kandang select logic to use
derived options
2026-04-13 11:48:32 +07:00
rstubryan 3ad04e5bac refactor(FE-remove-filter): Make select inputs clearable in
DashboardProduction and remove filter from kandang
2026-04-13 11:33:40 +07:00
ValdiANS 4649dfde89 Merge branch 'development' into fix/expense-report-filter 2026-04-13 11:21:03 +07:00
Adnan Zahir 55b13988bf Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!393
2026-04-13 11:17:24 +07:00
rstubryan b580a01bdc refactor(FE-formik-usage): Refactor MarketingFilter form values and
handlers
2026-04-13 11:13:39 +07:00
Rivaldi A N S 15ec6c3b9c Merge branch 'fix/report-default-filter-value' into 'development'
[FIX/FE] Report Default Filter Value

See merge request mbugroup/lti-web-client!392
2026-04-13 04:02:06 +00:00
ValdiANS 8b970aeb64 fix: open filter modal when component is mounted 2026-04-13 11:01:00 +07:00
ValdiANS de6fd2367e fix: set filter default value 2026-04-13 11:00:02 +07:00
ValdiANS 3fedbc7ffb fix: adjust showEditButton condition 2026-04-13 10:58:33 +07:00
ValdiANS 9e297cc0a4 chore: remove unnecessary code 2026-04-13 10:58:23 +07:00
rstubryan 6ff3a715e0 refactor(FE-load-more-option): Add infinite scroll to location and
supplier dropdowns
2026-04-13 10:46:51 +07:00
ValdiANS cd4cef883e fix: change kandang filter to project flock kandang with period 2026-04-13 10:08:09 +07:00
Rivaldi A N S d853781c17 Merge branch 'fix/laporan-rekapitulasi-pembelian-per-supplier' into 'development'
[FIX/FE] Laporan Rekapitulasi Pembelian Per Supplier

See merge request mbugroup/lti-web-client!391
2026-04-13 02:48:37 +00:00
ValdiANS 8faed2e561 fix: implement lazy loading in select input in filter modal 2026-04-13 09:44:38 +07:00
Rivaldi A N S 8aeef46ee3 Merge branch 'fix/closing-kandang-button' into 'development'
[FIX/FE] Closing Kandang Button

See merge request mbugroup/lti-web-client!390
2026-04-13 02:36:14 +00:00
ValdiANS c9000c1e2c fix: disable button if kandang is selected 2026-04-13 09:33:41 +07:00
ValdiANS bb3541090a fix: pass kandang ID ClosingKandangList component 2026-04-13 09:33:23 +07:00
ValdiANS ad0e617ed0 fix: render button if href is provided and is disabled 2026-04-13 09:33:01 +07:00
Rivaldi A N S 73ef1c2ece Merge branch 'fix/daily-sales-report' into 'development'
[FIX/FE] Daily Sales Report

See merge request mbugroup/lti-web-client!389
2026-04-12 14:37:55 +00:00
ValdiANS 9cf0d15c33 fix: implement lazy loading for select input 2026-04-12 21:36:40 +07:00
Adnan Zahir 19033278b3 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!388
2026-04-11 14:13:02 +07:00
Rivaldi A N S c66f7b1cbf Merge branch 'fix/hpp-report' into 'development'
[FIX/FE] HPP Report

See merge request mbugroup/lti-web-client!387
2026-04-10 10:08:27 +00:00
ValdiANS 17ebc31f00 fix: implement infinite scroll in select input 2026-04-10 17:07:07 +07:00
Rivaldi A N S ce0b4d744c Merge branch 'fix/marketing-delivery-order' into 'development'
[FIX/FE] Marketing Delivery Order

See merge request mbugroup/lti-web-client!386
2026-04-10 09:15:15 +00:00
ValdiANS f6f3290743 fix: add weight_per_convertion to BaseDelivery 2026-04-10 16:13:02 +07:00
ValdiANS 31a4dec8a3 fix: get weight_per_convertion from delivery order first 2026-04-10 16:12:47 +07:00
ValdiANS fbb6f87368 fix: add weight_per_convertion to payload when creating/updating delivery order 2026-04-10 16:12:35 +07:00
Rivaldi A N S d88d71fb16 Merge branch 'fix/marketing-delivery-order' into 'development'
[FIX/FE] Marketing Delivery Order

See merge request mbugroup/lti-web-client!385
2026-04-10 08:13:27 +00:00
ValdiANS 570024c2e6 chore: prettier format 2026-04-10 15:08:13 +07:00
ValdiANS 70556d04ba fix: calculate unit price by weight 2026-04-10 15:07:39 +07:00
ValdiANS 00434002a7 fix: add harga satuan per peti 2026-04-10 15:06:57 +07:00
ValdiANS bcb1e0b5b6 fix: add (Kg) label to Total Harga Satuan 2026-04-10 15:06:38 +07:00
ValdiANS 03a6aabf1f fix: adjust initialPricePerConvertion value 2026-04-10 15:06:06 +07:00
ValdiANS 47adaa4f92 fix: return total_peti, weight_per_convertion, and price_per_convertion in DeliveryProductToFieldValues function 2026-04-10 15:02:48 +07:00
Rivaldi A N S f2cdbd497a Merge branch 'fix/marketing-delivery-order' into 'development'
[FIX/FE] Marketing Delivery Order

See merge request mbugroup/lti-web-client!384
2026-04-09 09:38:58 +00:00
ValdiANS 4ffea739a9 fix: comment edit button in renderSalesOrderContent 2026-04-09 16:37:35 +07:00
ValdiANS bf5591d61d fix: prioritize DO data if delivery orders exist 2026-04-09 16:36:59 +07:00
Rivaldi A N S a725ae4891 Merge branch 'fix/uniformity-form' into 'development'
[FIX/FE] Uniformity Form

See merge request mbugroup/lti-web-client!383
2026-04-09 08:45:55 +00:00
Adnan Zahir 4a6ac8a57d Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!382
2026-04-09 15:36:40 +07:00
ValdiANS f5d3fb3b9d uncomment pre-commit 2026-04-09 15:14:07 +07:00
ValdiANS 4a6c443003 fix: disable uniformity form uploading uniformity file 2026-04-09 15:13:16 +07:00
Rivaldi A N S 09f4af3ece Merge branch 'feat/recording-export' into 'development'
[FEAT/FE] Recording

See merge request mbugroup/lti-web-client!381
2026-04-09 07:24:57 +00:00
ValdiANS 62d250109b feat: add responseType to axios config 2026-04-09 14:15:29 +07:00
ValdiANS e50f4dbddb feat: add exportToExcel method to RecordingService 2026-04-09 14:15:12 +07:00
ValdiANS c898154b48 feat: add export button 2026-04-09 14:14:50 +07:00
Rivaldi A N S acb02c9bdc Merge branch 'fix/marketing-delivery-order' into 'development'
[FIX/FE] Marketing Delivery Order

See merge request mbugroup/lti-web-client!380
2026-04-09 04:26:47 +00:00
ValdiANS 986f429ea9 fix: add edit button to delivery item 2026-04-09 11:21:20 +07:00
ValdiANS 1dafb0d365 fix: adjust DeliveryProductToFieldValues and mergeSOwithDO return values 2026-04-09 11:09:04 +07:00
ValdiANS 095b1c5850 fix: adjust selected delivery product priority order 2026-04-09 11:04:57 +07:00
Rivaldi A N S 4297502c55 Merge branch 'fix/purchase-product-receive-confirmation' into 'development'
[FIX/FE] Purchase Product Receive Confirmation

See merge request mbugroup/lti-web-client!379
2026-04-08 08:37:44 +00:00
ValdiANS 726065da51 fix: make vehicle_number and transport_per_item required if expedition_vendor exist 2026-04-08 15:32:01 +07:00
ValdiANS 6c03e42006 fix: remove transport_per_item and vehicle_number value and disable them if expedition vendor is empty 2026-04-08 15:31:31 +07:00
ValdiANS 5c39e900f3 chore: remove unnecessary code 2026-04-08 15:30:37 +07:00
ValdiANS 68c1655824 fix: adjust unit_price and price_per_qty value to match the SalesOrderProductForm 2026-04-08 13:57:09 +07:00
Adnan Zahir 2b9847e1a9 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!378
2026-04-08 13:39:17 +07:00
Rivaldi A N S 0ef8c06e41 Merge branch 'fix/adjustment-issue-8-apr-26' into 'development'
[FIX/FE] Adjustment Filter Default Value Set Range to This Month

See merge request mbugroup/lti-web-client!377
2026-04-08 04:32:46 +00:00
rstubryan 68b25332b1 refactor(FE-set-to-end): Fix date range to include the end of the month 2026-04-08 11:29:51 +07:00
rstubryan b402a06706 feat(FE-moment-default-range): Set default date range to current month
in Dashboard component
2026-04-08 10:15:33 +07:00
Rivaldi A N S 7df2fad959 Merge branch 'fix/adjustment-dashboard-modal' into 'development'
[FIX/FE] Adjustment Dashboard Modal (Open Filter Issue)

See merge request mbugroup/lti-web-client!376
2026-04-08 02:59:37 +00:00
rstubryan 0b52fff5f5 refactor(FE-dashboard-modal): Refactor dashboard production data
fetching logic
2026-04-08 09:54:40 +07:00
Adnan Zahir 167769a711 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!375
2026-04-07 22:56:27 +07:00
Rivaldi A N S e251ab9eb4 Merge branch 'fix/marketing' into 'development'
[FIX/FE] Marketing - Sales Order Form

See merge request mbugroup/lti-web-client!374
2026-04-07 10:44:49 +00:00
ValdiANS 9f0fbcf041 fix: make price_per_qty calculation to price per kg and make unit_price calculation to price per egg (if category is TELUR and convertion unit QTY) 2026-04-07 17:24:19 +07:00
ValdiANS 05fbae680f fix: reorder input for price_per_qty and unit_price 2026-04-07 17:23:23 +07:00
ValdiANS 444c475cb4 fix: remove formattedUnitPrice 2026-04-07 17:22:46 +07:00
ValdiANS ef1ce2c78c fix: remove roundPrice, update unit price calculation in calculateTelurPeti 2026-04-07 16:59:35 +07:00
ValdiANS 429ff58bfd chore: remove unnecessary code 2026-04-07 16:57:01 +07:00
ValdiANS 8961004000 fix: set initialPricePerConvertion to unit_price 2026-04-07 16:55:39 +07:00
ValdiANS 2dc3bcf9f0 fix: make convertion unit support QTY when hitting update/create API 2026-04-07 16:55:23 +07:00
Adnan Zahir 417dbba458 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!373
2026-04-07 16:53:36 +07:00
Rivaldi A N S 9c31705865 Merge branch 'fix/adjustment-recording-form' into 'development'
[FIX/FE] Adjustment Zero Restriction on Jumlah Pakai (>0. value) and Add Refetch (Invalidate) at Recording Detail Page

See merge request mbugroup/lti-web-client!372
2026-04-07 09:13:40 +00:00
rstubryan b89730ab68 feat(FE-invalidate-mutation): Refactor SWR keys for recording detail
pages and add cache invalidation
2026-04-07 16:06:46 +07:00
rstubryan 6e34eede4b refactor(FE-jumlah-pakai-zero-restriction): Update validation message
for qty in StockObjectSchema
2026-04-07 16:01:59 +07:00
Rivaldi A N S ffd5e70947 Merge branch 'fix/adjustment-recording-form' into 'development'
[FIX/FE] Adjustment Comma's value for Jumlah Pakai Field and Commented Out Param at (location_id) Egg Product (Product Warehouse) Endpoint

See merge request mbugroup/lti-web-client!371
2026-04-07 08:32:54 +00:00
rstubryan 2f89c6f216 refactor(FE-unused-param): Comment out unused eggProductsLocationId
state and references
2026-04-07 15:26:25 +07:00
rstubryan ebf966228b refactor(FE-decimal-jumlah-pakai): Increase decimal scale for stock
quantity input to 3
2026-04-07 15:23:31 +07:00
Rivaldi A N S ebe1d77c72 Merge branch 'fix/marketing' into 'development'
[FIX/FE] Marketing

See merge request mbugroup/lti-web-client!370
2026-04-07 06:12:03 +00:00
ValdiANS 922a93414f fix: adjust unit price placeholder 2026-04-07 13:11:14 +07:00
Rivaldi A N S 854a1e7c4c Merge branch 'fix/recording' into 'development'
[FIX/FE] Recording

See merge request mbugroup/lti-web-client!369
2026-04-07 04:55:57 +00:00
ValdiANS 129a3fda44 fix: memoized formattedSuccessRawData and formattedErrorRawData 2026-04-07 11:54:00 +07:00
ValdiANS 981b48acc0 fix: check deep equality 2026-04-07 11:53:34 +07:00
Adnan Zahir dd5bbf0ac6 Merge branch 'codex/sales-at-farm-level' into 'development'
codex/fix: invisible depletion and egg <= 0

See merge request mbugroup/lti-web-client!368
2026-04-06 22:32:46 +07:00
Adnan Zahir 8872b283ac codex/fix: invisible depletion and egg <= 0 2026-04-06 22:28:39 +07:00
Adnan Zahir 860c9dec22 Merge branch 'codex/sales-at-farm-level' into 'development'
Codex/sales at farm level

See merge request mbugroup/lti-web-client!367
2026-04-04 10:08:36 +07:00
Adnan Zahir 0cd6c9bd2f Merge branch 'production' into development 2026-04-04 09:59:36 +07:00
Adnan Zahir 107d412c10 formatting 2026-04-04 09:57:01 +07:00
Adnan Zahir c6d8533190 codex/fix: inconsistent stock options and availability 2026-04-04 09:53:10 +07:00
Adnan Zahir ae90d55f81 Merge branch 'hotfix/bug-reported-by-user' into 'production'
[HOTFIX/FE] Adjustment

See merge request mbugroup/lti-web-client!365
2026-04-02 14:37:14 +07:00
ValdiANS c155717459 fix: use correct address and logo 2026-04-02 11:44:08 +07:00
ValdiANS d74de4b2d9 fix: use correct address 2026-04-02 11:44:00 +07:00
ValdiANS 529ba21f47 feat: create PurchaseFilter type 2026-04-02 11:41:02 +07:00
ValdiANS 449c2030fe feat: add filter modal 2026-04-02 11:40:53 +07:00
ValdiANS 679740972f feat: create PurchaseFilterModal component 2026-04-02 11:40:43 +07:00
ValdiANS 57b8326fdf fix: change from parseInt to parseFloat 2026-04-02 11:32:09 +07:00
ValdiANS e26b5127c5 fix: parse to float numberFormatValues.value 2026-04-02 11:28:10 +07:00
Rivaldi A N S 1a4a1e8e56 Merge branch 'fix/purchase-pdf-logo' into 'development'
[FIX/FE] Purchase PDF Logo

See merge request mbugroup/lti-web-client!364
2026-04-02 04:01:59 +00:00
ValdiANS 10d1f05aa5 fix: use correct address and logo 2026-04-02 11:00:17 +07:00
ValdiANS e4b6238771 fix: use correct address 2026-04-02 11:00:08 +07:00
Rivaldi A N S fc89922ed1 Merge branch 'fix/purchasing-filter' into 'development'
[FIX/FE] Purchase Filter

See merge request mbugroup/lti-web-client!363
2026-04-02 03:00:15 +00:00
ValdiANS 25b5165249 feat: create PurchaseFilter type 2026-04-02 09:57:48 +07:00
ValdiANS cae19d905b feat: add filter modal 2026-04-02 09:57:40 +07:00
ValdiANS c040c0e9bb feat: create PurchaseFilterModal component 2026-04-02 09:51:22 +07:00
Rivaldi A N S b3bd7563fa Merge branch 'fix/master-data-product' into 'development'
[FIX/FE] Master Data Product

See merge request mbugroup/lti-web-client!362
2026-04-01 09:13:34 +00:00
ValdiANS edf21fbfc4 fix: change from parseInt to parseFloat 2026-04-01 16:13:13 +07:00
ValdiANS 65f31f8340 fix: parse to float numberFormatValues.value 2026-04-01 16:13:01 +07:00
Adnan Zahir 772087bacd Merge branch 'codex/sales-at-farm-level' into 'development'
codex/fix: show farm stock usage on closing page

See merge request mbugroup/lti-web-client!361
2026-04-01 12:33:55 +07:00
Adnan Zahir f302bcdb4b codex/fix: show farm stock usage on closing page 2026-04-01 12:31:16 +07:00
Adnan Zahir b68bcc77f5 Merge branch 'codex/sales-at-farm-level' into 'development'
codex/fix: purchase receivement error and recording doesn't show depletion/egg

See merge request mbugroup/lti-web-client!360
2026-04-01 11:10:29 +07:00
Adnan Zahir 3d7a2073b0 formatting 2026-04-01 11:07:05 +07:00
Adnan Zahir 8b1546a305 codex/fix: purchase receivement error and recording doesn't show depletion/egg 2026-04-01 11:03:56 +07:00
Adnan Zahir fa3d0a1179 Merge branch 'codex/sales-at-farm-level' into 'development'
codex: initiated changes (farm-level warehouse stock manipulation on recording and sales)

See merge request mbugroup/lti-web-client!359
2026-04-01 10:27:42 +07:00
Adnan Zahir ffcf422cb5 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!358
2026-04-01 10:15:20 +07:00
Adnan Zahir 8d92da75cf codex: initiated changes 2026-04-01 10:14:05 +07:00
Rivaldi A N S 6b29406307 Merge branch 'fix/purchase-received-product-default-value' into 'development'
[FIX/FE] Purchase

See merge request mbugroup/lti-web-client!357
2026-03-30 07:42:32 +00:00
ValdiANS 4f3e304b2b fix: set received_qty default value to sub_qty 2026-03-30 14:40:26 +07:00
Adnan Zahir 18aff48dc2 Merge branch 'development' into 'production'
Development

See merge request mbugroup/lti-web-client!356
2026-03-27 15:39:56 +07:00
Rivaldi A N S 7bee13124d Merge branch 'fix/list-daily-checklist' into 'development'
[FIX/FE] List Daily Checklist

See merge request mbugroup/lti-web-client!355
2026-03-27 07:42:04 +00:00
ValdiANS f5d9dcbdf6 fix: set DailyChecklist.kandang optional 2026-03-27 11:12:58 +07:00
Rivaldi A N S 04d22e55db Merge branch 'fix/redirect-to-sso' into 'development'
[FIX/FE]: Redirect to SSO

See merge request mbugroup/lti-web-client!354
2026-03-26 09:21:09 +00:00
ValdiANS 8bf5a88edb fix: do not redirect to SSO when the error response status is 401 and API url is refresh API 2026-03-26 16:19:55 +07:00
Rivaldi A N S ee0c47b0a1 Merge branch 'fix/recording' into 'development'
[FIX/FE] Recording Form

See merge request mbugroup/lti-web-client!353
2026-03-17 17:14:28 +00:00
ValdiANS 93d4ff9339 fix: search stock product issue correctly 2026-03-18 00:13:18 +07:00
Adnan Zahir aa52211b0a Merge branch 'development' into 'production'
refactor(FE): Refactor to use `is_laying` instead of

See merge request mbugroup/lti-web-client!352
2026-03-17 13:38:35 +07:00
Rivaldi A N S 39cb38a23f Merge branch 'hotfix/adjustment-recording-fifo-stock' into 'development'
[HOTFIX/FE] Adjustment FIFO Stock V2 (Stock Related Usage)

See merge request mbugroup/lti-web-client!351
2026-03-17 04:38:42 +00:00
rstubryan c1087b37fb chore(FE-prettier): Format code for better readability in inventory
tables
2026-03-16 11:02:25 +07:00
rstubryan c4e27edd56 feat(FE): Add delete functionality to Inventory and Movement tables 2026-03-16 11:01:29 +07:00
rstubryan b020f2b187 refactor(FE): Rename available_qty to transfer_available_qty 2026-03-16 10:51:02 +07:00
rstubryan 375de4c86c refactor(FE): Remove unused dependency from useEffect in RecordingForm 2026-03-16 10:28:36 +07:00
rstubryan 8f361c4327 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into hotfix/adjustment-recording-fifo-stock 2026-03-16 10:10:16 +07:00
Rivaldi A N S 710be88794 Merge branch 'fix/inventory-adjustment' into 'development'
[FIX/FE] Inventory Adjustment

See merge request mbugroup/lti-web-client!350
2026-03-16 02:43:48 +00:00
ValdiANS 0f7a2bd796 fix: adjust formik schema for warehouse 2026-03-16 09:41:23 +07:00
ValdiANS 0c8a833e00 fix: add generic for OptionType type 2026-03-16 09:41:01 +07:00
Rivaldi A N S 0c42bfd70c Merge branch 'fix/inventory-adjustment' into 'development'
[FIX/FE] Inventory Adjustment

See merge request mbugroup/lti-web-client!349
2026-03-14 08:43:04 +00:00
ValdiANS 85dee607e0 fix: get kandang options from project flock kandang instead of kandang master data 2026-03-14 15:42:01 +07:00
rstubryan 6c7e310e67 feat(FE): Add support for available_qty in MovementForm 2026-03-13 13:33:18 +07:00
ragilap 85f6677c2a fixing recording filter form 2026-03-11 15:35:37 +07:00
rstubryan 811850857d refactor(FE): Restrict stock and depletion edits based on permissions 2026-03-11 10:18:19 +07:00
rstubryan 5494cb0ff2 refactor(FE): Remove restriction check for locked rows and add
"isGrowingLocked" badge
2026-03-11 10:03:54 +07:00
rstubryan 11eeac3289 refactor(FE): Refactor payload creation to respect recording
restrictions
2026-03-11 09:56:14 +07:00
ragilap 1621f2ab7d fixing disable field detail 2026-03-10 17:34:52 +07:00
ragilap 5540787154 implement transition recording 2026-03-10 17:05:42 +07:00
ragilap 1b499bc967 implement transition recording 2026-03-10 17:04:44 +07:00
rstubryan 44a5c51023 refactor(FE): Refactor recording restriction logic for clarity and
accuracy
2026-03-10 14:02:07 +07:00
rstubryan aa13e989c1 feat(FE): Add week calculation utility and improve state resets 2026-03-10 11:40:10 +07:00
rstubryan ebe7c367e7 refactor(FE): Refactor isLaying logic for clarity and reuse 2026-03-10 11:34:14 +07:00
rstubryan 2f085c287f Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into hotfix/adjustment-recording-fifo-stock 2026-03-10 11:13:56 +07:00
rstubryan 058f9f403d refactor(FE): Improve delete handlers with success and error feedback 2026-03-10 11:13:46 +07:00
Rivaldi A N S 8b8b7be4b7 Merge branch 'feat/daily-checklist-master-data' into 'development'
[FIX/FE] Daily Checklist

See merge request mbugroup/lti-web-client!348
2026-03-09 10:15:55 +00:00
ValdiANS efcecf4f66 fix: implement lazy loading in kandang select input 2026-03-09 17:14:35 +07:00
Rivaldi A N S a6c63a7dcb Merge branch 'feat/daily-checklist-master-data' into 'development'
[FIX/FE]: Daily Checklist Master Data Kandang

See merge request mbugroup/lti-web-client!347
2026-03-09 08:58:50 +00:00
ValdiANS 0263db9fae fix: use DailyChecklistKandangApi instead of KandangApi 2026-03-09 15:55:48 +07:00
rstubryan cc08e3af15 refactor(FE): Fix logical grouping in isLaying and isLayingCategory
checks
2026-03-09 15:04:58 +07:00
rstubryan 0929461ec5 refactor(FE): Improve transition and laying state handling in
RecordingForm
2026-03-09 15:03:42 +07:00
rstubryan ace6633f79 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into hotfix/adjustment-recording-fifo-stock 2026-03-09 14:04:22 +07:00
rstubryan f1a952ca6b refactor(FE): Refactor getRecordingRestrictionInfo for better
readability
2026-03-09 14:01:29 +07:00
rstubryan ed34a99117 refactor(FE): Refactor to use is_laying instead of
`project_flock_category`
2026-03-09 13:59:24 +07:00
Rivaldi A N S 4beaba1f15 Merge branch 'feat/daily-checklist-master-data' into 'development'
[FEAT/FE] Master Data Daily Checklist Kandang

See merge request mbugroup/lti-web-client!346
2026-03-09 06:49:31 +00:00
ValdiANS 8ea029efdd Merge branch 'development' into feat/daily-checklist-master-data 2026-03-09 13:42:01 +07:00
ValdiANS 02e4dba288 feat(FE): implement lazy loading for kandang select input 2026-03-09 13:41:18 +07:00
ValdiANS c42fdbf33d chore(FE): remove unnecessary code 2026-03-09 13:40:58 +07:00
ValdiANS 2cfa8c046b feat(FE): add onScroll prop to SelectPrimitive.Viewport 2026-03-09 13:40:47 +07:00
ValdiANS 30d5516161 fix: use DailyChecklistKandangApi instead of KandangApi 2026-03-09 12:47:12 +07:00
ValdiANS f83abc91da chore(FE): remove unncessary code 2026-03-09 12:30:49 +07:00
ValdiANS 918c51e83b fix(FE): add kandang_group to BaseKandang and add group_id to CreateKandangPayload 2026-03-09 12:30:16 +07:00
ValdiANS f1a4d9b648 feat(FE): create daily checklist kandang types 2026-03-09 12:29:52 +07:00
ValdiANS 29e33560f8 feat(FE): create daily checklist kandang API service 2026-03-09 12:29:36 +07:00
ValdiANS fb9e863862 feat(FE): create MasterKandangContent component 2026-03-09 12:29:20 +07:00
ValdiANS 1b3e5f94f1 feat(FE): add Kandang Group input 2026-03-09 12:29:04 +07:00
ValdiANS e1856926ea feat(FE): add group to kandang form schema 2026-03-09 12:28:48 +07:00
ValdiANS 2b096099d3 feat: add kandang group column 2026-03-09 12:28:29 +07:00
rstubryan ea25417e8d Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into hotfix/adjustment-recording-fifo-stock 2026-03-09 11:39:16 +07:00
kris 668abeca23 Merge branch 'development' into 'production'
ci: switch build images to AWS ECR Public

See merge request mbugroup/lti-web-client!345
2026-03-09 03:16:17 +00:00
M1 AIR deabb1c3ee Merge origin/production into development to resolve MR conflicts 2026-03-09 10:15:20 +07:00
M1 AIR 121c44070c ci: switch build images to AWS ECR Public 2026-03-09 09:45:58 +07:00
ValdiANS 0dbad23cd5 feat(FE): implement options lazy loading by adding onLoadMore and isLoadingMore props 2026-03-09 09:31:05 +07:00
ValdiANS b9a17f472b feat: add daily checklist master data kandang permission in ROUTE_PERMISSIONS 2026-03-09 09:30:26 +07:00
ValdiANS c07b245eeb feat(FE): add Kandang submenu in Daily Checklist Master Data menu 2026-03-09 09:30:04 +07:00
ValdiANS d7e32f8f5b feat(FE): create Daily Checklist Master Data Kandang page 2026-03-09 09:29:22 +07:00
ValdiANS 698fe2e851 feat(FE): add pre-commit script 2026-03-09 09:28:45 +07:00
rstubryan cdf0442a2b refactor(FE): Add transition restrictions for recording operations 2026-03-09 09:04:14 +07:00
Adnan Zahir 422c7c9fb0 Merge branch 'development' into 'production'
refactor(FE): Refactor RowOptionsMenu to use PopoverButton and

See merge request mbugroup/lti-web-client!344
2026-03-09 06:38:03 +07:00
Adnan Zahir 3042b54577 Merge branch 'fix/product-select-include-all-param' into 'development'
fix: add include all param to adjustment stock products select

See merge request mbugroup/lti-web-client!343
2026-03-09 00:51:43 +07:00
Adnan Zahir e5a686e5ee Merge branch 'hotfix/adjustment-fifo-stock-ttl' into 'development'
[HOTFIX/FE] FIFO Stock Adjustment for TTL, Recording and Project Flock (Chickin)

See merge request mbugroup/lti-web-client!342
2026-03-09 00:50:11 +07:00
Adnan Zahir 37d5a6b675 fix: add include all param to adjustment stock products select 2026-03-09 00:49:39 +07:00
rstubryan 2ff32094ce chore(FE): Fix inconsistent indentation in ChickLogsView and
RecordingForm
2026-03-08 22:13:26 +07:00
rstubryan 7207f1ba75 refactor(FE): Add isRecordingEditable check to detail actions 2026-03-08 22:12:29 +07:00
rstubryan 41d2e8737b feat(FE): Add chickin delete functionality with modal confirmation 2026-03-08 21:54:55 +07:00
rstubryan b2016314f5 refactor(FE): Restrict edit and delete actions based on recording status 2026-03-08 16:40:36 +07:00
rstubryan 7366d6490c refactor(FE): Validate transferToLayingId before fetching data 2026-03-08 16:34:59 +07:00
rstubryan e5e9b517fd refactor(FE): Update button visibility logic in TransferToLayingsTable 2026-03-08 16:17:20 +07:00
rstubryan b6629b0bbb refactor(FE): Set maxSourceQuantity in edit mode using existing data 2026-03-08 16:12:08 +07:00
rstubryan bac6766fa2 refactor(FE): Refactor transfer logic to use maxSourceQuantity state 2026-03-08 16:06:13 +07:00
Rivaldi A N S 9389fa0354 Merge branch 'fix/cleanup-warning-and-adjust-form-field' into 'development'
[FIX/FE] Cleanup Warning and Refactoring All Form Field (No Warning on Linter)

See merge request mbugroup/lti-web-client!341
2026-03-06 04:47:39 +00:00
rstubryan 37bc7a85e5 refactor(FE): Add depletion product handling in inventory adjustment
forms
2026-03-06 10:52:59 +07:00
rstubryan 667eb41eb2 refactor(FE): Refactor toggle logic for clarity in useModal 2026-03-06 10:08:13 +07:00
rstubryan e64b55e527 refactor(FE): Fix conditional call to onBackdropClick in Drawer
component
2026-03-06 10:00:25 +07:00
rstubryan 9710998dc6 refactor(FE): Handle null or undefined values in FinanceDetail component 2026-03-06 09:57:30 +07:00
rstubryan ca0b216ba0 refactor(FE): Handle null transaction_type and fix useEffect dependency 2026-03-06 09:53:57 +07:00
rstubryan 9ff6f3a35d refactor(FE): Refactor form components to improve state handling 2026-03-05 15:59:32 +07:00
rstubryan 333dd01f92 refactor(FE): Fix dependency array in useMemo for SalesClosingTable 2026-03-05 15:33:50 +07:00
rstubryan 75f765ee69 chore(FE): Add setTableState to useEffect dependency array 2026-03-05 15:05:17 +07:00
rstubryan 945bdb8b27 refactor(FE): Refactor formik field value setter in WarehousesTable 2026-03-05 15:02:00 +07:00
rstubryan 77eae32a3d refactor(FE): Refactor Formik field updates to use setFieldValue 2026-03-05 15:00:20 +07:00
rstubryan a5ebc6d1ae refactor(FE): Fix dependency arrays and improve error handling in
purchase components
2026-03-05 14:17:42 +07:00
rstubryan 15c7452d7b chore(FE): Fix missing dependency in useEffect hook 2026-03-05 14:15:41 +07:00
rstubryan 5dac900a1a refactor(FE): Refactor date filter state management in UniformityTable 2026-03-05 14:11:58 +07:00
rstubryan 4b49cd18f5 refactor(FE): Refactor form handlers to use consistent formik utilities 2026-03-05 13:45:01 +07:00
rstubryan a4cb4e202b refactor(FE): Fix dependency arrays and refactor setFieldValue usage 2026-03-05 13:36:43 +07:00
rstubryan 4a69eef294 fix(FE): Add handler to open filter modal and trigger form validation 2026-03-05 12:03:54 +07:00
rstubryan 2de6636bbf refactor(FE): Refactor tab actions to use memoized components 2026-03-05 11:59:27 +07:00
rstubryan a7951b6c28 refactor(FE): Fix missing dependencies in UniformityTable effect hooks 2026-03-05 11:47:16 +07:00
rstubryan 03baba40a6 refactor(FE): Remove unused params argument from
generateReportExpensePDF
2026-03-05 11:41:43 +07:00
rstubryan 96ef6f8496 refactor(FE): Refactor tab actions into a memoized component 2026-03-05 11:40:32 +07:00
rstubryan 94ab48d3f6 refactor(FE): Refactor tab actions to use memoized component 2026-03-05 11:21:56 +07:00
rstubryan ea88c3ce8e refactor(FE): Refactor tab actions to use memoized component 2026-03-05 11:10:36 +07:00
rstubryan 267ef9d812 refactor(FE): Refactor CustomerPaymentTab to use filterParams instead of
formik values
2026-03-05 11:01:52 +07:00
rstubryan b5fc1d4310 refactor(FE): Refactor tab actions to use memoized component 2026-03-05 10:57:13 +07:00
rstubryan c98e7d8cb3 refactor(FE): Fix population check to ensure proper boolean evaluation 2026-03-05 10:24:39 +07:00
rstubryan 1acbc91cfe refactor(FE): Reset dependent fields when location or project flock
changes
2026-03-05 10:19:30 +07:00
rstubryan 807041834b refactor(FE): Refactor formik field updates to use destructured methods 2026-03-05 09:54:50 +07:00
rstubryan 4de21561b3 refactor(FE): Refactor delivery order value initialization logic 2026-03-05 09:41:25 +07:00
rstubryan 1938f6cbda refactor(FE): Refactor DeliveryOrderProductTable to support delivery
order rendering
2026-03-04 17:13:30 +07:00
rstubryan f4a522fc0c refactor(FE): Refactor form field updates to use destructured Formik
methods
2026-03-04 16:48:21 +07:00
rstubryan 7ae04b3f3e refactor(FE): Refactor DashboardProduction callbacks for memoization 2026-03-04 14:12:45 +07:00
rstubryan b786acf71a chore(FE): Add setTableState to useEffect dependency arrays 2026-03-04 14:11:17 +07:00
rstubryan bb28ae8613 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into dev/restu 2026-03-04 11:59:06 +07:00
rstubryan 080592ff01 chore(FE): Remove unused variables and imports across components 2026-03-04 11:58:35 +07:00
Rivaldi A N S 6d41203a5e Merge branch 'feat/global-search-store' into 'development'
[FEAT/FE] Add Global Search Store and Filter for Each Table Index (All Module)

See merge request mbugroup/lti-web-client!340
2026-03-04 04:44:27 +00:00
rstubryan 89d7d3ef91 refactor(FE): Format imports in PurchaseTable.tsx 2026-03-04 11:07:30 +07:00
rstubryan 18ebf75aa7 feat(FE): Integrate UI store and pathname handling in table components 2026-03-04 11:06:53 +07:00
rstubryan 6e7dfebacc feat(FE): Integrate UI store for table state and search handling 2026-03-04 10:56:35 +07:00
rstubryan 4b93cb4589 feat(FE): Integrate UI store state with InventoryProductTable 2026-03-04 10:51:51 +07:00
rstubryan 58f1ab82c7 refactor(FE): Refactor long lines for readability in MovementTable 2026-03-04 10:45:15 +07:00
rstubryan 1fb9687142 feat(FE): Add filter functionality to inventory tables 2026-03-04 10:44:22 +07:00
rstubryan 4f6d71f1f4 refactor(FE): Refactor payload creation in
PurchaseOrderAcceptApprovalForm
2026-03-04 10:20:50 +07:00
rstubryan d502ec707c refactor(FE): Move error message above form actions in
InventoryAdjustmentForm
2026-03-04 09:36:37 +07:00
rstubryan fa86f488e1 refactor(FE): Standardize search input placeholders to "Search" 2026-03-03 14:19:52 +07:00
rstubryan 5e5400f56b feat(FE): Add advanced filtering capabilities to master data tables 2026-03-03 14:03:29 +07:00
rstubryan 741884ac29 feat(FE): Add filter schemas and types for master data components 2026-03-03 14:02:06 +07:00
rstubryan 4e278c5687 refactor(FE): Integrate UI store and pathname sync in master-data tables 2026-03-03 10:59:26 +07:00
rstubryan 3d2e40518b refactor(FE): Add table state management with path grouping logic 2026-03-03 10:33:03 +07:00
Rivaldi A N S cbab7f52f2 Merge branch 'dev/hotfix/restu' into 'development'
[HOTFIX/FE] Fix Constant Value of Adjustment Stock (Recording Depletion In)

See merge request mbugroup/lti-web-client!339
2026-03-03 02:50:52 +00:00
rstubryan ceb316d3da refactor(FE): Refactor subtype label mapping and fix depletion subtype
value
2026-03-03 09:15:57 +07:00
Rivaldi A N S 9ea152aef9 Merge branch 'hotfix/adjustment-stock-api-usage' into 'development'
[HOTFIX/FE] Fix Inventory AdjustmentForm using Product API Instead of Product Warehouse API

See merge request mbugroup/lti-web-client!338
2026-03-02 08:58:16 +00:00
rstubryan 910ea85b62 refactor(FE): Refactor InventoryAdjustmentForm to simplify product
handling
2026-03-02 15:24:14 +07:00
rstubryan 968243c370 refactor(FE): Refactor tab actions store to use slice pattern 2026-03-02 14:44:20 +07:00
Rivaldi A N S f1ba577a97 Merge branch 'fix/master-data-product-nonstock' into 'development'
[FIX/FE] Adjustment Product and Nonstock Match with FIFO Stock V2

See merge request mbugroup/lti-web-client!337
2026-03-02 07:33:43 +00:00
rstubryan c6b906a28e refactor(FE): Fix loading state for flag and sub-flag dropdowns 2026-03-02 14:12:42 +07:00
rstubryan eafcfd2f28 refactor(FE): Fix null check for product_flag_mapping in ProductForm 2026-03-02 14:06:12 +07:00
rstubryan 0e5d38f75c refactor(FE): Update field name from 'isExpedition' to 'flags' in
handler
2026-03-02 13:57:56 +07:00
rstubryan f2b59ded3c feat(FE): Add skeleton components for master data tables 2026-03-02 13:50:25 +07:00
rstubryan 1341b1ff53 refactor(FE): Add skeleton loaders for inventory tables 2026-03-02 13:31:23 +07:00
rstubryan 9c4c750664 refactor(FE): Refactor table skeleton components for consistency 2026-03-02 12:10:06 +07:00
rstubryan d3501e5f3d refactor(FE): Add skeleton loaders for ProjectFlock and TransferToLaying
tables
2026-03-02 11:56:27 +07:00
rstubryan d96388e5f4 refactor(FE): Rename and update import for UniformityTableFilter module 2026-03-02 11:42:34 +07:00
rstubryan 749b7d6f1a refactor(FE): Refactor UniformityTable to improve loading and empty
states
2026-03-02 11:34:27 +07:00
rstubryan aadf10b8b9 refactor(FE): Refactor master-data pages to simplify component rendering 2026-03-02 11:17:54 +07:00
rstubryan 7db6ae4077 refactor(FE): Refactor NonstocksTable to use Popover for row actions 2026-03-02 10:47:17 +07:00
rstubryan 7eaf6b7a3a refactor(FE): Refactor ProductTable and RowOptionsMenu for improved
clarity
2026-03-02 10:42:34 +07:00
rstubryan 8397d76171 refactor(FE): Add fallback for product flag mapping on constants error 2026-03-02 10:15:53 +07:00
rstubryan 56d4b8a5c9 refactor(FE): Update ProductFlagMapping types and related references 2026-03-02 10:15:06 +07:00
rstubryan ef9d820c0d refactor(FE): Refactor ProductForm to fetch constants via SWR 2026-03-02 10:06:06 +07:00
rstubryan 4e3c6736ab refactor(FE): Rename "Sub Flags" header to "Kategori Flags" 2026-03-02 09:58:01 +07:00
rstubryan aa1ef7a559 feat(FE): Add constants transformation utilities and API service 2026-03-02 09:57:21 +07:00
rstubryan 04b5a7bd4d refactor(FE): Update label in NonstockForm to 'Flags Ekspedisi' 2026-02-27 15:42:24 +07:00
rstubryan 3aec412599 refactor(FE): Update label text in NonstockForm RadioGroup 2026-02-27 15:38:47 +07:00
rstubryan 80a94c48c3 refactor(FE): Format product prices using formatCurrency helper 2026-02-27 15:38:11 +07:00
rstubryan 9bd4a73a90 refactor(FE): Refactor flags field to boolean and update form handling 2026-02-27 15:36:44 +07:00
rstubryan d1c6fe8fb4 refactor(FE): Add conditional validation for sub_flags in
ProductForm.schema
2026-02-27 15:03:09 +07:00
rstubryan a4378ebd04 refactor(FE): Refactor product flags to support single flag and
sub-flags
2026-02-27 14:57:45 +07:00
rstubryan 16f2f2bc06 feat(FE): Add PRODUCT_FLAG_MAPPING with flags, sub-flags, and mappings 2026-02-27 14:08:17 +07:00
rstubryan 64843a36ab refactor(FE): Refactor date input components for consistency and layout 2026-02-27 13:34:51 +07:00
rstubryan 396a5ab5ba refactor(FE): Rename and update FinanceTableFilter schema import path 2026-02-27 13:12:12 +07:00
rstubryan 9f4c041ec8 refactor(FE): Update FinanceTable layout and conditional styling 2026-02-27 11:27:51 +07:00
rstubryan 5e3d2273d1 refactor(FE): Refactor RowOptionsMenu to use PopoverButton and
PopoverContent
2026-02-27 11:25:37 +07:00
rstubryan 0b01eefe20 refactor(FE): Update button labels for clarity in FinanceTable 2026-02-27 11:23:06 +07:00
rstubryan 43045b3f8b Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into dev/restu 2026-02-27 11:21:34 +07:00
rstubryan d3ce60d3ba refactor(FE): Refactor FinanceTable and simplify Finance page structure 2026-02-27 11:14:13 +07:00
Rivaldi A N S 8c7577dcc5 Merge branch 'fix/adjustment-stock-and-ui-related' into 'development'
[FIX/FE] Refactor Adjustment Stock with Latest FIFO Stock and Adjustment UI (Production, Inventory, Pembelian, Penjualan, Biaya, Closing)

See merge request mbugroup/lti-web-client!336
2026-02-27 04:02:05 +00:00
rstubryan da3cadc37d Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into fix/adjustment-stock-and-ui-related 2026-02-27 10:28:35 +07:00
rstubryan 2e6aa1b83a refactor(FE): Filter out excluded product flags in product options 2026-02-27 10:04:54 +07:00
rstubryan 8811976f53 chore(FE): Remove redundant comments in InventoryAdjustmentForm 2026-02-27 09:30:10 +07:00
rstubryan 9fb65bdacd feat(FE): Validate quantity against available stock 2026-02-27 09:29:33 +07:00
Adnan Zahir 53e018aece Merge branch 'staging' into 'production'
refactor(FE): Add tab state management and skeleton for

See merge request mbugroup/lti-web-client!335
2026-02-26 16:37:04 +07:00
rstubryan 6f6f54571f refactor(FE): Reset transaction subtype when product changes for
RECORDING
2026-02-26 16:20:00 +07:00
rstubryan 3099588141 refactor(FE): Filter transaction subtypes based on selected product
flags
2026-02-26 16:10:19 +07:00
rstubryan 47ee911852 feat(FE): Add stock availability badge to product dropdown 2026-02-26 15:56:31 +07:00
rstubryan b4d0ed1537 refactor(FE): Refactor product options handling in
InventoryAdjustmentForm
2026-02-26 15:39:49 +07:00
rstubryan 36f2368e95 refactor(FE): Refactor product selection to use ProductWarehouse API 2026-02-26 15:31:43 +07:00
rstubryan a4d5cbb117 refactor(FE): Simplify conditional formatting in InventoryAdjustmentForm 2026-02-26 15:12:19 +07:00
rstubryan c926a81756 refactor(FE): Update transaction subtype handling and labels 2026-02-26 15:11:39 +07:00
rstubryan 2476b6a4b4 refactor(FE): Format prices and totals as currency in
InventoryAdjustmentTable
2026-02-26 14:52:44 +07:00
rstubryan 01c1843fd5 refactor(FE): Refactor MovementTable to use Popover for row actions 2026-02-26 14:37:34 +07:00
rstubryan f86498e350 refactor(FE): Refactor InventoryProductTable to use Popover for row
options
2026-02-26 14:29:27 +07:00
rstubryan 5cd24f2c46 refactor(FE): Fix form error list visibility and field touch handling 2026-02-26 14:12:11 +07:00
rstubryan da0be9cb52 refactor(FE): Update input components to adjust spacing and text size 2026-02-26 14:11:33 +07:00
rstubryan da1cdfb59e refactor(FE): Refactor transaction type handling with useEffect 2026-02-26 13:58:21 +07:00
rstubryan a991150262 refactor(FE): Refactor InventoryAdjustmentForm layout for better
responsiveness
2026-02-26 13:32:52 +07:00
rstubryan ee49c91fba refactor(FE): Add type annotation for inventory adjustment payload 2026-02-26 12:08:36 +07:00
rstubryan 75463326e3 refactor(FE): Refactor InventoryAdjustmentForm to remove 'edit' type
handling
2026-02-26 12:07:14 +07:00
rstubryan e98c49ac5a refactor(FE): Update columns in InventoryAdjustmentTable 2026-02-26 11:48:27 +07:00
rstubryan aeeb0b721c refactor(FE): Refactor InventoryAdjustmentTable for improved readability 2026-02-26 11:31:17 +07:00
Rivaldi A N S b14bc00af4 Merge branch 'fix/fe/return-to-logout' into 'development'
[FIX/FE] add return fe cors

See merge request mbugroup/lti-web-client!334
2026-02-26 04:27:56 +00:00
ragilap e2a4088e77 [FEAT/BE] add return fe cors 2026-02-26 11:19:47 +07:00
rstubryan ebe80358ee refactor(FE): Remove unused import isResponseSuccess from
InventoryAdjustmentForm
2026-02-26 11:11:51 +07:00
rstubryan 9d4e9f6318 refactor(FE): Refactor InventoryAdjustmentForm to use useSelect for
Kandang
2026-02-26 11:09:13 +07:00
rstubryan e5007a285a refactor(FE): Refactor InventoryAdjustmentForm to improve state
management
2026-02-26 10:38:41 +07:00
rstubryan da82c704d5 refactor(FE): Fix validation message formatting in
InventoryAdjustmentForm
2026-02-26 10:12:48 +07:00
rstubryan 88b9c890e5 refactor(FE): Refactor inventory adjustment form 2026-02-26 10:10:59 +07:00
rstubryan 5a67901722 feat(FE): Add transaction type and subtype options to constants 2026-02-26 09:11:05 +07:00
rstubryan 0031a65f97 refactor(FE): Ensure filter modal closes on reset across components 2026-02-25 16:30:31 +07:00
rstubryan a89e83af29 refactor(FE): Fix multiline formatting for isError conditions 2026-02-25 15:57:25 +07:00
rstubryan a75d84556a refactor(FE): Refactor date validation to use shared state and cleanup 2026-02-25 15:56:12 +07:00
rstubryan 0af7b172a0 refactor(FE): Refactor PurchaseTable to use Popover for row options menu 2026-02-25 12:08:31 +07:00
rstubryan 8be33b230b refactor(FE): Refactor row options menu to use popover components 2026-02-25 11:59:17 +07:00
rstubryan 4fda2f661a refactor(FE): Remove unnecessary padding and margin classes in
components
2026-02-25 11:49:41 +07:00
rstubryan 22b1102454 refactor(FE): Refactor ExpensesTable to use ExpensesFilterModal 2026-02-25 11:40:42 +07:00
rstubryan e2e64f093f refactor(FE): Refactor TransferToLayingFilterModal to use schema
validation
2026-02-25 11:02:26 +07:00
rstubryan 90942b41b9 refactor(FE): Fix formatting of disabled condition in RecordingTable
button
2026-02-25 10:53:32 +07:00
rstubryan 93a2d99b7f refactor(FE): Disable filter button if kandang_id is not selected 2026-02-25 10:52:03 +07:00
rstubryan dae9a24a7c refactor(FE): Refactor array formatting and improve code readability 2026-02-25 10:41:34 +07:00
rstubryan f701ab0d91 refactor(FE): Replace active filter count logic with ButtonFilter
component
2026-02-25 10:39:14 +07:00
rstubryan 47a2439777 feat(FE): Add support for grouped fields in ButtonFilter active count
calculation
2026-02-25 10:07:26 +07:00
rstubryan cce84a3a6f refactor(FE): Refactor ButtonFilter to support excluded fields with
useMemo
2026-02-25 09:46:19 +07:00
Rivaldi A N S f92622cc22 Merge branch 'fix/adjustment-production-module' into 'development'
[FIX/FE] Adjustment Production Module (Recording & Uniformity)

See merge request mbugroup/lti-web-client!333
2026-02-25 02:32:21 +00:00
rstubryan f0041ca938 refactor(FE): Filter inactive kandangs in UniformityForm options 2026-02-24 21:05:22 +07:00
rstubryan 6566b881b2 refactor(FE): Use formatTitleCase for category text in StatusBadge 2026-02-24 21:02:56 +07:00
rstubryan 1a2e38568b refactor(FE): Remove unused page size selector and related logic 2026-02-24 15:46:32 +07:00
rstubryan ced3970aae refactor(FE): Add padding to RecordingTableSkeleton container class 2026-02-24 15:38:19 +07:00
rstubryan 9de31c991d refactor(FE): Refactor approval checks for readability 2026-02-24 15:34:11 +07:00
rstubryan bdca10e0ac refactor(FE): Handle rejected recordings in selection logic 2026-02-24 15:31:22 +07:00
rstubryan 9a5e2987d5 refactor(FE): Conditionally load data based on filter modal state 2026-02-24 15:22:06 +07:00
rstubryan a5b4deaac4 refactor(FE): Refactor RecordingTable layout for improved readability 2026-02-24 15:13:37 +07:00
rstubryan 82953f4c9c Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into dev/restu 2026-02-24 14:48:34 +07:00
rstubryan 509fc5476d refactor(FE): Refactor recording table and add filter modal 2026-02-24 14:48:09 +07:00
Rivaldi A N S 6a10849a84 Merge branch 'fix/adjustment-pf-report-penjualan' into 'development'
[FIX/FE] Adjustment Project Flock Related, Penjualan Calculation (Both SO/DO) and Report Filter Display Issue

See merge request mbugroup/lti-web-client!332
2026-02-24 03:24:42 +00:00
rstubryan 50424a25fc refactor(FE): Remove redundant transformations and validations in
schemas
2026-02-23 16:05:12 +07:00
rstubryan 35b09b514f refactor(FE): Refactor form field change handlers for real-time
calculations
2026-02-23 15:30:54 +07:00
rstubryan 81e4e1fc6a refactor(FE): Update validation rules for SalesOrderProduct schema 2026-02-23 14:12:44 +07:00
rstubryan 62c9ab014d refactor(FE): Add period filter to ProjectFlockTable 2026-02-23 13:51:32 +07:00
rstubryan ba28d64562 refactor(FE): Format type definition for readability 2026-02-23 13:40:00 +07:00
rstubryan 75ee058818 feat(FE): Add filter functionality to ProjectFlockTable 2026-02-23 13:38:47 +07:00
rstubryan 755bddc74c refactor(FE): Fix logic for checking active projects in the same kandang
from the validation logic.
2026-02-23 12:10:44 +07:00
rstubryan 08aa1900a8 feat(FE): Add validation for disabling close button in
ProjectFlockDetail
2026-02-23 11:55:07 +07:00
rstubryan 7e1166b5e8 refactor(FE): Refactor tab actions store to use a unified implementation 2026-02-23 11:05:11 +07:00
rstubryan 75e9b06a83 refactor(FE): Set default value for show_unrecorded to false 2026-02-23 10:27:34 +07:00
Adnan Zahir ca58e19a48 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!331
2026-02-23 09:32:40 +07:00
Rivaldi A N S ac2d83a666 Merge branch 'fix/cleanup-code' into 'development'
[FIX/FE] Partial Remove Issue Warning on Build (1/2)

See merge request mbugroup/lti-web-client!330
2026-02-23 02:25:50 +00:00
rstubryan 03e0cebe35 refactor(FE): Fix formatting for array dependencies and className
conditions
2026-02-20 14:42:46 +07:00
rstubryan 1cc0e16c01 refactor(FE): Replace ButtonFilter with custom Filter button 2026-02-20 14:41:50 +07:00
rstubryan 1f2f3acebb refactor(FE): Remove unused imports and redundant code 2026-02-20 14:17:26 +07:00
Rivaldi A N S de0f9ae985 Merge branch 'fix/uniformity-ttl-project-flock-issue' into 'development'
[FIX/FE] Fix Isssue on Uniformity (Week Calculation), Project Flock (Modal Position), Transfer To Laying (Copywriting)

See merge request mbugroup/lti-web-client!329
2026-02-20 03:36:15 +00:00
rstubryan a0e79168b2 refactor(FE): Refactor setClosingLoading to use single-line syntax 2026-02-20 10:25:30 +07:00
rstubryan 797f88fe15 feat(FE): Add project flock closing modal and zustand store 2026-02-20 10:23:47 +07:00
rstubryan 4c3e7c615f refactor(FE): Refactor conditional text formatting in modal component 2026-02-20 10:12:06 +07:00
rstubryan b35b6c2ab8 feat(FE): Add submittedActionType state to track modal action type 2026-02-20 10:11:16 +07:00
Adnan Zahir 0971e6ddeb Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!328
2026-02-20 09:53:46 +07:00
rstubryan bbbd767cf2 refactor(FE): Fix week calculation logic in UniformityForm 2026-02-20 09:21:42 +07:00
Rivaldi A N S 3e30dcb04e Merge branch 'fix/closing-project-flock-recording-issue' into 'development'
[FIX/FE] Adjustment Closing Related (Closing Report, Closing Detail and Closing Table), Project Flock Detail (Form, Chickin), Recording Table

See merge request mbugroup/lti-web-client!327
2026-02-19 09:45:18 +00:00
rstubryan 1a137e7500 refactor(FE): Normalize status keys to uppercase in status utilities 2026-02-19 15:37:46 +07:00
rstubryan 3be6d5bb26 refactor(FE): Update status mappings for "CREATED" to "Pengajuan" 2026-02-19 15:35:08 +07:00
rstubryan e22f95cc58 refactor(FE): Remove unused variable approval.step_name in
RecordingTable
2026-02-19 15:28:27 +07:00
rstubryan 6ac903313c refactor(FE): Refactor chickin approval modal logic into Zustand store 2026-02-19 15:22:28 +07:00
rstubryan a4ff92520a refactor(FE): Update toast message for Project Flock approval/rejection 2026-02-19 14:50:43 +07:00
rstubryan 608cf4cbe7 feat(FE): Add StatusBadge to display project status in ClosingsTable 2026-02-19 14:41:21 +07:00
rstubryan 60e360537e refactor(FE): Refactor ClosingsTable header for improved styling 2026-02-19 14:37:20 +07:00
rstubryan e9784bd5ed refactor(FE): Refactor ClosingsTable component and update styles 2026-02-19 14:33:35 +07:00
rstubryan 4f018eb2b1 feat(FE): Add filter modal and skeleton components for ClosingsTable 2026-02-19 14:18:22 +07:00
rstubryan 40b3d779bc refactor(FE): Update column header and adjust table margin 2026-02-19 13:52:32 +07:00
rstubryan 1bdf413650 feat(FE): Add badge display for category columns in tables 2026-02-19 13:33:11 +07:00
rstubryan 495b1b2869 refactor(FE):Add HPP Amount column to daily marketing export 2026-02-19 12:18:27 +07:00
rstubryan a231140bc0 refactor(FE): Refactor ProductionDataClosingTab to use Card component 2026-02-19 12:02:04 +07:00
rstubryan a0af934002 feat(FE): Add headings and improve layout for financial tables 2026-02-19 11:52:57 +07:00
rstubryan 82975219a8 refactor(FE): Update border styles for ClosingDetailTabs and
ClosingKandangList
2026-02-19 11:43:46 +07:00
rstubryan 60ae670f24 refactor(FE): Refactor UI and improve conditional rendering in closing
pages
2026-02-19 11:38:34 +07:00
rstubryan 7d79b6b957 refactor(FE): Refactor table and tab styles for consistent spacing and
layout
2026-02-19 11:27:24 +07:00
rstubryan 8a1e0f080f refactor(FE): Refactor table components for consistent styling and
cleanup
2026-02-19 11:14:39 +07:00
rstubryan c3a69bc66a refactor(FE): Add Icon component and update table styles 2026-02-19 10:55:07 +07:00
rstubryan 4c1f11d859 refactor(FE): Update table column headers from '#' to 'No' 2026-02-19 10:50:52 +07:00
rstubryan 350ff0fbbe refactor(FE): Simplify headerRowClassName formatting in tables 2026-02-19 10:46:03 +07:00
rstubryan 4c70ec7cab refactor(FE): Refactor table components to improve styling and structure 2026-02-19 10:43:37 +07:00
rstubryan 944db8dba7 refactor(FE): Refactor Card and SapronakClosingSkeleton components for
readability
2026-02-19 10:15:20 +07:00
rstubryan befc1c1217 refactor(FE): Refactor skeleton components to remove default columns 2026-02-19 10:14:28 +07:00
rstubryan 8fe19feaac feat(FE): Add skeleton components for closing pages 2026-02-19 10:03:25 +07:00
rstubryan 9c953ca382 refactor(FE): Fix incorrect import and component usage in
SapronakClosingTab
2026-02-19 09:37:54 +07:00
rstubryan c53430fa1f refactor(FE): Organize Sapronak tables into a dedicated folder 2026-02-19 09:35:42 +07:00
rstubryan 1fe722cb81 refactor(FE): Refactor code formatting for consistency and readability 2026-02-19 09:33:31 +07:00
rstubryan d9bd73d8c1 refactor(FE): Refactor sales data fetching and component structure 2026-02-19 09:32:33 +07:00
rstubryan 0235494d46 refactor(FE): Refactor HPP Expedition handling in ClosingDetailPage 2026-02-19 09:29:01 +07:00
rstubryan 32354e3c2d refactor(FE): Adjust padding on tab header wrapper in ClosingDetailTabs 2026-02-18 16:32:26 +07:00
rstubryan 14e1c59a69 refactor(FE): Refactor ClosingDetail component to use tab store 2026-02-18 16:28:56 +07:00
rstubryan 42cc0f2661 refactor(FE): Refactor component and file names for consistency 2026-02-18 16:15:27 +07:00
rstubryan 2f5d518e15 refactor(FE): Move table components to a shared "table" directory 2026-02-18 15:43:52 +07:00
rstubryan d085b18788 refactor(FE): Refactor folder structure for closing-related components 2026-02-18 15:40:06 +07:00
Rivaldi A N S d68bedf5ce Merge branch 'fix/refactor-project-flock-detail' into 'development'
[FIX/FE] Refactor Project Flock Detail UI

See merge request mbugroup/lti-web-client!326
2026-02-18 08:21:57 +00:00
rstubryan 2169c0ea62 refactor(FE): Update StatusBadge color and text in ChickinForm 2026-02-18 15:00:26 +07:00
rstubryan 02165df89c refactor(FE): Update status badge text to use English labels 2026-02-18 14:50:11 +07:00
rstubryan 15289951e6 refactor(FE): Remove unused CSS classes from table components 2026-02-18 14:42:41 +07:00
rstubryan 62674044e7 refactor(FE): Replace Badge with StatusBadge in ProjectFlockDetail 2026-02-18 14:33:28 +07:00
rstubryan e94967ea4c refactor(FE): Adjust grid column layout based on selectedKandang status 2026-02-18 14:28:55 +07:00
rstubryan ed576fc8eb feat(FE): Improve empty state handling and add "Unclose Flock"
functionality
2026-02-18 13:49:02 +07:00
rstubryan d4c6a05c0c refactor(FE): Update button behavior based on kandang status 2026-02-18 13:21:29 +07:00
rstubryan da27f4c581 refactor(FE): Refactor status badge logic in ProjectFlockClosingForm 2026-02-18 13:15:06 +07:00
rstubryan 9d6cc90162 refactor(FE): Update table columns and improve UI for Project Flock
pages
2026-02-18 11:52:30 +07:00
rstubryan 512ccddfc7 refactor(FE): Refactor ChickinForm and ProjectFlockClosingForm
components
2026-02-18 09:59:50 +07:00
Rivaldi A N S f5b16b68e9 Merge branch 'dev/hotfix/restu' into 'development'
[HOTFIX/FE] Refactor fetching logic useSelect on Depletion (Recording)

See merge request mbugroup/lti-web-client!325
2026-02-15 03:11:31 +00:00
rstubryan e8e4f7b877 refactor(FE): Simplify product filtering logic in RecordingForm 2026-02-15 08:47:07 +07:00
Rivaldi A N S b6edd8f10c Merge branch 'feat/refactor-report-module-ui' into 'development'
[FEAT/FE] Refactor UI on Report Module and Additional Adjustment (Project Flock, Product Stock, Marketing)

See merge request mbugroup/lti-web-client!324
2026-02-13 03:59:03 +00:00
rstubryan ec3a0367dd refactor(FE): Hide delete button if only one item remains in table 2026-02-13 10:37:12 +07:00
rstubryan e9da5210ad refactor(FE): Simplify type definition for ReportExpenseColumn 2026-02-13 10:22:13 +07:00
rstubryan 67f2a80f23 refactor(FE): Refactor expense report page to use tab-based layout 2026-02-13 10:19:09 +07:00
rstubryan ceb594a4cc refactor(FE): Rename and update paths for ProductionResult components 2026-02-13 09:55:22 +07:00
rstubryan d312da4c66 refactor(FE): Refactor dropdown and export button components 2026-02-13 09:53:33 +07:00
rstubryan 3a676723e4 refactor(FE): Refactor table class names in DailyMarketingTab 2026-02-13 09:42:04 +07:00
rstubryan 684f67593f refactor(FE): Refactor SelectInput styles for improved readability 2026-02-13 09:32:45 +07:00
rstubryan d5962f94a1 refactor(FE): Refactor production result filter to use OptionType 2026-02-13 09:29:37 +07:00
rstubryan 5c00893ea3 refactor(FE): Refactor production result components and improve UI 2026-02-13 09:24:42 +07:00
rstubryan 211622c7b0 refactor(FE): Format import statements in report-tab.store.ts 2026-02-12 16:19:40 +07:00
rstubryan dbb523c710 refactor(FE): Refactor tab store to use a unified ReportTabStore 2026-02-12 16:16:40 +07:00
rstubryan 6aae18df54 refactor(FE): Update import paths for finance and marketing tab stores 2026-02-12 15:49:26 +07:00
rstubryan cb171118ee refactor(FE): Restrict row selection to specific approval criteria 2026-02-12 15:32:11 +07:00
rstubryan 45ac8348fe feat(FE): Add "Stock Akhir" column to StockLogTable 2026-02-12 15:23:17 +07:00
rstubryan 5d92e6774e feat(FE): Add stock field to StockLog type 2026-02-12 15:14:00 +07:00
rstubryan 6595ff7a6e refactor(FE): Add function to export production results to Excel 2026-02-12 15:03:24 +07:00
rstubryan dc4e945a35 refactor(FE): Refactor table column definitions to remove unused row
parameter
2026-02-12 14:50:19 +07:00
rstubryan b154b478bc refactor(FE): Refactor production result components structure 2026-02-12 14:15:56 +07:00
rstubryan 510573e66f refactor(FE): Add Excel export functionality for daily marketing report 2026-02-12 13:55:31 +07:00
rstubryan dbcf469123 refactor(FE): Remove DailyMarketingsTable component and refactor related
files
2026-02-12 13:44:22 +07:00
rstubryan 325fb373a8 refactor(FE): Rename components for clarity 2026-02-12 13:19:16 +07:00
rstubryan 4b6a8b2773 refactor(FE): Refactor file names for consistency in marketing report
components
2026-02-12 11:45:50 +07:00
rstubryan 5e4619fac7 feat(FE): Add DailyMarketingReportFilter and
DailyMarketingReportSkeleton components
2026-02-12 11:38:46 +07:00
rstubryan 43d26b4833 refactor(FE): Refactor marketing report components and add HPP filter 2026-02-12 11:16:26 +07:00
rstubryan 6d2855d117 refactor(FE): Add zustand store for marketing tab actions 2026-02-12 11:15:42 +07:00
Adnan Zahir 25fbf95062 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!323
2026-02-12 11:06:11 +07:00
rstubryan ee53ea61cc refactor(FE): Fix missing dependency in useCallback hooks 2026-02-12 10:57:22 +07:00
rstubryan 322b519def refactor(FE): Refactor filter schema and form handling for
PurchasesPerSupplier
2026-02-12 10:55:40 +07:00
rstubryan e23b53d797 refactor(FE): Refactor CustomerPaymentTab to use StatusBadge component 2026-02-12 10:46:06 +07:00
rstubryan fd78ca6ac1 refactor(FE): Refactor CustomerPaymentTab to use Formik for filter
management
2026-02-12 10:28:36 +07:00
rstubryan 28dabcbeb6 refactor(FE): Refactor filter parameter keys to singular form 2026-02-12 09:52:21 +07:00
rstubryan 62dd1de150 refactor(FE): Reset form values on filter modal open and submit 2026-02-12 09:45:18 +07:00
rstubryan 166e95930b refactor(FE): Remove unused imports and cleanup comments 2026-02-12 09:35:24 +07:00
rstubryan 52d58d0921 refactor(FE): Refactor PurchasesPerSupplierTab to use Formik for filters 2026-02-11 16:44:10 +07:00
rstubryan 14d0dc590f refactor(FE): Make dropdown filters clearable in PurchasesPerSupplierTab 2026-02-11 16:17:15 +07:00
rstubryan ed781da372 refactor(FE): Change Tabs variant from 'lifted' to 'boxed' 2026-02-11 16:12:14 +07:00
rstubryan 4e5745d237 refactor(FE): Add tab state management and skeleton for
PurchasesPerSupplierTab
2026-02-11 15:53:32 +07:00
Rivaldi A N S b03ef4923e Merge branch 'hotfix/purchase-and-project-flock-form' into 'development'
[HOTFIX/FE] Refactor Purchase (Staff & Receipt/Receive) and Project Flock Form (Modal)

See merge request mbugroup/lti-web-client!322
2026-02-11 07:29:22 +00:00
Rivaldi A N S d7486e8b8a Merge branch 'fix/refactor-native-pdf-renderer' into 'development'
[FIX/FE] Refactor Native PDF Renderer to Component Based

See merge request mbugroup/lti-web-client!321
2026-02-11 07:28:43 +00:00
rstubryan 498602a2c9 refactor(FE): Refactor input components to use consistent color
variables
2026-02-11 14:19:52 +07:00
rstubryan 1b4d373fea refactor(FE): Improve disabled and read-only states for input components 2026-02-11 13:54:48 +07:00
rstubryan 4215b0ea7d feat(FE): Add success modal and state management for ProjectFlock 2026-02-11 13:44:00 +07:00
rstubryan c3dee6b292 feat(FE): Add Zustand store for ProjectFlock management 2026-02-11 13:42:56 +07:00
rstubryan 3834982fca feat(FE): Add "has_chickin" property to disable quantity editing 2026-02-11 11:40:29 +07:00
rstubryan 539de03a5b refactor(FE): Update section width to use full width 2026-02-11 10:41:57 +07:00
rstubryan 0f1d2ce477 refactor(FE): Refactor PDF table components to simplify imports 2026-02-11 10:39:37 +07:00
rstubryan 70b63f7773 refactor(FE): Refactor PdfTable components to support generic data types 2026-02-11 10:38:51 +07:00
rstubryan 02d13efc25 refactor(FE): Refactor table column headers for clarity and consistency 2026-02-11 09:28:24 +07:00
rstubryan 1227b7639f refactor(FE): Refactor ProductionResultReportPDF to use reusable PDF
components
2026-02-10 16:52:52 +07:00
rstubryan 5593463eab refactor(FE): Refactor marketing report components into a dedicated
folder
2026-02-10 16:20:19 +07:00
rstubryan be7b2a0f93 refactor(FE): Refactor DailyMarketingReportPDF component for cleaner
structure
2026-02-10 16:06:11 +07:00
rstubryan 4c6ac6e8e1 refactor(FE): Refactor PdfStatusBadge to use a single style prop 2026-02-10 14:04:44 +07:00
rstubryan 5cc51c52d9 feat(FE): Add PdfPageNumber component for rendering page numbers 2026-02-10 14:02:53 +07:00
rstubryan 59eb781a22 refactor(FE): Refactor PDF components to support custom styles 2026-02-10 14:00:28 +07:00
rstubryan 2af83bed8a refactor(FE): Refactor getDetailData to remove unused parameters 2026-02-10 13:37:34 +07:00
rstubryan 4775c1e115 refactor(FE): Refactor HppPerKandang PDF generation logic and UI
renderer
2026-02-10 12:01:51 +07:00
rstubryan d0dea834c1 refactor(FE): Refactor HppPerKandang export logic to use ExcelJS 2026-02-10 11:54:15 +07:00
rstubryan def894e5f4 refactor(FE): Refactor PDF generation for purchases per supplier 2026-02-10 11:43:23 +07:00
rstubryan 4f9401ed34 refactor(FE): Refactor export logic for PurchasesPerSupplier report 2026-02-10 11:36:27 +07:00
rstubryan 80763acc53 refactor(FE): Add utility for PDF badge styles and integrate into
reports
2026-02-10 11:27:43 +07:00
Rivaldi A N S 5fb065de3e Merge branch 'feat/reusable-pdf-component' into 'development'
[FEAT/FE] Reusable PDF Component and Hotfix Penjualan

See merge request mbugroup/lti-web-client!320
2026-02-10 02:09:59 +00:00
rstubryan d6b9161500 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into feat/reusable-pdf-component 2026-02-10 09:01:15 +07:00
rstubryan bcc2070ed2 refactor(FE): Refactor DebtSupplierExportPDF to use reusable PDF
components
2026-02-09 21:50:35 +07:00
rstubryan e4e6e563c9 refactor(FE): Remove unused helper function formatTitleCaseGeneral 2026-02-09 17:07:00 +07:00
rstubryan efec9b6265 feat(FE): Add formatTitleCaseGeneral helper and update usage 2026-02-09 17:05:35 +07:00
rstubryan 4cf2f77265 fix(FE): Fix marketing type value logic in SalesOrderFormModal 2026-02-09 17:01:28 +07:00
rstubryan c86f0379b5 refactor(FE): Refactor CustomerPaymentExportPDF to use reusable PDF
components
2026-02-09 16:01:12 +07:00
rstubryan 606380460e feat(FE): Add PDF helper components for badges and typography 2026-02-09 15:58:28 +07:00
Rivaldi A N S a3bcabe5c2 Merge branch 'fix/remove-fcr-related' into 'development'
[FIX/FE] Remove FCR Related

See merge request mbugroup/lti-web-client!319
2026-02-09 08:58:26 +00:00
rstubryan 89ffad398f refactor(FE): Remove FCR-related links and permissions 2026-02-09 14:32:27 +07:00
rstubryan 35986aab56 refactor(FE): Remove FCR-related components and types 2026-02-09 14:28:02 +07:00
Rivaldi A N S 4717330bc8 Merge branch 'fix/adjustment-penjualan' into 'development'
[FIX/FE] Adjustment Penjualan UI and Data Fetch (2/2)

See merge request mbugroup/lti-web-client!318
2026-02-09 07:16:56 +00:00
rstubryan 291eee3bce refactor(FE): Add week field handling for marketing and sales order
forms
2026-02-09 14:06:43 +07:00
rstubryan e6a572ac17 refactor(FE): Add API call for updating delivery order on approval step
3
2026-02-09 13:31:03 +07:00
rstubryan bd5b614bf8 refactor(FE): Fix modal text logic for add_delivery action 2026-02-09 12:01:13 +07:00
rstubryan ba0753428d refactor(FE): Fix form reset and selection handling in
SalesOrderFormModal
2026-02-09 11:49:08 +07:00
rstubryan 862cf38f92 refactor(FE): Refactor DeliveryOrderProductTable to improve readability 2026-02-09 11:41:08 +07:00
rstubryan 1dc6ffca5c refactor(FE): Handle modal action to set step and selected delivery
product
2026-02-09 11:36:41 +07:00
rstubryan b7fd5d3569 refactor(FE): Add approval modal and handler for marketing approval 2026-02-09 11:25:19 +07:00
rstubryan 911136981a refactor(FE): Add clickable "Belum diisi" text for delivery forms 2026-02-09 11:23:49 +07:00
rstubryan 6cbe14b36e refactor(FE): Refactor SalesOrderProductTable to use renderTableContent
helper
2026-02-09 11:00:29 +07:00
rstubryan 80c79cc14b refactor(FE): Refactor DeliveryOrderProductTable to optimize conditional
rendering
2026-02-09 10:46:32 +07:00
rstubryan cb498b01d9 chore(FE): Refactor tables to remove unused props and imports 2026-02-09 10:26:23 +07:00
Rivaldi A N S cd95b1f8ff Merge branch 'fix/adjustment-penjualan' into 'development'
[FIX/FE] Adjustment Penjualan UI and Data Fetch

See merge request mbugroup/lti-web-client!317
2026-02-09 03:04:46 +00:00
rstubryan 60ace68dae refactor(FE): Remove FCR-related fields and functionality 2026-02-09 08:59:51 +07:00
Adnan Zahir b2f6c6c485 Merge branch 'staging' into 'production'
Staging

See merge request mbugroup/lti-web-client!316
2026-02-07 17:11:45 +07:00
rstubryan a8dce9da46 refactor(FE): Refactor table actions to be part of the "Value" column 2026-02-07 10:04:15 +07:00
rstubryan b85e47f601 refactor(FE): Add top border to table rows in product tables 2026-02-07 10:00:02 +07:00
rstubryan fc4a0a58e2 refactor(FE): Refactor tables to use Card component 2026-02-07 09:58:00 +07:00
rstubryan 039dfd529e refactor(FE): Increase max height of order form modals to 50vh 2026-02-07 09:33:58 +07:00
rstubryan 3b42709577 refactor(FE): Refactor modal action handling in order form modals 2026-02-07 09:32:34 +07:00
rstubryan 3dee5c1828 refactor(FE): Add reference number column to ExpensesTable 2026-02-07 09:29:05 +07:00
rstubryan 5ac958231a refactor(FE): Remove unused invoice download functionality from
PurchaseTable
2026-02-07 09:10:39 +07:00
rstubryan 54a6e7e247 refactor(FE): Refactor RecordingForm to simplify egg product filtering 2026-02-07 09:00:04 +07:00
rstubryan 4e80c1a703 refactor(FE): Fix warehouse name display in DeliveryOrderProductTable 2026-02-06 14:46:13 +07:00
rstubryan 9ee5e95d0b refactor(FE): Remove unused conditional rendering for step 3 2026-02-06 14:33:13 +07:00
rstubryan 3bacc59dc6 refactor(FE): Add condition to hide buttons when step number is 3 2026-02-06 14:32:30 +07:00
rstubryan 4d23929924 refactor(FE): Update approval logic and conditional rendering in
delivery forms
2026-02-06 14:20:52 +07:00
rstubryan c9a5a91970 refactor(FE): Update order number display logic in
DeliveryOrderFormModal
2026-02-06 14:20:10 +07:00
rstubryan 08d1447d11 refactor(FE): Update button label based on approval step number 2026-02-06 13:41:17 +07:00
rstubryan 304be4f432 feat(FE): Add support for displaying DO number in MarketingTable 2026-02-06 13:29:38 +07:00
rstubryan 5e9ce70320 feat(FE): Add "Ditolak" option to statusOptions in MarketingFilter 2026-02-06 13:21:33 +07:00
rstubryan 42088e51a8 refactor(FE): Refactor marketing filter to use unique customer options 2026-02-06 13:13:57 +07:00
rstubryan 9dc8f05534 feat: adjust penjualan calculation and delivery order logic 2026-02-06 10:55:38 +07:00
Adnan Zahir cc86151631 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!315
2026-02-06 10:39:39 +07:00
Rivaldi A N S e16fa9a167 Merge branch 'fix/project-flock' into 'development'
[FIX/FE] Project Flock

See merge request mbugroup/lti-web-client!314
2026-02-06 02:58:02 +00:00
ValdiANS 869110ad2e Merge branch 'development' into fix/project-flock 2026-02-06 09:51:20 +07:00
ValdiANS d415bbba82 feat: add getApprovalLineHistory method 2026-02-06 09:47:11 +07:00
ValdiANS 1ecca83339 feat: add getApprovalLineHistory method 2026-02-06 09:47:05 +07:00
ValdiANS a6c827bb40 feat: add PROJECT_FLOCK_KANDANGS in APPROVAL_WORKFLOWS 2026-02-06 09:46:51 +07:00
ValdiANS 968d9e1f2a fix: adjust ProjectFlockForm styling and create ProjectFlockFormConfirmationTable component 2026-02-06 09:46:37 +07:00
ValdiANS 7b9ba48204 fix: adjust ProjectFlockDetail styling and content 2026-02-06 09:46:00 +07:00
ValdiANS 6e2e9da1be chore: adjust ProjectFlockClosingForm styling 2026-02-06 09:45:38 +07:00
ValdiANS 980a5674e2 feat: create ProjectFlockConfirmationModal component 2026-02-06 09:45:07 +07:00
ValdiANS f5b9c52e71 chore: set chickin form scrollable 2026-02-06 09:44:56 +07:00
ValdiANS ade8fefe0d feat: auto scroll to AlertErrorList if AlertErrorList is showing 2026-02-06 09:44:33 +07:00
ValdiANS 6b54b49443 chore: adjust divider styling 2026-02-06 09:44:06 +07:00
ValdiANS 8fb16903f8 feat: add onClick prop and set text type to react node 2026-02-06 09:43:56 +07:00
ValdiANS f0637e2ce9 chore: add title prop 2026-02-06 09:43:34 +07:00
ValdiANS f6cf4a29ad feat: add ref prop to Alert 2026-02-06 09:43:27 +07:00
ValdiANS 66f017549c chore: use modal for project flock layout 2026-02-06 09:43:15 +07:00
ValdiANS db7219e261 chore: add shadow-bg class name 2026-02-06 09:42:45 +07:00
Rivaldi A N S ac6c77bb92 Merge branch 'dev/hotfix/restu' into 'development'
[HOTFIX/FE] Adjustment Param State on Customer Payment Tab

See merge request mbugroup/lti-web-client!313
2026-02-05 08:54:05 +00:00
rstubryan d5eeadc9a7 refactor(FE): Remove handleBlurField call on week change 2026-02-05 15:47:05 +07:00
rstubryan 70a9fa15ec refactor(FE): Switch week input to SelectInputRadio 2026-02-05 15:43:03 +07:00
rstubryan 4fd4374e64 refactor(FE): Validate date range and show toast on error 2026-02-05 15:04:12 +07:00
rstubryan b4353cf834 refactor(FE): Make filter type nullable and use applied filters 2026-02-05 14:55:27 +07:00
rstubryan eb95afe9a0 refactor(FE): Separate applied and modal filter state 2026-02-05 14:39:33 +07:00
rstubryan 92886fe5e2 refactor(FE): Consolidate date filters into trans_date 2026-02-05 14:28:14 +07:00
rstubryan fb1b310d1d refactor(FE): Replace SelectInput with SelectInputRadio 2026-02-05 14:13:13 +07:00
rstubryan 3b221795ba refactor(FE): Add filter_by option to customer payment reports 2026-02-05 14:08:05 +07:00
rstubryan d41600d8e2 refactor(FE): Replace week SelectInputRadio with NumberInput 2026-02-05 13:48:07 +07:00
Rivaldi A N S 856674de75 Merge branch 'dev/hotfix/restu' into 'development'
[HOTFIX/FE] Fix Meta Page on Penjualan Table Fetching

See merge request mbugroup/lti-web-client!312
2026-02-05 06:00:35 +00:00
rstubryan 1af2b72bea refactor(FE): Prevent badge text wrapping 2026-02-05 12:06:04 +07:00
rstubryan e66f30e703 refactor(FE): Use API metadata for table pagination 2026-02-05 12:04:08 +07:00
Rivaldi A N S ca32af592f Merge branch 'fix/adjustment-param-state-keuangan' into 'development'
[FIX/FE] Adjustment Param State on Fetch Keuangan

See merge request mbugroup/lti-web-client!311
2026-02-05 04:23:21 +00:00
rstubryan 372b439ff0 refactor(FE): Validate date range and show persistent toast 2026-02-05 11:13:53 +07:00
rstubryan 4aa9d54b1e refactor(FE): Remove unused search params and yup import 2026-02-05 11:02:20 +07:00
rstubryan b45c7c8ea6 refactor(FE): Use Formik for finance table filters 2026-02-05 10:58:59 +07:00
rstubryan c164977bb9 refactor(FE): Keep select menus open for multi-selects 2026-02-05 10:50:56 +07:00
rstubryan 3153423f14 refactor(FE): Replace size-full with w-full in FinanceTable 2026-02-05 10:48:26 +07:00
rstubryan ac3fbedccd refactor(FE): Rename filter keys to plural forms 2026-02-05 10:46:37 +07:00
Adnan Zahir 755f3fa0bb Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!310
2026-02-05 10:32:18 +07:00
Rivaldi A N S 9004de06fa Merge branch 'fix/marketing' into 'development'
[FIX/FE] Fixing UX Sales Order & Delivery Order

See merge request mbugroup/lti-web-client!309
2026-02-05 03:06:19 +00:00
randy-ar 4d7bd5213e fix(FE): fixing delivery order ui 2026-02-05 09:58:14 +07:00
randy-ar 2f1c4e3c87 fix(FE): fixing issue form not reset after success submit 2026-02-05 06:05:01 +07:00
randy-ar 43dcbf73ee feat(FE): adding 4 input scenario marketing type 2026-02-05 05:38:02 +07:00
randy-ar cb22fd1037 feat(FE): calculation penjualan telur + peti 2026-02-05 04:41:46 +07:00
randy-ar dfd86a04e0 feat(FE): scenario egg sale with type conversion qty 2026-02-05 02:39:10 +07:00
randy-ar 09cd6395e6 fix(FE): skeleton for input skenario sales order 2026-02-04 15:38:03 +07:00
Rivaldi A N S a8c9b697e3 Merge branch 'fix/purchase-adjustment-data' into 'development'
[FIX/FE] Refactor Purchase Adjustment Data Based on Latest BE API

See merge request mbugroup/lti-web-client!308
2026-02-04 07:24:16 +00:00
rstubryan 25a89b8987 refactor(FE): Update purchase search input UI 2026-02-04 14:16:53 +07:00
rstubryan 760e9ccd89 refactor(FE): Add invoice download and PO table columns 2026-02-04 14:13:59 +07:00
ValdiANS c019162390 Merge branch 'development' into fix/project-flock 2026-02-04 10:36:25 +07:00
Rivaldi A N S 428d9f33d9 Merge branch 'fix/transfer-to-laying' into 'development'
[FIX/FE] Transfer to Laying

See merge request mbugroup/lti-web-client!307
2026-02-04 03:35:57 +00:00
ValdiANS c3f4c9b1ec chore: remove keepPreviousData in useSWR config when fetching sapronak 2026-02-04 10:15:35 +07:00
ValdiANS 2918500585 chore: add is_approved query param when fetching project flock 2026-02-04 10:05:03 +07:00
Rivaldi A N S b48bf06f7d Merge branch 'fix/production-result-report' into 'development'
[FIX/FE] Production Result Report

See merge request mbugroup/lti-web-client!306
2026-02-03 09:50:18 +00:00
ValdiANS 2b343b893e chore: remove unncessary data and fix pagination for single selected project flock kandang 2026-02-03 16:45:49 +07:00
Rivaldi A N S 0c25751401 Merge branch 'fix/master-data-production-standard' into 'development'
[FIX/FE] Adding FCR Master Data Production Standard Growing

See merge request mbugroup/lti-web-client!305
2026-02-03 09:32:21 +00:00
randy-ar 9be5bb35c4 Merge branch 'development' of https://gitlab.com/mbugroup/lti-web-client into fix/master-data-production-standard 2026-02-03 14:40:12 +07:00
randy-ar c24cf7ed1a fix(FE): adding standard fcr to growing production standard 2026-02-03 14:39:34 +07:00
Rivaldi A N S 7b398bc2ee Merge branch 'fix/adjustment-uniformity-ui' into 'development'
[FIX/FE] Adjustment Uniformity, Expense, Purchase, and Recording Page UI

See merge request mbugroup/lti-web-client!304
2026-02-03 07:35:29 +00:00
rstubryan d9ee2bc7be Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into fix/adjustment-uniformity-ui 2026-02-03 14:22:23 +07:00
rstubryan f31eb8db59 refactor(FE): Show pending stock usage and depletions in detail 2026-02-03 14:20:32 +07:00
randy-ar 40411b0417 fix(FE): fixing total text color debt supplier 2026-02-03 14:12:08 +07:00
Rivaldi A N S fbbe5532a0 Merge branch 'fix/dashboard' into 'development'
[FIX/FE] Fixing Line Chart in Dashboard Page

See merge request mbugroup/lti-web-client!302
2026-02-03 07:00:11 +00:00
randy-ar c102a4043c fix(FE): fixing status badge color 2026-02-03 13:40:46 +07:00
randy-ar ab694270c4 Merge branch 'development' of https://gitlab.com/mbugroup/lti-web-client into fix/dashboard 2026-02-03 12:41:51 +07:00
randy-ar 0febc9d8f3 fix(FE): fixing line chart dashboard comparison 2026-02-03 12:41:22 +07:00
ValdiANS 1ee92f1064 Merge branch 'development' into fix/project-flock 2026-02-03 12:07:13 +07:00
Rivaldi A N S 15e53d2c2d Merge branch 'fix/not-found-page-permission' into 'development'
[FIX/FE] Not Found Page

See merge request mbugroup/lti-web-client!301
2026-02-03 05:06:11 +00:00
Rivaldi A N S 0093410d5b Merge branch 'fix/closing-overhead' into 'development'
[FIX/FE] Fixing Closing Overhead Per Kandang

See merge request mbugroup/lti-web-client!300
2026-02-03 05:04:43 +00:00
ValdiANS 7f4eb2ad35 chore: remove unnecessary code 2026-02-03 12:04:28 +07:00
ValdiANS f9e00a3f4f feat: create NotFoundPage component 2026-02-03 12:03:47 +07:00
ValdiANS 2d13564538 chore: bypass 404 page 2026-02-03 12:03:24 +07:00
ValdiANS 4fef966428 chore: remove unnecessary code 2026-02-03 12:02:43 +07:00
Rivaldi A N S e29097499a Merge branch 'fix/marketing' into 'development'
[FIX/FE] Refactor UI Sales Order & Delivery Order

See merge request mbugroup/lti-web-client!299
2026-02-03 05:02:22 +00:00
ValdiANS d4c8f9bbbc feat: create not-found page in app 2026-02-03 12:00:46 +07:00
rstubryan 43afd35e54 refactor(FE): Update add buttons styling and labels 2026-02-03 11:56:25 +07:00
rstubryan 489e8a31f3 refactor(FE): Make ConfirmationModal body scrollable and sticky 2026-02-03 11:46:45 +07:00
randy-ar 12c7e56604 fix(FE): fixing line chart dashboard 2026-02-03 11:45:33 +07:00
randy-ar eb6071aaf8 fix(FE): fixing closing overhead 2026-02-03 11:37:28 +07:00
randy-ar f01765d2f8 fix(FE): fixing closing overhead per kandang 2026-02-03 11:33:58 +07:00
rstubryan e5d6be446a refactor(FE): Enable closing modals on backdrop click 2026-02-03 11:23:07 +07:00
rstubryan bb83acbe81 refactor(FE): Render previews for multiple uniformities 2026-02-03 11:11:28 +07:00
rstubryan 758a0cd9a7 refactor(FE): Update Add button styles and labels 2026-02-03 10:46:58 +07:00
rstubryan 1a938b4218 refactor(FE): Use StatusBadge instead of PillBadge 2026-02-03 10:31:16 +07:00
ValdiANS dc5bd6b329 chore: adjust ProjectFlockKandangTable styling 2026-02-03 09:40:34 +07:00
ValdiANS 68f3c95b81 chore: adjust ProjectFlockForm styling 2026-02-03 09:40:16 +07:00
ValdiANS d826746f29 chore: adjust DrawerHeader styling 2026-02-03 09:39:58 +07:00
ValdiANS 39b18f7efc refactor: use Modal instead of Drawer 2026-02-03 09:17:17 +07:00
randy-ar e123ca9b13 Merge branch 'development' of https://gitlab.com/mbugroup/lti-web-client into fix/marketing 2026-02-02 22:01:37 +07:00
randy-ar 17589cb2b4 refactor(FE): refactor UI Sales Order and Delivery Order 2026-02-02 22:00:42 +07:00
Rivaldi A N S 0c0ad04c20 Merge branch 'fix/adjustment-confirmation-modal-and-recording-form' into 'development'
[HOTFIX/FE] Adjustment Confirmation Modal with Notes Usage and Recording Form

See merge request mbugroup/lti-web-client!298
2026-02-02 08:54:41 +00:00
rstubryan d327af814f refactor(FE): Handle missing selectedRecordDate and next-day data 2026-02-02 15:13:59 +07:00
rstubryan 8637d1c2c2 refactor(FE): Handle next-day error toast visibility 2026-02-02 15:05:47 +07:00
rstubryan 68feef77fc refactpr(FE): Extract approval and rejection handlers 2026-02-02 14:43:18 +07:00
rstubryan 4dec97b57c refactor(FE): Reset approval notes when opening/closing modals 2026-02-02 14:33:48 +07:00
rstubryan d776c73a03 refactor(FE): Add onClose handler and improve button behavior 2026-02-02 14:32:40 +07:00
rstubryan dc26da7404 refactor(FE): Remove next-day duplicate recording check 2026-02-02 12:11:24 +07:00
rstubryan 2425316fea refactor(FE): Exclude already selected products from options 2026-02-02 11:54:19 +07:00
Rivaldi A N S ff2e0ed114 Merge branch 'fix/adjustment-status-badge' into 'development'
[FIX/FE] Adjustment Usage of Status Badge (Recording, Purchase)

See merge request mbugroup/lti-web-client!297
2026-02-02 04:37:37 +00:00
kris 0efae3089d Update .gitlab-ci.yml file 2026-02-02 04:35:36 +00:00
rstubryan 1a9f5424a5 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into dev/restu 2026-02-02 11:18:52 +07:00
ValdiANS c19a7cba68 chore: lint 2026-02-02 11:15:38 +07:00
ValdiANS ec7427b948 Merge branch 'development' into fix/project-flock 2026-02-02 11:14:54 +07:00
Rivaldi A N S e169068e1c Merge branch 'fix/daily-checklist-permission' into 'development'
[FIX/FE] Daily Checklist Permission

See merge request mbugroup/lti-web-client!296
2026-02-02 04:14:06 +00:00
rstubryan 85556c0db0 refactor(FE): Use Color type for badge color typings 2026-02-02 11:10:58 +07:00
ValdiANS 7ac92ff451 chore: implement permission guard for approve/reject button 2026-02-02 10:59:44 +07:00
kris 448cf5ceae Update .gitlab-ci.yml file 2026-02-02 03:57:20 +00:00
ValdiANS 995d20bdf3 chore: implement permission guard for edit, approve/reject, and delete button 2026-02-02 10:54:34 +07:00
rstubryan 3ca4b324d3 refactor(FE): Unify status badge logic and use StatusBadge 2026-02-02 10:46:20 +07:00
kris 8fa2a444f0 Update .gitlab-ci.yml file 2026-02-02 03:42:31 +00:00
rstubryan 4a1464185b refactor(FE): Replace approval history modal with status badge 2026-02-02 10:30:34 +07:00
ValdiANS 448fb51c81 Merge branch 'development' into fix/project-flock 2026-02-02 08:50:53 +07:00
randy-ar a57f65a420 Merge branch 'development' of https://gitlab.com/mbugroup/lti-web-client into fix/marketing 2026-01-31 13:16:37 +07:00
randy-ar 70bb40d4f2 fix(FE): refactor sales order form create 2026-01-31 13:15:47 +07:00
Adnan Zahir ce1114d724 Merge branch 'staging' into 'production'
Staging

See merge request mbugroup/lti-web-client!295
2026-01-31 10:39:33 +07:00
Adnan Zahir 128b765045 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!294
2026-01-30 17:05:12 +07:00
Rivaldi A N S 66c8f67245 Merge branch 'hotfix/permission-guard' into 'development'
[HOTFIX/FE] Permission Guard

See merge request mbugroup/lti-web-client!293
2026-01-30 09:57:50 +00:00
ValdiANS 5b167db6c3 chore: add permission for transfer to laying 2026-01-30 16:55:32 +07:00
ValdiANS c6b9ed4f12 hotfix: add permission guard in transfer to laying page 2026-01-30 16:54:19 +07:00
Rivaldi A N S 9928997dd8 Merge branch 'fix/adjustment-uniformity-ui' into 'development'
[FIX/FE] Adjusment Pixel Perfect Uniformity UI

See merge request mbugroup/lti-web-client!289
2026-01-30 09:21:31 +00:00
Adnan Zahir 92c07e7841 Merge branch 'staging' into 'production'
Staging

See merge request mbugroup/lti-web-client!292
2026-01-30 16:13:35 +07:00
Adnan Zahir 1aba297920 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!291
2026-01-30 15:54:42 +07:00
randy-ar d92a63db41 Merge branch 'development' of https://gitlab.com/mbugroup/lti-web-client into fix/marketing 2026-01-30 15:54:25 +07:00
randy-ar 73319bbdfa fix(FE): fixing pixel perfect marketing table 2026-01-30 15:53:51 +07:00
rstubryan d12374e5d9 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into fix/adjustment-uniformity-ui 2026-01-30 15:43:29 +07:00
Rivaldi A N S 507cf710e1 Merge branch 'hotfix/permission-guard' into 'development'
[HOTFIX/FE] Permission Guard

See merge request mbugroup/lti-web-client!290
2026-01-30 08:43:00 +00:00
ValdiANS 8ce72b21e1 chore: update permissions for /report/marketing 2026-01-30 15:39:16 +07:00
ValdiANS 92cc082c54 chore: use localized language 2026-01-30 15:39:04 +07:00
ValdiANS 24f2b94bb8 feat: update menu permissions 2026-01-30 15:38:12 +07:00
rstubryan 67cf459216 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into fix/adjustment-uniformity-ui 2026-01-30 15:04:24 +07:00
rstubryan e3a2b41342 refactor(FE): Replace Badge with StatusBadge and cleanup utils 2026-01-30 14:55:11 +07:00
Rivaldi A N S fcea485286 Merge branch 'fix/transfer-context' into 'development'
[FIX/FE] Transfer Context

See merge request mbugroup/lti-web-client!288
2026-01-30 07:48:53 +00:00
rstubryan 0b7ff6f3f1 refactor(FE): Use accessorKey/styled headers and remove dead code 2026-01-30 14:44:29 +07:00
ValdiANS 190792affe chore: format license plate number 2026-01-30 14:44:26 +07:00
rstubryan 0a81790049 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into fix/adjustment-uniformity-ui 2026-01-30 14:37:05 +07:00
rstubryan b9b02f285f refactor(FE): Refine Uniformity table headers and layout 2026-01-30 14:36:36 +07:00
ValdiANS d3be683b69 chore: add transfer_context query when fetching source project flock 2026-01-30 14:35:21 +07:00
ValdiANS 2c27b2e41d chore: add transfer_context query when fetching source warehouse 2026-01-30 14:34:48 +07:00
rstubryan 8b0dd6deea refactor(FE): Set xl min height to 72 for Uniformity chart 2026-01-30 14:16:22 +07:00
rstubryan a5613980c0 refactor(FE): Update UniformityGaugeChart styles 2026-01-30 14:13:38 +07:00
Rivaldi A N S 12a02cd15d Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist

See merge request mbugroup/lti-web-client!287
2026-01-30 07:00:12 +00:00
ValdiANS aecf470173 chore: add max size and bottom label for file input in daily checklist form 2026-01-30 13:57:17 +07:00
rstubryan 64bd57cad4 refactor(FE): Reduce info icon size to 15 2026-01-30 13:50:21 +07:00
rstubryan ae0d03ddc0 refactor(FE): Reduce info icon size to 15 2026-01-30 13:49:47 +07:00
rstubryan 2a12bc4ba4 refactor(FE): Tweak spacing and icon size in uniformity form 2026-01-30 13:48:04 +07:00
rstubryan ace3018539 refactor(FE): Add bottom margin to Informasi Umum heading 2026-01-30 13:40:19 +07:00
rstubryan fbf7cb2d21 refactor(FE): Wrap table headers in styled span 2026-01-30 13:37:13 +07:00
rstubryan c0b1da89f1 refactor(FE): Standardize button styles in uniformity forms 2026-01-30 13:32:07 +07:00
Adnan Zahir 2aef6522bb Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!286
2026-01-30 13:32:04 +07:00
rstubryan 4b0397903d refactor(FE): Adjust file upload label styling 2026-01-30 13:27:11 +07:00
Rivaldi A N S 48a7cd168a Merge branch 'hotfix/permission-guard' into 'development'
[HOTFIX/FE] Permission Guard

See merge request mbugroup/lti-web-client!285
2026-01-30 06:26:19 +00:00
rstubryan 93b2496f55 refactor(FE): Adjust spacing in UniformityForm 2026-01-30 13:25:08 +07:00
ValdiANS 15c167d24d fix: add permission for Penjualan and Keuangan menu 2026-01-30 13:24:08 +07:00
rstubryan 8947d48a43 refactor(FE): Adjust spacing and border in UniformityForm 2026-01-30 13:20:04 +07:00
rstubryan 3de19d495e Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into fix/adjustment-uniformity-ui 2026-01-30 13:19:06 +07:00
Rivaldi A N S 8bf0f067bb Merge branch 'fix/daily-checklist' into 'development'
[FIX/FE] Daily Checklist Enhancement

See merge request mbugroup/lti-web-client!284
2026-01-30 04:49:13 +00:00
ValdiANS 970278f684 chore: sort activity and employee name 2026-01-30 11:46:29 +07:00
ValdiANS 99f8e5dcf3 chore: add validation in phase selection and sort activity and employee name 2026-01-30 11:45:50 +07:00
Adnan Zahir 3bab96c325 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!283
2026-01-30 11:40:25 +07:00
Adnan Zahir d40d352418 Merge branch 'fix/debt-supplier' into 'development'
[FIX/FE] Pixel Perfect Report Finance Debt Supplier & Customer Supplier

See merge request mbugroup/lti-web-client!282
2026-01-30 11:26:51 +07:00
ValdiANS 7956ce5b6f fix: issue when selecting all phase and employee 2026-01-30 11:18:39 +07:00
rstubryan 8babb4e3d7 refactor(FE): Use className props for drawer widths 2026-01-30 11:05:38 +07:00
ValdiANS de8fda9360 fix: reset input error when dialog is closed 2026-01-30 11:03:17 +07:00
rstubryan b2670f76bf Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into fix/adjustment-uniformity-ui 2026-01-30 10:52:54 +07:00
rstubryan 89f711241d refactor(FE): Remove left chart margin and lower min-height 2026-01-30 10:49:17 +07:00
ValdiANS 4e801bf744 Merge branch 'development' into fix/project-flock 2026-01-30 10:10:01 +07:00
ValdiANS c5269c4fc5 fix: adjust ProjectFlockTable UI 2026-01-29 16:17:27 +07:00
ValdiANS 4e00ded843 chore: add new step in PROJECT_FLOCKS approval workflows 2026-01-29 15:56:31 +07:00
Adnan Zahir 847772616e Merge branch 'staging' into 'production'
Staging

See merge request mbugroup/lti-web-client!274
2026-01-28 13:34:05 +07:00
Adnan Zahir 344140e973 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!271
2026-01-28 13:26:27 +07:00
Adnan Zahir 3ce1299091 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!268
2026-01-28 10:07:39 +07:00
Adnan Zahir aea35d4b9f Merge branch 'staging' into 'production'
Staging

See merge request mbugroup/lti-web-client!261
2026-01-27 10:36:16 +07:00
Adnan Zahir 5b134148a5 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!258
2026-01-27 09:13:31 +07:00
Adnan Zahir 32f4cf411f Merge branch 'staging' into 'production'
Staging

See merge request mbugroup/lti-web-client!254
2026-01-24 14:28:37 +07:00
Adnan Zahir 04d01970aa Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!253
2026-01-24 14:19:24 +07:00
Adnan Zahir 84cbbaf238 Merge branch 'staging' into 'production'
Staging: Transfer To Laying Rework

See merge request mbugroup/lti-web-client!249
2026-01-24 13:06:33 +07:00
Adnan Zahir 9176373072 Merge branch 'development' into 'staging'
Development: Transfer To Laying Rework

See merge request mbugroup/lti-web-client!248
2026-01-24 12:59:23 +07:00
Adnan Zahir 5c50e4a0c1 Merge branch 'staging' into 'production'
Staging

See merge request mbugroup/lti-web-client!244
2026-01-24 11:25:29 +07:00
Adnan Zahir 7e64ec0f79 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!243
2026-01-24 11:16:16 +07:00
Adnan Zahir e2be39af18 Merge branch 'staging' into 'production'
refactor(FE): Use local state for record date and disable

See merge request mbugroup/lti-web-client!237
2026-01-22 16:20:17 +07:00
Adnan Zahir 9322d6298c Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!236
2026-01-22 16:14:12 +07:00
Adnan Zahir e9cd84e89e Merge branch 'staging' into 'production'
Staging

See merge request mbugroup/lti-web-client!229
2026-01-21 15:15:04 +07:00
Adnan Zahir 89cfd31155 Merge branch 'development' into 'staging'
fix(FE): change nominal to absolute value, change form state initial balance,...

See merge request mbugroup/lti-web-client!228
2026-01-21 15:08:55 +07:00
Adnan Zahir ec5962bccc Merge branch 'staging' into 'production'
Staging

See merge request mbugroup/lti-web-client!214
2026-01-20 11:52:20 +07:00
Adnan Zahir 0eb4fa99a7 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!215
2026-01-20 11:46:20 +07:00
Adnan Zahir 2ef8b2dc9f Merge branch 'development' into 'staging'
Merge branch 'dev/hotfix/restu' into 'staging'

See merge request mbugroup/lti-web-client!203
2026-01-17 14:36:51 +07:00
Adnan Zahir aed1a1ed01 Merge branch 'development' into 'staging'
Hotfixes flock

See merge request mbugroup/lti-web-client!201
2026-01-17 11:29:55 +07:00
Adnan Zahir 2c9c2660c0 Merge branch 'development' into 'staging'
fix(FE): fix limit fetch data kandang

See merge request mbugroup/lti-web-client!198
2026-01-17 10:41:25 +07:00
Adnan Zahir b840f42ae0 Merge branch 'development' into 'staging'
refactor(FE): Improve vehicle number validation message and set

See merge request mbugroup/lti-web-client!196
2026-01-17 09:05:42 +07:00
Adnan Zahir 6bc86af32f Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!189
2026-01-15 16:21:40 +07:00
kris 1603ae62e0 Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!182
2026-01-15 06:55:35 +00:00
kris 8fd442621a Update .gitlab-ci.yml file 2026-01-14 02:52:03 +00:00
kris 35471fc597 Update .gitlab-ci.yml file 2026-01-14 02:29:31 +00:00
M1 AIR bd4242c4fd chore: fix conflict gitlab yml 2026-01-13 15:38:14 +07:00
M1 AIR 56bde974ad chore: gitlab ci yml 2026 01 13 2026-01-13 15:36:56 +07:00
M1 AIR 38258e4311 Merge remote-tracking branch 'origin/development' into staging 2026-01-13 15:27:31 +07:00
kris 149e525ff4 Update .gitlab-ci.yml file 2026-01-10 02:15:18 +00:00
M1 AIR 8fb761f02c Merge remote-tracking branch 'origin/development' into staging 2026-01-09 15:53:47 +07:00
M1 AIR 3bc5a5b75e delete .gitlab 2026-01-09 13:16:42 +07:00
M1 AIR 79112e0da8 Penyesuaian flow repo 2026-01-09 10:52:56 +07:00
M1 AIR bf9eb91ea2 Merge remote-tracking branch 'origin/development' into staging 2026-01-06 19:03:21 +07:00
kris e8c8ffadfe Update .gitlab-ci.yml file 2026-01-03 11:01:19 +00:00
M1 AIR 2ae1c5b382 Merge development into staging (keep staging CI config) 2026-01-03 16:43:49 +07:00
kris 961f81411b Merge branch 'development' into 'staging'
Development

See merge request mbugroup/lti-web-client!38
2025-12-18 10:30:13 +00:00
Mitra Berlian Unggas de439275e0 Merge branch 'development' into 'staging'
refactor(FE-114): streamline cost field validation messages and enhance layout...

See merge request mbugroup/lti-web-client!37
2025-10-28 08:44:08 +00:00
437 changed files with 45612 additions and 24841 deletions
+6
View File
@@ -45,3 +45,9 @@ next-env.d.ts
# claude # claude
.claude .claude
# rtk
rtk.exe
# local specs
/local-specs
+50 -3
View File
@@ -15,7 +15,7 @@ default:
# ========================================================== # ==========================================================
.build_template: &build_template .build_template: &build_template
stage: build stage: build
image: node:20-alpine image: public.ecr.aws/docker/library/node:20-alpine
cache: cache:
key: npm-cache key: npm-cache
paths: paths:
@@ -30,6 +30,10 @@ default:
- echo "NEXT_PUBLIC_LTI_URL=$NEXT_PUBLIC_LTI_URL" - echo "NEXT_PUBLIC_LTI_URL=$NEXT_PUBLIC_LTI_URL"
- echo "NEXT_PUBLIC_SSO_LOGIN_URL=$NEXT_PUBLIC_SSO_LOGIN_URL" - echo "NEXT_PUBLIC_SSO_LOGIN_URL=$NEXT_PUBLIC_SSO_LOGIN_URL"
- echo "NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL" - echo "NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL"
- echo "NEXT_PUBLIC_APP_ENV=$NEXT_PUBLIC_APP_ENV"
- echo "NEXT_PUBLIC_HELPDESK_URL=$NEXT_PUBLIC_HELPDESK_URL"
- echo "NEXT_PUBLIC_DASHBOARD_ACCOUNTING_URL=$NEXT_PUBLIC_DASHBOARD_ACCOUNTING_URL"
- echo "NEXT_PUBLIC_S3_PUBLIC_BASE_URL=$NEXT_PUBLIC_S3_PUBLIC_BASE_URL"
- echo "Building Next.js static export..." - echo "Building Next.js static export..."
- npx next build - npx next build
- | - |
@@ -41,7 +45,11 @@ default:
"built_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")", "built_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"NEXT_PUBLIC_LTI_URL": "$NEXT_PUBLIC_LTI_URL", "NEXT_PUBLIC_LTI_URL": "$NEXT_PUBLIC_LTI_URL",
"NEXT_PUBLIC_SSO_LOGIN_URL": "$NEXT_PUBLIC_SSO_LOGIN_URL", "NEXT_PUBLIC_SSO_LOGIN_URL": "$NEXT_PUBLIC_SSO_LOGIN_URL",
"NEXT_PUBLIC_API_BASE_URL": "$NEXT_PUBLIC_API_BASE_URL" "NEXT_PUBLIC_API_BASE_URL": "$NEXT_PUBLIC_API_BASE_URL",
"NEXT_PUBLIC_APP_ENV": "$NEXT_PUBLIC_APP_ENV",
"NEXT_PUBLIC_HELPDESK_URL": "$NEXT_PUBLIC_HELPDESK_URL",
"NEXT_PUBLIC_DASHBOARD_ACCOUNTING_URL": "$NEXT_PUBLIC_DASHBOARD_ACCOUNTING_URL"
"NEXT_PUBLIC_S3_PUBLIC_BASE_URL": "NEXT_PUBLIC_S3_PUBLIC_BASE_URL"
} }
EOF EOF
artifacts: artifacts:
@@ -56,7 +64,7 @@ default:
.deploy_template: &deploy_template .deploy_template: &deploy_template
stage: deploy stage: deploy
image: image:
name: amazon/aws-cli:latest name: public.ecr.aws/aws-cli/aws-cli:latest
entrypoint: ['/bin/sh', '-c'] entrypoint: ['/bin/sh', '-c']
script: script:
- set -e - set -e
@@ -142,6 +150,10 @@ build:dev:
NEXT_PUBLIC_SSO_LOGIN_URL: 'https://dev-auth-erp.mbugroup.id' NEXT_PUBLIC_SSO_LOGIN_URL: 'https://dev-auth-erp.mbugroup.id'
NEXT_PUBLIC_API_BASE_URL: 'https://dev-api-lti.mbugroup.id/api' NEXT_PUBLIC_API_BASE_URL: 'https://dev-api-lti.mbugroup.id/api'
NEXT_PUBLIC_CLIENT_ID: 'Lumbung-Telur-Indonesia' NEXT_PUBLIC_CLIENT_ID: 'Lumbung-Telur-Indonesia'
NEXT_PUBLIC_APP_ENV: 'development'
NEXT_PUBLIC_HELPDESK_URL: 'https://dev-helpdesk.mbugroup.id/'
NEXT_PUBLIC_DASHBOARD_ACCOUNTING_URL: 'https://dev-dashboard-ho.mbugroup.id/'
NEXT_PUBLIC_S3_PUBLIC_BASE_URL: 'https://mbu-lti-storage.s3.ap-southeast-3.amazonaws.com'
deploy:dev: deploy:dev:
<<: *deploy_template <<: *deploy_template
@@ -170,6 +182,9 @@ build:staging:
NEXT_PUBLIC_SSO_LOGIN_URL: 'https://stg-auth-erp.mbugroup.id' NEXT_PUBLIC_SSO_LOGIN_URL: 'https://stg-auth-erp.mbugroup.id'
NEXT_PUBLIC_API_BASE_URL: 'https://stg-api-lti.mbugroup.id/api' NEXT_PUBLIC_API_BASE_URL: 'https://stg-api-lti.mbugroup.id/api'
NEXT_PUBLIC_CLIENT_ID: 'Lumbung-Telur-Indonesia' NEXT_PUBLIC_CLIENT_ID: 'Lumbung-Telur-Indonesia'
NEXT_PUBLIC_APP_ENV: 'staging'
NEXT_PUBLIC_HELPDESK_URL: 'https://stg-helpdesk.mbugroup.id/'
NEXT_PUBLIC_DASHBOARD_ACCOUNTING_URL: 'https://stg-dashboard-ho.mbugroup.id/'
deploy:staging: deploy:staging:
<<: *deploy_template <<: *deploy_template
@@ -183,3 +198,35 @@ deploy:staging:
environment: environment:
name: staging name: staging
url: https://stg-lti-erp.mbugroup.id url: https://stg-lti-erp.mbugroup.id
# ==========================================================
# ====== (Branch production) ======
# ==========================================================
build:production:
<<: *build_template
rules:
- if: '$CI_COMMIT_BRANCH == "production"'
environment:
name: staging
variables:
NEXT_PUBLIC_LTI_URL: 'https://lti-erp.mbugroup.id'
NEXT_PUBLIC_SSO_LOGIN_URL: 'https://auth-erp.mbugroup.id'
NEXT_PUBLIC_API_BASE_URL: 'https://api-lti.mbugroup.id/api'
NEXT_PUBLIC_CLIENT_ID: 'Lumbung-Telur-Indonesia'
NEXT_PUBLIC_APP_ENV: 'production'
NEXT_PUBLIC_HELPDESK_URL: 'https://helpdesk.mbugroup.id/'
NEXT_PUBLIC_DASHBOARD_ACCOUNTING_URL: 'https://dashboard-ho.mbugroup.id/'
NEXT_PUBLIC_S3_PUBLIC_BASE_URL: 'https://mbu-lti-storage.s3.ap-southeast-3.amazonaws.com/'
deploy:production:
<<: *deploy_template
needs: ['build:production']
rules:
- if: '$CI_COMMIT_BRANCH == "production"'
variables:
S3_BUCKET: 'production-lti-erp.mbugroup.id'
AWS_REGION: 'ap-southeast-3'
CLOUDFRONT_DISTRIBUTION_ID: 'E1SSLXKYYITASJ'
environment:
name: staging
url: https://lti-erp.mbugroup.id
+2 -1
View File
@@ -1,3 +1,4 @@
npm run format npm run format
npm run lint npm run lint
npx tsc --noEmit npm run typecheck
git add .
+13
View File
@@ -0,0 +1,13 @@
# Project-local RTK filters — commit this file with your repo.
# Filters here override user-global and built-in filters.
# Docs: https://github.com/rtk-ai/rtk#custom-filters
schema_version = 1
# Example: suppress build noise from a custom tool
# [filters.my-tool]
# description = "Compact my-tool output"
# match_command = "^my-tool\\s+build"
# strip_ansi = true
# strip_lines_matching = ["^\\s*$", "^Downloading", "^Installing"]
# max_lines = 30
# on_empty = "my-tool: ok"
+486
View File
@@ -0,0 +1,486 @@
# LTI Web Client
Next.js 15 (App Router) + React 19 + TypeScript front-end for the LTI ERP system.
## Tech stack
- **Framework:** Next.js 15.5 (App Router, Turbopack)
- **UI:** React 19, Tailwind CSS v4, Radix UI, daisyUI, lucide-react
- **State:** zustand
- **Forms:** Formik + Yup, react-hook-form
- **Data fetching:** axios + SWR (custom `httpClient` / `httpClientFetcher` in `src/services/http`)
- **Tables:** @tanstack/react-table
- **Reporting:** @react-pdf/renderer, jspdf, exceljs, xlsx, recharts
## Scripts
- `npm run dev` — lint + dev server (Turbopack)
- `npm run build` — production build
- `npm run lint` — ESLint
- `npm run typecheck``next typegen && tsc --noEmit`
- `npm run format` — Prettier
- `npm run pre-commit` — format + lint + typecheck + build (Husky pre-commit hook)
## Project structure
```
src/
app/ # Next.js App Router routes (one folder per feature)
components/
pages/{feature}/ # Page-specific components (mirrors src/app)
helper/ # Cross-cutting helpers (e.g. SuspenseHelper)
ui/ # Shared UI primitives
services/
api/ # API service classes (extend BaseApiService)
http/ # httpClient / httpClientFetcher
hooks/ # Service-level hooks
stores/ # zustand stores grouped by domain
types/api/ # Request/response types per feature
lib/ # Shared helpers (api-helper, formik-helper, utils, validation, …)
config/, styles/
```
## Feature development standard
**Always follow this order when adding a new feature.** This is a team convention — deviating creates churn in code review.
1. **Types** — Define payload and response types in `src/types/api/{feature}` (or `{feature}.d.ts` for small features).
2. **API service** — Add `src/services/api/{feature}.ts` exporting a class that extends `BaseApiService<T, CreatePayload, UpdatePayload>` from [src/services/api/base.ts](src/services/api/base.ts). Use a subfolder (e.g. `src/services/api/daily-checklist/`) when the feature has multiple resource classes.
3. **Page** — Create the route under `src/app/{feature}` and a matching `src/components/pages/{feature}` folder for its components.
4. **Component slicing** — Break the page UI into components inside `src/components/pages/{feature}`.
5. **Wire up the API** — Consume the service class from step 2 inside the page/components (often via SWR).
6. **Detail layout** — When a route reads URL params via `useSearchParams` (e.g. `/feature/detail?id=123`), add `src/app/{feature}/detail/layout.tsx` that wraps `children` in `<SuspenseHelper>` from `@/components/helper/SuspenseHelper`.
7. **Shared state** — Use zustand stores in `src/stores/{domain}` when state must cross component boundaries.
8. **Helpers** — Reuse from [src/lib](src/lib) first (`api-helper.ts`, `formik-helper.ts`, `utils/`, `validation/`, etc.). Add new helpers there.
### Reference implementations
`closing`, `finance`, `expense`, `production`, `inventory`, `marketing`, `master-data`, `purchase`, `report`, `daily-checklist`, `dashboard` — all live in both `src/app/{feature}` and `src/components/pages/{feature}` and follow the standard above.
## Conventions
- Path alias `@/` maps to `src/`.
- Detail pages that read `useSearchParams` MUST be wrapped in `<SuspenseHelper>` via a `layout.tsx` (see [src/app/finance/detail/layout.tsx](src/app/finance/detail/layout.tsx) for the canonical pattern).
- API service classes inherit CRUD methods (`getAll`, `getSingle`, etc.) from `BaseApiService` — extend the class for feature-specific endpoints rather than calling `httpClient` directly from components.
- Pre-commit runs format + lint + typecheck + build; do not bypass with `--no-verify`.
## Table filter persistence pattern
Data tables across all modules (master-data, inventory, finance, purchase, etc.) use `useTableFilter` with `persist: true` to persist filter state in localStorage. This allows users' search, pagination, and filter choices to survive page refreshes.
**Three core principles (apply to all table components):**
1. **Set formik initialValues from tableFilterState** (not hardcoded defaults)
- Ensures the filter modal displays currently active filters when opened
- Initialize directly from persisted state: `location: tableFilterState.locationFilter`
2. **Pass `true` as last parameter to updateFilter calls**
- `updateFilter('fieldName', value, true)` immediately persists to localStorage
- Resets pagination to page 1 when filters change (via SWR revalidation)
- Apply to: search handlers, filter form submissions, reset handlers
3. **Create custom formikResetHandler function**
- Call `resetFilter()` (single call — resets all `useTableFilter` state to defaults)
- Reset any local error state (e.g. `setHasDateError(false)`, dismiss toasts)
- Call `formik.resetForm({ values: { ...defaults } })` to sync formik to defaults
- Call `filterModal.closeModal()` at the end
- Attach to form `onReset` handler (not `formik.handleReset`)
```tsx
const formikResetHandler = () => {
resetFilter();
setHasDateError(false);
if (dateErrorShown) { toast.dismiss(); setDateErrorShown(false); }
formik.resetForm({ values: { start_date: '', end_date: '', customers: [], filterBy: undefined } });
filterModal.closeModal();
};
// ...
<form onSubmit={formik.handleSubmit} onReset={formikResetHandler}>
```
**Optimization: Avoid useCallback and useMemo for trivial operations**
- `useCallback` and `useMemo` add overhead; only use them when the computation is expensive or the result is passed to a memoized child
- Simple derivations and pass-through handlers don't need them:
```tsx
// ✅ Good: plain derivation
const data = isResponseSuccess(response) ? (response.data ?? []) : [];
const meta =
isResponseSuccess(response) && response.meta ? response.meta : null;
// ❌ Avoid: useMemo for trivial conditional access
const data = useMemo(
() => (isResponseSuccess(response) ? (response.data ?? []) : []),
[response]
);
// ✅ Good: simple handler
const handleChange = (val) => setFieldValue('location', val);
// ❌ Avoid: unnecessary useCallback
const handleChange = useCallback(
(val) => setFieldValue('location', val),
[setFieldValue]
);
```
- `useMemo` IS justified for large column definition arrays (TanStack Table re-processes on every render)
**Best practice: Store OptionType objects directly, not IDs**
For select inputs, store the complete `OptionType` object (or `OptionType[]` for multi-select) in both formik state and tableFilterState. `useTableFilter`'s `serializeValue` handles serialization automatically:
- `OptionType<T>` → serialized as `String(value)` in the query string
- `OptionType<T>[]` → serialized as comma-separated values (CSV) — ideal for multi-select API params like `customer_ids`, `sales_ids`
```tsx
const { state: tableFilterState, updateFilter, ... } = useTableFilter<{
search: string;
customers: OptionType<number>[]; // multi-select → serializes as CSV
location?: OptionType<string>; // single-select → serializes as value string
filterBy?: OptionType<string>; // single-select radio
}>({
initial: {
search: '',
customers: [],
location: undefined,
filterBy: undefined,
},
paramMap: {
page: 'page',
pageSize: 'limit',
customers: 'customer_ids', // serializes OptionType[] → "1,2,3"
location: 'location_id', // serializes OptionType → "abc"
filterBy: 'filter_by',
},
persist: true,
storeName: 'my-table',
});
// Initialize formik directly from tableFilterState (no hardcoded defaults)
const formik = useFormik({
initialValues: {
customers: tableFilterState.customers,
location: tableFilterState.location,
filterBy: tableFilterState.filterBy,
},
...
});
// Use formik values directly — no computed helpers needed
<SelectInputCheckbox value={formik.values.customers} onChange={(val) => formik.setFieldValue('customers', Array.isArray(val) ? val : [])} />
<SelectInput value={formik.values.location} onChange={(val) => formik.setFieldValue('location', val)} />
<SelectInputRadio value={formik.values.filterBy ?? null} onChange={(val) => formik.setFieldValue('filterBy', !Array.isArray(val) ? (val ?? undefined) : undefined)} />
```
**Filter field naming convention**
- Multi-select fields: use plural entity name — `customers`, `salesPersons`, `locations`
- Single-select fields: use descriptive camelCase — `filterBy`, `status`, `category`
- No `Filter` suffix (e.g. avoid `customerFilter`, `locationFilter`)
**Filter modal: pass `openModal` directly, never use `enableReinitialize`**
`enableReinitialize: true` resets formik mid-interaction whenever `tableFilterState` changes, breaking the modal UX. Pass `filterModal.openModal` directly to the button — no ref wrapper needed. Formik retains its last state across open/close, which is acceptable UX (values sync with `tableFilterState` on submit and reset anyway).
```tsx
// ❌ Avoid: enableReinitialize breaks modal mid-interaction
const formik = useFormik({ initialValues: { ... }, enableReinitialize: true });
// ❌ Avoid: unnecessary ref indirection
const handleFilterModalOpenRef = useRef(() => {});
handleFilterModalOpenRef.current = () => { formik.setValues({...}); filterModal.openModal(); };
// ✅ Correct: pass openModal directly
<ButtonFilter onClick={filterModal.openModal} ... />
```
Include `filterModal.openModal` in the `useEffect` deps array when it's used inside the effect.
**Apply this pattern to:**
- Any data table component across any module that needs persistent filters
- Master-data tables, inventory lists, finance reports, purchase orders, etc.
- Whenever users' filter/search/pagination choices should survive page refreshes
**Reference implementations:**
- `SupplierTable`, `KandangsTable`, `LocationsTable`, `CustomersTable` in `src/components/pages/master-data/`
- `BalanceMonitoringTab` in `src/components/pages/report/finance/tab/` — multi-select + radio + date range
## SWR fetch pattern
Use `FinanceApi.getAllFetcher` (or the relevant service's `getAllFetcher`) when the result type matches the service generic `T`. When it differs, use `httpClientFetcher` with an explicit type:
```tsx
// ✅ Same type as service generic — use getAllFetcher
const { data } = useSWR(
`${Api.basePath}${getTableFilterQueryString()}`,
Api.getAllFetcher
);
// ✅ Different type — use httpClientFetcher with explicit useSWR type
const { data } = useSWR<
BaseApiResponse<BalanceMonitoringRow[]>,
AxiosError<BaseApiResponse>,
SWRHttpKey
>(
`${FinanceApi.basePath}/balance-monitoring${getTableFilterQueryString()}`,
httpClientFetcher
);
```
Always name the `toQueryString` alias `getTableFilterQueryString` when destructuring from `useTableFilter`.
## Server-side sorting pattern
Data tables use TanStack Table's `SortingState` wired to `useTableFilter` so that sorting triggers a server re-fetch rather than client-side reordering.
**Four-part wiring:**
1. **Local sort state** — `const [sorting, setSorting] = useState<SortingState>([]);`
2. **`useTableFilter` config** — Add `sort_by` and `order_by` to `initial` and `paramMap`. The `paramMap` key is the internal name; the value is the query param name sent to the server (they can differ, e.g. `order_by` → `sort_order`):
```ts
initial: { sort_by: '', order_by: '' }
paramMap: { sort_by: 'sort_by', order_by: 'sort_order' }
```
3. **`useEffect` sync** — Watches `sorting` and pushes changes into `useTableFilter`:
```ts
useEffect(() => {
if (sorting.length > 0) {
updateFilter('sort_by', sorting[0].id, true);
updateFilter('order_by', sorting[0].desc ? 'desc' : 'asc', true);
} else {
updateFilter('sort_by', '');
updateFilter('order_by', '');
}
}, [sorting]);
```
4. **SWR key** — SWR uses `getTableFilterToQueryString()` as its key, so any filter change (including sort) automatically re-fetches with the new query params. TanStack Table's built-in client sorting is effectively disabled; the server does the sorting.
**Pass `sorting`, `setSorting`, and `manualSorting` to `<Table>`:**
```tsx
<Table sorting={sorting} setSorting={handleSortingChange} manualSorting={true} ... />
```
`manualSorting={true}` is required — without it TanStack Table still applies its own client-side sort pass on top of the server-sorted data, producing incorrect order.
**Reference implementation:** `MarketingTable` in [src/components/pages/marketing/MarketingTable.tsx](src/components/pages/marketing/MarketingTable.tsx).
## Server-side file export pattern
All file exports (Excel, PDF, or any format) must use **server-side generation** — the server returns a binary blob and the browser triggers a download. Never generate files client-side with `xlsx`, `@react-pdf/renderer`, `jspdf`, or similar libraries.
**Rule:** Export methods live in the API service class, not in components. Components only build the query string and call the service method.
### Service method (in `src/services/api/{feature}.ts`)
```ts
async exportToExcel(initialQueryString: string) {
const params = new URLSearchParams(initialQueryString);
params.set('export', 'excel'); // or 'pdf', 'csv', etc.
params.set('page', '1');
params.set('limit', '99999999999');
const res = await httpClient<Blob>(`${this.basePath}?${params.toString()}`, {
method: 'GET',
responseType: 'blob',
});
const url = window.URL.createObjectURL(new Blob([res]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', `filename-${formatDate(Date.now(), 'DD-MM-YYYY')}.xlsx`);
document.body.appendChild(link);
link.click();
link.remove();
}
```
- Change `export=excel` → `export=pdf` (and the file extension) for PDF exports.
- Add one method per format; keep them side-by-side in the same service class.
### Component handler (in the page/tab component)
```ts
const handleExportExcel = useCallback(async () => {
setIsExcelExportLoading(true);
try {
const params = new URLSearchParams();
if (filterParams.foo) params.set('foo', filterParams.foo);
// ... map all active filter params ...
await FeatureApi.exportToExcel(params.toString());
toast.success('Excel berhasil dibuat dan diunduh.');
} catch {
toast.error('Gagal membuat Excel. Silakan coba lagi.');
} finally {
setIsExcelExportLoading(false);
}
}, [filterParams, searchValue]);
```
- Do **not** fetch all rows into the component to build the file — delegate entirely to the service method.
- Do **not** import `xlsx`, `@react-pdf/renderer`, `jspdf`, `exceljs` in page/tab components.
**Reference implementation:** `MarketingReportApiService.exportDailyMarketingToExcel` / `exportDailyMarketingToPDF` in [src/services/api/report/marketing-report.ts](src/services/api/report/marketing-report.ts), consumed by [src/components/pages/report/marketing/tab/DailyMarketingTab.tsx](src/components/pages/report/marketing/tab/DailyMarketingTab.tsx).
<!-- rtk-instructions v2 -->
# RTK (Rust Token Killer) - Token-Optimized Commands
## Golden Rule
**Always prefix commands with `rtk`**. If RTK has a dedicated filter, it uses it. If not, it passes through unchanged. This means RTK is always safe to use.
**Important**: Even in command chains with `&&`, use `rtk`:
```bash
# ❌ Wrong
git add . && git commit -m "msg" && git push
# ✅ Correct
rtk git add . && rtk git commit -m "msg" && rtk git push
```
## RTK Commands by Workflow
### Build & Compile (80-90% savings)
```bash
rtk cargo build # Cargo build output
rtk cargo check # Cargo check output
rtk cargo clippy # Clippy warnings grouped by file (80%)
rtk tsc # TypeScript errors grouped by file/code (83%)
rtk lint # ESLint/Biome violations grouped (84%)
rtk prettier --check # Files needing format only (70%)
rtk next build # Next.js build with route metrics (87%)
```
### Test (60-99% savings)
```bash
rtk cargo test # Cargo test failures only (90%)
rtk go test # Go test failures only (90%)
rtk jest # Jest failures only (99.5%)
rtk vitest # Vitest failures only (99.5%)
rtk playwright test # Playwright failures only (94%)
rtk pytest # Python test failures only (90%)
rtk rake test # Ruby test failures only (90%)
rtk rspec # RSpec test failures only (60%)
rtk test <cmd> # Generic test wrapper - failures only
```
### Git (59-80% savings)
```bash
rtk git status # Compact status
rtk git log # Compact log (works with all git flags)
rtk git diff # Compact diff (80%)
rtk git show # Compact show (80%)
rtk git add # Ultra-compact confirmations (59%)
rtk git commit # Ultra-compact confirmations (59%)
rtk git push # Ultra-compact confirmations
rtk git pull # Ultra-compact confirmations
rtk git branch # Compact branch list
rtk git fetch # Compact fetch
rtk git stash # Compact stash
rtk git worktree # Compact worktree
```
Note: Git passthrough works for ALL subcommands, even those not explicitly listed.
### GitHub (26-87% savings)
```bash
rtk gh pr view <num> # Compact PR view (87%)
rtk gh pr checks # Compact PR checks (79%)
rtk gh run list # Compact workflow runs (82%)
rtk gh issue list # Compact issue list (80%)
rtk gh api # Compact API responses (26%)
```
### JavaScript/TypeScript Tooling (70-90% savings)
```bash
rtk pnpm list # Compact dependency tree (70%)
rtk pnpm outdated # Compact outdated packages (80%)
rtk pnpm install # Compact install output (90%)
rtk npm run <script> # Compact npm script output
rtk npx <cmd> # Compact npx command output
rtk prisma # Prisma without ASCII art (88%)
```
### Files & Search (60-75% savings)
```bash
rtk ls <path> # Tree format, compact (65%)
rtk read <file> # Code reading with filtering (60%)
rtk grep <pattern> # Search grouped by file (75%)
rtk find <pattern> # Find grouped by directory (70%)
```
### Analysis & Debug (70-90% savings)
```bash
rtk err <cmd> # Filter errors only from any command
rtk log <file> # Deduplicated logs with counts
rtk json <file> # JSON structure without values
rtk deps # Dependency overview
rtk env # Environment variables compact
rtk summary <cmd> # Smart summary of command output
rtk diff # Ultra-compact diffs
```
### Infrastructure (85% savings)
```bash
rtk docker ps # Compact container list
rtk docker images # Compact image list
rtk docker logs <c> # Deduplicated logs
rtk kubectl get # Compact resource list
rtk kubectl logs # Deduplicated pod logs
```
### Network (65-70% savings)
```bash
rtk curl <url> # Compact HTTP responses (70%)
rtk wget <url> # Compact download output (65%)
```
### Meta Commands
```bash
rtk gain # View token savings statistics
rtk gain --history # View command history with savings
rtk discover # Analyze Claude Code sessions for missed RTK usage
rtk proxy <cmd> # Run command without filtering (for debugging)
rtk init # Add RTK instructions to CLAUDE.md
rtk init --global # Add RTK to ~/.claude/CLAUDE.md
```
## Token Savings Overview
| Category | Commands | Typical Savings |
| ---------------- | ------------------------------ | --------------- |
| Tests | vitest, playwright, cargo test | 90-99% |
| Build | next, tsc, lint, prettier | 70-87% |
| Git | status, log, diff, add, commit | 59-80% |
| GitHub | gh pr, gh run, gh issue | 26-87% |
| Package Managers | pnpm, npm, npx | 70-90% |
| Files | ls, read, grep, find | 60-75% |
| Infrastructure | docker, kubectl | 85% |
| Network | curl, wget | 65-70% |
Overall average: **60-90% token reduction** on common development operations.
<!-- /rtk-instructions -->
+2 -2
View File
@@ -1,4 +1,4 @@
FROM node:20-alpine FROM public.ecr.aws/docker/library/node:20-alpine
RUN apk add --no-cache git bash build-base curl RUN apk add --no-cache git bash build-base curl
@@ -22,4 +22,4 @@ RUN mkdir -p .next/server/app/_next && \
EXPOSE 3000 EXPOSE 3000
CMD ["npx", "serve", ".next/server/app", "-l", "3000"] CMD ["npx", "serve", ".next/server/app", "-l", "3000"]
+3 -1
View File
@@ -7,8 +7,10 @@
"build": "next build --turbopack", "build": "next build --turbopack",
"start": "next start", "start": "next start",
"lint": "eslint", "lint": "eslint",
"typecheck": "next typegen && tsc --noEmit",
"prepare": "husky", "prepare": "husky",
"format": "prettier --write ." "format": "prettier --write .",
"pre-commit": "npm run format && npm run lint && npm run typecheck && npm run build"
}, },
"dependencies": { "dependencies": {
"@react-pdf/renderer": "^4.3.1", "@react-pdf/renderer": "^4.3.1",
+2 -41
View File
@@ -3,11 +3,10 @@
import { useRouter, useSearchParams } from 'next/navigation'; import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr'; import useSWR from 'swr';
import ClosingDetail from '@/components/pages/closing/ClosingDetail'; import ClosingDetail from '@/components/pages/closing/ClosingDetailTabs';
import { ClosingApi } from '@/services/api/closing'; import { ClosingApi } from '@/services/api/closing';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { FlockApi } from '@/services/api/master-data';
import { ProjectFlockApi } from '@/services/api/production/project-flock'; import { ProjectFlockApi } from '@/services/api/production/project-flock';
import { ProjectFlockKandangApi } from '@/services/api/production'; import { ProjectFlockKandangApi } from '@/services/api/production';
@@ -34,33 +33,6 @@ const ClosingDetailPage = () => {
() => ProjectFlockKandangApi.getSingle(Number(kandangId)) () => ProjectFlockKandangApi.getSingle(Number(kandangId))
); );
const { data: salesData, isLoading: isLoadingSales } = useSWR(
kandangId
? `sales-${closingId}-${kandangId}`
: closingId
? `sales-${closingId}`
: null,
() =>
kandangId
? ClosingApi.getPenjualanByKandang(Number(closingId), Number(kandangId))
: ClosingApi.getPenjualan(Number(closingId))
);
const { data: hppEkspedisiData, isLoading: isLoadingHppEkspedisi } = useSWR(
kandangId
? `hpp-ekspedisi-${closingId}-${kandangId}`
: closingId
? `hpp-ekspedisi-${closingId}`
: null,
() =>
kandangId
? ClosingApi.getHppEkspedisiByKandang(
Number(closingId),
Number(kandangId)
)
: ClosingApi.getHppEkspedisi(Number(closingId))
);
if (!closingId) { if (!closingId) {
router.back(); router.back();
@@ -76,12 +48,7 @@ const ClosingDetailPage = () => {
return; return;
} }
const isLoading = const isLoading = isLoadingClosing || isLoadingProject || isLoadingKandang;
isLoadingClosing ||
isLoadingSales ||
isLoadingHppEkspedisi ||
isLoadingProject ||
isLoadingKandang;
return ( return (
<div className='w-full p-4 flex flex-row justify-center'> <div className='w-full p-4 flex flex-row justify-center'>
@@ -91,12 +58,6 @@ const ClosingDetailPage = () => {
<ClosingDetail <ClosingDetail
id={Number(closingId)} id={Number(closingId)}
initialValue={closing.data} initialValue={closing.data}
salesData={isResponseSuccess(salesData) ? salesData.data : undefined}
hppExpeditionData={
isResponseSuccess(hppEkspedisiData)
? hppEkspedisiData.data
: undefined
}
projectData={ projectData={
isResponseSuccess(projectData) ? projectData.data : undefined isResponseSuccess(projectData) ? projectData.data : undefined
} }
+1 -1
View File
@@ -2,7 +2,7 @@ import ClosingsTable from '@/components/pages/closing/ClosingsTable';
const Closing = () => { const Closing = () => {
return ( return (
<section className='w-full p-4'> <section className='w-full p-3'>
<ClosingsTable /> <ClosingsTable />
</section> </section>
); );
@@ -0,0 +1,11 @@
import { MasterKandangContent } from '@/figma-make/components/pages/master-data/kandang/MasterKandangContent';
const MasterKandangPage = () => {
return (
<section className='w-full'>
<MasterKandangContent />
</section>
);
};
export default MasterKandangPage;
+2 -2
View File
@@ -15,8 +15,8 @@ const ExpenseDetailPage = () => {
const expenseId = searchParams.get('expenseId'); const expenseId = searchParams.get('expenseId');
const { data: expense, isLoading: isLoadingExpense } = useSWR( const { data: expense, isLoading: isLoadingExpense } = useSWR(
expenseId, ['expense-detail', expenseId],
(id: number) => ExpenseApi.getSingle(id) ([_, id]) => ExpenseApi.getSingle(Number(id))
); );
if (!expenseId) { if (!expenseId) {
-1
View File
@@ -5,7 +5,6 @@ import useSWR from 'swr';
import { FinanceApi } from '@/services/api/finance'; import { FinanceApi } from '@/services/api/finance';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import FormFinanceAdd from '@/components/pages/finance/add/FormFinanceAdd'; import FormFinanceAdd from '@/components/pages/finance/add/FormFinanceAdd';
import FormFinanceAddInitialBalance from '@/components/pages/finance/add/initial-balance/FormFinanceAddInitialBalance';
const EditFinanceTransactionPage = () => { const EditFinanceTransactionPage = () => {
const router = useRouter(); const router = useRouter();
+1 -1
View File
@@ -4,7 +4,7 @@ import FinanceDetail from '@/components/pages/finance/FinanceDetail';
import useSWR from 'swr'; import useSWR from 'swr';
import { useRouter, useSearchParams } from 'next/navigation'; import { useRouter, useSearchParams } from 'next/navigation';
import { FinanceApi } from '@/services/api/finance'; import { FinanceApi } from '@/services/api/finance';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
const FinanceDetailPage = () => { const FinanceDetailPage = () => {
const router = useRouter(); const router = useRouter();
+1 -6
View File
@@ -3,12 +3,7 @@
import FinanceTable from '@/components/pages/finance/FinanceTable'; import FinanceTable from '@/components/pages/finance/FinanceTable';
const Finance = () => { const Finance = () => {
return ( return <FinanceTable />;
<section className='size-full p-6'>
<div className='flex flex-row gap-4'></div>
<FinanceTable />
</section>
);
}; };
export default Finance; export default Finance;
+2
View File
@@ -68,6 +68,8 @@
--shadow-button-soft: --shadow-button-soft:
0 3px 2px -2px var(--color-base-200), 0 4px 3px -2px var(--color-base-200); 0 3px 2px -2px var(--color-base-200), 0 4px 3px -2px var(--color-base-200);
--shadow-bg: 0px -2px 4px 0px #00000014;
} }
html { html {
+1 -1
View File
@@ -2,7 +2,7 @@ import InventoryAdjustmentTable from '@/components/pages/inventory/adjustment/In
const InventoryAdjustment = () => { const InventoryAdjustment = () => {
return ( return (
<section className='w-full p-4'> <section className='w-full'>
<InventoryAdjustmentTable /> <InventoryAdjustmentTable />
</section> </section>
); );
@@ -1,54 +0,0 @@
'use client';
import MarketingForm from '@/components/pages/marketing/form/MarketingForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { MarketingApi } from '@/services/api/marketing/marketing';
import { useRouter, useSearchParams } from 'next/navigation';
import toast from 'react-hot-toast';
import useSWR from 'swr';
const EditMarketingDelivery = () => {
const router = useRouter();
const searchParams = useSearchParams();
const soId = searchParams.get('marketingId');
const {
data: marketing,
isLoading: isLoading,
mutate: refreshMarketing,
} = useSWR(`get-so-${soId}`, () =>
MarketingApi.getSingle(soId ? parseInt(soId) : 0)
);
if (!soId) {
router.back();
return (
<div className='w-full flex flex-row justify-center items-center p-4'>
<span className='loading loading-spinner loading-xl' />
</div>
);
}
if (!isLoading && (!marketing || isResponseError(marketing))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4'>
{isLoading && <span className='loading loading-spinner loading-xl' />}
{!isLoading && isResponseSuccess(marketing) && (
<MarketingForm
formType='add_deliver'
initialValues={marketing.data}
afterSubmit={() => {
refreshMarketing();
}}
/>
)}
</div>
);
};
export default EditMarketingDelivery;
@@ -1,11 +0,0 @@
import MarketingForm from '@/components/pages/marketing/form/MarketingForm';
const AddSalesOrder = () => {
return (
<div className='size-full p-4'>
<MarketingForm formType='add' />
</div>
);
};
export default AddSalesOrder;
@@ -1,62 +0,0 @@
'use client';
import MarketingForm from '@/components/pages/marketing/form/MarketingForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { MarketingApi } from '@/services/api/marketing/marketing';
import { useRouter, useSearchParams } from 'next/navigation';
import toast from 'react-hot-toast';
import useSWR from 'swr';
const EditMarketingDelivery = () => {
const router = useRouter();
const searchParams = useSearchParams();
const soId = searchParams.get('marketingId');
const {
data: marketing,
isLoading: isLoading,
mutate: refreshMarketing,
} = useSWR(`get-so-${soId}`, () =>
MarketingApi.getSingle(soId ? parseInt(soId) : 0)
);
if (!soId) {
router.back();
return (
<div className='w-full flex flex-row justify-center items-center p-4'>
<span className='loading loading-spinner loading-xl' />
</div>
);
}
if (!isLoading && (!marketing || isResponseError(marketing))) {
router.replace('/404');
return;
}
if (
isResponseSuccess(marketing) &&
marketing.data.latest_approval.step_number != 3
) {
toast.error('Data Marketing perlu dilakukan approval terlebih dahulu!');
router.back();
}
return (
<div className='w-full p-4'>
{isLoading && <span className='loading loading-spinner loading-xl' />}
{!isLoading && isResponseSuccess(marketing) && (
<MarketingForm
formType='edit_deliver'
initialValues={marketing.data}
afterSubmit={() => {
refreshMarketing();
}}
/>
)}
</div>
);
};
export default EditMarketingDelivery;
-11
View File
@@ -1,11 +0,0 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
-49
View File
@@ -1,49 +0,0 @@
'use client';
import MarketingDetail from '@/components/pages/marketing/detail/MarketingDetail';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { MarketingApi } from '@/services/api/marketing/marketing';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
const DetailMarketing = () => {
const router = useRouter();
const searchParams = useSearchParams();
const soId = searchParams.get('marketingId');
const {
data: marketing,
isLoading: isLoading,
mutate: refreshMarketing,
} = useSWR(soId, (id: number) => MarketingApi.getSingle(id));
if (!soId) {
router.back();
return (
<div className='w-full flex flex-row justify-center items-center p-4'>
<span className='loading loading-spinner loading-xl' />
</div>
);
}
if (!isLoading && (!marketing || isResponseError(marketing))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4'>
{isLoading && <span className='loading loading-spinner loading-xl' />}
{!isLoading && isResponseSuccess(marketing) && (
<MarketingDetail
initialValues={marketing.data}
refresh={refreshMarketing}
/>
)}
</div>
);
};
export default DetailMarketing;
@@ -1,11 +0,0 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -1,52 +0,0 @@
'use client';
import MarketingForm from '@/components/pages/marketing/form/MarketingForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { MarketingApi } from '@/services/api/marketing/marketing';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
const EditSalesOrder = () => {
const router = useRouter();
const searchParams = useSearchParams();
const soId = searchParams.get('marketingId');
const {
data: marketing,
isLoading: isLoading,
mutate: refreshMarketing,
} = useSWR(`get-so-${soId}`, () =>
MarketingApi.getSingle(soId ? parseInt(soId) : 0)
);
if (!soId) {
router.back();
return (
<div className='w-full flex flex-row justify-center items-center p-4'>
<span className='loading loading-spinner loading-xl' />
</div>
);
}
if (!isLoading && (!marketing || isResponseError(marketing))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4'>
{isLoading && <span className='loading loading-spinner loading-xl' />}
{!isLoading && isResponseSuccess(marketing) && (
<MarketingForm
formType='edit'
initialValues={marketing.data}
afterSubmit={() => {
refreshMarketing();
}}
/>
)}
</div>
);
};
export default EditSalesOrder;
+6 -1
View File
@@ -1,9 +1,14 @@
import DeliveryOrderFormModal from '@/components/pages/marketing/DeliveryOrderFormModal';
import MarketingTable from '@/components/pages/marketing/MarketingTable'; import MarketingTable from '@/components/pages/marketing/MarketingTable';
import SalesOrderFormModal from '@/components/pages/marketing/SalesOrderFormModal';
const Marketing = () => { const Marketing = () => {
return ( return (
<div className='w-full p-4'> <div className='w-full'>
<MarketingTable /> <MarketingTable />
<SalesOrderFormModal />
<DeliveryOrderFormModal />
</div> </div>
); );
}; };
+1 -5
View File
@@ -1,11 +1,7 @@
import AreasTable from '@/components/pages/master-data/area/AreasTable'; import AreasTable from '@/components/pages/master-data/area/AreasTable';
const Nonstock = () => { const Nonstock = () => {
return ( return <AreasTable />;
<section className='w-full p-4'>
<AreasTable />
</section>
);
}; };
export default Nonstock; export default Nonstock;
+1 -5
View File
@@ -1,11 +1,7 @@
import BanksTable from '@/components/pages/master-data/bank/BanksTable'; import BanksTable from '@/components/pages/master-data/bank/BanksTable';
const Bank = () => { const Bank = () => {
return ( return <BanksTable />;
<section className='w-full p-4'>
<BanksTable />
</section>
);
}; };
export default Bank; export default Bank;
+1 -5
View File
@@ -1,11 +1,7 @@
import CustomersTable from '@/components/pages/master-data/customer/CustomersTable'; import CustomersTable from '@/components/pages/master-data/customer/CustomersTable';
const Customer = () => { const Customer = () => {
return ( return <CustomersTable />;
<section className='w-full p-4'>
<CustomersTable />
</section>
);
}; };
export default Customer; export default Customer;
-11
View File
@@ -1,11 +0,0 @@
import FcrForm from '@/components/pages/master-data/fcr/form/FcrForm';
const AddFcr = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<FcrForm />
</div>
);
};
export default AddFcr;
@@ -1,52 +0,0 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import FcrForm from '@/components/pages/master-data/fcr/form/FcrForm';
import { FcrApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { BaseApiResponse } from '@/types/api/api-general';
import { FcrWithStandards } from '@/types/api/master-data/fcr';
const FcrEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const fcrId = searchParams.get('fcrId');
const { data: fcr, isLoading: isLoadingFcr } = useSWR(
fcrId,
(id: number) =>
FcrApi.getSingle(id) as Promise<
BaseApiResponse<FcrWithStandards> | undefined
>
);
if (!fcrId) {
router.back();
return (
<div className='w-full flex flex-row justify-center items-center p-4'>
<span className='loading loading-spinner loading-xl' />
</div>
);
}
if (!isLoadingFcr && (!fcr || isResponseError(fcr))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingFcr && <span className='loading loading-spinner loading-xl' />}
{!isLoadingFcr && isResponseSuccess(fcr) && (
<FcrForm type='edit' initialValues={fcr.data} />
)}
</div>
);
};
export default FcrEdit;
-11
View File
@@ -1,11 +0,0 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
-52
View File
@@ -1,52 +0,0 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import FcrForm from '@/components/pages/master-data/fcr/form/FcrForm';
import { FcrApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { FcrWithStandards } from '@/types/api/master-data/fcr';
import { BaseApiResponse } from '@/types/api/api-general';
const FcrDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const fcrId = searchParams.get('fcrId');
const { data: fcr, isLoading: isLoadingFcr } = useSWR(
fcrId,
(id: number) =>
FcrApi.getSingle(id) as Promise<
BaseApiResponse<FcrWithStandards> | undefined
>
);
if (!fcrId) {
router.back();
return (
<div className='w-full flex flex-row justify-center items-center p-4'>
<span className='loading loading-spinner loading-xl' />
</div>
);
}
if (!isLoadingFcr && (!fcr || isResponseError(fcr))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingFcr && <span className='loading loading-spinner loading-xl' />}
{!isLoadingFcr && isResponseSuccess(fcr) && (
<FcrForm type='detail' initialValues={fcr.data} />
)}
</div>
);
};
export default FcrDetail;
-11
View File
@@ -1,11 +0,0 @@
import FcrsTable from '@/components/pages/master-data/fcr/FcrsTable';
const Fcr = () => {
return (
<section className='w-full p-4'>
<FcrsTable />
</section>
);
};
export default Fcr;
+1 -5
View File
@@ -1,11 +1,7 @@
import FlockTable from '@/components/pages/master-data/flock/FlocksTable'; import FlockTable from '@/components/pages/master-data/flock/FlocksTable';
const Flock = () => { const Flock = () => {
return ( return <FlockTable />;
<section className='w-full p-4'>
<FlockTable />
</section>
);
}; };
export default Flock; export default Flock;
+1 -5
View File
@@ -1,11 +1,7 @@
import KandangsTable from '@/components/pages/master-data/kandang/KandangsTable'; import KandangsTable from '@/components/pages/master-data/kandang/KandangsTable';
const Nonstock = () => { const Nonstock = () => {
return ( return <KandangsTable />;
<section className='w-full p-4'>
<KandangsTable />
</section>
);
}; };
export default Nonstock; export default Nonstock;
+1 -5
View File
@@ -1,11 +1,7 @@
import LocationsTable from '@/components/pages/master-data/location/LocationsTable'; import LocationsTable from '@/components/pages/master-data/location/LocationsTable';
const Nonstock = () => { const Nonstock = () => {
return ( return <LocationsTable />;
<section className='w-full p-4'>
<LocationsTable />
</section>
);
}; };
export default Nonstock; export default Nonstock;
+1 -5
View File
@@ -1,11 +1,7 @@
import NonstocksTable from '@/components/pages/master-data/nonstock/NonstocksTable'; import NonstocksTable from '@/components/pages/master-data/nonstock/NonstocksTable';
const Nonstock = () => { const Nonstock = () => {
return ( return <NonstocksTable />;
<section className='w-full p-4'>
<NonstocksTable />
</section>
);
}; };
export default Nonstock; export default Nonstock;
@@ -1,11 +1,7 @@
import ProductCategoryTable from '@/components/pages/master-data/product-category/ProductCategoryTable'; import ProductCategoryTable from '@/components/pages/master-data/product-category/ProductCategoryTable';
const ProductCategory = () => { const ProductCategory = () => {
return ( return <ProductCategoryTable />;
<section className='w-full p-4'>
<ProductCategoryTable />
</section>
);
}; };
export default ProductCategory; export default ProductCategory;
+1 -5
View File
@@ -1,11 +1,7 @@
import ProductsTable from '@/components/pages/master-data/product/ProductTable'; import ProductsTable from '@/components/pages/master-data/product/ProductTable';
const Product = () => { const Product = () => {
return ( return <ProductsTable />;
<section className='w-full p-4'>
<ProductsTable />
</section>
);
}; };
export default Product; export default Product;
@@ -1,11 +1,7 @@
import ProductionStandardTable from '@/components/pages/master-data/production-standard/ProductionStandardTable'; import ProductionStandardTable from '@/components/pages/master-data/production-standard/ProductionStandardTable';
const ProductionStandardPage = () => { const ProductionStandardPage = () => {
return ( return <ProductionStandardTable />;
<div className='w-full'>
<ProductionStandardTable />
</div>
);
}; };
export default ProductionStandardPage; export default ProductionStandardPage;
+1 -5
View File
@@ -1,11 +1,7 @@
import SuppliersTable from '@/components/pages/master-data/supplier/SupplierTable'; import SuppliersTable from '@/components/pages/master-data/supplier/SupplierTable';
const Supplier = () => { const Supplier = () => {
return ( return <SuppliersTable />;
<section className='w-full p-4'>
<SuppliersTable />
</section>
);
}; };
export default Supplier; export default Supplier;
@@ -0,0 +1,11 @@
import { SystemConfigContent } from '@/figma-make/components/pages/master-data/system-config/SystemConfigContent';
const SystemConfigPage = () => {
return (
<section className='w-full'>
<SystemConfigContent />
</section>
);
};
export default SystemConfigPage;
+1 -5
View File
@@ -1,11 +1,7 @@
import UomsTable from '@/components/pages/master-data/uom/UomsTable'; import UomsTable from '@/components/pages/master-data/uom/UomsTable';
const Nonstock = () => { const Nonstock = () => {
return ( return <UomsTable />;
<section className='w-full p-4'>
<UomsTable />
</section>
);
}; };
export default Nonstock; export default Nonstock;
+1 -5
View File
@@ -1,11 +1,7 @@
import WarehousesTable from '@/components/pages/master-data/warehouse/WarehousesTable'; import WarehousesTable from '@/components/pages/master-data/warehouse/WarehousesTable';
const Warehouse = () => { const Warehouse = () => {
return ( return <WarehousesTable />;
<section className='w-full p-4'>
<WarehousesTable />
</section>
);
}; };
export default Warehouse; export default Warehouse;
+5
View File
@@ -0,0 +1,5 @@
import PageNotFound from '@/components/helper/NotFoundPage';
export default function NotFound() {
return <PageNotFound />;
}
+1 -2
View File
@@ -3,10 +3,9 @@
import { useEffect } from 'react'; import { useEffect } from 'react';
import { usePathname, useRouter } from 'next/navigation'; import { usePathname, useRouter } from 'next/navigation';
import { useAuth } from '@/services/hooks/useAuth'; import { useAuth } from '@/services/hooks/useAuth';
import { redirectToSSO } from '@/lib/auth-helper';
export default function Home() { export default function Home() {
const { user, isLoadingUser } = useAuth(); const { isLoadingUser } = useAuth();
const router = useRouter(); const router = useRouter();
const pathname = usePathname(); const pathname = usePathname();
@@ -1,8 +1,8 @@
'use client'; 'use client';
import ProjectFlockForm from '@/components/pages/production/project-flock/form/ProjectFlockForm'; import ProjectFlockForm from '@/components/pages/production/project-flock/form/ProjectFlockForm';
import React, { useImperativeHandle } from 'react'; import React from 'react';
import toast from 'react-hot-toast'; // import React, { useImperativeHandle } from 'react';
const AddProjectFlock = () => { const AddProjectFlock = () => {
// useImperativeHandle(ref, () => ({ // useImperativeHandle(ref, () => ({
@@ -12,11 +12,10 @@ const ProjectFlockEdit = () => {
const projectFlockId = searchParams.get('projectFlockId'); const projectFlockId = searchParams.get('projectFlockId');
const { const { data: projectFlock, isLoading: isLoadingProjectFlock } = useSWR(
data: projectFlock, projectFlockId,
isLoading: isLoadingProjectFlock, (id: number) => ProjectFlockApi.getSingle(id)
mutate: refreshProjectFlocks, );
} = useSWR(projectFlockId, (id: number) => ProjectFlockApi.getSingle(id));
if (!projectFlockId) { if (!projectFlockId) {
router.back(); router.back();
@@ -1,7 +1,6 @@
'use client'; 'use client';
import ProjectFlockDetail from '@/components/pages/production/project-flock/detail/ProjectFlockDetail'; import ProjectFlockDetail from '@/components/pages/production/project-flock/detail/ProjectFlockDetail';
import ProjectFlockForm from '@/components/pages/production/project-flock/form/ProjectFlockForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { ProjectFlockApi } from '@/services/api/production/project-flock'; import { ProjectFlockApi } from '@/services/api/production/project-flock';
import { useRouter, useSearchParams } from 'next/navigation'; import { useRouter, useSearchParams } from 'next/navigation';
@@ -13,11 +12,10 @@ const ProjectFlockDetailPage = () => {
const projectFlockId = searchParams.get('projectFlockId'); const projectFlockId = searchParams.get('projectFlockId');
const { const { data: projectFlock, isLoading: isLoadingProjectFlock } = useSWR(
data: projectFlock, projectFlockId,
isLoading: isLoadingProjectFlock, (id: number) => ProjectFlockApi.getSingle(id)
mutate: refreshProjectFlock, );
} = useSWR(projectFlockId, (id: number) => ProjectFlockApi.getSingle(id));
if (!projectFlockId) { if (!projectFlockId) {
router.back(); router.back();
@@ -50,5 +48,3 @@ const ProjectFlockDetailPage = () => {
}; };
export default ProjectFlockDetailPage; export default ProjectFlockDetailPage;
ProjectFlockDetail;
ProjectFlockDetail;
+25 -13
View File
@@ -1,10 +1,10 @@
'use client'; 'use client';
import { usePathname, useRouter } from 'next/navigation'; import { usePathname, useRouter } from 'next/navigation';
import Drawer from '@/components/Drawer'; import React, { ReactNode, useEffect } from 'react';
import React, { ReactNode } from 'react';
import ProjectFlockTable from '@/components/pages/production/project-flock/ProjectFlockTable'; import ProjectFlockTable from '@/components/pages/production/project-flock/ProjectFlockTable';
import { useUiStore } from '@/stores/ui/ui.store'; import { useUiStore } from '@/stores/ui/ui.store';
import Modal, { useModal } from '@/components/Modal';
export default function ProjectFlockLayout({ export default function ProjectFlockLayout({
children, children,
@@ -23,9 +23,12 @@ export default function ProjectFlockLayout({
const isOpen = isAdd || isEdit || isDetail || isChickin || isClosing; const isOpen = isAdd || isEdit || isDetail || isChickin || isClosing;
const formModal = useModal();
const handleBackdropClick = () => { const handleBackdropClick = () => {
const unsub = useUiStore.getState().subscribeIsValid((isValid) => { const unsub = useUiStore.getState().subscribeIsValid((isValid) => {
if (isValid) { if (isValid) {
formModal.closeModal();
unsub(); // berhenti listen unsub(); // berhenti listen
router.push('/production/project-flock'); router.push('/production/project-flock');
} }
@@ -34,6 +37,14 @@ export default function ProjectFlockLayout({
toggleValidate(); toggleValidate();
}; };
useEffect(() => {
if (isOpen && !formModal.open) {
formModal.openModal();
} else {
formModal.closeModal();
}
}, [isOpen]);
return ( return (
<> <>
{/* List page always rendered */} {/* List page always rendered */}
@@ -43,18 +54,19 @@ export default function ProjectFlockLayout({
/> />
</div> </div>
{/* Render Drawer only on /add */} {/* Render Modal only on /add */}
<Drawer <Modal
open={isOpen} ref={formModal.ref}
setOpen={(v) => { position='end'
if (!v) router.push('/production/project-flock');
}}
closeOnBackdropClick={isDetail ? true : false}
onBackdropClick={handleBackdropClick} onBackdropClick={handleBackdropClick}
variant='right' className={{
zIndex='99999' modalBox: 'w-full sm:w-fit p-3 rounded-xl bg-transparent shadow-none',
sidebarContent={isOpen && <div className=''>{children}</div>} }}
/> >
<div className='w-full sm:w-[446px] h-full flex flex-col sm:flex-row items-stretch bg-base-100 rounded-xl overflow-hidden'>
{isOpen && children}
</div>
</Modal>
</> </>
); );
} }
@@ -11,10 +11,13 @@ const RecordingEdit = () => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const recordingId = searchParams.get('recordingId'); const recordingId = searchParams.get('recordingId');
const recordingDetailKey = recordingId
? ['recording-detail', recordingId]
: null;
const { data: recording, isLoading: isLoadingRecording } = useSWR( const { data: recording, isLoading: isLoadingRecording } = useSWR(
recordingId, recordingDetailKey,
(id: string) => RecordingApi.getSingle(parseInt(id)) ([, id]: [string, string]) => RecordingApi.getSingle(parseInt(id))
); );
if (!recordingId) { if (!recordingId) {
+5 -2
View File
@@ -11,10 +11,13 @@ const RecordingDetail = () => {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const recordingId = searchParams.get('recordingId'); const recordingId = searchParams.get('recordingId');
const recordingDetailKey = recordingId
? ['recording-detail', recordingId]
: null;
const { data: recording, isLoading: isLoadingRecording } = useSWR( const { data: recording, isLoading: isLoadingRecording } = useSWR(
recordingId, recordingDetailKey,
(id: string) => RecordingApi.getSingle(parseInt(id)) ([, id]: [string, string]) => RecordingApi.getSingle(parseInt(id))
); );
if (!recordingId) { if (!recordingId) {
+1 -1
View File
@@ -2,7 +2,7 @@ import RecordingTable from '@/components/pages/production/recording/RecordingTab
const Recording = () => { const Recording = () => {
return ( return (
<section className='w-full p-4 sm:p-0'> <section className='w-full'>
<RecordingTable /> <RecordingTable />
</section> </section>
); );
+12 -2
View File
@@ -1,15 +1,25 @@
import TransferToLayingsTable from '@/components/pages/production/transfer-to-laying/TransferToLayingsTable'; import TransferToLayingsTable from '@/components/pages/production/transfer-to-laying/TransferToLayingsTable';
import TransferToLayingFormModal from '@/components/pages/production/transfer-to-laying/TransferToLayingFormModal'; import TransferToLayingFormModal from '@/components/pages/production/transfer-to-laying/TransferToLayingFormModal';
import TransferToLayingDetailModal from '@/components/pages/production/transfer-to-laying/TransferToLayingDetailModal'; import TransferToLayingDetailModal from '@/components/pages/production/transfer-to-laying/TransferToLayingDetailModal';
import RequirePermission from '@/components/helper/RequirePermission';
const TransferToLaying = () => { const TransferToLaying = () => {
return ( return (
<section className='w-full'> <section className='w-full'>
<TransferToLayingsTable /> <TransferToLayingsTable />
<TransferToLayingFormModal /> <RequirePermission
permissions={[
'lti.production.transfer_to_laying.create',
'lti.production.transfer_to_laying.update',
]}
>
<TransferToLayingFormModal />
</RequirePermission>
<TransferToLayingDetailModal /> <RequirePermission permissions='lti.production.transfer_to_laying.detail'>
<TransferToLayingDetailModal />
</RequirePermission>
</section> </section>
); );
}; };
+2 -6
View File
@@ -1,13 +1,9 @@
'use client'; 'use client';
import ReportExpenseTable from '@/components/pages/report/expense/ReportExpenseTable'; import ReportExpenseTabs from '@/components/pages/report/expense/ReportExpenseTabs';
const ReportExpense = () => { const ReportExpense = () => {
return ( return <ReportExpenseTabs />;
<div className='w-full p-4'>
<ReportExpenseTable />
</div>
);
}; };
export default ReportExpense; export default ReportExpense;
+2 -6
View File
@@ -1,11 +1,7 @@
import MarketingReportContent from '@/components/pages/report/MarketingReportContent'; import MarketingReportContent from '@/components/pages/report/marketing/MarketingTabs';
const MarketingReportPage = () => { const MarketingReportPage = () => {
return ( return <MarketingReportContent />;
<section className='w-full p-4'>
<MarketingReportContent />
</section>
);
}; };
export default MarketingReportPage; export default MarketingReportPage;
+3 -3
View File
@@ -1,9 +1,9 @@
import ProductionResultContent from '@/components/pages/report/production-result/ProductionResultContent'; import ProductionResultTabs from '@/components/pages/report/production-result/ProductionResultTabs';
const ProductionResultReportPage = () => { const ProductionResultReportPage = () => {
return ( return (
<section className='w-full max-w-7xl pb-16'> <section className='w-full max-w-full'>
<ProductionResultContent /> <ProductionResultTabs />
</section> </section>
); );
}; };
+8 -3
View File
@@ -1,15 +1,16 @@
import { ReactNode } from 'react'; import { ReactNode, Ref } from 'react';
import { cn } from '@/lib/helper'; import { cn } from '@/lib/helper';
interface AlertProps { interface AlertProps {
ref?: Ref<HTMLDivElement> | undefined;
variant?: 'outline' | 'dash' | 'soft'; variant?: 'outline' | 'dash' | 'soft';
color?: 'info' | 'success' | 'warning' | 'error'; color?: 'info' | 'success' | 'warning' | 'error';
children?: ReactNode; children?: ReactNode;
className?: string; className?: string;
} }
const Alert = ({ children, variant, color, className }: AlertProps) => { const Alert = ({ children, ref, variant, color, className }: AlertProps) => {
const alertBaseClassName = cn('alert', { const alertBaseClassName = cn('alert', {
'alert-soft': variant === 'soft', 'alert-soft': variant === 'soft',
'alert-outline': variant === 'outline', 'alert-outline': variant === 'outline',
@@ -21,7 +22,11 @@ const Alert = ({ children, variant, color, className }: AlertProps) => {
'alert-error': color === 'error', 'alert-error': color === 'error',
}); });
return <div className={cn(alertBaseClassName, className)}>{children}</div>; return (
<div ref={ref} className={cn(alertBaseClassName, className)}>
{children}
</div>
);
}; };
export default Alert; export default Alert;
+3 -3
View File
@@ -51,7 +51,7 @@ const Button = ({
return ( return (
<> <>
{!href && ( {(!href || (href && disabled)) && (
<button <button
{...props} {...props}
type={type} type={type}
@@ -68,9 +68,9 @@ const Button = ({
</button> </button>
)} )}
{href && ( {href && !disabled && (
<Link <Link
href={disabled ? '#' : href} href={href}
target={target} target={target}
rel={rel} rel={rel}
aria-disabled={disabled} aria-disabled={disabled}
+8 -4
View File
@@ -16,7 +16,6 @@ interface DrawerProps {
onBackdropClick?: () => void; onBackdropClick?: () => void;
closeOnBackdropClick?: boolean; closeOnBackdropClick?: boolean;
expandedContent?: ReactNode; expandedContent?: ReactNode;
expandedWidth?: string;
} }
type DrawerClassName = { type DrawerClassName = {
@@ -25,6 +24,7 @@ type DrawerClassName = {
drawerSide?: string; drawerSide?: string;
drawerOverlay?: string; drawerOverlay?: string;
drawerSidebarContent?: string; drawerSidebarContent?: string;
drawerExpandedContent?: string;
}; };
const Drawer = ({ const Drawer = ({
@@ -39,7 +39,6 @@ const Drawer = ({
onBackdropClick, onBackdropClick,
closeOnBackdropClick = true, closeOnBackdropClick = true,
expandedContent, expandedContent,
expandedWidth = 'w-[400px]',
}: DrawerProps) => { }: DrawerProps) => {
const getDrawerClassNames = (): DrawerClassName => { const getDrawerClassNames = (): DrawerClassName => {
const baseClassNames = { const baseClassNames = {
@@ -56,6 +55,9 @@ const Drawer = ({
? 'w-full lg:min-w-[600px] lg:max-w-[600px]' ? 'w-full lg:min-w-[600px] lg:max-w-[600px]'
: 'w-full max-w-[300px] lg:w-[300px]'; : 'w-full max-w-[300px] lg:w-[300px]';
} }
if (className?.drawerSidebarContent) {
return '';
}
return 'w-full sm:min-w-120 sm:w-fit'; return 'w-full sm:min-w-120 sm:w-fit';
}; };
@@ -106,7 +108,9 @@ const Drawer = ({
if (closeOnBackdropClick) { if (closeOnBackdropClick) {
setOpen(false); setOpen(false);
} }
onBackdropClick && onBackdropClick(); if (onBackdropClick) {
onBackdropClick();
}
}; };
return ( return (
@@ -174,7 +178,7 @@ const Drawer = ({
<div <div
className={cn( className={cn(
'border-l border-gray-200 bg-white flex flex-col h-full', 'border-l border-gray-200 bg-white flex flex-col h-full',
expandedWidth className?.drawerExpandedContent
)} )}
> >
<div className='overflow-y-auto flex-1 h-full'> <div className='overflow-y-auto flex-1 h-full'>
+7 -3
View File
@@ -1,6 +1,5 @@
'use client'; 'use client';
import { useCallback } from 'react';
import { usePathname } from 'next/navigation'; import { usePathname } from 'next/navigation';
import Image from 'next/image'; import Image from 'next/image';
@@ -13,7 +12,6 @@ import PermissionNotFound from '@/components/helper/PermissionNotFound';
import { useUiStore } from '@/stores/ui/ui.store'; import { useUiStore } from '@/stores/ui/ui.store';
import { MAIN_DRAWER_LINKS } from '@/config/constant'; import { MAIN_DRAWER_LINKS } from '@/config/constant';
import { isPathActive } from '@/lib/helper';
import { ROUTE_PERMISSIONS } from '@/config/route-permission'; import { ROUTE_PERMISSIONS } from '@/config/route-permission';
import { useAuth } from '@/services/hooks/useAuth'; import { useAuth } from '@/services/hooks/useAuth';
@@ -74,6 +72,8 @@ const MainDrawer = ({
const formattedPathname = pathname.endsWith('/') ? pathname : `${pathname}/`; const formattedPathname = pathname.endsWith('/') ? pathname : `${pathname}/`;
const isPathnameNotFoundPage = formattedPathname === '/404/';
const isPermitted = ROUTE_PERMISSIONS[formattedPathname]?.some((permission) => const isPermitted = ROUTE_PERMISSIONS[formattedPathname]?.some((permission) =>
permissionCheck(permission) permissionCheck(permission)
); );
@@ -82,10 +82,14 @@ const MainDrawer = ({
setMainDrawerOpen(!mainDrawerOpen); setMainDrawerOpen(!mainDrawerOpen);
}; };
if (!isPermitted) { if (!isPermitted && !isPathnameNotFoundPage) {
return <PermissionNotFound />; return <PermissionNotFound />;
} }
if (isPathnameNotFoundPage) {
return children;
}
return ( return (
<Drawer <Drawer
open={mainDrawerOpen} open={mainDrawerOpen}
+5 -1
View File
@@ -31,7 +31,11 @@ export const useModal = (isNestingModal = false) => {
}, []); }, []);
const toggle = useCallback(() => { const toggle = useCallback(() => {
open ? closeModal() : openModal(); if (open) {
closeModal();
} else {
openModal();
}
}, [open, closeModal, openModal]); }, [open, closeModal, openModal]);
useEffect(() => { useEffect(() => {
+5 -1
View File
@@ -26,13 +26,17 @@ const Navbar = ({ toggleSidebar }: NavbarProps) => {
const logoutClickHandler = async () => { const logoutClickHandler = async () => {
const logoutRes = await AuthApi.logout(); const logoutRes = await AuthApi.logout();
if (isResponseError(logoutRes)) { if (isResponseError(logoutRes)) {
toast.error('Gagal logout! Coba lagi!'); toast.error('Gagal logout! Coba lagi!');
return; return;
} }
setUser(undefined); setUser(undefined);
const redirect = (logoutRes as { redirect?: string })?.redirect;
if (redirect) {
window.location.href = redirect;
return;
}
router.replace(process.env.NEXT_PUBLIC_SSO_LOGIN_URL as string); router.replace(process.env.NEXT_PUBLIC_SSO_LOGIN_URL as string);
}; };
+1 -1
View File
@@ -226,7 +226,7 @@ const Pagination = ({
const PageInfo = () => ( const PageInfo = () => (
<span className='text-nowrap text-sm font-medium text-base-content/50'> <span className='text-nowrap text-sm font-medium text-base-content/50'>
Page {currentPage} of {totalPages} Total Item: {totalItems} | Page {currentPage} of {totalPages}
</span> </span>
); );
+17 -6
View File
@@ -85,8 +85,8 @@ const DUMMY_SKELETON_DATA = Array.from({ length: 10 }, (_, index) => ({
})); }));
const emptyContentDefaultValue = ( const emptyContentDefaultValue = (
<div className='w-full p-5 text-center'> <div className='w-full text-center py-4'>
<span className='text-lg opacity-50'> <span className='text-sm opacity-50'>
Tidak ada data yang dapat ditampilkan... Tidak ada data yang dapat ditampilkan...
</span> </span>
</div> </div>
@@ -173,6 +173,7 @@ const Table = <TData extends object>({
const tableOptions: TableOptions<TData> = { const tableOptions: TableOptions<TData> = {
columns, columns,
data: isLoading ? (DUMMY_SKELETON_DATA as TData[]) : data, // Type assertion data: isLoading ? (DUMMY_SKELETON_DATA as TData[]) : data, // Type assertion
defaultColumn: { sortDescFirst: false },
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(), getSortedRowModel: getSortedRowModel(),
getPaginationRowModel: getPaginationRowModel(), getPaginationRowModel: getPaginationRowModel(),
@@ -452,6 +453,20 @@ const Table = <TData extends object>({
</Fragment> </Fragment>
); );
})} })}
{(data.length === 0 || table.getRowModel().rows.length === 0) &&
!isLoading && (
<tr>
<td
colSpan={
table.getAllLeafColumns().length + (withCheckbox ? 1 : 0)
}
className='p-0'
>
{emptyContent}
</td>
</tr>
)}
</tbody> </tbody>
<tfoot <tfoot
className={cn( className={cn(
@@ -489,10 +504,6 @@ const Table = <TData extends object>({
</table> </table>
</div> </div>
{(data.length === 0 || table.getRowModel().rows.length === 0) &&
!isLoading &&
emptyContent}
{data.length > 0 && {data.length > 0 &&
table.getRowModel().rows.length > 0 && table.getRowModel().rows.length > 0 &&
!isLoading && !isLoading &&
+15 -12
View File
@@ -1,4 +1,4 @@
import { HTMLAttributes, ReactNode, useEffect, useState } from 'react'; import { HTMLAttributes, ReactNode, useState } from 'react';
import { cn } from '@/lib/helper'; import { cn } from '@/lib/helper';
export interface TabItem { export interface TabItem {
@@ -6,6 +6,7 @@ export interface TabItem {
label: ReactNode; label: ReactNode;
content?: ReactNode; content?: ReactNode;
disabled?: boolean; disabled?: boolean;
hide?: boolean;
} }
export interface TabsProps export interface TabsProps
@@ -122,17 +123,19 @@ const Tabs = ({
> >
<div className={getSideContentClasses()}> <div className={getSideContentClasses()}>
<div role='tablist' className={getTabsClasses()}> <div role='tablist' className={getTabsClasses()}>
{tabs.map(({ id, label, disabled }) => ( {tabs.map(({ id, label, disabled, hide }) =>
<button hide ? null : (
key={id} <button
role='tab' key={id}
className={getTabClasses(id === activeTabId, disabled)} role='tab'
onClick={() => !disabled && handleTabChange(id)} className={getTabClasses(id === activeTabId, disabled)}
disabled={disabled} onClick={() => !disabled && handleTabChange(id)}
> disabled={disabled}
{label} >
</button> {label}
))} </button>
)
)}
</div> </div>
{sideContent && sideContent} {sideContent && sideContent}
</div> </div>
+3 -1
View File
@@ -9,6 +9,7 @@ import Button from '@/components/Button';
import { cn, formatDate } from '@/lib/helper'; import { cn, formatDate } from '@/lib/helper';
interface ApprovalStepsV2Props { interface ApprovalStepsV2Props {
title?: string;
approvals?: BaseApproval[]; approvals?: BaseApproval[];
steps: { steps: {
step_number: number; step_number: number;
@@ -23,6 +24,7 @@ interface ApprovalStepsV2Props {
} }
const ApprovalStepsV2 = ({ const ApprovalStepsV2 = ({
title = 'Progress Details',
approvals, approvals,
steps, steps,
maxVisibleSteps = 2, maxVisibleSteps = 2,
@@ -99,7 +101,7 @@ const ApprovalStepsV2 = ({
)} )}
> >
<h4 className='text-base font-medium text-base-content/50 font-roboto'> <h4 className='text-base font-medium text-base-content/50 font-roboto'>
Progress Details {title}
</h4> </h4>
<div <div
+41 -7
View File
@@ -3,15 +3,51 @@ import { getFilledFormikValuesCount } from '@/lib/formik-helper';
import { cn } from '@/lib/helper'; import { cn } from '@/lib/helper';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { FormikValues } from 'formik'; import { FormikValues } from 'formik';
import { useMemo } from 'react';
export type ButtonFilterProps = ButtonProps & { export type ButtonFilterProps = ButtonProps & {
values: FormikValues; values: FormikValues;
onClick: () => void; onClick: () => void;
excludeFields?: string[];
fieldGroups?: string[][];
}; };
// 'bg-gradient-to-t from-blue-50 to-blue-100 border-blue-500 text-blue-600 hover:from-blue-100 hover:to-blue-200 // 'bg-gradient-to-t from-blue-50 to-blue-100 border-blue-500 text-blue-600 hover:from-blue-100 hover:to-blue-200
const ButtonFilter = ({ values, onClick, ...props }: ButtonFilterProps) => { const ButtonFilter = ({
values,
onClick,
excludeFields = [],
fieldGroups = [],
...props
}: ButtonFilterProps) => {
const activeCount = useMemo(() => {
const filteredValues: FormikValues = {};
Object.keys(values).forEach((key) => {
if (!excludeFields.includes(key)) {
filteredValues[key] = values[key];
}
});
let count = getFilledFormikValuesCount(filteredValues);
fieldGroups.forEach((group) => {
const groupFields = group.filter(
(field) => !excludeFields.includes(field)
);
const filledGroupFields = groupFields.filter(
(field) => filteredValues[field]
);
if (
filledGroupFields.length === groupFields.length &&
groupFields.length > 1
) {
count -= groupFields.length - 1;
}
});
return count;
}, [values, excludeFields, fieldGroups]);
return ( return (
<Button <Button
{...props} {...props}
@@ -21,7 +57,7 @@ const ButtonFilter = ({ values, onClick, ...props }: ButtonFilterProps) => {
className={cn( className={cn(
'rounded-lg max-h-10 font-semibold text-sm gap-1.5', 'rounded-lg max-h-10 font-semibold text-sm gap-1.5',
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft', 'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft',
getFilledFormikValuesCount(values) > 0 activeCount > 0
? 'border-primary-gradient text-primary rounded-lg!' ? 'border-primary-gradient text-primary rounded-lg!'
: 'rounded-lg', : 'rounded-lg',
props.className props.className
@@ -31,14 +67,12 @@ const ButtonFilter = ({ values, onClick, ...props }: ButtonFilterProps) => {
icon='heroicons:funnel' icon='heroicons:funnel'
width={20} width={20}
height={20} height={20}
className={ className={activeCount > 0 ? 'text-blue-600' : ''}
getFilledFormikValuesCount(values) > 0 ? 'text-blue-600' : ''
}
/> />
Filter Filter
{getFilledFormikValuesCount(values) > 0 && ( {activeCount > 0 && (
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'> <span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
{getFilledFormikValuesCount(values)} {activeCount}
</span> </span>
)} )}
</Button> </Button>
+17
View File
@@ -0,0 +1,17 @@
import Button from '@/components/Button';
const PageNotFound = () => {
return (
<div className='w-full h-full flex-1 flex flex-col justify-center items-center gap-4'>
<h2 className='text-2xl font-bold text-error'>Halaman Tidak Ditemukan</h2>
<p className='text-gray-600 text-center'>
Halaman atau data yang anda cari tidak ditemukan.
</p>
<Button href='/dashboard' className='text-base-100'>
Kembali ke Dashboard
</Button>
</div>
);
};
export default PageNotFound;
+9 -2
View File
@@ -1,10 +1,17 @@
import Button from '@/components/Button';
const PermissionNotFound = () => { const PermissionNotFound = () => {
return ( return (
<div className='w-full h-screen flex flex-col justify-center items-center gap-4'> <div className='w-full h-screen flex flex-col justify-center items-center gap-4'>
<h2 className='text-2xl font-bold text-error'>Permission Not Found</h2> <h2 className='text-2xl font-bold text-error'>
Hak Akses Tidak Ditemukan
</h2>
<p className='text-gray-600 text-center'> <p className='text-gray-600 text-center'>
You do not have permission to access this page. Anda tidak memiliki hak akses untuk mengakses halaman ini.
</p> </p>
<Button href='/dashboard' className='text-base-100'>
Kembali ke Dashboard
</Button>
</div> </div>
); );
}; };
+9 -1
View File
@@ -1,24 +1,30 @@
import { ReactNode } from 'react';
import Badge from '@/components/Badge'; import Badge from '@/components/Badge';
import { cn } from '@/lib/helper'; import { cn } from '@/lib/helper';
import { Color } from '@/types/theme'; import { Color } from '@/types/theme';
interface StatusBadgeProps { interface StatusBadgeProps {
color: Color; color: Color;
text: string; text: ReactNode;
className?: { className?: {
badge?: string; badge?: string;
status?: string; status?: string;
}; };
onClick?: () => void;
} }
const StatusBadge = ({ const StatusBadge = ({
color = 'neutral', color = 'neutral',
text, text,
className, className,
onClick,
}: StatusBadgeProps) => { }: StatusBadgeProps) => {
return ( return (
<Badge <Badge
variant='soft' variant='soft'
onClick={onClick}
className={{ className={{
badge: cn( badge: cn(
'px-2 py-1 w-full flex flex-row justify-start gap-1 rounded-lg border border-base-content/10 text-xs font-medium text-base-content', 'px-2 py-1 w-full flex flex-row justify-start gap-1 rounded-lg border border-base-content/10 text-xs font-medium text-base-content',
@@ -28,6 +34,7 @@ const StatusBadge = ({
'bg-error/20': color === 'error', 'bg-error/20': color === 'error',
'bg-primary/20': color === 'info', 'bg-primary/20': color === 'info',
'bg-[#FF9A20]/12': color === 'warning', 'bg-[#FF9A20]/12': color === 'warning',
'bg-[#1166EF]/12': color === 'primary',
}, },
className?.badge className?.badge
), ),
@@ -45,6 +52,7 @@ const StatusBadge = ({
'text-error': color === 'error', 'text-error': color === 'error',
'text-primary': color === 'info', 'text-primary': color === 'info',
'text-[#FF9A20]': color === 'warning', 'text-[#FF9A20]': color === 'warning',
'text-[#1166EF]': color === 'primary',
})} })}
> >
<circle r='6' cx='6' cy='6' fill='currentColor' /> <circle r='6' cx='6' cy='6' fill='currentColor' />
@@ -27,7 +27,7 @@ export interface DrawerHeaderProps {
const DrawerHeader = ({ const DrawerHeader = ({
leftIcon = 'mdi:close', leftIcon = 'mdi:close',
leftIconSize = 24, leftIconSize = 20,
leftIconHref, leftIconHref,
leftIconOnClick, leftIconOnClick,
leftIconClassName, leftIconClassName,
@@ -43,7 +43,7 @@ const DrawerHeader = ({
icon={leftIcon} icon={leftIcon}
width={leftIconSize} width={leftIconSize}
height={leftIconSize} height={leftIconSize}
className={cn('cursor-pointer', leftIconClassName)} className={cn('cursor-pointer text-base-content ', leftIconClassName)}
/> />
); );
@@ -73,7 +73,7 @@ const DrawerHeader = ({
return ( return (
<div <div
className={cn( className={cn(
'flex flex-row justify-between items-center px-4 pt-4 pb-4 border-b border-base-content/10', 'flex flex-row justify-between items-center p-4 border-b border-base-content/10',
className className
)} )}
> >
@@ -82,7 +82,7 @@ const DrawerHeader = ({
{renderLeftIcon()} {renderLeftIcon()}
{showDivider && subtitle && ( {showDivider && subtitle && (
<div className='divider divider-horizontal p-0 m-0'></div> <div className='w-px h-full border-none bg-base-content/10' />
)} )}
{subtitle && ( {subtitle && (
+61 -11
View File
@@ -1,7 +1,10 @@
'use client';
import Alert from '@/components/Alert'; import Alert from '@/components/Alert';
import Button from '@/components/Button'; import Button from '@/components/Button';
import { cn } from '@/lib/helper';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import { useState } from 'react'; import { useEffect, useRef } from 'react';
/** /**
* Alert Unique Error List * Alert Unique Error List
@@ -10,34 +13,81 @@ import { useState } from 'react';
*/ */
const AlertErrorList = ({ const AlertErrorList = ({
formErrorList, formErrorList,
className,
onClose, onClose,
title,
}: { }: {
formErrorList: string[]; formErrorList: string[];
className?: {
alert?: string;
button?: string;
headerWrapper?: string;
headerIcon?: string;
headerText?: string;
titleWrapper?: string;
ul?: string;
li?: string;
};
onClose: () => void; onClose: () => void;
title?: string;
}) => { }) => {
const alertRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
if (formErrorList.length > 0) {
alertRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'start',
});
}
}, [formErrorList.length]);
if (formErrorList.length === 0) return null; if (formErrorList.length === 0) return null;
return ( return (
<Alert color='error' className='w-full flex flex-col gap-2 px-4'> <Alert
<div className='flex justify-between items-center gap-2 w-full'> ref={alertRef}
<div className='flex items-center gap-2'> color='error'
<Icon icon='material-symbols:error-outline' width={24} height={24} /> className={cn(
<span className='font-semibold'> 'w-full flex flex-col gap-2 px-3 rounded-lg',
Terdapat {formErrorList.length} error pada form: className?.alert
)}
>
<div
className={cn(
'flex justify-between items-center gap-2 w-full',
className?.headerWrapper
)}
>
<div className={cn('flex items-center gap-2', className?.titleWrapper)}>
<Icon
icon='material-symbols:error-outline'
className={cn(className?.headerIcon)}
width={20}
height={20}
/>
<span className={cn('font-semibold text-sm', className?.headerText)}>
{title || `Terdapat ${formErrorList.length} error pada form:`}
</span> </span>
</div> </div>
<Button <Button
type='button'
onClick={onClose} onClick={onClose}
variant='link' variant='link'
className='ml-auto p-0 w-fit text-white' className={cn('ml-auto p-0 w-fit text-white', className?.button)}
color='none' color='none'
> >
<Icon icon='material-symbols:close' width={24} height={24} /> <Icon icon='material-symbols:close' width={20} height={20} />
</Button> </Button>
</div> </div>
<ul className='list-disc list-inside pl-8 space-y-1 w-full'> <ul
className={cn(
'list-disc list-inside pl-4 space-y-1.5 w-full',
className?.ul
)}
>
{formErrorList.map((error, index) => ( {formErrorList.map((error, index) => (
<li key={index} className='text-sm'> <li key={index} className={cn('text-sm', className?.li)}>
{error} {error}
</li> </li>
))} ))}
@@ -0,0 +1,27 @@
import { Text, View, StyleSheet } from '@react-pdf/renderer';
import type { Style } from '@react-pdf/types';
type PdfParamBadgeProps = {
children: React.ReactNode;
style?: Style;
};
const styles = StyleSheet.create({
parameterBadge: {
backgroundColor: '#F5F5F5',
color: '#333333',
padding: 4,
borderRadius: 4,
fontSize: 8,
marginRight: 8,
marginBottom: 4,
},
});
export const PdfParamBadge = ({ children, style }: PdfParamBadgeProps) => {
return (
<View style={[styles.parameterBadge, ...(style ? [style] : [])]}>
<Text>{children}</Text>
</View>
);
};
@@ -0,0 +1,54 @@
import { Text, View, StyleSheet } from '@react-pdf/renderer';
import type { Style } from '@react-pdf/types';
type PdfStatusBadgeProps = {
children: React.ReactNode;
style?: Style;
};
const styles = StyleSheet.create({
statusBadge: {
paddingVertical: 2,
paddingHorizontal: 4,
borderRadius: 12,
fontSize: 7,
fontWeight: 'bold',
borderWidth: 1,
borderStyle: 'solid',
backgroundColor: '#F5F5F5',
borderColor: '#E5E7EB',
},
statusBadgeText: {
fontSize: 7,
fontWeight: 'bold',
color: '#333333',
},
});
export const PdfStatusBadge = ({ children, style }: PdfStatusBadgeProps) => {
const styleRecord = style as Record<string, unknown>;
const color = styleRecord?.color as string | undefined;
const viewStyle = Object.entries(styleRecord || {}).reduce(
(acc, [key, value]) => {
if (key !== 'color') {
acc[key] = value;
}
return acc;
},
{} as Record<string, unknown>
);
return (
<View
style={[
styles.statusBadge,
...(Object.keys(viewStyle).length > 0 ? [viewStyle as Style] : []),
]}
>
<Text style={[styles.statusBadgeText, ...(color ? [{ color }] : [])]}>
{children}
</Text>
</View>
);
};
@@ -0,0 +1,48 @@
import { Text, View, StyleSheet } from '@react-pdf/renderer';
import type { Style } from '@react-pdf/types';
type PdfPageNumberProps = {
style?: Style;
/**
* Format template for page number.
* Use {pageNumber} and {totalPages} as placeholders.
* Default: "{pageNumber} / {totalPages}"
*/
format?: string;
};
const styles = StyleSheet.create({
footer: {
width: '100%',
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 16,
position: 'absolute',
fontSize: 8,
bottom: 30,
left: 0,
right: 0,
textAlign: 'center',
color: 'grey',
},
});
export const PdfPageNumber = ({
style,
format = '{pageNumber} / {totalPages}',
}: PdfPageNumberProps) => {
return (
<View style={style || styles.footer} fixed>
<Text
render={({ pageNumber, totalPages }) =>
format
.replace('{pageNumber}', String(pageNumber))
.replace('{totalPages}', String(totalPages))
}
fixed
/>
</View>
);
};
+21 -14
View File
@@ -1,9 +1,10 @@
'use client'; 'use client';
import { View, StyleSheet } from '@react-pdf/renderer'; import { View, StyleSheet } from '@react-pdf/renderer';
import { PdfThead, PdfColumn } from './PdfThead'; import type { PdfColumn } from './types';
import { PdfTbody, PdfTbodyCell } from './PdfTbody'; import { PdfThead } from './PdfThead';
import { PdfTfoot, PdfTfootCell } from './PdfTfoot'; import { PdfTbody } from './PdfTbody';
import { PdfTfoot } from './PdfTfoot';
const styles = StyleSheet.create({ const styles = StyleSheet.create({
table: { table: {
@@ -13,10 +14,10 @@ const styles = StyleSheet.create({
}, },
}); });
interface PdfTableProps { interface PdfTableProps<TData = Record<string, unknown>> {
columns: PdfColumn[]; columns: PdfColumn<TData>[];
data: PdfTbodyCell[][]; data: TData[];
footer?: PdfTfootCell[]; showFooter?: boolean;
footerLabel?: string; footerLabel?: string;
firstRow?: { firstRow?: {
valueKey: string; valueKey: string;
@@ -26,20 +27,26 @@ interface PdfTableProps {
}; };
} }
export const PdfTable = ({ export const PdfTable = <TData = Record<string, unknown>,>({
columns, columns,
data, data,
footer, showFooter = false,
footerLabel = 'Total', footerLabel = 'Total',
firstRow, firstRow,
}: PdfTableProps) => { }: PdfTableProps<TData>) => {
// Check if any column has footer defined
const hasFooter =
showFooter || columns.some((col) => col.footer !== undefined);
return ( return (
<View style={styles.table}> <View style={styles.table}>
<PdfThead columns={columns} /> <PdfThead columns={columns} data={data} />
<PdfTbody columns={columns} rows={data} firstRow={firstRow} /> <PdfTbody columns={columns} data={data} firstRow={firstRow} />
{footer && footer.length > 0 && ( {hasFooter && data.length > 0 && (
<PdfTfoot columns={columns} cells={footer} label={footerLabel} /> <PdfTfoot columns={columns} data={data} label={footerLabel} />
)} )}
</View> </View>
); );
}; };
export type { PdfColumn };
+44 -54
View File
@@ -1,22 +1,8 @@
'use client'; 'use client';
import { Text, View, StyleSheet } from '@react-pdf/renderer'; import { Text, View, StyleSheet } from '@react-pdf/renderer';
import { ReactNode } from 'react';
export interface PdfColumn { import type { PdfColumn } from './types';
key: string;
header: string;
flex: number;
align?: 'left' | 'center' | 'right';
}
export interface PdfTbodyCell {
key: string;
value: string | number | React.ReactNode;
align?: 'left' | 'center' | 'right';
color?: string;
formatAs?: 'text' | 'date' | 'currency' | 'number';
formatDate?: string;
}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
tableRow: { tableRow: {
@@ -71,21 +57,22 @@ const styles = StyleSheet.create({
}, },
}); });
interface PdfTbodyProps { interface PdfTbodyProps<TData = Record<string, unknown>> {
columns: PdfColumn[]; columns: PdfColumn<TData>[];
rows: PdfTbodyCell[][]; data: TData[];
firstRow?: { firstRow?: {
valueKey: string; valueKey: string;
value: number; value: number;
align?: 'right'; align?: 'right';
color?: string; color?: string;
}; };
formatDate?: (date: string, format: string) => string;
formatNumber?: (num: number) => string;
formatCurrency?: (num: number) => string;
} }
export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => { export const PdfTbody = <TData = Record<string, unknown>,>({
columns,
data,
firstRow,
}: PdfTbodyProps<TData>) => {
return ( return (
<> <>
{/* First Row */} {/* First Row */}
@@ -93,17 +80,17 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
<View style={[styles.tableRow, styles.tableBorderBottom]}> <View style={[styles.tableRow, styles.tableBorderBottom]}>
{columns.map((column, index) => { {columns.map((column, index) => {
const isLastColumn = index === columns.length - 1; const isLastColumn = index === columns.length - 1;
const isfirstRowColumn = column.key === firstRow.valueKey; const isFirstRowColumn = column.key === firstRow.valueKey;
const align = column.align || 'center'; const align = column.align || 'left';
const cellStyle = const cellStyle =
column.key === 'no' column.key === 'no'
? [styles.tableCellNo, { flex: column.flex }] ? [styles.tableCellNo, { flex: column.flex || 1 }]
: isfirstRowColumn : isFirstRowColumn
? [ ? [
styles.tableCellRight, styles.tableCellRight,
{ {
flex: column.flex, flex: column.flex || 1,
color: firstRow.color || 'black', color: firstRow.color || 'black',
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
@@ -112,7 +99,7 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
? [ ? [
styles.tableCellRight, styles.tableCellRight,
{ {
flex: column.flex, flex: column.flex || 1,
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
] ]
@@ -120,7 +107,7 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
? [ ? [
styles.tableCellCenter, styles.tableCellCenter,
{ {
flex: column.flex, flex: column.flex || 1,
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
] ]
@@ -128,15 +115,15 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
? [ ? [
styles.tableCellLast, styles.tableCellLast,
{ {
flex: column.flex, flex: column.flex || 1,
borderRightWidth: 0, borderRightWidth: 0,
}, },
] ]
: [styles.tableCell, { flex: column.flex }]; : [styles.tableCell, { flex: column.flex || 1 }];
return ( return (
<View key={column.key} style={cellStyle}> <View key={column.key} style={cellStyle}>
<Text>{isfirstRowColumn ? firstRow.value : ''}</Text> <Text>{isFirstRowColumn ? firstRow.value : ''}</Text>
</View> </View>
); );
})} })}
@@ -144,8 +131,8 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
)} )}
{/* Data Rows */} {/* Data Rows */}
{rows.map((row, rowIndex) => { {data.map((row, rowIndex) => {
const isLastRow = rowIndex === rows.length - 1; const isLastRow = rowIndex === data.length - 1;
return ( return (
<View <View
@@ -156,19 +143,27 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
]} ]}
> >
{columns.map((column, colIndex) => { {columns.map((column, colIndex) => {
const cell = row.find((c) => c.key === column.key);
const isLastColumn = colIndex === columns.length - 1; const isLastColumn = colIndex === columns.length - 1;
const align = cell?.align || column.align || 'center'; const align = column.align || 'left';
// Get cell content from column.cell function or fallback to row value
let cellContent: ReactNode;
if (column.cell) {
cellContent = column.cell({ row, index: rowIndex });
} else {
cellContent =
((row as Record<string, unknown>)[column.key] as ReactNode) ??
'-';
}
const cellStyle = const cellStyle =
column.key === 'no' column.key === 'no'
? [styles.tableCellNo, { flex: column.flex }] ? [styles.tableCellNo, { flex: column.flex || 1 }]
: align === 'right' : align === 'right'
? [ ? [
styles.tableCellRight, styles.tableCellRight,
{ {
flex: column.flex, flex: column.flex || 1,
color: cell?.color || 'black',
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
] ]
@@ -176,37 +171,30 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
? [ ? [
styles.tableCellCenter, styles.tableCellCenter,
{ {
flex: column.flex, flex: column.flex || 1,
color: cell?.color || 'black',
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
] ]
: isLastColumn : isLastColumn
? [ ? [
styles.tableCellLast, styles.tableCellLast,
{ flex: column.flex, borderRightWidth: 0 }, { flex: column.flex || 1, borderRightWidth: 0 },
] ]
: [ : [
styles.tableCell, styles.tableCell,
{ {
flex: column.flex, flex: column.flex || 1,
color: cell?.color || 'black',
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
]; ];
return ( return (
<View key={column.key} style={cellStyle}> <View key={column.key} style={cellStyle}>
{cell?.value !== undefined && {typeof cellContent === 'string' ||
cell?.value !== null && typeof cellContent === 'number' ? (
cell?.value !== '' ? ( <Text>{String(cellContent)}</Text>
typeof cell.value === 'object' ? (
cell.value
) : (
<Text>{String(cell.value)}</Text>
)
) : ( ) : (
<Text>-</Text> cellContent
)} )}
</View> </View>
); );
@@ -217,3 +205,5 @@ export const PdfTbody = ({ columns, rows, firstRow }: PdfTbodyProps) => {
</> </>
); );
}; };
export type { PdfColumn };
+48 -38
View File
@@ -1,21 +1,8 @@
'use client'; 'use client';
import { Text, View, StyleSheet } from '@react-pdf/renderer'; import { Text, View, StyleSheet } from '@react-pdf/renderer';
import { ReactNode } from 'react';
export interface PdfColumn { import type { PdfColumn } from './types';
key: string;
header: string;
flex: number;
align?: 'left' | 'center' | 'right';
}
export interface PdfTfootCell {
key: string;
value: string | number;
align?: 'left' | 'center' | 'right';
flex?: number;
color?: string;
}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
tableRow: { tableRow: {
@@ -69,63 +56,86 @@ const styles = StyleSheet.create({
}, },
}); });
interface PdfTfootProps { interface PdfTfootProps<TData = Record<string, unknown>> {
columns: PdfColumn[]; columns: PdfColumn<TData>[];
cells: PdfTfootCell[]; data: TData[];
label?: string; label?: string;
} }
export const PdfTfoot = ({ export const PdfTfoot = <TData = Record<string, unknown>,>({
columns, columns,
cells, data,
label = 'Total', label = 'Total',
}: PdfTfootProps) => { }: PdfTfootProps<TData>) => {
return ( return (
<View style={[styles.tableRow, styles.summaryRow]}> <View style={[styles.tableRow, styles.summaryRow]}>
{columns.map((column, index) => { {columns.map((column, index) => {
const isLastColumn = index === columns.length - 1; const isLastColumn = index === columns.length - 1;
const cellData = cells.find((c) => c.key === column.key);
// Get footer content from column definition
let footerContent: ReactNode;
if (typeof column.footer === 'function') {
footerContent = column.footer(data);
} else {
footerContent = column.footer;
}
// Use label for first column (usually 'no' column)
const displayContent = column.key === 'no' ? label : footerContent;
// Determine alignment
const align = column.footerAlign || column.align || 'left';
const color = column.footerColor || 'black';
const cellStyle = const cellStyle =
column.key === 'no' column.key === 'no'
? [ ? [
styles.tableCellNo, styles.tableCellNo,
{ flex: column.flex, borderRightWidth: isLastColumn ? 0 : 1 }, {
flex: column.flex || 1,
borderRightWidth: isLastColumn ? 0 : 1,
color,
},
] ]
: cellData?.align === 'right' : align === 'right'
? [ ? [
styles.tableCellRight, styles.tableCellRight,
{ {
flex: column.flex, flex: column.flex || 1,
color: cellData?.color || 'black', color,
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
] ]
: cellData?.align === 'center' : align === 'center'
? [ ? [
styles.tableCellCenter, styles.tableCellCenter,
{ {
flex: column.flex, flex: column.flex || 1,
color: cellData?.color || 'black', color,
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
] ]
: isLastColumn : isLastColumn
? [styles.tableCellLast, { flex: column.flex }] ? [styles.tableCellLast, { flex: column.flex || 1, color }]
: [ : [styles.tableCell, { flex: column.flex || 1, color }];
styles.tableCell,
{
flex: column.flex,
color: cellData?.color || 'black',
},
];
return ( return (
<View key={column.key} style={cellStyle}> <View key={column.key} style={cellStyle}>
<Text>{column.key === 'no' ? label : cellData?.value || ''}</Text> {displayContent !== undefined && displayContent !== null ? (
typeof displayContent === 'string' ||
typeof displayContent === 'number' ? (
<Text>{String(displayContent)}</Text>
) : (
displayContent
)
) : (
<Text>-</Text>
)}
</View> </View>
); );
})} })}
</View> </View>
); );
}; };
export type { PdfColumn };
+29 -14
View File
@@ -1,13 +1,8 @@
'use client'; 'use client';
import { Text, View, StyleSheet } from '@react-pdf/renderer'; import { Text, View, StyleSheet } from '@react-pdf/renderer';
import { ReactNode } from 'react';
export interface PdfColumn { import type { PdfColumn } from './types';
key: string;
header: string;
flex: number;
align?: 'left' | 'center' | 'right';
}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
tableRow: { tableRow: {
@@ -48,23 +43,37 @@ const styles = StyleSheet.create({
}, },
}); });
interface PdfTheadProps { interface PdfTheadProps<TData = Record<string, unknown>> {
columns: PdfColumn[]; columns: PdfColumn<TData>[];
data?: TData[];
} }
export const PdfThead = ({ columns }: PdfTheadProps) => { export const PdfThead = <TData = Record<string, unknown>,>({
columns,
data,
}: PdfTheadProps<TData>) => {
return ( return (
<View style={[styles.tableRow, styles.tableHeader]}> <View style={[styles.tableRow, styles.tableHeader]}>
{columns.map((column, index) => { {columns.map((column, index) => {
const align = column.align || 'center';
const isLastColumn = index === columns.length - 1; const isLastColumn = index === columns.length - 1;
// Get header content from column definition
let headerContent: ReactNode;
if (typeof column.header === 'function') {
headerContent = column.header(data || []);
} else {
headerContent = column.header || column.key;
}
// Determine alignment - columns align right by default for numeric data
const align = column.align || 'left';
const cellStyle = const cellStyle =
align === 'right' align === 'right'
? [ ? [
styles.tableCellHeaderRight, styles.tableCellHeaderRight,
{ {
flex: column.flex, flex: column.flex || 1,
textAlign: 'right' as const, textAlign: 'right' as const,
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
@@ -72,7 +81,7 @@ export const PdfThead = ({ columns }: PdfTheadProps) => {
: [ : [
styles.tableCellHeader, styles.tableCellHeader,
{ {
flex: column.flex, flex: column.flex || 1,
textAlign: align as 'left' | 'center' | 'right', textAlign: align as 'left' | 'center' | 'right',
borderRightWidth: isLastColumn ? 0 : 1, borderRightWidth: isLastColumn ? 0 : 1,
}, },
@@ -80,10 +89,16 @@ export const PdfThead = ({ columns }: PdfTheadProps) => {
return ( return (
<View key={column.key} style={cellStyle}> <View key={column.key} style={cellStyle}>
<Text>{column.header}</Text> {typeof headerContent === 'string' ? (
<Text>{headerContent}</Text>
) : (
headerContent
)}
</View> </View>
); );
})} })}
</View> </View>
); );
}; };
export type { PdfColumn };
+1 -3
View File
@@ -2,6 +2,4 @@ export { PdfTable } from './PdfTable';
export { PdfThead } from './PdfThead'; export { PdfThead } from './PdfThead';
export { PdfTbody } from './PdfTbody'; export { PdfTbody } from './PdfTbody';
export { PdfTfoot } from './PdfTfoot'; export { PdfTfoot } from './PdfTfoot';
export type { PdfColumn } from './PdfThead'; export type { PdfColumn } from './types';
export type { PdfTbodyCell } from './PdfTbody';
export type { PdfTfootCell } from './PdfTfoot';
+24
View File
@@ -0,0 +1,24 @@
import { ReactNode } from 'react';
/**
* PdfColumn - Mirip dengan ColumnDef di TanStack Table
* Mengatur header (thead), body (tbody), dan footer (tfoot) dalam satu definisi
*/
export interface PdfColumn<TData = Record<string, unknown>> {
key: string;
flex?: number;
// Header configuration (thead)
header?: string | ((data: TData[]) => ReactNode);
// Body configuration (tbody)
align?: 'left' | 'center' | 'right';
cell?: (props: { row: TData; index: number }) => ReactNode | string | number;
// Footer configuration (tfoot)
footer?: string | number | ((data: TData[]) => ReactNode | string | number);
footerAlign?: 'left' | 'center' | 'right';
footerColor?: string;
}
export type { PdfColumn as default };
@@ -0,0 +1,80 @@
import { Color } from '@/types/theme';
import { Text, StyleSheet } from '@react-pdf/renderer';
import type { Style } from '@react-pdf/types';
type TypographySize = 'h1' | 'h2' | 'h3' | 'h4' | 'p' | 'small' | 'label';
type TypographyVariant = Color | 'default';
type PdfTypographyProps = {
children: React.ReactNode;
size?: TypographySize;
variant?: TypographyVariant;
color?: string;
style?: Style;
};
const styles = StyleSheet.create({
h1: {
fontSize: 14,
fontWeight: 'bold',
marginBottom: 5,
},
h2: {
fontSize: 12,
fontWeight: 'bold',
marginBottom: 8,
},
h3: {
fontSize: 10,
fontWeight: 'bold',
marginBottom: 4,
},
h4: {
fontSize: 9,
fontWeight: 'bold',
marginBottom: 3,
},
p: {
fontSize: 10,
marginBottom: 4,
},
small: {
fontSize: 8,
marginBottom: 2,
},
label: {
fontSize: 9,
marginBottom: 5,
},
});
const variantColors: Record<TypographyVariant, string> = {
default: '#333333',
primary: '#1f74bf',
secondary: '#6B7280',
accent: '#8B5CF6',
neutral: '#6B7280',
info: '#3B82F6',
success: '#065F46',
warning: '#92400E',
error: '#DC2626',
none: '#333333',
};
export const PdfTypography = ({
children,
size = 'p',
variant = 'default',
color,
style,
}: PdfTypographyProps) => {
const sizeStyle = styles[size];
const textColor = color || variantColors[variant];
return (
<Text style={[sizeStyle, { color: textColor }, ...(style ? [style] : [])]}>
{children}
</Text>
);
};
@@ -0,0 +1,65 @@
export type StatusColor = {
bg: string;
text: string;
border: string;
};
// Due status colors (for debt supplier reports)
export const dueStatusColors: Record<string, StatusColor> = {
'SUDAH JATUH TEMPO': {
bg: '#FEE2E2',
text: '#991B1B',
border: '#F87171',
}, // error/red
'BELUM JATUH TEMPO': {
bg: '#D1FAE5',
text: '#065F46',
border: '#34D399',
}, // success/green
'MENDEKATI JATUH TEMPO': {
bg: '#FEF3C7',
text: '#92400E',
border: '#FBBF24',
}, // warning/yellow
};
// Payment status colors (for customer payment & debt supplier reports)
export const paymentStatusColors: Record<string, StatusColor> = {
'BELUM LUNAS': {
bg: '#FEF3C7',
text: '#92400E',
border: '#FBBF24',
}, // warning/yellow
LUNAS: {
bg: '#DBEAFE',
text: '#1E40AF',
border: '#60A5FA',
}, // primary/blue
'PEMBAYARAN SEBAGIAN': { bg: '#D1FAE5', text: '#065F46', border: '#34D399' }, // success/green
PEMBAYARAN: {
bg: '#D1FAE5',
text: '#065F46',
border: '#34D399',
}, // success/green
};
// Fallback color for unknown statuses
export const fallbackStatusColor: StatusColor = {
bg: '#F3F4F6',
text: '#374151',
border: '#D1D5DB',
}; // neutral
export const getPDFBadgeStyle = (
statusText: string,
type: 'due' | 'payment' = 'payment'
): StatusColor => {
const normalizedStatus = statusText.toUpperCase().trim();
const colors =
type === 'due'
? dueStatusColors[normalizedStatus]
: paymentStatusColors[normalizedStatus];
return colors || fallbackStatusColor;
};
@@ -1,5 +1,4 @@
import IconSkeleton from '@/components/helper/skeleton/IconSkeleton'; import IconSkeleton from '@/components/helper/skeleton/IconSkeleton';
import { Icon } from '@iconify/react';
const DataStateSkeleton = ({ const DataStateSkeleton = ({
icon, icon,
@@ -7,6 +7,7 @@ import TextArea, { TextAreaProps } from '@/components/input/TextArea';
interface DebouncedTextAreaProps extends TextAreaProps { interface DebouncedTextAreaProps extends TextAreaProps {
delay?: number; delay?: number;
ref?: React.RefObject<HTMLTextAreaElement | null>;
} }
const DebouncedTextArea = (props: DebouncedTextAreaProps) => { const DebouncedTextArea = (props: DebouncedTextAreaProps) => {
@@ -19,6 +20,11 @@ const DebouncedTextArea = (props: DebouncedTextAreaProps) => {
const [debouncedChangeEvent] = useDebounce(internalChangeEvent, delay ?? 300); const [debouncedChangeEvent] = useDebounce(internalChangeEvent, delay ?? 300);
const [debouncedValue] = useDebounce(internalValue, delay ?? 300); const [debouncedValue] = useDebounce(internalValue, delay ?? 300);
// Sync internal value with external props.value when it changes (e.g., form reset)
useEffect(() => {
setInternalValue(props.value);
}, [props.value]);
const internalChangeHandler: ChangeEventHandler<HTMLTextAreaElement> = ( const internalChangeHandler: ChangeEventHandler<HTMLTextAreaElement> = (
e e
) => { ) => {
@@ -35,6 +41,7 @@ const DebouncedTextArea = (props: DebouncedTextAreaProps) => {
return ( return (
<TextArea <TextArea
{...props} {...props}
ref={props.ref}
value={internalValue} value={internalValue}
onChange={internalChangeHandler} onChange={internalChangeHandler}
/> />
+8 -2
View File
@@ -134,14 +134,20 @@ const DropFileInput: React.FC<DropFileInputProps> = ({
{!isError && bottomLabel && ( {!isError && bottomLabel && (
<p <p
className={cn('w-full text-sm opacity-60', className?.bottomLabel)} className={cn(
'w-full mt-1.5 text-xs opacity-60',
className?.bottomLabel
)}
> >
{bottomLabel} {bottomLabel}
</p> </p>
)} )}
{isError && ( {isError && (
<p <p
className={cn('w-full text-sm text-error', className?.errorMessage)} className={cn(
'w-full mt-1.5 text-xs text-error',
className?.errorMessage
)}
> >
{errorMessage} {errorMessage}
</p> </p>
+3 -1
View File
@@ -35,7 +35,9 @@ const NumberInput = ({
| undefined; | undefined;
if (newChangeEvent) { if (newChangeEvent) {
newChangeEvent.target.value = numberFormatValues.value; newChangeEvent.target.value = parseFloat(
numberFormatValues.value
) as unknown as string;
onChange?.(newChangeEvent); onChange?.(newChangeEvent);
} }
-1
View File
@@ -4,7 +4,6 @@ import { ChangeEvent } from 'react';
import { import {
PatternFormat, PatternFormat,
NumberFormatBase, NumberFormatBase,
NumberFormatBaseProps,
OnValueChange, OnValueChange,
} from 'react-number-format'; } from 'react-number-format';
import TextInput, { TextInputProps } from '@/components/input/TextInput'; import TextInput, { TextInputProps } from '@/components/input/TextInput';
+2 -2
View File
@@ -144,12 +144,12 @@ export const RadioGroup = ({
{/* Label bawah */} {/* Label bawah */}
{!isError && bottomLabel && ( {!isError && bottomLabel && (
<p className='text-sm opacity-60'>{bottomLabel}</p> <p className='mt-1.5 text-xs opacity-60'>{bottomLabel}</p>
)} )}
{/* Pesan error */} {/* Pesan error */}
{isError && errorMessage && ( {isError && errorMessage && (
<p className='text-sm text-error'>{errorMessage}</p> <p className='mt-1.5 text-xs text-error'>{errorMessage}</p>
)} )}
</div> </div>
</RadioGroupContext.Provider> </RadioGroupContext.Provider>
+62 -57
View File
@@ -24,8 +24,8 @@ import {
} from '@/types/api/api-general'; } from '@/types/api/api-general';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper'; import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
export interface OptionType { export interface OptionType<T = string | number> {
value: string | number; value: T;
label: string; label: string;
className?: string; className?: string;
labelClassName?: string; labelClassName?: string;
@@ -246,8 +246,8 @@ const SelectInput = <T extends OptionType>(props: SelectInputProps<T>) => {
className={cn( className={cn(
'inline-flex items-center px-3 border border-r-0 border-base-content/10 rounded-l-lg transition-all duration-200', 'inline-flex items-center px-3 border border-r-0 border-base-content/10 rounded-l-lg transition-all duration-200',
{ {
'bg-gray-100 border-base-content/10': !isDisabled, 'bg-base-100 border-base-content/10': !isDisabled,
'bg-gray-50 border-base-content/10': isDisabled, 'bg-base-200 border-base-content/10': isDisabled,
'border-error': isError, 'border-error': isError,
}, },
className?.inputPrefix className?.inputPrefix
@@ -278,28 +278,28 @@ const SelectInput = <T extends OptionType>(props: SelectInputProps<T>) => {
className={cn('w-full flex-1', className?.select)} className={cn('w-full flex-1', className?.select)}
classNames={{ classNames={{
control: ({ isFocused, isDisabled }) => control: ({ isFocused, isDisabled }) =>
cn('w-full border bg-white transition-shadow', 'rounded-lg!', { cn('w-full border transition-shadow', 'rounded-lg!', {
'cursor-pointer!': !readOnly && !isDisabled, 'bg-base-100!': !isDisabled && !readOnly,
'border-red-500! ring-2 ring-red-200': isError, 'bg-base-200! text-gray-400 cursor-not-allowed':
'border-indigo-500 ring-2 ring-indigo-200':
isFocused && !startAdornment,
'border-base-content/10!': !isError && !isFocused,
'bg-gray-100 text-gray-400 cursor-not-allowed':
isDisabled && !readOnly, isDisabled && !readOnly,
'bg-transparent! cursor-not-allowed!': readOnly, 'bg-transparent! cursor-not-allowed!': readOnly,
'cursor-pointer!': !readOnly && !isDisabled,
'border-error!': isError,
'ring-2 ring-error/20': isError,
'border-indigo-500 ring-2 ring-indigo-200':
isFocused && !startAdornment && !isError,
'border-base-content/10!': !isError && !isFocused,
'rounded-l-none!': inputPrefix && !startAdornment, 'rounded-l-none!': inputPrefix && !startAdornment,
'rounded-r-none!': inputSuffix && !startAdornment, 'rounded-r-none!': inputSuffix && !startAdornment,
}), }),
valueContainer: () => cn('flex-1 px-3! pr-2! py-2.5! gap-1'), valueContainer: () => cn('flex-1 px-3! pr-2! py-2.5! gap-1'),
placeholder: () => placeholder: () =>
cn({ cn('text-gray-400 text-sm leading-tight', {
'text-gray-400 text-sm leading-tight': !isError, 'text-error!': isError,
'text-red-300!': isError,
}), }),
singleValue: () => singleValue: () =>
cn({ cn('m-0! text-gray-900 text-sm leading-tight', {
'm-0! text-gray-900 text-sm leading-tight': !isError, 'text-error!': isError && !readOnly,
'text-error!': isError,
'text-gray-900!': readOnly, 'text-gray-900!': readOnly,
}), }),
input: () => cn('text-gray-900 m-0! p-0! text-sm leading-tight'), input: () => cn('text-gray-900 m-0! p-0! text-sm leading-tight'),
@@ -370,8 +370,8 @@ const SelectInput = <T extends OptionType>(props: SelectInputProps<T>) => {
className={cn( className={cn(
'inline-flex items-center px-3 border border-l-0 border-base-content/10 rounded-r-lg transition-all duration-200', 'inline-flex items-center px-3 border border-l-0 border-base-content/10 rounded-r-lg transition-all duration-200',
{ {
'bg-gray-100 border-base-content/10': !isDisabled, 'bg-base-100 border-base-content/10': !isDisabled,
'bg-gray-50 border-base-content/10': isDisabled, 'bg-base-200 border-base-content/10': isDisabled,
'border-error': isError, 'border-error': isError,
}, },
className?.inputSuffix className?.inputSuffix
@@ -403,31 +403,26 @@ const SelectInput = <T extends OptionType>(props: SelectInputProps<T>) => {
className={cn('w-full', className?.select)} className={cn('w-full', className?.select)}
classNames={{ classNames={{
control: ({ isFocused, isDisabled }) => control: ({ isFocused, isDisabled }) =>
cn( cn('w-full border transition-shadow rounded-lg!', {
'w-full border bg-white transition-shadow', 'bg-base-100!': !isDisabled && !readOnly,
// Gunakan rounded-lg untuk semua kasus 'bg-base-200! text-gray-400 cursor-not-allowed':
'rounded-lg!', isDisabled && !readOnly,
{ 'bg-transparent! cursor-not-allowed!': readOnly,
'cursor-pointer!': !readOnly && !isDisabled, 'cursor-pointer!': !readOnly && !isDisabled,
'border-red-500! ring-2 ring-red-200': isError, 'border-error!': isError,
'border-indigo-500 ring-2 ring-indigo-200': 'ring-2 ring-error/20': isError,
isFocused && !startAdornment, 'border-indigo-500 ring-2 ring-indigo-200':
'border-base-content/10!': !isError && !isFocused, isFocused && !startAdornment && !isError,
'bg-gray-100 text-gray-400 cursor-not-allowed': 'border-base-content/10!': !isError && !isFocused,
isDisabled && !readOnly, }),
'bg-transparent! cursor-not-allowed!': readOnly,
}
),
valueContainer: () => cn('flex-1 px-3! pr-2! py-2.5! gap-1'), valueContainer: () => cn('flex-1 px-3! pr-2! py-2.5! gap-1'),
placeholder: () => placeholder: () =>
cn({ cn('text-gray-400 text-sm leading-tight', {
'text-gray-400 text-sm leading-tight': !isError, 'text-error!': isError,
'text-red-300!': isError,
}), }),
singleValue: () => singleValue: () =>
cn({ cn('m-0! text-gray-900 text-sm leading-tight', {
'm-0! text-gray-900 text-sm leading-tight': !isError, 'text-error!': isError && !readOnly,
'text-error!': isError,
'text-gray-900!': readOnly, 'text-gray-900!': readOnly,
}), }),
input: () => cn('text-gray-900 m-0! p-0! text-sm leading-tight'), input: () => cn('text-gray-900 m-0! p-0! text-sm leading-tight'),
@@ -493,9 +488,11 @@ const SelectInput = <T extends OptionType>(props: SelectInputProps<T>) => {
/> />
)} )}
{isError && <p className='w-full text-sm text-error'>{errorMessage}</p>} {isError && (
<p className='w-full mt-1.5 text-xs text-error'>{errorMessage}</p>
)}
{!isError && bottomLabel && ( {!isError && bottomLabel && (
<p className='w-full text-sm opacity-60'>{bottomLabel}</p> <p className='w-full mt-1.5 text-xs opacity-60'>{bottomLabel}</p>
)} )}
</div> </div>
); );
@@ -526,7 +523,7 @@ const useSelect = <T,>(
const qs = new URLSearchParams({ const qs = new URLSearchParams({
...(params ?? {}), ...(params ?? {}),
[searchKey]: inputValue ?? '', [searchKey ? searchKey : 'search']: inputValue ?? '',
[pageKey]: String(pageIndex + 1), [pageKey]: String(pageIndex + 1),
[limitKey]: String(limit), [limitKey]: String(limit),
}).toString(); }).toString();
@@ -569,23 +566,31 @@ const useSelect = <T,>(
setSize(size + 1); setSize(size + 1);
}; };
let formattedSuccessRawData: SuccessApiResponse<T[]> | undefined = undefined;
let formattedErrorRawData: ErrorApiResponse | undefined = undefined;
const latestPagesIndex = pages?.length ? pages.length - 1 : 0; const latestPagesIndex = pages?.length ? pages.length - 1 : 0;
if (isResponseSuccess(pages?.[latestPagesIndex])) { const { formattedSuccessRawData, formattedErrorRawData } = useMemo(() => {
formattedSuccessRawData = { let successData: SuccessApiResponse<T[]> | undefined = undefined;
...pages?.[latestPagesIndex], let errorData: ErrorApiResponse | undefined = undefined;
data:
pages?.flatMap((page) => (isResponseSuccess(page) ? page.data : [])) ??
[],
};
}
if (isResponseError(pages?.[latestPagesIndex])) { if (isResponseSuccess(pages?.[latestPagesIndex])) {
formattedErrorRawData = pages?.[latestPagesIndex]; successData = {
} ...pages![latestPagesIndex],
data:
pages?.flatMap((page) =>
isResponseSuccess(page) ? page.data : []
) ?? [],
};
}
if (isResponseError(pages?.[latestPagesIndex])) {
errorData = pages![latestPagesIndex];
}
return {
formattedSuccessRawData: successData,
formattedErrorRawData: errorData,
};
}, [pages, latestPagesIndex]);
return { return {
inputValue, inputValue,
+4 -2
View File
@@ -159,9 +159,11 @@ const TagInput: React.FC<TagInputProps> = ({
{/* Bottom label or error message */} {/* Bottom label or error message */}
{!isError && bottomLabel && ( {!isError && bottomLabel && (
<p className='w-full text-sm opacity-60'>{bottomLabel}</p> <p className='w-full mt-1.5 text-xs opacity-60'>{bottomLabel}</p>
)}
{isError && (
<p className='w-full mt-1.5 text-xs text-error'>{errorMessage}</p>
)} )}
{isError && <p className='w-full text-sm text-error'>{errorMessage}</p>}
</div> </div>
); );
}; };
+3
View File
@@ -28,6 +28,7 @@ export interface TextAreaProps {
onChange?: ChangeEventHandler<HTMLTextAreaElement>; onChange?: ChangeEventHandler<HTMLTextAreaElement>;
onBlur?: FocusEventHandler<HTMLTextAreaElement>; onBlur?: FocusEventHandler<HTMLTextAreaElement>;
rows?: number; rows?: number;
ref?: React.RefObject<HTMLTextAreaElement | null>;
} }
const TextArea = ({ const TextArea = ({
@@ -49,6 +50,7 @@ const TextArea = ({
readOnly = false, readOnly = false,
isLoading = false, isLoading = false,
rows = 3, rows = 3,
ref,
}: TextAreaProps) => { }: TextAreaProps) => {
return ( return (
<div <div
@@ -99,6 +101,7 @@ const TextArea = ({
onBlur={onBlur} onBlur={onBlur}
disabled={disabled} disabled={disabled}
readOnly={readOnly} readOnly={readOnly}
ref={ref}
/> />
{(isLoading || endAdornment) && ( {(isLoading || endAdornment) && (
+18 -8
View File
@@ -104,8 +104,8 @@ const TextInput = ({
className={cn( className={cn(
'inline-flex items-center px-3 border border-r-0 border-base-content/10 rounded-l-lg transition-all duration-200', 'inline-flex items-center px-3 border border-r-0 border-base-content/10 rounded-l-lg transition-all duration-200',
{ {
'bg-gray-100 border-base-content/10': !disabled, 'bg-base-100 border-base-content/10': !disabled,
'bg-gray-50 border-base-content/10': disabled, 'bg-base-200 border-base-content/10': disabled,
'border-error': isError, 'border-error': isError,
'border-success!': isValid, 'border-success!': isValid,
}, },
@@ -118,7 +118,7 @@ const TextInput = ({
<div <div
className={cn( className={cn(
'input h-fit px-3 py-2.5 gap-1.5 text-sm font-normal leading-6 flex-1 rounded-lg! outline-none! transition-all duration-200 flex items-center bg-white border-base-content/10', 'input h-fit px-3 py-2.5 gap-1.5 text-sm font-normal leading-6 flex-1 rounded-lg! outline-none! transition-all duration-200 flex items-center border-base-content/10',
{ {
'border-error': isError, 'border-error': isError,
'border-success!': isValid, 'border-success!': isValid,
@@ -126,7 +126,8 @@ const TextInput = ({
'rounded-r-none!': inputSuffix, 'rounded-r-none!': inputSuffix,
'input-disabled': disabled, 'input-disabled': disabled,
'cursor-not-allowed': disabled, 'cursor-not-allowed': disabled,
'bg-gray-50': disabled, 'bg-base-100': !disabled,
'bg-base-200': disabled,
}, },
className?.inputWrapper className?.inputWrapper
)} )}
@@ -167,8 +168,8 @@ const TextInput = ({
className={cn( className={cn(
'inline-flex items-center px-3 border border-l-0 border-base-content/10 rounded-r-lg transition-all duration-200', 'inline-flex items-center px-3 border border-l-0 border-base-content/10 rounded-r-lg transition-all duration-200',
{ {
'bg-gray-100 border-base-content/10': !disabled, 'bg-base-100 border-base-content/10': !disabled,
'bg-gray-50 border-base-content/10': disabled, 'bg-base-200 border-base-content/10': disabled,
'border-error': isError, 'border-error': isError,
'border-success!': isValid, 'border-success!': isValid,
}, },
@@ -182,10 +183,12 @@ const TextInput = ({
) : ( ) : (
<div <div
className={cn( className={cn(
'input h-fit px-3 py-2.5 gap-1.5 text-sm font-normal leading-6 w-full rounded-lg! outline-none! transition-all duration-200 bg-white border-base-content/10', 'input h-fit px-3 py-2.5 gap-1.5 text-sm font-normal leading-6 w-full rounded-lg! outline-none! transition-all duration-200 flex items-center border-base-content/10',
{ {
'border-error': isError, 'border-error': isError,
'border-success!': isValid, 'border-success!': isValid,
'bg-base-100': !disabled,
'bg-base-200': disabled,
}, },
className?.inputWrapper className?.inputWrapper
)} )}
@@ -201,7 +204,14 @@ const TextInput = ({
onChange={onChange} onChange={onChange}
onBlur={onBlur} onBlur={onBlur}
disabled={disabled} disabled={disabled}
className={cn('grow', className?.input)} className={cn(
'grow bg-transparent outline-none',
{
'cursor-not-allowed': disabled,
'text-gray-500': disabled,
},
className?.input
)}
readOnly={readOnly} readOnly={readOnly}
/> />
+70 -59
View File
@@ -122,10 +122,18 @@ const ConfirmationModal = ({
closeOnBackdrop={closeOnBackdrop} closeOnBackdrop={closeOnBackdrop}
className={{ className={{
...className, ...className,
modalBox: cn('rounded-xl p-4', className?.modalBox), modalBox: cn(
'rounded-xl p-4 flex flex-col gap-4 max-h-[90vh]',
className?.modalBox
),
}} }}
> >
<div className='w-full flex flex-col gap-4'> <div
className={cn(
'flex flex-col gap-4',
children && 'sticky top-0 bg-inherit z-10'
)}
>
{iconPosition === 'center' ? ( {iconPosition === 'center' ? (
<> <>
<div className='w-fit mx-auto'> <div className='w-fit mx-auto'>
@@ -164,71 +172,74 @@ const ConfirmationModal = ({
</div> </div>
</div> </div>
)} )}
</div>
{children && <div className='w-full'>{children}</div>} {children && (
<div className='w-full flex-1 overflow-y-auto'>{children}</div>
)}
{(secondaryButton || primaryButton) && ( {(secondaryButton || primaryButton) && (
<div <div
className={cn('w-full grid gap-3', { className={cn(
'w-full grid gap-3',
children && 'sticky bottom-0 bg-inherit z-10',
{
'grid-cols-2': secondaryButton && primaryButton, 'grid-cols-2': secondaryButton && primaryButton,
'grid-cols-1': 'grid-cols-1':
(secondaryButton && !primaryButton) || (secondaryButton && !primaryButton) ||
(!secondaryButton && primaryButton), (!secondaryButton && primaryButton),
})} }
> )}
{secondaryButton && secondaryButton.text && ( >
<Button {secondaryButton && secondaryButton.text && (
{...secondaryButton} <Button
variant='outline' {...secondaryButton}
color={secondaryButton?.color} variant='outline'
isLoading={secondaryButton?.isLoading} color={secondaryButton?.color}
disabled={ isLoading={secondaryButton?.isLoading}
secondaryButton?.isLoading !== undefined disabled={
? secondaryButton?.isLoading secondaryButton?.isLoading !== undefined
: isPrimaryButtonLoading ? secondaryButton?.isLoading
: isPrimaryButtonLoading
}
onClick={(e) => {
if (secondaryButton?.onClick) {
secondaryButton.onClick(e);
} else {
closeModalHandler();
} }
onClick={(e) => { }}
if (secondaryButton?.onClick) { className={cn(
secondaryButton.onClick(e); 'p-2 rounded-xl text-sm',
} else { secondaryButton?.className
closeModalHandler(); )}
} >
}} {secondaryButton?.text ?? 'Tidak'}
className={cn( </Button>
'p-2 rounded-xl text-sm', )}
secondaryButton?.className
)}
>
{secondaryButton?.text ?? 'Tidak'}
</Button>
)}
{primaryButton && primaryButton.text && ( {primaryButton && primaryButton.text && (
<Button <Button
{...primaryButton} {...primaryButton}
color={primaryButton?.color ?? 'info'} color={primaryButton?.color ?? 'info'}
onClick={primaryButtonClickHandler} onClick={primaryButtonClickHandler}
isLoading={ isLoading={
primaryButton?.isLoading !== undefined primaryButton?.isLoading !== undefined
? primaryButton?.isLoading ? primaryButton?.isLoading
: isPrimaryButtonLoading : isPrimaryButtonLoading
} }
disabled={ disabled={
primaryButton?.isLoading !== undefined primaryButton?.isLoading !== undefined
? primaryButton?.isLoading ? primaryButton?.isLoading
: isPrimaryButtonLoading : isPrimaryButtonLoading
} }
className={cn( className={cn('p-2 rounded-xl text-sm', primaryButton?.className)}
'p-2 rounded-xl text-sm', >
primaryButton?.className {primaryButton?.text ?? 'Ya'}
)} </Button>
> )}
{primaryButton?.text ?? 'Ya'} </div>
</Button> )}
)}
</div>
)}
</div>
</Modal> </Modal>
); );
}; };
@@ -13,6 +13,7 @@ interface ConfirmationModalWithNotesProps
extends Omit<ConfirmationModalProps, 'children' | 'primaryButton'> { extends Omit<ConfirmationModalProps, 'children' | 'primaryButton'> {
rows?: number; rows?: number;
placeholder?: string; placeholder?: string;
onClose?: () => void;
primaryButton?: { primaryButton?: {
text?: string; text?: string;
@@ -32,6 +33,7 @@ const ConfirmationModalWithNotes: React.FC<ConfirmationModalWithNotesProps> = ({
className, className,
rows = 3, rows = 3,
placeholder = 'Catatan...', placeholder = 'Catatan...',
onClose,
...props ...props
}) => { }) => {
const randomId = useId(); const randomId = useId();
@@ -41,6 +43,11 @@ const ConfirmationModalWithNotes: React.FC<ConfirmationModalWithNotesProps> = ({
setNotes(e.target.value); setNotes(e.target.value);
}; };
const closeModalHandler = () => {
onClose?.();
ref.current?.close();
};
return ( return (
<ConfirmationModal <ConfirmationModal
ref={ref} ref={ref}
@@ -50,11 +57,32 @@ const ConfirmationModalWithNotes: React.FC<ConfirmationModalWithNotesProps> = ({
primaryButton={{ primaryButton={{
...primaryButton, ...primaryButton,
onClick: () => { onClick: () => {
primaryButton?.onClick?.(notes); if (primaryButton && primaryButton?.onClick) {
primaryButton?.onClick?.(notes);
} else {
closeModalHandler();
}
setNotes(''); setNotes('');
}, },
}} }}
secondaryButton={secondaryButton} secondaryButton={
secondaryButton
? {
...secondaryButton,
text: secondaryButton?.text ?? 'Tidak',
onClick: (e) => {
if (secondaryButton && secondaryButton?.onClick) {
secondaryButton.onClick?.(e);
} else {
closeModalHandler();
}
setNotes('');
},
}
: undefined
}
className={className} className={className}
{...props} {...props}
> >
+4 -1
View File
@@ -309,9 +309,10 @@ const useApprovalSteps = ({
moduleId: string; moduleId: string;
params?: { params?: {
page?: number; page?: number;
limit: number | string; limit?: number | string;
search?: string; search?: string;
group_step_number?: boolean; group_step_number?: boolean;
order_by_date?: 'ASC' | 'DESC';
}; };
}) => { }) => {
// Membuat URL Parameters // Membuat URL Parameters
@@ -319,6 +320,8 @@ const useApprovalSteps = ({
page: params?.page?.toString() || '', page: params?.page?.toString() || '',
limit: params?.limit?.toString() || '', limit: params?.limit?.toString() || '',
search: params?.search || '', search: params?.search || '',
group_step_number: params?.group_step_number?.toString() || '',
order_by_date: params?.order_by_date || '',
}).toString(); }).toString();
// fetching data approvals // fetching data approvals
@@ -5,28 +5,23 @@ import { useMemo, useState } from 'react';
import { Icon } from '@iconify/react'; import { Icon } from '@iconify/react';
import Button from '@/components/Button'; import Button from '@/components/Button';
import Tabs from '@/components/Tabs'; import Tabs from '@/components/Tabs';
import ClosingGeneralInformationTable from '@/components/pages/closing/ClosingGeneralInformationTable'; import ClosingGeneralInformationTable from '@/components/pages/closing/table/ClosingGeneralInformationTable';
import ClosingSapronakTabContent from '@/components/pages/closing/ClosingSapronakTabContent'; import SapronakClosingTab from '@/components/pages/closing/tab/SapronakClosingTab';
import ClosingProductionDataTabContent from '@/components/pages/closing/ClosingProductionDataTabContent'; import ProductionDataClosingTab from '@/components/pages/closing/tab/ProductionDataClosingTab';
import { import { ClosingGeneralInformation } from '@/types/api/closing';
ClosingGeneralInformation, import SapronakCalculationClosingTab from '@/components/pages/closing/tab/SapronakCalculationClosingTab';
BaseClosingSales, import OverheadClosingTab from '@/components/pages/closing/tab/OverheadClosingTab';
ClosingHppExpedition, import FinanceClosingTab from '@/components/pages/closing/tab/FinanceClosingTab';
} from '@/types/api/closing'; import SalesClosingTab from '@/components/pages/closing/tab/SalesClosingTab';
import ClosingSapronakCalculationTabContent from '@/components/pages/closing/ClosingSapronakCalculationTabContent'; import HppExpeditionClosingTab from '@/components/pages/closing/tab/HppExpeditionClosingTab';
import ClosingOverheadTabContent from '@/components/pages/closing/ClosingOverheadTabContent';
import ClosingFinanceTabContent from '@/components/pages/closing/ClosingFinanceTabContent';
import SalesReportTable from '@/components/pages/closing/sale/SalesReportTable';
import HppExpeditionReportTable from './hpp-ekspedisi/HppExpeditionReportTable';
import ClosingKandangList from '@/components/pages/closing/ClosingKandangList'; import ClosingKandangList from '@/components/pages/closing/ClosingKandangList';
import { ProjectFlock } from '@/types/api/production/project-flock'; import { ProjectFlock } from '@/types/api/production/project-flock';
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang'; import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
import { useTabActionsStore } from '@/stores/tab-actions/tab-actions.store';
interface ClosingDetailProps { interface ClosingDetailProps {
id: number; id: number;
initialValue?: ClosingGeneralInformation; initialValue?: ClosingGeneralInformation;
salesData?: BaseClosingSales;
hppExpeditionData?: ClosingHppExpedition;
projectData?: ProjectFlock; projectData?: ProjectFlock;
kandangData?: ProjectFlockKandang; kandangData?: ProjectFlockKandang;
} }
@@ -34,25 +29,24 @@ interface ClosingDetailProps {
const ClosingDetail: React.FC<ClosingDetailProps> = ({ const ClosingDetail: React.FC<ClosingDetailProps> = ({
id, id,
initialValue, initialValue,
salesData,
hppExpeditionData,
projectData, projectData,
kandangData, kandangData,
}) => { }) => {
const [activeTab, setActiveTab] = useState<string>('sapronak'); const [activeTabId, setActiveTabId] = useState<string>('sapronak');
const tabActions = useTabActionsStore((state) => state.tabActions);
const closingDetailTabs = useMemo(() => { const closingDetailTabs = useMemo(() => {
const validTabs = [ const validTabs = [
{ {
id: 'sapronak', id: 'sapronak',
label: 'Sapronak', label: 'Sapronak',
content: <ClosingSapronakTabContent projectFlockId={id} />, content: <SapronakClosingTab projectFlockId={id} />,
}, },
{ {
id: 'perhitunganSapronak', id: 'perhitunganSapronak',
label: 'Perhitungan Sapronak', label: 'Perhitungan Sapronak',
content: ( content: (
<ClosingSapronakCalculationTabContent <SapronakCalculationClosingTab
closingGeneralInformation={initialValue} closingGeneralInformation={initialValue}
projectFlockId={id} projectFlockId={id}
/> />
@@ -61,36 +55,42 @@ const ClosingDetail: React.FC<ClosingDetailProps> = ({
{ {
id: 'penjualan', id: 'penjualan',
label: 'Penjualan', label: 'Penjualan',
content: <SalesReportTable initialValues={salesData} />, content: <SalesClosingTab projectFlockId={id} />,
}, },
{ {
id: 'overhead', id: 'overhead',
label: 'Overhead', label: 'Overhead',
content: <ClosingOverheadTabContent projectFlockId={id} />, content: (
<OverheadClosingTab
projectFlockId={id}
generalInformation={initialValue}
kandangData={kandangData}
/>
),
}, },
{ {
id: 'hppEkspedisi', id: 'hppEkspedisi',
label: 'HPP Ekspedisi', label: 'HPP Ekspedisi',
content: <HppExpeditionReportTable initialValues={hppExpeditionData} />, content: <HppExpeditionClosingTab projectFlockId={id} />,
}, },
{ {
id: 'dataProduksi', id: 'dataProduksi',
label: 'Data Produksi', label: 'Data Produksi',
content: <ClosingProductionDataTabContent projectFlockId={id} />, content: <ProductionDataClosingTab projectFlockId={id} />,
}, },
{ {
id: 'keuangan', id: 'keuangan',
label: 'Keuangan', label: 'Keuangan',
content: <ClosingFinanceTabContent projectFlockId={id} />, content: <FinanceClosingTab projectFlockId={id} />,
}, },
]; ];
return validTabs; return validTabs;
}, [initialValue]); }, [initialValue, kandangData, id]);
return ( return (
<> <>
<section className='w-full max-w-7xl pb-16'> <section className='w-full'>
<header className='flex flex-col gap-4'> <header className='flex flex-col gap-4'>
<Button <Button
href={ href={
@@ -112,21 +112,24 @@ const ClosingDetail: React.FC<ClosingDetailProps> = ({
kandangData={kandangData} kandangData={kandangData}
/> />
{!kandangData && ( <ClosingKandangList
<ClosingKandangList initialValue={initialValue}
initialValue={initialValue} projectData={projectData}
projectData={projectData} selectedKandangId={kandangData?.id}
/> />
)}
<Tabs <Tabs
activeTabId={activeTab} activeTabId={activeTabId}
onTabChange={setActiveTab} onTabChange={setActiveTabId}
tabs={closingDetailTabs} tabs={closingDetailTabs}
variant='lifted' variant='boxed'
className={{ className={{
wrapper: 'w-full mt-4', tabHeaderWrapper:
'relative justify-between items-center py-3 before:absolute before:top-0 before:left-0 before:right-0 before:-mx-4 before:border-t before:border-base-content/10 after:absolute after:bottom-0 after:left-0 after:right-0 after:-mx-4 after:border-b after:border-base-content/10',
tab: 'w-fit',
content: 'p-0 m-0',
}} }}
sideContent={tabActions[activeTabId] || null}
/> />
</section> </section>
</> </>
@@ -1,17 +0,0 @@
import ClosingFinanceTable from '@/components/pages/closing/ClosingFinanceTable';
const ClosingFinanceTabContent = ({
projectFlockId,
}: {
projectFlockId: number;
}) => {
return (
<div className='flex flex-col gap-4'>
{projectFlockId && (
<ClosingFinanceTable projectFlockId={projectFlockId} />
)}
</div>
);
};
export default ClosingFinanceTabContent;

Some files were not shown because too many files have changed in this diff Show More