matab-panel/app/Filament/Resources/PatientResource/Pages/EditPatient.php

279 lines
11 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
namespace App\Filament\Resources\PatientResource\Pages;
use App\Filament\Resources\PatientResource;
use App\Models\SurgeryAppointment;
use App\Models\SurgeryCenter;
use Carbon\Carbon;
use Filament\Actions\Action;
use Filament\Actions\DeleteAction;
use Filament\Forms\Components\DatePicker;
use Filament\Schemas\Components\Grid;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TimePicker;
use Filament\Resources\Pages\EditRecord;
use Filament\Support\Enums\Width;
use Illuminate\Support\Facades\Http;
use Morilog\Jalali\Jalalian;
class EditPatient extends EditRecord
{
protected static string $resource = PatientResource::class;
protected Width|string|null $maxContentWidth = Width::SevenExtraLarge;
protected function getHeaderActions(): array
{
return [
$this->getSaveFormAction()
->formId('form'),
Action::make('surgeryAppointment')
->label(__('patients.actions.surgery_appointment'))
->icon('heroicon-o-calendar-days')
->color(fn () => $this->getRecord()->surgeryAppointment ? 'success' : 'info')
->modalWidth(Width::Large)
->fillForm(function (): array {
$appointment = $this->getRecord()->surgeryAppointment;
if ($appointment) {
$surgeryDate = $appointment->surgery_date;
return [
'surgery_date' => $surgeryDate?->format('Y-m-d'),
'surgery_time' => $surgeryDate?->format('H:i'),
'surgery_center_id' => $appointment->surgery_center_id,
];
}
return [
'surgery_date' => null,
'surgery_time' => '09:00',
'surgery_center_id' => null,
];
})
->form([
Placeholder::make('patient_name')
->label(__('patients.fields.full_name'))
->content(fn () => $this->getRecord()->full_name),
Grid::make(2)
->schema([
DatePicker::make('surgery_date')
->label(__('patients.fields.surgery_date'))
->jalali()
->minDate(today())
->required(),
TimePicker::make('surgery_time')
->label(__('patients.fields.surgery_time'))
->native(false)
->seconds(false)
->minutesStep(15),
]),
Select::make('surgery_center_id')
->label(__('patients.fields.surgery_center'))
->options(fn () => SurgeryCenter::pluck('name', 'id')->toArray())
->searchable()
->required(),
])
->modalSubmitAction(false)
->extraModalFooterActions(fn (Action $action): array => [
$action->makeModalSubmitAction('saveAppointment', arguments: ['save' => true])
->label(__('patients.actions.save_appointment'))
->color('primary')
->icon('heroicon-o-check')
->visible(fn () => $this->getRecord()->surgeryAppointment === null),
Action::make('printAdmissionFromModal')
->label(__('patients.actions.print_admission'))
->color('warning')
->icon('heroicon-o-printer')
->url(fn () => route('surgery-appointment.print.admission', $this->getRecord()), shouldOpenInNewTab: true)
->visible(fn () => $this->getRecord()->surgeryAppointment !== null),
$action->makeModalSubmitAction('deleteAppointment', arguments: ['delete' => true])
->label(__('patients.actions.delete_appointment'))
->color('danger')
->icon('heroicon-o-trash')
->visible(fn () => $this->getRecord()->surgeryAppointment !== null),
])
->action(function (array $data, array $arguments): void {
$record = $this->getRecord();
if (! empty($arguments['delete'])) {
$existingAppointment = $record->surgeryAppointment;
SurgeryAppointment::where('patient_id', $record->id)->delete();
$record->unsetRelation('surgeryAppointment');
if ($existingAppointment) {
\App\Filament\Pages\SmsLogsPage::cancelAppointmentMessages(
$record->hand_phone ?? '',
$existingAppointment->surgery_date->toDateTimeString(),
);
}
\Filament\Notifications\Notification::make()
->title(__('patients.actions.appointment_deleted'))
->success()
->send();
return;
}
$dateStr = $data['surgery_date'];
$timeStr = $data['surgery_time'] ?? '00:00';
$surgeryDateTime = Carbon::parse($dateStr . ' ' . $timeStr);
$jalaliDate = Jalalian::fromCarbon($surgeryDateTime)->format('Y/m/d');
$apiKey = \App\Models\OsurgInitial::val('sms_api_key', config('sms.api_key'));
$apiUrl = \App\Models\OsurgInitial::val('sms_api_url', config('sms.api_url'));
$smsPayload = [
'phoneNumber' => $record->hand_phone ?? '',
'patientName' => $record->full_name,
'surgeryDate' => $jalaliDate,
'patientId' => $record->id,
'surgeryDateFull' => $surgeryDateTime->toDateTimeString(),
];
// مرحله ۱: ارسال پیامک اولیه
try {
$response = Http::timeout(30)
->withHeader('X-API-Key', $apiKey)
->asJson()
->post($apiUrl . '/surgery-reminder', $smsPayload);
if (! ($response->json('success') ?? false)) {
\Filament\Notifications\Notification::make()
->title(__('patients.actions.api_failed'))
->body($response->json('message') ?? '')
->danger()
->send();
return;
}
} catch (\Throwable $e) {
\Filament\Notifications\Notification::make()
->title(__('patients.actions.api_failed'))
->body($e->getMessage())
->danger()
->send();
return;
}
$appointment = SurgeryAppointment::updateOrCreate(
['patient_id' => $record->id],
[
'surgery_date' => $surgeryDateTime,
'surgery_center_id' => $data['surgery_center_id'],
]
);
$record->unsetRelation('surgeryAppointment');
try {
Http::timeout(30)
->withHeader('X-API-Key', $apiKey)
->asJson()
->post($apiUrl . '/surgery-reminder', array_merge($smsPayload, [
'appointmentId' => $appointment->id,
]));
} catch (\Throwable) {
}
\Filament\Notifications\Notification::make()
->title(__('patients.actions.appointment_saved'))
->body(__('patients.actions.sms_sent'))
->success()
->send();
}),
Action::make('printPrescription')
->label(__('prescriptions.actions.print_prescription'))
->icon('heroicon-o-printer')
->color('info')
->visible(fn () => $this->getRecord()->prescriptions()->exists())
->url(fn () => route('prescription.print', $this->getRecord()->prescriptions()->latest()->first()))
->openUrlInNewTab(),
Action::make('printAdmission')
->label(__('prescriptions.actions.print_admission'))
->icon('heroicon-o-printer')
->color('warning')
->visible(fn () => $this->getRecord()->surgeryAppointment !== null)
->url(fn () => route('surgery-appointment.print.admission', $this->getRecord()))
->openUrlInNewTab(),
Action::make('printLab')
->label(__('prescriptions.actions.print_lab'))
->icon('heroicon-o-beaker')
->color('gray')
->url(fn () => route('patient.print.lab', $this->getRecord()))
->openUrlInNewTab(),
DeleteAction::make(),
];
}
protected function mutateFormDataBeforeFill(array $data): array
{
foreach (['birth_date'] as $field) {
if (($data[$field] ?? null) === '') {
$data[$field] = null;
}
}
foreach (['surgery_before', 'sergery_after'] as $field) {
if (($data[$field] ?? null) === '') {
$data[$field] = null;
}
}
foreach (['current_illness_1', 'current_illness_2', 'has_alergyto'] as $field) {
if (is_null($data[$field] ?? null)) {
$data[$field] = [];
}
}
foreach (['photos_before', 'photos_after', 'videos', 'audio_files'] as $field) {
$data[$field] = static::normalizeFileList($data[$field] ?? null);
}
return $data;
}
public static function normalizeFileList(mixed $value): array
{
if (empty($value)) {
return [];
}
if (is_string($value)) {
$decoded = json_decode($value, true);
$value = is_array($decoded) ? $decoded : [$value];
}
return collect((array) $value)
->map(function ($item) {
if (is_array($item) && isset($item['name'])) {
return $item['name'];
}
if (is_string($item) && $item !== '') {
return $item;
}
return null;
})
->filter()
->values()
->toArray();
}
protected function getFormActions(): array
{
return [];
}
}