Files
ladill-servers/resources/views/hosting/server-order.blade.php
T
isaaccladandCursor 1217bdac41
Deploy Ladill Servers / deploy (push) Successful in 22s
Fix 500 on authenticated pages by correcting Afia route.
Point Afia chat at servers.afia.chat, add missing input-error component, and fix stale layout/order route names.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-06 19:39:27 +00:00

305 lines
21 KiB
PHP

<x-user-layout>
<x-slot name="title">{{ $order->domain_name }} - Server Details</x-slot>
@php
$statusColors = [
'pending_payment' => 'bg-amber-50 text-amber-700 border-amber-200',
'pending_approval' => 'bg-amber-50 text-amber-700 border-amber-200',
'approved' => 'bg-blue-50 text-blue-700 border-blue-200',
'provisioning' => 'bg-blue-50 text-blue-700 border-blue-200',
'active' => 'bg-emerald-50 text-emerald-700 border-emerald-200',
'suspended' => 'bg-red-50 text-red-700 border-red-200',
'cancelled' => 'bg-gray-100 text-gray-500 border-gray-200',
'expired' => 'bg-gray-100 text-gray-500 border-gray-200',
'failed' => 'bg-red-50 text-red-700 border-red-200',
];
$statusLabels = collect([
'pending_payment', 'pending_approval', 'approved', 'provisioning',
'active', 'suspended', 'cancelled', 'expired', 'failed',
])->mapWithKeys(fn (string $status) => [
$status => \App\Models\CustomerHostingOrder::customerFacingStatusLabelFor($status),
])->all();
$statusColors['approved'] = 'bg-amber-50 text-amber-700 border-amber-200';
$backRoute = $order->product?->type === 'dedicated' ? route('servers.dedicated') : route('servers.vps');
$backLabel = $order->product?->type === 'dedicated' ? 'Dedicated Servers' : 'VPS';
$serverOrder = (array) ($order->meta['server_order'] ?? []);
$selectionSummary = (array) ($serverOrder['selection_summary'] ?? []);
$quote = (array) ($serverOrder['quote'] ?? []);
$panelRuntime = (array) data_get($order->meta, 'server_panel_runtime', data_get($serverOrder, 'panel_snapshot', []));
$quoteItems = collect((array) ($quote['line_items'] ?? []))
->filter(fn ($item) => ($item['code'] ?? null) !== 'base_plan')
->values();
@endphp
<div class="space-y-6" x-data="{ showCancelModal: false }">
{{-- Page Header --}}
<div class="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
<div>
<a href="{{ $backRoute }}" class="mb-2 inline-flex items-center gap-1 text-sm text-gray-500 hover:text-gray-700">
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5 8.25 12l7.5-7.5"/></svg>
Back to {{ $backLabel }}
</a>
<h1 class="text-2xl font-semibold tracking-tight text-gray-900">{{ $order->domain_name }}</h1>
<p class="mt-1 text-sm text-gray-500">{{ $order->product?->name ?? 'Server Order' }}</p>
</div>
<div class="flex items-center gap-2">
<span class="inline-flex items-center rounded-lg border px-3 py-1.5 text-sm font-medium {{ $statusColors[$order->status] ?? 'bg-gray-100 text-gray-500 border-gray-200' }}">
{{ $statusLabels[$order->status] ?? ucfirst($order->status) }}
</span>
</div>
</div>
<div class="grid gap-6 lg:grid-cols-3">
{{-- Main Content --}}
<div class="space-y-6 lg:col-span-2">
{{-- Server Details --}}
<div class="rounded-xl border border-gray-200 bg-white">
<div class="border-b border-gray-100 px-5 py-4">
<h2 class="text-sm font-semibold text-gray-900">Server Details</h2>
</div>
<div class="divide-y divide-gray-100">
<div class="flex items-center justify-between px-5 py-3">
<span class="text-sm text-gray-500">Server Name</span>
<span class="text-sm font-medium text-gray-900">{{ $order->domain_name }}</span>
</div>
<div class="flex items-center justify-between px-5 py-3">
<span class="text-sm text-gray-500">Plan</span>
<span class="text-sm font-medium text-gray-900">{{ $order->product?->name ?? '-' }}</span>
</div>
<div class="flex items-center justify-between px-5 py-3">
<span class="text-sm text-gray-500">Region</span>
<span class="text-sm font-medium text-gray-900">{{ $order->meta['region'] ?? 'EU' }}</span>
</div>
@if ($order->server_ip)
<div class="flex items-center justify-between px-5 py-3">
<span class="text-sm text-gray-500">IP Address</span>
<span class="font-mono text-sm font-medium text-gray-900">{{ $order->server_ip }}</span>
</div>
@endif
<div class="flex items-center justify-between px-5 py-3">
<span class="text-sm text-gray-500">Billing Cycle</span>
<span class="text-sm font-medium text-gray-900">{{ str($order->billing_cycle)->replace('_', ' ')->title() }}</span>
</div>
<div class="flex items-center justify-between px-5 py-3">
<span class="text-sm text-gray-500">Amount</span>
<span class="text-sm font-medium text-gray-900">{{ strtoupper($order->currency) }} {{ number_format($order->amount_paid, 2) }}</span>
</div>
</div>
</div>
@if ($panelRuntime !== [])
<div class="rounded-xl border border-gray-200 bg-white">
<div class="border-b border-gray-100 px-5 py-4">
<h2 class="text-sm font-semibold text-gray-900">Panel Mode</h2>
</div>
<div class="space-y-3 px-5 py-4">
<div>
<p class="text-sm font-medium text-gray-900">{{ $panelRuntime['label'] ?? 'Server Access' }}</p>
<p class="mt-1 text-sm text-gray-600">{{ $panelRuntime['primary_message'] ?? '' }}</p>
@if (! empty($panelRuntime['secondary_message']))
<p class="mt-1 text-xs text-gray-500">{{ $panelRuntime['secondary_message'] }}</p>
@endif
</div>
@if (! empty($panelRuntime['future_capabilities']))
<div class="rounded-lg bg-amber-50 px-3 py-2 text-xs text-amber-900">
Managed features after provisioning: {{ implode(', ', (array) $panelRuntime['future_capabilities']) }}
</div>
@endif
</div>
</div>
@endif
{{-- Server Resources --}}
@if ($order->product)
<div class="rounded-xl border border-gray-200 bg-white">
<div class="border-b border-gray-100 px-5 py-4">
<h2 class="text-sm font-semibold text-gray-900">Server Resources</h2>
</div>
<div class="grid grid-cols-2 gap-4 p-5 sm:grid-cols-4">
<div class="text-center">
<p class="text-2xl font-bold text-gray-900">{{ $order->product->cpu_cores }}</p>
<p class="text-xs text-gray-500">vCPU Cores</p>
</div>
<div class="text-center">
<p class="text-2xl font-bold text-gray-900">{{ $order->product->formatRam() }}</p>
<p class="text-xs text-gray-500">RAM</p>
</div>
<div class="text-center">
<p class="text-2xl font-bold text-gray-900">{{ $order->product->formatDiskSize() }}</p>
<p class="text-xs text-gray-500">SSD Storage</p>
</div>
<div class="text-center">
<p class="text-2xl font-bold text-gray-900">{{ $order->product->formatBandwidth() }}</p>
<p class="text-xs text-gray-500">Bandwidth</p>
</div>
</div>
</div>
@endif
@if ($selectionSummary !== [])
<div class="rounded-xl border border-gray-200 bg-white">
<div class="border-b border-gray-100 px-5 py-4">
<h2 class="text-sm font-semibold text-gray-900">Selected Options</h2>
</div>
<div class="divide-y divide-gray-100">
@foreach ($selectionSummary as $item)
<div class="flex items-start justify-between gap-4 px-5 py-3">
<div>
<p class="text-sm text-gray-500">{{ $item['label'] ?? 'Option' }}</p>
@if (!empty($item['description']))
<p class="mt-1 text-xs text-gray-400">{{ $item['description'] }}</p>
@endif
</div>
<div class="text-right">
<p class="text-sm font-medium text-gray-900">{{ $item['value'] ?? '-' }}</p>
@if (!empty($item['monthly_amount']))
<p class="mt-1 text-xs text-gray-500">+ {{ strtoupper($order->currency) }} {{ number_format((float) $item['monthly_amount'], 2) }}/mo before term scaling</p>
@endif
</div>
</div>
@endforeach
</div>
</div>
@endif
@if ($quoteItems->isNotEmpty())
<div class="rounded-xl border border-gray-200 bg-white">
<div class="border-b border-gray-100 px-5 py-4">
<h2 class="text-sm font-semibold text-gray-900">Pricing Breakdown</h2>
</div>
<div class="space-y-3 p-5">
@foreach ($quoteItems as $item)
<div class="flex items-start justify-between gap-4 text-sm">
<p class="font-medium text-gray-900">{{ $item['label'] ?? 'Add-on' }}</p>
<span class="font-medium text-gray-900">{{ strtoupper($order->currency) }} {{ number_format((float) ($item['amount'] ?? 0), 2) }}</span>
</div>
@endforeach
<div class="flex items-center justify-between border-t border-gray-100 pt-3 text-sm font-semibold text-gray-900">
<span>Total Charged</span>
<span>{{ strtoupper($order->currency) }} {{ number_format((float) $order->amount_paid, 2) }}</span>
</div>
</div>
</div>
@endif
{{-- SSH Access (if active) --}}
@if ($order->isActive() && $order->server_ip)
<div class="rounded-xl border border-gray-200 bg-white">
<div class="border-b border-gray-100 px-5 py-4">
<h2 class="text-sm font-semibold text-gray-900">SSH Access</h2>
</div>
<div class="p-5">
<div class="rounded-lg bg-gray-900 p-4">
<code class="text-sm text-green-400">ssh root@{{ $order->server_ip }}</code>
</div>
<p class="mt-2 text-xs text-gray-500">Use the credentials sent to your email to connect.</p>
</div>
</div>
@endif
</div>
{{-- Sidebar --}}
<div class="space-y-6">
{{-- Quick Actions --}}
<div class="rounded-xl border border-gray-200 bg-white">
<div class="border-b border-gray-100 px-5 py-4">
<h2 class="text-sm font-semibold text-gray-900">Quick Actions</h2>
</div>
<div class="space-y-2 p-5">
@if ($order->control_panel_url && $order->isActive())
<a href="{{ $order->control_panel_url }}" target="_blank"
class="flex w-full items-center justify-center gap-2 rounded-lg bg-gray-900 px-4 py-2.5 text-sm font-medium text-white transition hover:bg-gray-800">
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"/></svg>
Open Server Manager
</a>
@endif
<a href="{{ ladill_account_url('/support-tickets/create') }}"
class="flex w-full items-center justify-center gap-2 rounded-lg border border-gray-200 bg-white px-4 py-2.5 text-sm font-medium text-gray-700 transition hover:bg-gray-50">
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z"/></svg>
Get Support
</a>
@if ($order->canBeCancelled())
<button @click="showCancelModal = true" type="button"
class="flex w-full items-center justify-center gap-2 rounded-lg border border-red-200 bg-white px-4 py-2.5 text-sm font-medium text-red-600 transition hover:bg-red-50">
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg>
Cancel Order
</button>
@endif
</div>
</div>
{{-- Status Timeline --}}
<div class="rounded-xl border border-gray-200 bg-white">
<div class="border-b border-gray-100 px-5 py-4">
<h2 class="text-sm font-semibold text-gray-900">Status</h2>
</div>
<div class="p-5">
<div class="space-y-3">
<div class="flex items-center gap-3">
<div class="flex h-6 w-6 items-center justify-center rounded-full bg-emerald-100">
<svg class="h-3 w-3 text-emerald-600" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 0 1 0 1.414l-8 8a1 1 0 0 1-1.414 0l-4-4a1 1 0 0 1 1.414-1.414L8 12.586l7.293-7.293a1 1 0 0 1 1.414 0Z" clip-rule="evenodd"/></svg>
</div>
<div>
<p class="text-sm font-medium text-gray-900">Order Placed</p>
<p class="text-xs text-gray-500">{{ $order->created_at->format('M d, Y H:i') }}</p>
</div>
</div>
<div class="flex items-center gap-3">
<div class="flex h-6 w-6 items-center justify-center rounded-full {{ $order->approved_at ? 'bg-emerald-100' : 'bg-gray-100' }}">
@if ($order->approved_at)
<svg class="h-3 w-3 text-emerald-600" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 0 1 0 1.414l-8 8a1 1 0 0 1-1.414 0l-4-4a1 1 0 0 1 1.414-1.414L8 12.586l7.293-7.293a1 1 0 0 1 1.414 0Z" clip-rule="evenodd"/></svg>
@else
<div class="h-2 w-2 rounded-full bg-gray-300"></div>
@endif
</div>
<div>
<p class="text-sm font-medium {{ $order->approved_at ? 'text-gray-900' : 'text-gray-400' }}">Approved</p>
@if ($order->approved_at)
<p class="text-xs text-gray-500">{{ $order->approved_at->format('M d, Y H:i') }}</p>
@endif
</div>
</div>
<div class="flex items-center gap-3">
<div class="flex h-6 w-6 items-center justify-center rounded-full {{ $order->provisioned_at ? 'bg-emerald-100' : 'bg-gray-100' }}">
@if ($order->provisioned_at)
<svg class="h-3 w-3 text-emerald-600" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 0 1 0 1.414l-8 8a1 1 0 0 1-1.414 0l-4-4a1 1 0 0 1 1.414-1.414L8 12.586l7.293-7.293a1 1 0 0 1 1.414 0Z" clip-rule="evenodd"/></svg>
@else
<div class="h-2 w-2 rounded-full bg-gray-300"></div>
@endif
</div>
<div>
<p class="text-sm font-medium {{ $order->provisioned_at ? 'text-gray-900' : 'text-gray-400' }}">Provisioned</p>
@if ($order->provisioned_at)
<p class="text-xs text-gray-500">{{ $order->provisioned_at->format('M d, Y H:i') }}</p>
@endif
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{-- Cancel Modal --}}
<template x-teleport="body">
<div x-show="showCancelModal" x-cloak class="fixed inset-0 z-50 overflow-y-auto sm:flex sm:items-center sm:justify-center sm:p-4" @keydown.escape.window="showCancelModal = false">
<div x-show="showCancelModal" x-transition class="fixed inset-0 bg-gray-900/50 backdrop-blur-sm hidden sm:block" @click="showCancelModal = false"></div>
<div x-show="showCancelModal" x-transition class="relative min-h-full sm:min-h-0 w-full sm:max-w-md sm:rounded-xl sm:border sm:border-gray-200 bg-white p-6 shadow-xl" @click.stop>
<button @click="showCancelModal = false" type="button" class="absolute top-3 right-3 z-10 flex h-8 w-8 items-center justify-center rounded-full text-gray-400 hover:bg-gray-100 hover:text-gray-600 sm:hidden"><svg class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12"/></svg></button>
<h3 class="text-lg font-semibold text-gray-900">Cancel Order</h3>
<p class="mt-2 text-sm text-gray-500">Are you sure you want to cancel this server order? This action cannot be undone.</p>
<form action="{{ route('servers.orders.cancel', $order) }}" method="POST" class="mt-4">
@csrf
<div class="flex items-center justify-end gap-3">
<button @click="showCancelModal = false" type="button" class="rounded-lg px-4 py-2 text-sm font-medium text-gray-500 hover:text-gray-700">Keep Order</button>
<button type="submit" class="rounded-lg bg-red-600 px-4 py-2 text-sm font-medium text-white hover:bg-red-700">Cancel Order</button>
</div>
</form>
</div>
</div>
</template>
</div>
</x-user-layout>