fix: preserve Weeztix saved company/coupon after reload (Alpine sync)

Stop clearing DB-backed labels when API omits names; inject select options
for saved GUIDs when lists fail or omit rows; parse usage_count from JSON;
show OAuth fields hint when credentials already stored.

Made-with: Cursor
This commit is contained in:
2026-04-05 10:44:47 +02:00
parent a3158ffa34
commit 70c1d25ad4
2 changed files with 79 additions and 6 deletions

View File

@@ -788,8 +788,15 @@ document.addEventListener('alpine:init', () => {
async init() {
if (cfg.existing) {
this.codePrefix = cfg.existing.code_prefix || 'PREREG';
this.usageCount =
typeof cfg.existing.usage_count === 'number' ? cfg.existing.usage_count : 1;
const uc = cfg.existing.usage_count;
if (typeof uc === 'number' && !Number.isNaN(uc)) {
this.usageCount = uc;
} else if (uc !== null && uc !== undefined && String(uc).trim() !== '') {
const parsed = parseInt(String(uc), 10);
this.usageCount = Number.isNaN(parsed) ? 1 : parsed;
} else {
this.usageCount = 1;
}
this.companyGuid = cfg.existing.company_guid || '';
this.companyName = cfg.existing.company_name || '';
this.couponGuid = cfg.existing.coupon_guid || '';
@@ -800,6 +807,10 @@ document.addEventListener('alpine:init', () => {
if (this.companyGuid) {
await this.loadCouponsForGuid(this.companyGuid);
}
} else if (cfg.existing && (cfg.existing.company_guid || cfg.existing.coupon_guid)) {
// Show saved choices even when not connected (e.g. expired refresh); lists are from DB only.
this.ensureSelectedCompanyInList();
this.ensureSelectedCouponInList();
}
},
@@ -819,13 +830,50 @@ document.addEventListener('alpine:init', () => {
},
syncCompanyNameFromSelection() {
if (!this.companyGuid) {
this.companyName = '';
return;
}
const c = this.companies.find((x) => x.guid === this.companyGuid);
this.companyName = c && c.name ? c.name : '';
if (c && typeof c.name === 'string' && c.name.trim() !== '') {
this.companyName = c.name.trim();
}
// If API row has no name or list is still loading, keep companyName from server (DB).
},
syncCouponName() {
if (!this.couponGuid) {
this.couponName = '';
return;
}
const c = this.coupons.find((x) => x.guid === this.couponGuid);
this.couponName = c ? c.name : '';
if (c && typeof c.name === 'string' && c.name.trim() !== '') {
this.couponName = c.name.trim();
}
},
ensureSelectedCompanyInList() {
const guid = this.companyGuid;
if (!guid || this.companies.some((x) => x.guid === guid)) {
return;
}
const label =
typeof this.companyName === 'string' && this.companyName.trim() !== ''
? this.companyName.trim()
: guid;
this.companies = [{ guid, name: label }, ...this.companies];
},
ensureSelectedCouponInList() {
const guid = this.couponGuid;
if (!guid || this.coupons.some((x) => x.guid === guid)) {
return;
}
const label =
typeof this.couponName === 'string' && this.couponName.trim() !== ''
? this.couponName.trim()
: guid;
this.coupons = [{ guid, name: label }, ...this.coupons];
},
async loadCompanies() {
@@ -833,9 +881,11 @@ document.addEventListener('alpine:init', () => {
const { res, data } = await this.postJson(this.companiesUrl, { page_id: this.pageId });
if (!res.ok) {
this.errorMessage = data.message || this.strings.genericError;
this.ensureSelectedCompanyInList();
return;
}
this.companies = Array.isArray(data.companies) ? data.companies : [];
this.ensureSelectedCompanyInList();
this.syncCompanyNameFromSelection();
},
@@ -858,11 +908,26 @@ document.addEventListener('alpine:init', () => {
});
if (!res.ok) {
this.errorMessage = data.message || this.strings.loadCouponsError;
this.ensureSelectedCouponInList();
return;
}
this.coupons = Array.isArray(data.coupons) ? data.coupons : [];
this.ensureSelectedCouponInList();
this.syncCouponName();
},
/** Prefer API/display name; avoid showing raw GUID when a label exists. */
companyLabel(c) {
if (!c || typeof c.guid !== 'string') {
return '';
}
const n = c.name;
if (typeof n === 'string' && n.trim() !== '') {
return n.trim();
}
return c.guid;
},
}));
});

View File

@@ -62,9 +62,12 @@
<p class="font-medium">{{ __('Verbonden met Weeztix') }}</p>
@if ($wz->token_expires_at)
<p class="mt-1 text-emerald-800">
{{ __('Toegangstoken verloopt om:') }}
{{ __('Huidig toegangstoken tot:') }}
<span class="font-mono text-xs">{{ $wz->token_expires_at->timezone(config('app.timezone'))->format('Y-m-d H:i') }}</span>
</p>
<p class="mt-2 text-emerald-800/90">
{{ __('Het toegangstoken wordt automatisch vernieuwd bij API-gebruik (o.a. kortingscodes), zolang de refresh-token geldig is. Je hoeft niet opnieuw te verbinden.') }}
</p>
@endif
</div>
@elseif ($wz !== null && ! $wz->is_connected)
@@ -127,6 +130,11 @@
@if ($wz === null) required @endif
>
</div>
@if ($wz !== null)
<p class="text-xs text-slate-500">
{{ __('Client ID en secret zijn opgeslagen maar worden niet opnieuw getoond. Laat de velden leeg om ze te behouden; vul ze alleen in als je ze wilt wijzigen.') }}
</p>
@endif
<button type="submit" class="rounded-lg bg-slate-800 px-4 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-slate-700">
{{ __('Gegevens opslaan') }}
</button>
@@ -164,7 +172,7 @@
>
<option value="">{{ __('Selecteer een bedrijf…') }}</option>
<template x-for="c in companies" :key="c.guid">
<option :value="c.guid" x-text="(c.name || c.guid)"></option>
<option :value="c.guid" x-text="companyLabel(c)"></option>
</template>
</select>
<input type="hidden" name="company_name" :value="companyName">