Compare commits

...

481 Commits

Author SHA1 Message Date
ValdiANS e4b61cfe05 chore(FE-199): create Expense API service with dummy data 2025-11-06 15:30:22 +07:00
ValdiANS c59a88bbcb chore(FE-188,193): create formik helper function utils and create removeArrayItemAndSync formik helper function 2025-11-06 15:29:42 +07:00
ValdiANS a8b1f6f8c2 chore(FE-188,193): create convertRowSelectionArrToObj and convertRowSelectionObjToArr helper function 2025-11-06 15:29:15 +07:00
ValdiANS 6e582c4e7c chore(FE-188,193): create ACCEPTED_FILE_TYPES constant 2025-11-06 15:29:00 +07:00
ValdiANS f011f5b7f9 feat(FE-188,193): create ExpenseRequestKandangDetailExpense component 2025-11-06 15:28:42 +07:00
ValdiANS 1d4a16cd0b feat(FE-198): add kandangs, existing_documents, kandangExpenses to ExpenseFormSchemaType and create helper function to get form initial values 2025-11-06 15:28:12 +07:00
ValdiANS 2a71734583 feat(FE-188,193): add Vendor, Request Documents, and Kandang Detail Expense input 2025-11-06 15:26:54 +07:00
ValdiANS e9eee6eb3e feat(FE-188,193): create ExpenseKandangsTable component 2025-11-06 15:22:03 +07:00
ValdiANS 6a070e39da chore(FE-188): updateDropFileInput component 2025-11-04 15:54:13 +07:00
ValdiANS 3b69286a8e chore(FE-188): add DropFileInput component 2025-11-04 15:47:01 +07:00
ValdiANS 0de2e87221 fix(FE-188): required symbol space 2025-11-04 15:46:49 +07:00
ValdiANS 9daa6aaf8c chore(FE-188): update Modal component 2025-11-04 15:46:30 +07:00
ValdiANS a12ae51f3a fix(FE-188): rename to ExpenseRequestForm 2025-11-04 15:46:08 +07:00
ValdiANS 17c316c4af fix(FE-188): required symbol space 2025-11-04 15:45:36 +07:00
ValdiANS c438a8f6aa chore: install react-dropzone 2025-11-04 15:39:55 +07:00
ValdiANS afa0c6c83f chore: rename ExpenseForm to ExpenseRequestForm 2025-11-03 16:16:12 +07:00
ValdiANS 1afa6f7fad chore: rename ExpenseForm.schema.ts to ExpenseRequestForm.schema.ts 2025-11-03 16:15:19 +07:00
ValdiANS ae560c2451 chore: run prettier formatting before every commit 2025-11-03 10:31:44 +07:00
ValdiANS 176e1e7cb8 chore: install react-day-picker 2025-11-03 10:29:23 +07:00
ValdiANS f6d4ef4697 chore: update DateInput component 2025-11-03 10:27:51 +07:00
ValdiANS 33c0d5513c Merge branch 'development' into feat/FE/US-163/expense-request 2025-11-03 09:26:03 +07:00
Adnan Zahir d679c9f278 Merge branch 'fix/ISSUE-236/table-dropdown-issue' into 'development'
Fix: LTI Issue #236

See merge request mbugroup/lti-web-client!41
2025-11-03 09:08:21 +07:00
ValdiANS 0ae4fe0831 chore: format code using prettier 2025-11-01 15:58:47 +07:00
ValdiANS f01dae5f97 chore: add format script 2025-11-01 15:58:03 +07:00
ValdiANS 42b4206e66 chore: install prettier 2025-11-01 15:53:37 +07:00
ValdiANS 46572fd992 chore: update add button styling 2025-11-01 15:36:21 +07:00
ValdiANS b2540f1d43 chore: use RowOptionsMenuWrapper 2025-11-01 15:36:11 +07:00
ValdiANS ad10ffbba3 chore: set min width for RowCollapseOptions 2025-11-01 15:35:49 +07:00
ValdiANS 8a3c7d35ec chore: update add button styling and copywriting 2025-11-01 15:35:34 +07:00
ValdiANS d853b43e17 fix: use RowOptionsMenuWrapper component for RowOptionsMenu 2025-11-01 15:31:11 +07:00
ValdiANS e6187555ce chore: create RowOptionsMenuWrapper component 2025-11-01 15:26:25 +07:00
ValdiANS bba8fb15e5 chore: change a element to button 2025-11-01 15:24:52 +07:00
ValdiANS 15893c18c9 feat(FE-199): create Expense API types 2025-10-31 14:33:28 +07:00
ValdiANS 026e60704b feat(FE-199): create Expense API service 2025-10-31 14:33:19 +07:00
ValdiANS 21b155e64b feat(FE-195): add Expense menu 2025-10-31 14:30:36 +07:00
ValdiANS 1a1bf8754e feat(FE-188): create Expense Form schema 2025-10-31 14:30:00 +07:00
ValdiANS a51c7c44ec feat(FE-188): create ExpenseForm component 2025-10-31 14:29:31 +07:00
ValdiANS 4d1241d712 feat(FE-195): create ExpenseTable component 2025-10-31 14:29:11 +07:00
ValdiANS 80747bb441 chore(FE-195): adjust ConfirmationModal primaryButton and secondaryButton props 2025-10-31 14:28:51 +07:00
ValdiANS 00f64b1897 chore: add string as the valueKey and labelKey type 2025-10-31 14:28:04 +07:00
ValdiANS 01bfe1cc3b chore: export ButtonProps interface 2025-10-31 14:27:13 +07:00
ValdiANS a0cf6c0f56 feat(FE-188): create Add Expense page 2025-10-31 14:26:52 +07:00
ValdiANS c72befb5b4 feat(FE-195): create Expense page 2025-10-31 14:25:01 +07:00
Adnan Zahir e708911429 Merge branch 'fix/FE/US-82/approval-workflow-steps-component' into 'development'
[FIX/FE][US#82] Rework Approval Steps component

See merge request mbugroup/lti-web-client!40
2025-10-30 11:04:04 +07:00
ValdiANS 79cfcad026 chore(FE-91): set formatCurrency default currency to indonesian currency 2025-10-30 11:03:22 +07:00
ValdiANS 37afcc76c3 Merge branch 'development' into fix/FE/US-82/approval-workflow-steps-component 2025-10-30 10:50:57 +07:00
ValdiANS f7eb89c113 feat(FE-91): create constant type file 2025-10-30 10:49:50 +07:00
ValdiANS c9c343b840 chore(FE-91): create BaseGroupedApproval, Approvals, and GroupedApprovals api types 2025-10-30 10:49:36 +07:00
ValdiANS 5c3b1c489f chore(FE-91): set color for step-warning 2025-10-30 10:48:37 +07:00
ValdiANS dd3a0079db chore(FE-91): set formatNumber locale to id-ID as default 2025-10-30 10:48:18 +07:00
ValdiANS bce58c585d feat(FE-91): create approval-line config file 2025-10-30 10:47:51 +07:00
ValdiANS b720c1411b chore(FE-91): make warning step icon glow 2025-10-30 10:47:29 +07:00
ValdiANS 82c1645d92 chore(FE-91): rework ApprovalSteps and create helper function for formatting approval workflow 2025-10-30 10:45:41 +07:00
Adnan Zahir d0d201bf3a Merge branch 'feat/FE/US-77/transfer-to-laying' into 'development'
[FIX/FE][US#77] Transfer to Laying

See merge request mbugroup/lti-web-client!36
2025-10-29 15:07:40 +07:00
ValdiANS f88af89562 Merge branch 'development' into feat/FE/US-77/transfer-to-laying 2025-10-28 09:48:41 +07:00
Adnan Zahir 883d68032a Merge branch 'feat/FE/US-75/chick-in-doc' into 'development'
[FEAT/FE][US#75] Chick In DOC

See merge request mbugroup/lti-web-client!34
2025-10-27 17:23:06 +07:00
Rivaldi A N S e45a9ba5e4 Merge branch 'dev/randy' into 'feat/FE/US-75/chick-in-doc'
[FIX/FE][US#75/TASK#94] Resolve merge conflict from development branch

See merge request mbugroup/lti-web-client!35
2025-10-27 06:14:27 +00:00
ValdiANS de7076e513 Merge branch 'development' into feat/FE/US-77/transfer-to-laying 2025-10-27 13:07:09 +07:00
randy-ar 6706f361d8 refactor(FE): change number input to reuseablecomponent from ui-component 2025-10-27 13:03:38 +07:00
randy-ar 4bd6fe8c35 fix(FE-86): resolve merge conflict 2025-10-27 11:27:08 +07:00
randy-ar cbb4f7421e fix(FE-86): fixing error null value 2025-10-27 10:58:49 +07:00
Rivaldi A N S 459605f133 Merge branch 'dev/randy' into 'feat/FE/US-75/chick-in-doc'
[FEAT/FE][US#75/TASK#92-93-94-105] Slicing UI detail, create and edit Chickin and integrate with API

See merge request mbugroup/lti-web-client!33
2025-10-27 03:27:19 +00:00
randy-ar a65d00edc8 fix(FE): fixing pipeline run error 2025-10-25 17:01:02 +07:00
randy-ar 1e9d02b4b7 feat(FE-92-94): Slicing UI detail chickin & refactor number input chickin form 2025-10-25 16:27:15 +07:00
randy-ar f0f6ec53cb refactor(FE-84-87) refactor checkbox using reuseable component checkboxinput 2025-10-25 13:58:46 +07:00
Adnan Zahir 48c31373bf Merge branch 'feat/FE/US-76/daily-recording-growing' into 'development'
[FEAT/FE][US#76] Daily Recording Growing

See merge request mbugroup/lti-web-client!31
2025-10-25 13:37:39 +07:00
randy-ar 4f3dfb4221 Merge branch 'development' of https://gitlab.com/mbugroup/lti-web-client into dev/randy 2025-10-25 06:16:15 +07:00
randy-ar a13a51a16f fix(FE-92-93-105): adding input note and quantity for create/edit chickin 2025-10-25 06:15:29 +07:00
Rivaldi A N S fa21fe8da4 Merge branch 'feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form' into 'feat/FE/US-76/daily-recording-growing'
[FEAT/FE][US#76/TASK#114-129-130-131-136] Slicing UI Feature Daily Recording Growing

See merge request mbugroup/lti-web-client!32
2025-10-24 03:03:12 +00:00
rstubryan 8337fa5f55 fix(merge): resolve merge conflict 2025-10-24 09:53:04 +07:00
Adnan Zahir 54bff12e1a Merge branch 'feat/FE/US-75/chick-in-doc' into 'development'
[FEAT/FE][US#75] Chick In DOC

See merge request mbugroup/lti-web-client!30
2025-10-24 09:35:56 +07:00
Adnan Zahir aa17143532 Merge branch 'feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form' into 'feat/FE/US-76/daily-recording-growing'
[FEAT/FE][US#76/TASK#114-129-130-131-136] Slicing UI Feature Daily Recording Growing

See merge request mbugroup/lti-web-client!29
2025-10-24 09:34:51 +07:00
rstubryan 4381e42aaf refactor(FE-114): update input handling for vaccination stock, mortality count, and feed stock with improved parsing and formatting 2025-10-24 09:24:28 +07:00
Rivaldi A N S 24ed2cccbe Merge branch 'dev/randy' into 'feat/FE/US-75/chick-in-doc'
[FEAT/FE][US#75/TASK#92-93-106] Slicing UI list, create, and edit Chickin DOC

See merge request mbugroup/lti-web-client!24
2025-10-24 02:18:23 +00:00
rstubryan a9b0c084f8 refactor(FE-114): update input handling for vaccination stock, mortality count, and feed stock with improved parsing and formatting 2025-10-24 09:15:01 +07:00
rstubryan 16823fa84a refactor(FE-114): implement custom handlers for vaccination stock and mortality count input parsing 2025-10-24 09:00:29 +07:00
randy-ar 51bce1a2c7 feat(FE-86-88): Adding reject button and integrate with approval api 2025-10-23 20:23:25 +07:00
rstubryan e76d881d8a refactor(FE-114): add foreign key fields to enhance data relationships in project-flock type definitions 2025-10-23 20:00:42 +07:00
Rivaldi A N S b2044ac7bd Merge branch 'feat/FE/US-77/TASK-140-slicing-transfer-to-laying-edit-form' into 'feat/FE/US-77/transfer-to-laying'
[FEAT/FE][US#77/TASK#140] Slicing Transfer to Laying Edit Form

See merge request mbugroup/lti-web-client!27
2025-10-23 11:48:38 +00:00
randy-ar 8a467c2d65 fix(FE-92-93-105-106): fixing chickin form, after submit event and chickin modal trigger 2025-10-23 18:43:26 +07:00
ValdiANS d1d152ef5a feat(FE-140): create Edit Transfer to Laying page 2025-10-23 17:50:18 +07:00
Rivaldi A N S 82950b0ec0 Merge branch 'feat/FE/US-77/TASK-141-slicing-detail-page-for-transfer-to-laying' into 'feat/FE/US-77/transfer-to-laying'
[FEAT/FE][US#77/TASK#141] Slicing detail page for Transfer to Laying

See merge request mbugroup/lti-web-client!26
2025-10-23 10:37:31 +00:00
ValdiANS 3110b96305 feat(FE-141): add approve and reject method 2025-10-23 17:34:52 +07:00
ValdiANS 7e44226a6d feat(FE-141): add approve and reject functionality in Transfer to Laying Detail Page 2025-10-23 17:34:14 +07:00
rstubryan 3f76cb58fe refactor(FE-114): improve alignment and styling of checkbox inputs in RecordingForm 2025-10-23 17:15:17 +07:00
rstubryan 3cf8f4c89b refactor(FE-114): enhance numeric input handling for chicken weight and count with improved formatting 2025-10-23 16:49:32 +07:00
rstubryan 90ae7c469a refactor(FE-114): swap thousand and decimal separators for improved usability 2025-10-23 16:48:55 +07:00
rstubryan ae967c5ddb refactor(FE-114): integrate inputmask for enhanced numeric input handling and validation 2025-10-23 16:00:24 +07:00
rstubryan e801ba08ad chore(FE-114): add inputmask and its type definitions to package.json 2025-10-23 15:09:39 +07:00
rstubryan e6f5b2493b refactor(FE-Storyless): update input components to include consistent background styling 2025-10-23 13:51:34 +07:00
rstubryan 5f677f5076 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form 2025-10-23 13:50:23 +07:00
rstubryan 2de32dc944 refactor(FE-114): simplify CheckboxInput component and enhance styling options 2025-10-23 13:49:43 +07:00
ValdiANS ab534e203a Merge branch 'development' into feat/FE/US-77/TASK-141-slicing-detail-page-for-transfer-to-laying 2025-10-23 13:40:24 +07:00
randy-ar eaf41805d7 feat(FE-92-93-105-106): slicing ui chickin DOC and integrate with API 2025-10-23 13:30:27 +07:00
Adnan Zahir 631ebb9346 Merge branch 'feat/husky-setup' into 'development'
[FEAT/FE] Husky Setup

See merge request mbugroup/lti-web-client!23
2025-10-23 13:25:41 +07:00
rstubryan 7e53743b07 refactor(FE-114): remove FieldMessage component usage and streamline error message handling in form inputs 2025-10-23 13:14:16 +07:00
ValdiANS 70e1aca6c7 feat: create husky pre-commit file 2025-10-23 13:13:34 +07:00
ValdiANS d0d323954b feat: install husky 2025-10-23 13:10:03 +07:00
Rivaldi A N S d1c24bc486 Merge branch 'feat/FE/US-77/TASK-147-slicing-list-page-of-transfer-to-laying' into 'feat/FE/US-77/transfer-to-laying'
[FEAT/FE][US#77/TASK#147] Slicing List page of Transfer to Laying

See merge request mbugroup/lti-web-client!22
2025-10-23 06:06:03 +00:00
ValdiANS f998d32b0a chore(FE-147): add ApproveAction type 2025-10-23 12:55:31 +07:00
ValdiANS 3226b22dfb chore(FE-147): use dummy data 2025-10-23 12:55:12 +07:00
ValdiANS 9a51b2876f chore(FE-113,140,141): adjust back button link 2025-10-23 12:54:46 +07:00
ValdiANS ab9fbc9032 feat(FE-147): create TransferToLayingsTable component 2025-10-23 12:54:02 +07:00
ValdiANS d2f24723fc chore(FE-141): set dummy data for Transfer to Laying detail page 2025-10-23 12:53:41 +07:00
ValdiANS 5e710a792f chore(FE-147): set moment locale to 'id' globally 2025-10-23 12:52:51 +07:00
ValdiANS 3c8bdfbdac chore(FE-147): set generic when using getByPath function 2025-10-23 12:52:29 +07:00
ValdiANS 204369e0fe feat(FE-147): add CheckboxInput component 2025-10-23 12:51:39 +07:00
ValdiANS 1e2ea79a6a chore(FE-147): add close button for MainDrawer 2025-10-23 12:51:20 +07:00
ValdiANS c24c0817ae chore(FE-147): add rowSelection and setRowSelection props 2025-10-23 11:53:35 +07:00
ValdiANS e53325cdc5 feat(FE-147): show Transfer to Laying table 2025-10-23 11:53:12 +07:00
rstubryan 6687f4af98 feat(FE-Storyless): add Badge component with customizable variants, colors, and sizes 2025-10-23 11:18:57 +07:00
rstubryan 575a317eed refactor(FE-Storyless): update input components to ensure consistent background styling 2025-10-22 15:31:59 +07:00
rstubryan bdb3ab1a50 refactor(FE-114): refactor card native to card component 2025-10-22 14:49:38 +07:00
rstubryan f486a659d0 feat(FE-114): add Card component with customizable layout and styling options 2025-10-22 14:49:05 +07:00
rstubryan 58b4204aab refactor(FE-62): enhance MovementForm by integrating NumberInput for delivery cost fields and improving layout 2025-10-22 14:10:35 +07:00
rstubryan c249585bc2 refactor(FE-114): enhance form UI by adding required field indicators for multiple inputs 2025-10-22 13:55:12 +07:00
rstubryan 9c114628c7 refactor(FE-114,136): improve form validation handling and set touched state asynchronously 2025-10-22 10:54:20 +07:00
rstubryan b35d513e44 refactor(FE-114): update flock accessor key in RecordingTable component 2025-10-22 09:50:09 +07:00
rstubryan a904c35b7f refactor(FE-114): simplify project flock types and update flock reference in recording 2025-10-22 09:41:00 +07:00
rstubryan 2e595b5e86 refactor(FE-114): update import paths from flock to production for recording components 2025-10-22 09:11:23 +07:00
rstubryan 46fa3e57cd Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form 2025-10-21 16:10:40 +07:00
Rivaldi A N S 79b6d6917d Merge branch 'feat/FE/US-77/TASK-113-slicing-transfer-to-laying-create-form' into 'feat/FE/US-77/transfer-to-laying'
[FEAT/FE][US#77/TASK#113] Slicing Transfer to Laying Create Form

See merge request mbugroup/lti-web-client!21
2025-10-21 09:10:07 +00:00
ValdiANS 9f24d22a2c feat(FE-113): create FlockWithKandangs type 2025-10-21 15:54:50 +07:00
ValdiANS 06f1d3f6a4 fix(FE-113): fix merge error 2025-10-21 15:54:25 +07:00
ValdiANS e29613a37e chore(FE-113): add status field 2025-10-21 15:54:11 +07:00
ValdiANS 6e6675d0a7 feat(FE-113): change title and add Transfer ke Laying link 2025-10-21 15:37:25 +07:00
ValdiANS 32d4c0268f Merge branch 'development' into feat/FE/US-77/TASK-113-slicing-transfer-to-laying-create-form 2025-10-21 15:29:10 +07:00
rstubryan 2ab26153fd fix(resolve): fix resolve mismatch conflict path on merge 2025-10-21 15:24:55 +07:00
ValdiANS a29bbc9a42 chore(FE-113): comment Inventory Product link 2025-10-21 15:23:13 +07:00
rstubryan e7e0e308c7 fix(resolve): fix resolve mismatch conflict path on merge 2025-10-21 15:20:15 +07:00
ValdiANS 1ade8f8a38 Merge branch 'development' into feat/FE/US-77/TASK-113-slicing-transfer-to-laying-create-form 2025-10-21 15:18:34 +07:00
Adnan Zahir 791e8e787c Merge branch 'feat/FE/US-74/flock-request' into 'development'
[FEAT/FE][US#74/TASK#84-85-86-87-88-89-102] Project Flock

See merge request mbugroup/lti-web-client!20
2025-10-21 15:17:06 +07:00
ValdiANS a2c43a7f1e feat(FE-141): create Transfer to Laying Detail page 2025-10-21 15:12:09 +07:00
rstubryan 12202c2021 fix(resolve): fix resolve mismatch conflict path on merge 2025-10-21 15:10:57 +07:00
ValdiANS 4127075b13 feat(FE-113): create Transfer to Laying Create Form Schema 2025-10-21 15:09:33 +07:00
ValdiANS d9fa685ae6 feat(FE-113): create Transfer to Laying Create Form 2025-10-21 15:08:11 +07:00
ValdiANS 2f4daea253 feat(FE-113): create API Service for Transfer to Laying 2025-10-21 15:07:51 +07:00
ValdiANS bac72b8eb3 feat(FE-113): create Transfer to Laying type 2025-10-21 15:06:39 +07:00
ValdiANS 5af9c3ee27 chore(FE-113): change api route for getting user info to /auth/sso/userinfo 2025-10-21 15:06:10 +07:00
ValdiANS 1a76913f3f chore(FE-113): set vertical-align to top 2025-10-21 15:05:36 +07:00
ValdiANS 8b403a4208 feat(FE-113): create useSelect hook 2025-10-21 15:01:48 +07:00
ValdiANS 0bab704163 chore(FE-113): create getByPath helper function 2025-10-21 15:01:19 +07:00
ValdiANS d550dcbf48 feat(FE-141): create layout for detail Transfer to Laying route 2025-10-21 14:57:32 +07:00
ValdiANS 7fdbfe6dfb feat(FE-113): create Add Transfer to Laying page 2025-10-21 14:56:58 +07:00
ValdiANS 4e6d2088e1 feat(FE-147): create Transfer to Laying list page 2025-10-21 14:55:37 +07:00
rstubryan 67b180bf7c fix(resolve): fix resolve conflict 2025-10-21 14:36:27 +07:00
Rivaldi A N S 7853899486 Merge branch 'dev/randy' into 'feat/FE/US-74/flock-request'
[FEAT/FE][US#74/TASK#84-85-86-87-88-89-102] Create Feature Project Flocks and Feature Master Data Flocks

See merge request mbugroup/lti-web-client!13
2025-10-21 07:24:58 +00:00
randy-ar 9a04724095 fix(FE-86): fixing approve button and delete button 2025-10-21 14:11:08 +07:00
rstubryan 831995e8e4 refactor(FE-114): translate RecordingForm titles and table headers to Indonesian 2025-10-21 13:59:26 +07:00
randy-ar c8cdb3e772 fix(FE-88): fix error build 2025-10-21 13:22:49 +07:00
randy-ar e5b3af3239 fix(FE-88): fix project flock data types 2025-10-21 13:19:50 +07:00
rstubryan 0740f2d094 refactor(FE-114): ensure fields are marked as touched on change for better validation handling 2025-10-21 13:01:56 +07:00
rstubryan 25a97e34c7 refactor(FE-114): use React's useId hook for generating unique checkbox IDs in CheckboxInput 2025-10-21 11:54:57 +07:00
rstubryan 1ee1cf9ea9 refactor(FE-62): update errorMessage handling and setFieldTouched for form fields 2025-10-21 11:49:55 +07:00
randy-ar e4a1138d8d fix(FE-86-87-88) Hapus tombol edit di index, tambah tombol approve dan delete di detail, dan hit endpoint approve yang udah ada di hoppscocth 2025-10-21 11:37:33 +07:00
rstubryan 41bb05413c feat(FE-62): replace native checkboxes with CheckboxInput component in MovementForm 2025-10-21 11:26:15 +07:00
rstubryan c746bd94b2 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form 2025-10-21 10:42:04 +07:00
rstubryan acea3a3063 refactor(FE-114): replace native checkboxes with CheckboxInput component in RecordingForm 2025-10-21 10:38:26 +07:00
rstubryan b269728ecd feat(FE-114): add CheckboxInput component with customizable props and styling 2025-10-21 10:38:07 +07:00
Adnan Zahir e7a861d8a1 Merge branch 'chore/CI/ignore-build-script' into 'development'
chore(CI): added build-filter.sh to only deploy master and development branch

See merge request mbugroup/lti-web-client!19
2025-10-21 10:21:03 +07:00
Adnan Zahir 1a5a76c0f1 chore(CI): added build-filter.sh to only deploy master and development branch 2025-10-21 10:20:09 +07:00
randy-ar 838d7277c3 fix(FE) resolve merge conflict 2025-10-21 10:19:03 +07:00
randy-ar 1672705464 fix(FE-88-89) adjust category flock dengan API backend & set disabled input period 2025-10-21 10:14:17 +07:00
rstubryan 9ef4484fb3 Merge remote-tracking branch 'origin/feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form' into feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form 2025-10-21 09:55:21 +07:00
rstubryan 645668e1f9 refactor(FE-114): enhance body weight calculations in RecordingForm with auto-update for average weight 2025-10-21 09:55:12 +07:00
rstubryan fb29cea8d2 refactor(FE-114): enhance body weight calculations in RecordingForm with auto-update for average weight 2025-10-21 09:54:28 +07:00
rstubryan 1ecdff855e refactor(FE-114): enhance NumberInput component with improved styling and disabled state handling 2025-10-21 09:54:14 +07:00
rstubryan 7c6e079f56 refactor(FE-114): improve data handling in RecordingForm for numeric fields 2025-10-21 09:33:31 +07:00
rstubryan 41f8067727 refactor(FE-114): enhance NumberInput component with improved props and validation handling 2025-10-21 09:33:17 +07:00
Adnan Zahir f733b0750a Merge branch 'feat/FE/US-35/stock-transfer' into 'development'
[FEAT/FE][US#35/TASK#61-62-63-64-65] Transfer Stock

See merge request mbugroup/lti-web-client!18
2025-10-20 20:56:42 +07:00
rstubryan 83d31b7047 refactor(FE-114): remove unnecessary FieldMessage component from checkbox 2025-10-20 20:20:39 +07:00
rstubryan 966e0886e1 Merge remote-tracking branch 'origin/feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form' into feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form 2025-10-20 20:19:51 +07:00
rstubryan a67d353bcb refactor(FE-114): integrate FieldMessage component for improved field feedback in checkboxes 2025-10-20 20:19:42 +07:00
rstubryan ac2f246988 refactor(FE-114): integrate FieldMessage component for improved field feedback in checkboxes 2025-10-20 20:00:43 +07:00
rstubryan e0ce571000 refactor(FE-114): streamline cost field validation messages and enhance layout with FieldMessage component 2025-10-20 18:54:31 +07:00
rstubryan 1bcfd9bbb4 feat(FE-Storyless): add FieldMessage component for consistent field feedback across inputs 2025-10-20 18:54:02 +07:00
Rivaldi A N S c561c47eae Merge branch 'dev/restu' into 'feat/FE/US-35/stock-transfer'
[FEAT/FE][US#35/TASK#61-62-63-64-65] Create Feature Transfer Stock

See merge request mbugroup/lti-web-client!14
2025-10-20 08:28:22 +00:00
rstubryan c3338d3e05 feat(FE-62): add button for document path in MovementForm with link functionality 2025-10-20 15:23:18 +07:00
rstubryan ba9ae07455 refactor(FE-114): improve validation messages and update layout for better responsiveness 2025-10-20 13:10:41 +07:00
rstubryan c64ff527dd Merge branch 'dev/restu' of gitlab.com:mbugroup/lti-web-client into feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form 2025-10-20 12:56:43 +07:00
rstubryan f27e34128e refactor(FE-62): update layout and remove unused delete confirmation in MovementForm 2025-10-20 12:03:58 +07:00
rstubryan c8db992b17 feat(FE-62,63,65): add document_path field to deliveries in MovementForm 2025-10-20 11:50:19 +07:00
rstubryan d76f897840 refactor(FE-62): update wrapper class names for improved layout in MovementForm 2025-10-20 11:32:35 +07:00
rstubryan 5e0cc3699f Merge branch 'dev/restu' of gitlab.com:mbugroup/lti-web-client into feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form 2025-10-20 10:46:21 +07:00
rstubryan 895b7afa25 refactor(FE-114): improve product filtering logic for location and flag validation 2025-10-20 10:38:10 +07:00
ValdiANS a088189ed1 chore(FE-140): add Produksi and Transfer ke Laying menu 2025-10-20 10:14:22 +07:00
ValdiANS 406cfad31a chore(FE-140): adjust border radius 2025-10-20 10:14:04 +07:00
rstubryan 6c9c0e1839 Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into dev/restu 2025-10-20 10:10:30 +07:00
rstubryan eb02a8b6f7 refactor(storyless): update border class for consistent styling 2025-10-20 10:09:58 +07:00
rstubryan 73f379832c Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form 2025-10-20 10:09:18 +07:00
rstubryan 4233c19dc9 refactor(FE-114): rearrange code for better readability 2025-10-20 10:06:26 +07:00
Adnan Zahir 403765a2b5 Merge branch 'feat/FE/US-77/transfer-to-laying' into 'development'
[FEAT/FE][US#77] Transfer to Laying

See merge request mbugroup/lti-web-client!16
2025-10-20 10:03:03 +07:00
Rivaldi A N S d30d7328cf Merge branch 'feat/FE/US-77/TASK-113-slicing-transfer-to-laying-create-form' into 'feat/FE/US-77/transfer-to-laying'
[FEAT/FE][US#77/TASK#113] Slicing Transfer to Laying Create Form

See merge request mbugroup/lti-web-client!17
2025-10-20 02:57:58 +00:00
ValdiANS 376fa29f7e fix(FE-40): wrap master data detail with SuspenseHelper 2025-10-20 09:55:08 +07:00
rstubryan 16d72ebf6f feat(FE-114,136): integrate location selection and update flock handling in RecordingForm 2025-10-20 09:51:32 +07:00
Rivaldi A N S 52ad696178 Merge branch 'feat/FE/US-77/TASK-113-slicing-transfer-to-laying-create-form' into 'feat/FE/US-77/transfer-to-laying'
[FEAT/FE][US#77/TASK#113] Slicing Transfer to Laying create form

See merge request mbugroup/lti-web-client!15
2025-10-20 02:42:52 +00:00
ValdiANS 2b3aa9c3ee feat(FE-113): create permissionCheck helper function 2025-10-18 13:40:32 +07:00
ValdiANS 6fe85fac13 feat(FE-113): add Client, Permission, Role, and RoleWithPermission types 2025-10-18 13:40:08 +07:00
randy-ar 9964e1797a feat(FE-87): slicing ui multiple approval checkbox and approval modal confirmation 2025-10-18 12:58:18 +07:00
rstubryan e4f554bcd4 refactor(FE-114,136): update RecordingForm validation and input handling for feed and vaccination data 2025-10-18 12:25:04 +07:00
rstubryan c25b49c179 feat(FE-114): add NumberInput component and integrate into RecordingForm for enhanced numeric input handling 2025-10-18 11:39:18 +07:00
randy-ar a573551110 feat(FE-85-87-88): slicing ui and integrate api for search and edit 2025-10-18 10:46:47 +07:00
rstubryan 881e2bfc4a feat(FE-114,136): enhance product label display in RecordingForm with warehouse and stock information 2025-10-18 09:04:39 +07:00
rstubryan 474c2a1f7d Merge branch 'dev/restu' of gitlab.com:mbugroup/lti-web-client into feat/FE/US-76/TASK-114-129-136-slicing-ui-and-validation-create-edit-daily-recording-growing-form 2025-10-18 08:45:26 +07:00
rstubryan c4de085e11 feat(FE-62,63): enhance warehouse stock information display in MovementForm 2025-10-18 08:40:06 +07:00
rstubryan 0676411dd5 refactor(FE-62,65): enhance product quantity display and stock information in MovementForm 2025-10-17 19:23:19 +07:00
rstubryan f05d367a5d refactor(FE-65): enhance delivery cost validation and calculation in MovementForm 2025-10-17 18:51:35 +07:00
rstubryan edb5f30d6c refactor(FE-62): remove unused product fetching logic from MovementForm 2025-10-17 16:48:52 +07:00
rstubryan 7abe9b7dc6 refactor(FE-63,65): update Movement types and schema to include area and location for warehouses 2025-10-17 16:48:35 +07:00
rstubryan caf68d438f refactor(FE-114,136,137): update feed and vaccination fields to use IDs instead of names and add stock validation 2025-10-17 13:59:28 +07:00
rstubryan fa60f884c1 merge: resolve conflict 2025-10-17 13:18:34 +07:00
rstubryan c77968940e refactor(FE-114,136): update flock references to use ProjectFlock and adjust RecordingForm for new API 2025-10-17 13:16:54 +07:00
rstubryan cfb9b53b54 refactor(FE-63): simplify createMovementHandler by removing unnecessary payload checks 2025-10-17 10:13:14 +07:00
rstubryan caac9c20e6 refactor(FE-62): update MovementForm layout to improve responsiveness with grid system 2025-10-17 10:12:53 +07:00
rstubryan 8bf7603f66 refactor(FE-64): update MovementTable and TableRowOptions to conditionally show edit and delete options 2025-10-17 09:46:07 +07:00
rstubryan 8c662a5152 refactor(FE-65): update DeliveryObjectSchema to enforce minimum delivery costs of 1 2025-10-17 09:22:49 +07:00
randy-ar da92874a40 Merge branch 'feat/FE/US-74/flock-request' of https://gitlab.com/mbugroup/lti-web-client into dev/randy 2025-10-16 16:52:58 +07:00
randy-ar 5113bf4d3f feat(84-85-86-87-88-89-102): create feature project flocks and adjust master data flock feature 2025-10-16 16:49:44 +07:00
rstubryan 1bdec0c9ae refactor(FE-62,63): update MovementForm to handle 'detail' type with appropriate validations and stock checks 2025-10-16 16:46:33 +07:00
rstubryan 57dbcf3624 Merge remote-tracking branch 'origin/dev/restu' into dev/restu 2025-10-16 16:26:03 +07:00
rstubryan 501a68267e refactor(FE-63,63,65): enhance MovementForm to fetch and display product details from ProductWarehouse 2025-10-16 16:25:54 +07:00
rstubryan a2a57f758c refactor(FE-63,63,65): enhance MovementForm to fetch and display product details from ProductWarehouse 2025-10-16 16:24:42 +07:00
rstubryan 157dfc75ed refactor(FE-63): remove debug logging from form submission and movement handlers 2025-10-16 15:47:29 +07:00
rstubryan f5ce898bd2 feat(FE-62,63,65): enhance MovementForm with product warehouse selection, delivery document handling, and stock validation 2025-10-16 15:29:26 +07:00
rstubryan c6a0c542aa refactor(FE-62,63,65): refactor Movement and ProductWarehouse APIs, update MovementForm schema, and enhance MovementTable functionality 2025-10-16 14:33:49 +07:00
Adnan Zahir b0e11095f4 Merge branch 'feat/FE/US-82/approval-workflow-steps-component' into 'development'
[FEAT/FE][US#82] Slicing Approval Steps component

See merge request mbugroup/lti-web-client!12
2025-10-16 11:04:52 +07:00
rstubryan 79acdb4b7b merge: resolve conflict 2025-10-16 10:59:36 +07:00
rstubryan 19db9a4eac refactor(FE-114,136): enhance validation and default values in RecordingForm schema 2025-10-16 10:54:36 +07:00
Rivaldi A N S 1e0b342bbc Merge branch 'feat/FE/US-82/TASK-91-slicing-approval-steps-component' into 'feat/FE/US-82/approval-workflow-steps-component'
[FEAT/FE][US#82/TASK#91] Slicing Approval Steps component

See merge request mbugroup/lti-web-client!11
2025-10-16 03:16:47 +00:00
rstubryan 23d5a41d56 refactor(FE-114): improve recording date handling in RecordingForm 2025-10-16 10:08:49 +07:00
ValdiANS b7a30cc73a chore(FE-91): create ApprovalsLine type 2025-10-16 10:01:50 +07:00
ValdiANS 93beb86f91 feat(FE-91): create ApprovalSteps component 2025-10-16 10:01:40 +07:00
ValdiANS 0577f6ce1d feat(FE-91): create StepItem component 2025-10-16 10:01:29 +07:00
ValdiANS 76dd2e4c54 feat(FE-91): create Steps component 2025-10-16 10:01:23 +07:00
ValdiANS 156de6112b feat(FE-91): create Tooltip component 2025-10-16 10:01:14 +07:00
ValdiANS eb0f04310e chore(FE-91): create daisyui.css file for extending daisyUI style 2025-10-16 10:01:00 +07:00
rstubryan 27d2792a9c refactor(FE-114): enhance layout and structure of RecordingForm component 2025-10-16 09:24:00 +07:00
rstubryan ec387637ed refactor(FE-114): remove bulk delete functionality from RecordingTable 2025-10-16 09:12:21 +07:00
rstubryan 64e6724664 feat(FE-114): add bulk action functionality for approving, rejecting, and deleting recordings in RecordingTable 2025-10-16 09:07:12 +07:00
rstubryan f319a9b5d1 feat(FE-114): implement RecordingEdit and RecordingDetail components with error handling and loading states 2025-10-16 08:39:32 +07:00
randy-ar e2b35e765c feat(FE-102) create master data flock and add LTI theme 2025-10-15 20:01:41 +07:00
rstubryan 8bfce061e6 refactor(FE-114,136): improve location and coop field handling in RecordingForm 2025-10-15 17:53:08 +07:00
rstubryan 64a32fd214 refactor(FE-114,136): update RecordingForm schema and types to include location and coop fields 2025-10-15 17:39:27 +07:00
rstubryan 2ee88a2742 refactor(FE-114): enhance tanggal_recording handling and improve error messaging in RecordingForm 2025-10-15 13:45:48 +07:00
rstubryan aa21088e99 feat(FE-62): enhance MovementForm with delivery product input error handling and validation 2025-10-15 12:30:59 +07:00
rstubryan 06dc869b84 feat(FE-64): update MovementTable structure for improved data clarity and consistency 2025-10-15 12:08:52 +07:00
rstubryan df73ee1fdf feat(FE-62,63,65): refactor MovementForm and related types for improved clarity and consistency 2025-10-15 12:00:17 +07:00
rstubryan cf78687315 merge: resolve conflict 2025-10-15 11:05:37 +07:00
rstubryan 66e6fa84c8 Merge remote-tracking branch 'origin/dev/restu' into dev/restu 2025-10-15 10:56:16 +07:00
rstubryan dcd5d2692f feat(FE-62,65): enhance MovementForm and FormActions to improve form validation and reset behavior 2025-10-15 10:56:06 +07:00
rstubryan 3c4333021f feat(FE-62,65): enhance MovementForm and FormActions to improve form validation and reset behavior 2025-10-15 10:54:38 +07:00
rstubryan 56a9fc2349 refactor(FE-62,65): simplify error handling in MovementForm by consolidating error checks 2025-10-15 10:51:06 +07:00
rstubryan 24144f01d4 feat(FE-114,136): add error handling for repeater inputs in RecordingForm 2025-10-15 10:37:04 +07:00
Adnan Zahir 212fd3b4f2 Merge branch 'feat/FE/US-34/stock-adjustment' into 'development'
[FEAR/FE/US#34/TASK#51-52-53-54] Implement Feature Adjustment Inventory

See merge request mbugroup/lti-web-client!9
2025-10-15 10:26:14 +07:00
rstubryan 6f0467918b feat(FE-114): add tanggal_recording field to RecordingForm and update schema validation 2025-10-15 09:50:21 +07:00
rstubryan 53ee4cdc1b feat(FE-114): add Layout and AddRecording components with routing link 2025-10-15 09:29:29 +07:00
rstubryan b1a3796eca feat(FE-114,136): implement RecordingForm component with data handling and validation 2025-10-15 09:28:57 +07:00
rstubryan 89318407ea feat(FE-136): update RecordingForm schema to remove tanggal and add flock object 2025-10-14 23:01:01 +07:00
rstubryan 6dcb97bcac feat(FE-114,129): add RecordingForm and RecordingTable components with handlers 2025-10-14 22:03:51 +07:00
rstubryan 1869fa8dc5 feat(FE-136): add flock and recording management with validation in forms 2025-10-14 22:03:09 +07:00
rstubryan 4b4b74d07c feat(FE-65): add validation for quantity and required fields in MovementForm 2025-10-14 18:00:34 +07:00
rstubryan ff9e35eb52 Merge remote-tracking branch 'origin/dev/restu' into dev/restu
# Conflicts:
#	src/components/pages/inventory/movement/form/MovementForm.tsx
2025-10-14 14:04:24 +07:00
rstubryan 19bca9ec73 feat(FE-65): enhance MovementForm to support file uploads with FormData conversion 2025-10-14 14:03:46 +07:00
rstubryan 6facfd3d3c feat(FE-65): enhance MovementForm to support file uploads with FormData conversion 2025-10-14 14:00:58 +07:00
rstubryan b2f0bd6698 feat(FE-65): add file type validation for dokumen in MovementForm 2025-10-14 10:31:34 +07:00
rstubryan e7085ab4ff feat(FE-65): add file size validation for dokumen in MovementForm 2025-10-14 10:02:56 +07:00
rstubryan 44e07ddc50 feat(FE-64): refactor MovementTable with new TableToolbar and TableRowSizeSelector components 2025-10-14 09:26:21 +07:00
Rivaldi A N S 46860a93b9 Merge branch 'dev/randy' into 'feat/FE/US-34/stock-adjustment'
[FEAT/FE][US#33][TASK#51-54] Form Validation and UI/UX Adjustment

See merge request mbugroup/lti-web-client!10
2025-10-13 06:53:00 +00:00
randy-ar 302da65c59 fix(FE-51) adjust textarea component ui 2025-10-13 13:09:53 +07:00
randy-ar ce8471343c fix(FE-54) fix form input state inventory adjustment 2025-10-13 12:59:05 +07:00
randy-ar 880ff5740d fix(FE-42): fix validation supplier form and multi select component 2025-10-13 11:26:37 +07:00
randy-ar 9b53c75f2f fix(FE-42): fix validation supplier form and multi select component 2025-10-13 11:25:39 +07:00
rstubryan a4ff4f7b2a feat: add Layout component to wrap children with SuspenseHelper 2025-10-12 20:32:02 +07:00
rstubryan 754e3d526b feat(FE-64): add hatchery and npwp fields to MovementTable data structure 2025-10-12 19:15:14 +07:00
randy-ar f662f2951e fix(FE-51-54): fixing bug and layout form adjustment 2025-10-11 23:26:30 +07:00
randy-ar 1fd4b2aba5 Merge branch 'development' of https://gitlab.com/mbugroup/lti-web-client into feat/FE/US-34/stock-adjustment 2025-10-11 13:18:15 +07:00
randy-ar b75b5956eb feat/FE/US-34/TASK-52-53-slicing-ui-table-adjust-form-with-api 2025-10-11 13:12:05 +07:00
rstubryan 478f52c94b feat(FE-62,65): add biaya_ekspedisi_per_item field and calculation in MovementForm 2025-10-11 08:33:48 +07:00
randy-ar aa7b6581d9 feat/FE/US-34/TASK-54-51-slicing-ui-client-side-validation-stock-adjustment 2025-10-11 02:03:10 +07:00
rstubryan 757893c757 feat(FE-62): add quantity validation for ekspedisi in MovementForm and filter product options 2025-10-10 13:43:30 +07:00
rstubryan a1dc13ceb4 feat(FE-62): enhance MovementForm with area and location display for warehouse selection 2025-10-10 13:36:22 +07:00
rstubryan 157235433e feat(FE-62): implement bulk removal functionality for selected products and ekspedisi in MovementForm 2025-10-10 13:14:39 +07:00
rstubryan 57831646d9 refactor(FE-62): optimize product and ekspedisi removal logic in MovementForm 2025-10-10 11:14:59 +07:00
rstubryan 095190d757 refactor(FE-62,65): refactor MovementForm schema and component for improved product and ekspedisi handling 2025-10-10 10:19:56 +07:00
rstubryan 27f58051ad Merge branch 'development' of gitlab.com:mbugroup/lti-web-client into feat/FE/US-35/stock-transfer 2025-10-10 08:40:39 +07:00
rstubryan a9cdea7318 feat(FE-65): enhance MovementForm with initial values handling and refactor components 2025-10-10 08:40:17 +07:00
rstubryan 7dbf880228 feat(FE-62): add FormActions and FormHeader components for form management 2025-10-10 08:39:34 +07:00
Adnan Zahir 24b702548d Merge branch 'feat/FE/US-33/master-data-management' into 'development'
[FEAT/FE][US#33/TASK#40-41-42-43] Master Data Management

See merge request mbugroup/lti-web-client!8
2025-10-09 17:43:27 +07:00
rstubryan aacdbf0742 Merge branch 'feat/FE/US-33/TASK-40-slicing-ui-for-master-data-forms' of gitlab.com:mbugroup/lti-web-client into feat/FE/US-35/stock-transfer 2025-10-09 16:33:31 +07:00
Rivaldi A N S 96babba4bb Merge branch 'feat/FE/US-33/TASK-40-slicing-ui-for-master-data-customers-and-suppliers-forms' into 'feat/FE/US-33/TASK-40-slicing-ui-for-master-data-forms'
[FEAT/FE/US#33/TASK#40] Slicing UI for Costumer and Suppliers Forms in Master Data

See merge request mbugroup/lti-web-client!7
2025-10-09 08:19:28 +00:00
Rivaldi A N S acd66b0323 Merge branch 'bugfix/FE/ISSUE/build-error' into 'feat/FE/US-33/TASK-40-slicing-ui-for-master-data-forms'
[FIX/FE][ISSUE] Fix Issue for Next.js Build

See merge request mbugroup/lti-web-client!4
2025-10-09 07:50:58 +00:00
rstubryan c17ffc6aff feat(FE-62): add MovementEdit and MovementDetail components for inventory movement management 2025-10-09 14:34:25 +07:00
rstubryan 1ea9ee3069 feat(FE-62,63,65): implement MovementForm component for managing inventory movements 2025-10-09 14:30:05 +07:00
randy-ar 5cf98ed95e fix(FE-33): fix conflict git 2025-10-09 13:35:30 +07:00
Restu Bumi Ryan Ramadhan 558a1788dc Merge branch 'feat/FE/US-35/TASK-62-65-slicing-ui-for-inventory-movement-forms' into 'feat/FE/US-35/stock-transfer'
Feat/fe/us 35/task 62 65 slicing ui for inventory movement forms

See merge request mbugroup/lti-web-client!5
2025-10-09 06:11:39 +00:00
rstubryan e2036ab3dc chore: resolve conflict pull request 2025-10-09 13:05:27 +07:00
randy-ar a83452a0e4 feat(FE-33): create suppliers table and forms 2025-10-09 12:27:59 +07:00
rstubryan 3f712a638f chore: remove redundant start scripts from package.json 2025-10-09 11:45:27 +07:00
rstubryan 0ea78fee92 chore: resolve conflict pull request 2025-10-09 11:44:38 +07:00
rstubryan b561ed6193 fix: update dependencies in multiple tables to include updateSortingFilter in effect dependencies 2025-10-09 11:35:22 +07:00
rstubryan d7ae7e00d3 fix: update dependency in AreasTable to include updateFilter in sorting effect 2025-10-09 11:22:01 +07:00
rstubryan f0eabedcb2 refactor: refactor layout components to use SuspenseHelper for loading states 2025-10-09 11:06:59 +07:00
ValdiANS 94a5ce5604 feat(FE-40): create layout for /detail route and wrap the children in SuspenseHelper component 2025-10-09 11:05:55 +07:00
ValdiANS 9b56308cf0 feat(FE-40): create SuspenseHelper component 2025-10-09 11:05:30 +07:00
ValdiANS 6353b3aee4 feat(FE-40,41): create Master Data Edit FCR page 2025-10-09 10:05:24 +07:00
ValdiANS 527a155997 feat(FE-40,41): create Master Data Detail FCR page 2025-10-09 10:05:17 +07:00
ValdiANS f6163b1f69 feat(FE-40,41): create Master Data Add FCR page 2025-10-09 10:05:07 +07:00
ValdiANS d771b20956 feat(FE-43): create Master Data FCR page 2025-10-09 10:04:55 +07:00
ValdiANS da91201dde chore(FE-40): use optional chaining 2025-10-09 10:04:42 +07:00
ValdiANS 9b13ce2be6 chore(FE-40): render error message if isError and errorMessage exist 2025-10-09 10:04:20 +07:00
ValdiANS 764dacc627 feat(FE-43): create FcrsTable component 2025-10-09 10:04:01 +07:00
rstubryan d1f43c4e42 refactor: rename layout files for consistency and clarity 2025-10-09 10:00:38 +07:00
ValdiANS 5c0da471ae feat(FE-42): create Fcr form validation schema 2025-10-09 10:00:29 +07:00
ValdiANS 95556bfdd7 feat(FE-40,41): create FcrForm component 2025-10-09 09:59:53 +07:00
ValdiANS 24269d8c76 feat(FE-41): create Fcr api service 2025-10-09 09:59:34 +07:00
ValdiANS a6be56e6f2 feat(FE-41): create Fcr api type 2025-10-09 09:57:41 +07:00
ValdiANS f8f5e8403a chore(FE-40): create main drawer menu type 2025-10-09 09:55:14 +07:00
rstubryan 9f2add3a57 feat: add multiple layout components with suspense fallback for loading states 2025-10-09 09:38:16 +07:00
rstubryan 3051e931ca fix: enhance MainDrawer with typed MenuItem structure and submenu handling 2025-10-09 09:12:07 +07:00
randy-ar 21cc01fe68 feat(FE-33): create customers table and details 2025-10-09 04:36:57 +07:00
sweetpotet 21b9396323 feat(FE-33): create customers forms 2025-10-08 16:40:30 +07:00
rstubryan ddbf8b0896 refactor(FE-62): rename Product component to Movement for clarity 2025-10-08 16:16:12 +07:00
rstubryan 3f97ec45f8 feat(FE-64): add MovementTable component for inventory movement management 2025-10-08 16:06:19 +07:00
ValdiANS 1d7f100507 feat(FE-40,41): create Master Data Edit Bank page 2025-10-08 15:38:10 +07:00
ValdiANS 372f1698ca feat(FE-40,41): create Master Data Detail Bank page 2025-10-08 15:38:01 +07:00
ValdiANS 0d5e8383fd feat(FE-40,41): create Master Data Add Bank page 2025-10-08 15:37:26 +07:00
ValdiANS b9015ed673 feat(FE-43): create Master Data Bank page 2025-10-08 15:37:01 +07:00
ValdiANS ca42570a40 feat(FE-43): create BanksTable component 2025-10-08 15:36:13 +07:00
ValdiANS 16a15fce66 feat(FE-42): create Bank form validation schema 2025-10-08 15:35:56 +07:00
ValdiANS 8c507aa410 feat(FE-40,41): create BankForm component 2025-10-08 15:35:34 +07:00
ValdiANS 10749f06da feat(FE-41): create Bank API service 2025-10-08 15:35:15 +07:00
ValdiANS 293f457ecb feat(FE-41): create Bank type 2025-10-08 15:35:00 +07:00
rstubryan 7ceb25ea71 feat(FE-62,65): add inventory movement management with API and form validation 2025-10-08 15:26:45 +07:00
ValdiANS 780c0bb9d0 chore(FE-41): use Nonstock API service 2025-10-08 15:01:45 +07:00
ValdiANS b8548b72c9 feat(FE-40,41): create Nonstock form validation schema 2025-10-08 15:00:41 +07:00
ValdiANS c53f91ec3f feat(FE-43): create NonstocksTable component 2025-10-08 15:00:30 +07:00
ValdiANS 96fea80f62 feat(FE-40,41): create NonstockForm component 2025-10-08 15:00:06 +07:00
ValdiANS d24d50474d feat(FE-41): create Nonstock API service 2025-10-08 14:59:39 +07:00
ValdiANS f3d0e12bcd feat(FE-42): create flags type 2025-10-08 14:59:14 +07:00
ValdiANS 143d640a1e chore(FE-41): refactor nonstock type 2025-10-08 14:58:54 +07:00
ValdiANS 0e49e29002 feat(FE-42): create SUPPLIER_FLAG_OPTIONS constant 2025-10-08 14:58:21 +07:00
ValdiANS 8461667ca2 chore(FE-41): delete nonstock api helper function file 2025-10-08 14:56:52 +07:00
ValdiANS 3e7da624aa feat: add .prettierrc.json config 2025-10-08 13:47:56 +07:00
Rivaldi A N S 1968761b5d Merge branch 'feat/FE/US-33/TASK-40-slicing-ui-for-master-data-product-and-product-category-forms' into 'feat/FE/US-33/TASK-40-slicing-ui-for-master-data-forms'
[FEAT/FE][US#33/TASK#40-43] Implement Product & Product Category Feature (Type, Validation, Form, Table, and Pages)

See merge request mbugroup/lti-web-client!3
2025-10-08 03:08:01 +00:00
rstubryan 396ebe5001 feat(FE-43): add 'Code' column to Product Category table 2025-10-08 09:55:19 +07:00
rstubryan f5952f5a36 feat(FE-43): add Supplier API and data types for supplier management 2025-10-08 09:12:49 +07:00
rstubryan 250c42a04b feat(FE-40,41,42): add Product management pages with form handling and table display 2025-10-07 21:23:12 +07:00
rstubryan e1569c607c feat(FE-41,43): add Products table with CRUD operations and search functionality 2025-10-07 21:22:05 +07:00
rstubryan 3241cc9868 feat(FE-42): add Product API and form validation schema with product flags 2025-10-07 21:21:24 +07:00
rstubryan 26ec456937 feat(FE-40,41,42): add Product Category detail and edit pages with form handling 2025-10-07 18:59:31 +07:00
rstubryan 2b9b8e9920 feat(FE-41,43): implement Product Category table with CRUD operations 2025-10-07 18:58:38 +07:00
rstubryan 3cac49725f feat(FE-42): add Product Category API and form validation schema 2025-10-07 18:56:58 +07:00
rstubryan 4f0e02a93b chore: add .idea to .gitignore 2025-10-07 17:23:58 +07:00
ValdiANS af60e682ee chore(FE-41): redirect to /404 if response error 2025-10-05 16:19:37 +07:00
ValdiANS dcebd53c45 feat(FE-40): add edit button 2025-10-05 16:13:04 +07:00
ValdiANS 1ae2d13335 feat(FE-40,41): create Master Data Edit Warehouse page 2025-10-05 16:07:27 +07:00
ValdiANS 452139eeed feat(FE-40,41): create Master Data Detail Warehouse page 2025-10-05 16:07:17 +07:00
ValdiANS eb10dfe29f feat(FE-40,41): create Master Data Add Warehouse page 2025-10-05 16:07:06 +07:00
ValdiANS 70bdfc3b43 feat(FE-43): create Master Data Warehouse page 2025-10-05 16:06:51 +07:00
ValdiANS c1bc7beb4a feat(FE-43): create WarehousesTable component 2025-10-05 16:06:36 +07:00
ValdiANS 76cd64de5b feat(FE-42): create Warehouse form validation schema 2025-10-05 16:06:21 +07:00
ValdiANS 07691bfd9e feat(FE-40,41): create WarehouseForm component 2025-10-05 16:05:58 +07:00
ValdiANS 1f0c58d264 feat(FE-40): create WAREHOUSE_TYPE_OPTIONS constant 2025-10-05 16:05:33 +07:00
ValdiANS 19ce3989ba feat(FE-41): create Warehouse API service 2025-10-05 16:05:18 +07:00
ValdiANS a136ee1190 chore(FE-41): create Override type 2025-10-05 16:04:59 +07:00
ValdiANS acd28e5deb feat(FE-41): create warehouse api type 2025-10-05 16:04:46 +07:00
ValdiANS bfc81da349 feat(FE-40,41): create Master Data Edit Kandang page 2025-10-05 13:42:22 +07:00
ValdiANS 64bb87f92f feat(FE-40,41): create Master Data Detail Kandang page 2025-10-05 13:42:14 +07:00
ValdiANS f0c2910469 feat(FE-40,41): create Master Data Add Kandang page 2025-10-05 13:42:05 +07:00
ValdiANS 952110d7af feat(FE-43): create Master Data Kandang page 2025-10-05 13:41:45 +07:00
ValdiANS 6441a38a9d feat(FE-42): create Kandang form validation schema 2025-10-05 13:41:27 +07:00
ValdiANS 531a257e78 feat(FE-40,41): create KandangForm component 2025-10-05 13:41:08 +07:00
ValdiANS be844312d3 feat(FE-43): create KandangsTable component 2025-10-05 13:40:46 +07:00
ValdiANS 6ff19f05fd feat(FE-41): craete KandangApi service 2025-10-05 13:40:09 +07:00
ValdiANS 26093034fa feat(FE-41): create user API service 2025-10-05 13:39:38 +07:00
ValdiANS 0e5b718fd7 feat(FE-41): create kandang type 2025-10-05 13:39:25 +07:00
ValdiANS 0675d95a2a feat(FE-41): create user type 2025-10-05 13:39:16 +07:00
ValdiANS d5294e9b0b chore(FE-43): remove unnecessary code 2025-10-05 13:01:30 +07:00
ValdiANS 8c84e08f3b chore(FE-41): use .d.ts extension for types 2025-10-05 13:00:58 +07:00
ValdiANS f32e1ceec4 chore(FE-41): use BaseApiService class 2025-10-05 12:59:35 +07:00
ValdiANS f7b0933c0f feat(FE-41): create BaseApiService class 2025-10-05 12:59:15 +07:00
ValdiANS 508a530c3a chore(FE-43): add address and area sorting 2025-10-05 12:32:51 +07:00
ValdiANS 05a67bdc75 feat(FE-40,41): create Master Data Edit Location page 2025-10-04 14:59:44 +07:00
ValdiANS 54d2c85677 feat(FE-40,41): create Master Data Detail Location page 2025-10-04 14:59:30 +07:00
ValdiANS 288e4b92ff feat(FE-40,41): create Master Data Add Location page 2025-10-04 14:59:16 +07:00
ValdiANS 7e0dd1bdb1 feat(FE-43): create Master Data Location page 2025-10-04 14:59:03 +07:00
ValdiANS 57e5fafabd feat(FE-42): create Location form validation schema 2025-10-04 14:58:45 +07:00
ValdiANS e53d4e22b2 feat(FE-40,41): create LocationForm component 2025-10-04 14:58:25 +07:00
ValdiANS 3c0babb62b feat(FE-43): create LocationsTable component 2025-10-04 14:57:59 +07:00
ValdiANS e7e5456d15 feat(FE-41): create LocationApi service 2025-10-04 14:57:43 +07:00
ValdiANS d3977a0951 feat(FE-41): create Location type 2025-10-04 14:57:17 +07:00
ValdiANS 5b1dab2860 feat(FE-40): add onInputChange prop 2025-10-04 14:53:05 +07:00
ValdiANS 8ed12578b4 chore(FE-40): fix name input placeholder 2025-10-04 14:32:42 +07:00
ValdiANS 7ea599168c chore(FE-43): add conditional to set sorting and setSorting and add manualSorting props 2025-10-04 14:25:29 +07:00
ValdiANS a2345165c1 chore(FE-41): create BaseArea type 2025-10-04 14:09:03 +07:00
ValdiANS e1c34cf0fb chore(FE-41): create BaseUom type 2025-10-04 14:08:53 +07:00
ValdiANS 4332881ba6 chore(FE-40): add delete button and delete confirmation modal 2025-10-04 14:03:53 +07:00
ValdiANS 73cefbb7a3 chore(FE-40): change delete confirmation modal text 2025-10-04 14:03:27 +07:00
ValdiANS 9ba7b5dba4 feat(FE-40,41): create Master Data Edit Area page 2025-10-04 13:58:53 +07:00
ValdiANS 172d8efd8e feat(FE-40,41): create Master Data Detail Area page 2025-10-04 13:58:11 +07:00
ValdiANS 69ecacc1be feat(FE-40,41): create Master Data Add Area page 2025-10-04 13:57:48 +07:00
ValdiANS 4bf4981fd4 feat(FE-43): create Master Data Area page 2025-10-04 13:57:21 +07:00
ValdiANS 6dd6147c29 feat(FE-41): create AreaApi service 2025-10-04 13:57:05 +07:00
ValdiANS c494f8dbd5 feat(FE-41): create Area type 2025-10-04 13:56:51 +07:00
ValdiANS 211951132a feat(FE-42): create Area form validation schema 2025-10-04 13:56:17 +07:00
ValdiANS b82637fb3b feat(FE-40,41): create AreaForm component 2025-10-04 13:55:52 +07:00
ValdiANS eebc9940cc feat(FE-43): create AreasTable component 2025-10-04 13:55:28 +07:00
ValdiANS 777f0f5e81 feat(FE-40): add none type to Color 2025-10-04 12:23:31 +07:00
ValdiANS d29d1f27f8 chore(FE-41): create CreatedUser and BaseMetadata type 2025-10-04 12:23:14 +07:00
ValdiANS bbe55ee4c3 chore(FE-43): add ROWS_OPTIONS constant 2025-10-04 12:22:43 +07:00
ValdiANS 6dec9268c9 feat(FE-41): create Master Data API Service class 2025-10-04 12:22:25 +07:00
ValdiANS b5d9c55fbc chore(FE-41): create UOM type 2025-10-04 12:22:00 +07:00
ValdiANS d941674f9a feat(FE-40,41): create Master Data Edit UOM page 2025-10-04 12:21:38 +07:00
ValdiANS e6c14f57d9 feat(FE-40,41): create Master Data Detail UOM page 2025-10-04 12:21:14 +07:00
ValdiANS f27b261869 feat(FE-40,41): create Master Data Add UOM page 2025-10-04 12:20:19 +07:00
ValdiANS 6a396ccce6 feat(FE-43): create Master Data UOM page 2025-10-04 12:19:52 +07:00
ValdiANS 65e3833cd5 feat(FE-43): create RowDropdownOptions component 2025-10-04 12:19:15 +07:00
ValdiANS 34e9e60173 feat(FE-43): create RowCollapseOptions component 2025-10-04 12:19:01 +07:00
ValdiANS f1a8fda667 feat(FE-42): create UOM form validation schema 2025-10-04 12:18:39 +07:00
ValdiANS 36113f6c2a feat(FE-40,41): create UomForm component 2025-10-04 12:18:15 +07:00
ValdiANS e259d1720c feat(FE-43): create UomsTable component 2025-10-04 12:17:42 +07:00
ValdiANS 78750060de feat(FE-40): create ConfirmationModal component 2025-10-04 12:17:17 +07:00
ValdiANS ae159b9617 chore(FE-40): remove unnecessary dependencies 2025-10-04 12:15:06 +07:00
ValdiANS 56476c7dd9 chore(FE-40): adjust loading dots size 2025-10-04 12:14:47 +07:00
ValdiANS fa5d09e4fb chore(FE-40): add Toaster component in root layout 2025-10-04 12:14:18 +07:00
ValdiANS df1b4c29e5 feat(FE-43): create useTableFilter hooks 2025-10-04 12:13:49 +07:00
ValdiANS 20f6686afc chore(FE-43): add sorting and setSorting props 2025-10-04 12:08:08 +07:00
ValdiANS 18027f0bb9 chore(FE-43): get setPageSize from table object 2025-10-04 11:31:23 +07:00
ValdiANS 2976ffffbf chore(FE-40): install use-debounce 2025-10-04 11:18:23 +07:00
ValdiANS 5983a44311 chore(FE-40): add DebouncedTextInput component 2025-10-04 11:18:08 +07:00
ValdiANS 42dd91117e chore(FE-40): install react-hot-toast 2025-10-04 11:01:21 +07:00
ValdiANS 60d0d77dff feat(FE-40): add Alert component 2025-10-03 22:13:35 +07:00
Adnan Zahir 7723e2a8d3 Merge branch 'chore/CI/merge-request-notify-workflow' into 'development'
chore(CI): added gitlab ci yaml file for notify MR and MR-merged events

See merge request mbugroup/lti-web-client!2
2025-10-03 22:01:25 +07:00
Adnan Zahir 88fe135cb4 chore(CI): added gitlab ci yaml file for notify MR and MR-merged events 2025-10-03 21:58:55 +07:00
ValdiANS 83701a9689 chore(FE-40): update table pageSize if it change 2025-10-03 14:12:02 +07:00
ValdiANS e765a7a5fb chore(FE-40): hide empty content if is loading 2025-10-02 16:50:37 +07:00
ValdiANS 75a5caa63b feat(FE-40): create Nonstock Edit page 2025-10-02 12:03:23 +07:00
ValdiANS c40c707c17 feat(FE-40): create Nonstock Detail page 2025-10-02 12:03:06 +07:00
ValdiANS c3da39ef1b feat(FE-40): create Add Nonstock page 2025-10-02 12:02:21 +07:00
ValdiANS 230e966197 feat(FE-40): create Nonstock page 2025-10-02 12:02:11 +07:00
ValdiANS 62b3894983 feat(FE-40): create api type for nonstock 2025-10-02 12:02:02 +07:00
ValdiANS 8dd1ebdfe4 feat(FE-40): create api service for nonstock 2025-10-02 12:01:43 +07:00
ValdiANS 35c809193b feat(FE-40): create NonstocksTable component 2025-10-02 12:01:14 +07:00
ValdiANS e6acfc1214 feat(FE-40): create NonstockForm component 2025-10-02 12:01:00 +07:00
ValdiANS 36b66d9b2f feat(FE-40): create Dashboard page 2025-10-02 12:00:18 +07:00
ValdiANS 5c73f8f4af chore: update toggle dependencies 2025-10-02 12:00:02 +07:00
ValdiANS 2a6f2a1646 chore(FE-40): update MainDrawer component styling 2025-10-02 11:46:27 +07:00
ValdiANS d40a5dd898 chore: update Collapse styling 2025-10-02 11:46:09 +07:00
ValdiANS ca9205618a feat: add Modal component 2025-10-02 11:45:11 +07:00
ValdiANS 14046a1add chore(FE-40): create isResponseError api helper function 2025-10-01 16:02:12 +07:00
ValdiANS 8ad49a4480 chore(FE-40): export ErrorApiResponse and SucessApiResponse type 2025-10-01 16:01:47 +07:00
ValdiANS 4ff196cb9d chore(FE-40): remove unnecessary gap 2025-10-01 15:32:35 +07:00
ValdiANS 0afde48135 chore(FE-40): set correct page title 2025-10-01 15:24:33 +07:00
ValdiANS 9b2930375d chore(FE-40): fix bank link 2025-10-01 15:00:44 +07:00
ValdiANS 8a6a1e6b5c chore(FE-40): use RequireAuth in root layout 2025-10-01 15:00:06 +07:00
ValdiANS 6924aef8c4 feat(FE-40): create RequireAuth helper component 2025-10-01 14:59:46 +07:00
ValdiANS fa96d7a98a chore(FE-40): set opts.auth default to 'cookie' and export SWRHttpKey type 2025-10-01 14:08:02 +07:00
ValdiANS 3d3df42576 chore(FE-40): update import path and return isLoadingUser and setIsLoadingUser in useAuth 2025-10-01 14:07:30 +07:00
ValdiANS 05886896f1 chore(FE-40): update import path 2025-10-01 14:07:04 +07:00
ValdiANS a347024188 chore(FE-40): update CollapseMenu styling 2025-10-01 14:04:50 +07:00
ValdiANS 6969a2bcb8 chore(FE-40): move api.d.ts to /types/api/api-general.d.ts 2025-10-01 13:56:59 +07:00
ValdiANS 8206f7de5f feat(FE-40): create MainUiSlice type 2025-10-01 13:45:25 +07:00
ValdiANS a5b392ae76 feat(FE-40): create main UI slice 2025-10-01 13:45:16 +07:00
ValdiANS 6cbdff5398 feat(FE-40): add main UI slice to useUiStore 2025-10-01 13:45:00 +07:00
ValdiANS 87ce1e50aa feat(FE-40): create MAIN_DRAWER_LINKS constant 2025-10-01 13:44:42 +07:00
ValdiANS 2456d64a68 feat(FE-40): create MainDrawer component 2025-10-01 13:44:26 +07:00
ValdiANS c068fe5166 feat(FE-40): redirect to /dashboard 2025-10-01 13:44:18 +07:00
ValdiANS 19b7c53ec2 feat(FE-40): use MainDrawer component in root layout 2025-10-01 13:44:02 +07:00
ValdiANS 037e4776a8 chore: run eslint command in dev command 2025-09-30 15:45:33 +07:00
ValdiANS 3be69eeff8 fix: error type 2025-09-30 15:44:48 +07:00
ValdiANS a364a860fa chore: update PasswordInput component 2025-09-30 15:43:48 +07:00
ValdiANS 8e23a805a9 chore: update Button component 2025-09-30 15:43:04 +07:00
ValdiANS e052166b3a chore: update Pagination component 2025-09-30 15:42:25 +07:00
ValdiANS 691b49a902 chore: update Table component 2025-09-30 15:42:03 +07:00
ValdiANS 33f5ca2a57 chore: update Table component 2025-09-30 15:33:57 +07:00
ValdiANS 02c44ced92 chore: update Collapse component 2025-09-30 11:25:38 +07:00
ValdiANS 978285021e feat: add Collapse component 2025-09-29 11:58:57 +07:00
ValdiANS 7e57debb98 chore: update MenuItem component 2025-09-29 11:58:19 +07:00
Adnan Zahir a5d8ac47fe Merge branch 'init' into 'development'
init

See merge request mbugroup/lti-web-client!1
2025-09-26 11:41:47 +07:00
ValdiANS f127e16c7c chore: change copywriting 2025-09-26 11:36:53 +07:00
ValdiANS 2e1b0fef2b init 2025-09-26 11:06:31 +07:00
270 changed files with 37524 additions and 79 deletions
+47
View File
@@ -0,0 +1,47 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
# prettier
.prettierrc
# idea
.idea
+76
View File
@@ -0,0 +1,76 @@
stages: [notify]
# --- Notify when MR is opened/updated ---
notify_discord_mr:
stage: notify
image: alpine:3.20
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
variables:
WEBHOOK_URL: $DISCORD_WEBHOOK_URL
before_script:
- apk add --no-cache curl jq
script: |
MR_URL="${CI_PROJECT_URL}/-/merge_requests/${CI_MERGE_REQUEST_IID}"
jq -n \
--arg repo "$CI_PROJECT_PATH" \
--arg mr "#${CI_MERGE_REQUEST_IID}" \
--arg url "$MR_URL" \
--arg requestor "${GITLAB_USER_LOGIN:-$GITLAB_USER_NAME}" \
--arg source "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" \
--arg target "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" \
--arg title "$CI_MERGE_REQUEST_TITLE" \
'{
username: "CI Bot - FE",
embeds: [{
title: "📣 [LTI WEB CLIENT] Merge Request Opened/Updated",
description: ($mr + " in " + $repo),
url: $url,
color: 3447003,
fields: [
{name: "Author", value: $requestor, inline: true},
{name: "Source → Target", value: ($source + " → " + $target), inline: true},
{name: "Title", value: $title}
]
}]
}' \
| curl -sS -H "Content-Type: application/json" -d @- "$WEBHOOK_URL"
# --- Notify when MR is merged ---
notify_discord_merge:
stage: notify
image: alpine:3.20
rules:
# Only run for merge request pipelines that are in merged state
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_STATE == "merged"'
variables:
WEBHOOK_URL: $DISCORD_WEBHOOK_URL
before_script:
- apk add --no-cache curl jq
script: |
MR_URL="${CI_PROJECT_URL}/-/merge_requests/${CI_MERGE_REQUEST_IID}"
jq -n \
--arg repo "$CI_PROJECT_PATH" \
--arg mr "#${CI_MERGE_REQUEST_IID}" \
--arg url "$MR_URL" \
--arg requestor "${CI_MERGE_REQUEST_AUTHOR}" \
--arg source "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" \
--arg target "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" \
--arg title "$CI_MERGE_REQUEST_TITLE" \
'{
username: "CI Bot - FE",
embeds: [{
title: "✅ [LTI WEB CLIENT] Merge Request Merged",
description: ($mr + " has been merged into " + $repo),
url: $url,
color: 3066993,
fields: [
{name: "Author", value: $requestor, inline: true},
{name: "Source → Target", value: ($source + " → " + $target), inline: true},
{name: "Title", value: $title}
]
}]
}' \
| curl -sS -H "Content-Type: application/json" -d @- "$WEBHOOK_URL"
+3
View File
@@ -0,0 +1,3 @@
npm run format
npm run lint
npm run build
+15
View File
@@ -0,0 +1,15 @@
{
"singleQuote": true,
"jsxSingleQuote": true,
"endOfLine": "lf",
"arrowParens": "always",
"bracketSpacing": true,
"embeddedLanguageFormatting": "auto",
"htmlWhitespaceSensitivity": "css",
"printWidth": 80,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"semi": true,
"tabWidth": 2,
"trailingComma": "es5"
}
+15
View File
@@ -0,0 +1,15 @@
{
"singleQuote": true,
"jsxSingleQuote": true,
"endOfLine": "lf",
"arrowParens": "always",
"bracketSpacing": true,
"embeddedLanguageFormatting": "auto",
"htmlWhitespaceSensitivity": "css",
"printWidth": 80,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"semi": true,
"tabWidth": 2,
"trailingComma": "es5"
}
+22 -79
View File
@@ -1,93 +1,36 @@
# LTI - Client
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
## Getting Started
First, run the development server:
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.com/mbugroup/lti-client.git
git branch -M main
git push -uf origin main
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
## Integrate with your tools
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
- [ ] [Set up project integrations](https://gitlab.com/mbugroup/lti-client/-/settings/integrations)
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
## Collaborate with your team
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
## Learn More
## Test and Deploy
To learn more about Next.js, take a look at the following resources:
Use the built-in continuous integration in GitLab.
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
***
## Deploy on Vercel
# Editing this README
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
echo "VERCEL_GIT_COMMIT_REF: $VERCEL_GIT_COMMIT_REF"
if [[ "$VERCEL_GIT_COMMIT_REF" == "master" || "$VERCEL_GIT_COMMIT_REF" == "development" ]]; then
echo "✅ - Build can proceed"
exit 1
else
echo "🛑 - Build cancelled"
exit 0
fi
+25
View File
@@ -0,0 +1,25 @@
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import { FlatCompat } from '@eslint/eslintrc';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
});
const eslintConfig = [
...compat.extends('next/core-web-vitals', 'next/typescript'),
{
ignores: [
'node_modules/**',
'.next/**',
'out/**',
'build/**',
'next-env.d.ts',
],
},
];
export default eslintConfig;
+8
View File
@@ -0,0 +1,8 @@
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'export',
images: { unoptimized: true },
};
export default nextConfig;
+7098
View File
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
{
"name": "lti-web-client",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "eslint && next dev --turbopack",
"build": "next build --turbopack",
"start": "next start",
"lint": "eslint",
"prepare": "husky",
"format": "prettier --write ."
},
"dependencies": {
"@tanstack/match-sorter-utils": "^8.19.4",
"@tanstack/react-table": "^8.21.3",
"axios": "^1.12.2",
"clsx": "^2.1.1",
"formik": "^2.4.6",
"inputmask": "^5.0.9",
"moment": "^2.30.1",
"next": "15.5.3",
"react": "19.1.0",
"react-day-picker": "^9.11.1",
"react-dom": "19.1.0",
"react-dropzone": "^14.3.8",
"react-hot-toast": "^2.6.0",
"react-number-format": "^5.4.4",
"react-select": "^5.10.2",
"swr": "^2.3.6",
"tailwind-merge": "^3.3.1",
"use-debounce": "^10.0.6",
"yup": "^1.7.0",
"zustand": "^5.0.8"
},
"devDependencies": {
"@eslint/eslintrc": "^3",
"@iconify/react": "^6.0.2",
"@tailwindcss/postcss": "^4",
"@types/inputmask": "^5.0.7",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"daisyui": "^5.1.12",
"eslint": "^9",
"eslint-config-next": "15.5.3",
"husky": "^9.1.7",
"prettier": "^3.6.2",
"tailwindcss": "^4",
"typescript": "^5"
}
}
+5
View File
@@ -0,0 +1,5 @@
const config = {
plugins: ['@tailwindcss/postcss'],
};
export default config;
Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

+9
View File
@@ -0,0 +1,9 @@
const Dashboard = () => {
return (
<section className='w-full p-4'>
<h1 className='text-3xl font-bold text-primary'>Dashboard</h1>
</section>
);
};
export default Dashboard;
+11
View File
@@ -0,0 +1,11 @@
import ExpenseRequestForm from '@/components/pages/expense/form/ExpenseRequestForm';
const AddExpense = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<ExpenseRequestForm />
</div>
);
};
export default AddExpense;
+11
View File
@@ -0,0 +1,11 @@
import ExpensesTable from '@/components/pages/expense/ExpensesTable';
const Expense = () => {
return (
<section className='w-full p-4'>
<ExpensesTable />
</section>
);
};
export default Expense;
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+50
View File
@@ -0,0 +1,50 @@
@import 'tailwindcss';
@plugin "daisyui";
@import '../styles/daisyui.css';
@plugin "daisyui/theme" {
name: 'lti';
default: false;
prefersdark: false;
color-scheme: 'light';
--color-base-100: oklch(98% 0.001 106.423);
--color-base-200: oklch(97% 0.001 106.424);
--color-base-300: oklch(92% 0.003 48.717);
--color-base-content: oklch(22.389% 0.031 278.072);
--color-primary: oklch(60% 0.126 221.723);
--color-primary-content: oklch(100% 0 0);
--color-secondary: oklch(52% 0.105 223.128);
--color-secondary-content: oklch(100% 0 0);
--color-accent: oklch(45% 0.085 224.283);
--color-accent-content: oklch(100% 0 0);
--color-neutral: oklch(39% 0.07 227.392);
--color-neutral-content: oklch(100% 0 0);
--color-info: oklch(58% 0.158 241.966);
--color-info-content: oklch(100% 0 0);
--color-success: oklch(62% 0.194 149.214);
--color-success-content: oklch(100% 0 0);
--color-warning: oklch(85% 0.199 91.936);
--color-warning-content: oklch(0% 0 0);
--color-error: oklch(57% 0.245 27.325);
--color-error-content: oklch(100% 0 0);
--radius-selector: 0rem;
--radius-field: 0.25rem;
--radius-box: 0.25rem;
--size-selector: 0.21875rem;
--size-field: 0.1875rem;
--border: 1px;
--depth: 0;
--noise: 0;
}
:root {
--color-primary: #1f74bf;
}
@theme {
--font-inter: var(--font-inter);
}
html {
scrollbar-gutter: initial;
}
+11
View File
@@ -0,0 +1,11 @@
import InventoryAdjustmentForm from '@/components/pages/inventory/adjustment/form/InventoryAdjustmentForm';
const CreateInventoryAdjustment = () => {
return (
<section className='w-full p-4 flex flex-row justify-center'>
<InventoryAdjustmentForm />
</section>
);
};
export default CreateInventoryAdjustment;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,47 @@
'use client';
import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import InventoryAdjustmentForm from '@/components/pages/inventory/adjustment/form/InventoryAdjustmentForm';
import type { InventoryAdjustment } from '@/types/api/inventory/adjustment';
const DetailInventoryAdjustment = () => {
const router = useRouter();
const [inventoryAdjustment, setInventoryAdjustment] =
useState<InventoryAdjustment | null>(null);
// Ambil data dari router state
useEffect(() => {
console.log('Router State');
console.log(window.history.state);
const state = window.history.state?.usr as
| { inventoryAdjustment?: InventoryAdjustment }
| undefined;
if (state?.inventoryAdjustment) {
// jika object dikirim via router.push(state)
setInventoryAdjustment(state.inventoryAdjustment);
}
}, [router]);
const finalData = inventoryAdjustment;
console.log('Final Data');
console.log(finalData);
if (!finalData) {
return (
<div className='w-full flex flex-row justify-center items-center p-4'>
<span className='loading loading-spinner loading-xl' />
</div>
);
}
return (
<section className='w-full p-4 flex flex-row justify-center'>
<InventoryAdjustmentForm initialValues={finalData} />
</section>
);
};
export default DetailInventoryAdjustment;
+11
View File
@@ -0,0 +1,11 @@
import InventoryAdjustmentTable from '@/components/pages/inventory/adjustment/InventoryAdjustmentTable';
const InventoryAdjustment = () => {
return (
<section className='w-full p-4'>
<InventoryAdjustmentTable />
</section>
);
};
export default InventoryAdjustment;
+11
View File
@@ -0,0 +1,11 @@
import MovementForm from '@/components/pages/inventory/movement/form/MovementForm';
const AddMovement = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<MovementForm />
</div>
);
};
export default AddMovement;
@@ -0,0 +1,48 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import MovementForm from '@/components/pages/inventory/movement/form/MovementForm';
import { MovementApi } from '@/services/api/inventory';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const MovementEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const movementId = searchParams.get('movementId');
const { data: movement, isLoading: isLoadingMovement } = useSWR(
movementId,
(id: number) => MovementApi.getSingle(id)
);
if (!movementId) {
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 (!isLoadingMovement && (!movement || isResponseError(movement))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingMovement && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingMovement && isResponseSuccess(movement) && (
<MovementForm type='edit' initialValues={movement.data} />
)}
</div>
);
};
export default MovementEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,48 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import MovementForm from '@/components/pages/inventory/movement/form/MovementForm';
import { MovementApi } from '@/services/api/inventory';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const MovementDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const movementId = searchParams.get('movementId');
const { data: movement, isLoading: isLoadingMovement } = useSWR(
movementId,
(id: number) => MovementApi.getSingle(id)
);
if (!movementId) {
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 (!isLoadingMovement && (!movement || isResponseError(movement))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingMovement && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingMovement && isResponseSuccess(movement) && (
<MovementForm type='detail' initialValues={movement.data} />
)}
</div>
);
};
export default MovementDetail;
+11
View File
@@ -0,0 +1,11 @@
import MovementTable from '@/components/pages/inventory/movement/MovementTable';
const Movement = () => {
return (
<section className='w-full p-4'>
<MovementTable />
</section>
);
};
export default Movement;
+41
View File
@@ -0,0 +1,41 @@
import type { Metadata, Viewport } from 'next';
import { Inter } from 'next/font/google';
import '@/app/globals.css';
import { Toaster } from 'react-hot-toast';
import MainDrawer from '@/components/MainDrawer';
import RequireAuth from '@/components/helper/RequireAuth';
const inter = Inter({
variable: '--font-inter',
subsets: ['latin'],
});
export const viewport: Viewport = {
themeColor: '#1f74bf',
colorScheme: 'light',
initialScale: 1,
};
export const metadata: Metadata = {
title: 'LTI',
description: 'PT. Lumbung Telur Indonesia',
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang='en' data-theme='lti'>
<body className={`${inter.variable} antialiased font-inter`}>
<RequireAuth>
<MainDrawer>{children}</MainDrawer>
</RequireAuth>
<Toaster />
</body>
</html>
);
}
+11
View File
@@ -0,0 +1,11 @@
import AreaForm from '@/components/pages/master-data/area/form/AreaForm';
const AddNonstock = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<AreaForm />
</div>
);
};
export default AddNonstock;
@@ -0,0 +1,47 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import AreaForm from '@/components/pages/master-data/area/form/AreaForm';
import { AreaApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const AreaEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const areaId = searchParams.get('areaId');
const { data: area, isLoading: isLoadingArea } = useSWR(
areaId,
(id: number) => AreaApi.getSingle(id)
);
if (!areaId) {
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 (!isLoadingArea && (!area || isResponseError(area))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingArea && <span className='loading loading-spinner loading-xl' />}
{!isLoadingArea && isResponseSuccess(area) && (
<AreaForm type='edit' initialValues={area.data} />
)}
</div>
);
};
export default AreaEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
+47
View File
@@ -0,0 +1,47 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import AreaForm from '@/components/pages/master-data/area/form/AreaForm';
import { AreaApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const AreaDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const areaId = searchParams.get('areaId');
const { data: area, isLoading: isLoadingArea } = useSWR(
areaId,
(id: number) => AreaApi.getSingle(id)
);
if (!areaId) {
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 (!isLoadingArea && (!area || isResponseError(area))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingArea && <span className='loading loading-spinner loading-xl' />}
{!isLoadingArea && isResponseSuccess(area) && (
<AreaForm type='detail' initialValues={area.data} />
)}
</div>
);
};
export default AreaDetail;
+11
View File
@@ -0,0 +1,11 @@
import AreasTable from '@/components/pages/master-data/area/AreasTable';
const Nonstock = () => {
return (
<section className='w-full p-4'>
<AreasTable />
</section>
);
};
export default Nonstock;
+11
View File
@@ -0,0 +1,11 @@
import BankForm from '@/components/pages/master-data/bank/form/BankForm';
const AddBank = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<BankForm />
</div>
);
};
export default AddBank;
@@ -0,0 +1,47 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import BankForm from '@/components/pages/master-data/bank/form/BankForm';
import { BankApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const BankEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const bankId = searchParams.get('bankId');
const { data: bank, isLoading: isLoadingBank } = useSWR(
bankId,
(id: number) => BankApi.getSingle(id)
);
if (!bankId) {
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 (!isLoadingBank && (!bank || isResponseError(bank))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingBank && <span className='loading loading-spinner loading-xl' />}
{!isLoadingBank && isResponseSuccess(bank) && (
<BankForm type='edit' initialValues={bank.data} />
)}
</div>
);
};
export default BankEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
+47
View File
@@ -0,0 +1,47 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import BankForm from '@/components/pages/master-data/bank/form/BankForm';
import { BankApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const BankDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const bankId = searchParams.get('bankId');
const { data: bank, isLoading: isLoadingBank } = useSWR(
bankId,
(id: number) => BankApi.getSingle(id)
);
if (!bankId) {
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 (!isLoadingBank && (!bank || isResponseError(bank))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingBank && <span className='loading loading-spinner loading-xl' />}
{!isLoadingBank && isResponseSuccess(bank) && (
<BankForm type='detail' initialValues={bank.data} />
)}
</div>
);
};
export default BankDetail;
+11
View File
@@ -0,0 +1,11 @@
import BanksTable from '@/components/pages/master-data/bank/BanksTable';
const Bank = () => {
return (
<section className='w-full p-4'>
<BanksTable />
</section>
);
};
export default Bank;
+11
View File
@@ -0,0 +1,11 @@
import CustomerForm from '@/components/pages/master-data/customer/form/CustomerForm';
const AddCustomer = () => {
return (
<section className='w-full p-4 flex flex-row justify-center'>
<CustomerForm />
</section>
);
};
export default AddCustomer;
@@ -0,0 +1,47 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import { CustomerApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import CustomerForm from '@/components/pages/master-data/customer/form/CustomerForm';
const CustomerEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const costumerId = searchParams.get('customerId');
const { data: costumer, isLoading: isLoadingCostumer } = useSWR(
costumerId,
(id: number) => CustomerApi.getSingle(id)
);
if (!costumerId) {
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 (!isLoadingCostumer && (!costumer || isResponseError(costumer))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingCostumer && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingCostumer && isResponseSuccess(costumer) && (
<CustomerForm formType='edit' initialValues={costumer.data} />
)}
</div>
);
};
export default CustomerEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,47 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import { CustomerApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import CustomerForm from '@/components/pages/master-data/customer/form/CustomerForm';
const CustomerDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const costumerId = searchParams.get('customerId');
const { data: costumer, isLoading: isLoadingCostumer } = useSWR(
costumerId,
(id: number) => CustomerApi.getSingle(id)
);
if (!costumerId) {
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 (!isLoadingCostumer && (!costumer || isResponseError(costumer))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingCostumer && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingCostumer && isResponseSuccess(costumer) && (
<CustomerForm formType='detail' initialValues={costumer.data} />
)}
</div>
);
};
export default CustomerDetail;
+11
View File
@@ -0,0 +1,11 @@
import CustomersTable from '@/components/pages/master-data/customer/CustomersTable';
const Customer = () => {
return (
<section className='w-full p-4'>
<CustomersTable />
</section>
);
};
export default Customer;
+11
View File
@@ -0,0 +1,11 @@
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;
@@ -0,0 +1,52 @@
'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
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
+52
View File
@@ -0,0 +1,52 @@
'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
@@ -0,0 +1,11 @@
import FcrsTable from '@/components/pages/master-data/fcr/FcrsTable';
const Fcr = () => {
return (
<section className='w-full p-4'>
<FcrsTable />
</section>
);
};
export default Fcr;
+11
View File
@@ -0,0 +1,11 @@
import FlockForm from '@/components/pages/master-data/flock/form/FlockForm';
const AddFlock = () => {
return (
<section className='w-full p-4 flex flex-row justify-center'>
<FlockForm />
</section>
);
};
export default AddFlock;
@@ -0,0 +1,49 @@
'use client';
import FlockForm from '@/components/pages/master-data/flock/form/FlockForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { FlockApi } from '@/services/api/master-data';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
const FlockEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
// Get Query Params
const flockId = searchParams.get('flockId');
// Fetch Data
const { data: flock, isLoading: isLoadingFlock } = useSWR(
flockId,
(id: number) => FlockApi.getSingle(id)
);
if (!flockId) {
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 (!isLoadingFlock && (!flock || isResponseError(flock))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingFlock && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingFlock && isResponseSuccess(flock) && (
<FlockForm formType='edit' initialValues={flock.data} />
)}
</div>
);
};
export default FlockEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
+49
View File
@@ -0,0 +1,49 @@
'use client';
import FlockForm from '@/components/pages/master-data/flock/form/FlockForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { FlockApi } from '@/services/api/master-data';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
const FlockDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
// Get Query Params
const flockId = searchParams.get('flockId');
// Fetch Data
const { data: flock, isLoading: isLoadingFlock } = useSWR(
flockId,
(id: number) => FlockApi.getSingle(id)
);
if (!flockId) {
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 (!isLoadingFlock && (!flock || isResponseError(flock))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingFlock && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingFlock && isResponseSuccess(flock) && (
<FlockForm formType='detail' initialValues={flock.data} />
)}
</div>
);
};
export default FlockDetail;
+11
View File
@@ -0,0 +1,11 @@
import FlockTable from '@/components/pages/master-data/flock/FlocksTable';
const Flock = () => {
return (
<section className='w-full p-4'>
<FlockTable />
</section>
);
};
export default Flock;
+11
View File
@@ -0,0 +1,11 @@
import KandangForm from '@/components/pages/master-data/kandang/form/KandangForm';
const AddNonstock = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<KandangForm />
</div>
);
};
export default AddNonstock;
@@ -0,0 +1,49 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import KandangForm from '@/components/pages/master-data/kandang/form/KandangForm';
import { KandangApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const KandangEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const kandangId = searchParams.get('kandangId');
const { data: kandang, isLoading: isLoadingKandang } = useSWR(
kandangId,
(id: number) => KandangApi.getSingle(id)
);
if (!kandangId) {
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 (!isLoadingKandang && (!kandang || isResponseError(kandang))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingKandang && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingKandang && isResponseSuccess(kandang) && (
<KandangForm type='edit' initialValues={kandang.data} />
)}
</div>
);
};
export default KandangEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,49 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import KandangForm from '@/components/pages/master-data/kandang/form/KandangForm';
import { KandangApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const KandangDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const kandangId = searchParams.get('kandangId');
const { data: kandang, isLoading: isLoadingKandang } = useSWR(
kandangId,
(id: number) => KandangApi.getSingle(id)
);
if (!kandangId) {
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 (!isLoadingKandang && (!kandang || isResponseError(kandang))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingKandang && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingKandang && isResponseSuccess(kandang) && (
<KandangForm type='detail' initialValues={kandang.data} />
)}
</div>
);
};
export default KandangDetail;
+11
View File
@@ -0,0 +1,11 @@
import KandangsTable from '@/components/pages/master-data/kandang/KandangsTable';
const Nonstock = () => {
return (
<section className='w-full p-4'>
<KandangsTable />
</section>
);
};
export default Nonstock;
+11
View File
@@ -0,0 +1,11 @@
import LocationForm from '@/components/pages/master-data/location/form/LocationForm';
const AddNonstock = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<LocationForm />
</div>
);
};
export default AddNonstock;
@@ -0,0 +1,49 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import LocationForm from '@/components/pages/master-data/location/form/LocationForm';
import { LocationApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const LocationEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const locationId = searchParams.get('locationId');
const { data: location, isLoading: isLoadingLocation } = useSWR(
locationId,
(id: number) => LocationApi.getSingle(id)
);
if (!locationId) {
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 (!isLoadingLocation && (!location || isResponseError(location))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingLocation && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingLocation && isResponseSuccess(location) && (
<LocationForm type='edit' initialValues={location.data} />
)}
</div>
);
};
export default LocationEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,49 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import LocationForm from '@/components/pages/master-data/location/form/LocationForm';
import { LocationApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const LocationDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const locationId = searchParams.get('locationId');
const { data: location, isLoading: isLoadingLocation } = useSWR(
locationId,
(id: number) => LocationApi.getSingle(id)
);
if (!locationId) {
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 (!isLoadingLocation && (!location || isResponseError(location))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingLocation && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingLocation && isResponseSuccess(location) && (
<LocationForm type='detail' initialValues={location.data} />
)}
</div>
);
};
export default LocationDetail;
+11
View File
@@ -0,0 +1,11 @@
import LocationsTable from '@/components/pages/master-data/location/LocationsTable';
const Nonstock = () => {
return (
<section className='w-full p-4'>
<LocationsTable />
</section>
);
};
export default Nonstock;
+11
View File
@@ -0,0 +1,11 @@
import NonstockForm from '@/components/pages/master-data/nonstock/form/NonstockForm';
const AddNonstock = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<NonstockForm />
</div>
);
};
export default AddNonstock;
@@ -0,0 +1,49 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import NonstockForm from '@/components/pages/master-data/nonstock/form/NonstockForm';
import { NonstockApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const NonstockEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const nonstockId = searchParams.get('nonstockId');
const { data: nonstock, isLoading: isLoadingNonstock } = useSWR(
nonstockId,
(id: number) => NonstockApi.getSingle(id)
);
if (!nonstockId) {
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 (!isLoadingNonstock && (!nonstock || isResponseError(nonstock))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingNonstock && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingNonstock && isResponseSuccess(nonstock) && (
<NonstockForm type='edit' initialValues={nonstock.data} />
)}
</div>
);
};
export default NonstockEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,49 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import NonstockForm from '@/components/pages/master-data/nonstock/form/NonstockForm';
import { NonstockApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const NonstockDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const nonstockId = searchParams.get('nonstockId');
const { data: nonstock, isLoading: isLoadingNonstock } = useSWR(
nonstockId,
(id: number) => NonstockApi.getSingle(id)
);
if (!nonstockId) {
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 (!isLoadingNonstock && (!nonstock || isResponseError(nonstock))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingNonstock && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingNonstock && isResponseSuccess(nonstock) && (
<NonstockForm type='detail' initialValues={nonstock.data} />
)}
</div>
);
};
export default NonstockDetail;
+11
View File
@@ -0,0 +1,11 @@
import NonstocksTable from '@/components/pages/master-data/nonstock/NonstocksTable';
const Nonstock = () => {
return (
<section className='w-full p-4'>
<NonstocksTable />
</section>
);
};
export default Nonstock;
@@ -0,0 +1,11 @@
import ProductCategoryForm from '@/components/pages/master-data/product-category/form/ProductCategoryForm';
const AddProductCategory = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<ProductCategoryForm />
</div>
);
};
export default AddProductCategory;
@@ -0,0 +1,52 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import ProductCategoryForm from '@/components/pages/master-data/product-category/form/ProductCategoryForm';
import { ProductCategoryApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const ProductCategoryEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const productCategoryId = searchParams.get('productCategoryId');
const { data: productCategory, isLoading: isLoadingProductCategory } = useSWR(
productCategoryId,
(id: number) => ProductCategoryApi.getSingle(id)
);
if (!productCategoryId) {
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 (
!isLoadingProductCategory &&
(!productCategory || isResponseError(productCategory))
) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingProductCategory && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingProductCategory && isResponseSuccess(productCategory) && (
<ProductCategoryForm type='edit' initialValues={productCategory.data} />
)}
</div>
);
};
export default ProductCategoryEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,55 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import ProductCategoryForm from '@/components/pages/master-data/product-category/form/ProductCategoryForm';
import { ProductCategoryApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const ProductCategoryDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const productCategoryId = searchParams.get('productCategoryId');
const { data: productCategory, isLoading: isLoadingProductCategory } = useSWR(
productCategoryId,
(id: number) => ProductCategoryApi.getSingle(id)
);
if (!productCategoryId) {
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 (
!isLoadingProductCategory &&
(!productCategory || isResponseError(productCategory))
) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingProductCategory && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingProductCategory && isResponseSuccess(productCategory) && (
<ProductCategoryForm
type='detail'
initialValues={productCategory.data}
/>
)}
</div>
);
};
export default ProductCategoryDetail;
@@ -0,0 +1,11 @@
import ProductCategoryTable from '@/components/pages/master-data/product-category/ProductCategoryTable';
const ProductCategory = () => {
return (
<section className='w-full p-4'>
<ProductCategoryTable />
</section>
);
};
export default ProductCategory;
+11
View File
@@ -0,0 +1,11 @@
import ProductForm from '@/components/pages/master-data/product/form/ProductForm';
const AddProduct = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<ProductForm />
</div>
);
};
export default AddProduct;
@@ -0,0 +1,44 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import ProductForm from '@/components/pages/master-data/product/form/ProductForm';
import { ProductApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const ProductEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const productId = searchParams.get('productId');
const { data: product, isLoading } = useSWR(productId, (id: number) =>
ProductApi.getSingle(id)
);
if (!productId) {
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 && (!product || isResponseError(product))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoading && <span className='loading loading-spinner loading-xl' />}
{!isLoading && isResponseSuccess(product) && (
<ProductForm type='edit' initialValues={product.data} />
)}
</div>
);
};
export default ProductEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,44 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import ProductForm from '@/components/pages/master-data/product/form/ProductForm';
import { ProductApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const ProductDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const productId = searchParams.get('productId');
const { data: product, isLoading } = useSWR(productId, (id: number) =>
ProductApi.getSingle(id)
);
if (!productId) {
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 && (!product || isResponseError(product))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoading && <span className='loading loading-spinner loading-xl' />}
{!isLoading && isResponseSuccess(product) && (
<ProductForm type='detail' initialValues={product.data} />
)}
</div>
);
};
export default ProductDetail;
+11
View File
@@ -0,0 +1,11 @@
import ProductsTable from '@/components/pages/master-data/product/ProductTable';
const Product = () => {
return (
<section className='w-full p-4'>
<ProductsTable />
</section>
);
};
export default Product;
+11
View File
@@ -0,0 +1,11 @@
import SupplierForm from '@/components/pages/master-data/supplier/form/SupplierForm';
const AddSupplier = () => {
return (
<section className='w-full p-4 flex flex-row justify-center'>
<SupplierForm />
</section>
);
};
export default AddSupplier;
@@ -0,0 +1,49 @@
'use client';
import SupplierForm from '@/components/pages/master-data/supplier/form/SupplierForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { SupplierApi } from '@/services/api/master-data';
import { useSearchParams, useRouter } from 'next/navigation';
import useSWR from 'swr';
const SupplierEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
// Get Query Params
const supplierId = searchParams.get('supplierId');
// Fetch Data
const { data: supplier, isLoading: isLoadingSupplier } = useSWR(
supplierId,
(id: number) => SupplierApi.getSingle(id)
);
if (!supplierId) {
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 (!isLoadingSupplier && (!supplier || isResponseError(supplier))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingSupplier && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingSupplier && isResponseSuccess(supplier) && (
<SupplierForm formType='edit' initialValues={supplier.data} />
)}
</div>
);
};
export default SupplierEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,49 @@
'use client';
import SupplierForm from '@/components/pages/master-data/supplier/form/SupplierForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { SupplierApi } from '@/services/api/master-data';
import { useSearchParams, useRouter } from 'next/navigation';
import useSWR from 'swr';
const SupplierDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
// Get Query Params
const supplierId = searchParams.get('supplierId');
// Fetch Data
const { data: supplier, isLoading: isLoadingSupplier } = useSWR(
supplierId,
(id: number) => SupplierApi.getSingle(id)
);
if (!supplierId) {
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 (!isLoadingSupplier && (!supplier || isResponseError(supplier))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingSupplier && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingSupplier && isResponseSuccess(supplier) && (
<SupplierForm formType='detail' initialValues={supplier.data} />
)}
</div>
);
};
export default SupplierDetail;
+11
View File
@@ -0,0 +1,11 @@
import SuppliersTable from '@/components/pages/master-data/supplier/SupplierTable';
const Supplier = () => {
return (
<section className='w-full p-4'>
<SuppliersTable />
</section>
);
};
export default Supplier;
+11
View File
@@ -0,0 +1,11 @@
import UomForm from '@/components/pages/master-data/uom/form/UomForm';
const AddNonstock = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<UomForm />
</div>
);
};
export default AddNonstock;
@@ -0,0 +1,46 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import UomForm from '@/components/pages/master-data/uom/form/UomForm';
import { UomApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const UomEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const uomId = searchParams.get('uomId');
const { data: uom, isLoading: isLoadingUom } = useSWR(uomId, (id: number) =>
UomApi.getSingle(id)
);
if (!uomId) {
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 (!isLoadingUom && (!uom || isResponseError(uom))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingUom && <span className='loading loading-spinner loading-xl' />}
{!isLoadingUom && isResponseSuccess(uom) && (
<UomForm type='edit' initialValues={uom.data} />
)}
</div>
);
};
export default UomEdit;
+11
View File
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
+46
View File
@@ -0,0 +1,46 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import UomForm from '@/components/pages/master-data/uom/form/UomForm';
import { UomApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const UomDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const uomId = searchParams.get('uomId');
const { data: uom, isLoading: isLoadingUom } = useSWR(uomId, (id: number) =>
UomApi.getSingle(id)
);
if (!uomId) {
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 (!isLoadingUom && (!uom || isResponseError(uom))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingUom && <span className='loading loading-spinner loading-xl' />}
{!isLoadingUom && isResponseSuccess(uom) && (
<UomForm type='detail' initialValues={uom.data} />
)}
</div>
);
};
export default UomDetail;
+11
View File
@@ -0,0 +1,11 @@
import UomsTable from '@/components/pages/master-data/uom/UomsTable';
const Nonstock = () => {
return (
<section className='w-full p-4'>
<UomsTable />
</section>
);
};
export default Nonstock;
@@ -0,0 +1,11 @@
import WarehouseForm from '@/components/pages/master-data/warehouse/form/WarehouseForm';
const AddNonstock = () => {
return (
<div className='w-full p-4 flex flex-row justify-center'>
<WarehouseForm />
</div>
);
};
export default AddNonstock;
@@ -0,0 +1,49 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import WarehouseForm from '@/components/pages/master-data/warehouse/form/WarehouseForm';
import { WarehouseApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const WarehouseEdit = () => {
const router = useRouter();
const searchParams = useSearchParams();
const warehouseId = searchParams.get('warehouseId');
const { data: warehouse, isLoading: isLoadingWarehouse } = useSWR(
warehouseId,
(id: number) => WarehouseApi.getSingle(id)
);
if (!warehouseId) {
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 (!isLoadingWarehouse && (!warehouse || isResponseError(warehouse))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingWarehouse && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingWarehouse && isResponseSuccess(warehouse) && (
<WarehouseForm type='edit' initialValues={warehouse.data} />
)}
</div>
);
};
export default WarehouseEdit;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
@@ -0,0 +1,49 @@
'use client';
import { useRouter, useSearchParams } from 'next/navigation';
import useSWR from 'swr';
import WarehouseForm from '@/components/pages/master-data/warehouse/form/WarehouseForm';
import { WarehouseApi } from '@/services/api/master-data';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const WarehouseDetail = () => {
const router = useRouter();
const searchParams = useSearchParams();
const warehouseId = searchParams.get('warehouseId');
const { data: warehouse, isLoading: isLoadingWarehouse } = useSWR(
warehouseId,
(id: number) => WarehouseApi.getSingle(id)
);
if (!warehouseId) {
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 (!isLoadingWarehouse && (!warehouse || isResponseError(warehouse))) {
router.replace('/404');
return;
}
return (
<div className='w-full p-4 flex flex-row justify-center'>
{isLoadingWarehouse && (
<span className='loading loading-spinner loading-xl' />
)}
{!isLoadingWarehouse && isResponseSuccess(warehouse) && (
<WarehouseForm type='detail' initialValues={warehouse.data} />
)}
</div>
);
};
export default WarehouseDetail;
+11
View File
@@ -0,0 +1,11 @@
import WarehousesTable from '@/components/pages/master-data/warehouse/WarehousesTable';
const Warehouse = () => {
return (
<section className='w-full p-4'>
<WarehousesTable />
</section>
);
};
export default Warehouse;
+11
View File
@@ -0,0 +1,11 @@
import { redirect } from 'next/navigation';
export default function Home() {
redirect('/dashboard');
return (
<main className='w-full h-full min-h-screen flex flex-row justify-center items-center'>
<h1>LTI ERP</h1>
</main>
);
}
+11
View File
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
+270
View File
@@ -0,0 +1,270 @@
'use client';
import Button from '@/components/Button';
import SelectInput, { OptionType } from '@/components/input/SelectInput';
import Modal, { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
import ChickinForm from '@/components/pages/production/chickin/form/ChickinForm';
import Table from '@/components/Table';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { cn } from '@/lib/helper';
import { ProjectFlockApi } from '@/services/api/production';
import { useTableFilter } from '@/services/hooks/useTableFilter';
import { BaseApiResponse } from '@/types/api/api-general';
import { Kandang } from '@/types/api/master-data/kandang';
import { ProjectFlockKandang } from '@/types/api/production/project-flock-kandang';
import { Icon } from '@iconify/react';
import { useRouter, useSearchParams } from 'next/navigation';
import { useState } from 'react';
import useSWR from 'swr';
const AddChickin = () => {
const router = useRouter();
const searchParams = useSearchParams();
const projectFlockId = searchParams.get('projectFlockId');
// Tables Props
const { state: tableFilterState } = useTableFilter({
initial: { search: '' },
paramMap: { page: 'page', pageSize: 'limit' },
});
// States
const [selectedKandang, setSelectedKandang] = useState<Kandang | undefined>(
undefined
);
const [projectFlockKandang, setProjectFlockKandang] =
useState<BaseApiResponse<ProjectFlockKandang>>();
const [isLoadingProjectFlockKandang, setIsLoadingProjectFlockKandang] =
useState(false);
const [searchProjectFlock, setSearchProjectFlock] = useState('');
// Fetch Data
const { data: projectFlock, isLoading: isLoadingProjectFlock } = useSWR(
projectFlockId,
(id: number) => ProjectFlockApi.getSingle(id)
);
const { data: listProjectFlock, isLoading: isLoadingListProjectFlock } =
useSWR(
`${ProjectFlockApi.basePath}?${new URLSearchParams({
search: searchProjectFlock,
}).toString()}`,
ProjectFlockApi.getAllFetcher
);
const getProjectFlockKandangUrl = `/kandangs/lookup`;
// Mapping Options
const options = isResponseSuccess(listProjectFlock)
? listProjectFlock?.data.map((projectFlock) => {
return {
value: projectFlock.id,
label: `${projectFlock?.flock?.name} - ${projectFlock?.category} - Periode ${projectFlock.period}`,
};
})
: [];
const chickinModal = useModal();
const alertModal = useModal();
if (!projectFlockId) {
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 (
!isLoadingProjectFlock &&
(!projectFlock || isResponseError(projectFlock))
) {
router.replace('/404');
return;
}
// Handle Function
const handleChickinClick = async (kandang: Kandang) => {
setIsLoadingProjectFlockKandang(true);
setSelectedKandang(kandang);
const ProjectFlockKandangRes = await ProjectFlockApi.customRequest<
BaseApiResponse<ProjectFlockKandang>,
'GET'
>(getProjectFlockKandangUrl, {
method: 'GET',
params: {
project_flock_id: projectFlockId ?? 0,
kandang_id: kandang.id,
},
});
if (isResponseSuccess(ProjectFlockKandangRes)) {
setProjectFlockKandang(ProjectFlockKandangRes);
setIsLoadingProjectFlockKandang(false);
if (
ProjectFlockKandangRes.data.available_quantity &&
ProjectFlockKandangRes.data.available_quantity > 0
) {
chickinModal.openModal();
} else {
alertModal.openModal();
}
}
};
const handleAfterSubmit = () => {
chickinModal.closeModal();
router.push('/production/chickin');
};
return (
<>
{isResponseSuccess(projectFlock) && (
<>
<section className='w-full p-4'>
<header className='flex flex-col gap-4'>
<Button
href='/production/project-flock'
variant='link'
className='w-fit p-0 text-primary'
>
<Icon icon='uil:arrow-left' width={24} height={24} />
Kembali
</Button>
<div className='flex flex-col gap-4 w-full my-4'>
<div className='max-w-full sm:max-w-1/2 md:max-w-3/5 lg:max-w-2/5'>
<SelectInput
required
isSearchable
label='Project Flock'
options={options}
isLoading={isLoadingListProjectFlock}
value={{
label: `${projectFlock.data?.flock?.name} - ${projectFlock.data?.category} - Periode ${projectFlock.data?.period}`,
value: projectFlock.data?.id,
}}
onChange={(val) =>
router.push(
`/production/chickin/add?projectFlockId=${
(val as OptionType | null)?.value
}`
)
}
onInputChange={(val) => {
setSearchProjectFlock(val);
}}
/>
</div>
</div>
</header>
<Table<Kandang>
data={projectFlock.data?.kandangs}
columns={[
{
header: '#',
cell: (props) =>
tableFilterState.pageSize * (tableFilterState.page - 1) +
props.row.index +
1,
},
{
accessorKey: 'name',
header: 'Nama Kandang',
},
{
header: 'Aksi',
cell: (props) => {
return (
<>
<Button
color='success'
variant='outline'
onClick={() => {
handleChickinClick(props.row.original);
}}
disabled={isLoadingProjectFlockKandang}
>
<Icon
icon='mdi:home-import-outline'
width={24}
height={24}
/>
Chickin
</Button>
</>
);
},
},
]}
page={undefined}
className={{
containerClassName: cn({
'mb-20':
isResponseSuccess(projectFlock) &&
projectFlock.data?.kandangs?.length === 0,
}),
tableWrapperClassName: 'overflow-x-auto min-h-full!',
tableClassName: 'font-inter w-full table-auto min-h-full!',
headerRowClassName: 'border-b border-b-gray-200',
headerColumnClassName:
'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
bodyRowClassName: 'border-b border-b-gray-200',
bodyColumnClassName:
'px-6 py-3 last:flex last:flex-row last:justify-end',
paginationClassName: 'hidden',
}}
/>
</section>
<Modal ref={chickinModal.ref}>
<div className='flex flex-row justify-between items-center'>
<h1 className='text-xl font-semibold text-center mb-6'>
Chickin Kandang - {selectedKandang?.name}
</h1>
<Button
color='error'
variant='link'
onClick={chickinModal.closeModal}
>
<Icon
className='text-black'
icon='uil:times'
width={24}
height={24}
/>
</Button>
</div>
{isResponseSuccess(projectFlockKandang) &&
!isLoadingProjectFlockKandang && (
<ChickinForm
initialValues={{
project_flock_kandang: projectFlockKandang.data,
created_user: projectFlock.data?.created_user,
created_at: projectFlock.data?.created_at,
updated_at: projectFlock.data?.updated_at,
approval: projectFlock.data?.approval,
}}
afterSubmit={handleAfterSubmit}
/>
)}
</Modal>
<ConfirmationModal
ref={alertModal.ref}
type='info'
text={`Persediaan Day Old Chick pada kandang (${selectedKandang?.name}) belum ada, mohon isi terlebih dahulu di bagian Persediaan!`}
secondaryButton={undefined}
primaryButton={{
text: 'Ya',
color: 'info',
onClick: () => {
alertModal.closeModal();
},
}}
/>
</>
)}
</>
);
};
export default AddChickin;
@@ -0,0 +1,11 @@
import SuspenseHelper from '@/components/helper/SuspenseHelper';
const Layout = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
return <SuspenseHelper>{children}</SuspenseHelper>;
};
export default Layout;
+351
View File
@@ -0,0 +1,351 @@
'use client';
import Button from '@/components/Button';
import Card from '@/components/Card';
import Modal, { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
import ChickinForm from '@/components/pages/production/chickin/form/ChickinForm';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { ChickinApi } from '@/services/api/production';
import { BaseApiResponse } from '@/types/api/api-general';
import {
Chickin,
ChickinApprovalPayload,
} from '@/types/api/production/chickin';
import { Icon } from '@iconify/react';
import { useRouter, useSearchParams } from 'next/navigation';
import { useState } from 'react';
import toast from 'react-hot-toast';
import useSWR from 'swr';
/**
* TODO: Refactor code - pindahin detail ke reuseable component
* setelah implement approval and reject
*/
const DetailChickin = () => {
const router = useRouter();
const searchParams = useSearchParams();
const chickinId = searchParams.get('chickinId');
const [isApproveLoading, setIsApproveLoading] = useState(false);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const confirmModal = useModal();
const deleteModal = useModal();
const chickinModal = useModal();
const {
data: chickin,
isLoading,
mutate: refreshChickin,
} = useSWR(chickinId, (id: number) => ChickinApi.getSingle(id));
const [isApprovedDisabled, setIsApprovedDisabled] = useState(
// chickin.data?.approval.step_number == 1 ? false : true
true
);
const [isRejectedDisabled, setIsRejectedDisabled] =
useState(!isApprovedDisabled);
const [approvalAction, setApprovalAction] = useState<'APPROVED' | 'REJECTED'>(
!isApprovedDisabled ? 'APPROVED' : 'REJECTED'
);
if (!chickinId) {
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 && (!chickin || isResponseError(chickin))) {
router.replace('/404');
return;
}
if (!isResponseSuccess(chickin)) {
return (
<div className='w-full flex flex-row justify-center items-center p-4'>
<span className='loading loading-spinner loading-xl' />
</div>
);
}
const confirmationModalClickHandler = async ({
action = 'APPROVED',
}: {
action: 'APPROVED' | 'REJECTED';
}) => {
if (chickin?.data.id === undefined) return;
setIsApproveLoading(true);
const approveChickinRes = await ChickinApi.customRequest<
BaseApiResponse<Chickin>,
ChickinApprovalPayload
>(`/approvals`, {
method: 'POST',
payload: {
action: action,
approvable_ids: [chickin.data.id],
},
});
if (isResponseSuccess(approveChickinRes)) {
if (refreshChickin) {
await refreshChickin();
}
toast.success(approveChickinRes.message as string);
}
if (isResponseError(approveChickinRes)) {
toast.error(approveChickinRes?.message as string);
}
confirmModal.closeModal();
setIsApproveLoading(false);
};
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
const deleteProjectFlockRes = await ChickinApi.delete(
chickin.data?.id as number
);
if (isResponseSuccess(deleteProjectFlockRes)) {
toast.success(deleteProjectFlockRes?.message as string);
router.push('/production/chickin');
}
if (isResponseError(deleteProjectFlockRes)) {
toast.error(deleteProjectFlockRes?.message as string);
}
deleteModal.closeModal();
setIsDeleteLoading(false);
};
return (
<>
<div className='w-full p-4 flex flex-col justify-center gap-4'>
{isLoading && <span className='loading loading-spinner loading-xl' />}
{!isLoading && isResponseSuccess(chickin) && (
<>
{/* <div className='w-full flex flex-col sm:flex-row gap-2'>
<Button
variant='outline'
color='success'
onClick={(() => {
if (chickin?.data.id) {
setApprovalAction('APPROVED');
confirmModal.openModal();
}
})}
disabled={!chickin?.data.id || isApprovedDisabled}
className='w-full sm:w-fit'
>
<Icon icon='material-symbols:check' width={24} height={24} />
Approve
</Button>
<Button
variant='outline'
color='error'
onClick={() => {
if (chickin?.data.id) {
setApprovalAction('REJECTED');
confirmModal.openModal();
}
}}
disabled={!chickin?.data.id || isRejectedDisabled}
className='w-full sm:w-fit'
>
<Icon icon='mdi:times' width={24} height={24} />
Reject
</Button>
</div> */}
<Card
title='Informasi Umum'
variant='bordered'
className={{
wrapper: 'w-full',
}}
>
<div className='grid grid-cols-2 gap-4 mt-4'>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Flock</div>
<div className='text-sm'>
{
chickin.data.project_flock_kandang?.project_flock.flock
.name
}
</div>
</div>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Area</div>
<div className='text-sm'>
{
chickin.data.project_flock_kandang?.project_flock.area
.name
}
</div>
</div>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Kategori</div>
<div className='text-sm'>
{chickin.data.project_flock_kandang?.project_flock.category}
</div>
</div>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Lokasi</div>
<div className='text-sm'>
{
chickin.data.project_flock_kandang?.project_flock.location
.name
}
</div>
</div>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Periode</div>
<div className='text-sm'>
{chickin.data.project_flock_kandang?.project_flock.period}
</div>
</div>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Kandang</div>
<div className='text-sm'>
{chickin.data.project_flock_kandang?.kandang.name}
</div>
</div>
</div>
</Card>
<Card
title='Detail Chickin'
variant='bordered'
className={{
wrapper: 'w-full',
}}
>
<div className='grid grid-cols-2 gap-4 mt-4'>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Flock Kandang</div>
<div className='text-sm'>
{
chickin.data.project_flock_kandang?.project_flock.flock
.name
}{' '}
- {chickin.data.project_flock_kandang?.kandang.name}
</div>
</div>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Tanggal Chickin</div>
<div className='text-sm'>
{chickin.data.chick_in_date
? new Date(chickin.data.chick_in_date).toLocaleDateString(
'id-ID'
)
: '-'}
</div>
</div>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Jumlah (Ekor)</div>
<div className='text-sm'>
{chickin.data.quantity?.toLocaleString('id-ID')}
</div>
</div>
<div className='flex flex-col gap-2'>
<div className='font-semibold text-sm'>Catatan</div>
<div className='text-sm'>{chickin.data.note}</div>
</div>
</div>
</Card>
<div className='w-full flex flex-col sm:flex-row gap-2'>
<Button
color='error'
onClick={() => {
deleteModal.openModal();
}}
>
<Icon icon='mdi:times' width={24} height={24} />
Delete
</Button>
<Button
color='warning'
onClick={() => {
chickinModal.openModal();
}}
>
<Icon icon='mdi:pencil-outline' width={24} height={24} />
Edit
</Button>
</div>
</>
)}
</div>
<ConfirmationModal
ref={deleteModal.ref}
type='error'
text={`Apakah anda yakin ingin menghapus data Project Flock ini (${chickin?.data.project_flock_kandang?.project_flock.flock.name} - ${chickin?.data.project_flock_kandang?.kandang.name})?`}
secondaryButton={{
text: 'Tidak',
}}
primaryButton={{
text: 'Ya',
color: 'error',
isLoading: isDeleteLoading,
onClick: confirmationModalDeleteClickHandler,
}}
/>
<Modal ref={chickinModal.ref}>
<div className='flex flex-row justify-between items-center'>
<h1 className='text-xl font-semibold text-center mb-6'>
Chickin Kandang -{' '}
{chickin?.data?.project_flock_kandang &&
chickin?.data?.project_flock_kandang.kandang?.name}
</h1>
<Button
color='error'
variant='link'
onClick={chickinModal.closeModal}
>
<Icon
className='text-black'
icon='uil:times'
width={24}
height={24}
/>
</Button>
</div>
<ChickinForm
initialValues={chickin?.data}
formType='edit'
afterSubmit={() => {
refreshChickin();
chickinModal.closeModal();
}}
/>
</Modal>
<ConfirmationModal
ref={confirmModal.ref}
type={approvalAction == 'APPROVED' ? 'success' : 'error'}
text={`Apakah anda yakin ingin ${
approvalAction == 'APPROVED' ? 'approve' : 'reject'
} chickin berikut? (${
chickin?.data.project_flock_kandang?.project_flock.flock.name
} - ${chickin?.data.project_flock_kandang?.kandang.name})?`}
secondaryButton={{
text: 'Tidak',
}}
primaryButton={{
text: 'Ya',
color: approvalAction == 'APPROVED' ? 'success' : 'error',
isLoading: isApproveLoading,
onClick: () => {
confirmationModalClickHandler({
action: approvalAction,
});
},
}}
/>
</>
);
};
export default DetailChickin;
+10
View File
@@ -0,0 +1,10 @@
import ChickinTable from '@/components/pages/production/chickin/ChickinTable';
const Chickin = () => {
return (
<section className='w-full p-4'>
<ChickinTable />
</section>
);
};
export default Chickin;
@@ -0,0 +1,13 @@
'use client';
import ProjectFlockForm from '@/components/pages/production/project-flock/form/ProjectFlockForm';
const AddProjectFlock = () => {
return (
<section className='w-full p-4 flex flex-row justify-center'>
<ProjectFlockForm formType='add' />
</section>
);
};
export default AddProjectFlock;

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