feat: profile_photo en contratos activos, notificaciones bilingues en reportes y foto en panel usuarios

- API contratos activos (cliente y proveedor): agrega campo profile_photo (técnico asignado o supplier, null si no tiene)
- Notificaciones push bilingues en comentarios de reporte: "Nueva actividad en tu reporte" / "New activity on your report"
- Moderador en web panel notifica a cliente y proveedor al comentar, con prefijo Moderador/Moderator
- Panel usuarios: columna de foto de perfil entre ID y Nombre

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 17:17:14 -06:00
parent 38da1b56ce
commit 0ed98c96ee
40 changed files with 1390 additions and 651 deletions

View File

@@ -13,27 +13,53 @@
$sortUrl = fn($f) => url('payments') . '?' . http_build_query(array_filter(['date_from' => $dateFrom, 'date_to' => $dateTo, 'field' => $f, 'sort' => $currentField === $f ? $nextSort : 'desc']));
@endphp
<div class="row">
<div class="col-sm-5">
<h3>Pagos a Proveedores</h3>
@if(session('warning'))
<div class="alert alert-warning">{{ session('warning') }}</div>
@endif
<div class="row align-items-center mb-2">
<div class="col-sm-4">
<h3 class="mb-0">Pagos a Proveedores</h3>
</div>
<div class="col-sm-7">
<div class="pull-right">
{!! Form::open(['method' => 'GET', 'url' => 'payments', 'class' => 'form-inline', 'role' => 'search']) !!}
<label class="mr-2 mb-0">Filtrar</label>
<input type="date" class="form-control mr-1" name="date_from" value="{{ $dateFrom }}">
<input type="date" class="form-control mr-1" name="date_to" value="{{ $dateTo }}">
<button type="submit" class="btn btn-primary mr-1">
<i class="fa fa-filter" aria-hidden="true"></i>
<div class="col-sm-8">
<div class="d-flex justify-content-end align-items-center flex-wrap" style="gap:.5rem">
{!! Form::open(['method' => 'GET', 'url' => 'payments', 'class' => 'd-flex align-items-center', 'style' => 'gap:.4rem']) !!}
<label class="mb-0 mr-1">Filtrar</label>
<input type="date" class="form-control form-control-sm" name="date_from" value="{{ $dateFrom }}">
<input type="date" class="form-control form-control-sm" name="date_to" value="{{ $dateTo }}">
<button type="submit" class="btn btn-sm btn-primary">
<i class="fa fa-filter"></i>
</button>
<a href="{{ url('payments') }}" class="btn btn-default">
<i class="fa fa-times" aria-hidden="true"></i>
<a href="{{ url('payments') }}" class="btn btn-sm btn-default">
<i class="fa fa-times"></i>
</a>
{!! Form::close() !!}
<form method="POST" action="{{ url('payments/generate') }}" id="generateForm">
@csrf
<input type="hidden" name="date_from" value="{{ $dateFrom }}">
<input type="hidden" name="date_to" value="{{ $dateTo }}">
<button type="button" class="btn btn-sm btn-success" onclick="confirmGenerate()">
<i class="fa fa-file-excel-o"></i> Generar Pagos
</button>
</form>
</div>
</div>
</div>
<script>
function confirmGenerate() {
var total = {{ $payments->total() }};
if (total === 0) {
alert('No hay contratos pendientes de pago.');
return;
}
if (confirm('Se generará un archivo Excel con ' + total + ' proveedor(es) y se marcarán sus contratos como pagados. ¿Continuar?')) {
document.getElementById('generateForm').submit();
}
}
</script>
<table class="table">
<thead>
<tr>