Files
timebank-cc-public/resources/views/livewire/mailings/partials/create-edit-form.blade.php
T

585 lines
37 KiB
PHP

<div class="space-y-6">
<!-- Basic Information -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<x-jetstream.label for="title" value="{{ __('Mailing title') }}" />
<x-input id="title" type="text" class="mt-1 block w-full" wire:model.defer="title" />
<x-jetstream.input-error for="title" class="mt-1" />
</div>
<div>
<div class="flex items-center space-x-2">
<x-jetstream.label for="type" value="{{ __('Mailing type') }}" />
<svg wire:loading.class.remove="hidden" wire:target="type,filterByProfileType,selectedProfileTypes,filterByLocation,fallbackLocale,selectedCountryIds,selectedDivisionIds,selectedCityIds,selectedDistrictIds" class="hidden animate-spin h-3.5 w-3.5 text-theme-brand flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>
</div>
<x-select id="type" class="mt-1 w-full" wire:model.live="type">
<x-select.option label="{{ __('Select mailing type...') }}" value="" />
<x-select.option label="{{ __('Local Newsletter') }}" value="local_newsletter" />
<x-select.option label="{{ __('General Newsletter') }}" value="general_newsletter" />
<x-select.option label="{{ __('General Newsletter only subscription') }}" value="general_newsletter_only" />
<x-select.option label="{{ __('System Message') }}" value="system_message" />
</x-select>
<p class="mt-1 text-sm text-gray-500">
@if($type === 'local_newsletter')
{{ __('Sent to users based on their location preferences') }}
@elseif($type === 'general_newsletter')
{{ __('Sent to all subscribed users and organizations') }}
@elseif($type === 'general_newsletter_only')
{{ __('Sent to profiles subscribed to the General Newsletter but not to the Local Newsletter') }}
@elseif($type === 'system_message')
{{ __('System announcements and important notices') }}
@else
{{ __('Please select a mailing type to continue') }}
@endif
</p>
<x-jetstream.input-error for="type" class="mt-1" />
</div>
</div>
<!-- Content Blocks -->
<div>
<div class="flex items-center justify-between mb-3">
<x-jetstream.label value="{{ __('Mailing content') }}" />
<x-jetstream.secondary-button wire:click="openPostSelector" class="text-sm">
<x-icon name="plus" class="w-4 h-4 mr-1" />
{{ __('Add Posts') }}
</x-jetstream.secondary-button>
</div>
@if(empty($selectedPosts))
<div class="border-2 border-dashed border-gray-300 rounded-lg p-8 text-center">
<x-icon name="document-text" class="w-12 h-12 mx-auto text-gray-400 mb-4" />
<p class="text-gray-500">{{ __('No posts selected yet') }}</p>
</div>
@else
<div class="space-y-3">
@foreach($selectedPosts as $index => $post)
<div class="flex items-center justify-between p-4 border border-gray-200 rounded-lg bg-gray-50">
<div class="flex-1">
<div class="flex items-center space-x-3">
<span class="flex-shrink-0 w-6 h-6 bg-theme-brand text-white rounded-full text-xs flex items-center justify-center">
{{ $post['order'] }}
</span>
<div>
<h4 class="font-medium text-gray-900">{{ $post['title'] }}</h4>
<p class="text-sm text-gray-500">Post ID: {{ $post['post_id'] }}</p>
@if (in_array($post['post_id'], $limitedPollPostIds ?? []))
<p class="mt-1 text-sm text-amber-700">{{ __('This poll is only for some members. Recipients outside its audience will see it in the mailing but cannot take part.') }}</p>
@endif
</div>
</div>
</div>
<div class="flex items-center space-x-2">
<!-- Move Up -->
@if($index > 0)
<button wire:click="movePostUp({{ $index }})"
class="p-1 text-gray-400 hover:text-gray-600">
<x-icon name="chevron-up" class="w-4 h-4" />
</button>
@endif
<!-- Move Down -->
@if($index < count($selectedPosts) - 1)
<button wire:click="movePostDown({{ $index }})"
class="p-1 text-gray-400 hover:text-gray-600">
<x-icon name="chevron-down" class="w-4 h-4" />
</button>
@endif
<!-- Remove -->
<button wire:click="removePost({{ $index }})"
class="p-1 text-red-400 hover:text-red-600">
<x-icon name="trash" class="w-4 h-4" />
</button>
</div>
</div>
@endforeach
</div>
@endif
<x-jetstream.input-error for="selectedPosts" class="mt-2" />
</div>
<!-- Subject (Multilingual) — shown only when posts are selected -->
@if(!empty($selectedPosts))
<div>
<x-jetstream.label value="{{ __('Email Subject') }}" />
<p class="mt-1 text-sm text-gray-500 mb-3">{{ __('Enter subject lines for each language based on your selected posts') }}</p>
<div class="space-y-3">
@foreach($availableLocales as $locale)
@php $isRequired = in_array($locale, $requiredLocales); @endphp
<div class="border rounded-lg p-3 {{ $isRequired ? 'border-gray-200' : 'border-dashed border-gray-200' }}">
<div class="flex items-center space-x-2 mb-2">
<span class="text-sm font-medium text-gray-700">
{{ strtoupper($locale) }}
</span>
<span class="text-xs text-gray-500">
({{ $locale === 'en' ? 'English' :
($locale === 'nl' ? 'Nederlands' :
($locale === 'de' ? 'Deutsch' :
($locale === 'es' ? 'Español' :
($locale === 'fr' ? 'Français' : $locale)))) }})
</span>
@if($locale === timebank_config('base_language', 'en'))
<span class="inline-flex px-2 py-0.5 text-xs font-medium rounded-full bg-theme-surface text-theme-primary">
{{ __('Primary') }}
</span>
@endif
@if($isRequired)
<span class="inline-flex px-2 py-0.5 text-xs font-medium rounded-full bg-blue-100 text-blue-700">
{{ __('Required') }}
</span>
@else
<span class="inline-flex px-2 py-0.5 text-xs font-medium rounded-full bg-gray-100 text-gray-500">
{{ __('Optional') }}
</span>
@endif
</div>
<x-input
type="text"
class="w-full"
placeholder="{{ __('Subject line in :language', ['language' => strtoupper($locale)]) }}"
wire:model.defer="subjects.{{ $locale }}" />
</div>
@endforeach
</div>
</div>
@endif
<!-- Scheduling (requires send mailings permission) -->
<div>
<div class="flex items-center space-x-2 mb-3">
<x-jetstream.label value="{{ __('Scheduling') }}" class="{{ !Gate::allows('send mailings') ? 'opacity-50' : '' }}" />
</div>
<div class="space-y-3">
<div class="md:w-1/2 {{ !Gate::allows('send mailings') ? 'opacity-50 pointer-events-none' : '' }}"
x-data
x-on:flatpickr-change.window="$wire.set('scheduledAt', $event.detail.value)"
x-on:flatpickr-set-date.window="
const fp = document.querySelector('[wire\\:key=\'flatpickr-scheduled-at\'] .flatpickr-input')?._flatpickr;
if (fp) { fp.setDate($event.detail.value || null, false); }
">
<div wire:ignore wire:key="flatpickr-scheduled-at">
<x-flatpickr
showTime
dateFormat="Y-m-d"
timeFormat="H:i"
altFormat="d-m-Y @ H:i"
altInput
placeholder="{{ Gate::allows('send mailings') ? __('Select a date and time') : __('No permission to schedule mailings') }}"
onClose="(selectedDates, dateStr) => window.dispatchEvent(new CustomEvent('flatpickr-change', { detail: { value: dateStr || null } }))"
class="mt-1 block w-full border-gray-300 rounded-md shadow-sm"
/>
</div>
<x-jetstream.input-error for="scheduledAt" class="mt-2" />
</div>
</div>
</div>
<!-- Profile Type Filtering -->
<div>
<div class="flex items-center space-x-2 mb-3">
<x-jetstream.label value="{{ __('Profile Type Filtering') }}" />
<svg wire:loading.class.remove="hidden" wire:target="type,filterByProfileType,selectedProfileTypes,filterByLocation,fallbackLocale,selectedCountryIds,selectedDivisionIds,selectedCityIds,selectedDistrictIds" class="hidden animate-spin h-3.5 w-3.5 text-theme-brand flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>
</div>
<div class="space-y-4">
<!-- Filter by Profile Type Toggle -->
<div class="flex items-center space-x-3">
<x-checkbox wire:model.live="filterByProfileType" />
<label class="text-sm font-medium text-gray-700">
{{ __('Filter recipients by profile type') }}
</label>
</div>
@if($filterByProfileType)
<div class="border border-gray-200 rounded-lg p-4 bg-gray-50">
<p class="text-sm text-gray-600 mb-4">
{{ __('Select which profile types should receive this mailing. You can select multiple types.') }}
</p>
<!-- Profile Type Selection -->
<div class="space-y-3">
<x-jetstream.label value="{{ __('Profile Types') }}" class="font-medium" />
<select multiple
class="block w-full border border-gray-300 rounded-md shadow-sm p-2 h-32 focus:ring-blue-500 focus:border-blue-500"
wire:model.live="selectedProfileTypes"
title="{{ __('Hold Ctrl/Cmd to select multiple profile types') }}">
<option value="User">
{{ __('Users') }} ({{ __('Individual profiles') }})
</option>
<option value="Organization">
{{ __('Organizations') }}
</option>
<option value="Bank">
{{ __('Banks') }}
</option>
<option value="Admin">
{{ __('Admins') }}
</option>
</select>
@if(count($selectedProfileTypes) > 0)
<div class="flex items-center justify-between">
<div class="flex flex-wrap gap-2">
@foreach($selectedProfileTypes as $profileType)
<span class="inline-flex px-2 py-1 text-xs font-medium rounded-full bg-theme-surface text-theme-primary">
@switch($profileType)
@case('User')
{{ __('Users') }}
@break
@case('Organization')
{{ __('Organizations') }}
@break
@case('Bank')
{{ __('Banks') }}
@break
@case('Admin')
{{ __('Admins') }}
@break
@endswitch
</span>
@endforeach
</div>
<button type="button"
wire:click="clearProfileTypes"
class="text-xs text-gray-500 hover:text-gray-700">
{{ __('Clear all') }}
</button>
</div>
@endif
<p class="text-xs text-gray-500">
{{ __('Tip: Hold Ctrl (Windows/Linux) or Cmd (Mac) while clicking to select multiple profile types') }}
</p>
</div>
@if(count($selectedProfileTypes) > 0)
<div class="mt-3 p-3 bg-theme-surface rounded-lg">
<p class="text-sm font-medium text-theme-primary">
{{ __('Filtering by :count profile type(s)', ['count' => count($selectedProfileTypes)]) }}
</p>
</div>
@endif
</div>
@endif
</div>
</div>
<!-- Contact Filtering -->
<div>
<div class="flex items-center space-x-2 mb-3">
<x-jetstream.label value="{{ __('Contact Filtering') }}" />
<svg wire:loading.class.remove="hidden" wire:target="filterByContacts,selectedContactProfiles" class="hidden animate-spin h-3.5 w-3.5 text-theme-brand flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>
</div>
<div class="space-y-4">
<div class="flex items-center space-x-3">
<x-checkbox wire:model.live="filterByContacts" />
<label class="text-sm font-medium text-gray-700">
{{ __('Filter by contacts of...') }}
</label>
</div>
@if($filterByContacts)
<div class="border border-gray-200 rounded-lg p-4 bg-gray-50">
<p class="text-sm text-gray-600 mb-4">
{{ __('Only send to profiles that have transactions with the selected profile(s). The selected contacts will also be included.') }}
</p>
<div wire:ignore>
<livewire:profile.select-multiple-profiles
wire:key="contact-profiles-selector-{{ $editingMailing->id ?? 'new' }}"
:label="__('Select profiles')"
:typesAvailable="[\App\Models\User::class, \App\Models\Organization::class, \App\Models\Bank::class]"
eventName="selectedProfiles"
/>
</div>
@if(count($selectedContactProfiles) > 0)
<div class="mt-3 space-y-2 max-w-md">
@foreach($selectedContactProfiles as $index => $contactProfile)
<div class="flex items-center justify-between rounded-md border border-theme-border bg-white px-2 py-2">
<div class="flex items-center">
<img src="{{ $contactProfile['profile_photo_path'] }}" class="w-8 rounded-full profile-photo">
<div class="ml-2 leading-tight">
<div class="text-sm font-semibold text-theme-primary">{{ $contactProfile['name'] }}</div>
@php
$contactMeta = implode(' · ', array_filter([$contactProfile['description'] ?? '', $contactProfile['location'] ?? '']));
@endphp
@if($contactMeta)
<div class="text-xs text-theme-secondary">{{ $contactMeta }}</div>
@endif
</div>
</div>
<button type="button"
class="ml-3 text-theme-secondary hover:text-red-600 flex-shrink-0"
wire:click="removeContactProfile({{ $index }})">
<x-icon mini name="x-circle" />
</button>
</div>
@endforeach
</div>
@endif
</div>
@endif
</div>
</div>
<!-- Location Filtering -->
@if($type === 'local_newsletter')
<div>
<div class="flex items-center space-x-2 mb-3">
<x-jetstream.label value="{{ __('Location Filtering') }}" />
<svg wire:loading.class.remove="hidden" wire:target="type,filterByProfileType,selectedProfileTypes,filterByLocation,fallbackLocale,selectedCountryIds,selectedDivisionIds,selectedCityIds,selectedDistrictIds" class="hidden animate-spin h-3.5 w-3.5 text-theme-brand flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>
</div>
<div class="space-y-4">
<!-- Filter by Location Toggle -->
<div class="flex items-center space-x-3">
<x-checkbox wire:model.live="filterByLocation" />
<label class="text-sm font-medium text-gray-700">
{{ __('Filter recipients by location') }}
</label>
</div>
@if($filterByLocation)
<div class="border border-gray-200 rounded-lg p-4 bg-gray-50">
<p class="text-sm text-gray-600 mb-4">
{{ __('Select a location to filter recipients. Only profiles with their primary location in the selected area will receive this mailing.') }}
</p>
<!-- Location Filter Component -->
<div wire:ignore>
<livewire:mailings.location-filter
wire:key="mailing-location-filter-{{ $editingMailing->id ?? 'new' }}"
/>
</div>
@if(count($selectedCountryIds) > 0 || count($selectedDivisionIds) > 0 || count($selectedCityIds) > 0 || count($selectedDistrictIds) > 0)
@php
$locationFilteredCount = collect($this->getCurrentRecipientCountsByLocale())->sum('count');
@endphp
<div class="mt-3 p-3 bg-theme-surface rounded-lg">
<p class="text-sm font-medium text-theme-primary">
{{ __('Estimated recipients with location filter: :count', ['count' => number_format($locationFilteredCount)]) }}
</p>
</div>
@endif
</div>
@endif
</div>
</div>
@endif
<!-- Fallback Locale -->
<div>
<div class="flex items-center space-x-2 mb-3">
<x-jetstream.label value="{{ __('Fallback language for missing translations') }}" />
<svg wire:loading.class.remove="hidden" wire:target="type,filterByProfileType,selectedProfileTypes,filterByLocation,fallbackLocale,selectedCountryIds,selectedDivisionIds,selectedCityIds,selectedDistrictIds" class="hidden animate-spin h-3.5 w-3.5 text-theme-brand flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>
</div>
<div class="md:w-1/2">
@if(empty($fallbackEligibleLocales))
<p class="text-sm text-gray-400 italic">{{ __('Select posts first to see available fallback languages.') }}</p>
@else
<x-select id="fallbackLocale" class="w-full" wire:model.live="fallbackLocale" placeholder="{{ __('Select an available language') }}">
@foreach($fallbackEligibleLocales as $locale)
@php $localeInfo = config('laravellocalization.supportedLocales.' . $locale); @endphp
<x-select.option
label="{{ strtoupper($locale) }}{{ $localeInfo ? ' — ' . $localeInfo['native'] : '' }}"
value="{{ $locale }}" />
@endforeach
</x-select>
@endif
</div>
</div>
<!-- Recipient Preview -->
<div class="bg-theme-surface border border-theme-border rounded-lg p-4" wire:key="recipient-preview-{{ $type ?: 'no-type' }}">
<h4 class="font-medium text-theme-primary mb-2">{{ __('Estimated Recipients') }}</h4>
@if($type)
<p class="text-sm text-theme-secondary">
{{ __('messages.mailings.recipients_info.' . $type) }}
@if($filterByLocation && (count($selectedCountryIds) > 0 || count($selectedDivisionIds) > 0 || count($selectedCityIds) > 0 || count($selectedDistrictIds) > 0))
<br><strong>{{ __('messages.mailings.recipients_info.location_filtering_active') }}</strong>
@endif
</p>
@else
<p class="p-3">
<strong>{{ __('messages.mailings.recipients_info.no_type_selected') }}</strong>
</p>
@endif
<!-- Real-time recipient count -->
@if($type)
@php
$currentRecipientCount = collect($this->getCurrentRecipientCountsByLocale())->where('has_content', true)->sum('count');
@endphp
@if($currentRecipientCount > 0)
<div class="mt-3 p-3 bg-theme-surface rounded-lg border border-theme-border">
<p class="text-sm font-medium text-theme-primary flex items-center space-x-2">
<span>{{ __('Current estimated recipients: :count', ['count' => number_format($currentRecipientCount)]) }}</span>
<svg wire:loading.class.remove="hidden" wire:target="type,filterByProfileType,selectedProfileTypes,filterByLocation,fallbackLocale,selectedCountryIds,selectedDivisionIds,selectedCityIds,selectedDistrictIds" class="hidden animate-spin h-3.5 w-3.5 text-theme-brand flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>
</p>
</div>
@endif
@else
<div class="mt-3 p-3 bg-theme-surface rounded-lg border border-theme-border">
<p class="text-sm font-medium text-theme-secondary flex items-center space-x-2">
<span>{{ __('Current estimated recipients: 0') }}</span>
<svg wire:loading.class.remove="hidden" wire:target="type,filterByProfileType,selectedProfileTypes,filterByLocation,fallbackLocale,selectedCountryIds,selectedDivisionIds,selectedCityIds,selectedDistrictIds" class="hidden animate-spin h-3.5 w-3.5 text-theme-brand flex-shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path></svg>
</p>
</div>
@endif
@if($type)
<div class="mt-3 p-3 bg-theme-surface rounded-lg border border-theme-border">
<p class="text-sm font-medium text-theme-primary mb-3">
{{ __('Recipients by Language & Content') }}
</p>
@php
$rowsByLocaleLocation = $this->getCurrentRecipientCountsByLocaleAndLocation();
@endphp
@if(count($rowsByLocaleLocation) > 0)
<table class="w-full text-xs" style="border-collapse: collapse;">
<thead>
<tr class="text-theme-secondary font-medium">
<th style="text-align: left; padding: 0 8px 4px 0; font-weight: 500;">{{ __('Language') }}</th>
<th style="text-align: left; padding: 0 8px 4px 8px; font-weight: 500;">{{ __('Posts') }}</th>
<th style="text-align: left; padding: 0 8px 4px 8px; font-weight: 500; white-space: nowrap;">{{ __('Location') }}</th>
<th style="text-align: right; padding: 0 0.5rem 4px 8px; font-weight: 500;">{{ __('Recipients') }}</th>
</tr>
</thead>
<tbody>
@php
$prevLocale = null;
$fallbackLanguageName = \App\Models\Language::where('lang_code', $fallbackLocale)->value('name') ?? strtoupper($fallbackLocale);
@endphp
@foreach($rowsByLocaleLocation as $row)
@php
$isFirstForLocale = $row['locale'] !== $prevLocale;
$prevLocale = $row['locale'];
$language = $isFirstForLocale ? \App\Models\Language::where('lang_code', $row['locale'])->first() : null;
$flag = $language ? $language->flag : '🏳️';
$languageName = $language ? $language->name : strtoupper($row['locale']);
$nativePosts = $row['content_blocks'] - ($row['fallback_posts'] ?? 0);
$fallbackPosts = $row['fallback_posts'] ?? 0;
$missingPosts = $row['missing_posts'] ?? 0;
@endphp
<tr>
{{-- Col 1: Language — only on first row for this locale --}}
<td style="padding: 2px 8px 2px 0; white-space: nowrap;">
@if($isFirstForLocale)
<span style="display: inline-flex; align-items: center; gap: 6px;">
<span>{{ $flag }}</span>
<span class="font-medium text-theme-primary">{{ $languageName }}</span>
</span>
@endif
</td>
{{-- Col 2: Posts — only on first row for this locale --}}
<td style="padding: 2px 8px;">
@if($isFirstForLocale)
<span style="display: inline-flex; align-items: center; gap: 4px; flex-wrap: nowrap;">
@if($nativePosts > 0)
<span class="font-medium rounded bg-green-100 text-green-800" style="padding: 2px 6px; white-space: nowrap;">
{{ $nativePosts }} {{ __('native') }}
</span>
@endif
@if($fallbackPosts > 0)
<span class="font-medium rounded bg-amber-100 text-amber-800" style="padding: 2px 6px; white-space: nowrap;">
{{ $fallbackPosts }} {{ __('fallback in') }} {{ $fallbackLanguageName }}
</span>
@endif
@if($missingPosts > 0)
<span class="font-medium rounded bg-theme-danger-light text-theme-danger-dark" style="padding: 2px 6px; white-space: nowrap;">
{{ $missingPosts }} {{ __('skipped') }}
</span>
@endif
@if($nativePosts === 0 && $fallbackPosts === 0)
<span class="font-medium rounded bg-theme-danger-light text-theme-danger-dark" style="padding: 2px 6px; white-space: nowrap;">
{{ __('No content') }}
</span>
@endif
</span>
@endif
</td>
{{-- Col 3: Location --}}
<td class="text-theme-secondary" style="padding: 2px 8px; white-space: nowrap;">
{{ $row['location'] ?: __('Unknown') }}
</td>
{{-- Col 4: Recipients --}}
<td class="text-theme-secondary" style="padding: 2px 0.5rem 2px 8px; text-align: right;">
{{ number_format($row['count']) }}
</td>
</tr>
@endforeach
</tbody>
</table>
@php
$totalRecipients = collect($rowsByLocaleLocation)->sum('count');
$skippedRecipients = collect($rowsByLocaleLocation)->where('has_content', false)->sum('count');
$incompleteRecipients = collect($rowsByLocaleLocation)->where('has_content', true)->where('all_posts', false)->sum('count');
$suppressedCount = $this->getCurrentSuppressedCount();
@endphp
<div class="mt-3 pt-2 border-t border-theme-border">
<div class="flex justify-between text-xs" style="padding-right: 0.5rem;">
<span class="font-medium text-theme-primary">{{ __('Total recipients:') }}</span>
<span class="text-theme-secondary">{{ number_format($totalRecipients) }}</span>
</div>
@if($suppressedCount > 0)
<div class="flex justify-between text-xs mt-1" style="padding-right: 0.5rem;">
<span class="text-theme-secondary">{{ __('Skipped (hard bounce):') }}</span>
<span class="font-medium text-gray-700">{{ number_format($suppressedCount) }}</span>
</div>
@endif
{{-- Recipients skipped entirely (zero posts) --}}
@if($skippedRecipients > 0)
@if($fallbackLocale)
<p class="text-xs text-theme-secondary mt-2">
{{ __('Some recipients will not receive the mailing because no content exists in their language or the fallback language.') }}
</p>
@else
<div class="mt-2 p-2 bg-red-50 border border-red-200 rounded">
<p class="text-xs font-semibold text-red-700">
{{ __(':count recipient(s) will be skipped — no content in their language.', ['count' => number_format($skippedRecipients)]) }}
</p>
<p class="text-xs text-red-600 mt-1">
{{ __('Set a fallback language above to include them.') }}
</p>
</div>
@endif
@endif
{{-- Recipients who get the mailing but miss some posts --}}
@if($incompleteRecipients > 0 && !$fallbackLocale)
<div class="mt-2 p-2 bg-amber-50 border border-amber-200 rounded">
<p class="text-xs font-semibold text-amber-700">
{{ __(':count recipient(s) will not receive all posts — some are missing a translation in their language.', ['count' => number_format($incompleteRecipients)]) }}
</p>
<p class="text-xs text-amber-600 mt-1">
{{ __('Set a fallback language above to include the missing posts.') }}
</p>
</div>
@endif
</div>
@else
<p class="text-xs text-theme-secondary">{{ __('No recipients found for this mailing type.') }}</p>
@endif
</div>
@endif
</div>
<!-- Validation errors summary -->
<x-errors />
</div>