Files
ladill-events/resources/views/qr/account/settings.blade.php
T
isaaccladandCursor 4c87c786da
Deploy Ladill Events / deploy (push) Successful in 42s
Add Events Pro/Business and BYO ticket gateways.
Cut ticket checkouts off Ladill Pay, settle to merchant gateways at 0% platform fee, and mirror Invoice freemium pricing (GHS 49 / 149).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-15 01:26:28 +00:00

329 lines
24 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<x-user-layout>
<x-slot name="title">Settings</x-slot>
@php
$ed = $eventDefaults;
$badgeFieldLabels = old('event_defaults.badge_fields', $ed['badge_fields'] ?? ['Company', 'Role']);
@endphp
<div class="mx-auto max-w-2xl">
<h1 class="text-xl font-semibold tracking-tight text-slate-900">Settings</h1>
<p class="mt-0.5 text-sm text-slate-500">Notifications, defaults for new events, and QR preferences.</p>
@if (session('success'))
<div class="mt-4 rounded-xl border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-800">{{ session('success') }}</div>
@endif
<form method="POST" action="{{ route('account.settings.update') }}" enctype="multipart/form-data" class="mt-6 space-y-4">
@csrf
@method('PUT')
<div class="rounded-2xl border border-slate-200 bg-white p-5">
<h2 class="text-sm font-semibold text-slate-900">Notifications</h2>
<p class="mt-1 text-xs text-slate-500">Choose what we email you about your events and account.</p>
<div class="mt-4">
<label for="notify_email" class="block text-[11px] font-medium text-slate-500">Notifications email</label>
<input type="email" id="notify_email" name="notify_email"
value="{{ old('notify_email', $settings->notify_email ?? $account->email) }}"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@error('notify_email') <p class="mt-1 text-xs text-rose-600">{{ $message }}</p> @enderror
</div>
<label class="mt-4 flex items-center justify-between gap-4">
<span>
<span class="block text-sm font-medium text-slate-800">New registrations</span>
<span class="block text-xs text-slate-400">Email when someone registers or buys a ticket.</span>
</span>
<input type="checkbox" name="notify_registrations" value="1"
@checked(old('notify_registrations', $settings->notify_registrations ?? true))
class="h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500">
</label>
<label class="mt-4 flex items-center justify-between gap-4">
<span>
<span class="block text-sm font-medium text-slate-800">Payouts & settlements</span>
<span class="block text-xs text-slate-400">Email when ticket revenue is ready to withdraw.</span>
</span>
<input type="checkbox" name="notify_payouts" value="1"
@checked(old('notify_payouts', $settings->notify_payouts ?? true))
class="h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500">
</label>
<label class="mt-4 flex items-center justify-between gap-4">
<span>
<span class="block text-sm font-medium text-slate-800">Low QR balance</span>
<span class="block text-xs text-slate-400">Email when your wallet is too low to publish a new event QR.</span>
</span>
<input type="checkbox" name="low_balance_alerts" value="1"
@checked(old('low_balance_alerts', $settings->low_balance_alerts ?? true))
class="h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500">
</label>
<label class="mt-4 flex items-center justify-between gap-4">
<span>
<span class="block text-sm font-medium text-slate-800">Ladill Events updates</span>
<span class="block text-xs text-slate-400">Occasional emails about new features and improvements.</span>
</span>
<input type="checkbox" name="product_updates" value="1"
@checked(old('product_updates', $settings->product_updates ?? true))
class="h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500">
</label>
</div>
<div class="rounded-2xl border border-slate-200 bg-white p-5">
<h2 class="text-sm font-semibold text-slate-900">Company branding</h2>
<p class="mt-1 text-xs text-slate-500">Your logo appears in customer emails (registration confirmations, join links, and programme shares).</p>
@if (\App\Support\AccountBranding::hasCustomLogo($settings))
<div class="mt-4">
<img src="{{ \App\Support\AccountBranding::logoUrl($settings) }}" alt="Company logo" class="h-12 w-auto max-w-[200px] rounded-lg border border-slate-100 bg-slate-50 object-contain p-2">
</div>
<label class="mt-3 flex items-center gap-2 text-sm text-slate-600">
<input type="checkbox" name="remove_logo" value="1" class="rounded border-slate-300 text-rose-600 focus:ring-rose-500">
Remove current logo
</label>
@endif
<div class="mt-4">
<label for="logo" class="block text-[11px] font-medium text-slate-500">{{ \App\Support\AccountBranding::hasCustomLogo($settings) ? 'Replace logo' : 'Upload logo' }}</label>
<input type="file" id="logo" name="logo" accept="image/png,image/jpeg,image/webp,image/svg+xml"
class="mt-1 block w-full text-sm text-slate-600 file:mr-3 file:rounded-lg file:border-0 file:bg-indigo-50 file:px-3 file:py-2 file:text-sm file:font-semibold file:text-indigo-700 hover:file:bg-indigo-100">
@error('logo') <p class="mt-1 text-xs text-rose-600">{{ $message }}</p> @enderror
</div>
</div>
<div class="rounded-2xl border border-slate-200 bg-white p-5">
<h2 class="text-sm font-semibold text-slate-900">New event defaults</h2>
<p class="mt-1 text-xs text-slate-500">Pre-fill the create flow so every new event starts with your usual setup.</p>
<div class="mt-4 grid gap-4 sm:grid-cols-2">
<div>
<label for="default_currency" class="block text-[11px] font-medium text-slate-500">Currency</label>
<select id="default_currency" name="event_defaults[currency]"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@foreach (['GHS' => 'GHS (Ghanaian Cedi)', 'USD' => 'USD (US Dollar)', 'NGN' => 'NGN (Nigerian Naira)', 'KES' => 'KES (Kenyan Shilling)'] as $code => $label)
<option value="{{ $code }}" @selected(old('event_defaults.currency', $ed['currency']) === $code)>{{ $label }}</option>
@endforeach
</select>
</div>
<div>
<label for="default_mode" class="block text-[11px] font-medium text-slate-500">Collection type</label>
<select id="default_mode" name="event_defaults[mode]"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
<option value="ticketing" @selected(old('event_defaults.mode', $ed['mode']) === 'ticketing')>Ticketed event</option>
<option value="contributions" @selected(old('event_defaults.mode', $ed['mode']) === 'contributions')>Contributions / gifts</option>
<option value="free" @selected(old('event_defaults.mode', $ed['mode']) === 'free')>Free registration</option>
</select>
</div>
</div>
<div class="mt-4 grid gap-4 sm:grid-cols-2">
<div>
<label for="default_badge_size" class="block text-[11px] font-medium text-slate-500">Badge size</label>
<select id="default_badge_size" name="event_defaults[badge_size]"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@foreach (['4x3' => '4 × 3 in (landscape)', '4x6' => '4 × 6 in (lanyard)', 'cr80' => 'CR80 card'] as $size => $label)
<option value="{{ $size }}" @selected(old('event_defaults.badge_size', $ed['badge_size']) === $size)>{{ $label }}</option>
@endforeach
</select>
</div>
<div>
<label for="default_brand_color" class="block text-[11px] font-medium text-slate-500">Brand color</label>
<input type="color" id="default_brand_color" name="event_defaults[brand_color]"
value="{{ old('event_defaults.brand_color', $ed['brand_color']) }}"
class="mt-1 h-10 w-full cursor-pointer rounded-lg border border-slate-200 bg-white p-1">
</div>
</div>
<div class="mt-4">
<label for="default_organizer" class="block text-[11px] font-medium text-slate-500">Default organizer name</label>
<input type="text" id="default_organizer" name="event_defaults[organizer]" maxlength="120"
value="{{ old('event_defaults.organizer', $ed['organizer']) }}"
placeholder="e.g. CAPBuSS Events"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
</div>
<div class="mt-4" x-data="{ fields: @js(array_values($badgeFieldLabels)) }">
<label class="block text-[11px] font-medium text-slate-500">Default badge fields</label>
<p class="mt-0.5 text-[11px] text-slate-400">Extra attendee fields shown on badges (e.g. Company, Role).</p>
<div class="mt-2 space-y-2">
<template x-for="(field, i) in fields" :key="i">
<div class="flex items-center gap-2">
<input type="text" :name="'event_defaults[badge_fields]['+i+']'" x-model="fields[i]" maxlength="40"
class="flex-1 rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
<button type="button" x-show="fields.length > 1" @click="fields.splice(i, 1)"
class="rounded-lg border border-slate-200 px-2 py-1 text-xs text-slate-500 hover:bg-slate-50">Remove</button>
</div>
</template>
</div>
<button type="button" @click="fields.push('')"
class="mt-2 text-xs font-semibold text-indigo-600 hover:text-indigo-800">+ Add field</button>
</div>
<label class="mt-4 flex items-center justify-between gap-4 rounded-xl border border-slate-100 bg-slate-50/80 px-4 py-3">
<span>
<span class="block text-sm font-medium text-slate-800">Registration open by default</span>
<span class="block text-xs text-slate-400">New events accept sign-ups unless you turn this off.</span>
</span>
<input type="checkbox" name="event_defaults[registration_open]" value="1"
@checked(old('event_defaults.registration_open', $ed['registration_open']))
class="h-5 w-5 rounded border-slate-300 text-indigo-600 focus:ring-indigo-500">
</label>
</div>
<details class="group rounded-2xl border border-slate-200 bg-white">
<summary class="cursor-pointer list-none p-5 marker:content-none">
<div class="flex items-center justify-between gap-3">
<div>
<h2 class="text-sm font-semibold text-slate-900">QR code defaults</h2>
<p class="mt-1 text-xs text-slate-500">Style applied when you design event QR codes.</p>
</div>
<svg class="h-5 w-5 shrink-0 text-slate-400 transition group-open:rotate-180" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5"/></svg>
</div>
</summary>
<div class="space-y-4 border-t border-slate-100 px-5 pb-5 pt-4">
<div class="grid gap-4 sm:grid-cols-2">
<div>
<label for="foreground" class="block text-[11px] font-medium text-slate-500">Foreground</label>
<input type="color" id="foreground" name="default_style[foreground]"
value="{{ old('default_style.foreground', $style['foreground']) }}"
class="mt-1 h-10 w-full cursor-pointer rounded-lg border border-slate-200 bg-white p-1">
</div>
<div>
<label for="background" class="block text-[11px] font-medium text-slate-500">Background</label>
<input type="color" id="background" name="default_style[background]"
value="{{ old('default_style.background', $style['background']) }}"
class="mt-1 h-10 w-full cursor-pointer rounded-lg border border-slate-200 bg-white p-1">
</div>
</div>
<div class="grid gap-4 sm:grid-cols-2">
<div>
<label for="module_style" class="block text-[11px] font-medium text-slate-500">Module style</label>
<select id="module_style" name="default_style[module_style]"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@foreach ($moduleStyles as $key => $meta)
<option value="{{ $key }}" @selected(old('default_style.module_style', $style['module_style']) === $key)>{{ $meta['label'] }}</option>
@endforeach
</select>
</div>
<div>
<label for="error_correction" class="block text-[11px] font-medium text-slate-500">Error correction</label>
<select id="error_correction" name="default_style[error_correction]"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@foreach (['L' => 'Low', 'M' => 'Medium', 'Q' => 'Quartile', 'H' => 'High'] as $key => $label)
<option value="{{ $key }}" @selected(old('default_style.error_correction', $style['error_correction']) === $key)>{{ $label }} ({{ $key }})</option>
@endforeach
</select>
</div>
</div>
<div class="grid gap-4 sm:grid-cols-2">
<div>
<label for="finder_outer" class="block text-[11px] font-medium text-slate-500">Corner outer</label>
<select id="finder_outer" name="default_style[finder_outer]"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@foreach ($cornerOuterStyles as $key => $meta)
<option value="{{ $key }}" @selected(old('default_style.finder_outer', $style['finder_outer']) === $key)>{{ $meta['label'] }}</option>
@endforeach
</select>
</div>
<div>
<label for="finder_inner" class="block text-[11px] font-medium text-slate-500">Corner inner</label>
<select id="finder_inner" name="default_style[finder_inner]"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@foreach ($cornerInnerStyles as $key => $meta)
<option value="{{ $key }}" @selected(old('default_style.finder_inner', $style['finder_inner']) === $key)>{{ $meta['label'] }}</option>
@endforeach
</select>
</div>
</div>
<div class="grid gap-4 sm:grid-cols-2">
<div>
<label for="frame_style" class="block text-[11px] font-medium text-slate-500">Frame</label>
<select id="frame_style" name="default_style[frame_style]"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
@foreach ($frameStyles as $key => $meta)
<option value="{{ $key }}" @selected(old('default_style.frame_style', $style['frame_style']) === $key)>{{ $meta['label'] }}</option>
@endforeach
</select>
</div>
<div>
<label for="frame_color" class="block text-[11px] font-medium text-slate-500">Frame color</label>
<input type="color" id="frame_color" name="default_style[frame_color]"
value="{{ old('default_style.frame_color', $style['frame_color']) }}"
class="mt-1 h-10 w-full cursor-pointer rounded-lg border border-slate-200 bg-white p-1">
</div>
</div>
<div>
<label for="frame_text" class="block text-[11px] font-medium text-slate-500">Frame label</label>
<input type="text" id="frame_text" name="default_style[frame_text]" maxlength="100"
value="{{ old('default_style.frame_text', $style['frame_text']) }}"
placeholder="SCAN ME"
class="mt-1 w-full rounded-lg border border-slate-200 bg-slate-50 px-3 py-2 text-sm focus:border-indigo-300 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-100">
</div>
</div>
</details>
<div class="rounded-2xl border border-slate-200 bg-white p-5 space-y-4">
<div>
<h2 class="text-base font-semibold text-slate-900">Payment gateway</h2>
<p class="mt-1 text-sm text-slate-500">Connect Paystack, Flutterwave, or Hubtel. Ticket and contribution payments go 100% to you 0% Ladill platform fee.</p>
</div>
<div>
<label class="text-sm font-medium text-slate-700">Provider</label>
<select name="gateway_provider" class="mt-1 w-full rounded-lg border-slate-200">
<option value="">Select a provider</option>
<option value="paystack" @selected(old('gateway_provider', $gateway?->provider) === 'paystack')>Paystack</option>
<option value="flutterwave" @selected(old('gateway_provider', $gateway?->provider) === 'flutterwave')>Flutterwave</option>
<option value="hubtel" @selected(old('gateway_provider', $gateway?->provider) === 'hubtel')>Hubtel</option>
</select>
</div>
<div class="grid gap-4 md:grid-cols-2">
<div>
<label class="text-sm font-medium text-slate-700">Public key / Merchant account</label>
<input type="text" name="gateway_public_key" value="{{ old('gateway_public_key') }}" placeholder="{{ $gateway?->public_key ? '•••• saved — leave blank to keep' : 'pk_live_…' }}" class="mt-1 w-full rounded-lg border-slate-200">
</div>
<div>
<label class="text-sm font-medium text-slate-700">Secret / API key</label>
<input type="password" name="gateway_secret_key" value="" placeholder="{{ $gateway?->secret_key ? '•••• saved — leave blank to keep' : 'sk_live_…' }}" class="mt-1 w-full rounded-lg border-slate-200" autocomplete="new-password">
</div>
</div>
<div>
<label class="text-sm font-medium text-slate-700">Webhook secret (optional)</label>
<input type="password" name="gateway_webhook_secret" value="" placeholder="{{ $gateway?->webhook_secret ? '•••• saved — leave blank to keep' : 'Optional' }}" class="mt-1 w-full rounded-lg border-slate-200" autocomplete="new-password">
</div>
<label class="inline-flex items-center gap-2 text-sm text-slate-700">
<input type="hidden" name="gateway_is_active" value="0">
<input type="checkbox" name="gateway_is_active" value="1" @checked(old('gateway_is_active', $gateway?->is_active ?? true)) class="rounded border-slate-300 text-indigo-600 focus:ring-indigo-500">
Gateway enabled for paid tickets and contributions
</label>
@if ($gateway?->isConfigured())
<p class="rounded-lg bg-emerald-50 px-3 py-2 text-sm text-emerald-800">Gateway connected ({{ ucfirst($gateway->provider) }}).</p>
@else
<p class="rounded-lg bg-amber-50 px-3 py-2 text-sm text-amber-800">Paid checkouts stay disabled until a gateway is connected.</p>
@endif
</div>
<button type="submit" class="btn-primary">
Save settings
</button>
</form>
<div class="mt-4 rounded-2xl border border-slate-200 bg-white p-5">
<h2 class="text-sm font-semibold text-slate-900">Messaging integrations</h2>
<p class="mt-1 text-xs text-slate-500">Configure SMS and email credentials for outbound messages.</p>
<a href="{{ route('account.integrations') }}" class="mt-3 inline-block text-sm font-semibold text-indigo-600 hover:text-indigo-800">Open messaging integrations </a>
</div>
<p class="mt-6 text-xs text-slate-400">
Profile, password, and security are managed on
<a href="{{ ladill_account_url('account-settings') }}" class="font-medium text-indigo-600 hover:text-indigo-800">account.ladill.com</a>.
</p>
</div>
</x-user-layout>