Fix QR codes views to use user.qr-codes route names.
Deploy Ladill QR Plus / deploy (push) Successful in 56s
Deploy Ladill QR Plus / deploy (push) Successful in 56s
Removes missing topup route/modal and sends low-balance users to the platform wallet. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,8 +20,10 @@ use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\View\View;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
@@ -45,12 +47,22 @@ class QrCodeController extends Controller
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
$ladillWalletBalance = 0.0;
|
||||
try {
|
||||
$ladillWalletBalance = $this->platformBilling->balanceMinor($user->public_id) / 100;
|
||||
} catch (Throwable $e) {
|
||||
Log::warning('QR Plus index could not load Ladill wallet balance', [
|
||||
'user' => $user->public_id,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
|
||||
return view('qr-codes.index', [
|
||||
'wallet' => $wallet,
|
||||
'qrCodes' => $qrCodes,
|
||||
'pricePerQr' => QrWallet::pricePerQr(),
|
||||
'minTopup' => QrWallet::minTopupGhs(),
|
||||
'ladillWalletBalance' => $this->platformBilling->balanceMinor($user->public_id) / 100,
|
||||
'ladillWalletBalance' => $ladillWalletBalance,
|
||||
'topupUrl' => 'https://'.config('app.account_domain').'/wallet',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -352,6 +352,7 @@ document.addEventListener('alpine:init', () => {
|
||||
balance: Number(config.balance ?? 0),
|
||||
price: Number(config.price ?? 0),
|
||||
modalId: config.modalId ?? null,
|
||||
topupUrl: config.topupUrl ?? null,
|
||||
href: config.href ?? null,
|
||||
requiresPayment: Object.prototype.hasOwnProperty.call(config, 'requiresPayment')
|
||||
? config.requiresPayment !== false
|
||||
@@ -367,6 +368,11 @@ document.addEventListener('alpine:init', () => {
|
||||
return this.needsTopupFor(this.requiresPayment);
|
||||
},
|
||||
openTopup() {
|
||||
if (this.topupUrl) {
|
||||
window.location.href = this.topupUrl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (! this.modalId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
selected: [],
|
||||
toggle(id) { const i = this.selected.indexOf(id); i === -1 ? this.selected.push(id) : this.selected.splice(i, 1); },
|
||||
get qs() { return this.selected.map(id => 'ids[]=' + id).join('&'); },
|
||||
printSelected() { window.open(@js(route('qr-codes.badges', $qrCode)) + '?auto=1&' + this.qs, '_blank'); },
|
||||
zplSelected() { window.location = @js(route('qr-codes.badges.zpl', $qrCode)) + '?' + this.qs; }
|
||||
printSelected() { window.open(@js(route('user.qr-codes.badges', $qrCode)) + '?auto=1&' + this.qs, '_blank'); },
|
||||
zplSelected() { window.location = @js(route('user.qr-codes.badges.zpl', $qrCode)) + '?' + this.qs; }
|
||||
}">
|
||||
|
||||
{{-- Flash --}}
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
{{-- Header --}}
|
||||
<div>
|
||||
<a href="{{ route('qr-codes.show', $qrCode) }}" class="inline-flex items-center gap-1 text-sm text-slate-500 hover:text-slate-700">
|
||||
<a href="{{ route('user.qr-codes.show', $qrCode) }}" class="inline-flex items-center gap-1 text-sm text-slate-500 hover:text-slate-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>
|
||||
{{ $qrCode->label }}
|
||||
</a>
|
||||
@@ -41,7 +41,7 @@
|
||||
<p class="text-xs text-slate-500">Email & text the <span class="font-medium text-slate-600">{{ $programme->label }}</span> programme link to all confirmed attendees.</p>
|
||||
</div>
|
||||
</div>
|
||||
<form method="POST" action="{{ route('qr-codes.attendees.share-programme', $qrCode) }}"
|
||||
<form method="POST" action="{{ route('user.qr-codes.attendees.share-programme', $qrCode) }}"
|
||||
x-data="{ busy: false }"
|
||||
@submit="if (!confirm('Send the programme outline to all confirmed attendees by email and SMS?')) { $event.preventDefault(); return; } busy = true;"
|
||||
class="shrink-0">
|
||||
@@ -90,9 +90,9 @@
|
||||
class="rounded-xl bg-indigo-600 px-3.5 py-2 text-xs font-semibold text-white hover:bg-indigo-700 transition">Print selected</button>
|
||||
<button type="button" x-show="selected.length" x-cloak @click="zplSelected()"
|
||||
class="rounded-xl border border-slate-200 px-3.5 py-2 text-xs font-semibold text-slate-600 hover:bg-slate-50 transition">ZPL selected</button>
|
||||
<a href="{{ route('qr-codes.badges', $qrCode) }}?auto=1" target="_blank"
|
||||
<a href="{{ route('user.qr-codes.badges', $qrCode) }}?auto=1" target="_blank"
|
||||
class="rounded-xl bg-slate-900 px-3.5 py-2 text-xs font-semibold text-white hover:bg-slate-800 transition">Print all badges</a>
|
||||
<a href="{{ route('qr-codes.badges.zpl', $qrCode) }}"
|
||||
<a href="{{ route('user.qr-codes.badges.zpl', $qrCode) }}"
|
||||
class="rounded-xl border border-slate-200 px-3.5 py-2 text-xs font-semibold text-slate-600 hover:bg-slate-50 transition">Download ZPL</a>
|
||||
</div>
|
||||
@endunless
|
||||
@@ -144,7 +144,7 @@
|
||||
</td>
|
||||
@unless($isContribution)
|
||||
<td class="px-4 py-3 text-right">
|
||||
<form method="POST" action="{{ route('qr-codes.attendees.check-in', [$qrCode, $reg]) }}">
|
||||
<form method="POST" action="{{ route('user.qr-codes.attendees.check-in', [$qrCode, $reg]) }}">
|
||||
@csrf @method('PATCH')
|
||||
<button type="submit" class="rounded-lg border px-2.5 py-1 text-xs font-semibold transition {{ $reg->checked_in_at ? 'border-emerald-200 bg-emerald-50 text-emerald-700' : 'border-slate-200 text-slate-500 hover:bg-slate-50' }}">
|
||||
{{ $reg->checked_in_at ? '✓ In' : 'Check in' }}
|
||||
|
||||
@@ -2,20 +2,18 @@
|
||||
<x-slot name="title">Create QR Code</x-slot>
|
||||
|
||||
@php
|
||||
$modalId = 'service-topup-qr';
|
||||
$openTopup = session('open_topup_modal') === 'qr';
|
||||
$defaultStyle = \App\Support\Qr\QrStyleDefaults::merge(old('style'));
|
||||
@endphp
|
||||
|
||||
<div class="mx-auto max-w-6xl space-y-6"
|
||||
x-data="qrCustomizer({
|
||||
previewUrl: @js(route('qr-codes.style-preview')),
|
||||
previewUrl: @js(route('user.qr-codes.style-preview')),
|
||||
csrf: @js(csrf_token()),
|
||||
shortCode: 'preview',
|
||||
style: @js($defaultStyle),
|
||||
balance: @js((float) $wallet->spendableBalance()),
|
||||
price: @js((float) $pricePerQr),
|
||||
topupModalId: @js($modalId),
|
||||
topupUrl: @js($topupUrl),
|
||||
type: @js(old('type', 'url')),
|
||||
})">
|
||||
|
||||
@@ -25,7 +23,7 @@
|
||||
|
||||
{{-- Mobile page header --}}
|
||||
<div class="flex items-center gap-3 py-1 lg:hidden">
|
||||
<a href="{{ route('qr-codes.index') }}"
|
||||
<a href="{{ route('user.qr-codes.index') }}"
|
||||
class="flex h-9 w-9 items-center justify-center rounded-xl border border-slate-200 bg-white shadow-sm text-slate-500 hover:text-slate-900 transition">
|
||||
<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"/>
|
||||
@@ -36,7 +34,7 @@
|
||||
|
||||
{{-- Desktop page header --}}
|
||||
<div class="hidden lg:block">
|
||||
<a href="{{ route('qr-codes.index') }}" class="inline-flex items-center gap-1 text-sm text-slate-500 hover:text-slate-700">
|
||||
<a href="{{ route('user.qr-codes.index') }}" class="inline-flex items-center gap-1 text-sm text-slate-500 hover:text-slate-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>
|
||||
QR Codes
|
||||
</a>
|
||||
@@ -44,7 +42,7 @@
|
||||
<p class="mt-1 text-sm text-slate-500">Customize your code, then create.</p>
|
||||
</div>
|
||||
|
||||
<form x-ref="createForm" action="{{ route('qr-codes.store') }}" method="POST" enctype="multipart/form-data"
|
||||
<form x-ref="createForm" action="{{ route('user.qr-codes.store') }}" method="POST" enctype="multipart/form-data"
|
||||
class="grid grid-cols-1 gap-8 lg:grid-cols-[380px_1fr]"
|
||||
@submit="submitOrTopup($event)">
|
||||
@csrf
|
||||
@@ -77,7 +75,7 @@
|
||||
slug: @js(old('custom_short_code', '')),
|
||||
status: '',
|
||||
timer: null,
|
||||
checkUrl: @js(route('qr-codes.check-slug')),
|
||||
checkUrl: @js(route('user.qr-codes.check-slug')),
|
||||
baseUrl: @js(\App\Models\QrCode::publicBaseUrl() . '/q'),
|
||||
check() {
|
||||
clearTimeout(this.timer);
|
||||
@@ -250,18 +248,4 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<x-user.service-topup-modal
|
||||
:id="$modalId"
|
||||
title="Add QR credits"
|
||||
description="Top up your QR balance to create codes."
|
||||
:topup-action="route('qr-codes.topup')"
|
||||
:min-topup="$minTopup"
|
||||
:suggested-amount="max($minTopup, $pricePerQr)"
|
||||
:ladill-wallet-balance="$ladillWalletBalance"
|
||||
:service-balance="$wallet->spendableBalance()"
|
||||
service-balance-label="QR balance"
|
||||
:return-url="url()->current()"
|
||||
:open-on-load="$openTopup"
|
||||
/>
|
||||
</x-user-layout>
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
<x-user-layout>
|
||||
<x-slot name="title">QR Codes</x-slot>
|
||||
|
||||
@php
|
||||
$modalId = 'service-topup-qr';
|
||||
$openTopup = session('open_topup_modal') === 'qr';
|
||||
@endphp
|
||||
|
||||
<div class="space-y-6"
|
||||
x-data="balanceGate({
|
||||
balance: @js((float) $wallet->spendableBalance()),
|
||||
price: @js((float) $pricePerQr),
|
||||
modalId: @js($modalId),
|
||||
href: @js(route('qr-codes.create')),
|
||||
topupUrl: @js($topupUrl),
|
||||
href: @js(route('user.qr-codes.create')),
|
||||
})">
|
||||
@foreach(['success', 'error'] as $flash)
|
||||
@if(session($flash))
|
||||
@@ -70,7 +65,7 @@
|
||||
@else
|
||||
<div class="divide-y divide-slate-100">
|
||||
@foreach($qrCodes as $code)
|
||||
<a href="{{ route('qr-codes.show', $code) }}" class="flex items-center gap-4 px-6 py-4 transition hover:bg-slate-50">
|
||||
<a href="{{ route('user.qr-codes.show', $code) }}" class="flex items-center gap-4 px-6 py-4 transition hover:bg-slate-50">
|
||||
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg {{ $code->is_active ? 'bg-violet-100 text-violet-600' : 'bg-slate-100 text-slate-400' }}">
|
||||
<x-icons.qr-code class="h-5 w-5" />
|
||||
</div>
|
||||
@@ -88,18 +83,4 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<x-user.service-topup-modal
|
||||
:id="$modalId"
|
||||
title="Add QR credits"
|
||||
description="Top up your QR balance to create codes."
|
||||
:topup-action="route('qr-codes.topup')"
|
||||
:min-topup="$minTopup"
|
||||
:suggested-amount="max($minTopup, $pricePerQr)"
|
||||
:ladill-wallet-balance="$ladillWalletBalance"
|
||||
:service-balance="$wallet->spendableBalance()"
|
||||
service-balance-label="QR balance"
|
||||
:return-url="route('qr-codes.index')"
|
||||
:open-on-load="$openTopup"
|
||||
/>
|
||||
</x-user-layout>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
balance: config.balance ?? null,
|
||||
price: config.price ?? null,
|
||||
topupModalId: config.topupModalId ?? null,
|
||||
topupUrl: config.topupUrl ?? null,
|
||||
canonicalSyncUrl: config.canonicalSyncUrl ?? null,
|
||||
csrf: config.csrf ?? null,
|
||||
_canonicalSynced: false,
|
||||
@@ -225,28 +226,36 @@
|
||||
Object.assign(this, presets[preset] || presets.square);
|
||||
this.schedulePreview();
|
||||
},
|
||||
checkBalance(event) {
|
||||
if (this.balance === null || this.price === null || !this.topupModalId) {
|
||||
return;
|
||||
redirectTopup() {
|
||||
if (this.topupUrl) {
|
||||
window.location.href = this.topupUrl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.balance <= 0 || this.balance < this.price) {
|
||||
event?.preventDefault();
|
||||
window.dispatchEvent(new CustomEvent('open-modal', {
|
||||
detail: this.topupModalId,
|
||||
bubbles: true,
|
||||
}));
|
||||
}
|
||||
},
|
||||
submitOrTopup(event) {
|
||||
if (this.balance <= 0 || this.balance < this.price) {
|
||||
event?.preventDefault();
|
||||
if (this.topupModalId) {
|
||||
window.dispatchEvent(new CustomEvent('open-modal', {
|
||||
detail: this.topupModalId,
|
||||
bubbles: true,
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
checkBalance(event) {
|
||||
if (this.balance === null || this.price === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.balance <= 0 || this.balance < this.price) {
|
||||
event?.preventDefault();
|
||||
this.redirectTopup();
|
||||
}
|
||||
},
|
||||
submitOrTopup(event) {
|
||||
if (this.balance <= 0 || this.balance < this.price) {
|
||||
event?.preventDefault();
|
||||
this.redirectTopup();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
<p class="mb-3 text-[10px] font-semibold uppercase tracking-[0.1em] text-slate-400">Download & Share</p>
|
||||
<div class="grid grid-cols-4 gap-2">
|
||||
|
||||
<a href="{{ route('qr-codes.download', [$qrCode, 'png']) }}"
|
||||
<a href="{{ route('user.qr-codes.download', [$qrCode, 'png']) }}"
|
||||
class="group flex flex-col items-center gap-1.5 rounded-xl border border-slate-200 bg-white py-3.5 text-center transition hover:border-indigo-300 hover:bg-indigo-50">
|
||||
<svg class="h-4 w-4 text-slate-400 transition group-hover:text-indigo-500" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12M12 16.5V3"/>
|
||||
@@ -109,7 +109,7 @@
|
||||
<span class="text-xs font-semibold text-slate-600 transition group-hover:text-indigo-700">PNG</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('qr-codes.download', [$qrCode, 'svg']) }}"
|
||||
<a href="{{ route('user.qr-codes.download', [$qrCode, 'svg']) }}"
|
||||
class="group flex flex-col items-center gap-1.5 rounded-xl border border-slate-200 bg-white py-3.5 text-center transition hover:border-violet-300 hover:bg-violet-50">
|
||||
<svg class="h-4 w-4 text-slate-400 transition group-hover:text-violet-500" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21 3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5"/>
|
||||
@@ -117,7 +117,7 @@
|
||||
<span class="text-xs font-semibold text-slate-600 transition group-hover:text-violet-700">SVG</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('qr-codes.download', [$qrCode, 'pdf']) }}"
|
||||
<a href="{{ route('user.qr-codes.download', [$qrCode, 'pdf']) }}"
|
||||
class="group flex flex-col items-center gap-1.5 rounded-xl border border-slate-200 bg-white py-3.5 text-center transition hover:border-rose-300 hover:bg-rose-50">
|
||||
<svg class="h-4 w-4 text-slate-400 transition group-hover:text-rose-500" fill="none" stroke="currentColor" stroke-width="2" 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.25m2.25 0H5.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"/>
|
||||
|
||||
@@ -596,11 +596,13 @@
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<a href="{{ route('qr-codes.attendees', $qrCode) }}"
|
||||
@if (Route::has('user.qr-codes.attendees'))
|
||||
<a href="{{ route('user.qr-codes.attendees', $qrCode) }}"
|
||||
class="flex items-center justify-center gap-2 rounded-xl border border-indigo-200 bg-indigo-50 px-4 py-3 text-sm font-semibold text-indigo-700 hover:bg-indigo-100 transition">
|
||||
<svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="1.8" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 0 0 2.625.372 9.337 9.337 0 0 0 4.121-.952 4.125 4.125 0 0 0-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 0 1 8.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0 1 11.964-3.07M12 6.375a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0Zm8.25 2.25a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"/></svg>
|
||||
Manage attendees & print badges
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@elseif($qrCode->type === \App\Models\QrCode::TYPE_ITINERARY)
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
<div class="mx-auto max-w-6xl space-y-6"
|
||||
x-data="qrCustomizer({
|
||||
previewUrl: @js(route('qr-codes.style-preview')),
|
||||
previewUrl: @js(route('user.qr-codes.style-preview')),
|
||||
csrf: @js(csrf_token()),
|
||||
canonicalSyncUrl: @js(route('qr-codes.canonical-image', $qrCode)),
|
||||
canonicalSyncUrl: @js(route('user.qr-codes.canonical-image', $qrCode)),
|
||||
shortCode: @js($qrCode->short_code),
|
||||
qrData: @js($qrCode->encodedPayload()),
|
||||
initialPreview: @js($previewDataUri),
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
{{-- Mobile page header --}}
|
||||
<div class="flex items-center gap-3 py-1 lg:hidden">
|
||||
<a href="{{ route('qr-codes.index') }}"
|
||||
<a href="{{ route('user.qr-codes.index') }}"
|
||||
class="flex h-9 w-9 items-center justify-center rounded-xl border border-slate-200 bg-white shadow-sm text-slate-500 hover:text-slate-900 transition">
|
||||
<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"/>
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
{{-- Desktop page header --}}
|
||||
<div class="hidden lg:block">
|
||||
<a href="{{ route('qr-codes.index') }}" class="inline-flex items-center gap-1 text-sm text-slate-500 hover:text-slate-700">
|
||||
<a href="{{ route('user.qr-codes.index') }}" class="inline-flex items-center gap-1 text-sm text-slate-500 hover:text-slate-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>
|
||||
QR Codes
|
||||
</a>
|
||||
@@ -55,7 +55,7 @@
|
||||
</div>
|
||||
|
||||
{{-- Main 2-column layout --}}
|
||||
<form x-ref="updateForm" action="{{ route('qr-codes.update', $qrCode) }}" method="POST" enctype="multipart/form-data"
|
||||
<form x-ref="updateForm" action="{{ route('user.qr-codes.update', $qrCode) }}" method="POST" enctype="multipart/form-data"
|
||||
class="grid grid-cols-1 gap-8 lg:grid-cols-[380px_1fr]">
|
||||
@csrf
|
||||
@method('PATCH')
|
||||
@@ -193,15 +193,15 @@
|
||||
$mobileShareEnc = urlencode($mobileShareUrl);
|
||||
@endphp
|
||||
<div class="grid grid-cols-4 gap-2 px-6 pb-6">
|
||||
<a href="{{ route('qr-codes.download', [$qrCode, 'png']) }}"
|
||||
<a href="{{ route('user.qr-codes.download', [$qrCode, 'png']) }}"
|
||||
class="flex flex-col items-center gap-1 rounded-xl border border-white/20 bg-white/10 py-3 text-center text-white transition hover:bg-white/20">
|
||||
<span class="text-xs font-semibold">PNG</span>
|
||||
</a>
|
||||
<a href="{{ route('qr-codes.download', [$qrCode, 'svg']) }}"
|
||||
<a href="{{ route('user.qr-codes.download', [$qrCode, 'svg']) }}"
|
||||
class="flex flex-col items-center gap-1 rounded-xl border border-white/20 bg-white/10 py-3 text-center text-white transition hover:bg-white/20">
|
||||
<span class="text-xs font-semibold">SVG</span>
|
||||
</a>
|
||||
<a href="{{ route('qr-codes.download', [$qrCode, 'pdf']) }}"
|
||||
<a href="{{ route('user.qr-codes.download', [$qrCode, 'pdf']) }}"
|
||||
class="flex flex-col items-center gap-1 rounded-xl border border-white/20 bg-white/10 py-3 text-center text-white transition hover:bg-white/20">
|
||||
<span class="text-xs font-semibold">PDF</span>
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user