From 12f8d0bbdad1c37bd5f0804981802c52c2a47df7 Mon Sep 17 00:00:00 2001 From: althaf Date: Wed, 22 Jul 2026 10:10:06 +0700 Subject: [PATCH] integrate image cropper for avatar upload/delete option/retouch --- .../Web/Produktivitas/PetaniController.php | 11 ++ public/assets/img/avatars/3.jpg | Bin 0 -> 5568 bytes .../views/produktivitas/petani/add.blade.php | 88 ++++++++++++- .../views/produktivitas/petani/edit.blade.php | 116 ++++++++++++++++-- .../produktivitas/petani/header.blade.php | 6 +- 5 files changed, 206 insertions(+), 15 deletions(-) create mode 100644 public/assets/img/avatars/3.jpg diff --git a/app/Http/Controllers/Web/Produktivitas/PetaniController.php b/app/Http/Controllers/Web/Produktivitas/PetaniController.php index 92a99ef..336c77a 100644 --- a/app/Http/Controllers/Web/Produktivitas/PetaniController.php +++ b/app/Http/Controllers/Web/Produktivitas/PetaniController.php @@ -224,6 +224,13 @@ class PetaniController extends Controller $validatedData = $this->validatePetani($request); + if ($request->input('hapus_foto') == '1') { + if ($petani->foto && Storage::exists($petani->foto)) { + Storage::delete($petani->foto); + } + $validatedData['foto'] = null; + } + if ($request->hasFile('file_ktp')) { $file_ktp = $request->file('file_ktp'); $validatedData['path_ktp'] = $file_ktp->store('petani/ktp'); @@ -235,6 +242,10 @@ class PetaniController extends Controller $validatedData['file_kk'] = $file_kk->getClientOriginalName(); } if ($request->hasFile('foto')) { + + if ($petani->foto && Storage::exists($petani->foto)) { + Storage::delete($petani->foto); + } $file_foto = $request->file('foto'); $validatedData['foto'] = $file_foto->store('petani/foto'); } diff --git a/public/assets/img/avatars/3.jpg b/public/assets/img/avatars/3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..93c4cc0d6309c792c41894ebcf1416c3f7b7f384 GIT binary patch literal 5568 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 literal 0 HcmV?d00001 diff --git a/resources/views/produktivitas/petani/add.blade.php b/resources/views/produktivitas/petani/add.blade.php index 15fbb69..c460c44 100644 --- a/resources/views/produktivitas/petani/add.blade.php +++ b/resources/views/produktivitas/petani/add.blade.php @@ -1,3 +1,17 @@ +@push('style') + + + +@endpush + +@push('scripts') + + @extends('layout.main') @section('content') @@ -29,7 +43,7 @@
Foto profil petani
+ + @endsection @push('scripts') @@ -300,24 +332,74 @@ } }); $('#add-petani-desa').select2(); + + let croppieInstance = null; $('#fotoPreview').on('click', function () { + $('#foto').val(''); $('#foto').click(); }); $('#foto').on('change', function (e) { - const file = e.target.files[0]; if (!file) return; + if(!file.type.match(/^image\/(png|jpeg|jpg)$/)) { + return; + } + const reader = new FileReader(); reader.onload = function (event) { - $('#fotoPreview').attr('src', event.target.result); + $('#cropModal').modal('show'); + + if (!croppieInstance) { + const el = document.getElementById('croppie-container'); + croppieInstance = new Croppie(el, { + viewport: { width: 200, height: 200,}, + boundary: { width: 300, height: 300 }, + showZoomer: true, + enableOrientation: true + }); + } + + setTimeout(function() { + croppieInstance.bind({ + url: event.target.result + }); + }, 200); }; reader.readAsDataURL(file); }); + $('#cropImageBtn').on('click', function() { + croppieInstance.result({ + type: 'base64', + format: 'png', + size: 'viewport' + }).then(function(base64) { + + $('#fotoPreview').attr('src', base64); + + function dataURLtoFile(dataurl, filename) { + let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], + bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); + while(n--){ + u8arr[n] = bstr.charCodeAt(n); + } + return new File([u8arr], filename, {type: mime}); + } + + let croppedFile = dataURLtoFile(base64, 'foto_profil_crop.png'); + + let dataTransfer = new DataTransfer(); + dataTransfer.items.add(croppedFile); + document.getElementById('foto').files = dataTransfer.files; + + $('#cropModal').modal('hide'); + }); + }); + // 1 MB = 1048576 bytes $.validator.addMethod('maxfilesize', function (value, element, param) { return this.optional(element) || (element.files[0] && element.files[0].size <= param); diff --git a/resources/views/produktivitas/petani/edit.blade.php b/resources/views/produktivitas/petani/edit.blade.php index cc3dd1b..33764db 100644 --- a/resources/views/produktivitas/petani/edit.blade.php +++ b/resources/views/produktivitas/petani/edit.blade.php @@ -1,5 +1,19 @@ @extends('layout.main') +@push('style') + + + +@endpush + +@push('scripts') + + @section('content')
@if ($errors->any()) @@ -23,20 +37,24 @@
@csrf @method('PUT') +
- Foto profil petani -
+ + @endsection @push('scripts') @@ -306,24 +342,86 @@ }); $('#edit-petani-desa').select2(); + let croppieInstance = null; + $('#fotoPreview').on('click', function () { + $('#foto').val(''); $('#foto').click(); }); $('#foto').on('change', function (e) { - const file = e.target.files[0]; if (!file) return; + if(!file.type.match(/^image\/(png|jpeg|jpg)$/)) { + return; + } + const reader = new FileReader(); reader.onload = function (event) { - $('#fotoPreview').attr('src', event.target.result); + $('#cropModal').modal('show'); + + if (!croppieInstance) { + const el = document.getElementById('croppie-container'); + croppieInstance = new Croppie(el, { + viewport: { width: 200, height: 200 }, + boundary: { width: '100%', height: 280 }, + showZoomer: true, + enableOrientation: true + }); + } + + setTimeout(function() { + croppieInstance.bind({ + url: event.target.result + }); + }, 200); }; reader.readAsDataURL(file); }); - // 1 MB = 1048576 bytes + + $('#cropImageBtn').on('click', function() { + croppieInstance.result({ + type: 'base64', + format: 'png', + size: 'viewport', + }).then(function(base64) { + + $('#fotoPreview').attr('src', base64); + + $('#hapus_foto').val('0'); + $('#btnHapusFoto').show(); + + function dataURLtoFile(dataurl, filename) { + let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], + bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); + while(n--){ + u8arr[n] = bstr.charCodeAt(n); + } + return new File([u8arr], filename, {type: mime}); + } + + let croppedFile = dataURLtoFile(base64, 'foto_profil_crop.png'); + + let dataTransfer = new DataTransfer(); + dataTransfer.items.add(croppedFile); + document.getElementById('foto').files = dataTransfer.files; + + $('#cropModal').modal('hide'); + }); + }); + + $('#btnHapusFoto').on('click', function() { + $('#hapus_foto').val('1'); + + $('#foto').val(''); + + $('#fotoPreview').attr('src', "{{ asset('assets/img/avatars/3.jpg') }}"); + + $(this).hide(); + }); $.validator.addMethod('maxfilesize', function (value, element, param) { return this.optional(element) || (element.files[0] && element.files[0].size <= param); }, 'File size must be less than {0} bytes.'); diff --git a/resources/views/produktivitas/petani/header.blade.php b/resources/views/produktivitas/petani/header.blade.php index 70b8c67..15c31de 100644 --- a/resources/views/produktivitas/petani/header.blade.php +++ b/resources/views/produktivitas/petani/header.blade.php @@ -7,10 +7,10 @@
@if (!isset($petani)) - Foto Petani + Foto Petani @else - Foto Petani + Foto Petani @endif