fix(hosting): fix site creation form + add delete to sites list
Site creation form:
- Replace old "Create from Prospect" button (called removed endpoint)
with inline prospect_id + merchant_id fields
- Schema requires at least one — form validates before submit
- Clean payload (strip nulls/empty strings before POST)
Sites list:
- Add trash icon delete button with confirmation dialog
- Calls DELETE /admin/hosting/sites/{id} (existing endpoint)
- Reloads list after successful deletion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -44,18 +44,25 @@
|
||||
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray dark:bg-gray-700 dark:text-gray-300"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Prospect Selector -->
|
||||
<!-- Prospect or Merchant (at least one required) -->
|
||||
<div class="pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-1">Create from Prospect (optional)</label>
|
||||
<div class="flex mt-1 space-x-2">
|
||||
<input type="number" x-model="prospectId" placeholder="Prospect ID" {# noqa: FE008 - prospect ID input #}
|
||||
class="flex-1 px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray dark:bg-gray-700 dark:text-gray-300">
|
||||
<button type="button" @click="createFromProspect()"
|
||||
:disabled="!prospectId || creating"
|
||||
class="inline-flex items-center px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-teal-600 border border-transparent rounded-lg hover:bg-teal-700 focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed">
|
||||
Create from Prospect
|
||||
</button>
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-1">
|
||||
Prospect ID
|
||||
</label>
|
||||
<input type="number" x-model.number="form.prospect_id" placeholder="e.g. 2" {# noqa: FE008 #}
|
||||
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray dark:bg-gray-700 dark:text-gray-300">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400 mb-1">
|
||||
Merchant ID
|
||||
</label>
|
||||
<input type="number" x-model.number="form.merchant_id" placeholder="e.g. 1" {# noqa: FE008 #}
|
||||
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:focus:shadow-outline-gray dark:bg-gray-700 dark:text-gray-300">
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-xs text-gray-400 mt-1">At least one is required. Prospect ID auto-creates a merchant from prospect data.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -66,7 +73,7 @@
|
||||
Cancel
|
||||
</a>
|
||||
<button type="button" @click="createSite()"
|
||||
:disabled="!form.business_name || creating"
|
||||
:disabled="!canCreate || creating"
|
||||
class="inline-flex items-center justify-center px-4 py-2 text-sm font-medium leading-5 text-white transition-colors duration-150 bg-teal-600 border border-transparent rounded-lg hover:bg-teal-700 focus:outline-none focus:shadow-outline-purple disabled:opacity-50 disabled:cursor-not-allowed">
|
||||
<span x-show="!creating" x-html="$icon('plus', 'w-4 h-4 mr-2')"></span>
|
||||
<span x-show="creating" x-html="$icon('spinner', 'w-4 h-4 mr-2')"></span>
|
||||
@@ -85,15 +92,34 @@ function hostingSiteNew() {
|
||||
return {
|
||||
...data(),
|
||||
currentPage: 'hosting-sites',
|
||||
form: { business_name: '', contact_name: '', contact_email: '', contact_phone: '', internal_notes: '' },
|
||||
prospectId: '',
|
||||
form: {
|
||||
business_name: '',
|
||||
prospect_id: null,
|
||||
merchant_id: null,
|
||||
contact_name: '',
|
||||
contact_email: '',
|
||||
contact_phone: '',
|
||||
internal_notes: '',
|
||||
},
|
||||
creating: false,
|
||||
errorMsg: '',
|
||||
get canCreate() {
|
||||
return this.form.business_name && (this.form.prospect_id || this.form.merchant_id);
|
||||
},
|
||||
async createSite() {
|
||||
if (!this.canCreate) {
|
||||
this.errorMsg = 'Business name and at least one of Prospect ID or Merchant ID required';
|
||||
return;
|
||||
}
|
||||
this.creating = true;
|
||||
this.errorMsg = '';
|
||||
try {
|
||||
const site = await apiClient.post('/admin/hosting/sites', this.form);
|
||||
// Clean nulls
|
||||
var payload = {};
|
||||
for (var k in this.form) {
|
||||
if (this.form[k] !== null && this.form[k] !== '') payload[k] = this.form[k];
|
||||
}
|
||||
const site = await apiClient.post('/admin/hosting/sites', payload);
|
||||
window.location.href = '/admin/hosting/sites/' + site.id;
|
||||
} catch (e) {
|
||||
this.errorMsg = e.message || 'Failed to create site';
|
||||
@@ -101,18 +127,6 @@ function hostingSiteNew() {
|
||||
this.creating = false;
|
||||
}
|
||||
},
|
||||
async createFromProspect() {
|
||||
this.creating = true;
|
||||
this.errorMsg = '';
|
||||
try {
|
||||
const site = await apiClient.post('/admin/hosting/sites/from-prospect/' + this.prospectId);
|
||||
window.location.href = '/admin/hosting/sites/' + site.id;
|
||||
} catch (e) {
|
||||
this.errorMsg = e.message || 'Failed to create from prospect';
|
||||
} finally {
|
||||
this.creating = false;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -95,6 +95,11 @@
|
||||
title="View details">
|
||||
<span x-html="$icon('eye', 'w-5 h-5')"></span>
|
||||
</a>
|
||||
<button type="button" @click="deleteSite(s)"
|
||||
class="flex items-center justify-center p-2 text-red-600 rounded-lg hover:bg-red-50 dark:text-red-400 dark:hover:bg-gray-700 focus:outline-none transition-colors"
|
||||
title="Delete">
|
||||
<span x-html="$icon('trash', 'w-5 h-5')"></span>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -144,6 +149,16 @@ function hostingSitesList() {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
async deleteSite(site) {
|
||||
if (!confirm('Delete "' + site.business_name + '"? This will also delete the associated store.')) return;
|
||||
try {
|
||||
await apiClient.delete('/admin/hosting/sites/' + site.id);
|
||||
Utils.showToast('Site deleted', 'success');
|
||||
await this.loadSites();
|
||||
} catch (e) {
|
||||
Utils.showToast('Failed: ' + e.message, 'error');
|
||||
}
|
||||
},
|
||||
get startIndex() {
|
||||
if (this.pagination.total === 0) return 0;
|
||||
return (this.pagination.page - 1) * this.pagination.per_page + 1;
|
||||
|
||||
Reference in New Issue
Block a user