Initial commit
This commit is contained in:
239
app/Http/Livewire/Calls/Create.php
Normal file
239
app/Http/Livewire/Calls/Create.php
Normal file
@@ -0,0 +1,239 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Calls;
|
||||
|
||||
use App\Models\Account;
|
||||
use App\Models\Call;
|
||||
use App\Models\CallTranslation;
|
||||
use App\Models\Locations\Location;
|
||||
use App\Models\Transaction;
|
||||
use App\Services\CallCreditService;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Livewire\Component;
|
||||
use WireUi\Traits\WireUiActions;
|
||||
|
||||
class Create extends Component
|
||||
{
|
||||
use WireUiActions;
|
||||
|
||||
public string $content = '';
|
||||
public ?string $till = null;
|
||||
public ?int $tagId = null;
|
||||
public bool $isPublic = false;
|
||||
|
||||
// Location fields
|
||||
public $country = null;
|
||||
public $division = null;
|
||||
public $city = null;
|
||||
public $district = null;
|
||||
|
||||
public bool $showModal = false;
|
||||
public bool $showNoCreditsModal = false;
|
||||
|
||||
protected $listeners = [
|
||||
'countryToParent',
|
||||
'divisionToParent',
|
||||
'cityToParent',
|
||||
'districtToParent',
|
||||
'callTagSelected',
|
||||
'callTagCleared',
|
||||
];
|
||||
|
||||
protected function messages(): array
|
||||
{
|
||||
return [
|
||||
'till.required' => __('Expire date is required.'),
|
||||
'till.date' => __('Expire date must be a valid date.'),
|
||||
'till.after' => __('Expire date must be in the future.'),
|
||||
'till.before_or_equal'=> __('Expire date exceeds the maximum allowed period.'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getTillMaxDays(): ?int
|
||||
{
|
||||
$activeProfileType = session('activeProfileType');
|
||||
if ($activeProfileType && $activeProfileType !== \App\Models\User::class) {
|
||||
return timebank_config('calls.till_max_days_non_user');
|
||||
}
|
||||
return timebank_config('calls.till_max_days');
|
||||
}
|
||||
|
||||
protected function rules(): array
|
||||
{
|
||||
$tillMaxDays = $this->getTillMaxDays();
|
||||
$tillRule = 'required|date|after:today';
|
||||
if ($tillMaxDays !== null) {
|
||||
$tillRule .= '|before_or_equal:' . now()->addDays($tillMaxDays)->format('Y-m-d');
|
||||
}
|
||||
|
||||
return [
|
||||
'content' => ['required', 'string', 'max:' . timebank_config('calls.content_max_input', 200)],
|
||||
'till' => $tillRule,
|
||||
'tagId' => 'required|integer|exists:taggable_tags,tag_id',
|
||||
'country' => 'required|integer|exists:countries,id',
|
||||
'city' => 'nullable|integer|exists:cities,id',
|
||||
'district'=> 'nullable|integer|exists:districts,id',
|
||||
];
|
||||
}
|
||||
|
||||
public function openModal(): void
|
||||
{
|
||||
$activeProfileType = session('activeProfileType');
|
||||
|
||||
if (!$activeProfileType || !in_array($activeProfileType, [
|
||||
\App\Models\User::class,
|
||||
\App\Models\Organization::class,
|
||||
\App\Models\Bank::class,
|
||||
])) {
|
||||
abort(403, __('Only platform profiles (User, Organization, Bank) can create Calls.'));
|
||||
}
|
||||
|
||||
$activeProfileId = session('activeProfileId');
|
||||
if (!CallCreditService::profileHasCredits($activeProfileType, (int) $activeProfileId)) {
|
||||
$this->showNoCreditsModal = true;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->reset(['content', 'till', 'tagId', 'country', 'division', 'city', 'district', 'isPublic']);
|
||||
$this->resetValidation();
|
||||
|
||||
// Pre-fill expiry date from platform config default
|
||||
$defaultExpiryDays = timebank_config('calls.default_expiry_days');
|
||||
if ($defaultExpiryDays) {
|
||||
$this->till = now()->addDays($defaultExpiryDays)->format('Y-m-d');
|
||||
}
|
||||
|
||||
// Pre-fill location from the callable profile's primary location
|
||||
$profile = $activeProfileType::find(session('activeProfileId'));
|
||||
$location = $profile?->locations()->with(['country', 'division', 'city', 'district'])->first();
|
||||
if ($location) {
|
||||
$this->country = $location->country_id;
|
||||
$this->division = $location->division_id;
|
||||
$this->city = $location->city_id;
|
||||
$this->district = $location->district_id;
|
||||
}
|
||||
|
||||
$this->showModal = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the CallSkillInput child component when a tag is selected or created.
|
||||
*/
|
||||
public function callTagSelected(int $tagId): void
|
||||
{
|
||||
$this->tagId = $tagId;
|
||||
$this->resetValidation('tagId');
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the CallSkillInput child component when the tag input is cleared.
|
||||
*/
|
||||
public function callTagCleared(): void
|
||||
{
|
||||
$this->tagId = null;
|
||||
}
|
||||
|
||||
public function countryToParent($value): void { $this->country = $value ?: null; }
|
||||
public function divisionToParent($value): void { $this->division = $value ?: null; }
|
||||
public function cityToParent($value): void { $this->city = $value ?: null; }
|
||||
public function districtToParent($value): void { $this->district = $value ?: null; }
|
||||
|
||||
public function save(): void
|
||||
{
|
||||
$activeProfileType = session('activeProfileType');
|
||||
|
||||
if (!$activeProfileType || !in_array($activeProfileType, [
|
||||
\App\Models\User::class,
|
||||
\App\Models\Organization::class,
|
||||
\App\Models\Bank::class,
|
||||
])) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
$this->validate();
|
||||
|
||||
// Resolve or create a standalone Location record
|
||||
$locationId = null;
|
||||
if ($this->country || $this->city) {
|
||||
$attributes = array_filter([
|
||||
'country_id' => $this->country ?: null,
|
||||
'division_id' => $this->division ?: null,
|
||||
'city_id' => $this->city ?: null,
|
||||
'district_id' => $this->district ?: null,
|
||||
]);
|
||||
$location = Location::whereNull('locatable_id')
|
||||
->whereNull('locatable_type')
|
||||
->where($attributes)
|
||||
->first();
|
||||
if (!$location) {
|
||||
$location = new Location($attributes);
|
||||
$location->save();
|
||||
}
|
||||
$locationId = $location->id;
|
||||
}
|
||||
|
||||
$call = Call::create([
|
||||
'callable_id' => session('activeProfileId'),
|
||||
'callable_type' => $activeProfileType,
|
||||
'tag_id' => $this->tagId ?: null,
|
||||
'location_id' => $locationId,
|
||||
'from' => now()->utc(),
|
||||
'till' => $this->till ?: null,
|
||||
'is_public' => $this->isPublic,
|
||||
]);
|
||||
|
||||
CallTranslation::create([
|
||||
'call_id' => $call->id,
|
||||
'locale' => App::getLocale(),
|
||||
'content' => $this->content ?: null,
|
||||
]);
|
||||
|
||||
$call->searchable();
|
||||
|
||||
$this->showModal = false;
|
||||
$this->reset(['content', 'till', 'tagId', 'country', 'division', 'city', 'district', 'isPublic']);
|
||||
|
||||
$this->dispatch('callSaved');
|
||||
|
||||
$this->notification()->success(
|
||||
title: __('Saved'),
|
||||
description: __('Your Call has been published.')
|
||||
);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$activeProfileType = session('activeProfileType');
|
||||
$activeProfileId = session('activeProfileId');
|
||||
$profileName = $activeProfileType
|
||||
? ($activeProfileType::find($activeProfileId)?->name ?? '')
|
||||
: '';
|
||||
|
||||
$canCreate = $activeProfileType && $activeProfileId
|
||||
? CallCreditService::profileHasCredits($activeProfileType, (int) $activeProfileId)
|
||||
: false;
|
||||
|
||||
// Calculate total spendable balance across all accounts for the active profile
|
||||
$spendableBalance = null;
|
||||
if ($activeProfileType && $activeProfileId) {
|
||||
$profile = $activeProfileType::find($activeProfileId);
|
||||
if ($profile) {
|
||||
$total = 0;
|
||||
foreach ($profile->accounts()->notRemoved()->get() as $account) {
|
||||
$balance = Transaction::where('from_account_id', $account->id)
|
||||
->orWhere('to_account_id', $account->id)
|
||||
->selectRaw('SUM(CASE WHEN to_account_id = ? THEN amount ELSE -amount END) as balance', [$account->id])
|
||||
->value('balance') ?? 0;
|
||||
$total += $balance - $account->limit_min;
|
||||
}
|
||||
$spendableBalance = $total;
|
||||
}
|
||||
}
|
||||
|
||||
return view('livewire.calls.create', [
|
||||
'profileName' => $profileName,
|
||||
'canCreate' => $canCreate,
|
||||
'spendableBalance' => $spendableBalance,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user