Skip to content

Commit

Permalink
image feature
Browse files Browse the repository at this point in the history
  • Loading branch information
iqbaleff214 committed Jun 2, 2024
1 parent 43856e1 commit d2c2a6e
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 49 deletions.
21 changes: 20 additions & 1 deletion app/Http/Controllers/ProfileController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;
use Random\RandomException;

class ProfileController extends Controller
{
Expand All @@ -23,10 +25,27 @@ public function edit(Request $request): View

/**
* Update the user's profile information.
*
* @throws RandomException
*/
public function update(ProfileUpdateRequest $request): RedirectResponse
{
$request->user()->fill($request->validated());
$data = $request->validated();

if (isset($data['image']) || $data['image'] === null) {
unset($data['image']);
}

if ($request->hasFile('image')) {
if ($request->user()->image) {
Storage::delete("public/{$request->user()->image}");
}

$data['image'] = time().random_int(0, PHP_INT_MAX).'.'.$request->file('image')->extension();
Storage::putFileAs('public', $request->file('image'), $data['image']);
}

$request->user()->fill($data);

if ($request->user()->isDirty('email')) {
$request->user()->email_verified_at = null;
Expand Down
22 changes: 20 additions & 2 deletions app/Http/Controllers/TeacherController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;
use Yajra\DataTables\DataTables;

Expand Down Expand Up @@ -39,8 +40,9 @@ class="btn p-0 dropdown-toggle hide-arrow"
</div>
</div>';
})
->editColumn('image', fn ($row) => '<a data-fslightbox href="'.$row->image_url.'"><img src="'.$row->image_url.'" alt="user-avatar" class="d-block rounded" height="30" width="30"></a>')
->editColumn('gender', fn ($row) => __('label.'.$row->gender))
->rawColumns(['action'])
->rawColumns(['action', 'image'])
->make();
}

Expand All @@ -65,6 +67,11 @@ public function store(StoreTeacherRequest $request): RedirectResponse
$data['role'] = Role::TEACHER;
$data['password'] = bcrypt('password');

if ($request->hasFile('image')) {
$data['image'] = time().random_int(0, PHP_INT_MAX).'.'.$request->file('image')->extension();
Storage::putFileAs('public', $request->file('image'), $data['image']);
}

User::create($data);

return redirect()->route('teacher.index')->with('notification', $this->successNotification('notification.success_create', 'menu.teacher'));
Expand Down Expand Up @@ -101,7 +108,18 @@ public function edit(User $teacher): View
public function update(UpdateTeacherRequest $request, User $teacher): RedirectResponse
{
try {
$teacher->update($request->validated());
$data = $request->validated();

if ($request->hasFile('image')) {
if ($teacher->image) {
Storage::delete("public/{$teacher->image}");
}

$data['image'] = time().random_int(0, PHP_INT_MAX).'.'.$request->file('image')->extension();
Storage::putFileAs('public', $request->file('image'), $data['image']);
}

$teacher->update($data);

return back()->with('notification', $this->successNotification('notification.success_update', 'menu.teacher'));
} catch (\Throwable $throwable) {
Expand Down
10 changes: 10 additions & 0 deletions app/Http/Requests/ProfileUpdateRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public function rules(): array
return [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'lowercase', 'email', 'max:255', Rule::unique(User::class)->ignore($this->user()->id)],
'image' => ['nullable', 'image', 'max:2048'],
'phone' => ['required'],
'address' => ['nullable'],
'marital_status' => ['nullable'],
'gender' => ['required'],
];
}

Expand All @@ -26,6 +31,11 @@ public function attributes(): array
return [
'name' => __('field.name'),
'email' => __('field.email'),
'image' => __('field.image'),
'phone' => __('field.phone'),
'address' => __('field.address'),
'marital_status' => __('field.marital_status'),
'gender' => __('field.gender'),
];
}
}
19 changes: 18 additions & 1 deletion app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Storage;

class User extends Authenticatable
{
Expand Down Expand Up @@ -45,6 +46,16 @@ class User extends Authenticatable
'image_url',
];

protected static function boot(): void
{
parent::boot();
static::deleting(function (User $user) {
if ($user->image) {
Storage::delete("public/$user->image");
}
});
}

/**
* Get the attributes that should be cast.
*
Expand All @@ -61,7 +72,13 @@ protected function casts(): array
public function imageUrl(): Attribute
{
return new Attribute(
get: fn () => 'https://ui-avatars.com/api/?name='.$this->name,
get: function () {
if ($this->image) {
return asset('storage/'.$this->image);
}

return asset('404_Black.jpg');
}
);
}

Expand Down
1 change: 1 addition & 0 deletions lang/en/button.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
'login' => 'Sign In',
'register' => 'Sign Up',
'delete_permanently' => 'Delete My Account',
'upload' => 'Upload',

];
1 change: 1 addition & 0 deletions lang/en/label.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@
'male' => 'Male',
'female' => 'Female',
'required' => 'Required',
'allowed_image_upload' => 'Allowed JPG or PNG. Max size of 2MB',
];
1 change: 1 addition & 0 deletions lang/id/button.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
'login' => 'Masuk',
'register' => 'Buat Akun',
'delete_permanently' => 'Hapus Akun Permanen',
'upload' => 'Unggah',

];
1 change: 1 addition & 0 deletions lang/id/label.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,5 @@
'male' => 'Laki-laki',
'female' => 'Perempuan',
'required' => 'Wajib',
'allowed_image_upload' => 'Hanya boleh JPG atau PNG. Ukuran maksimal 2MB',
];
1 change: 1 addition & 0 deletions resources/views/layouts/dashboard.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
@push('script')
<script src="{{ asset('assets/vendor/libs/select2/select2.min.js') }}"></script>
<script src="{{ asset('assets/vendor/libs/sweetalert2/sweetalert2.all.min.js') }}"></script>
<script src="{{ asset('assets/vendor/libs/fslightbox/fslightbox.js') }}"></script>
<script>
$('.select2').select2({theme: 'bootstrap-5'});
Expand Down
10 changes: 6 additions & 4 deletions resources/views/pages/account/change-password.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,19 @@
@method('put')
<div class="card-body">
<div class="row">
<div class="mb-3 col-md-12">
<div class="mb-3 col-md-6">
<x-forms.input-password name="current_password"/>
</div>
<div class="mb-3 col-md-12">
</div>
<div class="row">
<div class="mb-3 col-md-6">
<x-forms.input-password name="password"/>
</div>
<div class="mb-3 col-md-12">
<div class="mb-3 col-md-6">
<x-forms.input-password name="password_confirmation"/>
</div>
</div>
<div class="mt-2">
<div class="mt-4">
<button type="submit" class="btn btn-primary me-2">{{ __('button.submit') }}</button>
<button type="reset" class="btn btn-outline-secondary">{{ __('button.reset') }}</button>
</div>
Expand Down
86 changes: 71 additions & 15 deletions resources/views/pages/account/profile.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,63 @@
</li>
</ul>
<div class="card mb-4">
<h5 class="card-header">{{ __('label.profile_information') }}</h5>
<!-- Account -->
<div class="card-body">
<form id="formAccountSettings" action="{{ route('account.profile.update') }}" method="POST">
<form id="formAccountSettings" action="{{ route('account.profile.update') }}" method="POST"
enctype="multipart/form-data">
<h5 class="card-header">{{ __('label.profile_information') }}</h5>
<!-- Account -->
<div class="card-body">
<div class="d-flex align-items-start align-items-sm-center gap-4">
<a data-fslightbox href="{{ $user->image_url }}">
<img src="{{ $user->image_url }}"
alt="user-avatar" class="d-block rounded" height="100" width="100"
id="uploadImage">
</a>
<div class="button-wrapper">
<label for="upload" class="btn btn-primary me-2 mb-4" tabindex="0">
<span class="d-none d-sm-block">{{ __('button.upload') }}</span>
<i class="bx bx-upload d-block d-sm-none"></i>
<input type="file" id="upload" class="account-file-input" hidden="" name="image"
accept="image/png,image/jpeg">
</label>
<button type="button" class="btn btn-outline-secondary account-image-reset mb-4">
<i class="bx bx-reset d-block d-sm-none"></i>
<span class="d-none d-sm-block">{{ __('button.reset') }}</span>
</button>
<span class="error d-block">{{ $errors->first('image') }}</span>
<small class="text-muted mb-0 d-block">{{ __('label.allowed_image_upload') }}</small>
</div>
</div>
</div>
<hr class="m-0">
<div class="card-body">
@csrf
@method('patch')
<div class="row">
<div class="mb-3 col-md-6">
<x-forms.input name="name" :value="$user->name"/>
</div>
<div class="mb-3 col-md-6">
<x-forms.input name="email" type="email" :value="$user->email"/>
</div>
<div class="mb-3">
<x-forms.input name="name" :value="$user->name" required/>
</div>
<div class="mb-3">
<x-forms.input name="email" type="email" :value="$user->email" required/>
</div>
<div class="mt-2">
<div class="mb-3">
<x-forms.input-select2 name="gender" required :value="$user->gender"
:options="[ ['male', __('label.male')], ['female', __('label.female')] ]"/>
</div>
<div class="mb-3">
<x-forms.input name="phone" type="phone" required :value="$user->phone"/>
</div>
<div class="mb-3">
<x-forms.input-textarea name="address" :value="$user->address"/>
</div>
<div class="mb-3">
<x-forms.input-select2 name="marital_status" :value="$user->marital_status"
:options="[ ['single', __('label.single')], ['married', __('label.married')], ['divorced', __('label.divorced')], ['widowed', __('label.widowed')] ]"/>
</div>
<div class="mt-4">
<button type="submit" class="btn btn-primary me-2">{{ __('button.submit') }}</button>
<button type="reset" class="btn btn-outline-secondary">{{ __('button.reset') }}</button>
</div>
</form>
</div>
</div>
</form>
<!-- /Account -->
</div>
<div class="card">
Expand Down Expand Up @@ -87,6 +124,25 @@
accountActivationButton.attr('disabled', !checkBox.prop('checked'));
})
console.log($('#accountActivation'));
const imageElement = document.getElementById("uploadImage");
const imageInputElement = document.querySelector(".account-file-input");
const imageResetEl = document.querySelector(".account-image-reset");
if (imageElement) {
const originalImage = imageElement.src;
imageInputElement.onchange = () => {
imageInputElement.files[0] && (imageElement.src = window.URL.createObjectURL(imageInputElement.files[0]));
imageElement.closest('a').setAttribute('href', imageElement.src);
refreshFsLightbox();
}
imageResetEl.onclick = () => {
imageInputElement.value = "";
imageElement.src = originalImage;
imageElement.closest('a').setAttribute('href', imageElement.src);
refreshFsLightbox();
}
}
</script>
@endpush
Loading

0 comments on commit d2c2a6e

Please sign in to comment.