Improve tasks UI, dark theme, performance fixes, and admin pages polish

This commit is contained in:
2026-06-02 18:45:01 +03:30
parent 54aa8f40dd
commit 300575930f
18 changed files with 2598 additions and 780 deletions
+37 -111
View File
@@ -1,63 +1,9 @@
<?php
use App\Models\Attendance;
use App\Models\AttendanceBreak;
use Morilog\Jalali\Jalalian;
use Carbon\Carbon;
//dd($reqs);
$now = Jalalian::fromCarbon(Carbon::now());
foreach ($users as $user) {
$totaltime = 0;
$tsec = 0;
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, $s] = explode(':', $att->duration);
$tsec += $h * 3600 + $m * 60 + $s;
}
}
$hours = floor($tsec / 3600);
$minutes = floor(($tsec % 3600) / 60);
$seconds = $tsec % 60;
$totalTime = sprintf('%02d:%02d', $hours, $minutes);
$user->totaltime = $totalTime;
}
//dd($users);
$now = now()->format('Y-m-d');
foreach ($users as $u) {
$us = $u->attendances()
->whereNull('exited_at')
->latest('entered_at')
->first();
// dump($us);
if ($us) {
$us->entered_at = Carbon::parse($us->entered_at)->format('Y-m-d');
if ($us->entered_at == $now)
$us = true;
else
$us = false;
$u->working = $us ? 1 : 0;
} else
$u->working = 0;
foreach ($u->attendances as $u_att) {
$break = AttendanceBreak::wherenull('break_end')->where('attendance_id', $u_att->id)->exists();
if ($break)
$u->working = 2;
}
}
//dd($users);
$users = $users->sortByDesc('working');
//$users = json_decode(json: $users);
// $users = collect($users);
$usersChunked = $users->chunk(3);
//dd($users);
?>
@@ -66,43 +12,35 @@ $usersChunked = $users->chunk(3);
<div class="container w-full flex flex-col items-center">
@if(!collect($reqs)->pluck('attendances')->flatten()->isEmpty())
<div class="mt-10 bg-white rounded-lg shadow-md max-w-[350px] flex flex-col items-center">
<p style="min-font-size: 30; text-align: center; margin-bottom: 10px">درخواست ها</p>
{{-- {{dd($reqs)}}--}}
<div class="ui-requests-card flex flex-col items-center">
<p>درخواست ها</p>
@foreach ($reqs as $u)
@if(!empty($u['attendances']))
<button type="button"
class="w-[150px] p-3 font-bold text-white bg-blue-500 hover:bg-blue-700 rounded transition duration-150 text-center "
onclick="togglerequests('attendance-{{ $loop->index }}')"
style="margin: 10px 0; text-align: center; background-color: #00bcd4">
class="ui-chip-btn"
onclick="togglerequests('attendance-{{ $loop->index }}')">
{{ $u['name'] }}
</button>
{{-- @else--}}
{{-- <p class="text-stone-400" style="text-align: center">درخواستی ثبت نشده</p>--}}
{{-- @break--}}
@endif
<div id="attendance-{{ $loop->index }}" class="hidden-content pt-4">
<table style="max-width: 350px; margin: auto; text-align: center" class="w-[350px] table-auto">
<div id="attendance-{{ $loop->index }}" class="hidden-content pt-4 w-full">
<div class="ui-table-wrap">
<table class="w-full table-auto">
<thead>
<tr class="text-sm" style="background-color: #00a3ba; color: white; text-align: center;">
<th class="px-2 py-2 border w-1/6">درخواست</th>
<th class="px-2 py-2 border w-1/6">تاریخ</th>
<th class="px-2 py-2 border w-1/6">ورود</th>
<th class="px-2 py-2 border w-1/6">خروج</th>
{{-- @if($userType == 'admin')--}}
<th class="px-2 py-2 border w-1/6">تعیین وضعیت</th>
{{-- @endif--}}
<tr>
<th class="px-2 py-2 w-1/6">درخواست</th>
<th class="px-2 py-2 w-1/6">تاریخ</th>
<th class="px-2 py-2 w-1/6">ورود</th>
<th class="px-2 py-2 w-1/6">خروج</th>
<th class="px-2 py-2 w-1/6">تعیین وضعیت</th>
</tr>
</thead>
<tbody>
{{-- {{dd($u['attendances'])}}--}}
@forelse($u['attendances'] as $rec)
<tr style="background-color: {{$rec->id=='new' ? 'lightblue' : 'white'}}">
<tr class="{{ $rec->id=='new' ? 'is-new' : '' }}">
{{--{{dd($rec)}}--}}
<td class="px-4 py-2 border">{{ match ($rec->function) {
'edit' => "تغییر ساعت",
@@ -138,8 +76,7 @@ $usersChunked = $users->chunk(3);
<input type="hidden" name="update" id="update" value="approve">
<input type="hidden" name="data" id="data"
value="{{json_encode($rec)}}">
<button class="bg-white rounded w-full"
style="background-color: #81ff65; margin-bottom: 5px">
<button type="submit" class="ui-btn-approve">
تایید
</button>
</form>
@@ -148,8 +85,7 @@ $usersChunked = $users->chunk(3);
<input type="hidden" name="update" id="update" value="reject">
<input type="hidden" name="data" id="data"
value="{{json_encode($rec)}}">
<button class="bg-white rounded w-full"
style="background-color: #ff6565">
<button type="submit" class="ui-btn-reject">
رد
</button>
</form>
@@ -163,7 +99,8 @@ $usersChunked = $users->chunk(3);
@endforelse
</tbody>
</table>
</div> {{-- پایان hidden-content --}}
</div>
</div>
@endforeach
{{-- @if(collect($reqs)->pluck('attendances')->flatten()->isEmpty())--}}
{{-- <p class="text-stone-400" style="text-align: center">درخواستی ثبت نشده</p>--}}
@@ -175,38 +112,29 @@ $usersChunked = $users->chunk(3);
<div class="grid grid-cols-2 grid-rows-none ">
@foreach ($usersChunked as $chunk)
@foreach ($chunk as $u)
<div class="form m-3 justify-evenly rounded-lg shadow-md "
style="align-items: center; text-align: center; border: 2px solid
{{ $u->active_task ? '#00ff15' : ($u->working == 1 ? '#16c8ce' : ($u->working == 2 ? 'orange' : 'white' ))}}; padding: 10px; ">
@php
@endphp
<a href="/admin/{{ $u->user_name }}"
class=" rounded-xl"
style="text-decoration: none; color: inherit;">
<p style="font-weight: bold ; color:#333;">
{{ $u->name ?? $u->user_name }}
</p>
@php
$cardClass = 'ui-user-card m-3';
if ($u->active_task) {
$cardClass .= ' is-active';
} elseif ($u->working == 1) {
$cardClass .= ' is-working';
} elseif ($u->working == 2) {
$cardClass .= ' is-break';
}
@endphp
<div class="{{ $cardClass }}">
<a href="/admin/{{ $u->user_name }}">
<p class="ui-user-name">{{ $u->name ?? $u->user_name }}</p>
@if($u->active_task)
<p>وظیفه: {{ $u->active_task }}</p>
@endif
<p>
کارکرد ماه جاری:
{{ $u->totaltime }}
</p>
<p>
تعداد درخواست ها:
{{ $u->req_counts }}
</p>
<p>کارکرد ماه جاری: {{ $u->totaltime }}</p>
<p>تعداد درخواست ها: {{ $u->req_counts }}</p>
</a>
@if($userType == 'admin')
<button type="button"
class="rounded-lg bg-cyan-500 hover:bg-cyan-600"
onclick="window.location.href='{{ url('attendance/profile').'?username='.$u->user_name }}'"
style=" border: none; color: white; padding: 5px 10px; text-align: center; text-decoration: none;
display: inline-block; font-size: 16px; margin: 4px 2px; cursor: pointer; ">
class="ui-chip-btn mt-2 !min-w-0 !w-auto !text-sm"
onclick="window.location.href='{{ url('attendance/profile').'?username='.$u->user_name }}'">
ویرایش
</button>
@endif
@@ -214,10 +142,8 @@ $usersChunked = $users->chunk(3);
@endforeach
@endforeach
<a class="form m-3 justify-evenly rounded-lg shadow-md " href="{{route('admin.new')}}"
style="align-items: center; text-align: center; ">
<i class="fa-regular fa-plus "
style="font-size: 80px; width: 90%; height: 90%;"></i>
<a class="ui-user-card m-3 flex items-center justify-center min-h-[140px]" href="{{route('admin.new')}}">
<i class="fa-regular fa-plus text-5xl text-gray-400"></i>
</a>
</div>
+12 -14
View File
@@ -224,7 +224,7 @@ SVG;
@else
<div class="bg-white flex justify-flex p-4 rounded-xl max-w-[350px] flex-col items-center">
<div class="ui-panel 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>
@@ -361,7 +361,7 @@ SVG;
<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="overflow-hidden border border-gray-300 rounded-[23px] ui-panel max-w-[350px]">
<div class=" border-b border-gray-300 text-center w-full">
@@ -369,7 +369,7 @@ SVG;
<div class="w-[350px]">
@if(isset($_COOKIE['user_identity']))
<table class="min-w-full bg-white shadow-md rounded-lg table-auto">
<table class="min-w-full ui-attendance-table 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>
@@ -456,10 +456,10 @@ SVG;
<!-- ATTENDANCE Modal -->
<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>
class="ui-modal-backdrop centered hidden">
<div id="modal-content" class="ui-modal-panel max-w-sm w-full">
<h2 id="modal-title" class="ui-title"></h2>
<p id="modal-body" class="ui-subtitle"></p>
<div class="flex flex-col gap-4" style="align-items: center">
<div class="flex justify-center gap-2">
@@ -559,16 +559,14 @@ SVG;
{{-- START TASK MODAL --}}
<div id="taskModal"
class="hidden fixed inset-0 bg-black/40 items-start justify-center z-50 flex backdrop-blur-sm scroll-auto pt-10">
<div class="relative bg-white w-[350px] rounded-2xl shadow-lg p-5 text-center">
<button onclick="closeTaskModal()"
class="absolute top-3 right-3 text-gray-400 hover:text-gray-600 transition">
class="ui-modal-backdrop hidden">
<div class="ui-modal-panel">
<button type="button" onclick="closeTaskModal()" class="ui-modal-close" aria-label="بستن">
&times;
</button>
<h2 class="text-lg font-bold mb-3" id="modalTitle">انتخاب وظیفه</h2>
<p class="text-gray-600 mb-4" id="modalDesc">یکی از وظایف زیر را انتخاب کنید:</p>
<h2 class="ui-title" id="modalTitle">انتخاب وظیفه</h2>
<p class="ui-subtitle" id="modalDesc">یکی از وظایف زیر را انتخاب کنید:</p>
<div class="grid flex-col gap-2 grid-cols-2 pb-3 items-center justify-items-end">
@if(!empty($user->tasks))
+2 -3
View File
@@ -3,10 +3,9 @@
<div class=" flex flex-col items-center justify-center p-4 " dir="rtl"
style="padding-top: 50px">
<div class="bg-white p-6 md:p-8 rounded-2xl shadow-2xl w-[350px] max-w-sm border-t-8 border-[#16c8ce]">
<div class="ui-card ui-card-body w-[350px] max-w-sm" style="border-top: 4px solid var(--primary-color);">
<div class="text-center mb-6">
<h1 class="text-2xl font-extrabold text-gray-800 border-b pb-2">کاربر جدید</h1>
<h1 class="ui-title border-b border-gray-300 pb-2">کاربر جدید</h1>
</div>
<form id="attendanceForm" action="{{route('admin.new')}}" method="post" class="space-y-4">
+273 -86
View File
@@ -3,21 +3,17 @@
use Morilog\Jalali\Jalalian;
use Carbon\Carbon;
// پیدا کردن نام ماه قبل به تاریخ شمسی (مثلا اگر الان اسفند است، خروجی "بهمن" خواهد بود)
$previousMonthName = Jalalian::now()->subMonths(1)->format('%B');
// محاسبه مجموع کارکرد برای هر کارمند به تفکیک ماه
$employeeTotals = [];
foreach ($data as $employee) {
// تبدیل آبجکت به آرایه در صورت نیاز برای حلقه
$recordsGrouped = is_array($employee->records) ? $employee->records : (array)$employee->records;
$monthlyTotals = [];
foreach ($recordsGrouped as $month => $attendances) {
$tsec = 0;
foreach ($attendances as $attendance) {
// اگر duration موجود باشه استفاده می‌کنیم
if (!empty($attendance->duration)) {
[$h, $m, $s] = explode(':', $attendance->duration);
$tsec += (int)$h * 3600 + (int)$m * 60 + (int)$s;
@@ -26,29 +22,239 @@ foreach ($data as $employee) {
$hours = floor($tsec / 3600);
$minutes = floor(($tsec % 3600) / 60);
// ذخیره زمان برای این ماه
$monthlyTotals[$month] = sprintf('%02d:%02d', $hours, $minutes);
}
// ذخیره کل ماه‌ها برای این کارمند
$employeeTotals[$employee->id] = $monthlyTotals;
}
?>
@extends('app')
@section('content')
<div class="container flex flex-col items-center justify-center mx-auto pb-10">
@section('style')
<style>
.admin-show-page,
.ui-page {
width: 100%;
max-width: 420px;
margin: 0 auto;
padding: 0 0.5rem 1.5rem;
}
.admin-show-empty,
.ui-empty {
margin-top: 5rem;
text-align: center;
color: var(--text-muted);
font-size: 1.1rem;
font-weight: 700;
}
.employee-picker {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 0.45rem;
margin: 0.75rem 0 1rem;
padding: 0.75rem;
background: var(--surface-glass);
border: 1px solid var(--border-glass);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-soft);
backdrop-filter: blur(14px);
-webkit-backdrop-filter: blur(14px);
}
.emp-btn {
padding: 0.5rem 0.85rem;
border-radius: 9999px;
font-size: 0.82rem;
font-weight: 700;
border: 1px solid var(--border-input);
background: var(--surface-input);
color: var(--text-secondary);
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
}
.emp-btn:hover {
color: var(--text-primary);
background: var(--surface-tab-hover);
border-color: color-mix(in srgb, var(--primary-color) 35%, var(--border-input));
}
.emp-btn-active {
color: #fff;
background: var(--primary-color);
border-color: color-mix(in srgb, var(--primary-color) 80%, white);
box-shadow: 0 6px 18px color-mix(in srgb, var(--primary-color) 35%, transparent);
}
.employee-panel {
display: none;
flex-direction: column;
align-items: center;
width: 100%;
}
.employee-panel.is-visible {
display: flex;
}
.employee-header {
width: 100%;
max-width: 350px;
display: flex;
flex-direction: column;
gap: 0.65rem;
margin-bottom: 0.85rem;
}
.employee-header h2 {
margin: 0;
font-size: 1.15rem;
font-weight: 800;
color: var(--text-primary);
}
.employee-stat {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
gap: 0.35rem;
padding: 0.55rem 0.85rem;
border-radius: var(--radius-lg);
background: color-mix(in srgb, var(--primary-color) 12%, var(--surface-card));
border: 1px solid color-mix(in srgb, var(--primary-color) 28%, var(--border-subtle));
color: var(--text-secondary);
font-size: 0.78rem;
}
.employee-stat strong {
font-size: 0.95rem;
font-weight: 800;
color: color-mix(in srgb, var(--primary-color) 70%, var(--text-primary));
font-variant-numeric: tabular-nums;
}
.month-tabs {
width: 100%;
max-width: 350px;
display: flex;
gap: 0.35rem;
overflow-x: auto;
padding: 0.45rem;
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
background: var(--surface-tabs);
border: 1px solid var(--border-glass);
border-bottom: none;
scrollbar-width: none;
}
.month-tabs::-webkit-scrollbar {
display: none;
}
.month-tab {
flex-shrink: 0;
padding: 0.5rem 0.85rem;
border: none;
border-radius: 0.75rem;
background: transparent;
color: var(--text-muted);
font-size: 0.82rem;
font-weight: 700;
cursor: pointer;
transition: all 0.2s ease;
}
.month-tab:hover {
color: var(--text-primary);
background: var(--surface-tab-hover);
}
.month-tab-active {
color: color-mix(in srgb, var(--primary-color) 78%, var(--text-primary));
background: var(--surface-tab-active);
box-shadow: var(--shadow-soft);
}
.attendance-card {
width: 100%;
max-width: 350px;
background: var(--surface-glass);
border: 1px solid var(--border-glass);
border-radius: 0 0 var(--radius-xl) var(--radius-xl);
box-shadow: var(--shadow-soft);
overflow: hidden;
}
.attendance-table {
width: 100%;
border-collapse: collapse;
text-align: center;
}
.attendance-table thead th {
padding: 0.65rem 0.35rem;
font-size: 0.72rem;
font-weight: 700;
color: var(--text-muted);
background: var(--surface-tabs);
border-bottom: 1px solid var(--border-subtle);
}
.attendance-table thead th:not(:last-child) {
border-left: 1px solid var(--border-subtle);
}
.attendance-table tbody td {
padding: 0.5rem 0.25rem;
font-size: 0.82rem;
color: var(--text-primary);
border-bottom: 1px solid var(--border-subtle);
font-variant-numeric: tabular-nums;
}
.attendance-table tbody td:not(:last-child) {
border-left: 1px solid var(--border-subtle);
}
.attendance-table tbody tr:hover td {
background: var(--surface-tab-hover);
}
.attendance-table tfoot td {
padding: 0.75rem 0.5rem;
font-size: 0.85rem;
font-weight: 800;
color: var(--text-primary);
background: color-mix(in srgb, var(--primary-color) 10%, var(--surface-card));
border-top: 2px solid var(--border-subtle);
}
.panel-empty {
margin: 2.5rem 0;
text-align: center;
color: var(--text-muted);
font-weight: 700;
}
</style>
@endsection
@section('content')
<div class="admin-show-page">
@if(empty($data) || count($data) == 0)
<div class="mt-80 text-gray-500 text-xl font-bold italic">
<div class="admin-show-empty">
<h1>اطلاعاتی موجود نمیباشد</h1>
</div>
@else
<div class="flex flex-wrap justify-center gap-2 mt-10 mb-6 max-w-3xl">
<div class="employee-picker">
@foreach($data as $employee)
<button class="emp-btn px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-cyan-500 hover:text-white transition-colors duration-300 font-bold shadow-sm"
<button type="button"
class="emp-btn"
data-emp-id="{{ $employee->id }}"
onclick="openEmployee(event, 'emp_{{ $employee->id }}', '{{ $employee->id }}')">
{{ $employee->name }}
</button>
@@ -56,15 +262,13 @@ foreach ($data as $employee) {
</div>
@foreach($data as $employee)
<div id="emp_{{ $employee->id }}" class="employee-content hidden flex-col items-center justify-center w-full">
<div class="flex justify-between items-center mb-4 w-[350px]">
<h2 class="text-xl font-bold text-cyan-700">{{ $employee->name }}</h2>
<span class="text-xs bg-cyan-50 text-cyan-800 px-3 py-1.5 rounded-full border border-cyan-200 shadow-sm flex items-center gap-1">
<div id="emp_{{ $employee->id }}" class="employee-panel">
<div class="employee-header">
<h2>{{ $employee->name }}</h2>
<div class="employee-stat">
<span>کارکرد ماه قبل ({{ $previousMonthName }}):</span>
<strong class="text-sm font-black">{{ $employeeTotals[$employee->id][$previousMonthName] ?? '00:00' }}</strong>
</span>
<strong>{{ $employeeTotals[$employee->id][$previousMonthName] ?? '00:00' }}</strong>
</div>
</div>
@php
@@ -72,13 +276,14 @@ foreach ($data as $employee) {
@endphp
@if(empty($recordsGrouped))
<div class="my-10 text-gray-500 text-lg font-bold italic">
<div class="panel-empty">
رکورد ترددی برای این شخص ثبت نشده است.
</div>
@else
<div class="tab rounded-t-2xl max-w-[350px] mx-auto flex overflow-x-auto whitespace-nowrap hide-scrollbar" style="max-width: 350px">
<div class="month-tabs">
@foreach(array_keys($recordsGrouped) as $month)
<button class="tablinks-{{ $employee->id }} active rounded-t-2xl cursor-pointer px-4 py-2 bg-gray-100 border-b-2 border-transparent hover:bg-gray-200 flex-shrink-0"
<button type="button"
class="month-tab tablinks-{{ $employee->id }}"
onclick="openMonth(event, 'month_{{ $employee->id }}_{{ $month }}', '{{ $employee->id }}')">
{{ $month }}
</button>
@@ -86,43 +291,37 @@ foreach ($data as $employee) {
</div>
@foreach($recordsGrouped as $month => $records)
<div id="month_{{ $employee->id }}_{{ $month }}" class="tabcontent-{{ $employee->id }} hidden w-[350px] bg-white rounded-b-xl rounded-tl-2xl cursor-default leading-7 shadow-lg border border-gray-100">
<table style="width:100%; border-collapse: collapse; text-align: center">
<div id="month_{{ $employee->id }}_{{ $month }}"
class="attendance-card tabcontent-{{ $employee->id }}"
style="display: none;">
<table class="attendance-table">
<thead>
<tr style="border-bottom: 1px solid #ddd; background-color: #f8f9fa;">
<th style="border-right: 1px solid #ddd; padding: 8px 0;">تاریخ</th>
<th style="border-right: 1px solid #ddd;">روز</th>
<th style="border-right: 1px solid #ddd;">ورود</th>
<th style="border-right: 1px solid #ddd;">خروج</th>
<th style="border-right: 1px solid #ddd;">مدت</th>
<tr>
<th>تاریخ</th>
<th>روز</th>
<th>ورود</th>
<th>خروج</th>
<th>مدت</th>
</tr>
</thead>
<tbody>
@foreach($records as $row)
<tr class="hover:bg-cyan-100 transition-colors" style="border-bottom: 1px solid #ddd;">
<td style="border-right: 1px solid #ddd; padding: 4px 0;">
{{ Jalalian::fromCarbon(\Carbon\Carbon::parse($row->entered_at))->format('m/d') ?? '-' }}
</td>
<td style="border-right: 1px solid #ddd;">
{{ Jalalian::fromCarbon(\Carbon\Carbon::parse($row->entered_at))->format('%A') ?? '-' }}
</td>
<td style="border-right: 1px solid #ddd;">
{{ \Carbon\Carbon::parse($row->entered_at)->format('H:i') ?? '-' }}
</td>
<td style="border-right: 1px solid #ddd;">
{{ $row->exited_at ? \Carbon\Carbon::parse($row->exited_at)->format('H:i') : '-' }}
</td>
<td style="border-right: 1px solid #ddd;">
{{ $row->duration ? \Carbon\Carbon::parse($row->duration)->format('H:i') : '-' }}
</td>
<tr>
<td>{{ Jalalian::fromCarbon(Carbon::parse($row->entered_at))->format('m/d') ?? '-' }}</td>
<td>{{ Jalalian::fromCarbon(Carbon::parse($row->entered_at))->format('%A') ?? '-' }}</td>
<td>{{ Carbon::parse($row->entered_at)->format('H:i') ?? '-' }}</td>
<td>{{ $row->exited_at ? Carbon::parse($row->exited_at)->format('H:i') : '-' }}</td>
<td>{{ $row->duration ? Carbon::parse($row->duration)->format('H:i') : '-' }}</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<td colspan="5" class="bg-cyan-50 font-bold text-gray-700 rounded-b-xl" style="border-top: 2px solid #ddd; text-align: center; padding: 10px 0;">
<td colspan="5">
مجموع کارکرد این ماه: {{ $employeeTotals[$employee->id][$month] ?? '00:00' }}
</td>
</tr>
</tbody>
</tfoot>
</table>
</div>
@endforeach
@@ -132,58 +331,46 @@ foreach ($data as $employee) {
@endif
</div>
<style>
/* مخفی کردن اسکرول‌بار برای تب‌های ماه‌ها اگر تعدادشان زیاد شد */
.hide-scrollbar::-webkit-scrollbar { display: none; }
.hide-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
</style>
<script>
function openEmployee(evt, empContainerId, empId) {
let employeeContents = document.getElementsByClassName("employee-content");
for (let i = 0; i < employeeContents.length; i++) {
employeeContents[i].style.display = "none";
document.querySelectorAll('.employee-panel').forEach(el => el.classList.remove('is-visible'));
document.querySelectorAll('.emp-btn').forEach(btn => btn.classList.remove('emp-btn-active'));
const panel = document.getElementById(empContainerId);
if (panel) panel.classList.add('is-visible');
if (evt.currentTarget) {
evt.currentTarget.classList.add('emp-btn-active');
}
let empBtns = document.getElementsByClassName("emp-btn");
for (let i = 0; i < empBtns.length; i++) {
empBtns[i].classList.remove("bg-cyan-500", "text-white", "shadow-md");
empBtns[i].classList.add("bg-gray-200", "text-gray-700");
}
document.getElementById(empContainerId).style.display = "flex";
evt.currentTarget.classList.remove("bg-gray-200", "text-gray-700");
evt.currentTarget.classList.add("bg-cyan-500", "text-white", "shadow-md");
let firstMonthTab = document.querySelector("#" + empContainerId + " .tablinks-" + empId);
const firstMonthTab = document.querySelector('#' + empContainerId + ' .tablinks-' + empId);
if (firstMonthTab) {
firstMonthTab.click();
}
}
function openMonth(evt, monthId, empId) {
let tabcontents = document.getElementsByClassName("tabcontent-" + empId);
for (let i = 0; i < tabcontents.length; i++) {
tabcontents[i].style.display = "none";
}
document.querySelectorAll('.tabcontent-' + empId).forEach(el => {
el.style.display = 'none';
});
let tablinks = document.getElementsByClassName("tablinks-" + empId);
for (let i = 0; i < tablinks.length; i++) {
tablinks[i].classList.remove("bg-white", "border-cyan-500");
tablinks[i].classList.add("bg-gray-100", "border-transparent");
}
document.querySelectorAll('.tablinks-' + empId).forEach(btn => {
btn.classList.remove('month-tab-active');
});
document.getElementById(monthId).style.display = "block";
evt.currentTarget.classList.remove("bg-gray-100", "border-transparent");
evt.currentTarget.classList.add("bg-white", "border-cyan-500");
const monthPanel = document.getElementById(monthId);
if (monthPanel) monthPanel.style.display = 'block';
if (evt.currentTarget) {
evt.currentTarget.classList.add('month-tab-active');
}
}
document.addEventListener("DOMContentLoaded", function () {
let firstEmployeeBtn = document.querySelector(".emp-btn");
document.addEventListener('DOMContentLoaded', function () {
const firstEmployeeBtn = document.querySelector('.emp-btn');
if (firstEmployeeBtn) {
firstEmployeeBtn.click();
}
});
</script>
@endsection
@endsection