Teren dodeljen danes statistika

This commit is contained in:
Simon Pocrnjič 2025-10-09 01:05:17 +02:00
parent 6108028942
commit c8029c9eb0
3 changed files with 86 additions and 18 deletions

View File

@ -129,9 +129,39 @@ public function __invoke(): Response
$fieldJobsAssignedToday = FieldJob::query() $fieldJobsAssignedToday = FieldJob::query()
->whereDate(DB::raw('COALESCE(assigned_at, created_at)'), $today) ->whereDate(DB::raw('COALESCE(assigned_at, created_at)'), $today)
->select(['id', 'assigned_user_id', 'priority', 'assigned_at', 'created_at', 'contract_id']) ->select(['id', 'assigned_user_id', 'priority', 'assigned_at', 'created_at', 'contract_id'])
->with(['contract' => function ($q) {
$q->select('id', 'uuid', 'reference', 'client_case_id')
->with(['clientCase:id,uuid,person_id', 'clientCase.person:id,full_name', 'segments:id,name']);
}])
->latest(DB::raw('COALESCE(assigned_at, created_at)')) ->latest(DB::raw('COALESCE(assigned_at, created_at)'))
->limit(15) ->limit(15)
->get(); ->get()
->map(function ($fj) {
$contract = $fj->contract;
$segmentId = null;
if ($contract && method_exists($contract, 'segments')) {
// Determine active segment via pivot active flag if present
$activeSeg = $contract->segments->first();
if ($activeSeg && isset($activeSeg->pivot) && ($activeSeg->pivot->active ?? true)) {
$segmentId = $activeSeg->id;
}
}
return [
'id' => $fj->id,
'priority' => $fj->priority,
// Normalize to ISO8601 strings so FE retains timezone & time component
'assigned_at' => $fj->assigned_at?->toIso8601String(),
'created_at' => $fj->created_at?->toIso8601String(),
'contract' => $contract ? [
'uuid' => $contract->uuid,
'reference' => $contract->reference,
'client_case_uuid' => optional($contract->clientCase)->uuid,
'person_full_name' => optional(optional($contract->clientCase)->person)->full_name,
'segment_id' => $segmentId,
] : null,
];
});
// Imports in progress (queued / processing) // Imports in progress (queued / processing)
$importsInProgress = Import::query() $importsInProgress = Import::query()

View File

@ -27,9 +27,9 @@ class FieldJob extends Model
]; ];
protected $casts = [ protected $casts = [
'assigned_at' => 'date', 'assigned_at' => 'datetime',
'completed_at' => 'date', 'completed_at' => 'datetime',
'cancelled_at' => 'date', 'cancelled_at' => 'datetime',
'priority' => 'boolean', 'priority' => 'boolean',
'address_snapshot ' => 'array', 'address_snapshot ' => 'array',
]; ];

View File

@ -115,6 +115,23 @@ function formatStaleDaysLabel(value) {
const whole = Math.floor(num); const whole = Math.floor(num);
return whole === 1 ? "1 dan" : whole + " dni"; return whole === 1 ? "1 dan" : whole + " dni";
} }
// Robust time formatter to avoid fixed 02:00:00 (timezone / fallback issues)
function formatJobTime(ts) {
if (!ts) return "";
try {
const d = new Date(ts);
if (isNaN(d.getTime())) return "";
// Show HH:MM (24h) and seconds only if non-zero seconds
const pad = (n) => n.toString().padStart(2, "0");
const h = pad(d.getHours());
const m = pad(d.getMinutes());
const s = d.getSeconds();
return s ? `${h}:${m}:${pad(s)}` : `${h}:${m}`;
} catch (e) {
return "";
}
}
</script> </script>
<template> <template>
@ -413,7 +430,8 @@ function formatStaleDaysLabel(value) {
>{{ c.client_ref || c.uuid.slice(0, 8) }}</Link >{{ c.client_ref || c.uuid.slice(0, 8) }}</Link
> >
<p class="text-[11px] text-gray-400 dark:text-gray-500"> <p class="text-[11px] text-gray-400 dark:text-gray-500">
Brez aktivnosti: {{ formatStaleDaysLabel(c.days_without_activity ?? c.days_stale) }} Brez aktivnosti:
{{ formatStaleDaysLabel(c.days_without_activity ?? c.days_stale) }}
</p> </p>
</div> </div>
<span <span
@ -453,23 +471,43 @@ function formatStaleDaysLabel(value) {
<li <li
v-for="f in fieldJobsAssignedToday" v-for="f in fieldJobsAssignedToday"
:key="f.id" :key="f.id"
class="py-2 flex items-center justify-between" class="py-2 flex items-start justify-between gap-3"
> >
<div class="min-w-0"> <div class="min-w-0 flex-1">
<p class="text-gray-700 dark:text-gray-300 text-sm">#{{ f.id }}</p> <p class="text-gray-700 dark:text-gray-300 text-sm font-medium">
#{{ f.id }}
<template v-if="f.contract">
·
<Link
:href="
route('clientCase.show', {
client_case: f.contract.client_case_uuid,
segment: f.contract.segment_id,
})
"
class="text-indigo-600 dark:text-indigo-400 hover:underline"
>
{{ f.contract.reference || f.contract.uuid?.slice(0, 8) }}
</Link>
<span
v-if="f.contract.person_full_name"
class="text-gray-500 dark:text-gray-400"
>
{{ f.contract.person_full_name }}
</span>
</template>
</p>
<p class="text-[11px] text-gray-400 dark:text-gray-500"> <p class="text-[11px] text-gray-400 dark:text-gray-500">
{{ {{ formatJobTime(f.created_at) }}
f.assigned_at || f.created_at
? new Date(f.assigned_at || f.created_at).toLocaleTimeString()
: ""
}}
</p> </p>
</div> </div>
<span <div class="flex items-center gap-2">
v-if="f.priority" <span
class="text-[10px] px-2 py-0.5 rounded bg-rose-50 dark:bg-rose-900/30 text-rose-600 dark:text-rose-300" v-if="f.priority"
>Prioriteta</span class="text-[10px] px-2 py-0.5 rounded bg-rose-50 dark:bg-rose-900/30 text-rose-600 dark:text-rose-300"
> >Prioriteta</span
>
</div>
</li> </li>
<li <li
v-if="!fieldJobsAssignedToday.length" v-if="!fieldJobsAssignedToday.length"