Wire Ladill domain picker and purchase modal into hosting flows.
Deploy Ladill Hosting / deploy (push) Successful in 51s
Deploy Ladill Hosting / deploy (push) Successful in 51s
Use the Domains API for owned domains across panel, account, and order forms, with an embedded iframe purchase modal instead of redirecting to domains.ladill.com. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
@props(['appLabel' => 'Ladill Hosting'])
|
||||
|
||||
<x-modal name="domain-purchase" maxWidth="2xl">
|
||||
<div class="flex flex-col" style="height: min(80vh, 720px);">
|
||||
<div class="flex shrink-0 items-center justify-between border-b border-slate-100 px-5 py-4">
|
||||
<div>
|
||||
<h2 class="text-base font-semibold text-slate-900">Register a domain</h2>
|
||||
<p class="mt-0.5 text-xs text-slate-500">Search and buy without leaving {{ $appLabel }}.</p>
|
||||
</div>
|
||||
<button type="button" data-close-modal="domain-purchase"
|
||||
class="rounded-lg p-1.5 text-slate-400 transition hover:bg-slate-100 hover:text-slate-600">
|
||||
<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>
|
||||
</div>
|
||||
<iframe id="ladill-domain-purchase-frame" title="Ladill Domains"
|
||||
src="about:blank"
|
||||
data-embed-url="{{ ladill_domains_embed_url() }}"
|
||||
class="min-h-0 w-full flex-1 border-0 bg-white"></iframe>
|
||||
</div>
|
||||
</x-modal>
|
||||
@@ -0,0 +1,140 @@
|
||||
@props([
|
||||
'ownedDomains' => [],
|
||||
'fieldName' => 'domain',
|
||||
'ownedUrl' => '',
|
||||
'variant' => 'slate',
|
||||
'showConnectionMethod' => false,
|
||||
'showDocumentRoot' => false,
|
||||
])
|
||||
|
||||
@php
|
||||
$ownedDomainHosts = collect($ownedDomains)->map(fn ($d) => (string) $d)->all();
|
||||
$oldValue = trim((string) old($fieldName, ''));
|
||||
$initialDomainSource = empty($ownedDomainHosts)
|
||||
? 'external'
|
||||
: ((string) old('is_owned_domain', '1') === '0' ? 'external' : 'ladill');
|
||||
$selectedOwnedDomain = in_array($oldValue, $ownedDomainHosts, true) ? $oldValue : '';
|
||||
$externalFallbackDomain = ! in_array($oldValue, $ownedDomainHosts, true) ? $oldValue : '';
|
||||
$isGray = $variant === 'gray';
|
||||
$inputClass = $isGray
|
||||
? 'block w-full rounded-lg border-gray-200 bg-white text-sm focus:border-gray-400 focus:ring-0'
|
||||
: 'block w-full rounded-xl border-slate-200 bg-slate-50 text-sm shadow-sm focus:border-indigo-500 focus:bg-white focus:ring-indigo-500';
|
||||
$toggleWrapClass = $isGray ? 'bg-gray-100' : 'bg-slate-100';
|
||||
$purchaseLinkClass = $isGray
|
||||
? 'font-medium text-gray-700 underline underline-offset-2 hover:text-gray-900'
|
||||
: 'font-medium text-indigo-600 underline underline-offset-2 hover:text-indigo-800';
|
||||
@endphp
|
||||
|
||||
<div>
|
||||
<div class="mb-2 flex items-center justify-between">
|
||||
<label class="text-sm font-medium {{ $isGray ? 'text-gray-700' : 'text-slate-700' }}">Domain</label>
|
||||
<div class="inline-flex items-center rounded-md {{ $toggleWrapClass }} p-0.5 text-[11px] font-medium">
|
||||
<button type="button" @click="domainSource = 'ladill'"
|
||||
:class="domainSource === 'ladill' ? 'bg-white text-slate-900 shadow-sm' : 'text-slate-500'"
|
||||
class="rounded px-2 py-1 transition">Ladill</button>
|
||||
<button type="button" @click="domainSource = 'external'"
|
||||
:class="domainSource === 'external' ? 'bg-white text-slate-900 shadow-sm' : 'text-slate-500'"
|
||||
class="rounded px-2 py-1 transition">External</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div x-show="domainSource === 'ladill'" x-cloak>
|
||||
<template x-if="ownedDomains.length">
|
||||
<div class="space-y-2">
|
||||
<select name="{{ $fieldName }}" x-model="selectedOwnedDomain" :disabled="domainSource !== 'ladill'" class="{{ $inputClass }}">
|
||||
<option value="">Choose a domain...</option>
|
||||
<template x-for="domain in ownedDomains" :key="domain">
|
||||
<option :value="domain" x-text="domain"></option>
|
||||
</template>
|
||||
</select>
|
||||
<p class="text-xs {{ $isGray ? 'text-gray-500' : 'text-slate-500' }}">
|
||||
Prefer another?
|
||||
<button type="button" @click="openPurchaseModal()" class="{{ $purchaseLinkClass }}">Get a new domain</button>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
<template x-if="!ownedDomains.length">
|
||||
<div @class([
|
||||
'rounded-xl px-4 py-3 text-center text-sm',
|
||||
'bg-gray-50 text-gray-600' => $isGray,
|
||||
'bg-slate-50 text-slate-600' => ! $isGray,
|
||||
])>
|
||||
No Ladill domains yet.
|
||||
<button type="button" @click="openPurchaseModal()" class="{{ $purchaseLinkClass }}">Register a domain</button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div x-show="domainSource === 'external'" x-cloak>
|
||||
<input type="text" name="{{ $fieldName }}" x-model="externalDomain" :disabled="domainSource !== 'external'"
|
||||
placeholder="example.com" class="{{ $inputClass }} @error($fieldName) border-rose-300 @enderror">
|
||||
<p class="mt-1.5 text-xs {{ $isGray ? 'text-gray-500' : 'text-slate-500' }}">Enter your domain without www or http (e.g., example.com)</p>
|
||||
</div>
|
||||
|
||||
@error($fieldName)
|
||||
<p class="mt-1.5 text-sm text-rose-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="is_owned_domain" :value="domainSource === 'ladill' ? '1' : '0'">
|
||||
|
||||
@if($showConnectionMethod)
|
||||
<div x-show="domainSource === 'external'" x-cloak class="mt-5">
|
||||
<label class="mb-3 block text-sm font-medium {{ $isGray ? 'text-gray-700' : 'text-slate-700' }}">Connection method</label>
|
||||
<div class="space-y-3">
|
||||
<label @class([
|
||||
'relative flex cursor-pointer rounded-lg border bg-white p-4 transition hover:bg-slate-50',
|
||||
'border-slate-200' => ! $isGray,
|
||||
'border-gray-200 hover:bg-gray-50' => $isGray,
|
||||
])>
|
||||
<input type="radio" name="onboarding_mode" value="ns_auto" x-model="onboardingMode" class="sr-only peer">
|
||||
<div class="flex flex-1 items-start gap-3">
|
||||
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-emerald-100 text-emerald-600">
|
||||
<svg class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 0 6h13.5a3 3 0 1 0 0-6m-16.5-3a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3m-19.5 0a4.5 4.5 0 0 1 .9-2.7L5.737 5.1a3.375 3.375 0 0 1 2.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 0 1 .9 2.7m0 0a3 3 0 0 1-3 3m0 3h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Zm-3 6h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Z"/></svg>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-semibold text-slate-900">Point nameservers</p>
|
||||
<p class="mt-0.5 text-xs text-slate-500">Point your domain's nameservers to Ladill. We'll manage DNS and SSL automatically.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute right-4 top-4 hidden h-5 w-5 items-center justify-center rounded-full bg-indigo-600 text-white peer-checked:flex">
|
||||
<svg class="h-3 w-3" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>
|
||||
</div>
|
||||
<div class="pointer-events-none absolute inset-0 rounded-lg border-2 border-transparent peer-checked:border-indigo-600"></div>
|
||||
</label>
|
||||
|
||||
<label @class([
|
||||
'relative flex cursor-pointer rounded-lg border bg-white p-4 transition hover:bg-slate-50',
|
||||
'border-slate-200' => ! $isGray,
|
||||
'border-gray-200 hover:bg-gray-50' => $isGray,
|
||||
])>
|
||||
<input type="radio" name="onboarding_mode" value="manual_dns" x-model="onboardingMode" class="sr-only peer">
|
||||
<div class="flex flex-1 items-start gap-3">
|
||||
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-blue-100 text-blue-600">
|
||||
<svg class="h-5 w-5" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"/></svg>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<p class="text-sm font-semibold text-slate-900">Add DNS records</p>
|
||||
<p class="mt-0.5 text-xs text-slate-500">Keep your current DNS provider and manually add A records pointing to our server.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute right-4 top-4 hidden h-5 w-5 items-center justify-center rounded-full bg-indigo-600 text-white peer-checked:flex">
|
||||
<svg class="h-3 w-3" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/></svg>
|
||||
</div>
|
||||
<div class="pointer-events-none absolute inset-0 rounded-lg border-2 border-transparent peer-checked:border-indigo-600"></div>
|
||||
</label>
|
||||
</div>
|
||||
@error('onboarding_mode')
|
||||
<p class="mt-1.5 text-sm text-rose-600">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($showDocumentRoot)
|
||||
<div class="mt-5">
|
||||
<label class="mb-1 block text-sm font-medium text-slate-700">Document root <span class="font-normal text-slate-400">(optional)</span></label>
|
||||
<input type="text" name="document_root" placeholder="public_html/example.com" value="{{ old('document_root') }}"
|
||||
class="w-full rounded-lg border-slate-200 text-sm shadow-sm focus:border-indigo-500 focus:ring-indigo-500">
|
||||
<p class="mt-1 text-xs text-slate-500">Leave empty to use default: public_html/domain.com</p>
|
||||
</div>
|
||||
@endif
|
||||
Reference in New Issue
Block a user