Files

313 lines
14 KiB
PHP

<div>
<form wire:submit.prevent="showConfirmPaymentModal">
@csrf
<div class="bg-theme-background px-4 py-4 shadow sm:rounded-lg sm:p-6">
@php
$hasNoAccounts = false;
$isAdminProfile = session('activeProfileType') === 'App\Models\Admin';
if ($isAdminProfile) {
$hasNoAccounts = true;
} elseif (getActiveProfile() && method_exists(getActiveProfile(), 'accounts')) {
$hasNoAccounts = getActiveProfile()->accounts()->notRemoved()->count() === 0;
}
@endphp
@if($hasNoAccounts)
<div class="mb-6 rounded-lg border border-theme-border bg-theme-surface p-4 text-theme-primary">
<div class="flex items-center">
<div>
<h3 class="font-semibold">{{ __('No accounts available') }}</h3>
<p class="mt-1 text-sm">
@if($isAdminProfile)
{{ __('Admin profiles do not have accounts and cannot make payments. Please switch to a different profile to make payments.') }}
@else
{{ __('Your profile does not have any accounts to make payments from. Please contact an administrator to set up an account.') }}
@endif
</p>
</div>
</div>
</div>
@endif
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6 sm:col-span-4">
<!--- Amount --->
@livewire('amount', [
'maxLengthHoursInput' => timebank_config('maxLengthHoursInput.user'),
'hours' => $hours,
'minutes' => $minutes,
'amount' => $amount,
])
@error('amount')
<div class="mb-3 text-sm text-red-700" role="alert">
{{ __($message) }}
</div>
@enderror
<!--- From account --->
@livewire('from-account')
@error('fromAccountId')
<div class="mb-3 text-sm text-red-700" role="alert">
{{ __($message) }}
</div>
@enderror
<!--- To Account --->
@livewire('to-account', ['toHolderName' => $toHolderName, 'toAccountId' => $toAccountId])
@error('toAccountId')
<div class="mb-3 text-sm text-red-700" role="alert">
{{ __($message) }}
</div>
@enderror
<!--- Description --->
<div class="mt-4">
<label for="description" class="mt-2 block text-sm font-medium text-theme-primary"> {{ __('Description') }}</label>
<textarea
wire:model.live.debounce.500ms="description"
id="description"
placeholder=" {{ __('Payment description') }}"
rows="5"
class="mt-1 placeholder-theme-light focus:ring-theme-accent focus:border-theme-accent block w-full shadow-sm sm:text-sm border-theme-primary rounded-md @error('description') is-invalid @enderror" name="description">
</textarea>
</div>
@error('description')
<div class="mb-3 text-sm text-red-700" role="alert">
{{ __($message) }}
</div>
@enderror
<!--- Transaction type --->
@livewire('transaction-type-radio', ['type' => $type, 'typeOptions' => $typeOptions])
@error('transactionTypeSelected.name')
<div class="mb-3 text-sm text-red-700" role="alert">
{{ __($message) }}
</div>
@enderror
<!--- Remember payment data checkbox ----->
<div class="my-4">
<x-checkbox id="rememberPaymentData" secondary label="{{ __('Remember payment data for next payment') }}" wire:model="rememberPaymentData"/>
</div>
</div>
</div>
<div class="text-right">
<x-jetstream.button type="submit" wire:target="showModal" :disabled="!canActiveProfileCreatePayments()">
{{ __('Pay') }}
</x-jetstream.button>
</div>
</div>
<!----Transfer limit error Modal ---->
<style>
/* Ensure Pay modals render above the fixed navigation bar (nav is z-[80]) */
#payment-limit-error-dialog,
#new-recipient-dialog,
#confirm-payment-dialog {
z-index: 90;
}
</style>
<x-jetstream.dialog-modal id="payment-limit-error-dialog" wire:model.live="isPaymentLimitErrorModalOpen">
<x-slot name="title">
{{ __('Payment limit') }}
</x-slot>
<x-slot name="content">
{{ $limitError }}
</x-slot>
<x-slot name="footer">
<x-jetstream.secondary-button wire:click="$toggle('isPaymentLimitErrorModalOpen')" wire:loading.attr="disabled">
{{ __('Back') }}
</x-jetstream.secondary-button>
</x-slot>
</x-jetstream.dialog-modal>
<!----New recipient confirmation Modal ---->
<x-jetstream.dialog-modal id="new-recipient-dialog" wire:model.live="isNewRecipientModalOpen">
<x-slot name="title">
{{ __('New recipient') }}
</x-slot>
<x-slot name="content">
{{ __('You previously never had any chat conversation or payments with :name (:name) from :location. Are you sure you want to select this account?', [
'name' => $pendingToAccountDetails['holderName'] ?? '',
'location' => $pendingToAccountDetails['holderLocation'] ?? '',
]) }}
</x-slot>
<x-slot name="footer">
<x-jetstream.secondary-button wire:click="cancelNewRecipient" wire:loading.attr="disabled">
{{ __('Cancel') }}
</x-jetstream.secondary-button>
<x-jetstream.button class="ml-3" wire:click="confirmNewRecipient" wire:loading.attr="disabled">
{{ __('Continue') }}
</x-jetstream.button>
</x-slot>
</x-jetstream.dialog-modal>
<!---- Confirmation Modal ---->
@if (!$limitError && !empty($transactionTypeSelected))
<x-jetstream.dialog-modal id="confirm-payment-dialog" wire:model.live="isConfirmPaymentModalOpen">
<x-slot name="title">
{{ __('Confirm your payment') }}
</x-slot>
<x-slot name="content">
<div class="pb-3 px-1 sm:px-3">
<div class="font-semibold text-sm sm:text-base">
{{ __('Description') }}
</div>
<div class="text-sm sm:text-base">{{ $description }}</div>
</div>
<div class="flex flex-col py-3 gap-0">
<!-- From account row -->
<div class="flex items-center gap-4">
<div class="flex w-16 flex-shrink-0 justify-end">
<img alt="{{ session('activeProfileName') }}"
class="h-16 w-16 rounded-full profile-photo object-cover outline outline-1 outline-offset-2 outline-theme-primary"
src="{{ Storage::url(session('activeProfilePhoto')) }}">
</div>
<div class="leading-tight">
<div class="font-semibold text-sm">{{ session('activeProfileName') }}</div>
<div class="text-theme-secondary text-xs">{{ __(ucfirst(strtolower($fromAccountName))) }} {{ __('bank account') }}</div>
</div>
</div>
<!-- Connector: line, icon, amount, arrow -->
<div class="flex items-stretch gap-4">
<!-- Left: continuous line with icon centered and arrow at bottom -->
<div class="relative flex w-16 flex-shrink-0 justify-center">
<!-- Full-height vertical line -->
<div class="absolute inset-x-1/2 top-0 bottom-0 w-px bg-theme-primary"></div>
<!-- Icon centered vertically -->
<div class="relative flex h-full flex-col items-center justify-center">
<div class="flex h-6 w-6 items-center justify-center rounded-full bg-white text-theme-primary outline outline-1 outline-offset-1 outline-theme-primary">
<x-icon class="{{ ($transactionTypeSelected['icon'] ?? '') === 'arrow-path' ? '-scale-x-100' : '' }}" mini name="{{ $transactionTypeSelected['icon'] }}" />
</div>
</div>
<!-- Arrow at the bottom -->
<div class="absolute bottom-0 flex justify-center">
<svg fill="none" height="10" viewBox="0 0 15 10" width="15" xmlns="http://www.w3.org/2000/svg">
<path d="M7.5 0 L7.5 8 M7.5 8 L0 2 M7.5 8 L15 2" stroke-width="1" stroke="#4B5563" />
</svg>
</div>
</div>
<!-- Right: amount + label -->
<div class="flex items-center leading-tight py-2">
<div>
<div class="font-semibold text-sm">{{ tbFormat($amount) }}</div>
<div class="text-theme-secondary text-xs">{{ __($transactionTypeSelected['label']) }}</div>
</div>
</div>
</div>
<!-- To account row -->
<div class="flex items-center gap-4">
<div class="flex w-16 flex-shrink-0 justify-end">
<img alt="{{ $toHolderName }}"
class="h-16 w-16 rounded-full object-cover outline outline-1 outline-offset-2 outline-theme-primary"
src="{{ $toHolderPhoto }}">
</div>
<div class="leading-tight">
<div class="font-semibold text-sm">{{ $toHolderName }}</div>
<div class="text-theme-secondary text-xs">{{ __(ucfirst($toAccountName)) }} {{ __('bank account') }}</div>
</div>
</div>
</div>
@if (session('error'))
<div class="alert alert-danger text-red-500">
{{ session('error') }}
</div>
@endif
</x-slot>
<x-slot name="footer">
@if (session('error'))
<x-jetstream.secondary-button wire:click="$toggle('isConfirmPaymentModalOpen')" wire:loading.attr="disabled">
{{ __('Back') }}
</x-jetstream.secondary-button>
@else
<x-jetstream.secondary-button class="w-32 justify-center" wire:click="$toggle('isConfirmPaymentModalOpen')"
wire:loading.attr="disabled">
{{ __('Cancel') }}
</x-jetstream.secondary-button>
<x-jetstream.button class="ml-3 w-32 justify-center" wire:click="doTransfer()"
wire:loading.attr="disabled" :disabled="!canActiveProfileCreatePayments()">
{{ __('Pay') }}
</x-jetstream.button>
@endif
</x-slot>
</x-jetstream.dialog-modal>
@endif
</form>
{{-- Payment success modal --}}
<style>
/* Constrain success modal to viewport with margin, keep footer always visible */
#payment-success-dialog .mb-6 {
max-height: calc(100svh - 3rem);
display: flex;
flex-direction: column;
}
#payment-success-dialog .mb-6 > div {
display: flex;
flex-direction: column;
min-height: 0;
flex: 1;
}
#payment-success-dialog .mb-6 > div > .m-6 {
overflow-y: auto;
min-height: 0;
flex: 1;
}
</style>
<x-jetstream.dialog-modal id="payment-success-dialog" wire:model.live="isPaymentSuccessModalOpen" closeButton="true" maxWidth="sm">
<x-slot name="title">{{ __('Transaction done!') }}</x-slot>
<x-slot name="content">
<div class="flex flex-col items-center gap-3 py-2">
@if ($successHolderPhoto)
<img alt="{{ $successHolderName }}"
src="{{ $successHolderPhoto }}"
class="h-20 w-20 shrink-0 rounded-full object-cover outline outline-1 outline-offset-2 outline-theme-primary">
@endif
<div class="text-center leading-tight">
<div class="text-sm text-theme-secondary">{{ __('Payment sent to') }}</div>
<div class="mt-1 font-semibold text-theme-primary">{{ $successHolderName }}</div>
@if ($successAccountName)
<div class="text-xs text-theme-secondary">{{ $successAccountName }} {{ __('bank account') }}</div>
@endif
<div class="mt-2 font-bold text-theme-primary">{{ $successAmount }}</div>
</div>
</div>
@if ($successQrSvg)
{{-- QR hidden via Alpine when rendered size would drop below 200px --}}
<div x-data="{ showQr: true }"
x-init="$nextTick(() => { showQr = $el.offsetWidth >= 200 })"
x-show="showQr"
class="mt-4 flex flex-col items-center gap-2">
<a href="{{ $successTransactionUrl }}"
class="block w-full max-w-[200px] [&>svg]:h-auto [&>svg]:w-full">
{!! $successQrSvg !!}
</a>
<a href="{{ $successTransactionUrl }}"
class="text-xs text-theme-secondary underline hover:text-theme-primary">
{{ __('View transaction statement') }}
</a>
</div>
@endif
</x-slot>
<x-slot name="footer">
<div class="w-full flex justify-center">
<x-jetstream.button wire:click="$set('isPaymentSuccessModalOpen', false)">
{{ __('OK') }}
</x-jetstream.button>
</div>
</x-slot>
</x-jetstream.dialog-modal>
</div>