744 lines
36 KiB
PHP
Executable File
744 lines
36 KiB
PHP
Executable File
<?php
|
|
|
|
use App\Models\Attendance;
|
|
use App\Models\User;
|
|
use App\Models\ai;
|
|
use Morilog\Jalali\Jalalian;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Support\Collection;
|
|
|
|
$Attendance = isset($_COOKIE['user_identity'])
|
|
? ($_COOKIE['user_identity'] == 1370
|
|
? Attendance::all()
|
|
: Attendance::where('user_identity', $_COOKIE['user_identity'])->get())
|
|
: collect();
|
|
|
|
$jalalian_object = Jalalian::now();
|
|
|
|
$first_day_of_month = $jalalian_object->subDays($jalalian_object->getDay() - 1);
|
|
$carbon_gregorian = $first_day_of_month->toCarbon();
|
|
$thismonth = $carbon_gregorian->format('Y-m-d 00:00:00');
|
|
|
|
|
|
$ids = json_decode(request()->cookie('seen_angizeh_ids', '[]'), true) ?: [];
|
|
$s = ai::where('key', 'angizeh')
|
|
->when($ids, fn($q) => $q->whereNotIn('id', $ids))
|
|
->orderByDesc('id')
|
|
->first()
|
|
?? ai::where('key', 'angizeh')->orderByDesc('id')->first();
|
|
$ids = array_merge($ids, [$s->id]);
|
|
Cookie::queue('seen_angizeh_ids', json_encode($ids), 14400);
|
|
|
|
|
|
//total time
|
|
$now = Jalalian::fromCarbon(Carbon::now());
|
|
$tsec = 0;
|
|
//dd(->user_profile);
|
|
if (isset($_COOKIE['token01'])) {
|
|
$a = json_decode($_COOKIE['token01']);
|
|
$user = User::where('user_name', $a->user_profile)->with('attendances')->first();
|
|
|
|
} else {
|
|
$user = isset($_COOKIE['user_identity']) ? User::where('user_name', $_COOKIE['user_identity'])->with('attendances')->first() : null;
|
|
}
|
|
//dd($user);
|
|
if (!empty($user->attendanes)) {
|
|
foreach ($user->attendances as $att) {
|
|
$date = $att->entered_at != null ? Jalalian::fromCarbon(Carbon::parse($att->entered_at)) : null;
|
|
$att->date = $date != null ? $date->format('Y/m/d') : null;
|
|
if ($att->duration != null && $date != null && $now->getMonth() == $date->getMonth()) {
|
|
[$h, $m, $sec] = explode(':', $att->duration);
|
|
$tsec += $h * 3600 + $m * 60 + $sec;
|
|
}
|
|
}
|
|
}
|
|
$hours = floor($tsec / 3600);
|
|
$minutes = floor(($tsec % 3600) / 60);
|
|
|
|
|
|
$totalTime = sprintf('%02d:%02d', $hours, $minutes);
|
|
|
|
$formaction = (isset($_COOKIE['ad']) && $_COOKIE['ad'] == 1)
|
|
? 'admin/'
|
|
: 'attendance/';
|
|
$now = Carbon::now()->format('Y-m-d');
|
|
$existed = $Attendance->whereNull('exited_at')->first();
|
|
$requested = $Attendance->whereNull('exited_at')->where('requested', 'true')->first();
|
|
$lastday = $Attendance->whereNull('exited_at')->where('entered_at', '<', $now)->first();
|
|
$forgot = $lastday ? Carbon::parse($lastday->entered_at)->format('Y-m-d') : '';
|
|
//dd($lastday);
|
|
|
|
|
|
$hash = md5(strtolower(trim($user->email)));
|
|
$gravatarUrl = "https://www.gravatar.com/avatar/$hash?s=200&d=identicon";
|
|
|
|
|
|
?>
|
|
@extends('app')
|
|
@section('content')
|
|
|
|
<div class="container flex-col"
|
|
style="letter-spacing: 0;display: flex;justify-content: center;align-items: center; margin : 90px 0 10px 0">
|
|
|
|
|
|
{{-- <button type="button"--}}
|
|
{{-- class="fixed max-w-[350px] bottom-24 right-9 z-50--}}
|
|
{{-- w-16 h-16 flex items-center justify-center--}}
|
|
{{-- text-white rounded-full--}}
|
|
{{-- bg-blue-500 hover:bg-blue-600--}}
|
|
{{-- shadow-lg cursor-pointer transition-all duration-300"--}}
|
|
{{-- onclick="openModal('ثبت روز کاری جدید', 'new')">--}}
|
|
{{-- ثبت روز جدید--}}
|
|
{{-- </button>--}}
|
|
@if (!isset($_COOKIE['token-0']))
|
|
|
|
<form id="attendanceForm" class="form" action="{{ url('attendance/enter') }}" method="post"
|
|
style="text-align: left">
|
|
@csrf
|
|
<p class="title text-center font-bold text-lg mb-2">سامانه گذارش کار</p>
|
|
<p class="message text-right text-sm text-gray-700">{{ $s->response }}</p>
|
|
|
|
@php
|
|
$user_identity = $_COOKIE['user_identity'] ?? '';
|
|
@endphp
|
|
|
|
<input type="hidden" name="latitude" id="latitude">
|
|
<input type="hidden" name="longitude" id="longitude">
|
|
<input type="hidden" name="distance" id="distance">
|
|
|
|
<p id="distanceMessage" class="text-center mb-2 font-semibold text-gray-600">در حال بررسی موقعیت...</p>
|
|
|
|
<button id="submitBtn" disabled type="button"
|
|
class="bg-gray-400 text-white rounded cursor-not-allowed rounded-xl py-2 px-4 max-w-60 self-center"
|
|
style="width: 100%">
|
|
ورود/خروج
|
|
</button>
|
|
|
|
<div class="flex justify-flex" style="align-items: center;">
|
|
<button type="button"
|
|
class="w-1/2 p-2 text-sm text-white text-center rounded-xl bg-cyan-600 hover:bg-cyan-800 cursor-pointer"
|
|
onclick="openModal('ثبت روز کاری جدید', 'new')">
|
|
ثبت روز کاری
|
|
</button>
|
|
|
|
<button type="button" id="breakAttendance"
|
|
class="w-1/2 p-2 text-sm text-white text-center rounded-xl bg-gray-500 hover:bg-gray-600
|
|
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50 cursor-pointer mx-auto"
|
|
href="">
|
|
استراحت
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
<script>
|
|
let breakStarted = false;
|
|
let breakStartTime = null;
|
|
let breakTimer = null;
|
|
|
|
const breakBtn = document.getElementById('breakAttendance');
|
|
|
|
function formatLocalDatetime(date) {
|
|
const year = date.getFullYear();
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
const hours = String(date.getHours()).padStart(2, '0');
|
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
}
|
|
|
|
function formatDuration(totalSeconds) {
|
|
const hours = Math.floor(totalSeconds / 3600);
|
|
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
|
|
const h = String(hours);
|
|
const i = String(minutes).padStart(2, '0');
|
|
|
|
return `${h}:${i}`;
|
|
}
|
|
|
|
|
|
breakBtn.addEventListener('click', () => {
|
|
if (!breakStarted) {
|
|
// شروع استراحت 🚀
|
|
breakStarted = true;
|
|
breakStartTime = new Date();
|
|
|
|
// تغییر ظاهر دکمه و شروع تایمر (همچنان M:S نمایش داده می شود)
|
|
breakBtn.classList.remove('bg-gray-500', 'hover:bg-gray-600');
|
|
breakBtn.classList.add('bg-red-500', 'hover:bg-red-600');
|
|
breakBtn.textContent = '00:00';
|
|
|
|
let seconds = 0;
|
|
breakTimer = setInterval(() => {
|
|
seconds++;
|
|
// اینجا همچنان به صورت دقیقه:ثانیه نمایش داده می شود
|
|
const m = String(Math.floor(seconds / 60)).padStart(2, '0');
|
|
const s = String(seconds % 60).padStart(2, '0');
|
|
breakBtn.textContent = ` ${m}:${s}`;
|
|
}, 1000);
|
|
//send start time
|
|
let formData = new FormData();
|
|
formData.append('start_time', formatLocalDatetime(breakStartTime));
|
|
|
|
formData.append('_token', '{{ csrf_token() }}');
|
|
|
|
fetch("{{ url('attendance/break') }}", {
|
|
method: "POST",
|
|
body: formData
|
|
})
|
|
.then(res => res.json())
|
|
.then(data => console.log('✅ Break Started Logged:', data))
|
|
.catch(err => console.error('💥 Error starting break:', err));
|
|
|
|
} else {
|
|
// پایان استراحت 🛑
|
|
breakStarted = false;
|
|
const breakEndTime = new Date();
|
|
clearInterval(breakTimer);
|
|
|
|
// 1. محاسبه مدت زمان استراحت (بر حسب ثانیه)
|
|
const durationSec = Math.floor((breakEndTime - breakStartTime) / 1000);
|
|
|
|
// 2. تبدیل زمان های شروع و پایان به فرمت رشته ای
|
|
const breakStartTime_str = formatLocalDatetime(breakStartTime);
|
|
const breakEndTime_str = formatLocalDatetime(breakEndTime);
|
|
|
|
// 3. فرمت کردن مدت زمان به H:i (فقط برای نمایش در کنسول/هشدار)
|
|
const duration_formatted_h_i = formatDuration(durationSec);
|
|
|
|
// 4. نمایش دکمه به حالت اولیه
|
|
breakBtn.classList.remove('bg-red-500', 'hover:bg-red-600');
|
|
breakBtn.classList.add('bg-gray-500', 'hover:bg-gray-600');
|
|
breakBtn.textContent = 'استراحت';
|
|
|
|
// 5. ارسال دادهها به سرور
|
|
let formData = new FormData();
|
|
formData.append('start_time', breakStartTime_str);
|
|
formData.append('end_time', breakEndTime_str);
|
|
formData.append('duration_seconds', durationSec);
|
|
formData.append('_token', '{{ csrf_token() }}');
|
|
|
|
fetch("{{ url('attendance/break') }}", {
|
|
method: "POST",
|
|
body: formData
|
|
})
|
|
.then(res => res.json())
|
|
.then(data => console.log('✅ Break saved:', data))
|
|
.catch(err => console.error('💥 Error:', err));
|
|
}
|
|
});
|
|
</script>
|
|
|
|
@else
|
|
{{-- <button type="button"--}}
|
|
{{-- class="fixed max-w-[350px] bottom-24 right-9 z-50--}}
|
|
{{-- w-14 h-14 flex items-center justify-center--}}
|
|
{{-- text-white rounded-full--}}
|
|
{{-- bg-blue-500 hover:bg-blue-600--}}
|
|
{{-- shadow-lg cursor-pointer transition-all duration-300"--}}
|
|
{{-- onclick="openModal('ثبت روز کاری جدید', 'new')">--}}
|
|
{{-- +--}}
|
|
{{-- </button>--}}
|
|
<div class="bg-white flex justify-flex p-4 rounded-xl max-w-[350px] flex-col items-center">
|
|
|
|
<img src="{{$user->picture ?? $gravatarUrl}}" alt="Profile Picture" class="w-16 h-16 rounded-full ">
|
|
<label>
|
|
{{$user->name}}
|
|
</label>
|
|
|
|
<button type="button"
|
|
class="w-auto p-2 text-sm text-white text-center rounded-xl bg-blue-500 hover:bg-blue-600 cursor-pointer"
|
|
onclick="openModal('ثبت روز کاری جدید', 'new')">
|
|
ثبت روز کاری
|
|
</button>
|
|
|
|
|
|
</div>
|
|
@endif
|
|
|
|
|
|
<script>
|
|
{{-- naser--}}
|
|
{{-- @php--}}
|
|
{{-- $requested = $Attendance->whereNull('exited_at')->where('requested', 'true')->first();--}}
|
|
{{-- @endphp--}}
|
|
const existed = {{ $requested ? 'false' : ($existed ? 'true' : 'false') }};
|
|
const forgot = {{$forgot ? 'true' : 'false'}};
|
|
const distanceMessage = document.getElementById("distanceMessage");
|
|
|
|
|
|
const referenceLat = 32.6504751;
|
|
const referenceLng = 51.6936045;
|
|
|
|
const submitBtn = document.getElementById("submitBtn");
|
|
const latInput = document.getElementById("latitude");
|
|
const lngInput = document.getElementById("longitude");
|
|
const distanceInput = document.getElementById("distance");
|
|
const form = document.getElementById("attendanceForm");
|
|
// naser
|
|
if (existed && !forgot) {
|
|
submitBtn.textContent = "خروج";
|
|
} else {
|
|
submitBtn.textContent = "ورود";
|
|
}
|
|
|
|
|
|
function getDistanceInMeters(lat1, lon1, lat2, lon2) {
|
|
const earthRadius = 6371000; // meters
|
|
const toRad = deg => deg * Math.PI / 180;
|
|
const dLat = toRad(lat2 - lat1);
|
|
const dLon = toRad(lon2 - lon1);
|
|
lat1 = toRad(lat1);
|
|
lat2 = toRad(lat2);
|
|
const a = Math.sin(dLat / 2) ** 2 +
|
|
Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon / 2) ** 2;
|
|
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
return earthRadius * c;
|
|
}
|
|
|
|
navigator.geolocation.getCurrentPosition(
|
|
position => {
|
|
const lat = position.coords.latitude;
|
|
const lng = position.coords.longitude;
|
|
|
|
latInput.value = lat;
|
|
lngInput.value = lng;
|
|
|
|
const dist = Math.round(getDistanceInMeters(referenceLat, referenceLng, lat, lng));
|
|
distanceInput.value = dist;
|
|
distanceMessage.textContent = `فاصله: ${dist} متر`;
|
|
|
|
distanceMessage.classList.remove("bg-gray-400", "bg-blue-500", "bg-green-500", "bg-orange-500", "cursor-not-allowed");
|
|
if (dist < 10) {
|
|
distanceMessage.classList.add("text-green-500");
|
|
} else if (dist < 50) {
|
|
distanceMessage.classList.add("text-blue-500");
|
|
} else if (dist > 2000) {
|
|
distanceMessage.classList.add("text-orange-500");
|
|
} else {
|
|
distanceMessage.classList.add("text-gray-400");
|
|
}
|
|
submitBtn.disabled = false;
|
|
submitBtn.classList.remove("bg-gray-400", "cursor-not-allowed");
|
|
submitBtn.classList.add("bg-cyan-500", "hover:bg-cyan-700", "cursor-pointer");
|
|
|
|
},
|
|
error => alert("⛔ خطا در دریافت موقعیت مکانی: " + error.message), {
|
|
enableHighAccuracy: true,
|
|
timeout: 10000,
|
|
maximumAge: 0
|
|
}
|
|
);
|
|
const attendanceForm = document.getElementById('attendanceForm');
|
|
|
|
const output = document.getElementById('output');
|
|
const challenge = new Uint8Array(32);
|
|
window.crypto.getRandomValues(challenge);
|
|
const createOptions = {
|
|
challenge,
|
|
rp: {
|
|
name: "مثال سایت شما"
|
|
},
|
|
user: {
|
|
id: Uint8Array.from('user-id', c => c.charCodeAt(0)),
|
|
name: "user@example.com",
|
|
displayName: "نام کاربر"
|
|
},
|
|
pubKeyCredParams: [{
|
|
type: 'public-key',
|
|
alg: -7
|
|
}],
|
|
authenticatorSelection: {
|
|
authenticatorAttachment: "platform",
|
|
userVerification: "required"
|
|
},
|
|
timeout: 60000,
|
|
attestation: "direct"
|
|
};
|
|
submitBtn.addEventListener('click', async () => {
|
|
|
|
// ابتدا اعتبارسنجی اثر انگشت توسط WebAuthn
|
|
if (!window.PublicKeyCredential) {
|
|
alert('مرورگر شما از احراز هویت بیومتریک پشتیبانی نمیکند.');
|
|
return;
|
|
}
|
|
try {
|
|
const credential = await navigator.credentials.create({
|
|
publicKey: createOptions
|
|
});
|
|
attendanceForm.submit();
|
|
} catch (error) {
|
|
output.textContent = error.name === 'NotAllowedError' ? 'احراز هویت لغو شد یا دسترسی مجاز نبود.' : 'عملیات ناموفق بود. لطفاً دوباره امتحان کنید.';
|
|
}
|
|
});
|
|
</script>
|
|
|
|
|
|
<div class="w-full flex justify-center mt-4" style="">
|
|
<div class="overflow-hidden border border-gray-300 rounded-[23px] bg-white max-w-[350px]">
|
|
<div class=" border-b border-gray-300 text-center w-full">
|
|
|
|
|
|
<!-- Your Table Code Here -->
|
|
<div class="w-[350px]">
|
|
|
|
@if(isset($_COOKIE['user_identity']))
|
|
<table class="min-w-full bg-white shadow-md rounded-lg table-auto">
|
|
<thead class=" text-black sticky top-0 z-10"
|
|
style="background: rgba(244,244,244,0.82);border-bottom: 1px solid;border-color: #e1e1e1 ">
|
|
<tr>
|
|
@if($_COOKIE['user_identity'] == 1370)
|
|
<th class="py-3 px-6 text-right font-medium text-black uppercase tracking-wider"
|
|
style="color: #2c2c2c">نام
|
|
</th>
|
|
@endif
|
|
{{-- {{dd($user)}}--}}
|
|
<th class="py-3 px-6 text-right font-medium text-black uppercase tracking-wider"
|
|
style="color: #2c2c2c">تاریخ
|
|
<th class="py-3 px-6 text-right font-medium text-black uppercase tracking-wider"
|
|
style="color: #2c2c2c">ورود
|
|
</th>
|
|
<th class="py-3 px-6 text-center font-medium text-black uppercase tracking-wider"
|
|
style="color: #2c2c2c">
|
|
خروج
|
|
</th>
|
|
{{-- <th class="py-3 px-6 text-center font-medium text-black uppercase tracking-wider"--}}
|
|
{{-- style="color: #2c2c2c">--}}
|
|
{{-- استراحت--}}
|
|
{{-- </th>--}}
|
|
<th class="py-3 px-6 text-center font-medium text-black uppercase tracking-wider"
|
|
style="color: #2c2c2c">جمع
|
|
</th>
|
|
|
|
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-200">
|
|
@foreach($user->attendances as $item)
|
|
{{--{{dd($item)}}--}}
|
|
<tr class="hover:bg-red-100 cursor-pointer "
|
|
style="background-color: {{$item->requested ? '#bfdbfe' : '#ffffff' }}"
|
|
onclick="openModal('{{ $item->id }}', '{{ $item->id }}' , '{{ $item->entered_at }}', '{{ $item->exited_at }} ')">
|
|
@if($_COOKIE['user_identity'] == 1370)
|
|
<td class="py-4 px-6 text-sm text-gray-900 whitespace-nowrap">
|
|
{{$item->user_identity}}
|
|
</td>
|
|
@endif
|
|
|
|
<td class="py-4 px-6 text-sm text-gray-900 whitespace-nowrap text-right"
|
|
style="background-color: {{$item->requested ? '' :($item->distance < 10 ? '#d1fae5' : ($item->distance < 50 ? '#dbeafe' : ($item->distance > 2000 ? '#ffedd5' : '#f3f4f6'))) }}; color: #111827;">
|
|
{{ $item->entered_at ? Jalalian::fromCarbon(Carbon::parse($item->entered_at))->format('m/d') : '-' }}
|
|
</td>
|
|
|
|
<td class="py-4 px-6 text-sm text-gray-900 whitespace-nowrap text-right"
|
|
style="background-color: {{ $item->requested ? '' :($item->distance < 10 ? '#d1fae5' : ($item->distance < 50 ? '#dbeafe' : ($item->distance > 2000 ? '#ffedd5' : '#f3f4f6'))) }}; color: #111827;">
|
|
{{ $item->entered_at ? Carbon::parse($item->entered_at)->format('H:i') : '-' }}
|
|
</td>
|
|
|
|
<td class="py-4 px-6 text-sm text-gray-900 whitespace-nowrap text-center"
|
|
style="background-color: {{ $item->requested ? '' :($item->distance_exit < 10 ? '#d1fae5' : ($item->distance_exit < 50 ? '#dbeafe' : ($item->distance_exit > 2000 ? '#ffedd5' : '#f3f4f6'))) }}; color: #111827;">
|
|
{{ $item->exited_at ? Carbon::parse($item->exited_at)->format('H:i') : '-' }}
|
|
</td>
|
|
|
|
{{-- <td class="py-4 px-6 text-sm text-gray-900 whitespace-nowrap text-center"--}}
|
|
{{-- style="background-color: {{ $item->requested ? '' :($item->distance_exit < 10 ? '#d1fae5' : ($item->distance_exit < 50 ? '#dbeafe' : ($item->distance_exit > 2000 ? '#ffedd5' : '#f3f4f6'))) }}; color: #111827;">--}}
|
|
{{-- میزان استراحت--}}
|
|
{{-- </td>--}}
|
|
|
|
<td class="py-4 px-6 text-sm text-gray-900 whitespace-nowrap">
|
|
{{ $item->entered_at && $item->exited_at ? Carbon::parse($item->duration)->format('H:i') : '-' }}
|
|
</td>
|
|
|
|
|
|
</tr>
|
|
<tr class="spacer">
|
|
</tr>
|
|
@endforeach
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
@endif
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- Modals -->
|
|
<!-- Modals -->
|
|
<div id="modal-container"
|
|
class="fixed inset-0 z-50 hidden bg-black bg-opacity-60 flex items-center justify-center p-4">
|
|
<div id="modal-content" class=" bg-white p-4 sm:p-6 rounded-lg shadow-lg max-w-sm w-full relative">
|
|
<h2 id="modal-title" class="text-xl sm:text-2xl font-semibold mb-4 text-center"></h2>
|
|
<p id="modal-body" class="text-gray-700 mb-4 text-center"></p>
|
|
<div class="flex flex-col gap-4" style="align-items: center">
|
|
|
|
<div class="flex justify-center gap-2">
|
|
<div id="panel-access-link" href="#" class="" title="Panel Access"></div>
|
|
</div>
|
|
|
|
<form id="edit-form" method="post" action="{{$formaction.'edit'}}"
|
|
class="inline-block flex-col gap-2 flex items-center">
|
|
@csrf
|
|
|
|
<p id="new-date-label" style="display: none; text-align: right; ">تاریخ:</p>
|
|
<div id="new-date-group" class="input-group" style="margin: 20px; display: none;">
|
|
<input type="text" name="display_date" id="display_date"
|
|
class=" example1 form-control border p-2 rounded date-picker-input" value=""
|
|
readonly>
|
|
|
|
</div>
|
|
|
|
<p style=" ">ساعت شروع:</p>
|
|
<div class="input-group clockpicker border-2 border-gray-300 rounded-lg"
|
|
style="margin: 20px;">
|
|
<span class="input-group-addon bg-gray-200 align-middle text-stone-600 rounded-r-md p-2 pt-2.5">
|
|
<i class="fa-solid fa-clock"></i>
|
|
</span>
|
|
<input type="text" name="starttime" id="starttime"
|
|
class="form-control cursor-default p-2 w-36 "
|
|
placeholder="09:00
|
|
value="" readonly>
|
|
<button type="button" onclick="clearTime('starttime')"
|
|
class="p-2 bg-gray-200 hover:bg-gray-300 text-red-600 rounded-l-md w-9
|
|
title=" خالی کردن ساعت
|
|
">
|
|
×
|
|
</button>
|
|
</div>
|
|
|
|
<p>ساعت پایان:</p>
|
|
<div class="input-group clockpicker border-2 border-gray-300 rounded-lg"
|
|
style="margin: 20px;">
|
|
<span class="input-group-addon bg-gray-200 align-middle text-stone-600 rounded-r-md p-2 pt-2.5">
|
|
<i class="fa-solid fa-clock"></i>
|
|
</span>
|
|
<input type="text" name="endtime" id="endtime"
|
|
class="form-control cursor-default p-2 w-36"
|
|
placeholder="17:30"
|
|
value="" readonly>
|
|
<button type="button" onclick="clearTime('endtime')"
|
|
class="p-2 bg-gray-200 hover:bg-gray-300 text-red-600 rounded-l-md w-9
|
|
title=" خالی کردن ساعت
|
|
">
|
|
×
|
|
</button>
|
|
</div>
|
|
|
|
<input type="hidden" name="uname" id="uname" value="{{$user->user_name}}">
|
|
<input type="hidden" name="date" id="date" value="">
|
|
<input type="hidden" name="id" id="edit_id" value="">
|
|
|
|
<button type="submit" id="submit-edit-button" style="display: none;"
|
|
onclick="return confirmSubmit()">
|
|
ثبت تغییرات
|
|
</button>
|
|
</form>
|
|
|
|
<form id="delete-form" action="{{$formaction.'delete'}}" method="post" style="display: none;">
|
|
@csrf
|
|
<input type="hidden" name="id" id="delete_id" value="">
|
|
<button type="submit" id="submit-delete-button" onclick="return confirmSubmit()">
|
|
حذف
|
|
</button>
|
|
</form>
|
|
|
|
|
|
<div class="flex justify-center gap-2 mt-2 px-4">
|
|
|
|
<button type="button" class="bg-blue-500 text-white rounded p-2 **w-[70%]**"
|
|
onclick="document.getElementById('edit-form').submit(); return confirmSubmit()">
|
|
@if(isset($_COOKIE['ad']) && $_COOKIE['ad'] == 1)
|
|
ثبت تغییرات
|
|
@else
|
|
ارسال برای تایید
|
|
@endif
|
|
</button>
|
|
|
|
<button type="button" class="bg-red-500 text-white rounded p-2 **w-[30%]**"
|
|
onclick="document.getElementById('delete-form').submit(); return confirmSubmit()">
|
|
<i class="fas fa-trash text-white text-lg"></i>
|
|
</button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@endsection
|
|
|
|
@section('script')
|
|
<script>
|
|
function clearTime(fieldId) {
|
|
document.getElementById(fieldId).value = '';
|
|
}
|
|
|
|
function closeModal() {
|
|
document.getElementById('modal-container').classList.add('hidden');
|
|
}
|
|
|
|
document.getElementById('modal-container').addEventListener('click', (e) => {
|
|
if (e.target === document.getElementById('modal-container')) {
|
|
closeModal();
|
|
}
|
|
});
|
|
|
|
function confirmSubmit() {
|
|
return confirm("آیا تغییرات اعمال شوند؟");
|
|
}
|
|
|
|
function openModal(title, id, enteredAt, exitedAt) {
|
|
const isNewEntry = id === 'new';
|
|
const modalTitleElement = document.getElementById('modal-title');
|
|
|
|
// ✅ بهترین روش: انتخاب مستقیم فیلد مخفی با ID آن
|
|
const hiddenIdInput = document.getElementById('edit_id');
|
|
// const hiddenIdInput = document.getElementById('delete_id');
|
|
|
|
// انتخاب فیلد ID برای فرم حذف
|
|
const deleteIdInput = document.getElementById('delete_id');
|
|
const submitButton = document.querySelector('#modal-content button[type="submit"]');
|
|
const hiddenDateInput = document.querySelector('input[name="date"]');
|
|
|
|
// مقداردهی به فرم حذف
|
|
if (deleteIdInput) {
|
|
deleteIdInput.value = id;
|
|
}
|
|
|
|
const newDateLabel = document.getElementById('new-date-label');
|
|
const newDateGroup = document.getElementById('new-date-group');
|
|
const displayDateInput = document.getElementById('display_date');
|
|
|
|
const panelLink = document.getElementById('panel-access-link');
|
|
panelLink.href = `/go_down/${id}`;
|
|
|
|
document.getElementById('modal-container').classList.remove('hidden');
|
|
|
|
const startTimeInput = document.querySelector('input[name="starttime"]');
|
|
const endTimeInput = document.querySelector('input[name="endtime"]');
|
|
|
|
// تنظیم ساعتها
|
|
if (enteredAt && !isNaN(new Date(enteredAt).getTime())) {
|
|
startTimeInput.value = new Date(enteredAt).toLocaleTimeString('en-GB', {
|
|
hour: '2-digit',
|
|
minute: '2-digit'
|
|
});
|
|
} else {
|
|
startTimeInput.value = '09:00';
|
|
}
|
|
|
|
if (exitedAt && !isNaN(new Date(exitedAt).getTime())) {
|
|
endTimeInput.value = new Date(exitedAt).toLocaleTimeString('en-GB', {
|
|
hour: '2-digit',
|
|
minute: '2-digit'
|
|
});
|
|
}
|
|
// else {
|
|
// endTimeInput.value = '17:30';
|
|
// }
|
|
|
|
|
|
if (isNewEntry) {
|
|
// حالت ثبت جدید
|
|
modalTitleElement.innerText = 'ثبت روز کاری جدید';
|
|
newDateLabel.style.display = 'block';
|
|
newDateGroup.style.display = 'block';
|
|
|
|
displayDateInput.value = '';
|
|
hiddenDateInput.value = '';
|
|
|
|
// ✅ اصلاح: مقداردهی 'new' به فیلد ID
|
|
if (hiddenIdInput) hiddenIdInput.value = 'new';
|
|
|
|
submitButton.onclick = function () {
|
|
if (hiddenDateInput.value === '') {
|
|
alert("لطفاً یک تاریخ را از تقویم انتخاب کنید.");
|
|
return false;
|
|
}
|
|
return confirmSubmit();
|
|
};
|
|
|
|
} else {
|
|
// حالت ویرایش
|
|
modalTitleElement.innerText = 'تغییر ساعت کاری';
|
|
newDateLabel.style.display = 'none';
|
|
newDateGroup.style.display = 'none';
|
|
|
|
// ✅ اصلاح: استفاده از متغیر 'id' که از جدول فرستاده شده است
|
|
if (hiddenIdInput) hiddenIdInput.value = id;
|
|
if (hiddenDateInput) hiddenDateInput.value = enteredAt;
|
|
|
|
submitButton.onclick = function () {
|
|
return confirmSubmit();
|
|
};
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
$(document).ready(function () {
|
|
|
|
// 1. فعالسازی Clockpicker
|
|
$('.clockpicker').clockpicker({
|
|
autoclose: true,
|
|
placement: 'center',
|
|
align: 'left',
|
|
donetext: 'تایید',
|
|
vibrate: true,
|
|
// donetext: true,
|
|
});
|
|
|
|
|
|
$(".example1").persianDatepicker({
|
|
format: "YYYY/MM/DD",
|
|
altField: '#date',
|
|
altFormat: 'YYYY-MM-DD',
|
|
calendar: {
|
|
persian: {
|
|
locale: 'fa',
|
|
leapYearMode: "astronomical"
|
|
}
|
|
},
|
|
observer: true,
|
|
initialValue: false,
|
|
initialValueType: 'gregorian',
|
|
autoClose: true,
|
|
toolbox: {
|
|
calendarSwitch: {enabled: false},
|
|
todayButton: {enabled: true, text: {fa: "امروز"}}
|
|
},
|
|
onSelect: function (unix) {
|
|
// تبدیل تاریخ انتخابی به میلادی درست با timezone ایران
|
|
const d = new persianDate(unix).toCalendar('gregorian').toLocale('en');
|
|
console.log("Gregorian (Fixed):", d.format("YYYY-MM-DD"));
|
|
}
|
|
});
|
|
|
|
// 2. فعالسازی Persian Datepicker
|
|
// $('.example1').pDatepicker({
|
|
// format: 'YYYY/MM/DD',
|
|
// // placement: 'center',
|
|
// altField: '#date', // این فیلد مخفی، تاریخ میلادی تبدیل شده را دریافت میکند
|
|
// altFormat: 'YYYY-MM-DD', // میلادی ذخیره بشه
|
|
// // changeMonth: true,
|
|
// // changeYear: true,
|
|
// // showOtherMonths: true,
|
|
// // selectOtherMonths: true,
|
|
// autoClose: true,
|
|
//
|
|
// });
|
|
|
|
|
|
});
|
|
|
|
</script>
|
|
|
|
@endsection
|