CluPilotCloud/resources/views/livewire/admin/customers.blade.php

108 lines
8.2 KiB
PHP

<div class="space-y-5">
<div class="animate-rise">
<h1 class="text-2xl font-bold tracking-tight text-ink">{{ __('admin.nav.customers') }}</h1>
<p class="mt-1 text-sm text-muted">{{ __('admin.customers_sub') }}</p>
</div>
<div class="grid grid-cols-1 gap-5 lg:grid-cols-[1fr_300px] lg:items-start">
<div class="overflow-hidden rounded-lg border border-line bg-surface shadow-xs animate-rise [animation-delay:60ms]">
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead>
<tr class="border-b border-line bg-surface-2 text-left text-xs font-semibold text-muted">
<th class="px-4 py-3 font-semibold">{{ __('admin.col.customer') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.plan') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.mrr') }}</th>
<th class="px-4 py-3 font-semibold">{{ __('admin.col.status') }}</th>
<th class="px-4 py-3 text-right font-semibold">{{ __('admin.col.actions') }}</th>
</tr>
</thead>
<tbody>
@forelse ($rows as $r)
<tr class="border-b border-line last:border-0 hover:bg-surface-hover">
<td class="px-4 py-3">
{{-- The row leads somewhere now. The list
was the end of the road: an operator
answering a question had the name here
and the mail client in another window. --}}
<a href="{{ route('admin.customer', $r['uuid']) }}" wire:navigate
class="font-medium text-ink hover:underline">{{ $r['name'] }}</a>
<p class="font-mono text-xs text-muted">{{ $r['instance'] }}.clupilot.com</p>
</td>
<td class="px-4 py-3 text-body">
{{ $r['plan'] }}
@if ($r['granted'])
<span class="ml-1.5 inline-flex items-center gap-1 rounded-pill bg-accent-bg px-1.5 py-0.5 text-[11px] font-medium text-accent-text">
<x-ui.icon name="tag" class="size-3" />
{{ __('admin.granted_badge') }}
</span>
@endif
@if ($r['pending_change'])
{{-- Booked, not yet landed. Said on the
row that answers "what is this
customer on", because that is where
the question is asked. --}}
<p class="mt-0.5 flex items-center gap-1 text-xs text-muted">
<x-ui.icon name="calendar" class="size-4 text-warning" />
{{ __('admin.pending_change', ['plan' => $r['pending_change']['plan'], 'date' => $r['pending_change']['at']]) }}
</p>
@endif
</td>
<td class="px-4 py-3 font-mono text-body">{{ $r['mrr'] }}</td>
<td class="px-4 py-3"><x-ui.badge :status="$r['status']">{{ __('admin.status.'.$r['status']) }}</x-ui.badge></td>
<td class="px-4 py-3">
<div class="flex items-center justify-end gap-1.5">
@unless ($r['closed'])
<button type="button" wire:click="toggleSuspend('{{ $r['uuid'] }}')"
class="inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-xs font-semibold
{{ $r['suspended'] ? 'border-success-border text-success hover:bg-success-bg' : 'border-line text-muted hover:border-warning hover:text-warning' }}">
{{ $r['suspended'] ? __('admin.reactivate') : __('admin.suspend') }}
</button>
@endunless
@if (auth()->user()?->can('customers.grant_plan'))
<button type="button" title="{{ __('admin.grant_action') }}"
x-on:click="$dispatch('openModal', { component: 'admin.grant-plan', arguments: { uuid: '{{ $r['uuid'] }}' } })"
class="inline-flex items-center gap-1.5 rounded-md border border-line px-3 py-1.5 text-xs font-semibold text-body hover:border-accent-border hover:text-accent-text">
<x-ui.icon name="tag" class="size-3.5" />
{{ __('admin.grant_action') }}
</button>
@endif
{{-- Impersonation borrows the customer's PORTAL session; this
is administrator access to their Nextcloud itself. Two
different things, so two buttons. --}}
@if ($r['instance_uuid'] && auth()->user()?->can('instances.adminlogin'))
<button type="button" title="{{ __('instances.admin_action') }}"
x-on:click="$dispatch('openModal', { component: 'admin.instance-admin-access', arguments: { uuid: '{{ $r['instance_uuid'] }}' } })"
class="inline-flex items-center gap-1.5 rounded-md border border-line px-3 py-1.5 text-xs font-semibold text-body hover:border-accent-border hover:text-accent-text">
<x-ui.icon name="shield" class="size-3.5" />
{{ __('instances.admin_action') }}
</button>
@endif
<form method="POST" action="{{ route('admin.impersonate', $r['uuid']) }}" class="inline">
@csrf
<button type="submit"
class="inline-flex items-center gap-1.5 rounded-md border border-line px-3 py-1.5 text-xs font-semibold text-body hover:border-accent-border hover:text-accent-text">
<x-ui.icon name="log-out" class="size-3.5" />
{{ __('admin.impersonate') }}
</button>
</form>
</div>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="px-4 py-10 text-center text-sm text-muted">{{ __('admin.customers_empty') }}</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
<div class="rounded-lg border border-line bg-surface p-5 shadow-xs animate-rise [animation-delay:120ms]">
<h2 class="font-semibold text-ink">{{ __('admin.by_plan') }}</h2>
<div class="mt-3 h-56" wire:ignore><x-ui.chart :config="$plansChart" class="h-56" :label="__('admin.by_plan')" /></div>
</div>
</div>
</div>