Compare commits
235 Commits
736e3bef18
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5bc322170 | ||
|
|
749208ac97 | ||
|
|
1870583441 | ||
|
|
76c05ebe7c | ||
|
|
515731003c | ||
|
|
a9c7ec6b80 | ||
|
|
4038d47582 | ||
|
|
326987d6de | ||
|
|
f433fc3e41 | ||
|
|
5361c00e7b | ||
|
|
5e37bd1a76 | ||
|
|
5a53b90272 | ||
|
|
59548a486f | ||
|
|
c0bfe974ad | ||
|
|
895c5f6226 | ||
|
|
88d84ac457 | ||
|
|
94ad59ce24 | ||
|
|
b1630ea623 | ||
|
|
6a700fbd4b | ||
|
|
8e548126b2 | ||
|
|
2ec9b28a60 | ||
|
|
4fc242bc7d | ||
|
|
6df3a27383 | ||
|
|
7111b1db09 | ||
|
|
c4ee279d91 | ||
|
|
14c4ea5791 | ||
|
|
01a0aa8ca1 | ||
|
|
97fea41b62 | ||
|
|
5568d32a31 | ||
| 4e78ff77cc | |||
| 4c0917e6ba | |||
| c56e3383d1 | |||
| 967501d58f | |||
| 88fdc3aa7f | |||
| 183916a62a | |||
| a9490e132d | |||
| 438e5a3f43 | |||
| cbd469c97f | |||
| bc45f2756e | |||
| 73448548e7 | |||
| f0e9767e78 | |||
| 0e39450849 | |||
| 4c83d41eb0 | |||
| bccf52a8fb | |||
| 6e03c4d218 | |||
| 53f8c893ca | |||
| 52d070f4e5 | |||
| 209f3899b5 | |||
| 58d6ef0a9a | |||
| 1a0756fdca | |||
| f506972c91 | |||
| 19abe08a90 | |||
| 6428c9e20c | |||
| 9d66f21854 | |||
| da5bb6e99b | |||
| 680d5d4130 | |||
| f73a510984 | |||
| 4b7c3da3d4 | |||
| b0877399eb | |||
| 3b5b7f10c4 | |||
| 45e95725cd | |||
| a98a41efab | |||
| 3911e8e21a | |||
| dc871f36d4 | |||
| 2dd06d0e4f | |||
| a9e5f7ece8 | |||
| 7e7d583973 | |||
| ba6d703893 | |||
| 2bb9ec2ae2 | |||
| 1d67616cdb | |||
| 5a37d56cfb | |||
| c1b3a58c3a | |||
| c94ac5d12d | |||
| c24f7cbac6 | |||
| 8637c22ed7 | |||
| 2659aae278 | |||
| 038b5ea2fb | |||
| 54e11dcbb4 | |||
| 3ea35f6bca | |||
| b67fd61bf8 | |||
| 816a6c2f60 | |||
| 294ec0144d | |||
| c2e9198dbc | |||
| 074fe44ab3 | |||
| 31ab39b21c | |||
| 7bdd5243bd | |||
| 0da1efe5c3 | |||
| 8c24f00382 | |||
| 60f7efd6ba | |||
| c16bb98ed3 | |||
| 0779e4b9f6 | |||
| 9be16228f7 | |||
| 84f551ddc6 | |||
| 96415c2bc1 | |||
| 8c33cc6645 | |||
| cc3a9cd854 | |||
| 65a47e8028 | |||
| 310590010c | |||
| 84c4a584a0 | |||
| 1f31b020e8 | |||
| 10a08d5f45 | |||
| 504ddfbf8d | |||
| 516c17326c | |||
| e9f95b7ca8 | |||
| e79d77625f | |||
| 3953ee93b9 | |||
| b728a374a5 | |||
| 3369e97a3c | |||
| 5f2760713f | |||
| 09c0bec901 | |||
| 38b9908e1e | |||
| 870aba0bcf | |||
| c147f47876 | |||
| 6c38642af8 | |||
| fadda1f0d2 | |||
| 7119ae4cb7 | |||
| af0f24a6b6 | |||
| 711b5373da | |||
| e9e9f7dbd5 | |||
| 2df920af47 | |||
| 9c799ac105 | |||
| 44f00a8f5d | |||
| 8c1b128df2 | |||
| 3916f7f8ea | |||
| 074e07a04a | |||
| bdcb4811c4 | |||
| fa304450cb | |||
| ed95be1d39 | |||
| eb79c6db49 | |||
| 0f5d1098a0 | |||
| 96c8f860da | |||
| af2687cefc | |||
| de63b29a45 | |||
| e8595117ee | |||
| 92b067b939 | |||
| 94badf95b8 | |||
| 7f394b90fa | |||
| 45fbde31c7 | |||
| e27aa026fd | |||
| 13ad714b22 | |||
| 386e74374b | |||
| 910a7dd1b2 | |||
| 90b5a6bd6f | |||
| f8cf227f1d | |||
| 475cc9f30d | |||
| eaa8ecf1d4 | |||
| da6c5134fb | |||
| e0ceeeb73d | |||
| 4368fe1e4f | |||
| 10aa4095af | |||
| 968d37c67b | |||
| 3f21f55c39 | |||
| 80973d5b85 | |||
| b80651519f | |||
| 21bd0c0a68 | |||
| b9007a59a6 | |||
| 6f1de4531e | |||
| 8078242cf9 | |||
| feb2928cb4 | |||
| e61f5d315e | |||
| b858e02bf3 | |||
| 1873486d13 | |||
| 5d3ea6d787 | |||
| 834527647d | |||
| 11f99caf42 | |||
| 68d544b9c3 | |||
| b0038d3e94 | |||
| 64dc80e069 | |||
| 9ba3a6e623 | |||
| 61f45de617 | |||
| da24ea062e | |||
| fe21695e4e | |||
| 5b03a9be19 | |||
| 1499fc531d | |||
| 3fe38d5e26 | |||
| cadda739f8 | |||
| 1260462ede | |||
| 5b572bb732 | |||
| 75a7880d67 | |||
| 74a8556ba8 | |||
| 40d7d39ba6 | |||
| 9b43666caf | |||
| 6ef6ed128a | |||
| f537e9526b | |||
| 144ecd94fe | |||
| 02b555d7ce | |||
| 75dfed138a | |||
| 2b88bd80be | |||
| 72d2a4b1f5 | |||
| 4a24ee61ff | |||
| 1e9bad12c5 | |||
| 6bdc820589 | |||
| 90c3ea3fff | |||
| 5edcde1e4c | |||
| 3409849fa3 | |||
| ece23e01f2 | |||
| 989334db0a | |||
| e68789e467 | |||
| 2c323cf1de | |||
| 0833b7ff8f | |||
| 0d3dd8cca2 | |||
| cd5570f431 | |||
| d36ddcb2b2 | |||
| e24ad8deb0 | |||
| 6157902274 | |||
| 8f1e941d09 | |||
| acadd8c9a4 | |||
| 79c4bb0c24 | |||
| 74f04f44c1 | |||
| b0384112ea | |||
| 4b5e2a9f94 | |||
| bf5d8f6d05 | |||
| 0f6265ed15 | |||
| 2c44d4e273 | |||
| cfbb37e1af | |||
| efba12697a | |||
| 1b8b1ad9f1 | |||
| 7488171a11 | |||
| 918663c758 | |||
| a96f4fc8c8 | |||
| 01a7b01435 | |||
| 73d12068d8 | |||
| dcd80571bf | |||
| a07bcd3a5b | |||
| e19372eed1 | |||
| 58725db7ea | |||
| aff57eb574 | |||
| 47c81932fd | |||
| 02d94e193e | |||
| 02188c46fd | |||
| 1c9e9c3bed | |||
| 9e19abb2d9 | |||
| ff98b708b5 | |||
| d8c340028c | |||
| 85df3ec412 |
@@ -1,275 +0,0 @@
|
||||
### DB architecture guidelines
|
||||
|
||||
#### Overview
|
||||
|
||||
...
|
||||
|
||||
#### Core Concepts
|
||||
|
||||
- ....
|
||||
|
||||
#### User table
|
||||
- # Model App\Models\User
|
||||
- # Migrations database/migrations/0001_01_01_000000_create_users_table.php
|
||||
- # Seeder database/seeders/UsersTableSeeder.php
|
||||
...
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- username
|
||||
- first_name
|
||||
- last_name
|
||||
- phone
|
||||
- phone_verified_at
|
||||
- locale
|
||||
- password_must_be_changed
|
||||
- options
|
||||
- email_verified_at
|
||||
- remember_token
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- username (unique)
|
||||
- phone (unique)
|
||||
- email (unique)
|
||||
- email_verified_at
|
||||
- remember_token
|
||||
|
||||
##### Relations
|
||||
- roles (Role model)
|
||||
|
||||
|
||||
|
||||
#### Branch table
|
||||
- # Model App\Modules\Branch\Models\Branch
|
||||
- # Migrations app/Modules/Branch/Database/Migrations/2025_10_09_190439_create_branches_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- unique_code
|
||||
- name (json)
|
||||
- address (json)
|
||||
- region (string)[in: ag, mr, ah, ak, dz, bn, lb]
|
||||
- province_id
|
||||
- phone_numbers (json)
|
||||
- billing_username
|
||||
- billing_password
|
||||
- billing_swift_username
|
||||
- billing_swift_password
|
||||
- billing_visa_master_username
|
||||
- billing_visa_master_password
|
||||
- billing_sber_username
|
||||
- billing_sber_password
|
||||
- active
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- unique_code (unique)
|
||||
- region
|
||||
|
||||
##### Relations
|
||||
- province (Province model)
|
||||
- users (User model)
|
||||
|
||||
#### Province table
|
||||
- # Model App\Modules\Province\Models\Province
|
||||
- # Migrations app/Modules/Province/Database/Migrations/2025_10_09_185951_create_provinces_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- region
|
||||
- name (json)
|
||||
- active
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- None
|
||||
|
||||
##### Relations
|
||||
- None
|
||||
|
||||
#### LoanOrderRequiredDocs table
|
||||
- # Model App\Modules\LoanOrder\Models\LoanOrderRequiredDocs
|
||||
- # Migrations app/Modules/LoanOrder/Database/Migrations/2025_10_09_211513_create_loan_order_required_docs_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- name (text)
|
||||
- value (text)
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- None
|
||||
|
||||
##### Relations
|
||||
- loanOrders (LoanOrder model)
|
||||
|
||||
#### LoanType table
|
||||
- # Model App\Modules\LoanOrder\Models\LoanType
|
||||
- # Migrations app/Modules/LoanOrder/Database/Migrations/2025_10_09_183412_create_loan_types_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- name (json)
|
||||
- tax
|
||||
- maturity
|
||||
- notes
|
||||
- active
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- None
|
||||
|
||||
##### Relations
|
||||
- None
|
||||
|
||||
#### LoanOrder table
|
||||
- # Model App\Modules\LoanOrder\Models\LoanOrder
|
||||
- # Migrations app/Modules/LoanOrder/Database/Migrations/2025_10_09_220443_create_loan_orders_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- unique_id
|
||||
- source
|
||||
- user_id
|
||||
- loan_type
|
||||
- region
|
||||
- branch_id
|
||||
- customer_name
|
||||
- customer_surname
|
||||
- customer_patronic_name
|
||||
- passport_address
|
||||
- real_address
|
||||
- passport_serie
|
||||
- passport_id
|
||||
- passport_given_at
|
||||
- passport_given_by
|
||||
- born_place
|
||||
- born_at
|
||||
- email
|
||||
- phone
|
||||
- phone_additional
|
||||
- phone_home
|
||||
- work_region
|
||||
- work_province_id
|
||||
- work_company
|
||||
- work_company_accountant_number
|
||||
- work_started_at
|
||||
- work_salary
|
||||
- work_position
|
||||
- education
|
||||
- marriage_status
|
||||
- passport_one (text)
|
||||
- passport_two (text)
|
||||
- passport_three (text)
|
||||
- passport_four (text)
|
||||
- loan_amount
|
||||
- card_number
|
||||
- card_name
|
||||
- card_month
|
||||
- card_year
|
||||
- guarantor_name
|
||||
- guarantor_surname
|
||||
- guarantor_patronic_name
|
||||
- guarantor_passport_serie
|
||||
- guarantor_passport_id
|
||||
- guarantor_card_number
|
||||
- guarantor_card_name
|
||||
- guarantor_card_month
|
||||
- guarantor_card_year
|
||||
- guarantor_note
|
||||
- guarantor_2_name
|
||||
- guarantor_2_surname
|
||||
- guarantor_2_patronic_name
|
||||
- guarantor_2_passport_serie
|
||||
- guarantor_2_passport_id
|
||||
- guarantor_2_card_number
|
||||
- guarantor_2_card_name
|
||||
- guarantor_2_card_month
|
||||
- guarantor_2_card_year
|
||||
- guarantor_2_note
|
||||
- loan_card_number
|
||||
- loan_card_name
|
||||
- loan_card_month
|
||||
- loan_card_year
|
||||
- loan_order_required_doc_id
|
||||
- status
|
||||
- satisfiable
|
||||
- notes (text)
|
||||
- created_at
|
||||
- updated_at
|
||||
- deleted_at
|
||||
|
||||
##### Indexes
|
||||
- unique_id (unique)
|
||||
- source
|
||||
- customer_name
|
||||
- customer_surname
|
||||
- passport_serie
|
||||
- passport_id
|
||||
- phone
|
||||
- work_region
|
||||
- loan_amount
|
||||
|
||||
##### Relations
|
||||
- loanType (LoanType model)
|
||||
- branch (Branch model)
|
||||
- workProvince (Province model)
|
||||
- user (User model)
|
||||
- requiredDocs (LoanOrderRequiredDocs model)
|
||||
|
||||
#### OtpVerification table
|
||||
- # Model App\Modules\OtpVerification\Models\OtpVerification
|
||||
- # Migrations app/Modules/OtpVerification/Database/Migrations/2025_09_22_164249_create_otp_verifications_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- username
|
||||
- code
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- None
|
||||
|
||||
##### Relations
|
||||
- None
|
||||
|
||||
#### AuthEvent table
|
||||
- # Model App\Modules\BaseAuth\Models\AuthEvent
|
||||
- # Migrations app/Modules/BaseAuth/Database/Migrations/2025_10_07_181725_create_auth_events_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- name
|
||||
- request_method
|
||||
- ip
|
||||
- user_agent
|
||||
- target_url
|
||||
- options (json)
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- name
|
||||
- request_method
|
||||
- ip
|
||||
- user_agent
|
||||
- target_url
|
||||
|
||||
##### Relations
|
||||
- None
|
||||
|
||||
|
||||
@@ -643,279 +643,4 @@ Use the global helper functions to interact with modules throughout the applicat
|
||||
```php
|
||||
$path = modules_path('Invoice/Database'); // app/Modules/Invoice/Database
|
||||
```
|
||||
|
||||
|
||||
=== .ai/db-architecture rules ===
|
||||
|
||||
### DB architecture guidelines
|
||||
|
||||
#### Overview
|
||||
|
||||
...
|
||||
|
||||
#### Core Concepts
|
||||
|
||||
- ....
|
||||
|
||||
#### User table
|
||||
- # Model App\Models\User
|
||||
- # Migrations database/migrations/0001_01_01_000000_create_users_table.php
|
||||
- # Seeder database/seeders/UsersTableSeeder.php
|
||||
...
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- username
|
||||
- first_name
|
||||
- last_name
|
||||
- phone
|
||||
- phone_verified_at
|
||||
- locale
|
||||
- password_must_be_changed
|
||||
- options
|
||||
- email_verified_at
|
||||
- remember_token
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- username (unique)
|
||||
- phone (unique)
|
||||
- email (unique)
|
||||
- email_verified_at
|
||||
- remember_token
|
||||
|
||||
##### Relations
|
||||
- roles (Role model)
|
||||
|
||||
#### Branch table
|
||||
- # Model App\Modules\Branch\Models\Branch
|
||||
- # Migrations app/Modules/Branch/Database/Migrations/2025_10_09_190439_create_branches_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- unique_code
|
||||
- name (json)
|
||||
- address (json)
|
||||
- region (string)[in: ag, mr, ah, ak, dz, bn, lb]
|
||||
- province_id
|
||||
- phone_numbers (json)
|
||||
- billing_username
|
||||
- billing_password
|
||||
- billing_swift_username
|
||||
- billing_swift_password
|
||||
- billing_visa_master_username
|
||||
- billing_visa_master_password
|
||||
- billing_sber_username
|
||||
- billing_sber_password
|
||||
- active
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- unique_code (unique)
|
||||
- region
|
||||
|
||||
##### Relations
|
||||
- province (Province model)
|
||||
- users (User model)
|
||||
|
||||
#### Province table
|
||||
- # Model App\Modules\Province\Models\Province
|
||||
- # Migrations app/Modules/Province/Database/Migrations/2025_10_09_185951_create_provinces_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- region
|
||||
- name (json)
|
||||
- active
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- None
|
||||
|
||||
##### Relations
|
||||
- None
|
||||
|
||||
#### LoanOrderRequiredDocs table
|
||||
- # Model App\Modules\LoanOrder\Models\LoanOrderRequiredDocs
|
||||
- # Migrations app/Modules/LoanOrder/Database/Migrations/2025_10_09_211513_create_loan_order_required_docs_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- name (text)
|
||||
- value (text)
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- None
|
||||
|
||||
##### Relations
|
||||
- loanOrders (LoanOrder model)
|
||||
|
||||
#### LoanType table
|
||||
- # Model App\Modules\LoanOrder\Models\LoanType
|
||||
- # Migrations app/Modules/LoanOrder/Database/Migrations/2025_10_09_183412_create_loan_types_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- name (json)
|
||||
- tax
|
||||
- maturity
|
||||
- notes
|
||||
- active
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- None
|
||||
|
||||
##### Relations
|
||||
- None
|
||||
|
||||
#### LoanOrder table
|
||||
- # Model App\Modules\LoanOrder\Models\LoanOrder
|
||||
- # Migrations app/Modules/LoanOrder/Database/Migrations/2025_10_09_220443_create_loan_orders_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- unique_id
|
||||
- source
|
||||
- user_id
|
||||
- loan_type
|
||||
- region
|
||||
- branch_id
|
||||
- customer_name
|
||||
- customer_surname
|
||||
- customer_patronic_name
|
||||
- passport_address
|
||||
- real_address
|
||||
- passport_serie
|
||||
- passport_id
|
||||
- passport_given_at
|
||||
- passport_given_by
|
||||
- born_place
|
||||
- born_at
|
||||
- email
|
||||
- phone
|
||||
- phone_additional
|
||||
- phone_home
|
||||
- work_region
|
||||
- work_province_id
|
||||
- work_company
|
||||
- work_company_accountant_number
|
||||
- work_started_at
|
||||
- work_salary
|
||||
- work_position
|
||||
- education
|
||||
- marriage_status
|
||||
- passport_one (text)
|
||||
- passport_two (text)
|
||||
- passport_three (text)
|
||||
- passport_four (text)
|
||||
- loan_amount
|
||||
- card_number
|
||||
- card_name
|
||||
- card_month
|
||||
- card_year
|
||||
- guarantor_name
|
||||
- guarantor_surname
|
||||
- guarantor_patronic_name
|
||||
- guarantor_passport_serie
|
||||
- guarantor_passport_id
|
||||
- guarantor_card_number
|
||||
- guarantor_card_name
|
||||
- guarantor_card_month
|
||||
- guarantor_card_year
|
||||
- guarantor_note
|
||||
- guarantor_2_name
|
||||
- guarantor_2_surname
|
||||
- guarantor_2_patronic_name
|
||||
- guarantor_2_passport_serie
|
||||
- guarantor_2_passport_id
|
||||
- guarantor_2_card_number
|
||||
- guarantor_2_card_name
|
||||
- guarantor_2_card_month
|
||||
- guarantor_2_card_year
|
||||
- guarantor_2_note
|
||||
- loan_card_number
|
||||
- loan_card_name
|
||||
- loan_card_month
|
||||
- loan_card_year
|
||||
- loan_order_required_doc_id
|
||||
- status
|
||||
- satisfiable
|
||||
- notes (text)
|
||||
- created_at
|
||||
- updated_at
|
||||
- deleted_at
|
||||
|
||||
##### Indexes
|
||||
- unique_id (unique)
|
||||
- source
|
||||
- customer_name
|
||||
- customer_surname
|
||||
- passport_serie
|
||||
- passport_id
|
||||
- phone
|
||||
- work_region
|
||||
- loan_amount
|
||||
|
||||
##### Relations
|
||||
- loanType (LoanType model)
|
||||
- branch (Branch model)
|
||||
- workProvince (Province model)
|
||||
- user (User model)
|
||||
- requiredDocs (LoanOrderRequiredDocs model)
|
||||
|
||||
#### OtpVerification table
|
||||
- # Model App\Modules\OtpVerification\Models\OtpVerification
|
||||
- # Migrations app/Modules/OtpVerification/Database/Migrations/2025_09_22_164249_create_otp_verifications_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- username
|
||||
- code
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- None
|
||||
|
||||
##### Relations
|
||||
- None
|
||||
|
||||
#### AuthEvent table
|
||||
- # Model App\Modules\BaseAuth\Models\AuthEvent
|
||||
- # Migrations app/Modules/BaseAuth/Database/Migrations/2025_10_07_181725_create_auth_events_table.php
|
||||
- # Seeder Not found
|
||||
|
||||
##### Structure
|
||||
- id
|
||||
- name
|
||||
- request_method
|
||||
- ip
|
||||
- user_agent
|
||||
- target_url
|
||||
- options (json)
|
||||
- created_at
|
||||
- updated_at
|
||||
|
||||
##### Indexes
|
||||
- name
|
||||
- request_method
|
||||
- ip
|
||||
- user_agent
|
||||
- target_url
|
||||
|
||||
##### Relations
|
||||
- None
|
||||
</laravel-boost-guidelines>
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,9 +11,9 @@
|
||||
/.phpunit.cache
|
||||
/.vscode
|
||||
/.zed
|
||||
/database/data/
|
||||
/auth.json
|
||||
/node_modules
|
||||
/public/build
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
|
||||
66
README.md
66
README.md
@@ -1,61 +1,11 @@
|
||||
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
|
||||
CREATE USER 'nurmuhammet'@'%' IDENTIFIED BY 'K}#zL9@}QkR>MAHMYTJ';
|
||||
GRANT ALL PRIVILEGES ON *.* TO 'nurmuhammet'@'%' WITH GRANT OPTION;
|
||||
CREATE USER 'nurmuhammet'@'localhost' IDENTIFIED BY 'K}#zL9@}QkR>MAHMYTJ';
|
||||
GRANT ALL PRIVILEGES ON *.* TO 'nurmuhammet'@'localhost' WITH GRANT OPTION;
|
||||
create database nurmuhammetsdb;
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
|
||||
</p>
|
||||
|
||||
## About Laravel
|
||||
ALTER USER ahat WITH PASSWORD 'K}#zL9@}QkR>MAHMYTJ';
|
||||
|
||||
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
|
||||
|
||||
- [Simple, fast routing engine](https://laravel.com/docs/routing).
|
||||
- [Powerful dependency injection container](https://laravel.com/docs/container).
|
||||
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
|
||||
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
|
||||
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
|
||||
- [Robust background job processing](https://laravel.com/docs/queues).
|
||||
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
|
||||
|
||||
Laravel is accessible, powerful, and provides tools required for large, robust applications.
|
||||
|
||||
## Learning Laravel
|
||||
|
||||
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
|
||||
|
||||
You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch.
|
||||
|
||||
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
|
||||
|
||||
## Laravel Sponsors
|
||||
|
||||
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com).
|
||||
|
||||
### Premium Partners
|
||||
|
||||
- **[Vehikl](https://vehikl.com)**
|
||||
- **[Tighten Co.](https://tighten.co)**
|
||||
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
|
||||
- **[64 Robots](https://64robots.com)**
|
||||
- **[Curotec](https://www.curotec.com/services/technologies/laravel)**
|
||||
- **[DevSquad](https://devsquad.com/hire-laravel-developers)**
|
||||
- **[Redberry](https://redberry.international/laravel-development)**
|
||||
- **[Active Logic](https://activelogic.com)**
|
||||
|
||||
## Contributing
|
||||
|
||||
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
|
||||
|
||||
## License
|
||||
|
||||
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
||||
SELECT setval('users_id_seq', (SELECT MAX(id) from users));
|
||||
SELECT nextval('users_id_seq');
|
||||
|
||||
85
app/Filament/Clusters/Cards/CardOrders/CardOrderResource.php
Normal file
85
app/Filament/Clusters/Cards/CardOrders/CardOrderResource.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\CardOrders;
|
||||
|
||||
use App\Filament\Clusters\Cards\CardOrders\Pages\CreateCardOrder;
|
||||
use App\Filament\Clusters\Cards\CardOrders\Pages\EditCardOrder;
|
||||
use App\Filament\Clusters\Cards\CardOrders\Pages\ListCardOrders;
|
||||
use App\Filament\Clusters\Cards\CardOrders\Schemas\CardOrderForm;
|
||||
use App\Filament\Clusters\Cards\CardOrders\Tables\CardOrdersTable;
|
||||
use App\Filament\Clusters\Cards\CardsCluster;
|
||||
use App\Modules\CardOrder\Models\CardOrder;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
|
||||
class CardOrderResource extends Resource
|
||||
{
|
||||
protected static ?int $navigationSort = 2;
|
||||
|
||||
protected static ?string $model = CardOrder::class;
|
||||
|
||||
protected static ?string $cluster = CardsCluster::class;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedDocumentPlus;
|
||||
|
||||
protected static string|BackedEnum|null $activeNavigationIcon = Heroicon::DocumentPlus;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'unique_id';
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('New card order');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Card order');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Card orders');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return CardOrderForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return CardOrdersTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListCardOrders::route('/'),
|
||||
'create' => CreateCardOrder::route('/create'),
|
||||
'edit' => EditCardOrder::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<\App\Modules\CardOrder\Models\CardOrder>
|
||||
*/
|
||||
public static function getRecordRouteBindingEloquentQuery(): Builder
|
||||
{
|
||||
return parent::getRecordRouteBindingEloquentQuery()
|
||||
->withoutGlobalScopes([
|
||||
SoftDeletingScope::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\CardOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\Cards\CardOrders\CardOrderResource;
|
||||
use App\Modules\CardOrder\Repositories\CardOrderRepository;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateCardOrder extends CreateRecord
|
||||
{
|
||||
protected static string $resource = CardOrderResource::class;
|
||||
|
||||
/**
|
||||
* @return array<int, \Filament\Actions\Action>
|
||||
*/
|
||||
protected function getFormActions(): array
|
||||
{
|
||||
return [
|
||||
$this->getCreateFormAction(),
|
||||
$this->getCancelFormAction(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getRedirectUrl(): string
|
||||
{
|
||||
$defaultUrl = string($this->getResource()::getUrl('index'));
|
||||
|
||||
/** @var \App\Modules\CardOrder\Models\CardOrder */
|
||||
$record = $this->record;
|
||||
|
||||
$onlinePayment = CardOrderRepository::make()
|
||||
->createOnlinePaymentOrder($record);
|
||||
|
||||
return $onlinePayment->successful()
|
||||
? $onlinePayment->paymentLink()
|
||||
: $defaultUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\CardOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\Cards\CardOrders\CardOrderResource;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\ForceDeleteAction;
|
||||
use Filament\Actions\RestoreAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditCardOrder extends EditRecord
|
||||
{
|
||||
protected static string $resource = CardOrderResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Action::make('save_top')
|
||||
->label(__('filament-panels::resources/pages/edit-record.form.actions.save.label'))
|
||||
->submit(null)
|
||||
->action('save'),
|
||||
|
||||
DeleteAction::make(),
|
||||
ForceDeleteAction::make(),
|
||||
RestoreAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\CardOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\Cards\CardOrders\CardOrderResource;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
|
||||
class ListCardOrders extends ListRecords
|
||||
{
|
||||
protected static string $resource = CardOrderResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getTabs(): array
|
||||
{
|
||||
if (! user()->isSystemUser()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach (array_keys(OrderStatusRepository::statusClasses()) as $status) {
|
||||
if ($status === '') {
|
||||
$data[null] = Tab::make(__('All'));
|
||||
} else {
|
||||
$data[$status] = Tab::make(OrderStatusRepository::statusFormatted($status))->query(fn ($query) => $query->where('status', $status));
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
262
app/Filament/Clusters/Cards/CardOrders/Schemas/CardOrderForm.php
Normal file
262
app/Filament/Clusters/Cards/CardOrders/Schemas/CardOrderForm.php
Normal file
@@ -0,0 +1,262 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\CardOrders\Schemas;
|
||||
|
||||
use App\Modules\Country\Repositories\CountryRepository;
|
||||
use App\Modules\FilamentPermission\Repositories\FilamentPermissionRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\PhoneNumberVerification\Rules\PhoneNumberVerificationRule;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use App\Modules\TurkmenPassport\Repositories\TurkmenPassportRepository;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Hidden;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Schemas\Components\Fieldset;
|
||||
use Filament\Schemas\Components\FusedGroup;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Components\Wizard;
|
||||
use Filament\Schemas\Components\Wizard\Step;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class CardOrderForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Hidden::make('user_id')->default(Auth::id()),
|
||||
|
||||
Section::make(__('New card order'))
|
||||
->columnSpan(4)
|
||||
->columns(4)
|
||||
->disabled(fn (string $context): bool => FilamentPermissionRepository::forClients())
|
||||
->hidden(fn (string $context) => FilamentPermissionRepository::defaultSystemInput($context))
|
||||
->components([
|
||||
Select::make('status')
|
||||
->label(__('Status'))
|
||||
->options(OrderStatusRepository::statusValues())
|
||||
->default(OrderStatusRepository::defaultStatus())
|
||||
->native(false)
|
||||
->columnSpan(2),
|
||||
|
||||
Toggle::make('paid')
|
||||
->label(__('Paid'))
|
||||
->inline(false)
|
||||
->disabled(true)
|
||||
->onIcon(Heroicon::CheckCircle)
|
||||
->offIcon(Heroicon::XCircle)
|
||||
->onColor('success')
|
||||
->offColor('danger'),
|
||||
|
||||
RichEditor::make('notes')
|
||||
->label(__('Bellik'))
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
|
||||
Wizard::make([
|
||||
Step::make(__('Loan & Bank'))
|
||||
->schema([
|
||||
Fieldset::make(__('Loan type and amount'))
|
||||
->schema([
|
||||
Select::make('card_state_id')
|
||||
->relationship('cardState', 'name', fn (Builder $query) => $query->orderByTranslation('name'))
|
||||
->label(__('Card state'))
|
||||
->native(false)
|
||||
->required(),
|
||||
|
||||
Select::make('card_type_id')
|
||||
->relationship('cardType', 'name', fn (Builder $query) => $query->orderByTranslation('name'))
|
||||
->label(__('Card type'))
|
||||
->native(false)
|
||||
->required(),
|
||||
]),
|
||||
|
||||
Fieldset::make(__('Location'))
|
||||
->schema([
|
||||
Select::make('region')
|
||||
->label(__('Region'))
|
||||
->options(RegionRepository::values())
|
||||
->live()
|
||||
->afterStateUpdated(fn (callable $set) => $set('branch_id', null))
|
||||
->required(),
|
||||
|
||||
Select::make('branch_id')
|
||||
->label(__('Branch'))
|
||||
->relationship('branch', 'name', function ($query, callable $get) {
|
||||
$query->orderByTranslation('name');
|
||||
|
||||
$region = $get('region');
|
||||
if ($region) {
|
||||
$query->where('region', $region);
|
||||
}
|
||||
})
|
||||
->required(),
|
||||
]),
|
||||
]),
|
||||
Step::make(__('Personal information'))
|
||||
->columns(8)
|
||||
->schema([
|
||||
TextInput::make('customer_name')
|
||||
->label(__('Name'))
|
||||
->columnSpan(2)
|
||||
->default(user()->first_name)
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->autocomplete(Str::random(10)),
|
||||
|
||||
TextInput::make('customer_surname')
|
||||
->label(__('Surname'))
|
||||
->columnSpan(2)
|
||||
->default(user()->last_name)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('customer_patronic_name')
|
||||
->label(__('Patronic name'))
|
||||
->columnSpan(2)
|
||||
->default(user()->getOption('patronic_name'))
|
||||
->maxLength(255),
|
||||
|
||||
DatePicker::make('born_at')
|
||||
->displayFormat('d.m.Y')
|
||||
->label(__('Birth date'))
|
||||
->native(false)
|
||||
->columnSpan(2)
|
||||
->default(user()->getOption('born_at'))
|
||||
->required()
|
||||
->beforeOrEqual('today'),
|
||||
|
||||
FusedGroup::make([
|
||||
Select::make('passport_serie')
|
||||
->label(__('Passport serie'))
|
||||
->options(TurkmenPassportRepository::values())
|
||||
->native(false)
|
||||
->required()
|
||||
->default(user()->getOption('passport_serie'))
|
||||
->columnSpan(1),
|
||||
|
||||
TextInput::make('passport_id')
|
||||
->label(__('Passport number'))
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->default(user()->getOption('passport_id'))
|
||||
->mask('999999'),
|
||||
])
|
||||
->columnSpan(3)
|
||||
->label(__('Passport serie and number'))
|
||||
->columns(2),
|
||||
|
||||
DatePicker::make('passport_given_at')
|
||||
->label(__('Passport given date'))
|
||||
->columnSpan(2)
|
||||
->displayFormat('d.m.Y')
|
||||
->native(false)
|
||||
->closeOnDateSelection()
|
||||
->default(user()->getOption('passport_given_at'))
|
||||
->beforeOrEqual('today')
|
||||
->required(),
|
||||
|
||||
TextInput::make('born_place')
|
||||
->columnSpan(3)
|
||||
->label(__('Born place (passport)'))
|
||||
->default(user()->getOption('born_place'))
|
||||
->maxLength(255)
|
||||
->required(),
|
||||
|
||||
TextInput::make('passport_given_by')
|
||||
->label(__('Passport given by'))
|
||||
->columnSpan(4)
|
||||
->default(user()->getOption('passport_given_by'))
|
||||
->maxLength(255)
|
||||
->required(),
|
||||
|
||||
TextInput::make('passport_address')
|
||||
->columnSpan(4)
|
||||
->label(__('Proscription for home'))
|
||||
->default(user()->getOption('passport_address'))
|
||||
->maxLength(255)
|
||||
->required(),
|
||||
|
||||
TextInput::make('real_address')
|
||||
->label(__('Current home address'))
|
||||
->columnSpan(4)
|
||||
->default(user()->getOption('real_address'))
|
||||
->maxLength(255)
|
||||
->required(),
|
||||
|
||||
TextInput::make('phone')
|
||||
->label(__('Phone'))
|
||||
->required()
|
||||
->mask('99 99 99 99')
|
||||
->prefix('+993')
|
||||
->default(user()->phone)
|
||||
->rules([
|
||||
new PhoneNumberVerificationRule,
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('phone_additional')
|
||||
->label(__('Additional phone'))
|
||||
->mask('99 99 99 99')
|
||||
->prefix('+993')
|
||||
->default(user()->getOption('phone_additional'))
|
||||
->rules([
|
||||
new PhoneNumberVerificationRule,
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('job_location')
|
||||
->label(__('Work location and your position'))
|
||||
->columnSpan(6)
|
||||
->required(),
|
||||
|
||||
Select::make('citizenship')
|
||||
->label(__('Citizenship'))
|
||||
->options(CountryRepository::values())
|
||||
->default('TM')
|
||||
->columnSpan(2)
|
||||
->required(),
|
||||
]),
|
||||
Step::make(__('Pasport files'))
|
||||
->columns(4)
|
||||
->schema([
|
||||
FileUpload::make('passport_one')
|
||||
->label(__('Passport (page 1)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
|
||||
FileUpload::make('passport_two')
|
||||
->label(__('Passport (page 2-3)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
|
||||
FileUpload::make('passport_three')
|
||||
->label(__('Passport (page 8-9)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
|
||||
FileUpload::make('passport_four')
|
||||
->label(__('Passport (page 32)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
])->columnSpan(4),
|
||||
])->columnSpanFull()->skippable(fn (string $context) => $context === 'edit'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\CardOrders\Tables;
|
||||
|
||||
use App\Modules\CardOrder\Filament\Actions\PayCardOrderAction;
|
||||
use App\Modules\CardOrder\Models\CardOrder;
|
||||
use App\Modules\DefaultQueryForResourceIndex\Repositories\DefaultQueryForResourceIndexRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Actions\ForceDeleteBulkAction;
|
||||
use Filament\Actions\RestoreBulkAction;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Filters\TrashedFilter;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class CardOrdersTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->modifyQueryUsing(function (Builder $query) {
|
||||
DefaultQueryForResourceIndexRepository::make($query);
|
||||
})
|
||||
->defaultSort('created_at', 'desc')
|
||||
->columns([
|
||||
TextColumn::make('unique_id')
|
||||
->label(__('ID'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('status')
|
||||
->label(__('Status'))
|
||||
->color(OrderStatusRepository::statusColorMatching())
|
||||
->formatStateUsing(fn (string $state) => OrderStatusRepository::statusFormatted($state))
|
||||
->badge()
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('cardState.name')
|
||||
->label(__('Reason'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('cardType.name')
|
||||
->label(__('Card type'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->label(__('Created At'))
|
||||
->dateTime()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('region')
|
||||
->label(__('Region'))
|
||||
->formatStateUsing(fn (string $state): string => RegionRepository::label($state))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('branch.name')
|
||||
->label(__('Branch'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('customer_name')
|
||||
->label(__('Name'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('customer_surname')
|
||||
->label(__('Surname'))
|
||||
->searchable(),
|
||||
|
||||
IconColumn::make('paid')
|
||||
->label(__('Paid'))
|
||||
->boolean(),
|
||||
|
||||
TextColumn::make('phone')
|
||||
->label(__('Phone'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('updated_at')
|
||||
->label(__('Updated At'))
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
TextColumn::make('deleted_at')
|
||||
->label(__('Deleted At'))
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
TrashedFilter::make(),
|
||||
])
|
||||
->recordActions([
|
||||
PayCardOrderAction::make()
|
||||
->hidden(fn (CardOrder $record) => $record->paid),
|
||||
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
ForceDeleteBulkAction::make(),
|
||||
RestoreBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
152
app/Filament/Clusters/Cards/Cards/CardResource.php
Normal file
152
app/Filament/Clusters/Cards/Cards/CardResource.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\Cards;
|
||||
|
||||
use App\Filament\Clusters\Cards\Cards\Pages\ManageCards;
|
||||
use App\Filament\Clusters\Cards\CardsCluster;
|
||||
use App\Modules\AppHelpers\Repositories\DateHelper;
|
||||
use App\Modules\Card\Filament\Actions\CheckCardBalanceAction;
|
||||
use App\Modules\Card\Filament\Actions\DownloadCardRequisteAction;
|
||||
use App\Modules\Card\Filament\Actions\DownloadCardTransactionAction;
|
||||
use App\Modules\Card\Models\Card;
|
||||
use BackedEnum;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Forms\Components\Hidden;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class CardResource extends Resource
|
||||
{
|
||||
protected static ?int $navigationSort = 1;
|
||||
|
||||
protected static ?string $model = Card::class;
|
||||
|
||||
protected static ?string $cluster = CardsCluster::class;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCreditCard;
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('My cards');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Card');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Cards');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->columns(3)
|
||||
->components([
|
||||
Hidden::make('user_id')
|
||||
->default(fn () => user()->id),
|
||||
|
||||
TextInput::make('number')
|
||||
->label(__('Card number'))
|
||||
->mask('9999 9999 9999 9999')
|
||||
->dehydrateStateUsing(fn ($state) => str_replace(' ', '', $state))
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
|
||||
Select::make('month')
|
||||
->label(__('Card month'))
|
||||
->options(DateHelper::staticNumberMonths())
|
||||
->native(false)
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
|
||||
Select::make('year')
|
||||
->label(__('Card year'))
|
||||
->options(DateHelper::staticNumberYears())
|
||||
->native(false)
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
|
||||
TextInput::make('name')
|
||||
->label(__('Card name'))
|
||||
->maxLength(255)
|
||||
->columnSpanFull()
|
||||
->required(),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->modifyQueryUsing(function (Builder $query) {
|
||||
if (user()->isAdmin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query->where('user_id', user()->id);
|
||||
})
|
||||
->columns([
|
||||
TextColumn::make('number')
|
||||
->label(__('Card number'))
|
||||
->formatStateUsing(fn ($state) => trim(chunk_split($state, 4, ' ')))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('name')
|
||||
->label(__('Card name'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('month')
|
||||
->label(__('Card month'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('year')
|
||||
->label(__('Card year'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->recordActions([
|
||||
CheckCardBalanceAction::make(),
|
||||
DownloadCardTransactionAction::make(),
|
||||
DownloadCardRequisteAction::make(),
|
||||
|
||||
EditAction::make()
|
||||
->label(''),
|
||||
DeleteAction::make()
|
||||
->label(''),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ManageCards::route('/'),
|
||||
];
|
||||
}
|
||||
}
|
||||
27
app/Filament/Clusters/Cards/Cards/Pages/ManageCards.php
Normal file
27
app/Filament/Clusters/Cards/Cards/Pages/ManageCards.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\Cards\Pages;
|
||||
|
||||
use App\Filament\Clusters\Cards\Cards\CardResource;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ManageRecords;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
|
||||
class ManageCards extends ManageRecords
|
||||
{
|
||||
protected static string $resource = CardResource::class;
|
||||
|
||||
public function getTitle(): string|Htmlable
|
||||
{
|
||||
return __('My cards');
|
||||
}
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make()
|
||||
->label(__('Add card'))
|
||||
->createAnother(false),
|
||||
];
|
||||
}
|
||||
}
|
||||
27
app/Filament/Clusters/Cards/CardsCluster.php
Normal file
27
app/Filament/Clusters/Cards/CardsCluster.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards;
|
||||
|
||||
use BackedEnum;
|
||||
use Filament\Clusters\Cluster;
|
||||
use Filament\Pages\Enums\SubNavigationPosition;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class CardsCluster extends Cluster
|
||||
{
|
||||
protected static ?int $navigationSort = 1;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCreditCard;
|
||||
|
||||
protected static ?SubNavigationPosition $subNavigationPosition = SubNavigationPosition::Top;
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('Cards');
|
||||
}
|
||||
|
||||
public static function getClusterBreadcrumb(): string
|
||||
{
|
||||
return __('Cards');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\Resources\CardPinOrders;
|
||||
|
||||
use App\Filament\Clusters\Cards\CardsCluster;
|
||||
use App\Filament\Clusters\Cards\Resources\CardPinOrders\Pages\CreateCardPinOrder;
|
||||
use App\Filament\Clusters\Cards\Resources\CardPinOrders\Pages\EditCardPinOrder;
|
||||
use App\Filament\Clusters\Cards\Resources\CardPinOrders\Pages\ListCardPinOrders;
|
||||
use App\Filament\Clusters\Cards\Resources\CardPinOrders\Schemas\CardPinOrderForm;
|
||||
use App\Filament\Clusters\Cards\Resources\CardPinOrders\Tables\CardPinOrdersTable;
|
||||
use App\Modules\CardPinOrder\Models\CardPinOrder;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class CardPinOrderResource extends Resource
|
||||
{
|
||||
protected static ?int $navigationSort = 3;
|
||||
|
||||
protected static ?string $model = CardPinOrder::class;
|
||||
|
||||
protected static ?string $cluster = CardsCluster::class;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCreditCard;
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('Forgot card pin');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Pin order');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Pin orders');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return CardPinOrderForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return CardPinOrdersTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListCardPinOrders::route('/'),
|
||||
'create' => CreateCardPinOrder::route('/create'),
|
||||
'edit' => EditCardPinOrder::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\Resources\CardPinOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\Cards\Resources\CardPinOrders\CardPinOrderResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateCardPinOrder extends CreateRecord
|
||||
{
|
||||
protected static string $resource = CardPinOrderResource::class;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\Resources\CardPinOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\Cards\Resources\CardPinOrders\CardPinOrderResource;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditCardPinOrder extends EditRecord
|
||||
{
|
||||
protected static string $resource = CardPinOrderResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\Resources\CardPinOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\Cards\Resources\CardPinOrders\CardPinOrderResource;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
|
||||
class ListCardPinOrders extends ListRecords
|
||||
{
|
||||
protected static string $resource = CardPinOrderResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getTabs(): array
|
||||
{
|
||||
if (! user()->isSystemUser()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach (array_keys(OrderStatusRepository::statusClasses()) as $status) {
|
||||
if ($status === '') {
|
||||
$data[null] = Tab::make(__('All'));
|
||||
} else {
|
||||
$data[$status] = Tab::make(OrderStatusRepository::statusFormatted($status))->query(fn ($query) => $query->where('status', $status));
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\Resources\CardPinOrders\Schemas;
|
||||
|
||||
use App\Modules\FilamentPermission\Repositories\FilamentPermissionRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\PhoneNumberVerification\Rules\PhoneNumberVerificationRule;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use App\Modules\TurkmenPassport\Repositories\TurkmenPassportRepository;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Hidden;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Components\FusedGroup;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Schema;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class CardPinOrderForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Hidden::make('user_id')->default(Auth::id()),
|
||||
|
||||
Section::make(__('New card pin order'))
|
||||
->columnSpanFull()
|
||||
->disabled(fn (string $context): bool => FilamentPermissionRepository::forClients())
|
||||
->hidden(fn (string $context) => FilamentPermissionRepository::defaultSystemInput($context))
|
||||
->components([
|
||||
Select::make('status')
|
||||
->label(__('Status'))
|
||||
->options(OrderStatusRepository::statusValues())
|
||||
->default(OrderStatusRepository::defaultStatus())
|
||||
->native(false)
|
||||
->required()
|
||||
->columnSpanFull(),
|
||||
|
||||
RichEditor::make('notes')
|
||||
->label(__('Bellik'))
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
|
||||
Section::make(__('New card pin order'))
|
||||
->columnSpanFull()
|
||||
->columns(6)
|
||||
->components([
|
||||
Select::make('card_type_id')
|
||||
->relationship('cardType', 'name', fn (Builder $query) => $query->orderByTranslation('name'))
|
||||
->label(__('Card type'))
|
||||
->native(false)
|
||||
->columnSpan(3)
|
||||
->required(),
|
||||
|
||||
TextInput::make('card_number')
|
||||
->label(__('Card number'))
|
||||
->mask('9999 9999 9999 9999')
|
||||
->maxLength(255)
|
||||
->columnSpan(3)
|
||||
->required(),
|
||||
|
||||
Select::make('region')
|
||||
->label(__('Region'))
|
||||
->options(RegionRepository::values())
|
||||
->live()
|
||||
->afterStateUpdated(fn (callable $set) => $set('branch_id', null))
|
||||
->columnSpan(3)
|
||||
->required(),
|
||||
|
||||
Select::make('branch_id')
|
||||
->label(__('Branch'))
|
||||
->relationship('branch', 'name', function ($query, callable $get) {
|
||||
$query->orderByTranslation('name');
|
||||
|
||||
$region = $get('region');
|
||||
if ($region) {
|
||||
$query->where('region', $region);
|
||||
}
|
||||
})
|
||||
->columnSpan(3)
|
||||
->required(),
|
||||
|
||||
TextInput::make('customer_name')
|
||||
->label(__('Name'))
|
||||
->columnSpan(2)
|
||||
->default(user()->first_name)
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->autocomplete(Str::random(10))
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('customer_surname')
|
||||
->label(__('Surname'))
|
||||
->columnSpan(2)
|
||||
->default(user()->last_name)
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('customer_patronic_name')
|
||||
->label(__('Patronic name'))
|
||||
->columnSpan(2)
|
||||
->default(user()->getOption('patronic_name'))
|
||||
->maxLength(255)
|
||||
->columnSpan(2),
|
||||
|
||||
DatePicker::make('born_at')
|
||||
->displayFormat('d.m.Y')
|
||||
->label(__('Birth date'))
|
||||
->native(false)
|
||||
->columnSpan(2)
|
||||
->default(user()->getOption('born_at'))
|
||||
->required()
|
||||
->beforeOrEqual('today')
|
||||
->columnSpan(2),
|
||||
|
||||
FusedGroup::make([
|
||||
Select::make('passport_serie')
|
||||
->label(__('Passport serie'))
|
||||
->options(TurkmenPassportRepository::values())
|
||||
->native(false)
|
||||
->required()
|
||||
->default(user()->getOption('passport_serie'))
|
||||
->columnSpan(1),
|
||||
|
||||
TextInput::make('passport_id')
|
||||
->label(__('Passport number'))
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->default(user()->getOption('passport_id'))
|
||||
->mask('999999'),
|
||||
])
|
||||
->columnSpan(2)
|
||||
->label(__('Passport serie and number'))
|
||||
->columns(2),
|
||||
|
||||
TextInput::make('phone')
|
||||
->label(__('Phone'))
|
||||
->required()
|
||||
->mask('99 99 99 99')
|
||||
->prefix('+993')
|
||||
->default(user()->phone)
|
||||
->rules([
|
||||
new PhoneNumberVerificationRule,
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
FileUpload::make('passport_one')
|
||||
->label(__('Passport (page 1)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(3),
|
||||
|
||||
FileUpload::make('passport_two')
|
||||
->label(__('Passport (page 2-3)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(3),
|
||||
|
||||
FileUpload::make('passport_three')
|
||||
->label(__('Passport (page 8-9)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(3),
|
||||
|
||||
FileUpload::make('passport_four')
|
||||
->label(__('Passport (page 32)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(3),
|
||||
]),
|
||||
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Cards\Resources\CardPinOrders\Tables;
|
||||
|
||||
use App\Modules\DefaultQueryForResourceIndex\Repositories\DefaultQueryForResourceIndexRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class CardPinOrdersTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->modifyQueryUsing(function (Builder $query) {
|
||||
DefaultQueryForResourceIndexRepository::make($query);
|
||||
})
|
||||
->defaultSort('created_at', 'desc')
|
||||
->columns([
|
||||
TextColumn::make('id')
|
||||
->label('ID'),
|
||||
|
||||
TextColumn::make('cardType.name')
|
||||
->label(__('Card type'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->label(__('Created At'))
|
||||
->dateTime()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('region')
|
||||
->label(__('Region'))
|
||||
->formatStateUsing(fn (string $state): string => RegionRepository::label($state))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('branch.name')
|
||||
->label(__('Branch'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('customer_name')
|
||||
->label(__('Name'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('customer_surname')
|
||||
->label(__('Surname'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('phone')
|
||||
->label(__('Phone'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('status')
|
||||
->label(__('Status'))
|
||||
->formatStateUsing(fn (string $state) => OrderStatusRepository::statusFormatted($state))
|
||||
->sortable()
|
||||
->badge()
|
||||
->searchable(),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,7 @@ namespace App\Filament\Clusters\Loans\LoanOrders;
|
||||
use App\Filament\Clusters\Loans\LoanOrders\Pages\CreateLoanOrder;
|
||||
use App\Filament\Clusters\Loans\LoanOrders\Pages\EditLoanOrder;
|
||||
use App\Filament\Clusters\Loans\LoanOrders\Pages\ListLoanOrders;
|
||||
use App\Filament\Clusters\Loans\LoanOrders\Pages\ViewLoanOrder;
|
||||
use App\Filament\Clusters\Loans\LoanOrders\Schemas\LoanOrderForm;
|
||||
use App\Filament\Clusters\Loans\LoanOrders\Schemas\LoanOrderInfolist;
|
||||
use App\Filament\Clusters\Loans\LoanOrders\Tables\LoanOrdersTable;
|
||||
use App\Filament\Clusters\Loans\LoansCluster;
|
||||
use App\Modules\LoanOrder\Models\LoanOrder;
|
||||
@@ -53,11 +51,6 @@ class LoanOrderResource extends Resource
|
||||
return LoanOrderForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function infolist(Schema $schema): Schema
|
||||
{
|
||||
return LoanOrderInfolist::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return LoanOrdersTable::configure($table);
|
||||
@@ -75,7 +68,6 @@ class LoanOrderResource extends Resource
|
||||
return [
|
||||
'index' => ListLoanOrders::route('/'),
|
||||
'create' => CreateLoanOrder::route('/create'),
|
||||
'view' => ViewLoanOrder::route('/{record}'),
|
||||
'edit' => EditLoanOrder::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use App\Filament\Clusters\Loans\LoanOrders\LoanOrderResource;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\ForceDeleteAction;
|
||||
use Filament\Actions\RestoreAction;
|
||||
use Filament\Actions\ViewAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditLoanOrder extends EditRecord
|
||||
@@ -16,7 +15,6 @@ class EditLoanOrder extends EditRecord
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
ViewAction::make(),
|
||||
DeleteAction::make(),
|
||||
ForceDeleteAction::make(),
|
||||
RestoreAction::make(),
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
namespace App\Filament\Clusters\Loans\LoanOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\Loans\LoanOrders\LoanOrderResource;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
|
||||
class ListLoanOrders extends ListRecords
|
||||
{
|
||||
@@ -16,4 +18,23 @@ class ListLoanOrders extends ListRecords
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getTabs(): array
|
||||
{
|
||||
if (! user()->isSystemUser()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach (array_keys(OrderStatusRepository::statusClasses()) as $status) {
|
||||
if ($status === '') {
|
||||
$data[null] = Tab::make(__('All'));
|
||||
} else {
|
||||
$data[$status] = Tab::make(OrderStatusRepository::statusFormatted($status))->query(fn ($query) => $query->where('status', $status));
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Filament\Clusters\Loans\LoanOrders\Schemas;
|
||||
|
||||
use App\Modules\FilamentPermission\Repositories\FilamentPermissionRepository;
|
||||
use App\Modules\LoanOrder\Models\LoanOrderRequiredDocs;
|
||||
use App\Modules\LoanOrder\Repositories\LoanOrderRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
@@ -22,6 +23,7 @@ use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Components\Wizard;
|
||||
use Filament\Schemas\Components\Wizard\Step;
|
||||
use Filament\Schemas\Schema;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
@@ -38,6 +40,8 @@ class LoanOrderForm
|
||||
Section::make(__('New loan order'))
|
||||
->columnSpan(4)
|
||||
->columns(4)
|
||||
->disabled(fn (string $context): bool => FilamentPermissionRepository::forClients())
|
||||
->hidden(fn (string $context) => FilamentPermissionRepository::defaultSystemInput($context))
|
||||
->components([
|
||||
Select::make('status')
|
||||
->label(__('Status'))
|
||||
@@ -84,13 +88,12 @@ class LoanOrderForm
|
||||
->schema([
|
||||
Select::make('loan_type')
|
||||
->label(__('Loan type'))
|
||||
->relationship('loanType', 'name')
|
||||
->relationship('loanType', 'name', fn (Builder $query) => $query->orderByTranslation('name'))
|
||||
->required(),
|
||||
|
||||
TextInput::make('loan_amount')
|
||||
->label(__('Loan amount'))
|
||||
->numeric()
|
||||
->required()
|
||||
->minValue(1)
|
||||
->maxValue(40000)
|
||||
->suffix('TMT')
|
||||
@@ -109,6 +112,8 @@ class LoanOrderForm
|
||||
Select::make('branch_id')
|
||||
->label(__('Branch'))
|
||||
->relationship('branch', 'name', function ($query, callable $get) {
|
||||
$query->orderByTranslation('name');
|
||||
|
||||
$region = $get('region');
|
||||
if ($region) {
|
||||
$query->where('region', $region);
|
||||
@@ -125,18 +130,21 @@ class LoanOrderForm
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->autocomplete(Str::random(10)),
|
||||
->autocomplete(Str::random(10))
|
||||
->default(user()->first_name),
|
||||
|
||||
TextInput::make('customer_surname')
|
||||
->label(__('Surname'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
->maxLength(255)
|
||||
->default(user()->last_name),
|
||||
|
||||
TextInput::make('customer_patronic_name')
|
||||
->label(__('Patronic name'))
|
||||
->columnSpan(2)
|
||||
->maxLength(255),
|
||||
->maxLength(255)
|
||||
->default(user()->getOption('patronic_name')),
|
||||
|
||||
DatePicker::make('born_at')
|
||||
->displayFormat('d.m.Y')
|
||||
@@ -144,7 +152,8 @@ class LoanOrderForm
|
||||
->native(false)
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->beforeOrEqual('today'),
|
||||
->beforeOrEqual('today')
|
||||
->default(user()->getOption('born_at')),
|
||||
|
||||
FusedGroup::make([
|
||||
Select::make('passport_serie')
|
||||
@@ -152,13 +161,15 @@ class LoanOrderForm
|
||||
->options(TurkmenPassportRepository::values())
|
||||
->native(false)
|
||||
->required()
|
||||
->columnSpan(1),
|
||||
->columnSpan(1)
|
||||
->default(user()->getOption('passport_serie')),
|
||||
|
||||
TextInput::make('passport_id')
|
||||
->label(__('Passport number'))
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->mask('999999'),
|
||||
->mask('999999')
|
||||
->default(user()->getOption('passport_id')),
|
||||
])
|
||||
->columnSpan(3)
|
||||
->label(__('Passport serie and number'))
|
||||
@@ -171,37 +182,43 @@ class LoanOrderForm
|
||||
->native(false)
|
||||
->closeOnDateSelection()
|
||||
->beforeOrEqual('today')
|
||||
->required(),
|
||||
->required()
|
||||
->default(user()->getOption('passport_given_at')),
|
||||
|
||||
TextInput::make('born_place')
|
||||
->columnSpan(3)
|
||||
->label(__('Born place (passport)'))
|
||||
->maxLength(255)
|
||||
->required(),
|
||||
->required()
|
||||
->default(user()->getOption('born_place')),
|
||||
|
||||
TextInput::make('passport_given_by')
|
||||
->label(__('Passport given by'))
|
||||
->columnSpan(4)
|
||||
->maxLength(255)
|
||||
->required(),
|
||||
->required()
|
||||
->default(user()->getOption('passport_given_by')),
|
||||
|
||||
TextInput::make('passport_address')
|
||||
->columnSpan(4)
|
||||
->label(__('Proscription for home'))
|
||||
->maxLength(255)
|
||||
->required(),
|
||||
->required()
|
||||
->default(user()->getOption('passport_address')),
|
||||
|
||||
TextInput::make('real_address')
|
||||
->label(__('Current home address'))
|
||||
->columnSpan(4)
|
||||
->maxLength(255)
|
||||
->required(),
|
||||
->required()
|
||||
->default(user()->getOption('real_address')),
|
||||
|
||||
TextInput::make('email')
|
||||
->label(__('Email'))
|
||||
->email()
|
||||
->maxLength(255)
|
||||
->columnSpan(2),
|
||||
->columnSpan(2)
|
||||
->default(user()->getOption('email')),
|
||||
|
||||
TextInput::make('phone')
|
||||
->label(__('Phone'))
|
||||
@@ -211,7 +228,8 @@ class LoanOrderForm
|
||||
->rules([
|
||||
new PhoneNumberVerificationRule,
|
||||
])
|
||||
->columnSpan(2),
|
||||
->columnSpan(2)
|
||||
->default(user()->phone),
|
||||
|
||||
TextInput::make('phone_additional')
|
||||
->label(__('Additional phone'))
|
||||
@@ -281,12 +299,14 @@ class LoanOrderForm
|
||||
->options(RegionRepository::values())
|
||||
->columnSpan(1)
|
||||
->live()
|
||||
->afterStateUpdated(fn (callable $set) => $set('branch_id', null))
|
||||
->afterStateUpdated(fn (callable $set) => $set('work_province_id', null))
|
||||
->required(),
|
||||
|
||||
Select::make('work_province_id')
|
||||
->label(__('Work province'))
|
||||
->relationship('workProvince', 'name', function ($query, callable $get) {
|
||||
$query->orderByTranslation('name');
|
||||
|
||||
$region = $get('work_region');
|
||||
if ($region) {
|
||||
$query->where('region', $region);
|
||||
@@ -325,9 +345,10 @@ class LoanOrderForm
|
||||
->displayFormat('d.m.Y')
|
||||
->beforeOrEqual('today')
|
||||
->required()
|
||||
->native(false)
|
||||
->columnSpan(1),
|
||||
]),
|
||||
])->columnSpan(4),
|
||||
])->columnSpan(4)->skippable(fn (string $context) => $context === 'edit'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,71 +2,90 @@
|
||||
|
||||
namespace App\Filament\Clusters\Loans\LoanOrders\Tables;
|
||||
|
||||
use App\Modules\DefaultQueryForResourceIndex\Repositories\DefaultQueryForResourceIndexRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Actions\ForceDeleteBulkAction;
|
||||
use Filament\Actions\RestoreBulkAction;
|
||||
use Filament\Actions\ViewAction;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Filters\TrashedFilter;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class LoanOrdersTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->modifyQueryUsing(function (Builder $query) {
|
||||
$query->where('source', 'web');
|
||||
|
||||
DefaultQueryForResourceIndexRepository::make($query);
|
||||
})
|
||||
->defaultSort('created_at', 'desc')
|
||||
->columns([
|
||||
TextColumn::make('id')
|
||||
->label('ID')
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('loanType.name')
|
||||
->label('Тип кредита')
|
||||
->label(__('Loan type'))
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('region')
|
||||
->label('Регион')
|
||||
->label(__('Region'))
|
||||
->sortable()
|
||||
->searchable(),
|
||||
->searchable()
|
||||
->formatStateUsing(fn (string $state) => RegionRepository::label($state)),
|
||||
|
||||
TextColumn::make('branch.name')
|
||||
->label('Филиал')
|
||||
->label(__('Branch'))
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('customer_name')
|
||||
->label('Имя клиента')
|
||||
->label(__('Name'))
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('customer_surname')
|
||||
->label('Фамилия клиента')
|
||||
->label(__('Surname'))
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('phone')
|
||||
->label('Телефон')
|
||||
->label(__('Phone'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('status')
|
||||
->label('Статус')
|
||||
->label(__('Status'))
|
||||
->formatStateUsing(fn (string $state) => OrderStatusRepository::statusFormatted($state))
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('status')
|
||||
->badge()
|
||||
->color(OrderStatusRepository::statusColorMatching())
|
||||
->formatStateUsing(fn (string $state) => OrderStatusRepository::statusFormatted($state)),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->label('Дата создания')
|
||||
->label(__('Created At'))
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(),
|
||||
|
||||
TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->label(__('Updated At'))
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
|
||||
TextColumn::make('deleted_at')
|
||||
->label(__('Deleted At'))
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
@@ -75,7 +94,6 @@ class LoanOrdersTable
|
||||
TrashedFilter::make(),
|
||||
])
|
||||
->recordActions([
|
||||
ViewAction::make(),
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
|
||||
@@ -34,12 +34,12 @@ class LoanResource extends Resource
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Karz');
|
||||
return __('Loan');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Karzlar');
|
||||
return __('Loans');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
|
||||
@@ -22,6 +22,7 @@ class LoanForm
|
||||
->default(user()->getOption('passport_id')),
|
||||
|
||||
TextInput::make('account_number')
|
||||
->label(__('Account number'))
|
||||
->required()
|
||||
->string()
|
||||
->maxLength(23),
|
||||
|
||||
@@ -2,19 +2,30 @@
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Loans\Tables;
|
||||
|
||||
use App\Modules\Loan\Filaments\Actions\ShowLoanRemainingAction;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class LoansTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->modifyQueryUsing(function (Builder $query) {
|
||||
if (user()->isAdmin()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query->where('user_id', user()->id);
|
||||
})
|
||||
->columns([
|
||||
TextColumn::make('account_number')
|
||||
->label(__('Account number'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
@@ -31,7 +42,9 @@ class LoansTable
|
||||
//
|
||||
])
|
||||
->recordActions([
|
||||
ShowLoanRemainingAction::make(),
|
||||
EditAction::make(),
|
||||
DeleteAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
|
||||
@@ -9,8 +9,9 @@ use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class LoansCluster extends Cluster
|
||||
{
|
||||
protected static ?int $navigationSort = 2;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedBanknotes;
|
||||
// protected static string|BackedEnum|null $activeNavigationIcon = Heroicon::Banknotes;
|
||||
|
||||
protected static ?SubNavigationPosition $subNavigationPosition = SubNavigationPosition::Top;
|
||||
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanOrderMobiles;
|
||||
|
||||
use App\Filament\Clusters\Loans\LoansCluster;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Pages\CreateLoanOrderMobile;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Pages\EditLoanOrderMobile;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Pages\ListLoanOrderMobiles;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Schemas\LoanOrderMobileForm;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Tables\LoanOrderMobilesTable;
|
||||
use App\Modules\LoanOrderMobile\Models\LoanOrderMobile;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
|
||||
class LoanOrderMobileResource extends Resource
|
||||
{
|
||||
protected static ?string $model = LoanOrderMobile::class;
|
||||
|
||||
protected static ?int $navigationSort = 3;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedDevicePhoneMobile;
|
||||
|
||||
protected static string|BackedEnum|null $activeNavigationIcon = Heroicon::DevicePhoneMobile;
|
||||
|
||||
protected static ?string $cluster = LoansCluster::class;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'unique_id';
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('module.loan-order::loan-order.loan_order').' (mobile app)';
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('module.loan-order::loan-order.loan_order').' (mobile app)';
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('module.loan-order::loan-order.loan_orders').' (mobile app)';
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return LoanOrderMobileForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return LoanOrderMobilesTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListLoanOrderMobiles::route('/'),
|
||||
'create' => CreateLoanOrderMobile::route('/create'),
|
||||
'edit' => EditLoanOrderMobile::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<\App\Modules\LoanOrder\Models\LoanOrder>
|
||||
*/
|
||||
public static function getRecordRouteBindingEloquentQuery(): Builder
|
||||
{
|
||||
return parent::getRecordRouteBindingEloquentQuery()
|
||||
->withoutGlobalScopes([
|
||||
SoftDeletingScope::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Pages;
|
||||
|
||||
use App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\LoanOrderMobileResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateLoanOrderMobile extends CreateRecord
|
||||
{
|
||||
protected static string $resource = LoanOrderMobileResource::class;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Pages;
|
||||
|
||||
use App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\LoanOrderMobileResource;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\ForceDeleteAction;
|
||||
use Filament\Actions\RestoreAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditLoanOrderMobile extends EditRecord
|
||||
{
|
||||
protected static string $resource = LoanOrderMobileResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
DeleteAction::make(),
|
||||
ForceDeleteAction::make(),
|
||||
RestoreAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Pages;
|
||||
|
||||
use App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\LoanOrderMobileResource;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
|
||||
class ListLoanOrderMobiles extends ListRecords
|
||||
{
|
||||
protected static string $resource = LoanOrderMobileResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getTabs(): array
|
||||
{
|
||||
if (! user()->isSystemUser()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach (array_keys(OrderStatusRepository::statusClasses()) as $status) {
|
||||
if ($status === '') {
|
||||
$data[null] = Tab::make(__('All'));
|
||||
} else {
|
||||
$data[$status] = Tab::make(OrderStatusRepository::statusFormatted($status))->query(fn ($query) => $query->where('status', $status));
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,532 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Schemas;
|
||||
|
||||
use App\Modules\AppHelpers\Repositories\DateHelper;
|
||||
use App\Modules\LoanOrder\Models\LoanOrderRequiredDocs;
|
||||
use App\Modules\LoanOrder\Repositories\LoanOrderRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\PersonStates\Repositories\EducationRepository;
|
||||
use App\Modules\PersonStates\Repositories\MarriageRepository;
|
||||
use App\Modules\PhoneNumberVerification\Rules\PhoneNumberVerificationRule;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use App\Modules\TurkmenPassport\Repositories\TurkmenPassportRepository;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Hidden;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Components\Fieldset;
|
||||
use Filament\Schemas\Components\FusedGroup;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Components\Tabs;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
use Filament\Schemas\Components\Utilities\Get;
|
||||
use Filament\Schemas\Schema;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class LoanOrderMobileForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->columns(4)
|
||||
->components([
|
||||
Hidden::make('source')->default('mobile'),
|
||||
Hidden::make('user_id')->default(Auth::id()),
|
||||
|
||||
Section::make(__('New loan order'))
|
||||
->columnSpan(4)
|
||||
->columns(4)
|
||||
->components([
|
||||
Select::make('status')
|
||||
->label(__('Status'))
|
||||
->options(OrderStatusRepository::statusValues())
|
||||
->default(OrderStatusRepository::defaultStatus())
|
||||
->native(false)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
|
||||
Select::make('satisfiable')
|
||||
->label(__('Loan history'))
|
||||
->options(LoanOrderRepository::satisfiableValues())
|
||||
->native(false)
|
||||
->columnSpan(2),
|
||||
|
||||
Select::make('loan_order_required_doc_id')
|
||||
->label(__('Required documents'))
|
||||
->relationship('requiredDocs', 'name')
|
||||
->searchable()
|
||||
->native(false)
|
||||
->preload()
|
||||
->live()
|
||||
->afterStateUpdated(function ($state, callable $set) {
|
||||
if ($state) {
|
||||
/** @var null|LoanOrderRequiredDocs */
|
||||
$requiredDoc = LoanOrderRequiredDocs::find($state);
|
||||
|
||||
if ($requiredDoc) {
|
||||
$set('notes', $requiredDoc->value);
|
||||
}
|
||||
}
|
||||
})
|
||||
->columnSpanFull(),
|
||||
|
||||
RichEditor::make('notes')
|
||||
->label(__('Bellik'))
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
|
||||
Tabs::make('Loan Order')
|
||||
->tabs([
|
||||
Tab::make(__('Loan & Bank'))
|
||||
->schema([
|
||||
Fieldset::make(__('Loan type and amount'))
|
||||
->schema([
|
||||
Select::make('loan_type')
|
||||
->label(__('Loan type'))
|
||||
->relationship('loanType', 'name', fn (Builder $query) => $query->orderByTranslation('name')->where('id', 2))
|
||||
->required(),
|
||||
|
||||
TextInput::make('loan_amount')
|
||||
->label(__('Loan amount'))
|
||||
->numeric()
|
||||
->required()
|
||||
->minValue(1)
|
||||
->maxValue(40000)
|
||||
->suffix('TMT')
|
||||
->belowContent(__('Max is 40 000 TMT'))
|
||||
->live(),
|
||||
]),
|
||||
|
||||
Fieldset::make(__('Location'))
|
||||
->schema([
|
||||
Select::make('region')
|
||||
->label(__('Region'))
|
||||
->options(RegionRepository::values())
|
||||
->live()
|
||||
->afterStateUpdated(fn (callable $set) => $set('branch_id', null))
|
||||
->required(),
|
||||
|
||||
Select::make('branch_id')
|
||||
->label(__('Branch'))
|
||||
->relationship('branch', 'name', function ($query, callable $get) {
|
||||
$query->orderByTranslation('name');
|
||||
|
||||
$region = $get('region');
|
||||
if ($region) {
|
||||
$query->where('region', $region);
|
||||
}
|
||||
})
|
||||
->required(),
|
||||
]),
|
||||
]),
|
||||
Tab::make(__('Personal information'))
|
||||
->columns(8)
|
||||
->schema([
|
||||
TextInput::make('customer_name')
|
||||
->label(__('Name'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->autocomplete(Str::random(10))
|
||||
->default(user()->first_name),
|
||||
|
||||
TextInput::make('customer_surname')
|
||||
->label(__('Surname'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->default(user()->last_name),
|
||||
|
||||
TextInput::make('customer_patronic_name')
|
||||
->label(__('Patronic name'))
|
||||
->columnSpan(2)
|
||||
->maxLength(255)
|
||||
->default(user()->getOption('patronic_name')),
|
||||
|
||||
DatePicker::make('born_at')
|
||||
->displayFormat('d.m.Y')
|
||||
->label(__('Birth date'))
|
||||
->native(false)
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->beforeOrEqual('today')
|
||||
->default(user()->getOption('born_at')),
|
||||
|
||||
FusedGroup::make([
|
||||
Select::make('passport_serie')
|
||||
->label(__('Passport serie'))
|
||||
->options(TurkmenPassportRepository::values())
|
||||
->native(false)
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->default(user()->getOption('passport_serie')),
|
||||
|
||||
TextInput::make('passport_id')
|
||||
->label(__('Passport number'))
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->mask('999999')
|
||||
->default(user()->getOption('passport_id')),
|
||||
])
|
||||
->columnSpan(3)
|
||||
->label(__('Passport serie and number'))
|
||||
->columns(2),
|
||||
|
||||
DatePicker::make('passport_given_at')
|
||||
->label(__('Passport given date'))
|
||||
->columnSpan(2)
|
||||
->displayFormat('d.m.Y')
|
||||
->native(false)
|
||||
->closeOnDateSelection()
|
||||
->beforeOrEqual('today')
|
||||
->required()
|
||||
->default(user()->getOption('passport_given_at')),
|
||||
|
||||
TextInput::make('born_place')
|
||||
->columnSpan(3)
|
||||
->label(__('Born place (passport)'))
|
||||
->maxLength(255)
|
||||
->required()
|
||||
->default(user()->getOption('born_place')),
|
||||
|
||||
TextInput::make('passport_given_by')
|
||||
->label(__('Passport given by'))
|
||||
->columnSpan(4)
|
||||
->maxLength(255)
|
||||
->required()
|
||||
->default(user()->getOption('passport_given_by')),
|
||||
|
||||
TextInput::make('passport_address')
|
||||
->columnSpan(4)
|
||||
->label(__('Proscription for home'))
|
||||
->maxLength(255)
|
||||
->required()
|
||||
->default(user()->getOption('passport_address')),
|
||||
|
||||
TextInput::make('real_address')
|
||||
->label(__('Current home address'))
|
||||
->columnSpan(4)
|
||||
->maxLength(255)
|
||||
->required()
|
||||
->default(user()->getOption('real_address')),
|
||||
|
||||
TextInput::make('email')
|
||||
->label(__('Email'))
|
||||
->email()
|
||||
->maxLength(255)
|
||||
->columnSpan(2)
|
||||
->default(user()->getOption('email')),
|
||||
|
||||
TextInput::make('phone')
|
||||
->label(__('Phone'))
|
||||
->required()
|
||||
->mask('99 99 99 99')
|
||||
->prefix('+993')
|
||||
->rules([
|
||||
new PhoneNumberVerificationRule,
|
||||
])
|
||||
->columnSpan(2)
|
||||
->default(user()->phone),
|
||||
|
||||
TextInput::make('phone_additional')
|
||||
->label(__('Additional phone'))
|
||||
->mask('99 99 99 99')
|
||||
->prefix('+993')
|
||||
->rules([
|
||||
new PhoneNumberVerificationRule,
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('phone_home')
|
||||
->label(__('Home phone'))
|
||||
->numeric()
|
||||
->prefix('+993')
|
||||
->columnSpan(2),
|
||||
|
||||
Select::make('education')
|
||||
->columnSpan(2)
|
||||
->label(__('Education'))
|
||||
->options(EducationRepository::values())
|
||||
->native(false)
|
||||
->required(),
|
||||
|
||||
Select::make('marriage_status')
|
||||
->columnSpan(2)
|
||||
->label(__('Marital status'))
|
||||
->options(MarriageRepository::values())
|
||||
->native(false)
|
||||
->required(),
|
||||
]),
|
||||
Tab::make(__('Salary card'))
|
||||
->columns(6)
|
||||
->schema([
|
||||
TextInput::make('card_number')
|
||||
->label(__('Card number'))
|
||||
->mask('9999 9999 9999 9999')
|
||||
->dehydrateStateUsing(fn ($state) => str_replace(' ', '', $state))
|
||||
->columnSpan(2)
|
||||
->required(),
|
||||
|
||||
TextInput::make('card_name')
|
||||
->label(__('Card name'))
|
||||
->maxLength(255)
|
||||
->columnSpan(2)
|
||||
->required(),
|
||||
|
||||
Select::make('card_month')
|
||||
->label(__('Card month'))
|
||||
->options(DateHelper::staticNumberMonths())
|
||||
->native(false)
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
|
||||
Select::make('card_year')
|
||||
->label(__('Card year'))
|
||||
->options(DateHelper::staticNumberYears())
|
||||
->native(false)
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
]),
|
||||
Tab::make(__('Pasport files'))
|
||||
->columns(4)
|
||||
->schema([
|
||||
FileUpload::make('passport_one')
|
||||
->label(__('Passport (page 1)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
|
||||
FileUpload::make('passport_two')
|
||||
->label(__('Passport (page 2-3)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
|
||||
FileUpload::make('passport_three')
|
||||
->label(__('Passport (page 8-9)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
|
||||
FileUpload::make('passport_four')
|
||||
->label(__('Passport (page 32)'))
|
||||
->image()
|
||||
->maxSize(4096)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
]),
|
||||
Tab::make(__('Work'))
|
||||
->columns(4)
|
||||
->schema([
|
||||
Select::make('work_region')
|
||||
->label(__('Work region'))
|
||||
->options(RegionRepository::values())
|
||||
->columnSpan(1)
|
||||
->live()
|
||||
->afterStateUpdated(fn (callable $set) => $set('work_province_id', null))
|
||||
->required(),
|
||||
|
||||
Select::make('work_province_id')
|
||||
->label(__('Work province'))
|
||||
->relationship('workProvince', 'name', function ($query, callable $get) {
|
||||
$query->orderByTranslation('name');
|
||||
|
||||
$region = $get('work_region');
|
||||
if ($region) {
|
||||
$query->where('region', $region);
|
||||
}
|
||||
})
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
|
||||
TextInput::make('work_company')
|
||||
->label(__('Work company name'))
|
||||
->maxLength(255)
|
||||
->required()
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('work_company_accountant_number')
|
||||
->label(__('HR number'))
|
||||
->prefix('+993')
|
||||
->numeric()
|
||||
->required()
|
||||
->columnSpan(1),
|
||||
|
||||
TextInput::make('work_position')
|
||||
->label(__('Work position'))
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->columnSpan(1),
|
||||
|
||||
TextInput::make('work_salary')
|
||||
->label(__('Salary'))
|
||||
->numeric()
|
||||
->required()
|
||||
->columnSpan(1),
|
||||
|
||||
DatePicker::make('work_started_at')
|
||||
->label(__('Work started at'))
|
||||
->displayFormat('d.m.Y')
|
||||
->beforeOrEqual('today')
|
||||
->required()
|
||||
->columnSpan(1),
|
||||
]),
|
||||
Tab::make(__('Guarantor').' 1')
|
||||
->columns(6)
|
||||
->schema([
|
||||
TextInput::make('guarantor_name')
|
||||
->label(__('Guarantor').' '.__('Name'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('guarantor_surname')
|
||||
->label(__('Guarantor').' '.__('Surname'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('guarantor_patronic_name')
|
||||
->label(__('Guarantor').' '.__('Patronic name'))
|
||||
->columnSpan(2)
|
||||
->maxLength(255),
|
||||
|
||||
FusedGroup::make([
|
||||
Select::make('guarantor_passport_serie')
|
||||
->label(__('Passport serie'))
|
||||
->options(TurkmenPassportRepository::values())
|
||||
->native(false)
|
||||
->required()
|
||||
->columnSpan(1),
|
||||
|
||||
TextInput::make('guarantor_passport_id')
|
||||
->label(__('Passport number'))
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->mask('999999'),
|
||||
])
|
||||
->columnSpan(3)
|
||||
->label(__('Passport serie and number'))
|
||||
->columns(2),
|
||||
|
||||
TextInput::make('guarantor_note')
|
||||
->label(__('Guarantor').' '.__('Salary'))
|
||||
->columnSpan(3)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('guarantor_card_number')
|
||||
->label(__('Card number'))
|
||||
->mask('9999 9999 9999 9999')
|
||||
->dehydrateStateUsing(fn ($state) => str_replace(' ', '', $state))
|
||||
->columnSpan(2)
|
||||
->required(),
|
||||
|
||||
TextInput::make('guarantor_card_name')
|
||||
->label(__('Card name'))
|
||||
->maxLength(255)
|
||||
->columnSpan(2)
|
||||
->required(),
|
||||
|
||||
Select::make('guarantor_card_month')
|
||||
->label(__('Card month'))
|
||||
->options(DateHelper::staticNumberMonths())
|
||||
->native(false)
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
|
||||
Select::make('guarantor_card_year')
|
||||
->label(__('Card year'))
|
||||
->options(DateHelper::staticNumberYears())
|
||||
->native(false)
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
]),
|
||||
Tab::make(__('Guarantor').' 2')
|
||||
->columns(6)
|
||||
->hidden(function (Get $get): bool {
|
||||
$loan_amount = $get('loan_amount') ? string($get('loan_amount')) : 1;
|
||||
|
||||
return ! ($loan_amount && intval($loan_amount) > 20000);
|
||||
})
|
||||
->schema([
|
||||
TextInput::make('guarantor_2_name')
|
||||
->label(__('Guarantor').' '.__('Name'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('guarantor_2_surname')
|
||||
->label(__('Guarantor').' '.__('Surname'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('guarantor_2_patronic_name')
|
||||
->label(__('Guarantor').' '.__('Patronic name'))
|
||||
->columnSpan(2)
|
||||
->maxLength(255),
|
||||
|
||||
FusedGroup::make([
|
||||
Select::make('guarantor_2_passport_serie')
|
||||
->label(__('Passport serie'))
|
||||
->options(TurkmenPassportRepository::values())
|
||||
->native(false)
|
||||
->required()
|
||||
->columnSpan(1),
|
||||
|
||||
TextInput::make('guarantor_2_passport_id')
|
||||
->label(__('Passport number'))
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->mask('999999'),
|
||||
])
|
||||
->columnSpan(3)
|
||||
->label(__('Passport serie and number'))
|
||||
->columns(2),
|
||||
|
||||
TextInput::make('guarantor_2_note')
|
||||
->label(__('Guarantor').' '.__('Salary'))
|
||||
->columnSpan(3)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('guarantor_2_card_number')
|
||||
->label(__('Card number'))
|
||||
->mask('9999 9999 9999 9999')
|
||||
->dehydrateStateUsing(fn ($state) => str_replace(' ', '', $state))
|
||||
->columnSpan(2)
|
||||
->required(),
|
||||
|
||||
TextInput::make('guarantor_2_card_name')
|
||||
->label(__('Card name'))
|
||||
->maxLength(255)
|
||||
->columnSpan(2)
|
||||
->required(),
|
||||
|
||||
Select::make('guarantor_2_card_month')
|
||||
->label(__('Card month'))
|
||||
->options(DateHelper::staticNumberMonths())
|
||||
->native(false)
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
|
||||
Select::make('guarantor_2_card_year')
|
||||
->label(__('Card year'))
|
||||
->options(DateHelper::staticNumberYears())
|
||||
->native(false)
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
]),
|
||||
])->columnSpan(4),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Schemas;
|
||||
|
||||
use Filament\Schemas\Schema;
|
||||
|
||||
class LoanOrderMobileInfolist
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->columns(3)
|
||||
->components([
|
||||
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanOrderMobiles\Tables;
|
||||
|
||||
use App\Modules\DefaultQueryForResourceIndex\Repositories\DefaultQueryForResourceIndexRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Actions\ForceDeleteBulkAction;
|
||||
use Filament\Actions\RestoreBulkAction;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Filters\TrashedFilter;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class LoanOrderMobilesTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->modifyQueryUsing(function (Builder $query) {
|
||||
$query->where('source', 'mobile');
|
||||
|
||||
DefaultQueryForResourceIndexRepository::make($query);
|
||||
})
|
||||
->defaultSort('created_at', 'desc')
|
||||
->columns([
|
||||
TextColumn::make('id')
|
||||
->label('ID')
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('region')
|
||||
->label(__('Region'))
|
||||
->sortable()
|
||||
->searchable()
|
||||
->formatStateUsing(fn (string $state) => RegionRepository::label($state)),
|
||||
|
||||
TextColumn::make('branch.name')
|
||||
->label(__('Branch'))
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('customer_name')
|
||||
->label(__('Name'))
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('customer_surname')
|
||||
->label(__('Surname'))
|
||||
->sortable()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('phone')
|
||||
->label(__('Phone'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('status')
|
||||
->label(__('Status'))
|
||||
->sortable()
|
||||
->searchable()
|
||||
->badge()
|
||||
->color(OrderStatusRepository::statusColorMatching())
|
||||
->formatStateUsing(fn (string $state) => OrderStatusRepository::statusFormatted($state)),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->label(__('Created At'))
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(),
|
||||
|
||||
TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->label(__('Updated At'))
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
|
||||
TextColumn::make('deleted_at')
|
||||
->label(__('Deleted At'))
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
TrashedFilter::make(),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
ForceDeleteBulkAction::make(),
|
||||
RestoreBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters;
|
||||
|
||||
use App\Filament\Clusters\Loans\LoansCluster;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Pages\CreateLoanPaidOffLetter;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Pages\EditLoanPaidOffLetter;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Pages\ListLoanPaidOffLetters;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Schemas\LoanPaidOffLetterForm;
|
||||
use App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Tables\LoanPaidOffLettersTable;
|
||||
use App\Modules\LoanPaidOffLetter\Models\LoanPaidOffLetter;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
|
||||
class LoanPaidOffLetterResource extends Resource
|
||||
{
|
||||
protected static ?int $navigationSort = 3;
|
||||
|
||||
protected static ?string $model = LoanPaidOffLetter::class;
|
||||
|
||||
protected static ?string $cluster = LoansCluster::class;
|
||||
|
||||
public static function getNavigationIcon(): string|BackedEnum|Htmlable|null
|
||||
{
|
||||
return Heroicon::OutlinedDocumentText;
|
||||
}
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('Loan paid off letters');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Loan paid off letter');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Loan paid off letters');
|
||||
}
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'loan_reason';
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return LoanPaidOffLetterForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return LoanPaidOffLettersTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListLoanPaidOffLetters::route('/'),
|
||||
'create' => CreateLoanPaidOffLetter::route('/create'),
|
||||
'edit' => EditLoanPaidOffLetter::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Pages;
|
||||
|
||||
use App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\LoanPaidOffLetterResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateLoanPaidOffLetter extends CreateRecord
|
||||
{
|
||||
protected static string $resource = LoanPaidOffLetterResource::class;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Pages;
|
||||
|
||||
use App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\LoanPaidOffLetterResource;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditLoanPaidOffLetter extends EditRecord
|
||||
{
|
||||
protected static string $resource = LoanPaidOffLetterResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Pages;
|
||||
|
||||
use App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\LoanPaidOffLetterResource;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
|
||||
class ListLoanPaidOffLetters extends ListRecords
|
||||
{
|
||||
protected static string $resource = LoanPaidOffLetterResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getTabs(): array
|
||||
{
|
||||
if (! user()->isSystemUser()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach (array_keys(OrderStatusRepository::statusClasses()) as $status) {
|
||||
if ($status === '') {
|
||||
$data[null] = Tab::make(__('All'));
|
||||
} else {
|
||||
$data[$status] = Tab::make(OrderStatusRepository::statusFormatted($status))->query(fn ($query) => $query->where('status', $status));
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Schemas;
|
||||
|
||||
use App\Modules\FilamentPermission\Repositories\FilamentPermissionRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\PhoneNumberVerification\Rules\PhoneNumberVerificationRule;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use App\Modules\TurkmenPassport\Repositories\TurkmenPassportRepository;
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Hidden;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Components\FusedGroup;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Schema;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class LoanPaidOffLetterForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->columns(6)
|
||||
->components([
|
||||
Hidden::make('user_id')->default(Auth::id()),
|
||||
|
||||
Section::make(__('New loan paid off letter'))
|
||||
->columnSpan(4)
|
||||
->columns(6)
|
||||
->components([
|
||||
Select::make('region')
|
||||
->label(__('Region'))
|
||||
->options(RegionRepository::values())
|
||||
->live()
|
||||
->afterStateUpdated(fn (callable $set) => $set('branch_id', null))
|
||||
->columnSpan(3)
|
||||
->required(),
|
||||
|
||||
Select::make('branch_id')
|
||||
->label(__('Branch'))
|
||||
->relationship('branch', 'name', function ($query, callable $get) {
|
||||
$query->orderByTranslation('name');
|
||||
|
||||
$region = $get('region');
|
||||
if ($region) {
|
||||
$query->where('region', $region);
|
||||
}
|
||||
})
|
||||
->columnSpan(3)
|
||||
->required(),
|
||||
|
||||
TextInput::make('customer_name')
|
||||
->label(__('Name'))
|
||||
->columnSpan(2)
|
||||
->default(user()->first_name)
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->autocomplete(Str::random(10))
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('customer_surname')
|
||||
->label(__('Surname'))
|
||||
->columnSpan(2)
|
||||
->default(user()->last_name)
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('customer_patronic_name')
|
||||
->label(__('Patronic name'))
|
||||
->columnSpan(2)
|
||||
->default(user()->getOption('patronic_name'))
|
||||
->maxLength(255)
|
||||
->columnSpan(2),
|
||||
|
||||
DatePicker::make('born_at')
|
||||
->displayFormat('d.m.Y')
|
||||
->label(__('Birth date'))
|
||||
->native(false)
|
||||
->columnSpan(2)
|
||||
->default(user()->getOption('born_at'))
|
||||
->required()
|
||||
->beforeOrEqual('today')
|
||||
->columnSpan(2),
|
||||
|
||||
FusedGroup::make([
|
||||
Select::make('passport_serie')
|
||||
->label(__('Passport serie'))
|
||||
->options(TurkmenPassportRepository::values())
|
||||
->native(false)
|
||||
->required()
|
||||
->default(user()->getOption('passport_serie'))
|
||||
->columnSpan(1),
|
||||
|
||||
TextInput::make('passport_id')
|
||||
->label(__('Passport number'))
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->default(user()->getOption('passport_id'))
|
||||
->mask('999999'),
|
||||
])
|
||||
->columnSpan(2)
|
||||
->label(__('Passport serie and number'))
|
||||
->columns(2),
|
||||
|
||||
TextInput::make('phone')
|
||||
->label(__('Phone'))
|
||||
->required()
|
||||
->mask('99 99 99 99')
|
||||
->prefix('+993')
|
||||
->default(user()->phone)
|
||||
->rules([
|
||||
new PhoneNumberVerificationRule,
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('loan_contract_number')
|
||||
->label(__('Loan contract number'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
DatePicker::make('loan_contract_date')
|
||||
->displayFormat('d.m.Y')
|
||||
->label(__('Loan contract date'))
|
||||
->native(false)
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->beforeOrEqual('today')
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('loan_amount')
|
||||
->label(__('Loan amount'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->numeric()
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('loan_reason')
|
||||
->label(__('Loan reason'))
|
||||
->columnSpan(2)
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->columnSpan(6),
|
||||
]),
|
||||
|
||||
Section::make(__('By operator'))
|
||||
->columnSpan(2)
|
||||
->disabled(fn (string $context): bool => FilamentPermissionRepository::forClients())
|
||||
->hidden(fn (string $context) => FilamentPermissionRepository::defaultSystemInput($context))
|
||||
->components([
|
||||
Select::make('status')
|
||||
->label(__('Status'))
|
||||
->options(OrderStatusRepository::statusValues())
|
||||
->default(OrderStatusRepository::defaultStatus())
|
||||
->native(false)
|
||||
->required()
|
||||
->columnSpanFull(),
|
||||
|
||||
RichEditor::make('notes')
|
||||
->label(__('Bellik'))
|
||||
->toolbarButtons([
|
||||
'h2',
|
||||
'italic',
|
||||
'orderedList',
|
||||
'bold',
|
||||
'strike',
|
||||
'underline',
|
||||
])
|
||||
->columnSpanFull(),
|
||||
|
||||
FileUpload::make('loan_file')
|
||||
->label(__('Loan paid off letter file'))
|
||||
->columnSpanFull()
|
||||
->maxSize(4096)
|
||||
->columnSpan(2)
|
||||
->downloadable()
|
||||
->previewable(false),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Loans\Resources\LoanPaidOffLetters\Tables;
|
||||
|
||||
use App\Modules\DefaultQueryForResourceIndex\Repositories\DefaultQueryForResourceIndexRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class LoanPaidOffLettersTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->modifyQueryUsing(function (Builder $query) {
|
||||
DefaultQueryForResourceIndexRepository::make($query);
|
||||
})
|
||||
->defaultSort('created_at', 'desc')
|
||||
->columns([
|
||||
TextColumn::make('id')
|
||||
->label('ID')
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('region')
|
||||
->label(__('Region'))
|
||||
->formatStateUsing(fn (string $state) => RegionRepository::label($state)),
|
||||
|
||||
TextColumn::make('branch.name')
|
||||
->label(__('Branch')),
|
||||
|
||||
TextColumn::make('customer_name')
|
||||
->label(__('Name'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('customer_surname')
|
||||
->label(__('Surname'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('phone')
|
||||
->label(__('Phone'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('status')
|
||||
->label(__('Status'))
|
||||
->formatStateUsing(fn (string $state) => OrderStatusRepository::statusFormatted($state))
|
||||
->sortable()
|
||||
->badge()
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\OnlinePayments;
|
||||
|
||||
use BackedEnum;
|
||||
use Filament\Clusters\Cluster;
|
||||
use Filament\Pages\Enums\SubNavigationPosition;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class OnlinePaymentsCluster extends Cluster
|
||||
{
|
||||
protected static ?int $navigationSort = 5;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedServerStack;
|
||||
|
||||
protected static ?SubNavigationPosition $subNavigationPosition = SubNavigationPosition::Top;
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('Online payments');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments;
|
||||
|
||||
use App\Filament\Clusters\OnlinePayments\OnlinePaymentsCluster;
|
||||
use App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\Pages\EditOnlinePayment;
|
||||
use App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\Pages\ListOnlinePayments;
|
||||
use App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\Schemas\OnlinePaymentForm;
|
||||
use App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\Tables\OnlinePaymentsTable;
|
||||
use App\Modules\OnlinePayment\Models\OnlinePayment;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class OnlinePaymentResource extends Resource
|
||||
{
|
||||
protected static ?string $model = OnlinePayment::class;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedRectangleStack;
|
||||
|
||||
protected static ?string $cluster = OnlinePaymentsCluster::class;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'orderId';
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return OnlinePaymentForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return OnlinePaymentsTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListOnlinePayments::route('/'),
|
||||
'edit' => EditOnlinePayment::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\Pages;
|
||||
|
||||
use App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\OnlinePaymentResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateOnlinePayment extends CreateRecord
|
||||
{
|
||||
protected static string $resource = OnlinePaymentResource::class;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\Pages;
|
||||
|
||||
use App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\OnlinePaymentResource;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditOnlinePayment extends EditRecord
|
||||
{
|
||||
protected static string $resource = OnlinePaymentResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\Pages;
|
||||
|
||||
use App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\OnlinePaymentResource;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListOnlinePayments extends ListRecords
|
||||
{
|
||||
protected static string $resource = OnlinePaymentResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\Schemas;
|
||||
|
||||
use App\Modules\OnlinePayment\Repositories\OnlinePaymentRepository;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Components\Fieldset;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Schema;
|
||||
|
||||
class OnlinePaymentForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Section::make()
|
||||
->columnSpanFull()
|
||||
->columns([
|
||||
'default' => 1,
|
||||
'md' => 2,
|
||||
'xl' => 3,
|
||||
])
|
||||
->schema([
|
||||
// Payment Information
|
||||
Fieldset::make(__('Payment Information'))
|
||||
->columns([
|
||||
'default' => 1,
|
||||
'md' => 2,
|
||||
])
|
||||
->schema([
|
||||
TextInput::make('amount')
|
||||
->label(__('Amount'))
|
||||
->required()
|
||||
->numeric()
|
||||
->suffix('TMT')
|
||||
->rules(['required', 'numeric', 'min:0']),
|
||||
|
||||
TextInput::make('description')
|
||||
->label(__('Description'))
|
||||
->required()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('orderNumber')
|
||||
->label(__('Order Number'))
|
||||
->maxLength(255)
|
||||
->helperText(__('Leave empty to auto-generate')),
|
||||
|
||||
Select::make('paymentStatus')
|
||||
->label(__('Payment Status'))
|
||||
->options(OnlinePaymentRepository::statusValues())
|
||||
->default(OnlinePaymentRepository::PENDING)
|
||||
->required(),
|
||||
]),
|
||||
|
||||
// Card Information
|
||||
Fieldset::make(__('Card Information'))
|
||||
->columns([
|
||||
'default' => 1,
|
||||
'md' => 2,
|
||||
])
|
||||
->schema([
|
||||
TextInput::make('cardholderName')
|
||||
->label(__('Cardholder Name'))
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('pan')
|
||||
->label(__('Card Number (PAN)'))
|
||||
->maxLength(255)
|
||||
->mask('9999 9999 9999 9999')
|
||||
->placeholder('1234 5678 9012 3456'),
|
||||
|
||||
TextInput::make('expiration')
|
||||
->label(__('Expiration Date'))
|
||||
->mask('99/99')
|
||||
->placeholder('MM/YY'),
|
||||
|
||||
TextInput::make('approvalCode')
|
||||
->label(__('Approval Code'))
|
||||
->maxLength(255),
|
||||
]),
|
||||
|
||||
// Additional Information
|
||||
Fieldset::make(__('Additional Information'))
|
||||
->columns([
|
||||
'default' => 1,
|
||||
'md' => 2,
|
||||
])
|
||||
->schema([
|
||||
TextInput::make('booking_number')
|
||||
->label(__('Booking Number'))
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('depositedAmount')
|
||||
->label(__('Deposited Amount'))
|
||||
->numeric()
|
||||
->suffix('TMT'),
|
||||
|
||||
TextInput::make('refunded_amount')
|
||||
->label(__('Refunded Amount'))
|
||||
->numeric()
|
||||
->suffix('TMT'),
|
||||
|
||||
TextInput::make('username')
|
||||
->label(__('Username'))
|
||||
->maxLength(255)
|
||||
->helperText(__('Payment provider username')),
|
||||
]),
|
||||
|
||||
// URLs
|
||||
Fieldset::make(__('URLs'))
|
||||
->columns([
|
||||
'default' => 1,
|
||||
'md' => 2,
|
||||
])
|
||||
->schema([
|
||||
TextInput::make('formUrl')
|
||||
->label(__('Form URL'))
|
||||
->url()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('successUrl')
|
||||
->label(__('Success URL'))
|
||||
->url()
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('errorUrl')
|
||||
->label(__('Error URL'))
|
||||
->url()
|
||||
->maxLength(255),
|
||||
]),
|
||||
|
||||
// API Information
|
||||
Fieldset::make(__('API Information'))
|
||||
->columns([
|
||||
'default' => 1,
|
||||
'md' => 2,
|
||||
])
|
||||
->schema([
|
||||
TextInput::make('api_client')
|
||||
->label(__('API Client'))
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('callbackStatus')
|
||||
->label(__('Callback Status'))
|
||||
->maxLength(255),
|
||||
|
||||
TextInput::make('orderId')
|
||||
->label(__('Order ID'))
|
||||
->maxLength(255)
|
||||
->helperText(__('External order identifier')),
|
||||
]),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\OnlinePayments\Resources\OnlinePayments\Tables;
|
||||
|
||||
use App\Modules\OnlinePayment\Repositories\OnlinePaymentRepository;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class OnlinePaymentsTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->defaultSort('created_at', direction: 'desc')
|
||||
->columns([
|
||||
TextColumn::make('id')
|
||||
->label(__('ID'))
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('orderNumber')
|
||||
->label(__('Order Number'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('amount')
|
||||
->label(__('Amount'))
|
||||
->money('TMT')
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('description')
|
||||
->label(__('Description'))
|
||||
->limit(50),
|
||||
|
||||
TextColumn::make('paymentStatus')
|
||||
->label(__('Payment Status'))
|
||||
->badge()
|
||||
->color(fn (string $state): string => match ($state) {
|
||||
OnlinePaymentRepository::PAID => 'success',
|
||||
OnlinePaymentRepository::FAILED => 'danger',
|
||||
default => 'warning',
|
||||
})
|
||||
->formatStateUsing(fn (string $state): string => OnlinePaymentRepository::statusValues()[$state] ?? $state)
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('cardholderName')
|
||||
->label(__('Cardholder Name'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('pan')
|
||||
->label(__('Card Number'))
|
||||
->formatStateUsing(fn (string $state): string => $state ? '**** **** **** '.substr($state, -4) : '-')
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('orderId')
|
||||
->label(__('Order ID'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('username')
|
||||
->label(__('Username'))
|
||||
->searchable()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->label(__('Created At'))
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(),
|
||||
|
||||
TextColumn::make('updated_at')
|
||||
->label(__('Updated At'))
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
132
app/Filament/Clusters/Settings/CardStates/CardStateResource.php
Normal file
132
app/Filament/Clusters/Settings/CardStates/CardStateResource.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\CardStates;
|
||||
|
||||
use AbdulmajeedJamaan\FilamentTranslatableTabs\TranslatableTabs;
|
||||
use App\Filament\Clusters\Settings\CardStates\Pages\ManageCardStates;
|
||||
use App\Filament\Clusters\Settings\SettingsCluster;
|
||||
use App\Modules\CardOrder\Models\CardState;
|
||||
use BackedEnum;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class CardStateResource extends Resource
|
||||
{
|
||||
protected static ?string $model = CardState::class;
|
||||
|
||||
protected static ?string $cluster = SettingsCluster::class;
|
||||
|
||||
protected static ?int $navigationSort = 2;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedClipboardDocumentList;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'name';
|
||||
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return __('Cards');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Card state');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Card states');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->columns(2)
|
||||
->components([
|
||||
TranslatableTabs::make('nam')
|
||||
->schema([
|
||||
TextInput::make('name')
|
||||
->label(__('Card state'))
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
]),
|
||||
|
||||
Section::make(__('General'))
|
||||
->columns(6)
|
||||
->schema([
|
||||
TextInput::make('price')
|
||||
->label(__('Price'))
|
||||
->columnSpan(4)
|
||||
->required(),
|
||||
|
||||
Toggle::make('active')
|
||||
->label(__('Active'))
|
||||
->default(true)
|
||||
->inline(false)
|
||||
->columnSpan(2)
|
||||
->required(),
|
||||
|
||||
TextInput::make('notes')
|
||||
->label(__('Notes'))
|
||||
->columnSpanFull()
|
||||
->default(null),
|
||||
]),
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('name')
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('price')
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('notes'),
|
||||
|
||||
IconColumn::make('active')
|
||||
->boolean(),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
DeleteAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ManageCardStates::route('/'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\CardStates\Pages;
|
||||
|
||||
use App\Filament\Clusters\Settings\CardStates\CardStateResource;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ManageRecords;
|
||||
|
||||
class ManageCardStates extends ManageRecords
|
||||
{
|
||||
protected static string $resource = CardStateResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
130
app/Filament/Clusters/Settings/CardTypes/CardTypeResource.php
Normal file
130
app/Filament/Clusters/Settings/CardTypes/CardTypeResource.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\CardTypes;
|
||||
|
||||
use AbdulmajeedJamaan\FilamentTranslatableTabs\TranslatableTabs;
|
||||
use App\Filament\Clusters\Settings\CardTypes\Pages\ManageCardTypes;
|
||||
use App\Filament\Clusters\Settings\SettingsCluster;
|
||||
use App\Modules\CardOrder\Models\CardType;
|
||||
use BackedEnum;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class CardTypeResource extends Resource
|
||||
{
|
||||
protected static ?string $model = CardType::class;
|
||||
|
||||
protected static ?string $cluster = SettingsCluster::class;
|
||||
|
||||
protected static ?int $navigationSort = 2;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedSwatch;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'name';
|
||||
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return __('Cards');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Card type');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Card types');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
TranslatableTabs::make('name')
|
||||
->schema([
|
||||
TextInput::make('name')
|
||||
->label(__('Card state'))
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
]),
|
||||
|
||||
Section::make(__('General'))
|
||||
->columns(6)
|
||||
->schema([
|
||||
TextInput::make('price')
|
||||
->label(__('Price'))
|
||||
->columnSpan(4)
|
||||
->required(),
|
||||
|
||||
Toggle::make('active')
|
||||
->label(__('Active'))
|
||||
->default(true)
|
||||
->inline(false)
|
||||
->columnSpan(2)
|
||||
->required(),
|
||||
|
||||
TextInput::make('notes')
|
||||
->label(__('Notes'))
|
||||
->columnSpanFull()
|
||||
->default(null),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('name')
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('price')
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('notes'),
|
||||
|
||||
IconColumn::make('active')
|
||||
->boolean(),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
DeleteAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ManageCardTypes::route('/'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\CardTypes\Pages;
|
||||
|
||||
use App\Filament\Clusters\Settings\CardTypes\CardTypeResource;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ManageRecords;
|
||||
|
||||
class ManageCardTypes extends ManageRecords
|
||||
{
|
||||
protected static string $resource = CardTypeResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\CurrencyRates;
|
||||
|
||||
use App\Filament\Clusters\Settings\Resources\CurrencyRates\Pages\CreateCurrencyRate;
|
||||
use App\Filament\Clusters\Settings\Resources\CurrencyRates\Pages\EditCurrencyRate;
|
||||
use App\Filament\Clusters\Settings\Resources\CurrencyRates\Pages\ListCurrencyRates;
|
||||
use App\Filament\Clusters\Settings\Resources\CurrencyRates\Schemas\CurrencyRateForm;
|
||||
use App\Filament\Clusters\Settings\Resources\CurrencyRates\Tables\CurrencyRatesTable;
|
||||
use App\Filament\Clusters\Settings\SettingsCluster;
|
||||
use App\Modules\CurrencyRate\Models\CurrencyRate;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class CurrencyRateResource extends Resource
|
||||
{
|
||||
protected static ?string $model = CurrencyRate::class;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCurrencyDollar;
|
||||
|
||||
protected static ?string $cluster = SettingsCluster::class;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'name';
|
||||
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return __('Currencies');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Currency rate');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Currency rates');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return CurrencyRateForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return CurrencyRatesTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListCurrencyRates::route('/'),
|
||||
'create' => CreateCurrencyRate::route('/create'),
|
||||
'edit' => EditCurrencyRate::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\CurrencyRates\Pages;
|
||||
|
||||
use App\Filament\Clusters\Settings\Resources\CurrencyRates\CurrencyRateResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateCurrencyRate extends CreateRecord
|
||||
{
|
||||
protected static string $resource = CurrencyRateResource::class;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\CurrencyRates\Pages;
|
||||
|
||||
use App\Filament\Clusters\Settings\Resources\CurrencyRates\CurrencyRateResource;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditCurrencyRate extends EditRecord
|
||||
{
|
||||
protected static string $resource = CurrencyRateResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\CurrencyRates\Pages;
|
||||
|
||||
use App\Filament\Clusters\Settings\Resources\CurrencyRates\CurrencyRateResource;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListCurrencyRates extends ListRecords
|
||||
{
|
||||
protected static string $resource = CurrencyRateResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\CurrencyRates\Schemas;
|
||||
|
||||
use App\Modules\CurrencyRate\Models\CurrencyRate;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Schema;
|
||||
|
||||
class CurrencyRateForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Select::make('currency_from')
|
||||
->label(__('Currency from'))
|
||||
->native(false)
|
||||
->searchable()
|
||||
->options(CurrencyRate::currencies())
|
||||
->rules('required')
|
||||
->belowLabel('1 möçberi'),
|
||||
|
||||
Select::make('currency_to')
|
||||
->label(__('Currency to'))
|
||||
->native(false)
|
||||
->searchable()
|
||||
->options(CurrencyRate::currencies())
|
||||
->rules('required')
|
||||
->belowLabel('1 möçberi'),
|
||||
|
||||
TextInput::make('value')
|
||||
->label(__('Currency value'))
|
||||
->required()
|
||||
->numeric()
|
||||
->belowLabel('Bitin däl sanlary "." bilen ýazmaly'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\CurrencyRates\Tables;
|
||||
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class CurrencyRatesTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('currency_from')
|
||||
->label(__('Currency from'))
|
||||
->searchable(),
|
||||
TextColumn::make('currency_to')
|
||||
->label(__('Currency to'))
|
||||
->searchable(),
|
||||
TextColumn::make('value')
|
||||
->label(__('Currency value'))
|
||||
->searchable(),
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Pages;
|
||||
|
||||
use App\Filament\Clusters\Settings\Resources\VisaMasterSettings\VisaMasterSettingsResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateVisaMasterSettings extends CreateRecord
|
||||
{
|
||||
protected static string $resource = VisaMasterSettingsResource::class;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Pages;
|
||||
|
||||
use App\Filament\Clusters\Settings\Resources\VisaMasterSettings\VisaMasterSettingsResource;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditVisaMasterSettings extends EditRecord
|
||||
{
|
||||
protected static string $resource = VisaMasterSettingsResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Pages;
|
||||
|
||||
use App\Filament\Clusters\Settings\Resources\VisaMasterSettings\VisaMasterSettingsResource;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListVisaMasterSettings extends ListRecords
|
||||
{
|
||||
protected static string $resource = VisaMasterSettingsResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Schemas;
|
||||
|
||||
use App\Modules\VisaMasterPaymentOrder\Models\VisaMasterSettings;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Schema;
|
||||
|
||||
class VisaMasterSettingsForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Select::make('name')
|
||||
->label(__('Type'))
|
||||
->options(VisaMasterSettings::types())
|
||||
->native(false)
|
||||
->required(),
|
||||
|
||||
TextInput::make('display_name')
|
||||
->label(__('Name'))
|
||||
->required()
|
||||
->string()
|
||||
->maxLength(255)
|
||||
->readonly(! user()->isMe()),
|
||||
|
||||
RichEditor::make('value')
|
||||
->label(__('Content'))
|
||||
->required()
|
||||
->columnSpanFull(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Tables;
|
||||
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class VisaMasterSettingsTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('name')
|
||||
->searchable(),
|
||||
TextColumn::make('display_name')
|
||||
->searchable(),
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Settings\Resources\VisaMasterSettings;
|
||||
|
||||
use App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Pages\CreateVisaMasterSettings;
|
||||
use App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Pages\EditVisaMasterSettings;
|
||||
use App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Pages\ListVisaMasterSettings;
|
||||
use App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Schemas\VisaMasterSettingsForm;
|
||||
use App\Filament\Clusters\Settings\Resources\VisaMasterSettings\Tables\VisaMasterSettingsTable;
|
||||
use App\Filament\Clusters\Settings\SettingsCluster;
|
||||
use App\Modules\VisaMasterPaymentOrder\Models\VisaMasterSettings;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class VisaMasterSettingsResource extends Resource
|
||||
{
|
||||
protected static ?string $model = VisaMasterSettings::class;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedDocumentText;
|
||||
|
||||
protected static ?string $cluster = SettingsCluster::class;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'display_name';
|
||||
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return __('Currencies');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Warning text');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Warning text');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return VisaMasterSettingsForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return VisaMasterSettingsTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListVisaMasterSettings::route('/'),
|
||||
'create' => CreateVisaMasterSettings::route('/create'),
|
||||
'edit' => EditVisaMasterSettings::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class SettingsCluster extends Cluster
|
||||
{
|
||||
protected static ?int $navigationSort = 100;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedCog8Tooth;
|
||||
|
||||
protected static ?SubNavigationPosition $subNavigationPosition = SubNavigationPosition::End;
|
||||
|
||||
24
app/Filament/Clusters/Users/UsersCluster.php
Normal file
24
app/Filament/Clusters/Users/UsersCluster.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\Users;
|
||||
|
||||
use BackedEnum;
|
||||
use Filament\Clusters\Cluster;
|
||||
use Filament\Pages\Enums\SubNavigationPosition;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class UsersCluster extends Cluster
|
||||
{
|
||||
protected static ?int $navigationSort = 6;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedUsers;
|
||||
|
||||
protected static string|BackedEnum|null $activeNavigationIcon = Heroicon::Users;
|
||||
|
||||
protected static ?SubNavigationPosition $subNavigationPosition = SubNavigationPosition::Top;
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('Users');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\VisaMasterPaymentOrderResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateVisaMasterPaymentOrder extends CreateRecord
|
||||
{
|
||||
protected static string $resource = VisaMasterPaymentOrderResource::class;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\VisaMasterPaymentOrderResource;
|
||||
use App\Modules\VisaMasterPaymentOrder\Filament\Actions\PayVisaMasterPaymentAction;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\ForceDeleteAction;
|
||||
use Filament\Actions\RestoreAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
use Illuminate\Contracts\Support\Htmlable;
|
||||
|
||||
class EditVisaMasterPaymentOrder extends EditRecord
|
||||
{
|
||||
protected static string $resource = VisaMasterPaymentOrderResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
PayVisaMasterPaymentAction::make(),
|
||||
DeleteAction::make(),
|
||||
ForceDeleteAction::make(),
|
||||
RestoreAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getTitle(): string|Htmlable
|
||||
{
|
||||
return __('Order details');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\VisaMasterPaymentOrderResource;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListVisaMasterPaymentOrders extends ListRecords
|
||||
{
|
||||
protected static string $resource = VisaMasterPaymentOrderResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Pages;
|
||||
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Schemas\VisaMasterPaymentOrderInfolist;
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\VisaMasterPaymentOrderResource;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Resources\Pages\ViewRecord;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
|
||||
class ViewVisaMasterPaymentOrder extends ViewRecord
|
||||
{
|
||||
protected static string $resource = VisaMasterPaymentOrderResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
EditAction::make()
|
||||
->icon(Heroicon::OutlinedPencil),
|
||||
];
|
||||
}
|
||||
|
||||
public function infolist(Schema $schema): Schema
|
||||
{
|
||||
return VisaMasterPaymentOrderInfolist::configure($schema);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Schemas;
|
||||
|
||||
use App\Modules\FilamentPermission\Repositories\FilamentPermissionRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\PhoneNumberVerification\Rules\PhoneNumberVerificationRule;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use App\Modules\TurkmenPassport\Repositories\TurkmenPassportRepository;
|
||||
use App\Modules\VisaMasterPaymentOrder\Models\VisaMasterPaymentOrder;
|
||||
use Filament\Forms\Components\Hidden;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Schemas\Components\Fieldset;
|
||||
use Filament\Schemas\Components\FusedGroup;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Components\Wizard;
|
||||
use Filament\Schemas\Components\Wizard\Step;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use RalphJSmit\Filament\Upload\Filament\Forms\Components\AdvancedFileUpload;
|
||||
|
||||
class VisaMasterPaymentOrderForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Hidden::make('user_id')->default(Auth::id()),
|
||||
|
||||
Section::make()
|
||||
->columnSpan(4)
|
||||
->columns(4)
|
||||
->disabled(fn (string $context): bool => FilamentPermissionRepository::forClients())
|
||||
->components([
|
||||
Select::make('status')
|
||||
->label(__('Status'))
|
||||
->options(OrderStatusRepository::statusValues())
|
||||
->default(OrderStatusRepository::defaultStatus())
|
||||
->native(false)
|
||||
->columnSpan(2),
|
||||
|
||||
Toggle::make('paid')
|
||||
->label(sprintf('%s (%s)', __('Paid'), __('This month')))
|
||||
->inline(false)
|
||||
->disabled(true)
|
||||
->onIcon(Heroicon::CheckCircle)
|
||||
->offIcon(Heroicon::XCircle)
|
||||
->onColor('success')
|
||||
->offColor('danger'),
|
||||
|
||||
RichEditor::make('notes')
|
||||
->label(__('Bellik'))
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
|
||||
Wizard::make([
|
||||
Step::make(__('Order type and bank'))
|
||||
->schema([
|
||||
Fieldset::make(__('Order type'))
|
||||
->schema([
|
||||
Select::make('type')
|
||||
->label(__('Type'))
|
||||
->options(VisaMasterPaymentOrder::applicationTypes())
|
||||
->native(false)
|
||||
->required(),
|
||||
]),
|
||||
|
||||
Fieldset::make(__('Location'))
|
||||
->schema([
|
||||
Select::make('region')
|
||||
->label(__('Region'))
|
||||
->options(RegionRepository::values())
|
||||
->live()
|
||||
->afterStateUpdated(fn (callable $set) => $set('branch_id', null))
|
||||
->required(),
|
||||
|
||||
Select::make('branch_id')
|
||||
->label(__('Branch'))
|
||||
->relationship('branch', 'name', function ($query, callable $get) {
|
||||
$query->orderByTranslation('name');
|
||||
|
||||
$region = $get('region');
|
||||
if ($region) {
|
||||
$query->where('region', $region);
|
||||
}
|
||||
})
|
||||
->required(),
|
||||
]),
|
||||
]),
|
||||
Step::make(__('Payment sender data'))
|
||||
->columns(8)
|
||||
->schema([
|
||||
TextInput::make('sender_full_name')
|
||||
->label(__('Name, Surname, Patronic name'))
|
||||
->columnSpan(4)
|
||||
->default(user()->fullName())
|
||||
->required(),
|
||||
|
||||
FusedGroup::make([
|
||||
Select::make('sender_passport_serie')
|
||||
->label(__('Passport serie'))
|
||||
->options(TurkmenPassportRepository::values())
|
||||
->native(false)
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->default(user()->getOption('passport_serie')),
|
||||
|
||||
TextInput::make('sender_passport_number')
|
||||
->label(__('Passport number'))
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->mask('999999')
|
||||
->default(user()->getOption('passport_id')),
|
||||
])
|
||||
->columnSpan(2)
|
||||
->label(__('Passport serie and number'))
|
||||
->columns(2),
|
||||
|
||||
TextInput::make('phone')
|
||||
->label(__('Phone'))
|
||||
->required()
|
||||
->mask('99 99 99 99')
|
||||
->prefix('+993')
|
||||
->rules([
|
||||
new PhoneNumberVerificationRule,
|
||||
])
|
||||
->columnSpan(2)
|
||||
->default(user()->phone),
|
||||
|
||||
TextInput::make('sender_deposit_account')
|
||||
->label(__('Deposit account'))
|
||||
->columnSpan(4)
|
||||
->required(),
|
||||
|
||||
TextInput::make('address')
|
||||
->label(__('Address'))
|
||||
->columnSpan(4)
|
||||
->required(),
|
||||
|
||||
Section::make(__('Files'))
|
||||
->description('PNG, JPEG, PDF')
|
||||
->columnSpanFull()
|
||||
->columns(2)
|
||||
->schema([
|
||||
AdvancedFileUpload::make('sender_passport_local')
|
||||
->spatieMediaLibrary(collection: 'sender_passport_local')
|
||||
->multiple(),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('sender_passport_international')
|
||||
->collection('sender_passport_international')
|
||||
->label(__('Ugradyja degişli Türkmenistandan çykmak we Türkmenistana girmek üçin pasportynyň asyl görnüşi we göçürmesi')),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('sender_travel_stamp_on_passport')
|
||||
->collection('sender_travel_stamp_on_passport')
|
||||
->label(__('Ugradyja degişli Türkmenistandan çykmak we Türkmenistana girmek üçin pasportyndaky daşary döwletine gidendigi we daşary döwlete barandygy baradaky (ştampyň) bellenen sahypasynyň göçürmesi'))
|
||||
->required(),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('sender_proof_of_kinship')
|
||||
->collection('sender_proof_of_kinship')
|
||||
->label(__('Ugradyjynyň we kabul edijiniň (talybyň) özara garyndaşlyk derejesini tassyklaýjy resminamalarynyň göçürmesi')),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('sender_passport_local_old')
|
||||
->collection('sender_passport_local_old')
|
||||
->label(__('Ugradyjy we kabul ediji (talyp) 2015-nji ýyldan soňra Türkmenistanyň raýatynyň pasportyny ikinji gezek alan bolsa, onda birinji gezek alan pasportynyň seriýasy baradaky maglumat')),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('sender_passport_local_old_replacement')
|
||||
->collection('sender_passport_local_old_replacement')
|
||||
->label(__('Ugradyjy we kabul ediji (talyp) 2015-nji ýyldan soňra Türkmenistanyň raýatynyň pasportyny ikinji gezek alandan soňra birinji gezek alan pasportynyň seriýasy baradaky maglumaty bilmeýän ,bolsa onda polisiýanyň degişli edaralaryndan birinji alan pasportynyň seriýasy baradaky güwänamasy')),
|
||||
]),
|
||||
]),
|
||||
|
||||
Step::make(__('Payee information'))
|
||||
->columns(8)
|
||||
->schema([
|
||||
TextInput::make('reciever_full_name')
|
||||
->label(__('Name, Surname, Patronic name'))
|
||||
->columnSpan(5)
|
||||
->required(),
|
||||
|
||||
FusedGroup::make([
|
||||
Select::make('reciever_passport_serie')
|
||||
->label(__('Passport serie'))
|
||||
->options(TurkmenPassportRepository::values())
|
||||
->native(false)
|
||||
->required()
|
||||
->columnSpan(1),
|
||||
|
||||
TextInput::make('reciever_passport_number')
|
||||
->label(__('Passport number'))
|
||||
->required()
|
||||
->columnSpan(1)
|
||||
->mask('999999'),
|
||||
])
|
||||
->columnSpan(3)
|
||||
->label(__('Passport serie and number'))
|
||||
->columns(2),
|
||||
|
||||
Section::make(__('Files'))
|
||||
->description('PNG, JPEG, PDF')
|
||||
->columnSpanFull()
|
||||
->columns(2)
|
||||
->schema([
|
||||
SpatieMediaLibraryFileUpload::make('receiver_requisite')
|
||||
->collection('receiver_requisite')
|
||||
->label(__('Talyba degişli walýuta "VISA" kartyň rekwizitleri'))
|
||||
->maxSize(4096)
|
||||
->columnSpan(1)
|
||||
->required(),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('receiver_document_stating_he_is_studying')
|
||||
->collection('receiver_document_stating_he_is_studying')
|
||||
->label(__('Talybyň daşary ýurt döwletiniň ýokary okuw mekdebinde okaýandygy baradaky güwänamasy'))
|
||||
->maxSize(4096)
|
||||
->openable()
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('receiver_ticket')
|
||||
->collection('receiver_ticket')
|
||||
->label(__('Talybyň bilediniň göçürmesi'))
|
||||
->maxSize(4096)
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('receiver_passport_local')
|
||||
->collection('receiver_passport_local')
|
||||
->label(__('Talyba degişli Türkmenistanyň raýatynyň (içki milli) pasportynyň asyl görnüşi we göçürmesi'))
|
||||
->maxSize(4096)
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('receiver_passport_international')
|
||||
->collection('receiver_passport_international')
|
||||
->label(__('Talybyň Türkmenistandan çykmak we Türkmenistana girmek üçin (zagran) pasportynyň göçürmesi'))
|
||||
->maxSize(4096)
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('receiver_visa')
|
||||
->collection('receiver_visa')
|
||||
->label(__('Talybyň Türkmenistandan çykmak we Türkmenistana girmek üçin pasportyndaky daşary ýurtda galyp okap bilýändigi baradaky berlen möhleti hereket edýän rugsatnamasynyň (wizasynyň) bellenen sahypasynyň göçürmesi'))
|
||||
->maxSize(4096)
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('receiver_travel_stamp_on_passport')
|
||||
->collection('receiver_travel_stamp_on_passport')
|
||||
->label(__('Talybyň Türkmenistandan çykmak we Türkmenistana girmek üçin pasportyndaky Türkmenistandan çykandygy we daşary ýurt döwletine girendigi baradaky ştamplaryň (seneli ştampyň) bellenen sahypasynyň göçürmesi'))
|
||||
->maxSize(4096)
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileUpload::make('receiver_document_stating_he_is_studying_2')
|
||||
->collection('receiver_document_stating_he_is_studying_2')
|
||||
->label(__('Talybyň daşary ýurt döwletiniň ýokary okuw mekdebinde okaýandygy baradaky güwänamasyndaky maglumatyň doly takyk däl ýagdaýynda takyk däl maglumatyň sebäpleri baradaky daşary ýurt döwletiniň ýokary okuw mekdebinden haty'))
|
||||
->maxSize(4096)
|
||||
->columnSpan(1),
|
||||
]),
|
||||
]),
|
||||
|
||||
])->columnSpanFull()->skippable(fn (string $context) => $context === 'edit'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Schemas;
|
||||
|
||||
use App\Filament\Infolists\Components\SpatieMediaLibraryFileEntry;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use App\Modules\TurkmenPassport\Repositories\TurkmenPassportRepository;
|
||||
use App\Modules\VisaMasterPaymentOrder\Models\VisaMasterPaymentOrder;
|
||||
use Filament\Infolists\Components\IconEntry;
|
||||
use Filament\Infolists\Components\TextEntry;
|
||||
use Filament\Schemas\Components\Fieldset;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Components\Tabs;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class VisaMasterPaymentOrderInfolist
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Section::make()
|
||||
->columnSpanFull()
|
||||
->columns(4)
|
||||
->components([
|
||||
TextEntry::make('unique_id')
|
||||
->label(__('Order ID'))
|
||||
->columnSpan(1)
|
||||
->extraAttributes(['style' => 'text-transform:uppercase;font-size:1.5em;font-weight:bold;']),
|
||||
|
||||
TextEntry::make('type')
|
||||
->label(__('Payment type'))
|
||||
->extraAttributes(['style' => 'text-transform:uppercase;font-size:1.5em;font-weight:bold;']),
|
||||
|
||||
TextEntry::make('status')
|
||||
->label(__('Status'))
|
||||
->formatStateUsing(fn (string $state) => OrderStatusRepository::statusFormatted($state))
|
||||
->extraAttributes(['style' => 'text-transform:uppercase;font-size:1.2em;font-weight:bold;'])
|
||||
->color(OrderStatusRepository::statusColorMatching()),
|
||||
|
||||
IconEntry::make('paid')
|
||||
->label(sprintf('%s (%s)', __('Paid'), __('This month')))
|
||||
->boolean()
|
||||
->trueIcon(Heroicon::CheckCircle)
|
||||
->falseIcon(Heroicon::XCircle)
|
||||
->trueColor('success')
|
||||
->falseColor('danger'),
|
||||
|
||||
Fieldset::make(__('Location'))
|
||||
->schema([
|
||||
TextEntry::make('region')
|
||||
->label(__('Region'))
|
||||
->formatStateUsing(fn (string $state): string => RegionRepository::label($state)),
|
||||
|
||||
TextEntry::make('branch.name')
|
||||
->label(__('Branch'))
|
||||
->placeholder('-'),
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextEntry::make('notes')
|
||||
->label(__('Bellik'))
|
||||
->html()
|
||||
->visible(fn (VisaMasterPaymentOrder $record): bool => ! is_null($record->notes) && $record->notes != '' && $record->notes != '<p></p>' && Str::length($record->notes) > 7)
|
||||
->columnSpan(2)
|
||||
->placeholder('-'),
|
||||
]),
|
||||
|
||||
Tabs::make('Order Information')
|
||||
->tabs([
|
||||
Tab::make(__('Payment sender data'))
|
||||
->columns(8)
|
||||
->schema([
|
||||
Fieldset::make(__('Data'))
|
||||
->columnSpan(8)
|
||||
->columns(8)
|
||||
->schema([
|
||||
TextEntry::make('sender_full_name')
|
||||
->label(__('Name, Surname, Patronic name'))
|
||||
->columnSpan(4)
|
||||
->placeholder('-'),
|
||||
|
||||
TextEntry::make('sender_passport')
|
||||
->label(__('Passport serie and number'))
|
||||
->formatStateUsing(function ($record) {
|
||||
$serie = TurkmenPassportRepository::values()[$record->sender_passport_serie] ?? $record->sender_passport_serie;
|
||||
|
||||
return $serie.' '.$record->sender_passport_number;
|
||||
})
|
||||
->columnSpan(2)
|
||||
->placeholder('-'),
|
||||
|
||||
TextEntry::make('phone')
|
||||
->label(__('Phone'))
|
||||
->formatStateUsing(fn ($state) => '+993 '.$state)
|
||||
->columnSpan(2)
|
||||
->placeholder('-'),
|
||||
|
||||
TextEntry::make('sender_deposit_account')
|
||||
->label(__('Deposit account'))
|
||||
->columnSpan(4)
|
||||
->placeholder('-'),
|
||||
|
||||
TextEntry::make('address')
|
||||
->label(__('Address'))
|
||||
->columnSpan(4)
|
||||
->placeholder('-'),
|
||||
]),
|
||||
|
||||
Section::make(__('Files'))
|
||||
->description('PNG, JPEG, PDF')
|
||||
->columnSpanFull()
|
||||
->columns(2)
|
||||
->schema([
|
||||
SpatieMediaLibraryFileEntry::make('sender_passport_local')
|
||||
->collection('sender_passport_local')
|
||||
->label(__('Ugradyja degişli Türkmenistanyň raýatynyň (içki milli) pasportynyň asyl görnüşi we göçürmesi')),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('sender_passport_international')
|
||||
->collection('sender_passport_international')
|
||||
->label(__('Ugradyja degişli Türkmenistandan çykmak we Türkmenistana girmek üçin pasportynyň asyl görnüşi we göçürmesi')),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('sender_travel_stamp_on_passport')
|
||||
->collection('sender_travel_stamp_on_passport')
|
||||
->label(__('Ugradyja degişli Türkmenistandan çykmak we Türkmenistana girmek üçin pasportyndaky daşary döwletine gidendigi we daşary döwlete barandygy baradaky (ştampyň) bellenen sahypasynyň göçürmesi')),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('sender_proof_of_kinship')
|
||||
->collection('sender_proof_of_kinship')
|
||||
->label(__('Ugradyjynyň we kabul edijiniň (talybyň) özara garyndaşlyk derejesini tassyklaýjy resminamalarynyň göçürmesi')),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('sender_passport_local_old')
|
||||
->collection('sender_passport_local_old')
|
||||
->label(__('Ugradyjy we kabul ediji (talyp) 2015-nji ýyldan soňra Türkmenistanyň raýatynyň pasportyny ikinji gezek alan bolsa, onda birinji gezek alan pasportynyň seriýasy baradaky maglumat')),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('sender_passport_local_old_replacement')
|
||||
->collection('sender_passport_local_old_replacement')
|
||||
->label(__('Ugradyjy we kabul ediji (talyp) 2015-nji ýyldan soňra Türkmenistanyň raýatynyň pasportyny ikinji gezek alandan soňra birinji gezek alan pasportynyň seriýasy baradaky maglumaty bilmeýän ,bolsa onda polisiýanyň degişli edaralaryndan birinji alan pasportynyň seriýasy baradaky güwänamasy')),
|
||||
]),
|
||||
]),
|
||||
|
||||
Tab::make(__('Payee information'))
|
||||
->columns(8)
|
||||
->schema([
|
||||
TextEntry::make('reciever_full_name')
|
||||
->label(__('Name, Surname, Patronic name'))
|
||||
->columnSpan(5)
|
||||
->placeholder('-'),
|
||||
|
||||
TextEntry::make('reciever_passport')
|
||||
->label(__('Passport serie and number'))
|
||||
->formatStateUsing(function ($record) {
|
||||
$serie = TurkmenPassportRepository::values()[$record->reciever_passport_serie] ?? $record->reciever_passport_serie;
|
||||
|
||||
return $serie.' '.$record->reciever_passport_number;
|
||||
})
|
||||
->columnSpan(3)
|
||||
->placeholder('-'),
|
||||
|
||||
Section::make(__('Files'))
|
||||
->description('PNG, JPEG, PDF')
|
||||
->columnSpanFull()
|
||||
->columns(2)
|
||||
->schema([
|
||||
SpatieMediaLibraryFileEntry::make('receiver_requisite')
|
||||
->collection('receiver_requisite')
|
||||
->label(__('Talyba degişli walýuta "VISA" kartyň rekwizitleri'))
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('receiver_document_stating_he_is_studying')
|
||||
->collection('receiver_document_stating_he_is_studying')
|
||||
->label(__('Talybyň daşary ýurt döwletiniň ýokary okuw mekdebinde okaýandygy baradaky güwänamasy'))
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('receiver_ticket')
|
||||
->collection('receiver_ticket')
|
||||
->label(__('Talybyň bilediniň göçürmesi'))
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('receiver_passport_local')
|
||||
->collection('receiver_passport_local')
|
||||
->label(__('Talyba degişli Türkmenistanyň raýatynyň (içki milli) pasportynyň asyl görnüşi we göçürmesi'))
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('receiver_passport_international')
|
||||
->collection('receiver_passport_international')
|
||||
->label(__('Talybyň Türkmenistandan çykmak we Türkmenistana girmek üçin (zagran) pasportynyň göçürmesi'))
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('receiver_visa')
|
||||
->collection('receiver_visa')
|
||||
->label(__('Talybyň Türkmenistandan çykmak we Türkmenistana girmek üçin pasportyndaky daşary ýurtda galyp okap bilýändigi baradaky berlen möhleti hereket edýän rugsatnamasynyň (wizasynyň) bellenen sahypasynyň göçürmesi'))
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('receiver_travel_stamp_on_passport')
|
||||
->collection('receiver_travel_stamp_on_passport')
|
||||
->label(__('Talybyň Türkmenistandan çykmak we Türkmenistana girmek üçin pasportyndaky Türkmenistandan çykandygy we daşary ýurt döwletine girendigi baradaky ştamplaryň (seneli ştampyň) bellenen sahypasynyň göçürmesi'))
|
||||
->columnSpan(1),
|
||||
|
||||
SpatieMediaLibraryFileEntry::make('receiver_document_stating_he_is_studying_2')
|
||||
->collection('receiver_document_stating_he_is_studying_2')
|
||||
->label(__('Talybyň daşary ýurt döwletiniň ýokary okuw mekdebinde okaýandygy baradaky güwänamasyndaky maglumatyň doly takyk däl ýagdaýynda takyk däl maglumatyň sebäpleri baradaky daşary ýurt döwletiniň ýokary okuw mekdebinden haty'))
|
||||
->columnSpan(1),
|
||||
]),
|
||||
]),
|
||||
])->columnSpanFull(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Tables;
|
||||
|
||||
use App\Modules\DefaultQueryForResourceIndex\Repositories\DefaultQueryForResourceIndexRepository;
|
||||
use App\Modules\OrderStatus\Repositories\OrderStatusRepository;
|
||||
use App\Modules\Region\Repositories\RegionRepository;
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Actions\ForceDeleteBulkAction;
|
||||
use Filament\Actions\RestoreBulkAction;
|
||||
use Filament\Actions\ViewAction;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Filters\TrashedFilter;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class VisaMasterPaymentOrdersTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->modifyQueryUsing(function (Builder $query) {
|
||||
DefaultQueryForResourceIndexRepository::make($query);
|
||||
})
|
||||
->defaultSort('created_at', direction: 'desc')
|
||||
->columns([
|
||||
TextColumn::make('id')
|
||||
->label(__('ID'))
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('type')
|
||||
->label(__('Type'))
|
||||
->formatStateUsing(fn (string $state) => Str::upper($state)),
|
||||
|
||||
TextColumn::make('status')
|
||||
->label(__('Status'))
|
||||
->color(OrderStatusRepository::statusColorMatching())
|
||||
->formatStateUsing(fn (string $state) => OrderStatusRepository::statusFormatted($state))
|
||||
->badge(),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->label(__('Created At'))
|
||||
->dateTime()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('region')
|
||||
->label(__('Region'))
|
||||
->formatStateUsing(fn (string $state): string => RegionRepository::label($state))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('branch.name')
|
||||
->label(__('Branch'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('sender_full_name')
|
||||
->label(__('Full Name'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('phone')
|
||||
->label(__('Phone'))
|
||||
->searchable(),
|
||||
|
||||
IconColumn::make('paid')
|
||||
->label(sprintf('%s (%s)', __('Paid'), __('This month')))
|
||||
->boolean(),
|
||||
|
||||
])
|
||||
->filters([
|
||||
TrashedFilter::make(),
|
||||
])
|
||||
->recordActions([
|
||||
ViewAction::make(),
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
ForceDeleteBulkAction::make(),
|
||||
RestoreBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders;
|
||||
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Pages\CreateVisaMasterPaymentOrder;
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Pages\EditVisaMasterPaymentOrder;
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Pages\ListVisaMasterPaymentOrders;
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Pages\ViewVisaMasterPaymentOrder;
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Schemas\VisaMasterPaymentOrderForm;
|
||||
use App\Filament\Clusters\VisaMasterPayments\Resources\VisaMasterPaymentOrders\Tables\VisaMasterPaymentOrdersTable;
|
||||
use App\Filament\Clusters\VisaMasterPayments\VisaMasterPaymentsCluster;
|
||||
use App\Modules\VisaMasterPaymentOrder\Models\VisaMasterPaymentOrder;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
|
||||
class VisaMasterPaymentOrderResource extends Resource
|
||||
{
|
||||
protected static ?int $navigationSort = 1;
|
||||
|
||||
protected static ?string $model = VisaMasterPaymentOrder::class;
|
||||
|
||||
protected static ?string $cluster = VisaMasterPaymentsCluster::class;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'unique_id';
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = 'icon-visa-plain';
|
||||
|
||||
public static function getNavigationGroup(): ?string
|
||||
{
|
||||
return __('Visa/Master payments');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('Visa/Master payment');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Visa/Master payments');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return VisaMasterPaymentOrderForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return VisaMasterPaymentOrdersTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListVisaMasterPaymentOrders::route('/'),
|
||||
'create' => CreateVisaMasterPaymentOrder::route('/create'),
|
||||
'view' => ViewVisaMasterPaymentOrder::route('/{record}/view'),
|
||||
'edit' => EditVisaMasterPaymentOrder::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query for the record route binding
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder<\App\Modules\VisaMasterPaymentOrder\Models\VisaMasterPaymentOrder>
|
||||
*/
|
||||
public static function getRecordRouteBindingEloquentQuery(): Builder
|
||||
{
|
||||
return parent::getRecordRouteBindingEloquentQuery()
|
||||
->withoutGlobalScopes([
|
||||
SoftDeletingScope::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Clusters\VisaMasterPayments;
|
||||
|
||||
use BackedEnum;
|
||||
use Filament\Clusters\Cluster;
|
||||
use Filament\Pages\Enums\SubNavigationPosition;
|
||||
|
||||
class VisaMasterPaymentsCluster extends Cluster
|
||||
{
|
||||
protected static ?int $navigationSort = 3;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = 'icon-visa-plain';
|
||||
|
||||
protected static ?SubNavigationPosition $subNavigationPosition = SubNavigationPosition::Top;
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('International payments');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Infolists\Components;
|
||||
|
||||
use Closure;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Infolists\Components\Entry;
|
||||
use Filament\Support\Concerns\HasMediaFilter;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\MediaLibrary\MediaCollections\Models\Collections\MediaCollection;
|
||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||
use Throwable;
|
||||
|
||||
class SpatieMediaLibraryFileEntry extends Entry
|
||||
{
|
||||
use HasMediaFilter;
|
||||
|
||||
public function getViewMediaActionName(): string
|
||||
{
|
||||
return 'view_media_'.$this->getName();
|
||||
}
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->registerActions([
|
||||
Action::make($this->getViewMediaActionName())
|
||||
->label(__('Watch Full'))
|
||||
->modalContent(fn (array $arguments) => view('filament.infolists.components.image-modal', ['url' => $arguments['url']]))
|
||||
->modalSubmitAction(false)
|
||||
->modalCancelAction(false)
|
||||
->modalWidth('5xl'),
|
||||
]);
|
||||
}
|
||||
|
||||
protected string $view = 'filament.infolists.components.spatie-media-library-file-entry';
|
||||
|
||||
protected string|Closure|null $collection = null;
|
||||
|
||||
protected string|Closure|null $conversion = null;
|
||||
|
||||
protected string|Closure $visibility = 'private';
|
||||
|
||||
protected bool|Closure $isDownloadable = true;
|
||||
|
||||
protected bool|Closure $isPreviewable = true;
|
||||
|
||||
public function collection(string|Closure|null $collection): static
|
||||
{
|
||||
$this->collection = $collection;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function conversion(string|Closure|null $conversion): static
|
||||
{
|
||||
$this->conversion = $conversion;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function visibility(string|Closure $visibility): static
|
||||
{
|
||||
$this->visibility = $visibility;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function downloadable(bool|Closure $condition = true): static
|
||||
{
|
||||
$this->isDownloadable = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function previewable(bool|Closure $condition = true): static
|
||||
{
|
||||
$this->isPreviewable = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCollection(): ?string
|
||||
{
|
||||
return $this->evaluate($this->collection);
|
||||
}
|
||||
|
||||
public function getConversion(): ?string
|
||||
{
|
||||
return $this->evaluate($this->conversion);
|
||||
}
|
||||
|
||||
public function getVisibility(): string
|
||||
{
|
||||
return (string) $this->evaluate($this->visibility);
|
||||
}
|
||||
|
||||
public function isDownloadable(): bool
|
||||
{
|
||||
return (bool) $this->evaluate($this->isDownloadable);
|
||||
}
|
||||
|
||||
public function isPreviewable(): bool
|
||||
{
|
||||
return (bool) $this->evaluate($this->isPreviewable);
|
||||
}
|
||||
|
||||
public function getMediaUrl(Media $media, ?string $conversion = null): string
|
||||
{
|
||||
if ($this->getVisibility() === 'private') {
|
||||
try {
|
||||
return $media->getTemporaryUrl(
|
||||
now()->addMinutes(30)->endOfHour(),
|
||||
$conversion ?? '',
|
||||
);
|
||||
} catch (Throwable $exception) {
|
||||
// This driver does not support creating temporary URLs.
|
||||
}
|
||||
}
|
||||
|
||||
return $media->getUrl($conversion ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the media for the entry
|
||||
*
|
||||
* @return Collection<array-key, Media>
|
||||
*/
|
||||
public function getMedia(): Collection
|
||||
{
|
||||
$record = $this->getRecord();
|
||||
|
||||
if (! $record) {
|
||||
return collect([]);
|
||||
}
|
||||
|
||||
if ($this->hasStateRelationship($record)) {
|
||||
$record = $this->getStateRelationshipResults($record);
|
||||
}
|
||||
|
||||
$records = Arr::wrap($record);
|
||||
|
||||
$allMedia = collect([]);
|
||||
|
||||
$collection = $this->getCollection() ?? 'default';
|
||||
|
||||
foreach ($records as $record) {
|
||||
/** @var Model $record */
|
||||
$media = $record->getRelationValue('media');
|
||||
|
||||
if (! $media) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filteredMedia = $media
|
||||
->when(
|
||||
is_string($collection),
|
||||
fn (MediaCollection $mediaCollection) => $mediaCollection->filter(fn (Media $media): bool => $media->getAttributeValue('collection_name') === $collection),
|
||||
)
|
||||
->when(
|
||||
$this->hasMediaFilter(),
|
||||
fn (Collection $media) => $this->filterMedia($media)
|
||||
)
|
||||
->sortBy('order_column');
|
||||
|
||||
$allMedia = $allMedia->merge($filteredMedia);
|
||||
}
|
||||
|
||||
return $allMedia;
|
||||
}
|
||||
}
|
||||
11
app/Filament/Resources/Users/Pages/CreateUser.php
Normal file
11
app/Filament/Resources/Users/Pages/CreateUser.php
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Users\Pages;
|
||||
|
||||
use App\Filament\Resources\Users\UserResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateUser extends CreateRecord
|
||||
{
|
||||
protected static string $resource = UserResource::class;
|
||||
}
|
||||
19
app/Filament/Resources/Users/Pages/EditUser.php
Normal file
19
app/Filament/Resources/Users/Pages/EditUser.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Users\Pages;
|
||||
|
||||
use App\Filament\Resources\Users\UserResource;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditUser extends EditRecord
|
||||
{
|
||||
protected static string $resource = UserResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
19
app/Filament/Resources/Users/Pages/ListUsers.php
Normal file
19
app/Filament/Resources/Users/Pages/ListUsers.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Users\Pages;
|
||||
|
||||
use App\Filament\Resources\Users\UserResource;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListUsers extends ListRecords
|
||||
{
|
||||
protected static string $resource = UserResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
72
app/Filament/Resources/Users/Schemas/UserForm.php
Normal file
72
app/Filament/Resources/Users/Schemas/UserForm.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Users\Schemas;
|
||||
|
||||
use App\Modules\PhoneNumberVerification\Rules\PhoneNumberVerificationRule;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Schemas\Schema;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class UserForm
|
||||
{
|
||||
public static function configure(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->columns(6)
|
||||
->components([
|
||||
TextInput::make('name')
|
||||
->label(__('Full Name'))
|
||||
->required()
|
||||
->columnSpan(3),
|
||||
|
||||
TextInput::make('username')
|
||||
->label(__('Username'))
|
||||
->required()
|
||||
->unique(ignoreRecord: true)
|
||||
->columnSpan(3),
|
||||
|
||||
TextInput::make('phone')
|
||||
->label(__('Phone'))
|
||||
->unique(ignoreRecord: true)
|
||||
->mask('99 99 99 99')
|
||||
->prefix('+993')
|
||||
->dehydrateStateUsing(fn ($state) => unMaskTurkmenNumber($state))
|
||||
->rules([
|
||||
new PhoneNumberVerificationRule,
|
||||
])
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('email')
|
||||
->label(__('Email'))
|
||||
->email()
|
||||
->unique(ignoreRecord: true)
|
||||
->columnSpan(2),
|
||||
|
||||
TextInput::make('password')
|
||||
->label(__('Password'))
|
||||
->password()
|
||||
->dehydrateStateUsing(fn ($state) => Hash::make($state))
|
||||
->dehydrated(fn ($state) => filled($state))
|
||||
->required(fn (string $context): bool => $context === 'create')
|
||||
->columnSpan(2),
|
||||
|
||||
Select::make('roles')
|
||||
->label(__('Roles'))
|
||||
->relationship('roles', 'name')
|
||||
->multiple()
|
||||
->preload()
|
||||
->native(false)
|
||||
->columnSpan(3),
|
||||
|
||||
Select::make('branches')
|
||||
->label(__('Branches'))
|
||||
->relationship('branches', 'name', fn (Builder $query) => $query->distinct('id')->orderBy('id'))
|
||||
->multiple()
|
||||
->preload()
|
||||
->native(false)
|
||||
->columnSpan(3),
|
||||
]);
|
||||
}
|
||||
}
|
||||
57
app/Filament/Resources/Users/Tables/UsersTable.php
Normal file
57
app/Filament/Resources/Users/Tables/UsersTable.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Users\Tables;
|
||||
|
||||
use Filament\Actions\BulkActionGroup;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class UsersTable
|
||||
{
|
||||
public static function configure(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->defaultSort('created_at', direction: 'desc')
|
||||
->columns([
|
||||
TextColumn::make('id'),
|
||||
|
||||
TextColumn::make('first_name')
|
||||
->label(__('First name'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('last_name')
|
||||
->label(__('Last name'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('username')
|
||||
->label(__('Username'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('phone')
|
||||
->label(__('Phone number'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
|
||||
TextColumn::make('email')
|
||||
->label(__('Email'))
|
||||
->searchable()
|
||||
->sortable(),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([
|
||||
BulkActionGroup::make([
|
||||
DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
70
app/Filament/Resources/Users/UserResource.php
Normal file
70
app/Filament/Resources/Users/UserResource.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\Users;
|
||||
|
||||
use App\Filament\Clusters\Users\UsersCluster;
|
||||
use App\Filament\Resources\Users\Pages\CreateUser;
|
||||
use App\Filament\Resources\Users\Pages\EditUser;
|
||||
use App\Filament\Resources\Users\Pages\ListUsers;
|
||||
use App\Filament\Resources\Users\Schemas\UserForm;
|
||||
use App\Filament\Resources\Users\Tables\UsersTable;
|
||||
use App\Models\User;
|
||||
use BackedEnum;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Support\Icons\Heroicon;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class UserResource extends Resource
|
||||
{
|
||||
protected static ?string $model = User::class;
|
||||
|
||||
protected static ?string $cluster = UsersCluster::class;
|
||||
|
||||
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedUsers;
|
||||
|
||||
protected static string|BackedEnum|null $activeNavigationIcon = Heroicon::Users;
|
||||
|
||||
protected static ?string $recordTitleAttribute = 'phone';
|
||||
|
||||
public static function getNavigationLabel(): string
|
||||
{
|
||||
return __('Users');
|
||||
}
|
||||
|
||||
public static function getModelLabel(): string
|
||||
{
|
||||
return __('User');
|
||||
}
|
||||
|
||||
public static function getPluralModelLabel(): string
|
||||
{
|
||||
return __('Users');
|
||||
}
|
||||
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return UserForm::configure($schema);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return UsersTable::configure($table);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListUsers::route('/'),
|
||||
'create' => CreateUser::route('/create'),
|
||||
'edit' => EditUser::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ function logDB(): void
|
||||
*/
|
||||
function user(): User
|
||||
{
|
||||
abort_unless(Auth::check(), 'not-authenticated');
|
||||
abort_unless(Auth::check(), 401, 'Unauthorized');
|
||||
|
||||
/** @var \App\Models\User */
|
||||
$user = Auth::user();
|
||||
|
||||
69
app/Http/Controllers/MigrationController.php
Normal file
69
app/Http/Controllers/MigrationController.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Database\Seeders\Migrators\ActionEventsMigrator;
|
||||
use Database\Seeders\Migrators\BranchUserMigrator;
|
||||
use Database\Seeders\Migrators\CurrencyRatesMigrator;
|
||||
use Database\Seeders\Migrators\LoanOrderRequiredDocsMigrator;
|
||||
use Database\Seeders\Migrators\LoanOrdersMigrator;
|
||||
use Database\Seeders\Migrators\LoanTypesMigrator;
|
||||
use Database\Seeders\Migrators\MediaMigrator;
|
||||
use Database\Seeders\Migrators\ProvincesMigrator;
|
||||
use Database\Seeders\Migrators\BranchesMigrator;
|
||||
use Database\Seeders\Migrators\UsersMigrator;
|
||||
use Database\Seeders\Migrators\CardStatesMigrator;
|
||||
use Database\Seeders\Migrators\CardTypesMigrator;
|
||||
use Database\Seeders\Migrators\VisaMasterPaymentOrdersMigrator;
|
||||
use Database\Seeders\Migrators\VerificationsMigrator;
|
||||
use Database\Seeders\Migrators\PersonalAccessTokensMigrator;
|
||||
use Database\Seeders\Migrators\CardOrdersMigrator;
|
||||
use Database\Seeders\Migrators\VisaMasterSettingsMigrator;
|
||||
use Database\Seeders\Migrators\CardPinOrdersMigrator;
|
||||
use Database\Seeders\Migrators\ModelHasRolesMigrator;
|
||||
use Database\Seeders\Migrators\OnlinePaymentsMigrator;
|
||||
|
||||
class MigrationController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return $this->test();
|
||||
|
||||
$migrators = [
|
||||
new ActionEventsMigrator(),
|
||||
new UsersMigrator(),
|
||||
new ProvincesMigrator(),
|
||||
new BranchesMigrator(),
|
||||
new BranchUserMigrator(),
|
||||
new CardStatesMigrator(),
|
||||
new CardTypesMigrator(),
|
||||
new VerificationsMigrator(),
|
||||
new CurrencyRatesMigrator(),
|
||||
new LoanOrderRequiredDocsMigrator(),
|
||||
new PersonalAccessTokensMigrator(),
|
||||
new LoanTypesMigrator(),
|
||||
new CardOrdersMigrator(),
|
||||
new CardPinOrdersMigrator(),
|
||||
new LoanOrdersMigrator(),
|
||||
new ModelHasRolesMigrator(),
|
||||
new VisaMasterPaymentOrdersMigrator(),
|
||||
new OnlinePaymentsMigrator(),
|
||||
|
||||
new MediaMigrator(),
|
||||
];
|
||||
|
||||
foreach ($migrators as $migrator) {
|
||||
$migrator->migrate();
|
||||
}
|
||||
|
||||
return 'done';
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
(new OnlinePaymentsMigrator())->migrate();
|
||||
|
||||
return 'done';
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Filament\Notifications\Notification;
|
||||
use Illuminate\Http\Request;
|
||||
use Joaopaulolndev\FilamentEditProfile\Pages\EditProfilePage;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -19,6 +20,11 @@ class EnsureProfileIsFilled
|
||||
/** @var \App\Models\User */
|
||||
$user = $request->user();
|
||||
|
||||
// Skip if user is system user...
|
||||
if ($user->isSystemUser()) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
// 1. If user is not logged in, or profile is already complete, do nothing.
|
||||
// (Based on your logic: must_fill_profile == true means complete)
|
||||
if (! $user->must_fill_profile) {
|
||||
@@ -26,10 +32,13 @@ class EnsureProfileIsFilled
|
||||
}
|
||||
|
||||
// 3. Define the 'safe' routes
|
||||
$profilePageClass = EditProfilePage::class; // <-- !! IMPORTANT: Change to your page
|
||||
$profilePageClass = EditProfilePage::class;
|
||||
$profilePageUrl = $profilePageClass::getUrl();
|
||||
|
||||
$panelId = filament()->getCurrentPanel()->getId();
|
||||
/** @var \Filament\Panel */
|
||||
$panel = filament()->getCurrentPanel();
|
||||
|
||||
$panelId = $panel->getId();
|
||||
$logoutRouteName = "filament.{$panelId}.auth.logout";
|
||||
|
||||
// 4. Check for 'safe' conditions
|
||||
@@ -50,6 +59,11 @@ class EnsureProfileIsFilled
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title(__('Please update your profile'))
|
||||
->send();
|
||||
|
||||
// 6. If not, redirect them to the profile page.
|
||||
// Filament's SPA mode will intercept this 302 redirect
|
||||
// and navigate without a full page reload.
|
||||
|
||||
28
app/Http/Middleware/EnsureUserHasRole.php
Normal file
28
app/Http/Middleware/EnsureUserHasRole.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class EnsureUserHasRole
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
// if user does not have any role, add role "client"
|
||||
/** @var \App\Models\User */
|
||||
$user = $request->user();
|
||||
|
||||
if ($user->roles->count() == 0) {
|
||||
$user->assignRole('client');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -18,18 +18,19 @@ use Illuminate\Contracts\View\View;
|
||||
use Joaopaulolndev\FilamentEditProfile\Concerns\HasSort;
|
||||
use Livewire\Component;
|
||||
|
||||
class UserPassportFields extends Component implements HasForms
|
||||
class UserProfileFields extends Component implements HasForms
|
||||
{
|
||||
use HasSort;
|
||||
use InteractsWithForms;
|
||||
|
||||
/** @var array<string, mixed> */
|
||||
public ?array $data = [];
|
||||
|
||||
protected static int $sort = 10;
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
$this->form->fill();
|
||||
$this->form->fill(); // @phpstan-ignore-line
|
||||
}
|
||||
|
||||
public function form(Schema $schema): Schema
|
||||
@@ -42,7 +43,7 @@ class UserPassportFields extends Component implements HasForms
|
||||
->description(__('Fill your account profile information'))
|
||||
->schema([
|
||||
TextInput::make('first_name')
|
||||
->label(__('First name'))
|
||||
->label(__('Name'))
|
||||
->string()
|
||||
->maxLength(255)
|
||||
->default(user()->first_name)
|
||||
@@ -50,7 +51,7 @@ class UserPassportFields extends Component implements HasForms
|
||||
->required(),
|
||||
|
||||
TextInput::make('last_name')
|
||||
->label(__('Last name'))
|
||||
->label(__('Surname'))
|
||||
->string()
|
||||
->maxLength(255)
|
||||
->default(user()->last_name)
|
||||
@@ -88,6 +89,7 @@ class UserPassportFields extends Component implements HasForms
|
||||
->label(__('Email'))
|
||||
->email()
|
||||
->default(user()->email)
|
||||
->unique(ignoreRecord: false)
|
||||
->columnSpan(2),
|
||||
|
||||
Fieldset::make(__('Passport'))
|
||||
@@ -160,7 +162,7 @@ class UserPassportFields extends Component implements HasForms
|
||||
{
|
||||
try {
|
||||
/** @var array{first_name: string, last_name: string, patronic_name: null|string, born_at: string, phone: string, email: string, passport_serie: string, passport_id: string, passport_given_at: string, born_place: string, passport_given_by: string, passport_address: string, real_address: string} */
|
||||
$data = $this->form->getState();
|
||||
$data = $this->form->getState(); // @phpstan-ignore-line
|
||||
|
||||
user()->update([
|
||||
'first_name' => $data['first_name'],
|
||||
@@ -179,15 +181,13 @@ class UserPassportFields extends Component implements HasForms
|
||||
'must_fill_profile' => false,
|
||||
]);
|
||||
|
||||
$this->dispatch('refresh-topbar');
|
||||
Notification::make()
|
||||
->success()
|
||||
->title(__('Profile updated'))
|
||||
->send();
|
||||
} catch (Halt $exception) {
|
||||
return;
|
||||
}
|
||||
|
||||
Notification::make()
|
||||
->success()
|
||||
->title(__('Profile updated'))
|
||||
->send();
|
||||
}
|
||||
|
||||
public function render(): View
|
||||
@@ -3,11 +3,14 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Modules\UserAdjustments\Traits\UserAdjustments;
|
||||
use Filament\Models\Contracts\FilamentUser;
|
||||
use Filament\Models\Contracts\HasAvatar;
|
||||
use Filament\Panel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
use Spatie\Permission\Traits\HasRoles;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
@@ -19,14 +22,14 @@ use Spatie\Permission\Traits\HasRoles;
|
||||
* @property Date|null $created_at
|
||||
* @property Date|null $updated_at
|
||||
*/
|
||||
class User extends Authenticatable
|
||||
class User extends Authenticatable implements FilamentUser, HasAvatar
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasFactory;
|
||||
|
||||
use HasRoles;
|
||||
use Notifiable;
|
||||
use UserAdjustments;
|
||||
use HasApiTokens;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
@@ -48,4 +51,20 @@ class User extends Authenticatable
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* Can access panel
|
||||
*/
|
||||
public function canAccessPanel(Panel $panel): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the avatar URL for the user.
|
||||
*/
|
||||
public function getFilamentAvatarUrl(): ?string
|
||||
{
|
||||
return '/assets/images/avatar.png';
|
||||
}
|
||||
}
|
||||
|
||||
64
app/Modules/ActivityLog/ActivityLogModule.php
Normal file
64
app/Modules/ActivityLog/ActivityLogModule.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\ActivityLog;
|
||||
|
||||
use App\Modules\Makeable;
|
||||
use App\Modules\ModuleContract;
|
||||
|
||||
class ActivityLogModule implements ModuleContract
|
||||
{
|
||||
use Makeable;
|
||||
|
||||
/**
|
||||
* Module is enabled
|
||||
*/
|
||||
protected bool $enabled = true;
|
||||
|
||||
/**
|
||||
* Check if is module enabled
|
||||
*/
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable module
|
||||
*/
|
||||
public function disable(): void
|
||||
{
|
||||
$this->enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable module
|
||||
*/
|
||||
public function enable(): void
|
||||
{
|
||||
$this->enabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if module has a filament resource
|
||||
*/
|
||||
public function hasFilamentResource(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get module composer requirements
|
||||
*/
|
||||
public function getComposerRequirements(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get module composer suggestions
|
||||
*/
|
||||
public function getComposerSuggestions(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\ActivityLog\Repositories;
|
||||
|
||||
class ActivityLogRepository {}
|
||||
10
app/Modules/AppHelpers/Contracts/HasFailedMethod.php
Normal file
10
app/Modules/AppHelpers/Contracts/HasFailedMethod.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\AppHelpers\Contracts;
|
||||
|
||||
interface HasFailedMethod
|
||||
{
|
||||
public function failed(): bool;
|
||||
|
||||
public function successful(): bool;
|
||||
}
|
||||
142
app/Modules/AppHelpers/Repositories/DateHelper.php
Normal file
142
app/Modules/AppHelpers/Repositories/DateHelper.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\AppHelpers\Repositories;
|
||||
|
||||
class DateHelper
|
||||
{
|
||||
/**
|
||||
* Month as number
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public static function monthsAsNumber(): array
|
||||
{
|
||||
$month = [];
|
||||
|
||||
for ($m = 1; $m <= 12; $m++) {
|
||||
$month[] = str_pad(strval($m), 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
return $month;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static numbers for months
|
||||
*
|
||||
* @return array<int|string, string>
|
||||
*/
|
||||
public static function staticNumberMonths(): array
|
||||
{
|
||||
return [
|
||||
'01' => '01',
|
||||
'02' => '02',
|
||||
'03' => '03',
|
||||
'04' => '04',
|
||||
'05' => '05',
|
||||
'06' => '06',
|
||||
'07' => '07',
|
||||
'08' => '08',
|
||||
'09' => '09',
|
||||
'10' => '10',
|
||||
'11' => '11',
|
||||
'12' => '12',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Years until
|
||||
*
|
||||
* @param int|int $max
|
||||
* @return array<string|int, string|int>
|
||||
*/
|
||||
public static function yearsUntil(int $max = 50): array
|
||||
{
|
||||
$years = [];
|
||||
|
||||
$currentData = 2024;
|
||||
|
||||
for ($i = 0; $i <= $max; $i++) {
|
||||
$years[] = intval($currentData) + $i;
|
||||
}
|
||||
|
||||
return $years;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static numbers for years
|
||||
*
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public static function staticNumberYears(): array
|
||||
{
|
||||
return [
|
||||
'2024' => '2024',
|
||||
'2025' => '2025',
|
||||
'2026' => '2026',
|
||||
'2027' => '2027',
|
||||
'2028' => '2028',
|
||||
'2029' => '2029',
|
||||
'2030' => '2030',
|
||||
'2031' => '2031',
|
||||
'2032' => '2032',
|
||||
'2033' => '2033',
|
||||
'2034' => '2034',
|
||||
'2035' => '2035',
|
||||
'2036' => '2036',
|
||||
'2037' => '2037',
|
||||
'2038' => '2038',
|
||||
'2039' => '2039',
|
||||
'2040' => '2040',
|
||||
'2041' => '2041',
|
||||
'2042' => '2042',
|
||||
'2043' => '2043',
|
||||
'2044' => '2044',
|
||||
'2045' => '2045',
|
||||
'2046' => '2046',
|
||||
'2047' => '2047',
|
||||
'2048' => '2048',
|
||||
'2049' => '2049',
|
||||
'2050' => '2050',
|
||||
'2051' => '2051',
|
||||
'2052' => '2052',
|
||||
'2053' => '2053',
|
||||
'2054' => '2054',
|
||||
'2055' => '2055',
|
||||
'2056' => '2056',
|
||||
'2057' => '2057',
|
||||
'2058' => '2058',
|
||||
'2059' => '2059',
|
||||
'2060' => '2060',
|
||||
'2061' => '2061',
|
||||
'2062' => '2062',
|
||||
'2063' => '2063',
|
||||
'2064' => '2064',
|
||||
'2065' => '2065',
|
||||
'2066' => '2066',
|
||||
'2067' => '2067',
|
||||
'2068' => '2068',
|
||||
'2069' => '2069',
|
||||
'2070' => '2070',
|
||||
'2071' => '2071',
|
||||
'2072' => '2072',
|
||||
'2073' => '2073',
|
||||
'2074' => '2074',
|
||||
'2075' => '2075',
|
||||
'2076' => '2076',
|
||||
'2077' => '2077',
|
||||
'2078' => '2078',
|
||||
'2079' => '2079',
|
||||
'2080' => '2080',
|
||||
'2081' => '2081',
|
||||
'2082' => '2082',
|
||||
'2083' => '2083',
|
||||
'2084' => '2084',
|
||||
'2085' => '2085',
|
||||
'2086' => '2086',
|
||||
'2087' => '2087',
|
||||
'2088' => '2088',
|
||||
'2089' => '2089',
|
||||
'2090' => '2090',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ use Illuminate\Http\Response;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class LoginController extends Controller
|
||||
{
|
||||
@@ -113,7 +114,7 @@ class LoginController extends Controller
|
||||
protected function validateLogin(Request $request): void
|
||||
{
|
||||
$request->validate([
|
||||
$this->username() => ['required', 'string', 'max:250'],
|
||||
$this->username() => ['required', 'string', 'max:250', Rule::notIn('65999990', 'ulanyjy_ady')],
|
||||
'password' => ['required', 'string', 'max:250'],
|
||||
]);
|
||||
}
|
||||
@@ -159,6 +160,10 @@ class LoginController extends Controller
|
||||
$request->session()->put('auth.password_confirmed_at', time());
|
||||
}
|
||||
|
||||
if ($user->roles->count() == 0) {
|
||||
$user->assignRole('client');
|
||||
}
|
||||
|
||||
return $this->sendLoginResponse($request);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,8 @@ class RegisterController extends Controller
|
||||
'must_fill_profile' => true,
|
||||
]);
|
||||
|
||||
$user->assignRole('client');
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
@@ -170,4 +172,14 @@ class RegisterController extends Controller
|
||||
|
||||
return redirect(config()->string('module.base-auth.redirect_path'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resend verification
|
||||
*/
|
||||
public function resendVerification(): RedirectResponse
|
||||
{
|
||||
sendSMSVerification((string) user()->phone);
|
||||
|
||||
return to_route('sms-verification');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,18 @@ class RedirectIfUserPhoneIsUnVerfied
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if (Auth::check() && is_null($request->user()?->phone_verified_at)) {
|
||||
return redirect()->route('sms-verification');
|
||||
if (Auth::check()) {
|
||||
/** @var \App\Models\User */
|
||||
$user = $request->user();
|
||||
|
||||
// Skip if user is system user...
|
||||
if ($user->isSystemUser()) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
if (is_null($user->phone_verified_at)) {
|
||||
return redirect()->route('sms-verification');
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
||||
@@ -16,8 +16,13 @@ class RedirectIfUserPhoneIsVerfied
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
if (Auth::check() && ! is_null($request->user()?->phone_verified_at)) {
|
||||
return redirect()->route(config()->string('module.base-auth.redirect_path'));
|
||||
if (Auth::check()) {
|
||||
/** @var \App\Models\User */
|
||||
$user = $request->user();
|
||||
|
||||
if (! is_null($user->phone_verified_at) || $user->isSystemUser()) {
|
||||
return redirect(config()->string('module.base-auth.redirect_path'));
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
||||
@@ -29,4 +29,6 @@ return [
|
||||
'change_phone_label' => 'Telefon belgini üýtgetmek',
|
||||
'go_back' => 'Yza',
|
||||
'successfully_changed_phone' => 'Telefon belgiňiz üýtgedildi',
|
||||
'resend' => 'Täze tassyklaýyş belgi ugratmak',
|
||||
'phone_or_username_placeholder' => 'meselem: 65999990 yada ulanyjy_ady',
|
||||
];
|
||||
|
||||
@@ -49,11 +49,12 @@ async function login(event) {
|
||||
id="username"
|
||||
type="text"
|
||||
name="username"
|
||||
placeholder="+99365999990 {{ __('or') }} {{ __('module.base-auth::base.username') }}"
|
||||
placeholder="65999990 {{ __('or') }} {{ __('module.base-auth::base.username') }}"
|
||||
autofocus=""
|
||||
value="{{ old('username') }}"
|
||||
>
|
||||
|
||||
<span class="text-gray-500 text-xs">{{ __('module.base-auth::base.phone_or_username_placeholder') }}</span>
|
||||
<span id="username-error-box" class="text-red-500 text-italic error-box"></span>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -61,11 +61,22 @@
|
||||
|
||||
<span id="phone-error-box" class="text-red-500 text-italic error-box"></span>
|
||||
</div>
|
||||
<button type="submit" class="w-full flex justify-center shadow relative bg-primary-500 hover:bg-primary-400 text-white dark:text-gray-900 w-full flex justify-center cursor-pointer rounded text-sm font-bold focus:outline-none focus:ring ring-primary-200 dark:ring-gray-600 inline-flex items-center justify-center h-9 px-3 mb-3 w-full flex justify-center shadow relative bg-primary-500 hover:bg-primary-400 text-white dark:text-gray-900 w-full flex justify-center">
|
||||
<button type="button" class="w-full flex justify-center shadow relative bg-primary-500 hover:bg-primary-400 text-white dark:text-gray-900 w-full flex justify-center cursor-pointer rounded text-sm font-bold focus:outline-none focus:ring ring-primary-200 dark:ring-gray-600 inline-flex items-center justify-center h-9 px-3 mb-3 w-full flex justify-center shadow relative bg-primary-500 hover:bg-primary-400 text-white dark:text-gray-900 w-full flex justify-center">
|
||||
<span class=""><span>{{ __('module.base-auth::base.change_number') }}</span></span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
|
||||
<div class="flex justify-center items-center mb-6">
|
||||
<form id="resend-verification-form" action="{{ route('resend-verification') }}" method="POST">
|
||||
@csrf
|
||||
</form>
|
||||
|
||||
<span id="resend-verification-trigger" class="text-center font-normal mr-4 underline cursor-pointer d-none" onclick="requestNewVerification()">
|
||||
{{ __('module.base-auth::base.resend') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{{-- Verification form --}}
|
||||
<form method="POST" action="{{ route('sms-verification') }}" id="verification-form">
|
||||
@csrf
|
||||
@@ -81,7 +92,8 @@
|
||||
@endforeach
|
||||
@endif
|
||||
</div>
|
||||
<button type="submit" class="w-full flex justify-center shadow relative bg-primary-500 hover:bg-primary-400 text-white dark:text-gray-900 w-full flex justify-center cursor-pointer rounded text-sm font-bold focus:outline-none focus:ring ring-primary-200 dark:ring-gray-600 inline-flex items-center justify-center h-9 px-3 mb-3 w-full flex justify-center shadow relative bg-primary-500 hover:bg-primary-400 text-white dark:text-gray-900 w-full flex justify-center">
|
||||
|
||||
<button type="submit" class="w-full justify-center shadow relative bg-primary-500 hover:bg-primary-400 text-white dark:text-gray-900 cursor-pointer rounded text-sm font-bold focus:outline-none focus:ring ring-primary-200 dark:ring-gray-600 inline-flex items-center h-9 px-3 mb-3 bg-primary-500 hover:bg-primary-400">
|
||||
<span class=""><span>{{ __('module.base-auth::base.submit') }}</span></span>
|
||||
</button>
|
||||
</form>
|
||||
@@ -98,9 +110,15 @@ let changePhoneform = $_ID('change-phone-form')
|
||||
let verificationForm = $_ID('verification-form')
|
||||
let changePhoneButton = $_ID('change-phone-button')
|
||||
let goBackButton = $_ID('go-back-button')
|
||||
let resendVerificationTrigger = $_ID('resend-verification-trigger')
|
||||
let resendVerificationForm = $_ID('resend-verification-form')
|
||||
|
||||
ready(() => {
|
||||
new Inputmask("+(\\9\\93)-99-99-99-99").mask(phoneField);
|
||||
new Inputmask("+(\\9\\93)-99-99-99-99").mask(phoneField)
|
||||
|
||||
setTimeout(() => {
|
||||
show(resendVerificationTrigger)
|
||||
}, 5000)
|
||||
})
|
||||
|
||||
async function goBack() {
|
||||
@@ -125,7 +143,7 @@ async function changePhone(event) {
|
||||
if (response.errors) {
|
||||
loopObject(response.errors, item => addValidationClasses(item))
|
||||
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
removeValidationClasess()
|
||||
@@ -138,7 +156,11 @@ async function changePhone(event) {
|
||||
showCancelButton: false,
|
||||
})
|
||||
|
||||
window.location.href = response.url;
|
||||
window.location.href = response.url
|
||||
}
|
||||
|
||||
function requestNewVerification() {
|
||||
resendVerificationForm.submit()
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -20,9 +20,10 @@ Route::middleware(['web', 'guest'])->group(function () {
|
||||
Route::middleware(['web', 'auth', RedirectIfUserPhoneIsVerfied::class])->group(function () {
|
||||
Route::post('change-phone', [RegisterController::class, 'changePhone'])->name('change-phone');
|
||||
|
||||
Route::post('resend-verification', [RegisterController::class, 'resendVerification'])->name('resend-verification');
|
||||
|
||||
Route::get('sms-verification', [RegisterController::class, 'smsVerification'])
|
||||
->name('sms-verification');
|
||||
|
||||
Route::post('sms-verification', [RegisterController::class, 'verifySmsCode']);
|
||||
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user