feat(user): menambahkan upload ktp ,merubah logika trait untuk upload attachment,menyesuaikan avatar di header

This commit is contained in:
Yoga Pangestu 2024-11-30 19:15:10 +07:00
parent 091df5d9e9
commit 90b154f18a
12 changed files with 84 additions and 41 deletions

View File

@ -23,7 +23,7 @@ public function index(): View
{ {
return view('pages.admin.master.user.index', [ return view('pages.admin.master.user.index', [
'pageTitle' => 'Pengguna', 'pageTitle' => 'Pengguna',
'users' => User::with(['biography', 'attachment']) 'users' => User::with(['biography', 'attachments'])
->barbershop() ->barbershop()
->latest() ->latest()
->get(), ->get(),
@ -52,7 +52,8 @@ public function store(UserRequest $request): RedirectResponse
Biography::create(array_merge($validatedData, [ Biography::create(array_merge($validatedData, [
'user_id' => $newUser->id, 'user_id' => $newUser->id,
]), $validatedData); ]), $validatedData);
$this->uploadAttachment($validatedData['avatar'], 'users', User::class, $newUser->id); $this->uploadAttachment($validatedData['avatar'], 'users', User::class, $newUser->id, 'avatar');
$this->uploadAttachment($validatedData['ktp'], 'users', User::class, $newUser->id, 'ktp');
}); });
notify()->success('Data berhasil ditambahkan', 'Berhasil'); notify()->success('Data berhasil ditambahkan', 'Berhasil');
@ -90,11 +91,15 @@ public function update(User $user, UserRequest $request): RedirectResponse
'base_salary', 'base_salary',
'sop', 'sop',
'avatar', 'avatar',
'ktp',
]) ])
->toArray(); ->toArray();
$user->biography()->update($biographyData); $user->biography()->update($biographyData);
if (isset($validatedData['avatar'])) { if (isset($validatedData['avatar'])) {
$this->uploadAttachment($validatedData['avatar'], 'users', User::class, $user->id); $this->uploadAttachment($validatedData['avatar'], 'users', User::class, $user->id, 'avatar');
}
if (isset($validatedData['ktp'])) {
$this->uploadAttachment($validatedData['ktp'], 'users', User::class, $user->id, 'ktp');
} }
}); });

View File

@ -41,6 +41,9 @@ public function rules(): array
'avatar' => $isEdit 'avatar' => $isEdit
? ['nullable', 'image', 'mimes:jpeg,png,jpg,gif,svg', 'max:2048'] ? ['nullable', 'image', 'mimes:jpeg,png,jpg,gif,svg', 'max:2048']
: ['required', 'image', 'mimes:jpeg,png,jpg,gif,svg', 'max:2048'], : ['required', 'image', 'mimes:jpeg,png,jpg,gif,svg', 'max:2048'],
'ktp' => $isEdit
? ['nullable', 'image', 'mimes:jpeg,png,jpg,gif,svg', 'max:2048']
: ['required', 'image', 'mimes:jpeg,png,jpg,gif,svg', 'max:2048'],
'gender' => ['required', Rule::in(['1', '2'])], 'gender' => ['required', Rule::in(['1', '2'])],
]; ];

View File

@ -17,6 +17,7 @@ class Attachment extends Model
'name', 'name',
'extension', 'extension',
'size', 'size',
'type',
]; ];
public function getFormattedAttachmentAttribute(): string public function getFormattedAttachmentAttribute(): string

View File

@ -11,7 +11,7 @@
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphOne; use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
@ -99,8 +99,8 @@ public function cash(): HasMany
return $this->hasMany(Cash::class); return $this->hasMany(Cash::class);
} }
public function attachment(): MorphOne public function attachments(): MorphMany
{ {
return $this->morphOne(Attachment::class, 'attachmentable'); return $this->morphMany(Attachment::class, 'attachmentable');
} }
} }

View File

@ -10,9 +10,9 @@
trait UploadAttachment trait UploadAttachment
{ {
public function uploadAttachment(UploadedFile|string $file, string $path, string $classModel, string $featureId): void public function uploadAttachment(UploadedFile|string $file, string $path, string $classModel, string $featureId, string $type): void
{ {
DB::transaction(function () use ($file, $path, $classModel, $featureId) { DB::transaction(function () use ($file, $path, $classModel, $featureId, $type) {
if (is_string($file) && strpos($file, 'data:image') === 0) { if (is_string($file) && strpos($file, 'data:image') === 0) {
$imageData = explode(',', $file)[1]; $imageData = explode(',', $file)[1];
$image = base64_decode($imageData); $image = base64_decode($imageData);
@ -23,36 +23,36 @@ public function uploadAttachment(UploadedFile|string $file, string $path, string
$date = now()->format('Y-m-d'); $date = now()->format('Y-m-d');
Storage::disk('public')->put($path.'/'.$date.'/'.$fullFileName, $image); Storage::disk('public')->put($path.'/'.$date.'/'.$fullFileName, $image);
Attachment::create([ Attachment::updateOrCreate(
'attachmentable_id' => $featureId, [
'attachmentable_type' => $classModel, 'attachmentable_id' => $featureId,
'name' => $fileName, 'attachmentable_type' => $classModel,
'extension' => $extension, 'type' => $type,
'size' => strlen($image), ],
]); [
'name' => $fileName,
'extension' => $extension,
'size' => strlen($image),
]
);
} elseif ($file instanceof UploadedFile) { } elseif ($file instanceof UploadedFile) {
$existingAttachment = Attachment::where('attachmentable_id', $featureId)
->where('attachmentable_type', $classModel)
->first();
if ($existingAttachment) {
$oldFilePath = $path.'/'.$existingAttachment->created_at->format('Y-m-d').'/'.$existingAttachment->name.'.'.$existingAttachment->extension;
Storage::disk('public')->delete($oldFilePath);
$existingAttachment->delete();
}
$date = now()->format('Y-m-d'); $date = now()->format('Y-m-d');
$extension = $file->getClientOriginalExtension(); $extension = $file->getClientOriginalExtension();
$fileName = Str::uuid(); $fileName = Str::uuid();
$file->storeAs($path.'/'.$date, $fileName.'.'.$extension, 'public'); $file->storeAs($path.'/'.$date, $fileName.'.'.$extension, 'public');
Attachment::create([ Attachment::updateOrCreate(
'attachmentable_id' => $featureId, [
'attachmentable_type' => $classModel, 'attachmentable_id' => $featureId,
'name' => $fileName, 'attachmentable_type' => $classModel,
'extension' => $extension, 'type' => $type,
'size' => $file->getSize(), ],
]); [
'name' => $fileName,
'extension' => $extension,
'size' => $file->getSize(),
]
);
} }
}); });
} }

View File

@ -14,6 +14,7 @@ public function up(): void
Schema::create('attachments', function (Blueprint $table) { Schema::create('attachments', function (Blueprint $table) {
$table->id(); $table->id();
$table->nullableMorphs('attachmentable'); $table->nullableMorphs('attachmentable');
$table->string('type', 20);
$table->string('name', 50); $table->string('name', 50);
$table->string('extension', 10); $table->string('extension', 10);
$table->string('size', 10); $table->string('size', 10);

View File

@ -51,6 +51,7 @@ public function run(): void
'name' => $fileName, 'name' => $fileName,
'extension' => $file->getExtension(), 'extension' => $file->getExtension(),
'size' => $file->getSize(), 'size' => $file->getSize(),
'type' => 'avatar',
]); ]);
$path = 'users/'.now()->format('Y-m-d'); $path = 'users/'.now()->format('Y-m-d');

View File

@ -16,7 +16,10 @@ $(document).ready(function () {
gender: button.data("gender"), gender: button.data("gender"),
sop: button.data("sop"), sop: button.data("sop"),
avatar: button.data("avatar"), avatar: button.data("avatar"),
ktp: button.data("ktp"),
}; };
console.log(data);
var genderBadge = ''; var genderBadge = '';
if (data.gender === 1) { if (data.gender === 1) {
genderBadge = '<span class="badge bg-success">Laki-laki</span>'; genderBadge = '<span class="badge bg-success">Laki-laki</span>';
@ -34,5 +37,6 @@ $(document).ready(function () {
$('#user-address').text(data.address); $('#user-address').text(data.address);
$('#user-gender').html(genderBadge); $('#user-gender').html(genderBadge);
$('#user-sop').text(data.sop); $('#user-sop').text(data.sop);
$('#user-ktp').attr('src', data.ktp);
}); });
}); });

View File

@ -148,6 +148,19 @@ class="form-control rupiah-format @error('base_salary') is-invalid @enderror" id
@enderror @enderror
</div> </div>
<div class="col-lg-6 position-relative"> <div class="col-lg-6 position-relative">
<label class="form-label" for="ktp">KTP
<span class="form-span"><i>(.jpeg,.png,.jpg,.gif,.svg)</i></span>
</label>
<input name="ktp" class="form-control @error('ktp') is-invalid @enderror" id="ktp"
type="file" value="{{ old('ktp') }}"
accept="image/jpeg,image/png,image/jpg,image/gif,image/svg">
@error('ktp')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
<div class="col-lg-4 position-relative">
<label class="form-label" for="gender">Jenis Kelamin <label class="form-label" for="gender">Jenis Kelamin
</label> </label>
<select name="gender" class="form-control @error('gender') is-invalid @enderror select2" <select name="gender" class="form-control @error('gender') is-invalid @enderror select2"
@ -162,7 +175,7 @@ class="form-control rupiah-format @error('base_salary') is-invalid @enderror" id
</div> </div>
@enderror @enderror
</div> </div>
<div class="col-lg-6 position-relative"> <div class="col-lg-4 position-relative">
<label class="form-label" for="barbershop">Barbershop <label class="form-label" for="barbershop">Barbershop
</label> </label>
<select name="barbershop" class="form-control @error('barbershop') is-invalid @enderror select2" <select name="barbershop" class="form-control @error('barbershop') is-invalid @enderror select2"
@ -180,7 +193,7 @@ class="form-control rupiah-format @error('base_salary') is-invalid @enderror" id
</div> </div>
@enderror @enderror
</div> </div>
<div class="col-lg-6 position-relative"> <div class="col-lg-4 position-relative">
<label class="form-label" for="role">Role <label class="form-label" for="role">Role
</label> </label>
<select name="role" class="form-control @error('role') is-invalid @enderror select2" <select name="role" class="form-control @error('role') is-invalid @enderror select2"

View File

@ -147,6 +147,19 @@ class="form-control rupiah-format @error('base_salary') is-invalid @enderror" id
@enderror @enderror
</div> </div>
<div class="col-lg-6 position-relative"> <div class="col-lg-6 position-relative">
<label class="form-label" for="ktp">KTP
<span class="form-span"><i>(.jpeg,.png,.jpg,.gif,.svg, Opsional)</i></span>
</label>
<input name="ktp" class="form-control @error('ktp') is-invalid @enderror" id="ktp"
type="file" value="{{ old('ktp') }}"
accept="image/jpeg,image/png,image/jpg,image/gif,image/svg">
@error('ktp')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
<div class="col-lg-4 position-relative">
<label class="form-label" for="gender">Jenis Kelamin <label class="form-label" for="gender">Jenis Kelamin
</label> </label>
<select name="gender" class="form-control @error('gender') is-invalid @enderror select2" <select name="gender" class="form-control @error('gender') is-invalid @enderror select2"
@ -161,7 +174,7 @@ class="form-control rupiah-format @error('base_salary') is-invalid @enderror" id
</div> </div>
@enderror @enderror
</div> </div>
<div class="col-lg-6 position-relative"> <div class="col-lg-4 position-relative">
<label class="form-label" for="barbershop">Barbershop <label class="form-label" for="barbershop">Barbershop
</label> </label>
<select name="barbershop" class="form-control @error('barbershop') is-invalid @enderror select2" <select name="barbershop" class="form-control @error('barbershop') is-invalid @enderror select2"
@ -179,7 +192,7 @@ class="form-control rupiah-format @error('base_salary') is-invalid @enderror" id
</div> </div>
@enderror @enderror
</div> </div>
<div class="col-lg-6 position-relative"> <div class="col-lg-4 position-relative">
<label class="form-label" for="role">Role <label class="form-label" for="role">Role
</label> </label>
<select name="role" class="form-control @error('role') is-invalid @enderror select2" <select name="role" class="form-control @error('role') is-invalid @enderror select2"

View File

@ -93,7 +93,8 @@
data-address="{{ $user->biography->address ?? '-' }}" data-address="{{ $user->biography->address ?? '-' }}"
data-gender="{{ $user->biography->gender ?? '-' }}" data-gender="{{ $user->biography->gender ?? '-' }}"
data-sop="{{ $user->sop ?? '-' }}" data-sop="{{ $user->sop ?? '-' }}"
data-avatar="{{ Storage::url("users/{$user->attachment->formatted_attachment}") }}"> data-avatar="{{ optional($user->attachments()->where('type', 'avatar')->first())->formatted_attachment ? Storage::url('users/' . optional($user->attachments()->where('type', 'avatar')->first())->formatted_attachment) : '' }}"
data-ktp="{{ optional($user->attachments()->where('type', 'ktp')->latest()->first())->formatted_attachment ? Storage::url('users/' . optional($user->attachments()->where('type', 'ktp')->latest()->first())->formatted_attachment) : '' }}">
<i data-feather="eye"></i> <i data-feather="eye"></i>
</a> </a>
</li> </li>
@ -169,12 +170,13 @@
<td class="text-start"><span id="user-gender"></span></td> <td class="text-start"><span id="user-gender"></span></td>
</tr> </tr>
<tr> <tr>
<td class="text-start">Sop</td> <td class="text-start" colspan="3"><span id="user-sop"></span></td>
<td class="text-start">-></td>
<td class="text-start"><span id="user-sop"></span></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div class="mt-3">
<img id="user-ktp" src="" alt="ktp">
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -64,7 +64,7 @@
</li> </li>
<li class="profile-nav onhover-dropdown pe-0 py-0"> <li class="profile-nav onhover-dropdown pe-0 py-0">
<div class="media profile-media"> <div class="media profile-media">
<img src="{{ Storage::url('users/' . Auth::user()->attachment->formatted_attachment) }}" <img src="{{ Storage::url('users/' . Auth::user()->attachments()->first()->formatted_attachment) }}"
alt="image"> alt="image">
<div class="media-body"> <div class="media-body">
<span>{{ Auth::user()->biography->full_name }}</span> <span>{{ Auth::user()->biography->full_name }}</span>