CluPilotCloud/resources/views/livewire/admin/grant-plan.blade.php

192 lines
12 KiB
PHP

<?php use Illuminate\Support\Number; ?>
{{-- R24: the longest modal in the console — every plan, every add-on, a note
field. It was well past the bottom of the window and took its own grant
button with it. --}}
<x-ui.modal>
<x-slot:header>
{{-- Its own header: whose account this is belongs beside the title, and
the plain `title` prop cannot say two things. --}}
<div class="flex items-center justify-between gap-3">
<h3 class="text-base font-semibold text-ink">{{ __('admin.grant.title') }}</h3>
<span class="rounded bg-surface-2 px-2 py-0.5 text-xs text-muted">{{ $customerName }}</span>
</div>
</x-slot:header>
@if (count($grants) > 0)
<div class="mt-4 rounded-lg border border-line bg-surface-2 p-3">
<p class="text-xs font-semibold uppercase tracking-wider text-muted">{{ __('admin.grant.existing_title') }}</p>
<ul class="mt-2 space-y-2">
@foreach ($grants as $g)
@php
$lapsed = $g['granted_until'] && $g['granted_until']->isPast();
$nearingEnd = ! $lapsed && $g['granted_until'] && now()->diffInDays($g['granted_until'], false) <= 30;
@endphp
<li class="rounded-md bg-surface px-3 py-2 text-sm">
<div class="flex items-center justify-between gap-2">
<span class="inline-flex items-center gap-1.5 font-medium text-ink">
<x-ui.icon :name="$g['kind'] === 'package' ? 'box' : 'plug'" class="size-3.5 text-muted" />
{{ $g['label'] }}
</span>
<span class="font-mono text-xs text-muted">
{{ $g['price_cents'] === 0 ? __('admin.grant.free') : Number::currency($g['price_cents'] / 100, in: 'EUR', locale: app()->getLocale()) }}
</span>
</div>
<p class="mt-0.5 text-xs text-muted">
{{ __('admin.grant.by_on', ['who' => $g['granted_by'], 'when' => $g['granted_at']->local()->isoFormat('D. MMM YYYY')]) }}
</p>
@if ($g['note'])
<p class="mt-0.5 text-xs italic text-muted">{{ $g['note'] }}</p>
@endif
@if ($g['granted_until'])
<p @class([
'mt-1.5 inline-flex items-center gap-1 rounded-pill px-2 py-0.5 text-xs font-medium',
'bg-danger-bg text-danger' => $lapsed,
'bg-warning-bg text-warning' => $nearingEnd,
'bg-surface-2 text-muted' => ! $lapsed && ! $nearingEnd,
])>
<x-ui.icon name="calendar" class="size-3.5" />
{{ __('admin.grant.until', ['date' => $g['granted_until']->local()->isoFormat('D. MMM YYYY')]) }}
@if ($lapsed)
· {{ __('admin.grant.lapsed') }}
@elseif ($nearingEnd)
· {{ __('admin.grant.ending_soon') }}
@endif
</p>
@else
<p class="mt-1.5 text-xs text-muted">{{ __('admin.grant.unlimited') }}</p>
@endif
</li>
@endforeach
</ul>
</div>
@endif
<div class="mt-5">
@if ($hasSubscription)
<div class="flex rounded-md border border-line-strong p-1 text-sm">
<button type="button" wire:click="$set('kind', 'package')"
class="flex-1 rounded px-3 py-1.5 font-medium {{ $kind === 'package' ? 'bg-accent text-white' : 'text-muted' }}">
{{ __('admin.grant.kind_package') }}
</button>
<button type="button" wire:click="$set('kind', 'addon')"
class="flex-1 rounded px-3 py-1.5 font-medium {{ $kind === 'addon' ? 'bg-accent text-white' : 'text-muted' }}">
{{ __('admin.grant.kind_addon') }}
</button>
</div>
@endif
@if ($kind === 'package')
<div class="mt-4 space-y-4">
<div>
<label class="text-sm font-medium text-body" for="grant-plan">{{ __('admin.grant.plan') }}</label>
<select id="grant-plan" wire:model.live="plan" class="mt-1.5 w-full rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-body">
<option value="">{{ __('admin.grant.choose') }}</option>
@foreach ($plans as $key => $p)
<option value="{{ $key }}">{{ $p['name'] }}</option>
@endforeach
</select>
@error('plan')<p class="mt-1 text-xs text-danger">{{ $message }}</p>@enderror
</div>
<div class="grid grid-cols-2 gap-3">
<div>
<label class="text-sm font-medium text-body" for="grant-term">{{ __('admin.grant.term') }}</label>
<select id="grant-term" wire:model.live="term" class="mt-1.5 w-full rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-body">
<option value="monthly">{{ __('admin.grant.monthly') }}</option>
<option value="yearly">{{ __('admin.grant.yearly') }}</option>
</select>
</div>
<div>
<label class="text-sm font-medium text-body" for="grant-datacenter">{{ __('admin.grant.datacenter') }}</label>
<select id="grant-datacenter" wire:model="datacenter" class="mt-1.5 w-full rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-body">
@foreach ($datacenters as $code => $name)
<option value="{{ $code }}">{{ $name }} ({{ $code }})</option>
@endforeach
</select>
@error('datacenter')<p class="mt-1 text-xs text-danger">{{ $message }}</p>@enderror
</div>
</div>
<div class="rounded-lg border border-line bg-surface-2 p-3">
<p class="text-xs font-semibold uppercase tracking-wider text-muted">{{ __('admin.grant.bonus_title') }}</p>
<p class="mt-1 text-xs text-muted">{{ __('admin.grant.bonus_hint') }}</p>
<div class="mt-2 grid grid-cols-3 gap-3">
<div>
<label class="text-xs text-muted" for="grant-bonus-quota">{{ __('admin.grant.bonus_quota') }}</label>
<input id="grant-bonus-quota" type="number" min="0" wire:model="bonusQuotaGb" placeholder="0"
class="mt-1 w-full rounded-md border border-line-strong bg-surface px-2 py-1.5 text-sm text-ink" />
</div>
<div>
<label class="text-xs text-muted" for="grant-bonus-seats">{{ __('admin.grant.bonus_seats') }}</label>
<input id="grant-bonus-seats" type="number" min="0" wire:model="bonusSeats" placeholder="0"
class="mt-1 w-full rounded-md border border-line-strong bg-surface px-2 py-1.5 text-sm text-ink" />
</div>
<div>
<label class="text-xs text-muted" for="grant-bonus-traffic">{{ __('admin.grant.bonus_traffic') }}</label>
<input id="grant-bonus-traffic" type="number" min="0" wire:model="bonusTrafficGb" placeholder="0"
class="mt-1 w-full rounded-md border border-line-strong bg-surface px-2 py-1.5 text-sm text-ink" />
</div>
</div>
</div>
</div>
@else
<div class="mt-4 space-y-4">
<div>
<label class="text-sm font-medium text-body" for="grant-addon">{{ __('admin.grant.addon') }}</label>
<select id="grant-addon" wire:model.live="addonKey" class="mt-1.5 w-full rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-body">
<option value="">{{ __('admin.grant.choose') }}</option>
@foreach (array_keys($addons) as $key)
<option value="{{ $key }}">{{ __('billing.addon.'.$key.'.name') }}</option>
@endforeach
</select>
@error('addonKey')<p class="mt-1 text-xs text-danger">{{ $message }}</p>@enderror
</div>
<div>
<label class="text-sm font-medium text-body" for="grant-quantity">{{ __('admin.grant.quantity') }}</label>
<input id="grant-quantity" type="number" min="1" wire:model="quantity"
class="mt-1.5 w-full rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-ink" />
@error('quantity')<p class="mt-1 text-xs text-danger">{{ $message }}</p>@enderror
</div>
</div>
@endif
<div class="mt-4 grid grid-cols-2 gap-3">
<div>
<label class="text-sm font-medium text-body" for="grant-price">{{ __('admin.grant.price') }}</label>
<div class="mt-1.5 flex items-center gap-2">
<input id="grant-price" type="text" inputmode="decimal" wire:model="priceEuros"
class="w-full rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-ink" />
<span class="text-sm text-muted">€</span>
</div>
@if ($cataloguePriceCents !== null)
<p class="mt-1 text-xs text-muted">
{{ __('admin.grant.catalogue_price', ['price' => Number::currency($cataloguePriceCents / 100, in: 'EUR', locale: app()->getLocale())]) }}
</p>
@endif
@error('priceEuros')<p class="mt-1 text-xs text-danger">{{ $message }}</p>@enderror
</div>
<div>
<label class="text-sm font-medium text-body" for="grant-until">{{ __('admin.grant.until_label') }}</label>
<input id="grant-until" type="date" wire:model="until"
class="mt-1.5 w-full rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-ink" />
<p class="mt-1 text-xs text-muted">{{ __('admin.grant.until_hint') }}</p>
</div>
</div>
<div class="mt-4">
<label class="text-sm font-medium text-body" for="grant-note">{{ __('admin.grant.note') }}</label>
<textarea id="grant-note" rows="2" wire:model="note"
class="mt-1.5 w-full rounded-md border border-line-strong bg-surface px-3 py-2 text-sm text-ink"></textarea>
@error('note')<p class="mt-1 text-xs text-danger">{{ $message }}</p>@enderror
</div>
</div>
<x-slot:footer>
<div class="flex justify-end gap-3">
<x-ui.button variant="secondary" x-on:click="Livewire.dispatch('closeModal')">{{ __('admin.grant.cancel') }}</x-ui.button>
<x-ui.button variant="primary" wire:click="grant" wire:loading.attr="disabled">
<x-ui.icon name="tag" class="size-4" />{{ __('admin.grant.submit') }}
</x-ui.button>
</div>
</x-slot:footer>
</x-ui.modal>