diff --git a/app/Console/Commands/stubs/make-module/model.stub b/app/Console/Commands/stubs/make-module/model.stub index 00d7909..801bbfa 100644 --- a/app/Console/Commands/stubs/make-module/model.stub +++ b/app/Console/Commands/stubs/make-module/model.stub @@ -7,5 +7,5 @@ use Illuminate\Database\Eloquent\Model; class $CLASS_NAME$ extends Model { - use HasUuids; + } diff --git a/app/Modules/ApiAuth/Controllers/ApiAuthController.php b/app/Modules/ApiAuth/Controllers/ApiAuthController.php index d8bbd2b..776f768 100644 --- a/app/Modules/ApiAuth/Controllers/ApiAuthController.php +++ b/app/Modules/ApiAuth/Controllers/ApiAuthController.php @@ -19,10 +19,10 @@ class ApiAuthController extends Controller { UserRepo::registerUser($request); - sendSMSVerification($request->phone_number); + sendSMSVerification($request->phone); return response()->json([ - 'message' => sprintf('%s: %s', __('Verification code sent to'), $request->phone_number), + 'message' => sprintf('%s: %s', __('Verification code sent to'), $request->phone), ], 201); } @@ -31,10 +31,10 @@ class ApiAuthController extends Controller */ public function login(AuthLoginRequest $request): JsonResponse { - sendSMSVerification($request->phone_number); + sendSMSVerification($request->phone); return response()->json([ - 'message' => sprintf('%s: %s', __('Verification code sent to'), $request->phone_number), + 'message' => sprintf('%s: %s', __('Verification code sent to'), $request->phone), ], 201); } @@ -43,7 +43,7 @@ class ApiAuthController extends Controller */ public function verify(AuthVerifyRequest $request): JsonResponse { - $user = User::where('phone_number', $request->phone_number)->firstOrFail(); + $user = User::where('phone', $request->phone)->firstOrFail(); return response()->json([ 'message' => $user->createToken(bin2hex(random_bytes(20)))->plainTextToken, diff --git a/app/Modules/ApiAuth/Requests/AuthLoginRequest.php b/app/Modules/ApiAuth/Requests/AuthLoginRequest.php index f2eaf43..db8b93f 100644 --- a/app/Modules/ApiAuth/Requests/AuthLoginRequest.php +++ b/app/Modules/ApiAuth/Requests/AuthLoginRequest.php @@ -20,7 +20,7 @@ class AuthLoginRequest extends FormRequest * @var int * @example 65707012 */ - 'phone_number' => ['required', 'integer', 'between:61000000,71999999'], + 'phone' => ['required', 'integer', 'between:61000000,71999999'], ]; } } diff --git a/app/Modules/ApiAuth/Requests/AuthRegisterRequest.php b/app/Modules/ApiAuth/Requests/AuthRegisterRequest.php index a55064d..619c8fa 100644 --- a/app/Modules/ApiAuth/Requests/AuthRegisterRequest.php +++ b/app/Modules/ApiAuth/Requests/AuthRegisterRequest.php @@ -20,7 +20,7 @@ class AuthRegisterRequest extends FormRequest * @var int * @example 65707012 */ - 'phone_number' => ['required', 'integer', 'between:61000000,71999999', 'unique:users,phone_number'], + 'phone' => ['required', 'integer', 'between:61000000,71999999', 'unique:users,phone'], /** * User's name diff --git a/app/Modules/ApiAuth/Requests/AuthVerifyRequest.php b/app/Modules/ApiAuth/Requests/AuthVerifyRequest.php index 3cb7793..f43bde1 100644 --- a/app/Modules/ApiAuth/Requests/AuthVerifyRequest.php +++ b/app/Modules/ApiAuth/Requests/AuthVerifyRequest.php @@ -18,18 +18,16 @@ class AuthVerifyRequest extends FormRequest /** * Phone number to authenticate * - * @var int * @example 65707012 */ - 'phone_number' => ['required', 'integer', 'between:61000000,65999999'], + 'phone' => ['required', 'integer', 'between:61000000,65999999'], /** * Verification code (OTP) * - * @var int * @example 432123 */ - 'code' => ['required', 'integer', new PhoneCodeVerification($this->phone_number)], + 'code' => ['required', 'integer', new PhoneCodeVerification($this->phone)], ]; } } diff --git a/app/Modules/VisaMasterPaymentOrder/Database/Migrations/2024_09_04_180340_create_visa_master_payment_orders_table.php.php b/app/Modules/VisaMasterPaymentOrder/Database/Migrations/2024_09_04_180340_create_visa_master_payment_orders_table.php.php new file mode 100644 index 0000000..a6c41d4 --- /dev/null +++ b/app/Modules/VisaMasterPaymentOrder/Database/Migrations/2024_09_04_180340_create_visa_master_payment_orders_table.php.php @@ -0,0 +1,48 @@ +id(); + $table->string('unique_id')->nullable()->unique(); + + $table->string('type')->nullable(); + $table->string('passport_name')->nullable(); + $table->string('passport_surname')->nullable(); + $table->string('phone')->nullable(); + $table->string('email')->nullable(); + $table->string('region')->nullable(); + + $table->foreignId('branch_id')->nullable()->constrained('branches')->cascadeOnDelete(); + $table->foreignId('user_id')->nullable()->constrained('users')->cascadeOnDelete(); + + $table->string('address')->nullable(); + + $table->json('sender_datas')->nullable(); + $table->json('payment_reciever')->nullable(); + + $table->json('documents')->nullable(); + + $table->string('status')->nullable(); + $table->string('notes')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('visa_master_payment_orders'); + } +}; diff --git a/app/Modules/VisaMasterPaymentOrder/Models/VisaMasterPaymentOrder.php b/app/Modules/VisaMasterPaymentOrder/Models/VisaMasterPaymentOrder.php new file mode 100644 index 0000000..563cc8c --- /dev/null +++ b/app/Modules/VisaMasterPaymentOrder/Models/VisaMasterPaymentOrder.php @@ -0,0 +1,76 @@ + + */ + protected $casts = [ + 'sender_datas' => 'array', + 'payment_reciever' => 'array', + ]; + + /** + * Media conversions + * + * @param Media|null $media + */ + public function registerMediaConversions(?Media $media = null): void + { + $this->addMediaConversion('thumb') + ->width(200) + ->height(200); + } + + /** + * Media collections + */ + public function registerMediaCollections(): void + { + $this->addMediaCollection('main'); + } + + /** + * Branch + */ + public function branch(): BelongsTo + { + return $this->belongsTo(Branch::class); + } + + /** + * Get applications types + */ + public static function applicationTypes(): array + { + return [ + 'visa' => __('Visa'), + 'master' => __('Master'), + ]; + } +} diff --git a/app/Modules/VisaMasterPaymentOrder/Nova/Resources/Concerns/VisaMasterPaymentOrderFieldsForIndex.php b/app/Modules/VisaMasterPaymentOrder/Nova/Resources/Concerns/VisaMasterPaymentOrderFieldsForIndex.php new file mode 100644 index 0000000..1c96bf5 --- /dev/null +++ b/app/Modules/VisaMasterPaymentOrder/Nova/Resources/Concerns/VisaMasterPaymentOrderFieldsForIndex.php @@ -0,0 +1,66 @@ +hide(), + + Text::make(__('ID'), 'unique_id')->sortable(), + + Select::make(__('Ýüztutmanyň görnüşi'), 'type') + ->fullWidth() + ->searchable() + ->rules('required') + ->displayUsingLabels() + ->options(VisaMasterPaymentOrder::applicationTypes()), + + DateTime::make(__('Created at'), 'created_at') + ->turkmenDateTime(), + + Select::make(__('Region'), 'region') + ->displayUsingLabels() + ->options(RegionRepo::values()) + ->canSeeWhen('isAdmin', $resource) + ->sortable(), + + BelongsTo::make(__('Branch'), 'branch', Branch::class) + ->canSeeWhen('isAdmin', $resource) + ->filterable() + ->sortable(), + + Text::make(__('Name'), 'passport_name'), + + Text::make(__('Surname'), 'passport_surname'), + + Text::make(__('Phone'), 'phone'), + + Badge::make(__('Status'), 'status') + ->map(OrderRepo::statusClasses()) + ->addTypes([ + 'primary' => 'dark:bg-gray-900 bg-gray-600 text-white', + ]) + ->labels(OrderRepo::statusValues()) + ->withIcons() + ->icons(OrderRepo::statusIcons()) + ->sortable(), + ]; + } +} diff --git a/app/Modules/VisaMasterPaymentOrder/Nova/Resources/NovaVisaMasterPaymentOrder.php b/app/Modules/VisaMasterPaymentOrder/Nova/Resources/NovaVisaMasterPaymentOrder.php new file mode 100644 index 0000000..df7a2bb --- /dev/null +++ b/app/Modules/VisaMasterPaymentOrder/Nova/Resources/NovaVisaMasterPaymentOrder.php @@ -0,0 +1,241 @@ + + */ + public static $model = \App\Modules\VisaMasterPaymentOrder\Models\VisaMasterPaymentOrder::class; + + /** + * The single value that should be used to represent the resource when being displayed. + * + * @var string + */ + public static $title = 'unique_id'; + + /** + * The columns that should be searched. + * + * @var array + */ + public static $search = [ + 'unique_id', 'passport_name', 'passport_surname', 'phone', + ]; + + /** + * Get the displayable label of the resource. + */ + public static function label(): string + { + return sprintf( + '%s (%s)', + __('Visa/Master payments'), + Str::lower(__('For students')) + ); + } + + /** + * Get the displayable singular label of the resource. + */ + public static function singularLabel(): string + { + return sprintf( + '%s (%s)', + __('Visa/Master payment'), + Str::lower(__('For students')) + ); + } + + /** + * After resource created + * + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param \Illuminate\Database\Eloquent\Model $model + */ + public static function afterCreate(NovaRequest $request, Model $model): void + { + $model->update(['unique_id' => CardOrderRepo::fillUniqueId($model)]); + } + + /** + * Get the fields for index. + */ + public function fieldsForIndex(): array + { + return VisaMasterPaymentOrderFieldsForIndex::make($this); + } + + /** + * Get the fields displayed by the resource. + * + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @return array + */ + public function fields(NovaRequest $request): array + { + return [ + ID::hidden(), + + Hidden::make('user_id') + ->default(auth()->id()) + ->hideWhenUpdating(), + + new Panel(__('New :resource', ['resource' => $this->singularLabel()]), [ + Text::make(__('ID'), 'unique_id') + ->exceptOnForms(), + + Select::make(__('Status'), 'status') + ->displayUsingLabels() + ->searchable() + ->options(OrderRepo::statusValues()) + ->default(OrderRepo::defaultStatus()) + ->fullWidth() + ->hideFromDetail() + ->rules('required') + ->canSeeWhen('systemUser', $this), + + Badge::make(__('Status'), 'status') + ->map(OrderRepo::statusClasses()) + ->addTypes([ + 'primary' => 'dark:bg-gray-900 bg-gray-600 text-white', + ]) + ->labels(OrderRepo::statusValues()) + ->withIcons() + ->icons(OrderRepo::statusIcons()), + + Text::make(__('Note'), 'notes') + ->fullWidth() + ->canSeeWhen('systemUser', $this), + ]), + + new Panel(__('Application type'), [ + Select::make(__('Application type'), 'type') + ->fullWidth() + ->searchable() + ->rules('required') + ->displayUsingLabels() + ->options(VisaMasterPaymentOrder::applicationTypes()), + ]), + + new Panel(__('Location'), [ + Select::make(__('Region'), 'region') + ->fullWidth() + ->displayUsingLabels() + ->searchable() + ->options(RegionRepo::values()) + ->default(RegionRepo::default()) + ->rules('required') + ->sortable(), + + Select::make(__('Branch'), 'branch_id') + ->fullWidth() + ->displayUsingLabels() + ->searchable() + ->dependsOn('region', NovaRepo::dependsOnRegion('region', Branch::class)) + ->rules('required') + ->sortable(), + ]), + + new Panel(__('Personal data'), [ + Text::make(__('Passport name'), 'passport_name') + ->fullWidth() + ->rules('required', 'string', 'max:255'), + + Text::make(__('Passport surname'), 'passport_surname') + ->fullWidth() + ->rules('required', 'string', 'max:255'), + + NovaInputmask::make(__('Phone'), 'phone') + ->fullWidth() + ->phonenumber('TM') + ->rules('required', 'max:255') + ->hideFromIndex(), + + Text::make(__('Email'), 'email') + ->fullWidth() + ->rules('nullable', 'max:255', 'email') + ->hideFromIndex(), + + Text::make(__('Current Residence'), 'address') + ->fullWidth() + ->rules('required', 'string', 'max:255') + ->hideFromIndex(), + ]), + + new Panel(__('Payment'), [ + SimpleRepeatable::make(__('Payment sender data'), 'sender_datas', [ + Select::make(__('Passport serie'), 'passport_serie') + ->displayUsingLabels() + ->searchable() + ->options(PassportRepo::values()) + ->rules('required') + ->sortable(), + + NovaInputmask::make(__('Passport number'), 'passport_number') + ->mask('999999') + ->rules('required', 'max:255'), + + Text::make( + name: sprintf('%s %s %s', __('Name'), __('Surname'), __('Patronic name')), + attribute: 'full_name' + ) + ->rules('required', 'max:255'), + ])->minRows(1)->rules('required'), + + SimpleRepeatable::make('Tölegi kabul edijiniň maglumatlary', 'payment_reciever', [ + Select::make(__('Passport serie'), 'passport_serie') + ->displayUsingLabels() + ->searchable() + ->options(PassportRepo::values()) + ->rules('required') + ->sortable(), + + NovaInputmask::make(__('Passport number'), 'passport_number') + ->mask('999999') + ->rules('required', 'max:255'), + + Text::make( + name: sprintf('%s %s %s', __('Name'), __('Surname'), __('Patronic name')), + attribute: 'full_name' + ), + ])->maxRows(1)->minRows(1)->rules('required'), + + Files::make('Talap edilýän resminamalar', 'main') + ->conversionOnIndexView('thumb') + ->rules('required') + ->required() + ->hideFromIndex(), + ]), + ]; + } +} diff --git a/app/Providers/NovaServiceProvider.php b/app/Providers/NovaServiceProvider.php index 13b54fc..b71889a 100644 --- a/app/Providers/NovaServiceProvider.php +++ b/app/Providers/NovaServiceProvider.php @@ -146,6 +146,7 @@ class NovaServiceProvider extends NovaApplicationServiceProvider public function setupAssets(): void { Nova::style('additional', resource_path('css/vendor/nova/css/additional.css')); + Nova::script('additional', resource_path('js/vendor/nova/js/additional.js')); } /** diff --git a/app/Repos/System/Nova/NovaMenuRepo.php b/app/Repos/System/Nova/NovaMenuRepo.php index 3728883..51712d4 100644 --- a/app/Repos/System/Nova/NovaMenuRepo.php +++ b/app/Repos/System/Nova/NovaMenuRepo.php @@ -3,6 +3,7 @@ namespace App\Repos\System\Nova; use App\Modules\Swiftpayment\Nova\Resources\NovaSwiftpayment; +use App\Modules\VisaMasterPaymentOrder\Nova\Resources\NovaVisaMasterPaymentOrder; use App\Nova\Dashboards\Main; use App\Nova\Resources\Branch\Branch; use App\Nova\Resources\Order\Card\CardOrder; @@ -52,6 +53,8 @@ class NovaMenuRepo MenuGroup::make(__('Swift payments'), [ MenuItem::resource(NovaSwiftpayment::class) ->name(sprintf('%s (%s)', __('International payments'), __('Visa, Master, Sber, WU'))), + + MenuItem::resource(NovaVisaMasterPaymentOrder::class), ])->collapsedByDefault(), ])->icon('ticket')->collapsedByDefault(), diff --git a/app/Repos/UserRepo.php b/app/Repos/UserRepo.php index aa2ff10..9e3ef99 100644 --- a/app/Repos/UserRepo.php +++ b/app/Repos/UserRepo.php @@ -15,7 +15,7 @@ class UserRepo public static function registerUser(Request $request): User { return User::create([ - 'phone_number' => $request->phone_number, + 'phone' => $request->phone, 'name' => $request->name, 'username' => static::generateUsername($request->name), 'locale' => app()->getLocale(), diff --git a/app/Rules/PhoneCodeVerification.php b/app/Rules/PhoneCodeVerification.php index 467c381..dd575d2 100644 --- a/app/Rules/PhoneCodeVerification.php +++ b/app/Rules/PhoneCodeVerification.php @@ -9,7 +9,7 @@ use Illuminate\Contracts\Validation\ValidationRule; class PhoneCodeVerification implements ValidationRule { public function __construct( - protected int|string $phone, + protected null|int|string $phone, ) {} /** @@ -19,6 +19,12 @@ class PhoneCodeVerification implements ValidationRule */ public function validate(string $attribute, mixed $value, Closure $fail): void { + if (is_null($this->phone)) { + $fail(__('Could not parse phone number')); + + return; + } + $verification = Verification::where('username', $this->phone) ->where('code', $value) ->first(); diff --git a/lang/tk.json b/lang/tk.json index b2e3ec5..2dc081b 100644 --- a/lang/tk.json +++ b/lang/tk.json @@ -126,9 +126,12 @@ "Passport given by": "Kim tarapyndan berildi", "Passport id": "Pasport belgisi", "Passport serie": "Pasport seriýasy", + "Passport name": "Pasportdaky ady", + "Passport surname": "Pasportdaky familiýa", "Password": "Açar sözi", - "Patronic name": "Ataňyzyň ady", + "Patronic name": "Atasynyň ady", "Payload Too Large": "Loadük gaty uly", + "Payment": "Töleg", "Payment Required": "Töleg talap edilýär", "Pending": "Garaşylýar", "Permanent Redirect": "Hemişelik gönükdirme", @@ -176,7 +179,7 @@ "Showing": "Görkezmek", "Single": "Öýlenmedik/Durmuşa çykmadyk", "SSL Handshake Failed": "SSL el çarpmak şowsuz boldy", - "Surname": "Familiýa", + "Surname": "Familiýasy", "Switching Protocols": "Protokollary çalyşmak", "System": "Ulgam", "Tax": "Salgyt", @@ -287,5 +290,10 @@ "Swift payments": "Swift tölegler", "Swift payment": "Swift töleg", "International payments": "Halkara tölegler", - "Visa, Master, Sber, WU": "Visa, Master, Sber, WU" + "Visa, Master, Sber, WU": "Visa, Master, Sber, WU", + "Visa/Master payment": "Visa/Master tölegler", + "Visa/Master payments": "Visa/Master tölegleri", + "For students": "Talyplar üçin", + "Application type": "Ýüztutmanyň görnüşi", + "Payment sender data": "Tölegi ugradyjynyň maglumatlar" } diff --git a/resources/css/vendor/nova/css/additional.css b/resources/css/vendor/nova/css/additional.css index 1f15523..e04ad13 100644 --- a/resources/css/vendor/nova/css/additional.css +++ b/resources/css/vendor/nova/css/additional.css @@ -28,3 +28,9 @@ dialog a { /*div[data-popper-placement=bottom-start] {*/ /* display: contents;*/ /*}*/ + + +button[dusk="update-and-continue-editing-button"], +button[dusk="create-and-add-another-button"] { + display: none; +} diff --git a/resources/js/vendor/nova/js/additional.js b/resources/js/vendor/nova/js/additional.js new file mode 100644 index 0000000..e69de29 diff --git a/routes/api.php b/routes/api.php index 83f3aa7..b56c031 100644 --- a/routes/api.php +++ b/routes/api.php @@ -20,3 +20,9 @@ Route::post('auth/login', [ApiAuthController::class, 'login']); Route::post('auth/verify', [ApiAuthController::class, 'verify']); Route::middleware('auth:sanctum') ->post('auth/delete-user', [ApiAuthController::class, 'delete']); + +Route::middleware(['auth:sanctum', 'banned'])->group(function () { + // Profile... + // Route::get('profile', [ProfileController::class, 'index']); + // Route::post('profile', [ProfileController::class, 'store']); +});