152 lines
9.3 KiB
PHP
152 lines
9.3 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('content')
|
|
<div class="space-y-6">
|
|
<!-- Page Header -->
|
|
<div class="flex items-center gap-4">
|
|
<a href="{{ route('payroll.index') }}" class="p-2 text-gray-500 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/></svg>
|
|
</a>
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-gray-900">{{ $employee->full_name ?? ($employee->first_name . ' ' . $employee->last_name) }}</h1>
|
|
<p class="text-sm text-gray-500">{{ $employee->job_title ?? '' }} — {{ __('payroll.payroll_year', ['year' => $year]) }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Employee Info Card -->
|
|
<div class="bg-white rounded-xl border border-gray-200 p-5">
|
|
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
<div>
|
|
<div class="text-xs font-medium text-gray-500">{{ __('employee.contractType') }}</div>
|
|
<div class="text-sm font-medium text-gray-900">{{ __('employee.contract_' . ($employee->contract_type ?? 'full_time')) }}</div>
|
|
</div>
|
|
<div>
|
|
<div class="text-xs font-medium text-gray-500">{{ __('employee.baseSalary') }}</div>
|
|
<div class="text-sm font-medium text-gray-900">{{ number_format($employee->base_salary ?? 0) }}</div>
|
|
</div>
|
|
<div>
|
|
<div class="text-xs font-medium text-gray-500">{{ __('employee.hireDate') }}</div>
|
|
<div class="text-sm font-medium text-gray-900">{{ $employee->hire_date ? calendar_date($employee->hire_date) : '-' }}</div>
|
|
</div>
|
|
<div>
|
|
<div class="text-xs font-medium text-gray-500">{{ __('employee.status') }}</div>
|
|
<div class="text-sm font-medium">
|
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium
|
|
{{ $employee->status === 'active' ? 'bg-green-50 text-green-700' : 'bg-gray-100 text-gray-600' }}">
|
|
{{ __('employee.status_' . $employee->status) }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Yearly Statistics -->
|
|
<div class="grid grid-cols-2 md:grid-cols-5 gap-4">
|
|
<div class="bg-white rounded-xl border border-gray-200 p-4">
|
|
<div class="text-xs font-medium text-gray-500 mb-1">{{ __('payroll.total_gross') }}</div>
|
|
<div class="text-lg font-bold text-gray-900">{{ number_format($yearlyGross) }}</div>
|
|
</div>
|
|
<div class="bg-white rounded-xl border border-gray-200 p-4">
|
|
<div class="text-xs font-medium text-gray-500 mb-1">{{ __('payroll.total_deductions') }}</div>
|
|
<div class="text-lg font-bold text-red-600">{{ number_format($yearlyDeductions + $yearlyAdvances) }}</div>
|
|
</div>
|
|
<div class="bg-white rounded-xl border border-gray-200 p-4">
|
|
<div class="text-xs font-medium text-gray-500 mb-1">{{ __('payroll.total_net') }}</div>
|
|
<div class="text-lg font-bold text-teal-600">{{ number_format($yearlyNet) }}</div>
|
|
</div>
|
|
<div class="bg-white rounded-xl border border-gray-200 p-4">
|
|
<div class="text-xs font-medium text-gray-500 mb-1">{{ __('payroll.total_paid') }}</div>
|
|
<div class="text-lg font-bold text-green-600">{{ number_format($yearlyPaid) }}</div>
|
|
</div>
|
|
<div class="bg-white rounded-xl border border-gray-200 p-4">
|
|
<div class="text-xs font-medium text-gray-500 mb-1">{{ __('payroll.total_unpaid') }}</div>
|
|
<div class="text-lg font-bold text-amber-600">{{ number_format($yearlyUnpaid) }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Year Filter -->
|
|
<div class="bg-white rounded-xl border border-gray-200 p-4">
|
|
<form method="GET" action="{{ route('payroll.show', $employee->id) }}" class="flex gap-3 items-end">
|
|
<div class="w-32">
|
|
<label class="block text-xs font-medium text-gray-500 mb-1">{{ __('payroll.year') }}</label>
|
|
<select name="year" class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-teal-500">
|
|
@foreach(range(now()->year - 2, now()->year + 1) as $y)
|
|
<option value="{{ $y }}" {{ $year == $y ? 'selected' : '' }}>{{ $y }}</option>
|
|
@endforeach
|
|
</select>
|
|
</div>
|
|
<button type="submit" class="px-4 py-2 bg-gray-100 text-gray-700 text-sm font-medium rounded-lg hover:bg-gray-200 transition-colors">{{ __('common.filter') }}</button>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Monthly Breakdown -->
|
|
<div class="space-y-4">
|
|
@foreach(range(1, 12) as $m)
|
|
@isset($financials[$m])
|
|
<div class="bg-white rounded-xl border border-gray-200 overflow-hidden">
|
|
<div class="px-5 py-3 bg-gray-50 border-b border-gray-200 flex items-center justify-between">
|
|
<h3 class="text-sm font-semibold text-gray-800">{{ $persianMonths[$m] ?? $m }}</h3>
|
|
@php
|
|
$monthFinancials = $financials[$m];
|
|
$monthGross = $monthFinancials->whereIn('type', ['salary', 'overtime', 'bonus', 'allowance'])->sum('amount');
|
|
$monthDeductions = $monthFinancials->where('type', 'deduction')->sum('amount');
|
|
$monthAdvances = $monthFinancials->where('type', 'advance')->sum('amount');
|
|
$monthNet = $monthGross - $monthDeductions - $monthAdvances;
|
|
$monthPaid = $monthFinancials->where('is_paid', true)->whereIn('type', ['salary', 'overtime', 'bonus', 'allowance'])->sum('amount');
|
|
@endphp
|
|
<div class="flex items-center gap-4 text-xs">
|
|
<span class="text-gray-500">{{ __('payroll.total_gross') }}: <strong class="text-gray-900">{{ number_format($monthGross) }}</strong></span>
|
|
<span class="text-red-500">{{ __('payroll.total_deductions') }}: <strong>{{ number_format($monthDeductions + $monthAdvances) }}</strong></span>
|
|
<span class="text-teal-600">{{ __('payroll.total_net') }}: <strong>{{ number_format($monthNet) }}</strong></span>
|
|
@if($monthPaid < $monthGross)
|
|
<span class="text-amber-600">{{ __('payroll.unpaid') }}: {{ number_format($monthGross - $monthPaid) }}</span>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
<table class="w-full">
|
|
<tbody class="divide-y divide-gray-100">
|
|
@foreach($monthFinancials as $f)
|
|
<tr class="hover:bg-gray-50 transition-colors">
|
|
<td class="px-5 py-2.5 w-32">
|
|
<span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium
|
|
{{ $f->type === 'salary' ? 'bg-teal-50 text-teal-700' :
|
|
($f->type === 'overtime' ? 'bg-blue-50 text-blue-700' :
|
|
($f->type === 'bonus' ? 'bg-emerald-50 text-emerald-700' :
|
|
($f->type === 'allowance' ? 'bg-cyan-50 text-cyan-700' :
|
|
($f->type === 'deduction' ? 'bg-red-50 text-red-700' :
|
|
'bg-amber-50 text-amber-700')))) }}">
|
|
{{ __('payroll.type_' . $f->type) }}
|
|
</span>
|
|
</td>
|
|
<td class="px-5 py-2.5 text-sm font-medium {{ in_array($f->type, ['deduction', 'advance']) ? 'text-red-600' : 'text-gray-900' }}">
|
|
{{ in_array($f->type, ['deduction', 'advance']) ? '-' : '' }}{{ number_format($f->amount) }}
|
|
</td>
|
|
<td class="px-5 py-2.5 text-sm text-gray-500">{{ $f->description ?? '-' }}</td>
|
|
<td class="px-5 py-2.5 text-sm text-gray-500">{{ $f->effective_date ? calendar_date($f->effective_date) : '-' }}</td>
|
|
<td class="px-5 py-2.5 w-24">
|
|
@if($f->is_paid)
|
|
<span class="inline-flex items-center gap-1 text-xs font-medium text-green-600">
|
|
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>
|
|
{{ __('payroll.paid') }}
|
|
</span>
|
|
@else
|
|
<a href="{{ route('payroll.pay', $f) }}" class="text-xs font-medium text-amber-600 hover:text-amber-800" onclick="return confirm('{{ __('payroll.confirm_pay') }}')">{{ __('payroll.pay') }}</a>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
@endisset
|
|
@endforeach
|
|
|
|
@if($financials->isEmpty())
|
|
<div class="bg-white rounded-xl border border-gray-200 p-12 text-center text-gray-500">
|
|
{{ __('payroll.no_records_year') }}
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endsection
|