feat: implement register logic and make register page dynamic

This commit is contained in:
2026-08-16 11:30:44 +03:30
parent a394aa79e0
commit c78b52b6f2
3 changed files with 266 additions and 89 deletions
@@ -2,8 +2,17 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\Enums\UserStatus;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\Auth\RegisterPostRequest;
use App\Models\File;
use App\Models\Province;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
class RegisterController extends Controller class RegisterController extends Controller
{ {
@@ -13,11 +22,89 @@ class RegisterController extends Controller
$withOutHeader = true; $withOutHeader = true;
$withOutFooter = true; $withOutFooter = true;
return view('auth.register' , compact('title' , 'withOutHeader' , 'withOutFooter')); $provinces = Province::where('status', 1)
->orderBy('name')
->pluck('name', 'id');
return view('auth.register' , compact('title' , 'withOutHeader' , 'withOutFooter' , 'provinces'));
} }
public function post() public function post(RegisterPostRequest $request)
{ {
$data = $request->validated();
DB::beginTransaction();
try {
$fileId = null;
if ($request->hasFile('avatar')) {
$image = $request->file('avatar');
$imageName = time() . '_' . rand(11111, 99999) . '.' . $image->extension();
$path = $image->storeAs(
'user_avatar',
$imageName,
'public'
);
$file = File::create([
'name' => $imageName,
'original_name' => $image->getClientOriginalName(),
'extension' => $image->extension(),
'size' => $image->getSize(),
'path' => $path,
]);
$fileId = $file->id;
}
$user = User::create([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'file_id' => $fileId,
'province_id' => $data['province_id'] ?? null,
'city_id' => $data['city_id'] ?? null,
'national_code' => $data['national_code'],
'gender' => $data['gender'],
'marital_status' => $data['marital_status'],
'spouse_name' => $data['spouse_name'] ?? null,
'mobile' => $data['mobile'],
'email' => $data['email'],
'username' => $data['username'],
'password' => Hash::make($data['password']),
'status' => UserStatus::ENABLE->value,
]);
DB::commit();
Auth::login($user);
return redirect()
->route('index')
->with('success', 'ثبت‌نام شما با موفقیت انجام شد.');
} catch (\Exception $exception) {
DB::rollBack();
if (isset($path) && Storage::disk('public')->exists($path)) {
Storage::disk('public')->delete($path);
}
return back()
->withInput()
->with('error', 'ثبت‌نام با خطا مواجه شد. لطفاً دوباره تلاش کنید.');
}
} }
} }
+64 -11
View File
@@ -2,8 +2,11 @@
namespace App\Http\Requests\Auth; namespace App\Http\Requests\Auth;
use App\Enums\UserGender;
use App\Enums\UserMarital;
use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
class RegisterPostRequest extends FormRequest class RegisterPostRequest extends FormRequest
{ {
@@ -41,19 +44,69 @@ class RegisterPostRequest extends FormRequest
'required', 'required',
'string', 'string',
'digits:10', 'digits:10',
'regex:/^[0-9]{10}$/',
'unique:users,national_code' 'unique:users,national_code'
], ],
'gender' => [], 'gender' => [
'marital_status' => [], 'required',
'spouse_name' => [], 'integer',
'mobile' => [], Rule::enum(UserGender::class),
'email' => [], ],
'username' => [], 'marital_status' => [
'avatar' => [], 'required',
'password' => [], 'integer',
'password_confirmation' => [], Rule::enum(UserMarital::class),
'user_province' => [], ],
'user_city' => [], 'spouse_name' => [
'nullable',
'string',
'min:5',
'max:255',
'persian_alpha'
],
'mobile' => [
'required',
'string',
'ir_mobile:zero'
],
'email' => [
'required',
'email',
'max:150',
'unique:users,email'
],
'username' => [
'required',
'string',
'regex:/^[a-zA-Z0-9]+$/',
'alpha_num',
'min:8',
'max:100',
'unique:users,username'
],
'avatar' => [
'nullable',
'image',
'mimes:jpg,png,jpeg,webp',
'max:800'
],
'password' => [
'required',
'min:8',
'max:255',
'alpha_num',
'confirmed'
],
'user_province' => [
'nullable',
'integer',
'exists:provinces,id'
],
'user_city' => [
'nullable',
'integer',
'exists:cities,id'
]
]; ];
} }
} }
+89 -52
View File
@@ -15,7 +15,12 @@
<div class="login-area py-120"> <div class="login-area py-120">
<div class="container"> <div class="container">
<!-- چون تعداد فیلدها زیاد شده، عرض کانتینر رو از col-md-5 به col-md-8 یا 9 تغییر دادم تا فضا باز بشه --> @if(session('error'))
<span style="color: red" >{{session('error')}}</span>
@endif
@if(session('success'))
<span style="color: red" >{{session('success')}}</span>
@endif
<div class="col-md-8 mx-auto"> <div class="col-md-8 mx-auto">
<div class="login-form"> <div class="login-form">
<div class="login-header"> <div class="login-header">
@@ -25,13 +30,14 @@
<p>حساب MyTrip خود را ایجاد کنید</p> <p>حساب MyTrip خود را ایجاد کنید</p>
</div> </div>
<form action="#" method="POST" enctype="multipart/form-data"> <form action="{{route('auth.register.post')}}" method="POST" enctype="multipart/form-data">
@csrf @csrf
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="first_name">نام</label> <label for="first_name">نام <span style="color: red">*</span></label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="text" id="first_name" name="first_name" class="form-control" placeholder="نام" value="{{ old('first_name') }}"> <input type="text" id="first_name" name="first_name" class="form-control" placeholder="نام" value="{{ old('first_name') }}">
<i class="far fa-user"></i> <i class="far fa-user"></i>
@@ -42,10 +48,9 @@
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="last_name">نام خانوادگی</label> <label for="last_name">نام خانوادگی<span style="color: red">*</span></label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="text" id="last_name" name="last_name" class="form-control" placeholder="نام خانوادگی" value="{{ old('last_name') }}"> <input type="text" id="last_name" name="last_name" class="form-control" placeholder="نام خانوادگی" value="{{ old('last_name') }}">
<i class="far fa-user"></i> <i class="far fa-user"></i>
@@ -57,11 +62,11 @@
</div> </div>
</div> </div>
<div class="row">
<div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="national_code">کد ملی</label> <label for="national_code">کد ملی<span style="color: red">*</span></label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="text" id="national_code" name="national_code" class="form-control" placeholder="کد ملی" value="{{ old('national_code') }}"> <input type="text" id="national_code" name="national_code" class="form-control" placeholder="کد ملی" value="{{ old('national_code') }}">
<i class="far fa-id-card"></i> <i class="far fa-id-card"></i>
@@ -72,15 +77,15 @@
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="gender">جنسیت</label> <label for="gender">جنسیت<span style="color: red">*</span></label>
<div class="form-group-icon"> <div class="form-group-icon">
<select id="gender" name="gender" class="form-control"> <select id="gender" name="gender" class="form-control">
<option value="">انتخاب کنید</option> <option value="" @selected(old('gender') === null || old('gender') === '')>انتخاب کنید</option>
<option value="male">آقا</option> <option value="{{ \App\Enums\UserGender::UNKNOWN->value }}" @selected(old('gender') !== null && old('gender') !== '' && old('gender') == \App\Enums\UserGender::UNKNOWN->value)>نامشخص</option>
<option value="female">خانم</option> <option value="{{ \App\Enums\UserGender::MALE->value }}" @selected(old('gender') !== null && old('gender') !== '' && old('gender') == \App\Enums\UserGender::MALE->value)>آقا</option>
<option value="{{ \App\Enums\UserGender::FEMALE->value }}" @selected(old('gender') !== null && old('gender') !== '' && old('gender') == \App\Enums\UserGender::FEMALE->value)>خانم</option>
</select> </select>
<i class="far fa-venus-mars"></i> <i class="far fa-venus-mars"></i>
</div> </div>
@@ -91,16 +96,17 @@
</div> </div>
</div> </div>
<div class="row">
<div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="marital_status">وضعیت تاهل</label> <label for="marital_status">وضعیت تاهل<span style="color: red">*</span></label>
<div class="form-group-icon"> <div class="form-group-icon">
<select id="marital_status" name="marital_status" class="form-control"> <select id="marital_status" name="marital_status" class="form-control">
<option value="">انتخاب کنید</option> <option value="" @selected(old('marital_status') === null || old('marital_status') === '')>انتخاب کنید</option>
<option value="single">مجرد</option> <option value="{{ \App\Enums\UserMarital::SINGLE->value }}" @selected(old('marital_status') !== null && old('marital_status') !== '' && old('marital_status') == \App\Enums\UserMarital::SINGLE->value)>مجرد</option>
<option value="married">متأهل</option> <option value="{{ \App\Enums\UserMarital::MARRIED->value }}" @selected(old('marital_status') !== null && old('marital_status') !== '' && old('marital_status') == \App\Enums\UserMarital::MARRIED->value)>متأهل</option>
<option value="{{ \App\Enums\UserMarital::DIVORCED->value }}" @selected(old('marital_status') !== null && old('marital_status') !== '' && old('marital_status') == \App\Enums\UserMarital::DIVORCED->value)>جدا شده</option>
</select> </select>
<i class="fas fa-ring"></i> <i class="fas fa-ring"></i>
</div> </div>
@@ -110,7 +116,6 @@
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="spouse_name">نام و نام خانوادگی همسر</label> <label for="spouse_name">نام و نام خانوادگی همسر</label>
@@ -125,11 +130,11 @@
</div> </div>
</div> </div>
<div class="row">
<div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="mobile">شماره همراه</label> <label for="mobile">شماره همراه<span style="color: red">*</span></label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="text" id="mobile" name="mobile" class="form-control" placeholder="0912..." value="{{ old('mobile') }}"> <input type="text" id="mobile" name="mobile" class="form-control" placeholder="0912..." value="{{ old('mobile') }}">
<i class="fas fa-phone"></i> <i class="fas fa-phone"></i>
@@ -140,12 +145,11 @@
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="email">آدرس ایمیل</label> <label for="email">آدرس ایمیل<span style="color: red">*</span></label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="email" id="mobile" name="email" class="form-control" placeholder="ایمیل خود را وارد کنید" value="{{old('email')}}"> <input type="email" id="email" name="email" class="form-control" placeholder="ایمیل خود را وارد کنید" value="{{ old('email') }}">
<i class="far fa-envelope"></i> <i class="far fa-envelope"></i>
</div> </div>
@error('email') @error('email')
@@ -155,11 +159,11 @@
</div> </div>
</div> </div>
<div class="row">
<div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="username">نام کاربری</label> <label for="username">نام کاربری<span style="color: red">*</span></label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="text" id="username" name="username" class="form-control" placeholder="Username" value="{{ old('username') }}"> <input type="text" id="username" name="username" class="form-control" placeholder="Username" value="{{ old('username') }}">
<i class="far fa-user-circle"></i> <i class="far fa-user-circle"></i>
@@ -170,7 +174,6 @@
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="avatar">عکس پروفایل</label> <label for="avatar">عکس پروفایل</label>
@@ -185,13 +188,13 @@
</div> </div>
</div> </div>
<div class="row">
<div class="row">
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="password">رمز عبور</label> <label for="password">رمز عبور<span style="color: red">*</span></label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="password" id="password" name="password" class="form-control" placeholder="رمز عبور" required> <input type="password" id="password" name="password" class="form-control" placeholder="رمز عبور">
<i class="far fa-lock"></i> <i class="far fa-lock"></i>
</div> </div>
@error('password') @error('password')
@@ -200,12 +203,11 @@
</div> </div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <div class="form-group">
<label for="password_confirmation">تایید رمز عبور</label> <label for="password_confirmation">تایید رمز عبور</label>
<div class="form-group-icon"> <div class="form-group-icon">
<input type="password" id="password_confirmation" name="password_confirmation" class="form-control" placeholder="تکرار رمز عبور" required> <input type="password" id="password_confirmation" name="password_confirmation" class="form-control" placeholder="تکرار رمز عبور">
<i class="far fa-check-circle"></i> <i class="far fa-check-circle"></i>
</div> </div>
@error('password_confirmation') @error('password_confirmation')
@@ -215,36 +217,38 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-md-6">
<label for="province_id">استان</label>
<select id="province_id" name="province_id" class="form-control">
<option value="">انتخاب استان</option>
@foreach ($provinces as $id => $name)
<option value="{{ $id }}" @selected(old('province_id') == $id)>
{{ $name }}
</option>
@endforeach
</select>
@error('province_id')
<span style="color: red">{{ $message }}</span>
@enderror
</div>
<div class="col-md-6"> <div class="col-md-6">
<div class="form-group"> <label for="city_id">شهر</label>
<label for="user_province">استان</label> <select id="city_id" name="city_id" class="form-control" disabled>
<div class="form-group-icon"> <option value="">ابتدا استان را انتخاب کنید</option>
<input type="text" id="user_province" name="user_province" class="form-control" placeholder="استان" value="{{old('user_province')}}"> </select>
<i class="fas fa-map-marker-alt"></i> @error('city_id')
</div>
@error('user_province')
<span style="color: red">{{ $message }}</span> <span style="color: red">{{ $message }}</span>
@enderror @enderror
</div> </div>
</div> </div>
<div class="col-md-6">
<div class="form-group">
<label for="user_city">شهر</label>
<div class="form-group-icon">
<input type="text" id="user_city" name="user_city" class="form-control" placeholder="شهر" value="{{old('user_city')}}">
<i class="fas fa-city"></i>
</div>
@error('user_city')
<span style="color: red">{{$message}}</span>
@enderror
</div>
</div>
</div>
<div class="form-check form-group mt-3"> <div class="form-check form-group mt-3">
<input class="form-check-input" type="checkbox" name="terms" value="1" id="agree" required> <input class="form-check-input" type="checkbox" name="terms" value="1" id="agree" required>
<label class="form-check-label" for="agree"> <label class="form-check-label" for="agree">
@@ -267,4 +271,37 @@
</div> </div>
</main> </main>
<script>
$(document).ready(function () {
$('#province_id').on('change', function () {
let provinceId = $(this).val();
let citySelect = $('#city_id');
citySelect.prop('disabled', true);
if (!provinceId) {
citySelect.html('<option value="">ابتدا استان را انتخاب کنید</option>');
return;
}
citySelect.html('<option value="">در حال بارگذاری...</option>');
$.get('/get-cities/' + provinceId, function (data) {
citySelect.html('<option value="">انتخاب شهر</option>');
$.each(data, function (key, city) {
citySelect.append(
'<option value="' + city.id + '">' + city.name + '</option>'
);
});
citySelect.prop('disabled', false);
}).fail(function () {
citySelect.html('<option value="">خطا در دریافت شهرها</option>');
});
});
});
</script>
@endsection @endsection