TIF_Nganjuk_E41220879/resources/views/profile/edit.blade.php

482 lines
28 KiB
PHP

<x-app-layout>
@section('title', 'Profil Saya')
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Profil Saya
</h2>
</x-slot>
<style>
.profile-wrapper {
padding: 2rem 1.5rem;
max-width: 1200px;
margin: 0 auto;
}
/* Tab Nav */
.profile-tabs {
display: flex;
gap: 6px;
background: #fff;
border-radius: 12px;
box-shadow: 0 1px 4px rgba(0,0,0,.1);
padding: 6px;
margin-bottom: 1.5rem;
}
.tab-btn {
flex: 1;
padding: 10px 16px;
border-radius: 8px;
font-size: .875rem;
font-weight: 500;
border: none;
cursor: pointer;
transition: all .2s;
color: #4b5563;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.tab-btn.active {
background-color: #4A538F;
color: #fff;
box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
/* Layout dua kolom */
.profile-grid {
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
align-items: flex-start;
}
.card-photo {
flex: 1 1 280px;
max-width: 320px;
background: #fff;
border-radius: 16px;
box-shadow: 0 1px 4px rgba(0,0,0,.12);
overflow: hidden;
}
.card-data {
flex: 2 1 400px;
background: #fff;
border-radius: 16px;
box-shadow: 0 1px 4px rgba(0,0,0,.12);
overflow: hidden;
}
.card-header {
background: linear-gradient(to right, #4A538F, #5C66A8);
padding: 1.25rem 1.5rem;
}
/* View grid */
.profile-info-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.25rem;
}
.profile-info-grid .full-width {
grid-column: 1 / -1;
}
/* Form grid */
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.25rem;
}
.form-grid .full-width {
grid-column: 1 / -1;
}
@media (max-width: 640px) {
.profile-info-grid, .form-grid {
grid-template-columns: 1fr;
}
.profile-info-grid .full-width,
.form-grid .full-width {
grid-column: 1;
}
.card-photo {
max-width: 100%;
}
}
</style>
<div class="profile-wrapper">
{{-- Tab Navigation --}}
<div class="profile-tabs" id="profile-tabs">
<button onclick="switchTab('info')" id="tab-info" class="tab-btn active">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
</svg>
Informasi Profil
</button>
<button onclick="switchTab('password')" id="tab-password" class="tab-btn">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
</svg>
Ubah Password
</button>
</div>
{{-- Tab: Informasi Profil --}}
<div id="panel-info">
{{-- Hidden form untuk verifikasi email --}}
<form id="send-verification" method="post" action="{{ route('verification.send') }}">
@csrf
</form>
<div class="profile-grid">
{{-- Card Foto Profil (kiri) --}}
<div class="card-photo">
{{-- Header --}}
<div class="card-header" style="text-align:center;">
<div style="width:96px;height:96px;border-radius:50%;border:4px solid rgba(255,255,255,.5);overflow:hidden;background:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;margin:0 auto;">
@if(auth()->user()->profile_photo)
<img src="{{ asset('storage/' . auth()->user()->profile_photo) }}"
alt="Foto profil"
style="width:100%;height:100%;object-fit:cover;">
@else
<svg width="48" height="48" fill="white" viewBox="0 0 24 24">
<path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/>
</svg>
@endif
</div>
<h3 style="margin-top:.75rem;font-size:1.1rem;font-weight:700;color:#fff;">{{ auth()->user()->name }}</h3>
@if(auth()->user()->position)
<span style="display:inline-block;margin-top:.25rem;background:rgba(255,255,255,.2);color:#fff;font-size:.75rem;padding:2px 10px;border-radius:999px;">
{{ auth()->user()->position }}
</span>
@endif
</div>
{{-- Form Upload Foto --}}
<div style="padding:1.25rem 1.5rem;">
<p style="font-size:.7rem;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.75rem;">Foto Profil</p>
<form method="post" action="{{ route('profile.update') }}" enctype="multipart/form-data" style="display:flex;flex-direction:column;gap:.75rem;">
@csrf
@method('patch')
<input type="hidden" name="_photo_only" value="1">
<input id="profile_photo" name="profile_photo" type="file" accept="image/*"
style="font-size:.875rem;color:#4b5563;width:100%;" />
<p style="font-size:.75rem;color:#9ca3af;">JPG atau PNG, maks. 2MB</p>
<x-input-error class="mt-1" :messages="$errors->get('profile_photo')" />
<button type="submit"
style="width:100%;padding:.5rem 1rem;background:#4A538F;color:#fff;font-size:.875rem;font-weight:500;border:none;border-radius:.5rem;cursor:pointer;"
onmouseover="this.style.background='#424B84'"
onmouseout="this.style.background='#4A538F'">
Upload Foto
</button>
</form>
{{-- Info singkat --}}
<div style="margin-top:1.25rem;padding-top:1rem;border-top:1px solid #e5e7eb;display:flex;flex-direction:column;gap:.5rem;">
<div>
<p style="font-size:.75rem;color:#9ca3af;">Email</p>
<p style="font-size:.875rem;font-weight:500;color:#374151;word-break:break-all;">{{ auth()->user()->email ?? '-' }}</p>
</div>
<div>
<p style="font-size:.75rem;color:#9ca3af;">NIP</p>
<p style="font-size:.875rem;font-weight:500;color:#374151;">{{ auth()->user()->nip ?? '-' }}</p>
</div>
<div>
<p style="font-size:.75rem;color:#9ca3af;">Divisi</p>
<p style="font-size:.875rem;font-weight:500;color:#374151;">{{ auth()->user()->division ?? '-' }}</p>
</div>
</div>
</div>
</div>
{{-- Card Data Profil (kanan) --}}
<div class="card-data">
{{-- Header --}}
<div class="card-header" style="display:flex;align-items:center;justify-content:space-between;">
<div>
<h3 style="font-size:1.1rem;font-weight:700;color:#fff;margin:0;">Data Profil</h3>
<p style="font-size:.875rem;color:rgba(255,255,255,.7);margin:0;">Informasi lengkap akun Anda</p>
</div>
<button onclick="toggleEditMode()" id="btn-edit-profil"
style="display:flex;align-items:center;gap:.5rem;background:#fff;color:#4A538F;font-size:.875rem;font-weight:600;padding:.5rem 1rem;border:none;border-radius:.5rem;cursor:pointer;box-shadow:0 1px 3px rgba(0,0,0,.1);"
onmouseover="this.style.background='#E9EBF5'"
onmouseout="this.style.background='#fff'">
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/>
</svg>
Edit Profil
</button>
</div>
{{-- View Mode --}}
<div id="view-mode" style="padding:1.5rem;">
<div class="profile-info-grid">
<div>
<p style="font-size:.7rem;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.05em;">NIP</p>
<p style="margin-top:.25rem;color:#1f2937;font-weight:500;">{{ auth()->user()->nip ?? '-' }}</p>
</div>
<div>
<p style="font-size:.7rem;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.05em;">Nama Lengkap</p>
<p style="margin-top:.25rem;color:#1f2937;font-weight:500;">{{ auth()->user()->name ?? '-' }}</p>
</div>
<div>
<p style="font-size:.7rem;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.05em;">Email</p>
<p style="margin-top:.25rem;color:#1f2937;font-weight:500;">{{ auth()->user()->email ?? '-' }}</p>
</div>
<div>
<p style="font-size:.7rem;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.05em;">No. Telepon</p>
<p style="margin-top:.25rem;color:#1f2937;font-weight:500;">{{ auth()->user()->phone ?? '-' }}</p>
</div>
<div>
<p style="font-size:.7rem;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.05em;">Jenis Kelamin</p>
<p style="margin-top:.25rem;color:#1f2937;font-weight:500;text-transform:capitalize;">{{ auth()->user()->gender ?? '-' }}</p>
</div>
<div>
<p style="font-size:.7rem;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.05em;">Divisi</p>
<p style="margin-top:.25rem;color:#1f2937;font-weight:500;">{{ auth()->user()->division ?? '-' }}</p>
</div>
<div>
<p style="font-size:.7rem;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.05em;">Jabatan</p>
<p style="margin-top:.25rem;color:#1f2937;font-weight:500;">{{ auth()->user()->position ?? '-' }}</p>
</div>
<div class="full-width">
<p style="font-size:.7rem;font-weight:600;color:#9ca3af;text-transform:uppercase;letter-spacing:.05em;">Alamat</p>
<p style="margin-top:.25rem;color:#1f2937;font-weight:500;">{{ auth()->user()->address ?? '-' }}</p>
</div>
</div>
</div>
{{-- Edit Mode (hidden by default) --}}
<div id="edit-mode" style="display:none;padding:1.5rem;">
<form method="post" action="{{ route('profile.update') }}" enctype="multipart/form-data">
@csrf
@method('patch')
<div class="form-grid">
{{-- NIP --}}
<div>
<div class="flex items-center">
<x-input-label for="nip" value="NIP" /><span style="color:#ef4444;margin-left:2px;">*</span>
</div>
<x-text-input id="nip" name="nip" type="text" class="mt-1 block w-full" :value="old('nip', $user->nip)" required />
<x-input-error class="mt-2" :messages="$errors->get('nip')" />
</div>
{{-- Nama --}}
<div>
<div class="flex items-center">
<x-input-label for="name" value="Nama Lengkap" /><span style="color:#ef4444;margin-left:2px;">*</span>
</div>
<x-text-input id="name" name="name" type="text" class="mt-1 block w-full" :value="old('name', $user->name)" required autofocus autocomplete="name" />
<x-input-error class="mt-2" :messages="$errors->get('name')" />
</div>
{{-- Email --}}
<div>
<div class="flex items-center">
<x-input-label for="email" value="Email" /><span style="color:#ef4444;margin-left:2px;">*</span>
</div>
<x-text-input id="email" name="email" type="email" class="mt-1 block w-full" :value="old('email', $user->email)" required autocomplete="username" />
<x-input-error class="mt-2" :messages="$errors->get('email')" />
@if ($user instanceof \Illuminate\Contracts\Auth\MustVerifyEmail && ! $user->hasVerifiedEmail())
<div style="margin-top:.5rem;">
<p style="font-size:.875rem;color:#374151;">
{{ __('Your email address is unverified.') }}
<button form="send-verification" style="text-decoration:underline;color:#4A538F;font-size:.875rem;background:none;border:none;cursor:pointer;">
{{ __('Click here to re-send the verification email.') }}
</button>
</p>
@if (session('status') === 'verification-link-sent')
<p style="margin-top:.25rem;font-size:.875rem;color:#16a34a;">
{{ __('A new verification link has been sent to your email address.') }}
</p>
@endif
</div>
@endif
</div>
{{-- No Telepon --}}
<div>
<div class="flex items-center">
<x-input-label for="phone" value="No. Telepon" /><span style="color:#ef4444;margin-left:2px;">*</span>
</div>
<x-text-input id="phone" name="phone" type="text" class="mt-1 block w-full" :value="old('phone', $user->phone)" required />
<x-input-error class="mt-2" :messages="$errors->get('phone')" />
</div>
{{-- Jenis Kelamin --}}
<div>
<div class="flex items-center">
<x-input-label for="gender" value="Jenis Kelamin" /><span style="color:#ef4444;margin-left:2px;">*</span>
</div>
<select id="gender" name="gender" required class="mt-1 block w-full border-gray-300 rounded-md shadow-sm text-sm">
<option value="">Pilih jenis kelamin</option>
<option value="laki-laki" @selected(old('gender', $user->gender) === 'laki-laki')>Laki-laki</option>
<option value="perempuan" @selected(old('gender', $user->gender) === 'perempuan')>Perempuan</option>
</select>
<x-input-error class="mt-2" :messages="$errors->get('gender')" />
</div>
{{-- Divisi --}}
<div>
<div class="flex items-center">
<x-input-label for="division" value="Divisi" /><span style="color:#ef4444;margin-left:2px;">*</span>
</div>
<x-text-input id="division" name="division" type="text" class="mt-1 block w-full" :value="old('division', $user->division)" required />
<x-input-error class="mt-2" :messages="$errors->get('division')" />
</div>
{{-- Jabatan --}}
<div>
<x-input-label for="position" value="Jabatan" />
<x-text-input id="position" name="position" type="text" class="mt-1 block w-full" :value="old('position', $user->position)" />
<x-input-error class="mt-2" :messages="$errors->get('position')" />
</div>
{{-- Alamat --}}
<div class="full-width">
<x-input-label for="address" value="Alamat" />
<textarea id="address" name="address" rows="3"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm text-sm">{{ old('address', $user->address) }}</textarea>
<x-input-error class="mt-2" :messages="$errors->get('address')" />
</div>
</div>
{{-- Actions --}}
<div style="margin-top:1.5rem;padding-top:1.25rem;border-top:1px solid #e5e7eb;display:flex;align-items:center;gap:.75rem;">
<x-primary-button>
<svg style="width:16px;height:16px;margin-right:6px;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
Simpan Perubahan
</x-primary-button>
<button type="button" onclick="toggleEditMode()"
style="padding:.5rem 1rem;font-size:.875rem;font-weight:500;color:#4b5563;background:#f3f4f6;border:none;border-radius:.5rem;cursor:pointer;">
Batal
</button>
@if (session('status') === 'profile-updated')
<p x-data="{ show: true }" x-show="show" x-transition
x-init="setTimeout(() => show = false, 2000)"
style="font-size:.875rem;color:#16a34a;font-weight:500;">
Profil berhasil diperbarui
</p>
@endif
</div>
</form>
</div>
</div>
</div>
</div>{{-- /panel-info --}}
{{-- Tab: Ubah Password --}}
<div id="panel-password" style="display:none;">
<div style="max-width:520px;margin:0 auto;background:#fff;border-radius:16px;box-shadow:0 1px 4px rgba(0,0,0,.12);overflow:hidden;">
{{-- Header --}}
<div class="card-header">
<div style="display:flex;align-items:center;gap:.75rem;">
<div style="width:40px;height:40px;border-radius:50%;background:rgba(255,255,255,.2);display:flex;align-items:center;justify-content:center;">
<svg width="20" height="20" fill="none" stroke="white" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
</svg>
</div>
<div>
<h3 style="font-size:1.1rem;font-weight:700;color:#fff;margin:0;">Ubah Password</h3>
<p style="font-size:.875rem;color:rgba(255,255,255,.7);margin:0;">Gunakan password yang kuat dan unik</p>
</div>
</div>
</div>
<div style="padding:1.5rem;">
<form method="post" action="{{ route('password.update') }}" style="display:flex;flex-direction:column;gap:1.25rem;">
@csrf
@method('put')
<div>
<x-input-label for="update_password_current_password" :value="__('Password Saat Ini')" />
<x-text-input id="update_password_current_password" name="current_password" type="password"
class="mt-1 block w-full" autocomplete="current-password" />
<x-input-error :messages="$errors->updatePassword->get('current_password')" class="mt-2" />
</div>
<div>
<x-input-label for="update_password_password" :value="__('Password Baru')" />
<x-text-input id="update_password_password" name="password" type="password"
class="mt-1 block w-full" autocomplete="new-password" />
<x-input-error :messages="$errors->updatePassword->get('password')" class="mt-2" />
</div>
<div>
<x-input-label for="update_password_password_confirmation" :value="__('Konfirmasi Password Baru')" />
<x-text-input id="update_password_password_confirmation" name="password_confirmation" type="password"
class="mt-1 block w-full" autocomplete="new-password" />
<x-input-error :messages="$errors->updatePassword->get('password_confirmation')" class="mt-2" />
</div>
<div style="padding-top:1.25rem;border-top:1px solid #e5e7eb;display:flex;align-items:center;gap:.75rem;">
<x-primary-button>
<svg style="width:16px;height:16px;margin-right:6px;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
</svg>
Simpan Password
</x-primary-button>
@if (session('status') === 'password-updated')
<p x-data="{ show: true }" x-show="show" x-transition
x-init="setTimeout(() => show = false, 2000)"
style="font-size:.875rem;color:#16a34a;font-weight:500;">
Password berhasil diperbarui
</p>
@endif
</div>
</form>
</div>
</div>
</div>{{-- /panel-password --}}
</div>
<script>
function switchTab(tab) {
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.classList.remove('active');
});
document.getElementById('tab-' + tab).classList.add('active');
document.getElementById('panel-info').style.display = (tab === 'info') ? 'block' : 'none';
document.getElementById('panel-password').style.display = (tab === 'password') ? 'block' : 'none';
}
function toggleEditMode() {
const viewMode = document.getElementById('view-mode');
const editMode = document.getElementById('edit-mode');
const btnEdit = document.getElementById('btn-edit-profil');
if (editMode.style.display === 'none' || editMode.style.display === '') {
viewMode.style.display = 'none';
editMode.style.display = 'block';
btnEdit.innerHTML = `<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/></svg> Tutup`;
} else {
viewMode.style.display = 'block';
editMode.style.display = 'none';
btnEdit.innerHTML = `<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"/></svg> Edit Profil`;
}
}
// Auto-open edit mode if there are validation errors on profile fields
@if($errors->hasAny(['name', 'email', 'nip', 'phone', 'gender', 'address', 'division', 'position', 'profile_photo']))
document.addEventListener('DOMContentLoaded', function() {
toggleEditMode();
});
@endif
// Auto-switch to password tab if there are password errors
@if($errors->updatePassword->any())
document.addEventListener('DOMContentLoaded', function() {
switchTab('password');
});
@endif
</script>
</x-app-layout>