203 lines
10 KiB
PHP
Executable File
203 lines
10 KiB
PHP
Executable File
@extends('app')
|
|
@section('content')
|
|
{{-- {{dd($user)}}--}}
|
|
<div class="w-full mt-[90px] justify-center container flex">
|
|
<div class="ui-card">
|
|
<div class="ui-card-body">
|
|
<img src="/assets/img/bg/bg-shape.jpg" class="rounded-full w-32 h-32 mx-auto pb-6" alt="">
|
|
{{-- <p class=""> تاریخ شروع همکاری:--}}
|
|
{{-- {{\Morilog\Jalali\Jalalian::fromCarbon(\Carbon\Carbon::parse($user->created_at))->format('Y/m/d')}}</p>--}}
|
|
@if ($errors->has('password'))
|
|
<div class="mt-3 mb-3 text-red-500 text-sm justify-self-center ">
|
|
<label>
|
|
{{ $errors->first('password') }}
|
|
</label>
|
|
</div>
|
|
@endif
|
|
<form action="{{route('edit.profile')}}" method="post"
|
|
class="grid grid-cols-2 gap-2 justify-items-stretch content-between text-sm indent-2.5 align-middle divide">
|
|
{{-- align-center text-sm text-start">--}}
|
|
{{-- <div class="grid grid-cols-2 h-64 gap-2 justify-items-stretch content-between text-sm indent-2.5 align-middle divide">--}}
|
|
@csrf
|
|
@if(!empty($viewerIsAdmin))
|
|
<input type="hidden" name="target_username" value="{{ $user->user_name }}">
|
|
@endif
|
|
|
|
<label class="pb-3">نام و نام خانوادگی:</label>
|
|
<input type="text" name="name" value="{{ $user->name ?? '' }}"
|
|
placeholder="نام و نام خانوادگی"
|
|
class="border border-gray-300 rounded-md text-center">
|
|
|
|
<label class="pb-3">ایمیل:</label>
|
|
<input type="email" name="email" value="{{ $user->email ?? '' }}"
|
|
placeholder="ایمیل"
|
|
class="border border-gray-300 rounded-md text-center">
|
|
|
|
<label class="pb-3">شماره تماس:</label>
|
|
<input type="tel" name="number" value="{{ $user->number ?? '' }}"
|
|
placeholder="شماره تماس"
|
|
pattern="^09\d{9}$"
|
|
class="border border-gray-300 rounded-md text-center" required>
|
|
|
|
<label class="pb-3">تاریخ تولد:</label>
|
|
<div class="flex flex-col gap-1">
|
|
<input type="text" id="birthday_display"
|
|
value="{{ $user->birthday ? \App\Support\JalaliHelper::format($user->birthday) : '' }}"
|
|
placeholder="اختیاری — انتخاب تاریخ"
|
|
class="border border-gray-300 rounded-md text-center"
|
|
autocomplete="off" readonly>
|
|
<input type="hidden" name="birthday" id="birthday"
|
|
value="{{ $user->birthday ? $user->birthday->format('Y-m-d') : '' }}">
|
|
<button type="button" id="clear_birthday"
|
|
class="text-xs text-gray-500 hover:text-red-500 cursor-pointer self-end">
|
|
پاک کردن
|
|
</button>
|
|
</div>
|
|
|
|
<label class="pb-3">چت آیدی تلگرام:</label>
|
|
<input type="text" pattern="\d+" name="chatid" value="{{ $user->chatid ?? '' }}"
|
|
placeholder="چت آیدی تلگرام"
|
|
class="border border-gray-300 rounded-md text-center">
|
|
|
|
<label class="pb-3">رمز عبور:</label>
|
|
<input type="password" name="password" value="{{ $user->password ?? '' }}"
|
|
placeholder="رمز عبور"
|
|
class="input border border-gray-300 rounded-md text-center">
|
|
<input type="password" name="password_confirmation"
|
|
placeholder="تکرار رمز عبور"
|
|
class="input border border-gray-300 rounded-md text-center col-start-2 min-h-8">
|
|
|
|
@if(!empty($_COOKIE['ad']) && $_COOKIE['ad'] == 1)
|
|
<label class="pb-3">نقش کاربری:</label>
|
|
<select name="role" class="border border-gray-300 rounded-md text-center">
|
|
<option value="0" {{ $user->is_admin == 0 ? 'selected' : '' }}>کارمند</option>
|
|
<option value="1" {{ $user->is_admin == 1 ? 'selected' : '' }}>ادمین</option>
|
|
</select>
|
|
@endif
|
|
|
|
@if(!empty($viewerIsAdmin))
|
|
<label class="pb-3">ساعت شروع کار:</label>
|
|
<div class="flex flex-col gap-1">
|
|
<input type="time" name="work_start_time"
|
|
value="{{ $user->work_start_time ? substr((string) $user->work_start_time, 0, 5) : '' }}"
|
|
class="border border-gray-300 rounded-md text-center">
|
|
<span class="text-[11px] text-gray-500 indent-0">
|
|
خالی = پیشفرض {{ \App\Services\LatePenaltyService::WORK_START }}
|
|
</span>
|
|
</div>
|
|
@endif
|
|
<button type="submit"
|
|
class="col-span-2 bg-cyan-500 hover:bg-cyan-700 cursor-pointer
|
|
rounded-xl border border-400 justify-self-center
|
|
p-1.5 text-white">
|
|
ثبت تغییرات
|
|
</button>
|
|
{{-- </div>--}}
|
|
</form>
|
|
|
|
|
|
|
|
{{-- اضافه کن درست بعد از فرم یا قبل از دکمه submit --}}
|
|
<button type="button" id="registerFingerprint" class="...">ثبت اثر انگشت</button>
|
|
|
|
<script>
|
|
$(document).ready(function () {
|
|
$('#birthday_display').persianDatepicker({
|
|
format: 'YYYY/MM/DD',
|
|
autoClose: true,
|
|
initialValue: false,
|
|
toolbox: {
|
|
calendarSwitch: {enabled: false},
|
|
todayButton: {enabled: true, text: {fa: 'امروز'}}
|
|
},
|
|
onSelect: function (unix) {
|
|
const gregorian = new persianDate(unix).toCalendar('gregorian').toLocale('en');
|
|
$('#birthday').val(gregorian.format('YYYY-MM-DD'));
|
|
}
|
|
});
|
|
|
|
$('#clear_birthday').on('click', function () {
|
|
$('#birthday_display').val('');
|
|
$('#birthday').val('');
|
|
});
|
|
});
|
|
|
|
function base64urlToBuffer(base64url) {
|
|
const padding = '='.repeat((4 - base64url.length % 4) % 4);
|
|
const base64 = (base64url + padding).replace(/-/g, '+').replace(/_/g, '/');
|
|
const str = atob(base64);
|
|
const buf = new ArrayBuffer(str.length);
|
|
const view = new Uint8Array(buf);
|
|
for (let i = 0; i < str.length; i++) view[i] = str.charCodeAt(i);
|
|
return buf;
|
|
}
|
|
|
|
document.getElementById('registerFingerprint').addEventListener('click', async function() {
|
|
try {
|
|
// 1. گرفتن options از سرور
|
|
const res = await fetch("{{ route('fingerprint.register.options') }}", {
|
|
method: "POST",
|
|
headers: {
|
|
"X-CSRF-TOKEN": "{{ csrf_token() }}",
|
|
"Accept": "application/json"
|
|
}
|
|
});
|
|
|
|
const options = await res.json();
|
|
|
|
if (!options.publicKey) {
|
|
alert(options.error || "خطا در گرفتن options");
|
|
return;
|
|
}
|
|
|
|
// ✅ اینجا: تبدیل user.id و challenge به ArrayBuffer
|
|
options.publicKey.user.id = base64urlToBuffer(options.publicKey.user.id);
|
|
options.publicKey.challenge = base64urlToBuffer(options.publicKey.challenge);
|
|
|
|
// 2. ایجاد credential
|
|
const credential = await navigator.credentials.create({ publicKey: options.publicKey });
|
|
|
|
// 3. آمادهسازی payload برای verifyRegister
|
|
const payload = {
|
|
id: credential.id,
|
|
response: {
|
|
clientDataJSON: bufferToBase64url(credential.response.clientDataJSON),
|
|
attestationObject: bufferToBase64url(credential.response.attestationObject),
|
|
publicKey: "" // کنترلر استخراج میکنه
|
|
},
|
|
name: "دستگاه {{ $user->name }}"
|
|
};
|
|
|
|
// 4. ارسال به verifyRegister
|
|
const verifyRes = await fetch("{{ route('fingerprint.register.verify') }}", {
|
|
method: "POST",
|
|
headers: {
|
|
"X-CSRF-TOKEN": "{{ csrf_token() }}",
|
|
"Content-Type": "application/json",
|
|
"Accept": "application/json"
|
|
},
|
|
body: JSON.stringify(payload)
|
|
});
|
|
|
|
const verifyData = await verifyRes.json();
|
|
alert(verifyData.message || "ثبت اثر انگشت انجام شد");
|
|
|
|
} catch (e) {
|
|
console.error(e);
|
|
alert("خطا در ثبت اثر انگشت");
|
|
}
|
|
});
|
|
|
|
function bufferToBase64url(buffer) {
|
|
const bytes = new Uint8Array(buffer);
|
|
let str = '';
|
|
for (let i = 0; i < bytes.byteLength; i++) str += String.fromCharCode(bytes[i]);
|
|
return btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
}
|
|
</script>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@endsection
|