Open Prescribe from consultation as a modal/bottomsheet.
Deploy Ladill Care / deploy (push) Successful in 46s

Reuse the shared prescription form in x-modal so desktop gets a popup and mobile gets the existing bottomsheet behavior, then return to the consultation after create.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-18 14:58:58 +00:00
co-authored by Cursor
parent 2b3eed8f84
commit 40325144bb
6 changed files with 106 additions and 41 deletions
@@ -216,6 +216,7 @@ class ConsultationController extends Controller
'pathwayInstruments' => $pathwayInstruments ?? collect(),
'queueIntegration' => $queueIntegration,
'queueBranchId' => $queueBranchId,
'medicationRoutes' => config('care.medication_routes'),
]);
}
@@ -187,6 +187,12 @@ class PrescriptionController extends Controller
$return = app(ConsultationReturnContext::class);
$return->remember($consultation);
if ($request->input('return_to') === 'consultation') {
return redirect()
->route('care.consultations.show', $consultation)
->with('success', 'Prescription created.');
}
return redirect()->route('care.prescriptions.show', array_filter([
'prescription' => $prescription,
...$return->query($consultation),
@@ -34,9 +34,13 @@
@endif
@if ($canPrescribe)
<a href="{{ route('care.prescriptions.create', [$consultation, 'from_consultation' => $consultation->uuid]) }}" class="{{ $btnSecondary }}">
<button
type="button"
class="{{ $btnSecondary }}"
@click.stop="$dispatch('open-modal', {{ \Illuminate\Support\Js::from('prescribe-'.$consultation->id) }})"
>
Prescribe
</a>
</button>
@endif
@if ($canRequestInvestigations && $investigationTypes->isNotEmpty() && ! $isCompleted)
@@ -486,4 +486,20 @@
</div>
</x-modal>
@endif
@if ($canPrescribe)
<x-modal :name="'prescribe-'.$consultation->id" maxWidth="2xl">
<div class="px-5 pb-6 pt-2 sm:px-6 sm:pb-6 sm:pt-4">
<h2 class="pr-8 text-lg font-semibold text-slate-900">New prescription</h2>
<p class="mt-1 text-sm text-slate-500">{{ $consultation->patient->fullName() }} ({{ $consultation->patient->patient_number }})</p>
<div class="mt-4 max-h-[70vh] overflow-y-auto pr-1">
@include('care.prescriptions.partials.form', [
'consultation' => $consultation,
'routes' => $medicationRoutes ?? config('care.medication_routes'),
'compact' => true,
])
</div>
</div>
</x-modal>
@endif
</x-app-layout>
@@ -4,43 +4,9 @@
<h1 class="text-xl font-semibold text-slate-900">New prescription</h1>
<p class="mt-1 text-sm text-slate-500">{{ $consultation->patient->fullName() }} ({{ $consultation->patient->patient_number }})</p>
<form method="POST" action="{{ route('care.prescriptions.store', $consultation) }}" class="mt-6 space-y-6" x-data="{ items: [{ is_procedure: false, name: '', dosage: '', frequency: '', duration: '', route: 'oral', quantity: '', instructions: '' }] }">
@csrf
<section class="rounded-2xl border border-slate-200 bg-white p-6">
<div class="flex items-center justify-between">
<h2 class="text-sm font-semibold uppercase text-slate-500">Medications & procedures</h2>
<button type="button" @click="items.push({ is_procedure: false, name: '', dosage: '', frequency: '', duration: '', route: 'oral', quantity: '', instructions: '' })" class="text-sm text-sky-600">Add line</button>
</div>
<template x-for="(item, index) in items" :key="index">
<div class="mt-4 grid gap-3 rounded-xl border border-slate-100 bg-slate-50 p-4 sm:grid-cols-2">
<div class="sm:col-span-2 flex items-center gap-4">
<label class="inline-flex items-center gap-2 text-sm"><input type="checkbox" :name="'items['+index+'][is_procedure]'" value="1" x-model="item.is_procedure" class="rounded border-slate-300"> Procedure</label>
</div>
<div class="sm:col-span-2">
<input type="text" :name="'items['+index+'][name]'" x-model="item.name" required placeholder="Medication or procedure name" class="w-full rounded-lg border-slate-300 text-sm">
</div>
<input type="text" :name="'items['+index+'][dosage]'" x-model="item.dosage" placeholder="Dosage" class="rounded-lg border-slate-300 text-sm">
<input type="text" :name="'items['+index+'][frequency]'" x-model="item.frequency" placeholder="Frequency" class="rounded-lg border-slate-300 text-sm">
<input type="text" :name="'items['+index+'][duration]'" x-model="item.duration" placeholder="Duration" class="rounded-lg border-slate-300 text-sm">
<select :name="'items['+index+'][route]'" x-model="item.route" class="rounded-lg border-slate-300 text-sm">
@foreach ($routes as $value => $label)
<option value="{{ $value }}">{{ $label }}</option>
@endforeach
</select>
<input type="text" :name="'items['+index+'][quantity]'" x-model="item.quantity" placeholder="Quantity" class="rounded-lg border-slate-300 text-sm">
<input type="text" :name="'items['+index+'][instructions]'" x-model="item.instructions" placeholder="Instructions" class="sm:col-span-2 rounded-lg border-slate-300 text-sm">
</div>
</template>
</section>
<section class="rounded-2xl border border-slate-200 bg-white p-6">
<label class="block text-sm font-medium text-slate-700">Notes</label>
<textarea name="notes" rows="2" class="mt-1 w-full rounded-lg border-slate-300 text-sm"></textarea>
<input type="hidden" name="activate" value="1">
<input type="hidden" name="from_consultation" value="{{ $consultation->uuid }}">
</section>
<div class="flex gap-3">
<button type="submit" class="btn-primary">Create prescription</button>
<a href="{{ route('care.consultations.show', $consultation) }}" class="rounded-lg border border-slate-200 px-4 py-2 text-sm text-slate-600">Cancel</a>
</div>
</form>
@include('care.prescriptions.partials.form', [
'consultation' => $consultation,
'routes' => $routes,
'compact' => false,
])
</x-app-layout>
@@ -0,0 +1,72 @@
{{-- Shared prescription line-item form body (create page + consultation modal). --}}
@php
$routes = $routes ?? config('care.medication_routes', []);
$compact = $compact ?? false;
@endphp
<form
method="POST"
action="{{ route('care.prescriptions.store', $consultation) }}"
class="{{ $compact ? 'space-y-4' : 'mt-6 space-y-6' }}"
x-data="{ items: [{ is_procedure: false, name: '', dosage: '', frequency: '', duration: '', route: 'oral', quantity: '', instructions: '' }] }"
>
@csrf
<section @class([
'space-y-3' => $compact,
'rounded-2xl border border-slate-200 bg-white p-6' => ! $compact,
])>
<div class="flex items-center justify-between">
<h2 @class([
'text-sm font-semibold text-slate-800' => $compact,
'text-sm font-semibold uppercase text-slate-500' => ! $compact,
])>Medications &amp; procedures</h2>
<button type="button" @click="items.push({ is_procedure: false, name: '', dosage: '', frequency: '', duration: '', route: 'oral', quantity: '', instructions: '' })" class="text-sm font-medium text-sky-600 hover:text-sky-700">Add line</button>
</div>
<template x-for="(item, index) in items" :key="index">
<div class="grid gap-3 rounded-xl border border-slate-100 bg-slate-50 p-4 sm:grid-cols-2">
<div class="sm:col-span-2 flex items-center gap-4">
<label class="inline-flex items-center gap-2 text-sm"><input type="checkbox" :name="'items['+index+'][is_procedure]'" value="1" x-model="item.is_procedure" class="rounded border-slate-300"> Procedure</label>
</div>
<div class="sm:col-span-2">
<input type="text" :name="'items['+index+'][name]'" x-model="item.name" required placeholder="Medication or procedure name" class="w-full rounded-lg border-slate-300 text-sm">
</div>
<input type="text" :name="'items['+index+'][dosage]'" x-model="item.dosage" placeholder="Dosage" class="rounded-lg border-slate-300 text-sm">
<input type="text" :name="'items['+index+'][frequency]'" x-model="item.frequency" placeholder="Frequency" class="rounded-lg border-slate-300 text-sm">
<input type="text" :name="'items['+index+'][duration]'" x-model="item.duration" placeholder="Duration" class="rounded-lg border-slate-300 text-sm">
<select :name="'items['+index+'][route]'" x-model="item.route" class="rounded-lg border-slate-300 text-sm">
@foreach ($routes as $value => $label)
<option value="{{ $value }}">{{ $label }}</option>
@endforeach
</select>
<input type="text" :name="'items['+index+'][quantity]'" x-model="item.quantity" placeholder="Quantity" class="rounded-lg border-slate-300 text-sm">
<input type="text" :name="'items['+index+'][instructions]'" x-model="item.instructions" placeholder="Instructions" class="sm:col-span-2 rounded-lg border-slate-300 text-sm">
</div>
</template>
</section>
<section @class([
'space-y-2' => $compact,
'rounded-2xl border border-slate-200 bg-white p-6' => ! $compact,
])>
<label class="block text-sm font-medium text-slate-700">Notes</label>
<textarea name="notes" rows="2" class="mt-1 w-full rounded-lg border-slate-300 text-sm"></textarea>
<input type="hidden" name="activate" value="1">
<input type="hidden" name="from_consultation" value="{{ $consultation->uuid }}">
@if ($compact)
<input type="hidden" name="return_to" value="consultation">
@endif
</section>
<div @class(['flex flex-col-reverse gap-2 sm:flex-row sm:justify-end' => $compact, 'flex gap-3' => ! $compact])>
@if ($compact)
<button
type="button"
class="rounded-xl border border-slate-200 px-4 py-2.5 text-sm font-semibold text-slate-700 hover:bg-slate-50"
@click="$dispatch('close-modal', {{ \Illuminate\Support\Js::from('prescribe-'.$consultation->id) }})"
>
Cancel
</button>
<button type="submit" class="btn-primary">Create prescription</button>
@else
<button type="submit" class="btn-primary">Create prescription</button>
<a href="{{ route('care.consultations.show', $consultation) }}" class="rounded-lg border border-slate-200 px-4 py-2 text-sm text-slate-600">Cancel</a>
@endif
</div>
</form>