151 lines
6.2 KiB
PHP
151 lines
6.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Call;
|
|
use Illuminate\Support\Facades\App;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
class CallController extends Controller
|
|
{
|
|
public function showById($id)
|
|
{
|
|
$call = Call::withTrashed()->with([
|
|
'callable',
|
|
'translations' => function ($query) {
|
|
$query->where('locale', App::getLocale());
|
|
},
|
|
'tag.contexts.category.translations',
|
|
'tag.contexts.category.ancestors.translations',
|
|
'location.city.translations',
|
|
'location.district.translations',
|
|
'location.country.translations',
|
|
'location.division.translations',
|
|
'loveReactant.reactionCounters',
|
|
])->findOrFail($id);
|
|
|
|
$activeProfileType = session('activeProfileType');
|
|
$activeProfileId = session('activeProfileId');
|
|
$isAdmin = $activeProfileType === \App\Models\Admin::class;
|
|
$isCallable = $activeProfileType === $call->callable_type
|
|
&& (int) $activeProfileId === (int) $call->callable_id;
|
|
|
|
// Deleted calls are only visible to admins and the callable itself
|
|
$isDeleted = $call->trashed();
|
|
if ($isDeleted && !$isAdmin && !$isCallable) {
|
|
return view('calls.unavailable');
|
|
}
|
|
|
|
// Blocked calls are only visible to admins and the callable itself
|
|
if ($call->is_suppressed && !$isAdmin && !$isCallable) {
|
|
return view('calls.unavailable');
|
|
}
|
|
|
|
// Paused calls are only visible to admins and the callable itself
|
|
if ($call->is_paused && !$isAdmin && !$isCallable) {
|
|
return view('calls.unavailable');
|
|
}
|
|
|
|
// Guests cannot view private calls
|
|
if (!$call->is_public && !Auth::check()) {
|
|
return redirect()->route('login')
|
|
->with('status', __('This call is private. Please log in to view it.'));
|
|
}
|
|
|
|
// Expired calls are only visible to the owner and admins
|
|
$isExpired = $call->till !== null && $call->till->isPast();
|
|
if ($isExpired && !$isCallable && !$isAdmin) {
|
|
return view('calls.unavailable');
|
|
}
|
|
|
|
$locale = App::getLocale();
|
|
|
|
// Build category hierarchy
|
|
$tagCategory = $call->tag?->contexts->first()?->category;
|
|
$tagColor = $tagCategory?->relatedColor ?? 'gray';
|
|
$tagCategories = [];
|
|
if ($tagCategory) {
|
|
foreach ($tagCategory->ancestorsAndSelf()->get()->reverse() as $cat) {
|
|
$name = $cat->translations->firstWhere('locale', $locale)?->name
|
|
?? $cat->translations->first()?->name
|
|
?? '';
|
|
if ($name) {
|
|
$tagCategories[] = ['name' => $name, 'color' => $cat->relatedColor ?? 'gray'];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Build callable profile's location short string (city first, fallback to division or country)
|
|
$callableLocation = null;
|
|
if ($call->callable && method_exists($call->callable, 'locations')) {
|
|
$firstLoc = $call->callable->locations()->with(['city.translations', 'division.translations', 'country.translations'])->first();
|
|
if ($firstLoc) {
|
|
$cCity = optional($firstLoc->city?->translations->first())->name;
|
|
$cDivision = optional($firstLoc->division?->translations->first())->name;
|
|
$cCountry = optional($firstLoc->country?->translations->first())->name;
|
|
$callableLocation = $cCity ?? $cDivision ?? $cCountry ?: null;
|
|
}
|
|
}
|
|
|
|
// Build call exchange location: "City District, Division, COUNTRY_CODE"
|
|
$callLocation = null;
|
|
if ($call->location) {
|
|
$loc = $call->location;
|
|
$parts = [];
|
|
$cityPart = null;
|
|
if ($loc->city) {
|
|
$cityPart = optional($loc->city->translations->first())->name;
|
|
}
|
|
if ($loc->district) {
|
|
$districtName = optional($loc->district->translations->first())->name;
|
|
$cityPart = $cityPart ? $cityPart . ' ' . $districtName : $districtName;
|
|
}
|
|
if ($cityPart) $parts[] = $cityPart;
|
|
if ($loc->division) {
|
|
$divisionName = optional($loc->division->translations->first())->name;
|
|
if ($divisionName) $parts[] = $divisionName;
|
|
}
|
|
if ($loc->country && $loc->country->code !== 'XX') {
|
|
$parts[] = strtoupper($loc->country->code);
|
|
} elseif ($loc->country && $loc->country->code === 'XX') {
|
|
$parts[] = __('Location not specified');
|
|
}
|
|
$callLocation = $parts ? implode(', ', $parts) : null;
|
|
}
|
|
|
|
// Determine whether to show the expiry badge (within configured warning window)
|
|
$expiryWarningDays = timebank_config('calls.expiry_warning_days', 7);
|
|
$expiryBadgeText = null;
|
|
if ($call->till && $expiryWarningDays !== null) {
|
|
$daysLeft = (int) now()->startOfDay()->diffInDays($call->till->startOfDay(), false);
|
|
if ($daysLeft <= $expiryWarningDays) {
|
|
if ($daysLeft <= 0) {
|
|
$expiryBadgeText = __('Expires today');
|
|
} elseif ($daysLeft === 1) {
|
|
$expiryBadgeText = __('Expires tomorrow');
|
|
} else {
|
|
$expiryBadgeText = __('Expires in :days days', ['days' => $daysLeft]);
|
|
}
|
|
}
|
|
}
|
|
|
|
$callableType = $call->callable ? strtolower(class_basename($call->callable)) : null;
|
|
$viewName = Auth::check() ? 'calls.show' : 'calls.show-guest';
|
|
return view($viewName, compact('call', 'tagColor', 'tagCategories', 'callableType', 'callableLocation', 'callLocation', 'expiryBadgeText', 'isExpired', 'isDeleted', 'isAdmin'));
|
|
}
|
|
|
|
public function manage()
|
|
{
|
|
$activeProfileType = getActiveProfileType();
|
|
$allowedTypes = [
|
|
'User', 'Organization', 'Bank', 'Admin',
|
|
];
|
|
|
|
if (!$activeProfileType || !in_array($activeProfileType, $allowedTypes)) {
|
|
abort(403, __('You do not have access to this page.'));
|
|
}
|
|
|
|
return view('calls.manage');
|
|
}
|
|
}
|