Initial commit

This commit is contained in:
Ronald Huynen
2026-03-23 21:37:59 +01:00
commit 2547717edb
2193 changed files with 972171 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
<x-app-layout>
<x-slot name="header">
{{ __('Users overview') }}
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
<div class="p-6 sm:px-20 bg-white border-b border-gray-200">
<div class="mt-8 text-2xl">
{{ __('Users overview title') }}
</div>
@can('manage users')
<div class="mt-6 text-gray-500">
{{ __('Users overview intro here. How to search, filter etc.') }}
</div>
<div >
<livewire:user-datatables searchable="name, email, id" exportable />
</div>
@endcan
</div>
</div>
</div>
@livewireScripts
</x-app-layout>

View File

@@ -0,0 +1,169 @@
<div>
<!-- Generate API Token -->
<x-jetstream.form-section submit="createApiToken">
<x-slot name="title">
{{ __('Create API Token') }}
</x-slot>
<x-slot name="description">
{{ __('API tokens allow third-party services to authenticate with our application on your behalf.') }}
</x-slot>
<x-slot name="form">
<!-- Token Name -->
<div class="col-span-6 sm:col-span-4">
<x-jetstream.label for="name" value="{{ __('Token Name') }}" />
<x-jetstream.input id="name" type="text" class="mt-1 block w-full" wire:model="createApiTokenForm.name" autofocus />
<x-jetstream.input-error for="name" class="mt-2" />
</div>
<!-- Token Permissions -->
@if (Laravel\Jetstream\Jetstream::hasPermissions())
<div class="col-span-6">
<x-jetstream.label for="permissions" value="{{ __('Permissions') }}" />
<div class="mt-2 grid grid-cols-1 md:grid-cols-2 gap-4">
@foreach (Laravel\Jetstream\Jetstream::$permissions as $permission)
<label class="flex items-center">
<x-jetstream.checkbox wire:model="createApiTokenForm.permissions" :value="$permission"/>
<span class="ml-2 text-sm text-theme-primary">{{ $permission }}</span>
</label>
@endforeach
</div>
</div>
@endif
</x-slot>
<x-slot name="actions">
<x-jetstream.action-message class="mr-3" on="created">
{{ __('Created.') }}
</x-jetstream.action-message>
<x-jetstream.button>
{{ __('Create') }}
</x-jetstream.button>
</x-slot>
</x-jetstream.form-section>
@if ($this->user->tokens->isNotEmpty())
<x-jetstream.section-border />
<!-- Manage API Tokens -->
<div class="mt-10 sm:mt-0">
<x-jetstream.action-section>
<x-slot name="title">
{{ __('Manage API Tokens') }}
</x-slot>
<x-slot name="description">
{{ __('You may delete any of your existing tokens if they are no longer needed.') }}
</x-slot>
<!-- API Token List -->
<x-slot name="content">
<div class="space-y-6">
@foreach ($this->user->tokens->sortBy('name') as $token)
<div class="flex items-center justify-between">
<div>
{{ $token->name }}
</div>
<div class="flex items-center">
@if ($token->last_used_at)
<div class="text-sm text-theme-light">
{{ __('Last used') }} {{ $token->last_used_at->diffForHumans() }}
</div>
@endif
@if (Laravel\Jetstream\Jetstream::hasPermissions())
<button class="cursor-pointer ml-6 text-sm text-theme-light underline" wire:click="manageApiTokenPermissions({{ $token->id }})">
{{ __('Permissions') }}
</button>
@endif
<button class="cursor-pointer ml-6 text-sm text-red-500" wire:click="confirmApiTokenDeletion({{ $token->id }})">
{{ __('Delete') }}
</button>
</div>
</div>
@endforeach
</div>
</x-slot>
</x-jetstream.action-section>
</div>
@endif
<!-- Token Value Modal -->
<x-jetstream.dialog-modal wire:model.live="displayingToken">
<x-slot name="title">
{{ __('API Token') }}
</x-slot>
<x-slot name="content">
<div>
{{ __('Please copy your new API token. For your security, it won\'t be shown again.') }}
</div>
<x-jetstream.input x-ref="plaintextToken" type="text" readonly :value="$plainTextToken"
class="mt-4 bg-theme-surface px-4 py-2 rounded font-mono text-sm text-theme-secondary w-full"
autofocus autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
@showing-token-modal.window="setTimeout(() => $refs.plaintextToken.select(), 250)"
/>
</x-slot>
<x-slot name="footer">
<x-jetstream.secondary-button wire:click="$set('displayingToken', false)" wire:loading.attr="disabled">
{{ __('Close') }}
</x-jetstream.secondary-button>
</x-slot>
</x-jetstream.dialog-modal>
<!-- API Token Permissions Modal -->
<x-jetstream.dialog-modal wire:model.live="managingApiTokenPermissions">
<x-slot name="title">
{{ __('API Token Permissions') }}
</x-slot>
<x-slot name="content">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
@foreach (Laravel\Jetstream\Jetstream::$permissions as $permission)
<label class="flex items-center">
<x-jetstream.checkbox wire:model="updateApiTokenForm.permissions" :value="$permission"/>
<span class="ml-2 text-sm text-theme-primary">{{ $permission }}</span>
</label>
@endforeach
</div>
</x-slot>
<x-slot name="footer">
<x-jetstream.secondary-button wire:click="$set('managingApiTokenPermissions', false)" wire:loading.attr="disabled">
{{ __('Cancel') }}
</x-jetstream.secondary-button>
<x-jetstream.button class="ml-3" wire:click="updateApiToken" wire:loading.attr="disabled">
{{ __('Save') }}
</x-jetstream.button>
</x-slot>
</x-jetstream.dialog-modal>
<!-- Delete Token Confirmation Modal -->
<x-jetstream.confirmation-modal wire:model.live="confirmingApiTokenDeletion">
<x-slot name="title">
{{ __('Delete API Token') }}
</x-slot>
<x-slot name="content">
{{ __('Are you sure you would like to delete this API token?') }}
</x-slot>
<x-slot name="footer">
<x-jetstream.secondary-button wire:click="$toggle('confirmingApiTokenDeletion')" wire:loading.attr="disabled">
{{ __('Cancel') }}
</x-jetstream.secondary-button>
<x-jetstream.danger-button class="ml-3" wire:click="deleteApiToken" wire:loading.attr="disabled">
{{ __('Delete') }}
</x-jetstream.danger-button>
</x-slot>
</x-jetstream.confirmation-modal>
</div>

View File

@@ -0,0 +1,11 @@
<x-app-layout>
<x-slot name="header">
{{ __('API Tokens') }}
</x-slot>
<div>
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
@livewire('api.api-token-manager')
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,28 @@
<x-guest-layout>
<x-jetstream.authentication-card>
<x-slot name="logo">
<x-jetstream.application-mark class="hidden md:block md:h-20 xl:h-28 w-auto md:mt-3" />
</x-slot>
<div class="mb-4 text-sm text-theme-secondary">
{{ __('This is a secure area of the application. Please confirm your password before continuing.') }}
</div>
<x-jetstream.validation-errors class="mb-4" />
<form method="POST" action="{{ route('password.confirm') }}">
@csrf
<div>
<x-jetstream.label for="password" value="{{ __('Password') }}" />
<x-jetstream.input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="current-password" autofocus />
</div>
<div class="flex justify-end mt-4">
<x-jetstream.button class="ml-4">
{{ __('Confirm') }}
</x-jetstream.button>
</div>
</form>
</x-jetstream.authentication-card>
</x-guest-layout>

View File

@@ -0,0 +1,34 @@
<x-guest-layout>
<x-jetstream.authentication-card>
<x-slot name="logo">
<x-jetstream.application-mark class="hidden md:block md:h-20 xl:h-28 w-auto md:mt-3" />
</x-slot>
<div class="mb-4 text-sm text-theme-secondary">
{{ __('Forgot the profile\'s password? No problem. Just let us know the email address of this profile and we will email a password reset link that will allow you to choose a new one.') }}
</div>
@if (session('status'))
<div class="mb-4 font-medium text-sm text-green-600">
{{ session('status') }}
</div>
@endif
<x-jetstream.validation-errors class="mb-4" />
<form method="POST" action="{{ route('non-user.password.email', ['profileType' => $profileType]) }}">
@csrf
<div class="block">
<x-jetstream.label for="email" value="{{ __('Email') }}" />
<x-jetstream.input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
</div>
<div class="flex items-center justify-end mt-4">
<x-jetstream.button>
{{ __('Email Password Reset Link') }}
</x-jetstream.button>
</div>
</form>
</x-jetstream.authentication-card>
</x-guest-layout>

View File

@@ -0,0 +1,34 @@
<x-guest-layout>
<x-jetstream.authentication-card>
<x-slot name="logo">
<x-jetstream.application-mark class="hidden md:block md:h-20 xl:h-28 w-auto md:mt-3" />
</x-slot>
<div class="mb-4 text-sm text-theme-secondary">
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
</div>
@if (session('status'))
<div class="mb-4 font-medium text-sm text-green-600">
{{ session('status') }}
</div>
@endif
<x-jetstream.validation-errors class="mb-4" />
<form method="POST" action="{{ route('password.email') }}">
@csrf
<div class="block">
<x-jetstream.label for="email" value="{{ __('Email') }}" />
<x-jetstream.input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
</div>
<div class="flex items-center justify-end mt-4">
<x-jetstream.button>
{{ __('Email Password Reset Link') }}
</x-jetstream.button>
</div>
</form>
</x-jetstream.authentication-card>
</x-guest-layout>

View File

@@ -0,0 +1,125 @@
@php
if (request()->has('redirect')) {
session(['url.intended' => request()->query('redirect')]);
}
@endphp
<x-guest-layout>
<x-jetstream.authentication-card>
<x-slot name="logo">
<x-jetstream.application-mark class="hidden md:block md:h-20 xl:h-28 w-auto md:mt-3" />
</x-slot>
@if(isMaintenanceMode() || session('maintenance_mode_active'))
<div class="mb-6 rounded-md bg-gray-50 border border-gray-300 p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M8.485 2.495c.673-1.167 2.357-1.167 3.03 0l6.28 10.875c.673 1.167-.17 2.625-1.516 2.625H3.72c-1.347 0-2.189-1.458-1.515-2.625L8.485 2.495zM10 5a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 0110 5zm0 9a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-sm font-medium text-gray-800">
{{ __('Site under maintenance') }}
</h3>
<div class="mt-2 text-sm text-gray-600">
<p>
{{ __('The site is currently undergoing maintenance, and login is temporarily unavailable. Thank you for your patience.') }}
</p>
</div>
</div>
</div>
</div>
@endif
@if ($errors->any())
<div class="mb-4">
@if(session('maintenance_mode_active'))
{{-- Show maintenance error without "Whoops!" heading --}}
<div class="rounded-md bg-red-50 border border-red-200 p-4">
<div class="flex">
<div class="flex-shrink-0">
<svg class="h-5 w-5 text-red-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" />
</svg>
</div>
<div class="ml-3">
<div class="text-sm text-red-800">
@foreach ($errors->all() as $error)
<p>{{ $error }}</p>
@endforeach
</div>
</div>
</div>
</div>
@else
{{-- Show standard validation errors with "Whoops!" heading --}}
<x-jetstream.validation-errors />
@endif
</div>
@endif
@if (session('status'))
<div class="mb-4 font-medium text-sm text-green-600">
{{ session('status') }}
</div>
@endif
<form method="POST" action="{{ route('login') }}">
@csrf
<div>
<x-jetstream.label for="name" value="{!! __('Email or username') !!}" />
<x-jetstream.input id="name" class="block mt-1 w-full" type="text" name="name" value="{{ old('name', request()->input('name')) }}" required autofocus autocomplete="username" />
</div>
<div class="mt-4" x-data="{ showPassword: false }">
<x-jetstream.label for="password" value="{{ __('Password') }}" />
<div class="relative">
<x-jetstream.input id="password" class="block mt-1 w-full pr-10" ::type="showPassword ? 'text' : 'password'" name="password" required autocomplete="current-password" />
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5">
<button type="button" @click="showPassword = !showPassword" class="ring-opacity-70 hover:opacity-90 focus:outline-none focus:text-theme-primary">
<template x-if="showPassword">
<x-icon name="eye" class="h-5 w-5" />
</template>
<template x-if="!showPassword">
<x-icon name="eye-slash" class="h-5 w-5 opacity-70" />
</template>
</button>
</div>
</div>
</div>
<div class="flex items-center justify-end mt-8 mb-8">
@if (Route::has('password.request'))
<a class="underline text-sm text-theme-primary hover:text-theme-primary" href="{{ route('password.request') }}">
{{ __('Forgot your password?') }}
</a>
@endif
<x-jetstream.button class="ml-4">
{{ __('Log in') }}
</x-jetstream.button>
</div>
</form>
</x-jetstream.authentication-card>
@push('scripts')
<script>
// Check if there's a redirect parameter in the URL
const urlParams = new URLSearchParams(window.location.search);
const redirectUrl = urlParams.get('redirect');
if (redirectUrl) {
// Send to server to store in session
fetch('{{ route("store-intended-url") }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
body: JSON.stringify({ url: redirectUrl })
});
}
</script>
@endpush
</x-guest-layout>

View File

@@ -0,0 +1,94 @@
<x-guest-layout>
<x-jetstream.authentication-card>
<x-slot name="logo">
<x-jetstream.application-mark class="hidden md:block md:h-20 xl:h-28 w-auto md:mt-3" />
</x-slot>
<x-jetstream.section-title>
<x-slot name="title">{{ __('Please introduce yourself in a few sentences') }}</x-slot>
<x-slot name="description">
<div class="my-4">{{ __('Other Timebankers like to know who you are before they start their first exchange with you.') }}</div>
<div class="my-4">{{ __('Explaining why you like to be part of our time economy can also help with getting new exhanges.') }}</div>
<!--- Stepper --->
<h1 class="mt-12 text-theme-secondary">{{ __('Step 2 of 3') }}</h1>
<div class="mb-10 mt-2 relative inset-x-0 bottom-0 h-4 rounded-full overflow-hidden">
<div class=" w-full h-full bg-theme-surface absolute "></div>
<div class=" h-full bg-theme-secondary absolute" style="width:66%"></div>
</div>
</x-slot>
</x-jetstream.section-title>
<div class="mt-5 md:mt-0 md:col-span-2">
<x-jetstream.validation-errors class="mb-4" />
<!---- Right section --->
<div class="px-4 py-5 bg-theme-background sm:p-6 shadow sm:rounded-tl-md sm:rounded-tr-md">
<div class="mt-0 text-2xl">
{{ __('') }}
</div>
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6 sm:col-span-4">
<form method="POST" action="{{ route('register-step2.create') }}" enctype="multipart/form-data">
@csrf
<div class="mt-4">
<x-jetstream.label for="photo" value="{{ __('Profile photo') }}" />
<input type="file" name="photo" />
</div>
<div class="mt-4">
<x-jetstream.label for="about" value="{{ __('Short intro about yourself') }}" />
<x-jetstream.input id="about" class="block mt-1 w-full" type="text" name="about" :value="old('about')" required autofocus autocomplete="about" />
</div>
<div class="mt-4">
<x-jetstream.label for="motivation" value="{{ __('Why do you like to joinTimebank.cc?') }}" />
<x-jetstream.input id="motivation" class="block mt-1 w-full" type="text" name="motivation" :value="old('motivation')" required autofocus autocomplete="motivation" />
</div>
<div class="mt-4">
<x-jetstream.label for="date_of_birth" value="{{ __('Date of birth') }}" />
<x-jetstream.input id="date_of_birth" class="block mt-1 w-full" type="text" name="date_of_birth" :value="old('date_of_birth')" required autofocus autocomplete="date_of_birth" />
</div>
@if (Laravel\Jetstream\Jetstream::hasTermsAndPrivacyPolicyFeature())
<div class="mt-4">
<x-jetstream.label for="terms">
<div class="flex items-center">
<x-jetstream.checkbox name="terms" id="terms" />
<div class="ml-2">
{!! __('I agree to the :terms_of_service and :privacy_policy', [
'terms_of_service' => '<a target="_blank" href="'.route('app.terms.show').'" class="underline text-sm text-theme-primary hover:text-theme-primary">'.__('Terms of Service').'</a>',
'privacy_policy' => '<a target="_blank" href="'.route('policy.show').'" class="underline text-sm text-theme-primary hover:text-theme-primary">'.__('Privacy Policy').'</a>',
]) !!}
</div>
</div>
</x-jetstream.label>
</div>
@endif
</div>
</div>
<div class="flex items-center justify-end mt-4">
<x-jetstream.button class="ml-4">
{{ __('Register') }}
</x-jetstream.button>
</div>
</form>
</div>
</div>
</x-jetstream.authentication-card>
</x-guest-layout>

View File

@@ -0,0 +1,60 @@
<x-guest-layout>
<x-jetstream.authentication-card>
<x-slot name="logo">
<x-jetstream.application-mark class="hidden md:block md:h-20 xl:h-28 w-auto md:mt-3" />
</x-slot>
<x-jetstream.validation-errors class="mb-4" />
<form method="POST" action="{{ route('register') }}">
@csrf
<div>
<x-jetstream.label for="name" value="{{ __('Name') }}" />
<x-jetstream.input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" />
</div>
<div class="mt-4">
<x-jetstream.label for="email" value="{{ __('Email') }}" />
<x-jetstream.input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required />
</div>
<div class="mt-4">
<x-jetstream.label for="password" value="{{ __('Password') }}" />
<x-jetstream.input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
</div>
<div class="mt-4">
<x-jetstream.label for="password_confirmation" value="{{ __('Confirm Password') }}" />
<x-jetstream.input id="password_confirmation" class="block mt-1 w-full" type="password" name="password_confirmation" required autocomplete="new-password" />
</div>
@if (Laravel\Jetstream\Jetstream::hasTermsAndPrivacyPolicyFeature())
<div class="mt-4">
<x-jetstream.label for="terms">
<div class="flex items-center">
<x-jetstream.checkbox name="terms" id="terms" />
<div class="ml-2">
{!! __('I agree to the :terms_of_service and :privacy_policy', [
'terms_of_service' => '<a target="_blank" href="'.route('app.terms.show').'" class="underline text-sm text-gray-600 hover:text-gray-900">'.__('Terms of Service').'</a>',
'privacy_policy' => '<a target="_blank" href="'.route('policy.show').'" class="underline text-sm text-gray-600 hover:text-gray-900">'.__('Privacy Policy').'</a>',
]) !!}
</div>
</div>
</x-jetstream.label>
</div>
@endif
<div class="flex items-center justify-end mt-4">
<a class="underline text-sm text-gray-600 hover:text-gray-900" href="{{ route('login') }}">
{{ __('Already registered?') }}
</a>
<x-jetstream.button class="ml-4">
{{ __('Register') }}
</x-jetstream.button>
</div>
</form>
</x-jetstream.authentication-card>
</x-guest-layout>

View File

@@ -0,0 +1,6 @@
<x-guest-layout>
<div class="flex items-center justify-center min-h-screen">
<!-- Registration Livewire Component (contains modals) -->
@livewire('registration')
</div>
</x-guest-layout>

View File

@@ -0,0 +1,63 @@
<x-guest-layout>
<x-jetstream.authentication-card>
<x-slot name="logo">
<x-jetstream.application-mark class="hidden md:block md:h-20 xl:h-28 w-auto md:mt-3" />
</x-slot>
<x-jetstream.validation-errors class="mb-4" />
<form method="POST" action="{{ route('non-user.password.update', ['profileType' => $profileType]) }}">
@csrf
<input type="hidden" name="token" value="{{ $token }}">
<input type="hidden" name="profileType" value="{{ $profileType }}">
<div class="block">
<x-jetstream.label for="email" value="{{ __('Email') }}" />
<x-jetstream.input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email', $email)" required autofocus />
</div>
<div class="mt-4" x-data="{ showPassword: false }">
<x-jetstream.label for="password" value="{{ __('Password') }}" />
<div class="relative">
<x-jetstream.input id="password" class="block mt-1 w-full pr-10" ::type="showPassword ? 'text' : 'password'" name="password" required autocomplete="new-password" />
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5">
<button type="button" @click="showPassword = !showPassword" class="text-theme-muted hover:text-theme-primary focus:outline-none focus:text-theme-primary ring-opacity-70 hover:opacity-90">
<template x-if="showPassword">
<x-icon name="eye" class="h-5 w-5" />
</template>
<template x-if="!showPassword">
<x-icon name="eye-slash" class="h-5 w-5 opacity-70" />
</template>
</button>
</div>
</div>
</div>
<div class="mt-4" x-data="{ showPassword: false }">
<x-jetstream.label for="password_confirmation" value="{{ __('Confirm Password') }}" />
<div class="relative">
<x-jetstream.input id="password_confirmation" class="block mt-1 w-full pr-10" ::type="showPassword ? 'text' : 'password'" name="password_confirmation" required autocomplete="new-password" />
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5">
<button type="button" @click="showPassword = !showPassword" class="text-theme-muted hover:text-theme-primary focus:outline-none focus:text-theme-primary ring-opacity-70 hover:opacity-90">
<template x-if="showPassword">
<x-icon name="eye" class="h-5 w-5" />
</template>
<template x-if="!showPassword">
<x-icon name="eye-slash" class="h-5 w-5 opacity-70" />
</template>
</button>
</div>
</div>
</div>
<div class="flex items-center justify-end mt-4">
<x-jetstream.button>
{{ __('Reset password') }}
</x-jetstream.button>
</div>
</form>
</x-jetstream.authentication-card>
</x-guest-layout>

View File

@@ -0,0 +1,61 @@
<x-guest-layout>
<x-jetstream.authentication-card>
<x-slot name="logo">
<x-jetstream.application-mark class="hidden md:block md:h-20 xl:h-28 w-auto md:mt-3" />
</x-slot>
<x-jetstream.validation-errors class="mb-4" />
<form method="POST" action="{{ route('password.update') }}">
@csrf
<input type="hidden" name="token" value="{{ $request->route('token') }}">
<div class="block">
<x-jetstream.label for="email" value="{{ __('Email') }}" />
<x-jetstream.input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email', $request->email)" required autofocus />
</div>
<div class="mt-4" x-data="{ showPassword: false }">
<x-jetstream.label for="password" value="{{ __('Password') }}" />
<div class="relative">
<x-jetstream.input id="password" class="block mt-1 w-full pr-10" ::type="showPassword ? 'text' : 'password'" name="password" required autocomplete="new-password" />
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5">
<button type="button" @click="showPassword = !showPassword" class="text-theme-muted hover:text-theme-primary focus:outline-none focus:text-theme-primary">
<template x-if="!showPassword">
<x-icon name="eye" class="h-5 w-5" />
</template>
<template x-if="showPassword">
<x-icon name="eye-slash" class="h-5 w-5" />
</template>
</button>
</div>
</div>
</div>
<div class="mt-4" x-data="{ showPassword: false }">
<x-jetstream.label for="password_confirmation" value="{{ __('Confirm Password') }}" />
<div class="relative">
<x-jetstream.input id="password_confirmation" class="block mt-1 w-full pr-10" ::type="showPassword ? 'text' : 'password'" name="password_confirmation" required autocomplete="new-password" />
<div class="absolute inset-y-0 right-0 pr-3 flex items-center text-sm leading-5">
<button type="button" @click="showPassword = !showPassword" class="text-theme-muted hover:text-theme-primary focus:outline-none focus:text-theme-primary">
<template x-if="!showPassword">
<x-icon name="eye" class="h-5 w-5" />
</template>
<template x-if="showPassword">
<x-icon name="eye-slash" class="h-5 w-5" />
</template>
</button>
</div>
</div>
</div>
<div class="flex items-center justify-end mt-4">
<x-jetstream.button>
{{ __('Reset password') }}
</x-jetstream.button>
</div>
</form>
</x-jetstream.authentication-card>
</x-guest-layout>

View File

@@ -0,0 +1,57 @@
t<x-guest-layout>
<x-jetstream.authentication-card>
<x-slot name="logo">
<x-jetstream.application-mark class="hidden md:block md:h-20 xl:h-28 w-auto md:mt-3" />
</x-slot>
<div x-data="{ recovery: false }">
<div class="mb-4 text-sm text-theme-secondary" x-show="! recovery">
{{ __('Please confirm access to your account by entering the authentication code provided by your authenticator application.') }}
</div>
<div class="mb-4 text-sm text-theme-secondary" x-show="recovery">
{{ __('Please confirm access to your account by entering one of your emergency recovery codes.') }}
</div>
<x-jetstream.validation-errors class="mb-4" />
<form method="POST" action="{{ route('two-factor.login') }}">
@csrf
<div class="mt-4" x-show="! recovery">
<x-jetstream.label for="code" value="{{ __('Code') }}" />
<x-jetstream.input id="code" class="block mt-1 w-full" type="text" inputmode="numeric" name="code" autofocus x-ref="code" autocomplete="one-time-code" />
</div>
<div class="mt-4" x-show="recovery">
<x-jetstream.label for="recovery_code" value="{{ __('Recovery Code') }}" />
<x-jetstream.input id="recovery_code" class="block mt-1 w-full" type="text" name="recovery_code" x-ref="recovery_code" autocomplete="one-time-code" />
</div>
<div class="flex items-center justify-end mt-4">
<button type="button" class="text-sm text-theme-secondary hover:text-theme-primary underline cursor-pointer"
x-show="! recovery"
x-on:click="
recovery = true;
$nextTick(() => { $refs.recovery_code.focus() })
">
{{ __('Use a recovery code') }}
</button>
<button type="button" class="text-sm text-theme-secondary hover:text-theme-primary underline cursor-pointer"
x-show="recovery"
x-on:click="
recovery = false;
$nextTick(() => { $refs.code.focus() })
">
{{ __('Use an authentication code') }}
</button>
<x-jetstream.button class="ml-4">
{{ __('Log in') }}
</x-jetstream.button>
</div>
</form>
</div>
</x-jetstream.authentication-card>
</x-guest-layout>

View File

@@ -0,0 +1,53 @@
<x-app-layout>
<div class="min-h-screen flex flex-col justify-center items-center py-6 relative overflow-hidden">
<!-- Background Image -->
<div class="absolute inset-0 z-0">
@livewire('welcome.login-landing-post', ['type' => 'SiteContents\Welcome\Landing' ?? null, 'random' => true, 'limit' => 1])
</div>
<!-- Verification Card -->
<div class="mx-8 sm:max-w-md px-12 py-6 bg-theme-background dark:bg-theme-secondary backdrop-blur-sm shadow-2xl rounded-lg z-20 relative">
<div class="flex justify-center mb-8">
<x-jetstream.application-mark class="h-20 xl:h-28 w-auto" />
</div>
<div class="mb-4 text-sm text-theme-secondary">
{{ __('Before continuing, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
</div>
@if (session('status') == 'verification-link-sent')
<div class="mb-4 font-medium text-sm text-green-600">
{{ __('A new verification link has been sent to the email address you provided in your profile settings.') }}
</div>
@endif
<div class="mt-4 mb-4 flex flex-col gap-4">
<form method="POST" action="{{ route('verification.send') }}" class="flex justify-center">
@csrf
<div>
<x-jetstream.button type="submit">
{{ __('Resend Verification Email') }}
</x-jetstream.button>
</div>
</form>
<div class="flex flex-col gap-2">
<a
href="{{ LaravelLocalization::localizeURL(route('profile.settings')) }}"
class="underline text-sm text-theme-secondary hover:text-theme-primary"
>
{{ __('Edit Profile') }}</a>
<form method="POST" action="{{ route('logout') }}" class="inline">
@csrf
<button type="submit" class="underline text-sm text-theme-secondary hover:text-theme-primary">
{{ __('Log out') }}
</button>
</form>
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,29 @@
<x-app-layout>
<x-slot name="header">
{{ trans_with_platform('@PLATFORM_NAME@ calls') }}
</x-slot>
<div class="py-6">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-theme-background overflow-x-visible shadow-xl sm:rounded-lg">
<div class="p-12 px-6 sm:px-20 bg-theme-background">
@php
$sidePostType = session('activeProfileType') === \App\Models\Admin::class
? 'SiteContents\\Manage\\CallsAdmin'
: 'SiteContents\\Manage\\Calls';
$sidePostFallback = session('activeProfileType') === \App\Models\Admin::class
? __('Manage calls (admin)')
: __('Manage calls');
@endphp
@livewire('side-post', [
'type' => $sidePostType,
'latest' => true,
'fallbackTitle' => $sidePostFallback,
'fallbackDescription' => ''])
@livewire('calls.manage')
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,131 @@
<x-guest-layout>
<x-slot name="header">
{{ trans_with_platform('@PLATFORM_NAME@ call') }}
</x-slot>
<div class="py-0 md:py-12" id="custom-timebank-style">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden shadow-xl sm:rounded-lg relative bg-{{ $tagColor ?? 'gray' }}-400">
<div class="absolute inset-0 bg-black/50"></div>
{{-- Like button absolutely positioned top-right, matching event card full view --}}
<div class="absolute top-14 right-4 md:right-10 lg:right-14 z-30">
@livewire('reaction-button', [
'typeName' => 'like',
'showCounter' => true,
'reactionCounter' => $call->loveReactant?->reactionCounters->firstWhere('reaction_type_id', 3)?->count ?? 0,
'modelClass' => \App\Models\Call::class,
'modelId' => $call->id,
'size' => 'w-10 h-10',
'inverseColors' => true,
'redirectUrl' => url()->current(),
], key('like-call-' . $call->id))
</div>
<div class="relative p-6 sm:px-20 lg:px-32 lg:py-18">
{{-- Tag category badges + expiry --}}
<div class="mb-2 mt-0 md:mt-6 lg:mt-12">
<div class="flex flex-wrap items-center gap-2">
@foreach ($tagCategories as $cat)
<span class="bg-{{ $cat['color'] ?? 'gray' }}-400 inline-flex items-center rounded-md px-2 py-1 text-sm font-normal text-black">
{{ $cat['name'] }}
</span>
@endforeach
</div>
@if ($call->till)
<div class="mt-2 text-xs text-white/70">
{{ __('Expires') }}: {{ $call->till->translatedFormat('l d F Y') }}
</div>
@endif
@if ($call->is_suppressed)
<div class="mt-0.5 text-xs text-red-400">
{{ __('Publication blocked due to policy violation') }}
</div>
@else
<div class="mt-0.5 text-xs text-white/70">
<a href="{{ route('static-report-issue', [], false) . '?' . http_build_query(['subject' => __('Call reported for policy review'), 'message' => trans_with_platform('Please review this call for @PLATFORM_NAME@ policy compliance.') . "\n\n" . url()->current()]) }}"
class="underline underline-offset-2 hover:text-white/90">{{ __('Report') }}</a>{{ __(' this call for policy review') }}
</div>
@endif
</div>
{{-- Title (tag name) --}}
<h2 class="mt-4 lg:mt-8 text-3xl lg:text-5xl font-semibold leading-tight text-white">
@if ($isDeleted)<span class="text-red-400">{{ __('DELETED') }}: </span>@elseif ($call->is_suppressed)<span class="text-red-400">{{ __('BLOCKED') }}: </span>@elseif ($call->is_paused)<span class="text-red-400">{{ __('PAUSED') }}: </span>@elseif ($isExpired)<span class="text-red-400">{{ __('EXPIRED') }}: </span>@endif{{ $call->tag?->translation?->name ?? $call->tag?->name }}
</h2>
{{-- Location + expiry badges --}}
@if ($callLocation || $expiryBadgeText)
<div class="mt-3 flex flex-wrap items-center gap-2">
@if ($callLocation)
<h4 class="inline-block items-center rounded-sm bg-black px-2 pb-1 pt-0.5 text-sm lg:text-base font-normal uppercase text-white">
{{ $callLocation }}
</h4>
@endif
@if ($expiryBadgeText)
<h4 class="inline-block items-center rounded-sm bg-black px-2 pb-1 pt-0.5 text-sm lg:text-base font-normal uppercase text-white">
{{ $expiryBadgeText }}
</h4>
@endif
</div>
@endif
{{-- Content --}}
@if ($call->translations->first()?->content)
<div class="mt-6">
<div class="px-0 py-2 text-xl lg:text-2xl leading-normal lg:leading-loose font-bold text-white">
{{ $call->translations->first()->content }}
</div>
</div>
@endif
{{-- Callable profile block no profile link for guests; photo blurred per config --}}
@if ($call->callable?->name || $callableLocation)
<div class="my-8 lg:my-12">
<div class="flex items-center gap-4">
@if ($call->callable?->profile_photo_url)
<div class="h-16 w-16 flex-shrink-0 rounded-full outline outline-1 outline-offset-1 outline-white/60 overflow-hidden">
<img src="{{ $call->callable->profile_photo_url }}"
alt=""
class="h-full w-full object-cover">
</div>
@endif
<div>
<div class="font-semibold text-lg text-white">{{ $call->callable?->name }}</div>
@if ($callableLocation)
<div class="text-sm text-white/70 mt-1">{{ $callableLocation }}</div>
@endif
</div>
</div>
</div>
@endif
</div>
{{-- Social share + respond button --}}
<div class="relative flex items-center justify-between gap-8 pl-6 sm:pl-20 lg:pl-32 pr-4 md:pr-10 lg:pr-14 mb-12">
{{-- Social share buttons (left, only when public) --}}
<div>
@if ($call->is_public)
{!! Share::mastodon()
->bluesky()
->linkedin()
->instagram()
->facebook()
->whatsapp()
->text($call->tag?->translation?->name ?? $call->tag?->name ?? '')
->render() !!}
@endif
</div>
{{-- Respond button (right) --}}
<a href="{{ route('login') }}">
<x-jetstream.button>
{{ __('Respond') }}
</x-jetstream.button>
</a>
</div>
</div>
</div>
</div>
</x-guest-layout>

View File

@@ -0,0 +1,123 @@
<x-app-layout>
<x-slot name="header">
{{ trans_with_platform('@PLATFORM_NAME@ call') }}
</x-slot>
<div class="py-0 md:py-12" id="custom-timebank-style">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden shadow-xl sm:rounded-lg relative bg-{{ $tagColor ?? 'gray' }}-400">
<div class="absolute inset-0 bg-black/50"></div>
{{-- Like button absolutely positioned top-right, matching event card full view --}}
<div class="absolute top-14 right-4 md:right-10 lg:right-14 z-30">
@livewire('reaction-button', [
'typeName' => 'like',
'showCounter' => true,
'reactionCounter' => $call->loveReactant?->reactionCounters->firstWhere('reaction_type_id', 3)?->count ?? 0,
'modelClass' => \App\Models\Call::class,
'modelId' => $call->id,
'size' => 'w-10 h-10',
'inverseColors' => true,
], key('like-call-' . $call->id))
</div>
<div class="relative p-6 sm:px-20 lg:px-32 lg:py-18">
{{-- Tag category badges + expiry --}}
<div class="mb-2 mt-0 md:mt-6 lg:mt-12">
<div class="flex flex-wrap items-center gap-2">
@foreach ($tagCategories as $cat)
<span class="bg-{{ $cat['color'] ?? 'gray' }}-400 inline-flex items-center rounded-md px-2 py-1 text-sm font-normal text-black">
{{ $cat['name'] }}
</span>
@endforeach
</div>
@if ($call->till)
<div class="mt-2 text-xs text-white/70">
{{ __('Expires') }}: {{ $call->till->translatedFormat('l d F Y') }}
</div>
@endif
@if ($call->is_suppressed)
<div class="mt-0.5 text-xs text-red-400">
{{ __('Publication blocked due to policy violation') }}
</div>
@else
<div class="mt-0.5 text-xs text-white/70">
<a href="{{ route('static-report-issue', [], false) . '?' . http_build_query(['subject' => __('Call reported for policy review'), 'message' => trans_with_platform('Please review this call for @PLATFORM_NAME@ policy compliance.') . "\n\n" . url()->current()]) }}"
class="underline underline-offset-2 hover:text-white/90">{{ __('Report') }}</a>{{ __(' this call for policy review') }}
</div>
@endif
</div>
{{-- Title (tag name) --}}
<h2 class="mt-4 lg:mt-8 text-3xl lg:text-5xl font-semibold leading-tight text-white">
@if ($isDeleted)<span class="text-red-400">{{ __('DELETED') }}: </span>@elseif ($call->is_suppressed)<span class="text-red-400">{{ __('BLOCKED') }}: </span>@elseif ($call->is_paused)<span class="text-red-400">{{ __('PAUSED') }}: </span>@elseif ($isExpired)<span class="text-red-400">{{ __('EXPIRED') }}: </span>@endif{{ $call->tag?->translation?->name ?? $call->tag?->name }}
</h2>
{{-- Location + expiry badges --}}
@if ($callLocation || $expiryBadgeText)
<div class="mt-3 flex flex-wrap items-center gap-2">
@if ($callLocation)
<h4 class="inline-block items-center rounded-sm bg-black px-2 pb-1 pt-0.5 text-sm lg:text-base font-normal uppercase text-white">
{{ $callLocation }}
</h4>
@endif
@if ($expiryBadgeText)
<h4 class="inline-block items-center rounded-sm bg-black px-2 pb-1 pt-0.5 text-sm lg:text-base font-normal uppercase text-white">
{{ $expiryBadgeText }}
</h4>
@endif
</div>
@endif
{{-- Content --}}
@if ($call->translations->first()?->content)
<div class="mt-6">
<div class="px-0 py-2 text-xl lg:text-2xl leading-normal lg:leading-loose font-bold text-white">
{{ $call->translations->first()->content }}
</div>
</div>
@endif
{{-- Callable profile block --}}
<div class="my-8 lg:my-12">
<a href="{{ url(strtolower(class_basename($call->callable)) . '/' . $call->callable?->id) }}"
class="flex items-center gap-4 hover:opacity-80 cursor-pointer">
@if ($call->callable?->profile_photo_url)
<img src="{{ $call->callable->profile_photo_url }}"
alt="{{ $call->callable->name }}"
class="h-16 w-16 flex-shrink-0 rounded-full object-cover outline outline-1 outline-offset-1 outline-white/60">
@endif
<div>
<div class="font-semibold text-lg text-white">{{ $call->callable?->name }}</div>
@if ($callableLocation)
<div class="text-sm text-white/70 mt-1">{{ $callableLocation }}</div>
@endif
</div>
</a>
</div>
</div>
{{-- Social share + action buttons --}}
<div class="relative flex items-center justify-between gap-8 pl-6 sm:pl-20 lg:pl-32 pr-4 md:pr-10 lg:pr-14 mb-12">
{{-- Social share buttons (left, only when public) --}}
<div>
@if ($call->is_public)
{!! Share::mastodon()
->bluesky()
->linkedin()
->instagram()
->facebook()
->whatsapp()
->text($call->tag?->translation?->name ?? $call->tag?->name ?? '')
->render() !!}
@endif
</div>
{{-- Send message button (right) --}}
@livewire('calls.send-message-button', ['callable' => $call->callable, 'call' => $call], key('send-message-' . $call->id))
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,27 @@
<x-app-layout>
<x-slot name="header">
{{ __('Calls') }}
</x-slot>
<div class="py-6">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-xl sm:rounded-lg">
<div class="border-b border-gray-200 bg-white p-6 sm:px-20">
<div class="mt-12">
<div class="text-5xl font-bold text-gray-900">
{{ __('This call is not available') }}
</div>
</div>
<div class="mb-12 mt-6">
<span class="text-xl text-gray-700">
{{ __('This call has expired or is currently not available.') }}
</span>
</div>
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,28 @@
<x-app-layout>
<x-slot name="header">
{{ __('Categories') }}
</x-slot>
<div class="py-6">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-theme-background overflow-hidden shadow-xl sm:rounded-lg">
<div class="p-12 px-6 sm:px-20 bg-theme-background">
@livewire('side-post', [
'type' => 'SiteContents\Manage\Categories' ?? null,
'random' => false,
'fallbackTitle' => __('Manage categories'),
'fallbackDescription' => '' ])
<!--- Admin section -->
@livewire('categories.manage')
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,118 @@
@props([
'result' => [],
'index' => 0,
'href' => null,
'wireClick' => null,
'showScore' => false,
'showCallable' => true,
'showReactions' => true,
'photoBlur' => 0,
'photoContrast' => 100,
'photoSaturate' => 100,
'photoBrightness' => 100,
'heightClass' => 'h-[430px] md:h-[550px] lg:h-[430px]',
'truncateExcerpt' => false,
])
<div class="relative flex flex-col justify-end overflow-hidden rounded-lg bg-theme-background shadow-2xl {{ $heightClass }}">
@if ($wireClick)
<a href="#" wire:click.prevent="{{ $wireClick }}"
class="relative flex h-full cursor-pointer flex-col overflow-hidden rounded-lg">
@else
<a href="{{ $href ?? route('call.show', ['id' => $result['id']]) }}"
class="relative flex h-full cursor-pointer flex-col overflow-hidden rounded-lg">
@endif
<!-- Tag category color background -->
<div class="absolute inset-0 z-0 bg-{{ $result['tag_color'] ?? 'gray' }}-400"></div>
<div class="absolute inset-0 z-10 bg-black/50"></div>
<!-- Card content -->
<div class="relative z-20 flex h-full flex-col justify-between px-6 pt-10 pb-10 lg:px-14 lg:pt-14 lg:pb-14 text-white">
<div class="flex-1">
<div class="flex items-start justify-between gap-4">
<div class="flex flex-wrap items-center gap-2">
{{-- Deepest tag category badge only --}}
@php $deepestCat = !empty($result['tag_categories']) ? last($result['tag_categories']) : null; @endphp
@if ($deepestCat)
<span class="bg-{{ $deepestCat['color'] ?? 'gray' }}-400 inline-flex items-center rounded-md px-2 py-1 text-sm font-normal text-black">
{{ $deepestCat['name'] }}
</span>
@endif
</div>
{{-- Reaction button --}}
@if ($showReactions)
<div class="flex items-start -m-2 flex-shrink-0">
<div class="-my-3">
@livewire('reaction-button', [
'typeName' => 'like',
'showCounter' => true,
'reactionCounter' => $result['like_count'],
'modelClass' => $result['model'],
'modelId' => $result['id'],
'size' => 'w-6 h-6',
'inverseColors' => true,
], key('like-' . $result['model'] . '-' . $result['id'] . '-' . $index))
</div>
</div>
@endif
</div>
<div>
<h2 class="my-3 text-4xl font-semibold leading-tight line-clamp-2">
{{ $result['title'] }}
</h2>
{{-- Location + expiry badges --}}
@if (!empty($result['location']) || !empty($result['expiry_badge_text']))
<div class="mt-3 flex flex-wrap items-center gap-2">
@if (!empty($result['location']))
<h4 class="inline-block items-center rounded-sm bg-black px-2 pb-1 pt-0.5 text-sm font-normal uppercase text-white">
{{ $result['location'] }}
</h4>
@endif
@if (!empty($result['expiry_badge_text']))
<h4 class="inline-block items-center rounded-sm bg-black px-2 pb-1 pt-0.5 text-sm font-normal uppercase text-white">
{{ $result['expiry_badge_text'] }}
</h4>
@endif
</div>
@endif
<p class="mt-3 text-base font-semibold {{ $truncateExcerpt ? 'line-clamp-2' : '' }}">
{{ $result['excerpt'] }}
</p>
</div>
</div>
@if ($showCallable)
<div class="flex flex-wrap items-end gap-4">
<div class="flex items-center gap-3">
{{-- Callable avatar --}}
@if (!empty($result['photo']))
<div class="h-16 w-16 flex-shrink-0 rounded-full outline outline-1 outline-offset-1 outline-white/50 overflow-hidden">
<img src="{{ $result['photo'] }}"
alt="{{ $result['callable_name'] }}"
class="h-full w-full object-cover" />
</div>
@endif
<div class="flex flex-col gap-1 text-sm">
{{-- Callable name --}}
@if (!empty($result['callable_name']))
<span class="font-medium">{{ $result['callable_name'] }}</span>
@endif
{{-- Callable location --}}
@if (!empty($result['callable_location']))
<span class="text-white/80">{{ $result['callable_location'] }}</span>
@endif
</div>
</div>
</div>
@endif
</div>
@if ($showScore)
<div class="text-2xs absolute bottom-5 right-5 z-20 text-transparent sm:text-white drop-shadow">
{{ __('search score') . ': ' . round($result['score'] ?? 0, 1) }}
</div>
@endif
</a>
</div>

View File

@@ -0,0 +1,65 @@
<footer class="bg-theme-brand mx-auto pt-4 lg:pt-9">
<div class="container mx-auto max-w-7xl px-6 py-9 sm:px-6 lg:px-8">
<div class="grid grid-cols-2 gap-y-12 gap-x-8 md:gap-12 text-base md:grid-cols-3 lg:grid-cols-4">
@php
$footerSections = collect(timebank_config('footer.sections', []))
->where('visible', true)
->sortBy('order');
@endphp
@foreach($footerSections as $section)
<div>
<p class="text-sm font-extrabold text-theme-background md:font-semibold dark:text-theme-background">
{{ __($section['title']) }}
</p>
<div class="mt-1 flex flex-col items-start space-y-2 text-xs">
@php
$links = collect($section['links'] ?? [])
->where('visible', true)
->sortBy('order');
@endphp
@foreach($links as $link)
@if(isset($link['auth_required']) && $link['auth_required'])
@auth
<a class="text-theme-light hover:text-theme-accent dark:text-theme-secondary dark:hover:text-theme-accent transition-colors duration-300 hover:underline"
href="{{ route($link['route']) }}">
{{ __($link['title']) }}
</a>
@endauth
@elseif(isset($link['url']))
<a class="text-theme-light hover:text-theme-accent dark:text-theme-secondary dark:hover:text-theme-accent transition-colors duration-300 hover:underline"
href="{{ $link['url'] }}">
{{ __($link['title']) }}
</a>
@else
<a class="text-theme-light hover:text-theme-accent dark:text-theme-secondary dark:hover:text-theme-accent transition-colors duration-300 hover:underline"
href="{{ route($link['route']) }}">
{{ __($link['title']) }}
</a>
@endif
@endforeach
</div>
</div>
@endforeach
</div>
<!-- Bottom Section: Application Mark and Text -->
<div class="my-6 flex w-full flex-col items-end justify-end space-y-2">
<div class="invert-100 flex flex-col items-center justify-center">
<a href="{{ route('main') }}">
<x-jetstream.application-mark class="block h-9 w-auto" />
</a>
<p class="mt-2 text-2xs dark:text-theme-light font-semibold text-gray-800">
{{ __(timebank_config('footer.tagline','')) }}
</p>
</div>
</div>
</div>
</footer>

View File

@@ -0,0 +1,6 @@
<button {{ $attributes->merge([
'type' => 'button',
'class' => 'inline-flex items-center pl-4 pr-2 py-2 bg-theme-background border border-theme-border rounded-md font-semibold text-xs text-theme-primary uppercase tracking-widest shadow-sm hover:bg-theme-border hover:text-theme-secondary focus:outline-none focus:border-blue-300 focus:ring focus:ring-blue-200 active:text-theme-primary active:bg-theme-surface disabled:opacity-25 transition']) }}>
{{ $slot }}
<span class="ml-2"><x-icon name="chevron-down" class="w-5 h-5" mini/></span>
</button>

View File

@@ -0,0 +1,10 @@
@props(['on'])
<div x-data="{ shown: false, timeout: null }"
x-init="@this.on('{{ $on }}', () => { clearTimeout(timeout); shown = true; timeout = setTimeout(() => { shown = false }, 2000); })"
x-show.transition.out.opacity.duration.1500ms="shown"
x-transition:leave.opacity.duration.1500ms
style="display: none;"
{{ $attributes->merge(['class' => 'text-sm text-theme-secondary']) }}>
{!! $slot->isEmpty() ? 'Saved.' : $slot !!}
</div>

View File

@@ -0,0 +1,12 @@
<div {{ $attributes->merge(['class' => 'md:grid md:grid-cols-3 md:gap-6']) }}>
<x-jetstream.section-title>
<x-slot name="title">{{ $title }}</x-slot>
<x-slot name="description">{{ $description }}</x-slot>
</x-jetstream.section-title>
<div class="md:mt-0 md:col-span-2">
<div class="px-4 py-5 sm:p-6 bg-theme-background shadow sm:rounded-lg">
{{ $content }}
</div>
</div>
</div>

View File

@@ -0,0 +1,4 @@
<div class="w-full max-w-md mx-auto">
@include(theme_logo('svg_inline', 'logos.timebank_cc'), ['logoTitle' => $logoTitle ?? __('Search') . ' - ' . config('app.name')])
</div>

View File

@@ -0,0 +1,4 @@
<div {{ $attributes }}>
@include(theme_logo('svg_inline', 'logos.timebank_cc'), ['logoTitle' => $logoTitle ?? config('app.name')])
</div>

View File

@@ -0,0 +1,6 @@
<a href="/" class="block max-w-md">
<div class="w-full h-auto">
@include(theme_logo('svg_inline', 'logos.timebank_cc'), ['logoTitle' => $logoTitle ?? __('Go to homepage') . ' - ' . config('app.name')])
</div>
</a>

View File

@@ -0,0 +1,14 @@
<div class="min-h-screen flex flex-col justify-center items-center py-6 relative overflow-hidden">
<!-- Background Image -->
<div class="absolute inset-0 z-0">
@livewire('welcome.login-landing-post', ['type' => 'SiteContents\Welcome\Landing' ?? null, 'random' => true, 'limit' => 1])
</div>
<!-- Login Modal Card -->
<div class="mx-8 sm:max-w-md px-12 py-6 bg-theme-background dark:bg-theme-secondary backdrop-blur-sm shadow-2xl rounded-lg z-20 relative">
<div class="flex justify-center mb-8">
{{ $logo }}
</div>
{{ $slot }}
</div>
</div>

View File

@@ -0,0 +1,46 @@
@props(['style' => session('flash.bannerStyle', 'success'), 'message' => session('flash.banner')])
<div x-data="{{ json_encode(['show' => true, 'style' => $style, 'message' => $message]) }}"
:class="{ 'bg-green-100': style == 'success', 'bg-red-100': style == 'danger', 'bg-theme-surface': style != 'success' && style != 'danger' }"
style="display: none;"
x-show="show && message"
x-init="
document.addEventListener('banner-message', event => {
style = event.detail.style;
message = event.detail.message;
show = true;
});
">
<div class="mx-auto py-2 px-3 sm:px-6 lg:px-8">
<div class="flex items-center justify-between flex-wrap">
<div class="w-0 flex-1 flex items-center min-w-0">
<span class="flex p-2 rounded-lg" :class="{ 'bg-green-100': style == 'success', 'bg-red-100': style == 'danger' }">
<svg x-show="style == 'success'" class="h-5 w-5 text-green-700" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<svg x-show="style == 'danger'" class="h-5 w-5 text-red-700" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<svg x-show="style != 'success' && style != 'danger'" class="h-5 w-5 text-dark" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</span>
<p class="ml-3 font-medium text-sm text-dark truncate" x-text="message"></p>
</div>
<div class="shrink-0 sm:ml-3">
<button
type="button"
class="-mr-1 flex p-2 rounded-md focus:outline-none sm:-mr-2 transition"
:class="{ 'hover:bg-green-300 focus:bg-green-300': style == 'success', 'hover:bg-red-300 focus:bg-red-300': style == 'danger' }"
aria-label="Dismiss"
x-on:click="show = false">
<svg class="h-5 w-5 text-dark" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,37 @@
@php
// Determine the wire target from wire:click or use explicit wire:target if provided
$wireTarget = null;
if ($attributes->has('wire:target')) {
$wireTarget = $attributes->get('wire:target');
} else {
// Look for wire:click variants (wire:click, wire:click.prevent, etc.)
foreach ($attributes->getAttributes() as $key => $value) {
if (str_starts_with($key, 'wire:click')) {
// Skip $dispatch, $set, $toggle etc. as they don't create loading states
if (!str_starts_with(trim($value), '$')) {
$wireTarget = $value;
break;
}
}
}
}
@endphp
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center justify-center px-4 py-2 bg-theme-primary-900 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest shadow-lg hover:shadow-sm hover:bg-theme-primary-700 hover:text-theme-primary-100 focus:outline-none focus:border-theme-accent focus:ring-1 focus:ring-theme-accent active:bg-theme-primary-900 disabled:opacity-25 transition']) }}>
@if(!$attributes->has('no-spinner') && $wireTarget)
<span class="relative flex items-center justify-center w-full">
<span wire:loading wire:target="{{ $wireTarget }}" class="absolute flex items-center justify-center">
<svg class="animate-spin h-5 w-5" 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 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</span>
<span wire:loading.class="opacity-0" wire:target="{{ $wireTarget }}" class="inline-flex items-center">
{{ $slot }}
</span>
</span>
@else
{{ $slot }}
@endif
</button>

View File

@@ -0,0 +1 @@
<input type="checkbox" {!! $attributes->merge(['class' => 'rounded border-theme-border text-theme-secondary shadow-sm focus:border-theme-border focus:ring focus:ring-gray-200 focus:ring-opacity-50']) !!}>

View File

@@ -0,0 +1,27 @@
@props(['id' => null, 'maxWidth' => null])
<x-jetstream.modal :id="$id" :maxWidth="$maxWidth" {{ $attributes }}>
<div class="bg-theme-background px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<div class="sm:flex sm:items-start">
<div class="mx-auto shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
<svg class="h-6 w-6 text-red-600" stroke="currentColor" fill="none" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
</svg>
</div>
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
<h3 class="text-lg">
{!! $title !!}
</h3>
<div class="mt-2">
{!! $content !!}
</div>
</div>
</div>
</div>
<div class="flex flex-row justify-end px-6 py-4 bg-theme-surface text-right">
{!! $footer !!}
</div>
</x-jetstream.modal>

View File

@@ -0,0 +1,46 @@
@props(['title' => __('Confirm Password'), 'content' => __('For your security, please confirm your password to continue.'), 'button' => __('Confirm')])
@php
$confirmableId = md5($attributes->wire('then'));
@endphp
<span
{{ $attributes->wire('then') }}
x-data
x-ref="span"
x-on:click="$wire.startConfirmingPassword('{{ $confirmableId }}')"
x-on:password-confirmed.window="setTimeout(() => $event.detail.id === '{{ $confirmableId }}' && $refs.span.dispatchEvent(new CustomEvent('then', { bubbles: false })), 250);"
>
{{ $slot }}
</span>
@once
<x-jetstream.dialog-modal wire:model.live="confirmingPassword">
<x-slot name="title">
{{ $title }}
</x-slot>
<x-slot name="content">
{{ $content }}
<div class="mt-4" x-data="{}" x-on:confirming-password.window="setTimeout(() => $refs.confirmable_password.focus(), 250)">
<x-jetstream.input type="password" class="mt-1 block w-3/4" placeholder="{{ __('Password') }}"
x-ref="confirmable_password"
wire:model="confirmablePassword"
wire:keydown.enter="confirmPassword" />
<x-jetstream.input-error for="confirmable_password" class="mt-2" />
</div>
</x-slot>
<x-slot name="footer">
<x-jetstream.secondary-button wire:click="stopConfirmingPassword" wire:loading.attr="disabled">
{{ __('Cancel') }}
</x-jetstream.secondary-button>
<x-jetstream.button class="ml-3" dusk="confirm-password-button" wire:click="confirmPassword" wire:loading.attr="disabled">
{{ $button }}
</x-jetstream.button>
</x-slot>
</x-jetstream.dialog-modal>
@endonce

View File

@@ -0,0 +1,37 @@
@php
// Determine the wire target from wire:click or use explicit wire:target if provided
$wireTarget = null;
if ($attributes->has('wire:target')) {
$wireTarget = $attributes->get('wire:target');
} else {
// Look for wire:click variants (wire:click, wire:click.prevent, etc.)
foreach ($attributes->getAttributes() as $key => $value) {
if (str_starts_with($key, 'wire:click')) {
// Skip $dispatch, $set, $toggle etc. as they don't create loading states
if (!str_starts_with(trim($value), '$')) {
$wireTarget = $value;
break;
}
}
}
}
@endphp
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center justify-center px-4 py-2 bg-theme-danger-dark border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest shadow-md hover:shadow-sm hover:bg-theme-danger focus:outline-none focus:border-theme-accent focus:ring-1 focus:ring-theme-accent active:bg-theme-danger disabled:opacity-25 transition']) }}>
@if(!$attributes->has('no-spinner') && $wireTarget)
<span class="relative flex items-center justify-center w-full">
<span wire:loading wire:target="{{ $wireTarget }}" class="absolute flex items-center justify-center">
<svg class="animate-spin h-5 w-5" 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 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</span>
<span wire:loading.class="opacity-0" wire:target="{{ $wireTarget }}" class="inline-flex items-center">
{{ $slot }}
</span>
</span>
@else
{{ $slot }}
@endif
</button>

View File

@@ -0,0 +1,24 @@
@props(['id' => null, 'maxWidth' => null, 'closeButton' => false])
<x-jetstream.modal :id="$id" :maxWidth="$maxWidth" {{ $attributes }}>
<div class="px-6 py-6">
<div class="flex items-center justify-between">
<div class="text-xl font-medium">
{!! $title !!}
</div>
@if($closeButton)
<button type="button" @click="show = false" class="hover:text-theme-secondary transition-colors">
<x-icon name="x-mark" class="w-6 h-6" />
</button>
@endif
</div>
<div class="m-6">
{!! $content !!}
</div>
<div class="flex flex-row justify-end px-6 py-6 text-right">
{!! $footer !!}
</div>
</div>
</x-jetstream.modal>

View File

@@ -0,0 +1 @@
<a {{ $attributes->merge(['class' => 'block px-4 py-2 text-sm leading-5 text-theme-primary hover:bg-theme-surface focus:outline-none focus:bg-theme-surface transition']) }}>{{ $slot }}</a>

View File

@@ -0,0 +1,47 @@
@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-theme-background', 'dropdownClasses' => ''])
@php
switch ($align) {
case 'left':
$alignmentClasses = 'origin-top-left left-0';
break;
case 'top':
$alignmentClasses = 'origin-top';
break;
case 'none':
case 'false':
$alignmentClasses = '';
break;
case 'right':
default:
$alignmentClasses = 'origin-top-right right-0';
break;
}
switch ($width) {
case '48':
$width = 'w-48';
break;
}
@endphp
<div class="relative" x-data="{ open: false }" @click.away="open = false" @close.stop="open = false">
<div @click="open = ! open">
{{ $trigger }}
</div>
<div x-show="open"
x-transition:enter="transition ease-out duration-200"
x-transition:enter-start="transform opacity-0 scale-95"
x-transition:enter-end="transform opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75"
x-transition:leave-start="transform opacity-100 scale-100"
x-transition:leave-end="transform opacity-0 scale-95"
class="absolute z-50 mt-2 {{ $width }} rounded-md shadow-lg {{ $alignmentClasses }} {{ $dropdownClasses }}"
style="display: none;"
@click="open = false">
<div class="rounded-md ring-1 ring-black ring-opacity-5 {{ $contentClasses }}">
{{ $content }}
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
@props(['submit'])
<div {{ $attributes->merge(['class' => 'md:grid md:grid-cols-3 md:gap-6']) }}>
<div class="mt-6 mb-6 md:mt-0 md:mb-0">
<x-jetstream.section-title>
<x-slot name="title">{{ $title }}</x-slot>
<x-slot name="description">{{ $description }}</x-slot>
</x-jetstream.section-title>
</div>
<div class="md:mt-0 md:col-span-2">
<form wire:submit="{{ $submit }}">
<div class="px-4 py-5 bg-theme-background sm:p-6 shadow sm:rounded-md">
<div class="grid grid-cols-6 gap-6">
{{ $form }}
</div>
@if (isset($actions))
<div class="flex items-center justify-end px-4 py-3 bg-gray-white text-right">
{{ $actions }}
</div>
@endif
</div>
</form>
</div>
</div>

View File

@@ -0,0 +1,5 @@
@props(['for'])
@error($for)
<p {{ $attributes->merge(['class' => 'text-sm text-red-600']) }}>{{ $message }}</p>
@enderror

View File

@@ -0,0 +1,3 @@
@props(['disabled' => false])
<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'border-theme-border focus:border-theme-accent focus:ring-1 focus:ring-theme-accent rounded-md shadow-sm']) !!}>

View File

@@ -0,0 +1,5 @@
@props(['value'])
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-theme-primary']) }}>
{!! html_entity_decode($value ?? $slot, ENT_QUOTES | ENT_HTML5, 'UTF-8') !!}
</label>

View File

@@ -0,0 +1,7 @@
<button {{ $attributes->merge([
'type' => 'button',
'class' => 'inline-flex items-center px-4 py-2 bg-theme-surface border border-theme-border rounded-md font-semibold text-xs text-theme-primary uppercase tracking-widest shadow-md hover:shadow-sm hover:bg-theme-primary-50 hover:text-theme-secondary focus:outline-none focus:border-theme-accent focus:ring-1 focus:ring-theme-accent active:text-theme-primary active:bg-theme-surface disabled:opacity-25 transition']) }}>
{{ $slot }}
</button>

View File

@@ -0,0 +1,73 @@
@props(['id', 'maxWidth'])
@php
$id = $id ?? md5($attributes->wire('model'));
$maxWidth = [
'sm' => 'sm:max-w-sm',
'md' => 'sm:max-w-md',
'lg' => 'sm:max-w-lg',
'xl' => 'sm:max-w-xl',
'2xl' => 'sm:max-w-2xl',
'3xl' => 'sm:max-w-3xl',
'4xl' => 'sm:max-w-4xl',
][$maxWidth ?? '2xl'];
@endphp
<div
x-data="{
show: @entangle($attributes->wire('model')),
focusables() {
// All focusable element types...
let selector = 'a, button, input:not([type=\'hidden\']), textarea, select, details, [tabindex]:not([tabindex=\'-1\'])'
return [...$el.querySelectorAll(selector)]
// All non-disabled elements...
.filter(el => ! el.hasAttribute('disabled'))
},
firstFocusable() { return this.focusables()[0] },
lastFocusable() { return this.focusables().slice(-1)[0] },
nextFocusable() { return this.focusables()[this.nextFocusableIndex()] || this.firstFocusable() },
prevFocusable() { return this.focusables()[this.prevFocusableIndex()] || this.lastFocusable() },
nextFocusableIndex() { return (this.focusables().indexOf(document.activeElement) + 1) % (this.focusables().length + 1) },
prevFocusableIndex() { return Math.max(0, this.focusables().indexOf(document.activeElement)) -1 },
}"
x-init="$watch('show', value => {
if (value) {
document.body.classList.add('overflow-y-hidden');
{{ $attributes->has('focusable') ? 'setTimeout(() => firstFocusable().focus(), 100)' : '' }}
} else {
document.body.classList.remove('overflow-y-hidden');
@this.dispatch('closeModal');
}
})"
x-on:close.stop="show = false"
x-on:keydown.escape.window="show = false"
x-on:keydown.tab.prevent="$event.shiftKey || nextFocusable().focus()"
x-on:keydown.shift.tab.prevent="prevFocusable().focus()"
x-show="show"
id="{{ $id }}"
class="jetstream-modal fixed inset-0 overflow-y-auto px-4 py-6 sm:px-0 z-50"
style="display: none;"
>
<div x-show="show" class="fixed inset-0 transform transition-all" {{--x-on:click="show = false"--}} x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
>
<div class="absolute inset-0 bg-black opacity-50"></div>
</div>
<div x-show="show" class="mb-6 bg-theme-background rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
{{ $slot }}
</div>
</div>

View File

@@ -0,0 +1,11 @@
@props(['active'])
@php
$classes = ($active ?? false)
? 'inline-flex items-center px-1 pt-1 border-theme-muted text-sm font-medium leading-5 text-theme-primary hover:text-theme-secondary focus:outline-none focus:border-gray-900'
: 'inline-flex items-center px-1 pt-1 border-transparent text-sm font-medium leading-5 text-theme-primary hover:text-theme-secondary hover:border-theme-border focus:outline-none focus:text-theme-primary focus:border-theme-border transition';
@endphp
<a {{ $attributes->merge(['class' => $classes]) }}>
{{ $slot }}
</a>

View File

@@ -0,0 +1,11 @@
@props(['active'])
@php
$classes = ($active ?? false)
? 'block pl-3 pr-4 py-2 border-l-4 border-black text-base font-semibold text-theme-primary bg-theme-surface focus:outline-none focus:text-theme-secondary focus:bg-theme-border focus:border-gray-700'
: 'block pl-3 pr-4 py-2 border-l-4 border-transparent text-base text-theme-primary leading-5 hover:text-theme-primary hover:bg-theme-surface hover:border-theme-border focus:outline-none focus:text-theme-primary focus:bg-theme-surface focus:border-theme-border';
@endphp
<a {{ $attributes->merge(['class' => $classes]) }}>
{{ $slot }}
</a>

View File

@@ -0,0 +1,41 @@
@php
// Determine the wire target from wire:click or use explicit wire:target if provided
$wireTarget = null;
if ($attributes->has('wire:target')) {
$wireTarget = $attributes->get('wire:target');
} else {
// Look for wire:click variants (wire:click, wire:click.prevent, etc.)
foreach ($attributes->getAttributes() as $key => $value) {
if (str_starts_with($key, 'wire:click')) {
// Skip $dispatch, $set, $toggle etc. as they don't create loading states
if (!str_starts_with(trim($value), '$')) {
$wireTarget = $value;
break;
}
}
}
}
@endphp
<button {{ $attributes->merge([
'type' => 'button',
'class' => 'inline-flex items-center px-4 py-2 bg-theme-secondary border border-theme-border rounded-md font-semibold text-xs text-theme-primary uppercase tracking-widest shadow-md hover:shadow-sm hover:bg-theme-border hover:text-theme-secondary focus:outline-none focus:border-theme-accent focus:ring-1 focus:ring-theme-accent active:text-theme-primary active:bg-theme-surface disabled:opacity-25 transition']) }}>
@if(!$attributes->has('no-spinner') && $wireTarget)
<span class="relative flex items-center justify-center w-full">
<span wire:loading wire:target="{{ $wireTarget }}" class="absolute flex items-center justify-center">
<svg class="animate-spin h-5 w-5" 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 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</span>
<span wire:loading.class="opacity-0" wire:target="{{ $wireTarget }}" class="inline-flex items-center">
{{ $slot }}
</span>
</span>
@else
{{ $slot }}
@endif
</button>

View File

@@ -0,0 +1,4 @@
<div class="hidden sm:block">
<div class="py-8">
</div>
</div>

View File

@@ -0,0 +1,13 @@
<div class="md:col-span-1 flex justify-between">
<div class="px-4 sm:px-0">
<h3 class="text-xl font-strong text-theme-primary">{!! $title !!}</h3>
<p class="hidden md:block mt-1 text-sm text-theme-secondary">
{!! $description !!}
</p>
</div>
<div class="px-4 sm:px-0">
{!! $aside ?? '' !!}
</div>
</div>

View File

@@ -0,0 +1,19 @@
@props(['team', 'component' => 'dropdown-link'])
<form method="POST" action="{{ route('current-team.update') }}" x-data>
@method('PUT')
@csrf
<!-- Hidden Team ID -->
<input type="hidden" name="team_id" value="{{ $team->id }}">
<x-dynamic-component :component="$component" href="#" x-on:click.prevent="$root.submit();">
<div class="flex items-center">
@if (Auth::user()->isCurrentTeam($team))
<svg class="mr-2 h-5 w-5 text-green-400" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor" viewBox="0 0 24 24"><path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
@endif
<div class="truncate">{{ $team->name }}</div>
</div>
</x-dynamic-component>
</form>

View File

@@ -0,0 +1,51 @@
@props(['style' => session('flash.bannerStyle', 'success'), 'message' => session('flash.banner')])
<div x-data="{{ json_encode(['show' => true, 'style' => $style, 'message' => $message]) }}"
:class="{ 'fixed bottom-0 left-0 right-0 bg-green-100': style == 'success', 'fixed bottom-0 left-0 right-0 bg-red-100': style == 'danger', 'fixed bottom-0 left-0 right-0 bg-theme-surface': style != 'success' && style != 'danger' }"
style="display: none;"
x-show="show && message"
x-transition:leave.opacity.duration.1000ms
x-init="
document.addEventListener('toaster-message', event => {
style = event.detail.style;
message = event.detail.message;
show = true;
timeout = setTimeout(() => { show = false }, 4000);
});
">
<div class="mx-auto py-4 px-6 sm:px-6 lg:px-8">
<div class="flex items-center justify-between flex-wrap">
<div class="w-0 flex-1 flex items-center min-w-0">
<span class="flex p-2 rounded-lg" :class="{ 'bg-green-100': style == 'success', 'bg-red-100': style == 'danger' }">
<svg x-show="style == 'success'" class="h-5 w-5 text-green-700" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<svg x-show="style == 'danger'" class="h-5 w-5 text-red-700" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<svg x-show="style != 'success' && style != 'danger'" class="h-5 w-5 text-dark" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</span>
<p class="ml-3 font-medium text-sm text-dark truncate" x-text="message"></p>
</div>
<div class="shrink-0 sm:ml-3">
<button
type="button"
class="-mr-1 flex p-2 rounded-md focus:outline-none sm:-mr-2 transition"
:class="{ 'hover:bg-green-300 focus:bg-green-300': style == 'success', 'hover:bg-red-300 focus:bg-red-300': style == 'danger' }"
aria-label="Dismiss"
x-on:click="show = false">
<svg class="h-5 w-5 text-dark" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,11 @@
@if ($errors->any())
<div {{ $attributes }}>
<div class="font-medium text-red-600">{{ __('Whoops! Something went wrong.') }}</div>
<ul class="mt-3 list-disc list-inside text-sm text-red-600">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif

View File

@@ -0,0 +1,93 @@
<div class="p-6 sm:px-20 bg-theme-background border-b border-theme-border">
<div>
<x-jetstream.application-logo class="block h-12 w-auto" />
</div>
<div>
{{-- {{ __('Last login at')}} {{ $loginAt }} --}}
</div>
<div class="mt-8 text-2xl">
Welcome to your Jetstream application!
</div>
<div class="mt-6 text-theme-muted">
Laravel Jetstream provides a beautiful, robust starting point for your next Laravel application. Laravel is designed
to help you build your application using a development environment that is simple, powerful, and enjoyable. We believe
you should love expressing your creativity through programming, so we have spent time carefully crafting the Laravel
ecosystem to be a breath of fresh air. We hope you love it.
</div>
</div>
<div class="bg-theme-border bg-opacity-25 grid grid-cols-1 md:grid-cols-2">
<div class="p-6">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-theme-muted"><path d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path></svg>
<div class="ml-4 text-lg text-theme-secondary leading-7 font-semibold"><a href="https://laravel.com/docs">Documentation</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-sm text-theme-muted">
Laravel has wonderful documentation covering every aspect of the framework. Whether you're new to the framework or have previous experience, we recommend reading all of the documentation from beginning to end.
</div>
<a href="https://laravel.com/docs">
<div class="mt-3 flex items-center text-sm font-semibold text-theme-primary">
<div>Explore the documentation</div>
<div class="ml-1 text-theme-muted">
<svg viewBox="0 0 20 20" fill="currentColor" class="w-4 h-4"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</div>
</div>
</a>
</div>
</div>
<div class="p-6 border-t border-theme-border md:border-t-0 md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-theme-muted"><path d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"></path><path d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
<div class="ml-4 text-lg text-theme-secondary leading-7 font-semibold"><a href="https://laracasts.com">Laracasts</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-sm text-theme-muted">
Laracasts offers thousands of video tutorials on Laravel, PHP, and JavaScript development. Check them out, see for yourself, and massively level up your development skills in the process.
</div>
<a href="https://laracasts.com">
<div class="mt-3 flex items-center text-sm font-semibold text-theme-primary">
<div>Start watching Laracasts</div>
<div class="ml-1 text-theme-muted">
<svg viewBox="0 0 20 20" fill="currentColor" class="w-4 h-4"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</div>
</div>
</a>
</div>
</div>
<div class="p-6 border-t border-theme-border">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-theme-muted"><path d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg>
<div class="ml-4 text-lg text-theme-secondary leading-7 font-semibold"><a href="https://tailwindcss.com/">Tailwind</a></div>
</div>
<div class="ml-12">
<div class="mt-2 text-sm text-theme-muted">
Laravel Jetstream is built with Tailwind, an amazing utility first CSS framework that doesn't get in your way. You'll be amazed how easily you can build and maintain fresh, modern designs with this wonderful framework at your fingertips.
</div>
</div>
</div>
<div class="p-6 border-t border-theme-border md:border-l">
<div class="flex items-center">
<svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-theme-muted"><path d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path></svg>
<div class="ml-4 text-lg text-theme-secondary leading-7 font-semibold">Authentication</div>
</div>
<div class="ml-12">
<div class="mt-2 text-sm text-theme-muted">
Authentication and registration views are included with Laravel Jetstream, as well as support for user email verification and resetting forgotten passwords. So, you're free to get started what matters most: building your application.
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,74 @@
<nav id="navigation-menu" class="bg-theme-background shadow-md border-b border-theme-primary fixed top-0 left-0 right-0 z-50" x-data="{ open: false }">
@if(auth()->guest() || request()->routeIs('goodbye-deleted-user'))
<!-- Primary Navigation Menu -->
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div class="flex h-16 items-center justify-between">
<!-- Logo -->
<div class="flex shrink-0 items-center">
<a href="{{ route('welcome') }}">
<x-jetstream.application-mark class="block h-9 w-auto" />
</a>
</div>
<!-- Language selector ---->
<!-- This changes the session('locale') and by the Middleware StoreUserLangPreference this locale
is stored as the lang_preference in the user table -->
@php
$languages = Illuminate\Support\Facades\DB::table('languages')->orderBy('lang_code', 'asc')->get();
$supportedLocales = LaravelLocalization::getSupportedLocales();
// Sort the supported locales alphabetically by the language name
uasort($supportedLocales, function ($a, $b) {
return strcmp($a['native'], $b['native']);
});
@endphp
<div class="flex ml-auto items-center">
<x-jetstream.dropdown>
<x-slot name="trigger">
<span class="inline-flex rounded-md">
<button class="inline-flex items-center py-2 text-sm font-medium leading-4 text-theme-primary hover:text-theme-secondary focus:bg-theme-surface focus:outline-none active:bg-theme-surface"
type="button">
<x-icon name="globe-alt" class="w-6 h-5" outline />
</button>
</span>
</x-slot>
<x-slot name="content">
<div class="w-60">
@foreach ($supportedLocales as $localeCode => $properties)
@php
$language = $languages->firstWhere('lang_code', strtolower($localeCode));
@endphp
@if ($language)
<div class="block px-4 py-2">
<a class="text-theme-primary transition hover:text-theme-secondary focus:border-theme-primary focus:text-theme-secondary"
href="{{ LaravelLocalization::getLocalizedURL($localeCode, null, [], true) }}"
hreflang="{{ $localeCode }}" rel="alternate">
{{ $language->flag }}
<span class="ml-3 text-theme-primary hove:text-theme-secondary">{{ Lang::get($language->name, [], $localeCode) }}</span>
</a>
</div>
@endif
@endforeach
</div>
</x-slot>
</x-jetstream.dropdown>
</div>
@if (Route::has('login'))
<div class="flex items-center space-x-2 ml-4">
@if (Route::has('register'))
<a href="{{ route('register') }}"
class="text-theme-primary hover:text-theme-secondary py-2 text-sm font-medium focus:outline-none">
{{ __('Register') }}
</a>
@endif
<a href="{{ route('login') }}"
class="text-theme-primary hover:text-theme-secondary pl-3 py-2 text-sm font-medium focus:outline-none">
{{ __('Log in') }}
</a>
</div>
@endif
</div>
</div>
@endif
</nav>

View File

@@ -0,0 +1,15 @@
<x-jetstream.form-section submit="saveTags">
<x-slot name="title">
{{ str_replace('@PLATFORM_NAME@', platform_name(), __('Activies you share on @PLATFORM_NAME@')) }}
</x-slot>
<x-slot name="description">
<p>{{ __('Which activities and skills can you share on Timebank? Give practical examples, avoid vague or general keywords.') }}
<p> {{ __('Rare skills can be interesting for others, but very common activities are also very useful to offer!') }} </p>
</x-slot>
<x-slot name="form">
</div>
@livewire('skills-form')
</x-slot>
</x-jetstream.form-section>

View File

@@ -0,0 +1,6 @@
<x-alert padding="none" title="{{ __('Please add new tags responsibly!') }}" warning>
<x-slot name="slot">
{{ __('Your name will be linked to this tag keyword.') }} <br>
{{ __('New activity tags are reviewed, and inappropriate or useless labels can be removed without notice.') }}
</x-slot>
</x-alert>

View File

@@ -0,0 +1,31 @@
<x-app-layout>
<x-slot name="header">
@if(getActiveProfileType() == 'User')
{{ __('Your contacts') }}
@else
{{ __('Contacts')}}
@endif
</x-slot>
<div class="py-6">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="sm:bg-white overflow-hidden shadow-xl sm:rounded-lg">
<div class="p-6 sm:px-20 bg-white border-b border-gray-200">
<div class="my-0 sm:my-6 lg:my-12">
@livewire('side-post', [
'type' => 'SiteContents\Contacts' ?? null,
'random' => false,
'fallbackTitle' => '',
'fallbackDescription' => '' ])
</div>
<!--- Contacts table -->
@livewire('contacts')
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,140 @@
@component('emails.layouts.html', ['subject' => __('Your profile has been deleted')])
{{-- Greeting --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Hello :name,', ['name' => $full_name ?? $name]) }}
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{!! __('Your :appname user profile has been deleted.', ['appname' => config('app.name')]) !!}
</p>
{{-- Deletion Reason (only shown for auto-deletions) --}}
@if(isset($autoDeleted) && $autoDeleted)
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
<strong>{{ __('Reason for deletion:') }}</strong>
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('Your profile was automatically deleted due to prolonged inactivity.') }}
@if(isset($daysNotLoggedIn) && isset($totalDaysToDelete))
{{ __('Profiles are deleted after :days days of no login activity.', ['days' => round($totalDaysToDelete)]) }}
{{ __('Your last login was more than :days days ago.', ['days' => round($daysNotLoggedIn)]) }}
@endif
</p>
@endif
{{-- Account Details Table --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
<strong>{{ __('Account Details:') }}</strong>
</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
<tr>
<td width="35%" style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Username:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $name }}
</td>
</tr>
<tr>
<td width="35%" style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Full name:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $full_name }}
</td>
</tr>
<tr>
<td width="35%" style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Email:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $deletedMail }}
</td>
</tr>
<tr>
<td width="35%" style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
<strong>{{ __('Deleted at:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
{{ $time }}
</td>
</tr>
</table>
{{-- Balance handling information --}}
@if(isset($totalBalance) && $totalBalance != 0)
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 20px 0 10px 0; padding: 0; line-height: 1.5;">
<strong>{{ __('Balance handling:') }}</strong>
</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
<tr>
<td width="35%" style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Total balance:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ tbFormat($totalBalance) }}
</td>
</tr>
@if($balanceHandlingOption === 'donate' && isset($donationOrganizationName))
<tr>
<td width="35%" style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Action:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ __('Donated to organization') }}
</td>
</tr>
<tr>
<td width="35%" style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Organization:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $donationOrganizationName }}
</td>
</tr>
<tr>
<td width="35%" style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
<strong>{{ __('Account:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
{{ __('messages.' . $donationAccountName . '_account') }}
</td>
</tr>
@else
<tr>
<td width="35%" style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
<strong>{{ __('Action:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
{{ __('Balance deleted') }}
</td>
</tr>
@endif
</table>
@endif
{{-- Deletion information --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('All your accounts, personal profile data, photos, or other uploaded files and messages will be permanently deleted. Historical data such as transaction descriptions and messages you shared with other :appname users will be anonymized. We did not share any of your data with third parties.', ['appname' => config('app.name')]) }}
</p>
{{-- Closing message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; padding: 0; line-height: 1.5;">
{!! __('On behalf of the :appname Team, we hope to see you another time!', ['appname' => config('app.name')]) !!}
</p>
{{-- Footer note --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 20px 0 0 0; border-collapse: collapse;">
<tr>
<td style="padding: 15px; background-color: #f9fafb; border-top: 1px solid #e5e7eb; font-family: Arial, Helvetica, sans-serif; font-size: 13px; color: #6b7280; line-height: 1.5;">
{{ __('This is an automated notification about your account deletion. This action will become permanent after :days days.', ['days' => $gracePeriodDays ?? 30]) }}
</td>
</tr>
</table>
@endcomponent

View File

@@ -0,0 +1,55 @@
@component('emails.layouts.html', ['subject' => $subject, 'locale' => $locale ?? config('app.fallback_locale')])
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; line-height: 1.6;">
{{ trans('Hello :name,', ['name' => $notifiable->full_name ?? $notifiable->name], $locale ?? config('app.fallback_locale')) }}
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; line-height: 1.6;">
{{ trans('You are receiving this email because we received a password reset request for your account.', [], $locale ?? config('app.fallback_locale')) }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; line-height: 1.6;">
{{ trans('Click the button below to reset your password. This link will expire in :count minutes.', ['count' => $expireMinutes], $locale ?? config('app.fallback_locale')) }}
</p>
{{-- Button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 30px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $resetUrl }}" style="height:44px;v-text-anchor:middle;width:220px;" arcsize="14%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $resetUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; line-height: 44px; text-align: center; text-decoration: none; width: 220px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ trans('Reset Password', [], $locale ?? config('app.fallback_locale')) }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Alternative link --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 0 0; line-height: 1.6; text-align: left;">
{{ trans("If the button doesn't work, copy and paste this link into your browser:", [], $locale ?? config('app.fallback_locale')) }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 12px; color: {{ theme_color('text.primary') }}; margin: 10px 0 30px 0; line-height: 1.6; text-align: left; word-break: break-all;">
<a href="{{ $resetUrl }}" style="color: {{ theme_color('primary.600') }}; text-decoration: underline;">{{ $resetUrl }}</a>
</p>
{{-- Security notice --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 0 0; line-height: 1.6;">
{{ trans('If you did not request this password reset, no further action is required.', [], $locale ?? config('app.fallback_locale')) }}
</p>
{{-- Closing --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 0 0; line-height: 1.6;">
{{ timebank_config('mail.platform_sign_off_signature.' . ($locale ?? config('app.fallback_locale'))) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endcomponent

View File

@@ -0,0 +1,46 @@
@component('emails.layouts.html', ['subject' => __('Your call has been blocked')])
{{-- Warning Banner --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: #FEF2F2; border-left: 4px solid #DC2626;">
<tr>
<td style="padding: 20px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif;">
<h1 style="color: #991B1B; margin: 0 0 10px 0; font-size: 24px; font-weight: bold;">{{ __('Your call has been blocked') }}</h1>
<p style="font-size: 16px; color: #991B1B; margin: 0;">
{{ $callTitle }}
</p>
</td>
</tr>
</table>
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Dear') }} {{ $callable->name }},
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Your call ":title" has been blocked by the platform administrators for policy review and is no longer visible.', ['title' => $callTitle]) }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; padding: 0; line-height: 1.5;">
{{ __('If you believe this was done in error, please contact our support team.') }}
</p>
{{-- CTA button --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0; border-collapse: collapse;">
<tr>
<td align="center" style="padding: 0;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
<tr>
<td align="center" style="border-radius: 8px; background-color: #111827;">
<a href="mailto:{{ $supportEmail }}" style="display: inline-block; padding: 16px 40px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; color: #ffffff; text-decoration: none; border-radius: 8px; mso-padding-alt: 0;">
{{ __('Contact support') }}
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
@endcomponent

View File

@@ -0,0 +1,50 @@
@component('emails.layouts.html', ['subject' => __('Your call has expired')])
{{-- Warning Banner --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: #F9FAFB; border-left: 4px solid {{ theme_color('text.primary') }};">
<tr>
<td style="padding: 20px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif;">
<h1 style="color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; font-size: 24px; font-weight: bold;">{{ __('Your call has expired') }}</h1>
<p style="font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0;">
{{ $callTitle }}
</p>
</td>
</tr>
</table>
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Dear') }} {{ $callable->name }},
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Your call ":title" has expired and is no longer visible on the platform.', ['title' => $callTitle]) }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; padding: 0; line-height: 1.5;">
{{ __('You can create a new call or extend the expiry date on your calls page.') }}
</p>
{{-- CTA button --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0; border-collapse: collapse;">
<tr>
<td align="center" style="padding: 0;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
<tr>
<td align="center" style="border-radius: 8px; background-color: #111827;">
<a href="{{ $loginUrl }}" style="display: inline-block; padding: 16px 40px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; color: #ffffff; text-decoration: none; border-radius: 8px; mso-padding-alt: 0;">
{{ __('Manage your calls') }}
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; color: #6B7280; margin: 15px 0 30px 0; padding: 0; line-height: 1.5; text-align: center;">
{{ __('Click the button above to log in and manage your calls.') }}
</p>
@endcomponent

View File

@@ -0,0 +1,50 @@
@component('emails.layouts.html', ['subject' => __('Your call expires in :days days', ['days' => $daysRemaining])])
{{-- Warning Banner --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: #F9FAFB; border-left: 4px solid {{ theme_color('text.primary') }};">
<tr>
<td style="padding: 20px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif;">
<h1 style="color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; font-size: 24px; font-weight: bold;">{{ __('Your call expires in :days days', ['days' => $daysRemaining]) }}</h1>
<p style="font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0;">
{{ $callTitle }}
</p>
</td>
</tr>
</table>
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Dear') }} {{ $callable->name }},
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Your call ":title" expires in :days days.', ['title' => $callTitle, 'days' => $daysRemaining]) }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; padding: 0; line-height: 1.5;">
{{ __('Renew it before it is removed from the platform.') }}
</p>
{{-- CTA button --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0; border-collapse: collapse;">
<tr>
<td align="center" style="padding: 0;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
<tr>
<td align="center" style="border-radius: 8px; background-color: #111827;">
<a href="{{ $loginUrl }}" style="display: inline-block; padding: 16px 40px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; color: #ffffff; text-decoration: none; border-radius: 8px; mso-padding-alt: 0;">
{{ __('Manage your calls') }}
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; color: #6B7280; margin: 15px 0 30px 0; padding: 0; line-height: 1.5; text-align: center;">
{{ __('Click the button above to log in and manage your calls.') }}
</p>
@endcomponent

View File

@@ -0,0 +1,99 @@
@component('emails.layouts.html', ['locale' => app()->getLocale(), 'subject' => match($contact['context'] ?? 'contact') {
'report-issue' => __('Copy of Your Issue Report'),
'report-error' => __('Copy of Your Error Report'),
'delete-profile' => __('Copy of Your Profile Deletion Request'),
default => __('Copy of Your Contact Form Submission'),
}])
{{-- Greeting --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Hello') }} {{ explode(' ', $contact['full_name'])[0] }},
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('This is a copy of your :type submitted to :site:', [
'type' => match($contact['context'] ?? 'contact') {
'report-issue' => __('issue report'),
'report-error' => __('error report'),
'delete-profile' => __('profile deletion request'),
default => __('message'),
},
'site' => config('app.name')
]) }}
</p>
{{-- Contact Information --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
<tr>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: {{ theme_color('text.primary') }}; width: 100px;">
{{ __('Your name') }}:
</td>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }};">
{{ $contact['name'] == $contact['full_name'] ? $contact['name'] : $contact['name'] . ' (' . $contact['full_name'] .')' }}
</td>
</tr>
<tr>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: {{ theme_color('text.primary') }};">
{{ __('Your email') }}:
</td>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }};">
{{ $contact['email'] }}
</td>
</tr>
@if(!empty($contact['subject']))
<tr>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: {{ theme_color('text.primary') }};">
{{ __('Subject') }}:
</td>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }};">
{{ $contact['subject'] }}
</td>
</tr>
@endif
@if(!empty($contact['url']))
<tr>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: {{ theme_color('text.primary') }};">
{{ __('Page URL') }}:
</td>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; word-break: break-all;">
{{ $contact['url'] }}
</td>
</tr>
@endif
</table>
{{-- Message content panel --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: {{ theme_color('text.surface') }}; border-left: 4px solid {{ theme_color('text.secondary') }};">
<tr>
<td style="padding: 15px 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: {{ theme_color('text.secondary') }}; margin: 0 0 10px 0; padding: 0;">
{{ __('Your message') }}:
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.secondary') }}; margin: 0; padding: 0; line-height: 1.5; white-space: pre-wrap;">{{ $contact['message'] }}</p>
</td>
</tr>
</table>
{{-- Confirmation message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
@if(($contact['context'] ?? 'contact') === 'delete-profile')
{{ __('We have received your profile deletion request and will review it according to our data retention policies. You will be contacted regarding the next steps.') }}
@else
{{ __('We have received your message and will get back to you as soon as possible.') }}
@endif
</p>
{{-- Closing --}}
@if(!in_array(($contact['context'] ?? 'contact'), ['delete-profile', 'report-error', 'report-issue']))
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 30px 0; padding: 0; line-height: 1.5;">
{{ timebank_config('mail.platform_sign_off_signature.' . app()->getLocale()) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endif
{{-- Subcopy --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: {{ theme_color('text.muted') }}; margin: 30px 0 10px 0; padding: 0; line-height: 1.5; border-top: 1px solid #e5e7eb; padding-top: 20px;">
{{ __('This is an automated confirmation that your message was successfully submitted through the contact form.') }}
</p>
@endcomponent

View File

@@ -0,0 +1,117 @@
@component('emails.layouts.html', ['locale' => app()->getLocale(), 'subject' => match($contact['context'] ?? 'contact') {
'report-issue' => __('Issue Report'),
'report-error' => __('Error Report'),
'delete-profile' => __('Profile Deletion Request'),
default => __('Contact Form Submission'),
}])
{{-- Title --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 20px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.4;">
{{ match($contact['context'] ?? 'contact') {
'report-issue' => __('Issue Report'),
'report-error' => __('Error Report'),
'delete-profile' => __('Profile Deletion Request'),
default => __('Contact Form Submission'),
} }}
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('You have received a new :type from :site:', [
'type' => match($contact['context'] ?? 'contact') {
'report-issue' => __('issue report'),
'report-error' => __('error report'),
'delete-profile' => __('profile deletion request'),
default => __('contact form submission'),
},
'site' => config('app.name')
]) }}
</p>
{{-- Contact Information --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
<tr>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: {{ theme_color('text.primary') }}; width: 100px;">
{{ __('From') }}:
</td>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }};">
{{ $contact['name'] == $contact['full_name'] ? $contact['name'] : $contact['name'] . ' (' . $contact['full_name'] .')' }}
</td>
</tr>
<tr>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: {{ theme_color('text.primary') }};">
{{ __('Email') }}:
</td>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }};">
{{ $contact['email'] }}
</td>
</tr>
@if(!empty($contact['subject']))
<tr>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: {{ theme_color('text.primary') }};">
{{ __('Subject') }}:
</td>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }};">
{{ $contact['subject'] }}
</td>
</tr>
@endif
@if(!empty($contact['url']))
<tr>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: {{ theme_color('text.primary') }};">
{{ __('Page URL') }}:
</td>
<td style="padding: 5px 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; word-break: break-all;">
{{ $contact['url'] }}
</td>
</tr>
@endif
</table>
{{-- Message content panel --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: {{ theme_color('text.surface') }}; border-left: 4px solid {{ theme_color('text.secondary') }};">
<tr>
<td style="padding: 15px 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: {{ theme_color('text.secondary') }}; margin: 0 0 10px 0; padding: 0;">
{{ __('Message') }}:
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.secondary') }}; margin: 0; padding: 0; line-height: 1.5; white-space: pre-wrap;">{{ $contact['message'] }}</p>
</td>
</tr>
</table>
{{-- Action Required for delete-profile --}}
@if(($contact['context'] ?? 'contact') === 'delete-profile')
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 15px; background-color: #fef3c7; border-left: 4px solid #f59e0b; line-height: 1.5;">
<strong>{{ __('Action Required') }}:</strong> {{ __('This user has requested profile deletion. Please review and process according to your data retention policies.') }}
</p>
@endif
{{-- View Profile Button --}}
@if(!empty($contact['is_authenticated']) && !empty($contact['profile_url']))
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 10px auto 20px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $contact['profile_url'] }}" style="height:40px;v-text-anchor:middle;width:200px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $contact['profile_url'] }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 200px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('View :name', ['name' => $contact['full_name']]) }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
@endif
{{-- Subcopy --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: {{ theme_color('text.muted') }}; margin: 30px 0 10px 0; padding: 0; line-height: 1.5; border-top: 1px solid #e5e7eb; padding-top: 20px;">
{{ __('This is an automated message from the contact form on :site.', ['site' => config('app.name')]) }}
</p>
@endcomponent

View File

@@ -0,0 +1,97 @@
@component('emails.layouts.html', ['subject' => __('Warning: Your profile will be deleted soon')])
{{-- Warning Banner --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: #F9FAFB; border-left: 4px solid {{ theme_color('text.primary') }};">
<tr>
<td style="padding: 20px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif;">
<h1 style="color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; font-size: 24px; font-weight: bold;">{{ __('Inactive profile warning') }}</h1>
<p style="font-size: 18px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0;">
{{ __('Your profile will be deleted in') }}: <span style="font-size: 22px;">{{ $timeRemaining }}</span>
</p>
</td>
</tr>
</table>
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Dear') }} {{ $profile->name }},
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Your profile has been inactive for :days days. We will automatically delete your profile if you do not log in again soon.', ['days' => round($daysSinceLogin)]) }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{__('This measure maintains an active platform for our community and protects your privacy by removing outdated personal information.') }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5; font-weight: bold;">
{{ __('This action is irreversible. We will permanently delete all your personal data. Your past transactions will remain visible to other users but will be fully anonymized.') }}
</p>
@if(!empty($accounts))
{{-- Account Balances Table --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
<strong>{{ __('Your accounts') }}</strong>
</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: #F9FAFB; border: 1px solid #E5E7EB;">
<tr>
<td style="padding: 15px;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
@foreach($accounts as $account)
<tr style="border-bottom: 1px solid #E5E7EB;">
<td style="padding: 10px 0; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; color: #6B7280;">
{{ $account['name'] }}
</td>
<td style="padding: 10px 0; text-align: right; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 500; color: {{ theme_color('text.primary') }};">
{{ $account['balanceFormatted'] }}
</td>
</tr>
@endforeach
<tr style="border-top: 2px solid #9CA3AF;">
<td style="padding: 15px 0 5px 0; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #374151;">
{{ __('Total balance') }}
</td>
<td style="padding: 15px 0 5px 0; text-align: right; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; color: {{ theme_color('text.primary') }};">
{{ tbFormat($totalBalance) }}
</td>
</tr>
</table>
</td>
</tr>
</table>
@endif
{{-- Balance deletion warning --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
{{ __('All your account balances will be permanently deleted.') }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; padding: 0; line-height: 1.5; font-weight: bold;">
{{ __('Balance to be deleted') }}: {{ tbFormat($totalBalance) }}
</p>
{{-- Call to action button --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0; border-collapse: collapse;">
<tr>
<td align="center" style="padding: 0;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
<tr>
<td align="center" style="border-radius: 8px; background-color: #111827;">
<a href="{{ $loginUrl }}" style="display: inline-block; padding: 16px 40px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; color: #ffffff; text-decoration: none; border-radius: 8px; mso-padding-alt: 0;">
{{ __('Activate profile') }}
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; color: #6B7280; margin: 15px 0 30px 0; padding: 0; line-height: 1.5; text-align: center;">
{{ __('Click the button above to log in and prevent your profile from being deleted.') }}
</p>
@endcomponent

View File

@@ -0,0 +1,97 @@
@component('emails.layouts.html', ['subject' => __('Urgent: Your profile will be deleted soon')])
{{-- Warning Banner --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: #F9FAFB; border-left: 4px solid {{ theme_color('text.primary') }};">
<tr>
<td style="padding: 20px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif;">
<h1 style="color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; font-size: 24px; font-weight: bold;">{{ __('Urgent: Inactive profile warning') }}</h1>
<p style="font-size: 18px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0;">
{{ __('Your profile will be deleted in') }}: <span style="font-size: 22px;">{{ $timeRemaining }}</span>
</p>
</td>
</tr>
</table>
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Dear') }} {{ $profile->name }},
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('This is your second warning. Your profile has been inactive for :days days and will be automatically deleted if you do not log in soon.', ['days' => round($daysSinceLogin)]) }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{__('This measure maintains an active platform for our community and protects your privacy by removing outdated personal information.') }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5; font-weight: bold;">
{{ __('This action is irreversible. We will permanently delete all your personal data. Your past transactions will remain visible to other users but will be fully anonymized.') }}
</p>
@if(!empty($accounts))
{{-- Account Balances Table --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
<strong>{{ __('Your accounts') }}</strong>
</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: #F9FAFB; border: 1px solid #E5E7EB;">
<tr>
<td style="padding: 15px;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
@foreach($accounts as $account)
<tr style="border-bottom: 1px solid #E5E7EB;">
<td style="padding: 10px 0; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; color: #6B7280;">
{{ $account['name'] }}
</td>
<td style="padding: 10px 0; text-align: right; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 500; color: {{ theme_color('text.primary') }};">
{{ $account['balanceFormatted'] }}
</td>
</tr>
@endforeach
<tr style="border-top: 2px solid #9CA3AF;">
<td style="padding: 15px 0 5px 0; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #374151;">
{{ __('Total balance') }}
</td>
<td style="padding: 15px 0 5px 0; text-align: right; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; color: {{ theme_color('text.primary') }};">
{{ tbFormat($totalBalance) }}
</td>
</tr>
</table>
</td>
</tr>
</table>
@endif
{{-- Balance deletion warning --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
{{ __('All your account balances will be permanently deleted.') }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; padding: 0; line-height: 1.5; font-weight: bold;">
{{ __('Balance to be deleted') }}: {{ tbFormat($totalBalance) }}
</p>
{{-- Call to action button --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0; border-collapse: collapse;">
<tr>
<td align="center" style="padding: 0;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
<tr>
<td align="center" style="border-radius: 8px; background-color: #111827;">
<a href="{{ $loginUrl }}" style="display: inline-block; padding: 16px 40px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; color: #ffffff; text-decoration: none; border-radius: 8px; mso-padding-alt: 0;">
{{ __('Activate profile') }}
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; color: #6B7280; margin: 15px 0 30px 0; padding: 0; line-height: 1.5; text-align: center;">
{{ __('Click the button above to log in and prevent your profile from being deleted.') }}
</p>
@endcomponent

View File

@@ -0,0 +1,98 @@
@component('emails.layouts.html', ['subject' => __('Final warning: Your profile will be deleted very soon')])
{{-- Warning Banner --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: #F9FAFB; border-left: 4px solid {{ theme_color('text.primary') }};">
<tr>
<td style="padding: 20px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif;">
<h1 style="color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; font-size: 24px; font-weight: bold;">{{ __('Final warning: Inactive profile removal') }}</h1>
<p style="font-size: 18px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0;">
{{ __('Your profile will be deleted in') }}: <span style="font-size: 22px;">{{ $timeRemaining }}</span>
</p>
</td>
</tr>
</table>
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Dear') }} {{ $profile->name }},
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('This is our final warning. Your profile has been inactive for :days days and will be automatically deleted very soon. This is your last chance to prevent deletion.', ['days' => round($daysSinceLogin)]) }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{__('This measure maintains an active platform for our community and protects your privacy by removing outdated personal information.') }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5; font-weight: bold;">
{{ __('This action is irreversible. We will permanently delete all your personal data. Your past transactions will remain visible to other users but will be fully anonymized.') }}
</p>
@if(!empty($accounts))
{{-- Account Balances Table --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
<strong>{{ __('Your accounts') }}</strong>
</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: #F9FAFB; border: 1px solid #E5E7EB;">
<tr>
<td style="padding: 15px;">
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
@foreach($accounts as $account)
<tr style="border-bottom: 1px solid #E5E7EB;">
<td style="padding: 10px 0; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; color: #6B7280;">
{{ $account['name'] }}
</td>
<td style="padding: 10px 0; text-align: right; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; font-weight: 500; color: {{ theme_color('text.primary') }};">
{{ $account['balanceFormatted'] }}
</td>
</tr>
@endforeach
<tr style="border-top: 2px solid #9CA3AF;">
<td style="padding: 15px 0 5px 0; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: #374151;">
{{ __('Total balance') }}
</td>
<td style="padding: 15px 0 5px 0; text-align: right; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; color: {{ theme_color('text.primary') }};">
{{ tbFormat($totalBalance) }}
</td>
</tr>
</table>
</td>
</tr>
</table>
@endif
{{-- Balance deletion warning --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
{{ __('All your account balances will be permanently deleted.') }}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; padding: 0; line-height: 1.5; font-weight: bold;">
{{ __('Balance to be deleted') }}: {{ tbFormat($totalBalance) }}
</p>
{{-- Call to action button --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 30px 0; border-collapse: collapse;">
<tr>
<td align="center" style="padding: 0;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="border-collapse: collapse;">
<tr>
<td align="center" style="border-radius: 8px; background-color: #111827;">
<a href="{{ $loginUrl }}" style="display: inline-block; padding: 16px 40px; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 18px; font-weight: bold; color: #ffffff; text-decoration: none; border-radius: 8px; mso-padding-alt: 0;">
{{ __('Activate Profile Now') }}
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 14px; color: #6B7280; margin: 15px 0 30px 0; padding: 0; line-height: 1.5; text-align: center;">
{{ __('Click the button above to log in and prevent your profile from being deleted.') }}
</p>
@endcomponent

View File

@@ -0,0 +1,143 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{{ $locale ?? config('app.locale') }}" lang="{{ $locale ?? config('app.locale') }}">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="x-apple-disable-message-reformatting" />
<title>{{ $subject ?? config('app.name') }}</title>
<!--[if mso]>
<style type="text/css">
body, table, td, p, a, li {
font-family: Arial, sans-serif !important;
}
</style>
<![endif]-->
<style type="text/css">
/* Progressive Enhancement for Mobile */
@media only screen and (max-width: 600px) {
.email-container {
width: 100% !important;
}
.email-content {
padding: 20px 15px !important;
}
.mobile-padding {
padding-left: 8px !important;
padding-right: 8px !important;
}
.mobile-button {
width: 100% !important;
max-width: 280px !important;
min-width: 200px !important;
}
.mobile-button a {
width: 100% !important;
max-width: 280px !important;
min-width: 200px !important;
display: block !important;
}
.mobile-text {
font-size: 14px !important;
}
.mobile-text-small {
font-size: 13px !important;
}
.mobile-title {
font-size: 18px !important;
}
/* Reduce padding for outer wrapper */
.outer-padding {
padding: 20px 10px 0 10px !important;
}
/* Make tables responsive */
table[role="presentation"] {
width: 100% !important;
}
/* Adjust logo padding */
.logo-cell {
padding: 0 0 10px 0 !important;
}
}
/* Extra small screens (300px) */
@media only screen and (max-width: 360px) {
.email-content {
padding: 15px 10px !important;
}
.mobile-padding {
padding-left: 5px !important;
padding-right: 5px !important;
}
.mobile-button {
width: 60% !important;
max-width: 180px !important;
min-width: auto !important;
margin-left: auto !important;
margin-right: auto !important;
}
.mobile-button a {
width: 100% !important;
max-width: 100% !important;
min-width: auto !important;
padding-left: 5px !important;
padding-right: 5px !important;
font-size: 13px !important;
}
.outer-padding {
padding: 10px 5px 0 5px !important;
}
}
</style>
<!--[if !mso]><!-->
<style type="text/css">
/* Client-specific Styles - These won't be inlined */
body {
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
</style>
<!--<![endif]-->
</head>
<body style="margin: 0; padding: 0; width: 100%; background-color: #f4f4f4; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif;">
<table role="presentation" class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color: #f4f4f4; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td align="center" class="outer-padding" style="padding: 40px 20px 0 20px; mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<!-- Header -->
<table role="presentation" width="600" cellpadding="0" cellspacing="0" border="0" style="max-width: 600px; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td align="center" class="logo-cell" style="padding: 0 0 15px 0; mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<img src="{{ asset('storage/app-images/app_mail_logo.png') }}" alt="{{ config('app.name') }}" width="120" style="width: 120px; max-width: 120px; height: auto; display: block; margin: 0 auto; border: 0; -ms-interpolation-mode: bicubic;" />
</td>
</tr>
</table>
<!-- Content Container -->
<table role="presentation" class="email-container" width="600" cellpadding="0" cellspacing="0" border="0" style="max-width: 600px; background-color: #ffffff; border-collapse: collapse; mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<tr>
<td class="email-content" style="padding: 40px 30px; mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
{{ $slot }}
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f9fafb; padding: 20px; text-align: center; border-top: 1px solid #e5e7eb; mso-table-lspace: 0pt; mso-table-rspace: 0pt;">
<p style="margin: 5px 0; padding: 0; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 12px; color: #6b7280; line-height: 1.5; text-align: center;">
{{ __('Need help, or having issues?') }} <a href="mailto:{{ timebank_config('mail.support.email') }}" style="color: #6b7280; border-bottom: 1px solid #6b7280; text-decoration: none;">{{ __('Email our team') }}</a>
</p>
<p style="margin: 5px 0; padding: 0; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 12px; color: #6b7280; line-height: 1.5; text-align: center;">
<a href="{{ config('app.url') }}" style="color: #6b7280; border-bottom: 1px solid #6b7280; text-decoration: none;">
{{ __('Visit our website') }}
</a>
</p>
<p style="margin: 15px 0 5px 0; padding: 0; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 12px; color: #6b7280; line-height: 1.5; text-align: center;">
© {{ date('Y') }} {{ config('app.name') }}. {{ __('All rights reserved.') }}
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,62 @@
@component('emails.layouts.html', ['subject' => trans('mail.new_message_subject')])
{{-- Greeting --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Hello') }} {{ explode(' ', $recipientName)[0] }},
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('Your conversation on :site with :name has an unread update:', ['site' => config('app.name'), 'name' => $groupName ?? $senderName]) }}
</p>
{{-- Message content panel --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse; background-color: {{ theme_color('text.surface') }}; border-left: 4px solid {{ theme_color('text.secondary') }};">
<tr>
<td style="padding: 15px 20px;">
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: {{ theme_color('text.secondary') }}; margin: 0 0 10px 0; padding: 0;">
{{ __(':sender:', ['sender' => $senderName]) }}
</p>
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.secondary') }}; margin: 0; padding: 0; line-height: 1.5;">
{{ $messageContent }}
</p>
</td>
</tr>
</table>
{{-- Follow conversation message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('Follow this conversation on our website by clicking the Chat Messenger button below:') }}
</p>
{{-- Button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 10px auto 20px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $conversationUrl }}" style="height:40px;v-text-anchor:middle;width:180px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $conversationUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 180px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('Chat Messenger') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Closing --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 30px 0; padding: 0; line-height: 1.5;">
{{ timebank_config('mail.platform_sign_off_signature.' . app()->getLocale()) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
{{-- Subcopy --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: {{ theme_color('text.muted') }}; margin: 30px 0 10px 0; padding: 0; line-height: 1.5; border-top: 1px solid #e5e7eb; padding-top: 20px;">
{{ __("You can't reply to this email. Use the Chat Messenger on our website instead.") }}
</p>
@endcomponent

View File

@@ -0,0 +1,72 @@
{{-- Article Block Template for Email Newsletter --}}
<table role="presentation" class="content-block" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-bottom: 30px; border-top: 1px solid #e5e7eb; padding-top: 30px;">
<tr>
<td>
{{-- Image --}}
@if(isset($post['image']) && $post['image'])
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-bottom: 20px;">
<tr>
<td align="center">
<img src="{{ $post['image'] }}" alt="{{ $post['title'] }}"
style="max-width: 100%; height: auto; display: block; border: 0;"
width="560" />
</td>
</tr>
</table>
@endif
{{-- Title --}}
<h2 style="font-family: Arial, Helvetica, sans-serif; font-size: 26px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.3; ">
<a href="{{ $post['url'] }}" style="color: {{ theme_color('text.primary') }}; text-decoration: none;">
{{ $post['title'] }}
</a>
</h2>
{{-- Category --}}
@if(isset($post['category']) && $post['category'])
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 15px 0;">
<tr>
<td style="background-color: {{ theme_color('brand') }}; padding: 4px 12px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #ffffff; font-weight: bold;">
{{ $post['category'] }}
</td>
</tr>
</table>
@endif
{{-- Author (prominent for articles) --}}
@if(isset($post['author']) && $post['author'])
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('brand') }}; margin: 0 0 15px 0; padding: 0; font-weight: bold;">
{{ __('Written by') }} {{ $post['author'] }}
</p>
@endif
{{-- Excerpt --}}
@if(isset($post['excerpt']) && $post['excerpt'])
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.secondary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ $post['excerpt'] }}
</p>
@endif
{{-- Continue reading button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 20px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $post['url'] }}" style="height:40px;v-text-anchor:middle;width:200px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $post['url'] }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 200px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('Continue Reading') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@@ -0,0 +1,121 @@
{{-- Event Block Template for Email Newsletter --}}
<table role="presentation" class="content-block" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-bottom: 30px; border-top: 1px solid #e5e7eb; padding-top: 30px;">
<tr>
<td>
{{-- Image --}}
@if(isset($post['image']) && $post['image'])
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-bottom: 20px;">
<tr>
<td align="center">
<img src="{{ $post['image'] }}" alt="{{ $post['title'] }}"
style="max-width: 100%; height: auto; display: block; border: 0;"
width="560" />
</td>
</tr>
</table>
@endif
{{-- Title --}}
<h2 style="font-family: Arial, Helvetica, sans-serif; font-size: 24px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.3; ">
<a href="{{ $post['url'] }}" style="color: {{ theme_color('text.primary') }}; text-decoration: none;">
{{ $post['title'] }}
</a>
</h2>
{{-- Category --}}
@if(isset($post['category']) && $post['category'])
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 15px 0;">
<tr>
<td style="background-color: {{ theme_color('brand') }}; padding: 4px 12px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #ffffff; font-weight: bold;">
{{ $post['category'] }}
</td>
</tr>
</table>
@endif
{{-- Date, time, Venue and location --}}
@if(isset($post['venue']) && $post['venue'])
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('brand') }}; margin: 0 0 10px 0; padding: 0; font-weight: bold;">
@if(isset($post['event_date']) && $post['event_date'])
{{ $post['event_date'] }}
@if(isset($post['event_time']) && $post['event_time'])
- {{ $post['event_time'] }}
@endif
<br>{{ $post['venue'] }}
@endif
@if(isset($post['address']) && $post['address'])
<br>{{ $post['address'] }}
@endif
</p>
@endif
{{-- Excerpt --}}
@if(isset($post['excerpt']) && $post['excerpt'])
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.secondary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ $post['excerpt'] }}
</p>
@endif
{{-- Organizer --}}
@if(isset($post['author']) && $post['author'])
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.secondary') }}; margin: 0 0 20px 0;">
<span style="font-weight: bold;"> {{ __('Organized by') }} {{ $post['author'] }} </span>
</p>
@endif
{{-- Event buttons --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 20px 0;">
<tr>
<td align="center">
{{-- Event page button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" style="display: inline-block; vertical-align: top;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $post['url'] }}" style="height:44px;v-text-anchor:middle;width:150px;" arcsize="14%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $post['url'] }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: inline-block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; padding: 12px 20px; text-align: center; text-decoration: none; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('Event page') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Calendar link if available --}}
@if(isset($post['calendar_url']) && $post['calendar_url'])
<!--[if !mso]><!-->
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" style="display: inline-block; vertical-align: top; margin-left: 10px;">
<!--<![endif]-->
<!--[if mso]>
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="left" style="display: inline-block;">
<![endif]-->
<tr>
<td align="center" style="border-radius: 6px; background-color: #6b7280;">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $post['calendar_url'] }}" style="height:44px;v-text-anchor:middle;width:180px;" arcsize="14%" stroke="f" fillcolor="#6b7280">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $post['calendar_url'] }}" style="background-color: #6b7280; border-radius: 6px; color: #ffffff; display: inline-block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; padding: 12px 20px; text-align: center; text-decoration: none; -webkit-text-size-adjust: none; mso-hide: all;">
📅 {{ __('Add to Calendar') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
@endif
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@@ -0,0 +1,46 @@
{{-- Image Block Template for Email Newsletter --}}
<table role="presentation" class="content-block" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-bottom: 30px; border-top: 1px solid #e5e7eb; padding-top: 30px;">
<tr>
<td>
{{-- Image --}}
@if(isset($post['image']) && $post['image'])
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-bottom: 0;">
<tr>
<td align="center">
@if(isset($post['url']) && $post['url'])
<a href="{{ $post['url'] }}" style="display: block;">
<img src="{{ $post['image'] }}" alt="{{ $post['title'] ?? '' }}"
style="max-width: 100%; height: auto; display: block; border: 0;"
width="560" />
</a>
@else
<img src="{{ $post['image'] }}" alt="{{ $post['title'] ?? '' }}"
style="max-width: 100%; height: auto; display: block; border: 0;"
width="560" />
@endif
</td>
</tr>
</table>
{{-- Caption and Owner - small text aligned right --}}
@if((isset($post['media_caption']) && $post['media_caption']) || (isset($post['media_owner']) && $post['media_owner']))
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-top: 8px;">
<tr>
<td align="right" style="font-family: Arial, Helvetica, sans-serif; font-size: 11px; color: {{ theme_color('text.secondary') }}; line-height: 1.4;">
@if(isset($post['media_caption']) && $post['media_caption'])
<span style="font-style: italic;">{{ $post['media_caption'] }}</span>
@endif
@if((isset($post['media_caption']) && $post['media_caption']) && (isset($post['media_owner']) && $post['media_owner']))
<span style="margin: 0 4px;"></span>
@endif
@if(isset($post['media_owner']) && $post['media_owner'])
<span>{{ $post['media_owner'] }}</span>
@endif
</td>
</tr>
</table>
@endif
@endif
</td>
</tr>
</table>

View File

@@ -0,0 +1,82 @@
{{-- News Block Template for Email Newsletter --}}
<table role="presentation" class="content-block" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-bottom: 30px; border-top: 1px solid #e5e7eb; padding-top: 30px;">
<tr>
<td>
{{-- Image --}}
@if(isset($post['image']) && $post['image'])
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-bottom: 20px;">
<tr>
<td align="center">
<img src="{{ $post['image'] }}" alt="{{ $post['title'] }}"
style="max-width: 100%; height: auto; display: block; border: 0;"
width="560" />
</td>
</tr>
</table>
@endif
{{-- Location prefix for news --}}
@if(isset($post['location_prefix']) && $post['location_prefix'])
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-weight: bold; color: {{ theme_color('brand') }}; text-transform: uppercase; margin: 0 0 10px 0; letter-spacing: 1px;">
{{ $post['location_prefix'] }}
</p>
@endif
{{-- Title --}}
<h2 style="font-family: Arial, Helvetica, sans-serif; font-size: 24px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.3;">
<a href="{{ $post['url'] }}" style="color: {{ theme_color('text.primary') }}; text-decoration: none;">
{{ $post['title'] }}
</a>
</h2>
{{-- Category --}}
@if(isset($post['category']) && $post['category'])
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 15px 0;">
<tr>
<td style="background-color: {{ theme_color('brand') }}; padding: 4px 12px; font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #ffffff; font-weight: bold;">
{{ $post['category'] }}
</td>
</tr>
</table>
@endif
{{-- Excerpt --}}
@if(isset($post['excerpt']) && $post['excerpt'])
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.secondary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ $post['excerpt'] }}
</p>
@endif
{{-- Author and date --}}
@if(isset($post['author']) && $post['author'])
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-bottom: 20px;">
<tr>
<td style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.secondary') }};">
<span style="font-weight: bold;">{{ __('By') }} {{ $post['author'] }}</span>
</td>
</tr>
</table>
@endif
{{-- Read more button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 20px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $post['url'] }}" style="height:40px;v-text-anchor:middle;width:200px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $post['url'] }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 200px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('Full article') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@@ -0,0 +1,114 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{{ $locale ?? config('app.locale') }}" lang="{{ $locale ?? config('app.locale') }}">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="x-apple-disable-message-reformatting" />
<title>{{ $subject }}</title>
<!--[if mso]>
<style type="text/css">
body, table, td, p, a, li {
font-family: Arial, sans-serif !important;
}
</style>
<![endif]-->
<style type="text/css">
/* Client-specific Styles */
body, table, td, p, a, li, blockquote {
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
table, td {
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
img {
-ms-interpolation-mode: bicubic;
border: 0;
height: auto;
line-height: 100%;
outline: none;
}
/* Reset styles */
body {
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
}
/* What it does: Stops Outlook from adding extra spacing to tables. */
table {
border-collapse: collapse !important;
}
/* What it does: Fixes webkit padding issue. */
table.email-container {
border-spacing: 0 !important;
}
/* Progressive Enhancement for Mobile */
@media only screen and (max-width: 600px) {
.email-container {
width: 100% !important;
}
}
</style>
</head>
<body style="margin: 0; padding: 0; width: 100%; background-color: #f4f4f4; font-family: Arial, Helvetica, sans-serif;">
<table role="presentation" class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center">
<table role="presentation" class="email-container" width="600" cellpadding="0" cellspacing="0" border="0" style="max-width: 600px; background-color: #ffffff;">
<!-- Header -->
<tr>
<td style="background-color: {{ theme_color('brand') }}; padding: 20px; text-align: center;">
<img src="{{ asset('storage/app-images/app_mail_logo_inverted.png') }}" alt="{{ config('app.name') }}" width="90" height="auto" style="width: 90px; max-width: 90px; height: auto; display: block; margin: 0 auto; border: 0; outline: none;" />
@if(isset($mailingTitle))
<p style="color: #ffffff; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: 600; margin: 0; padding: 0; mso-line-height-rule: exactly; line-height: 1.5;">
{{ $mailingTitle }}
</p>
@endif
</td>
</tr>
<!-- Content -->
<tr>
<td class="email-content" style="padding: 30px 20px 0px 20px;">
@if(isset($contentBlocks) && count($contentBlocks) > 0)
@foreach($contentBlocks as $block)
@include($block['template'], ['post' => $block['data']])
@endforeach
@else
{{ $slot ?? '' }}
@endif
</td>
</tr>
<!-- Footer -->
<tr>
<td style="background-color: #f9fafb; padding: 20px; text-align: center; border-top: 1px solid #e5e7eb;">
<p style="margin: 5px 0; padding: 0; font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #6b7280; line-height: 1.5;">
{{ __('You received this newsletter because you subscribed to our updates.') }}
</p>
<p style="margin: 5px 0; padding: 0; font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #6b7280; line-height: 1.5;">
<a href="{{ $unsubscribeUrl ?? '#' }}" style="color: #6b7280; text-decoration: underline;">
{{ __('Unsubscribe') }}
</a> |
<a href="{{ config('app.url') }}" style="color: #6b7280; text-decoration: underline;">
{{ __('Visit our website') }}
</a>
</p>
<p style="margin: 15px 0 5px 0; padding: 0; font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #6b7280; line-height: 1.5;">
© {{ date('Y') }} {{ config('app.name') }}. {{ __('All rights reserved.') }}
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,53 @@
@component('emails.layouts.html', ['subject' => __('Your profile has been updated')])
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; line-height: 1.6;">
{{ __('Hello :name,', ['name' => $profile->full_name ?? $profile->name]) }}
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; line-height: 1.6;">
{!! __('An administrator has made changes to your profile on <strong>:appname</strong>.', ['appname' => config('app.name')]) !!}
</p>
@if(!empty($changedFields))
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; line-height: 1.6;">
<strong>{{ __('Changed fields:') }}</strong>
</p>
<ul style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 20px; line-height: 1.6;">
@foreach($changedFields as $field)
<li>{{ $field }}</li>
@endforeach
</ul>
@endif
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; line-height: 1.6;">
{{ __('Please review these changes by logging into your account.') }}
</p>
{{-- Button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 30px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $buttonUrl }}" style="height:44px;v-text-anchor:middle;width:220px;" arcsize="14%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $buttonUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; line-height: 44px; text-align: center; text-decoration: none; width: 220px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('Review profile') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Closing --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 0 0; line-height: 1.6;">
{{ timebank_config('mail.platform_sign_off_signature.' . app()->getLocale()) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endcomponent

View File

@@ -0,0 +1,46 @@
@component('emails.layouts.html', ['subject' => $action === 'attached' ? trans('Your profile has been linked', [], $locale) : trans('Your profile has been unlinked', [], $locale), 'locale' => $locale])
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; line-height: 1.6;">
{{ trans('Hello', [], $locale) }} {{ $recipient->full_name ?? $recipient->name }},
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; line-height: 1.6;">
@if($action === 'attached')
{{ trans('Your profile on', [], $locale) }} <strong>{{ config('app.name') }}</strong> {{ trans('has been linked to', [], $locale) }} <strong>{{ $linkedProfile->name }}</strong>.
@else
{{ trans('Your profile on', [], $locale) }} <strong>{{ config('app.name') }}</strong> {{ trans('has been unlinked from', [], $locale) }} <strong>{{ $linkedProfile->name }}</strong>.
@endif
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; line-height: 1.6;">
{{ trans('You can now switch profiles via your profile menu in the top right corner of our website.', [], $locale) }}
</p>
{{-- Button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 30px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $buttonUrl }}" style="height:44px;v-text-anchor:middle;width:220px;" arcsize="14%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $buttonUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; line-height: 44px; text-align: center; text-decoration: none; width: 220px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ trans('View Profile', [], $locale) }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Closing --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 0 0; line-height: 1.6;">
{{ timebank_config('mail.platform_sign_off_signature.' . $locale) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endcomponent

View File

@@ -0,0 +1,83 @@
@component('emails.layouts.html', ['subject' => trans('messages.Reservation_cancelled', [], 'en')])
{{-- Greeting --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Hello') }} {{ $reacter->full_name ?? $reacter->name }},
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('Your reservation for :event has been cancelled.', ['event' => $post->translations->first()->title]) }}
</p>
@if($post->meeting)
{{-- Event Details --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
{{ __('Event Details:') }}
</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
@if($post->meeting->venue)
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Location:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $post->meeting->venue }}
</td>
</tr>
@endif
@if($post->meeting->address)
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Address:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $post->meeting->address }}
</td>
</tr>
@endif
@if($post->meeting->from)
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
<strong>{{ __('Date & Time:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
{{ \Illuminate\Support\Carbon::parse($post->meeting->from)->isoFormat('dddd D MMMM YYYY, H:mm') }}
</td>
</tr>
@endif
</table>
@endif
{{-- Reserve again message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('If you wish to reserve again, you can view the event:') }}
</p>
{{-- Button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 10px auto 20px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $buttonUrl }}" style="height:40px;v-text-anchor:middle;width:160px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $buttonUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 160px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('View Event') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Closing --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 30px 0; padding: 0; line-height: 1.5;">
{{ timebank_config('mail.platform_sign_off_signature.' . app()->getLocale()) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endcomponent

View File

@@ -0,0 +1,83 @@
@component('emails.layouts.html', ['subject' => trans('messages.Reservation_confirmation', [], 'en')])
{{-- Greeting --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
Hello {{ $reacter->full_name ?? $reacter->name }},
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
Your reservation for <strong>{{ $post->translations->first()->title }}</strong> has been confirmed!
</p>
@if($post->meeting)
{{-- Event Details --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
Event Details:
</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
@if($post->meeting->venue)
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>Location:</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $post->meeting->venue }}
</td>
</tr>
@endif
@if($post->meeting->address)
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>Address:</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $post->meeting->address }}
</td>
</tr>
@endif
@if($post->meeting->from)
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
<strong>Date & Time:</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
{{ \Illuminate\Support\Carbon::parse($post->meeting->from)->isoFormat('dddd D MMMM YYYY, H:mm') }}
</td>
</tr>
@endif
</table>
@endif
{{-- View details message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
View the full event details:
</p>
{{-- Button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 10px auto 20px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $buttonUrl }}" style="height:40px;v-text-anchor:middle;width:160px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $buttonUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 160px; -webkit-text-size-adjust: none; mso-hide: all;">
View Event
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Closing --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 30px 0; padding: 0; line-height: 1.5;">
{{ timebank_config('mail.platform_sign_off_signature.' . app()->getLocale()) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endcomponent

View File

@@ -0,0 +1,92 @@
@component('emails.layouts.html', ['subject' => trans('messages.Reservation_update', [], 'en')])
{{-- Greeting --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Hello') }} {{ $reacter->full_name ?? $reacter->name }},
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __(':organizer has sent you an update about :event:', ['organizer' => $organizer->name, 'event' => $post->translations->first()->title]) }}
</p>
{{-- Custom Message Panel --}}
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
<tr>
<td style="padding: 20px; border-left: 4px solid {{ theme_color('text.secondary') }}; font-family: Arial, Helvetica, sans-serif; font-size: 15px; color: {{ theme_color('text.secondary') }}; line-height: 1.6; background-color: {{ theme_color('text.surface') }} ">
{{ $customMessage }}
</td>
</tr>
</table>
@if($post->meeting)
{{-- Event Details --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 10px 0 10px 0; padding: 0; line-height: 1.5;">
{{ __('Event Details:') }}
</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
@if($post->meeting->venue)
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Location:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $post->meeting->venue }}
</td>
</tr>
@endif
@if($post->meeting->address)
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Address:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $post->meeting->address }}
</td>
</tr>
@endif
@if($post->meeting->from)
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
<strong>{{ __('Date & Time:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
{{ \Illuminate\Support\Carbon::parse($post->meeting->from)->isoFormat('dddd D MMMM YYYY, H:mm') }}
</td>
</tr>
@endif
</table>
@endif
{{-- View details message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('View the full event details:') }}
</p>
{{-- Button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 10px auto 20px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $buttonUrl }}" style="height:40px;v-text-anchor:middle;width:160px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $buttonUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 160px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('View Event') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Closing --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 30px 0; padding: 0; line-height: 1.5;">
{{ timebank_config('mail.platform_sign_off_signature.' . app()->getLocale()) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endcomponent

View File

@@ -0,0 +1,43 @@
@component('emails.layouts.html', ['subject' => trans('messages.Your_profile_has_received_a_'. $reactionType['name'], [], 'en')])
{{-- Greeting --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Hello') }} {{ $to['name'] }},
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('Your profile on :site just received a :reaction from :user!', ['site' => config('app.name'), 'reaction' => __($reactionType['name']), 'user' => $from->name]) }}
</p>
{{-- See profile message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('See the profile page of :user here:', ['user' => $from->name]) }}
</p>
{{-- Button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 10px auto 20px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $buttonUrl }}" style="height:40px;v-text-anchor:middle;width:200px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $buttonUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 200px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ $from->name }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Closing --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 30px 0; padding: 0; line-height: 1.5;">
{{ timebank_config('mail.platform_sign_off_signature.' . app()->getLocale()) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endcomponent

View File

@@ -0,0 +1,52 @@
@component('emails.layouts.html', ['subject' => trans('messages.new_tag_added') . ': ' . ($tagInfo['tag'] ?? 'Unknown')])
{{-- Greeting --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Hello') }},
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{{ __('A new tag has been added:') }}
</p>
{{-- Tag Information Table --}}
@if($tagInfo)
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Name:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $tagInfo['tag'] ?? '-' }}
</td>
</tr>
@if(isset($tagInfo['category_path']))
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Category:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $tagInfo['category_path'] }}
</td>
</tr>
@endif
@if(isset($tagInfo['comment']))
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
<strong>{{ __('Description:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
{{ $tagInfo['comment'] }}
</td>
</tr>
@endif
</table>
@endif
{{-- Closing --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 30px 0; padding: 0; line-height: 1.5;">
{{ config('app.name') }}
</p>
@endcomponent

View File

@@ -0,0 +1,27 @@
@component('mail::message')
{{ __('You have been invited to join the :team team!', ['team' => $invitation->team->name]) }}
@if (Laravel\Fortify\Features::enabled(Laravel\Fortify\Features::registration()))
{{ __('If you do not have an account, you may create one by clicking the button below. After creating an account, you may click the invitation acceptance button in this email to accept the team invitation:') }}
@component('mail::button', ['url' => route('register')])
{{ __('Create Account') }}
@endcomponent
{{ __('If you already have an account, you may accept this invitation by clicking the button below:') }}
@else
{{ __('You may accept this invitation by clicking the button below:') }}
@endif
@component('mail::button', ['url' => $acceptUrl])
{{ __('Accept Invitation') }}
@endcomponent
{{ __('If you did not expect to receive an invitation to this team, you may discard this email.') }}
@component('mail::subcopy')
Need help, or having issues? Email our team at [{{ timebank_config('mail.support.email') }}](mailto:{{ timebank_config('mail.support.email') }}).
@endcomponent
@endcomponent

View File

@@ -0,0 +1,97 @@
@component('emails.layouts.html', ['subject' => __('Payment received from :name', ['name' => $transaction->accountFrom->accountable->name])])
{{-- Greeting --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 15px 0; padding: 0; line-height: 1.5;">
{{ __('Hello') }} {{ $transaction->accountTo->accountable->full_name ?? $transaction->accountTo->accountable->name }},
</p>
{{-- Main message --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; padding: 0; line-height: 1.5;">
{!! __('You have received a new payment on your <strong>:account</strong> account from <strong>:from</strong>.', ['account' => $transaction->accountTo->name, 'from' => $transaction->accountFrom->accountable->name]) !!}
</p>
{{-- Transaction Details --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: {{ theme_color('text.primary') }}; margin: 0 0 10px 0; padding: 0; line-height: 1.5;">
{{ __('Transaction Details:') }}
</p>
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin: 0 0 20px 0; border-collapse: collapse;">
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Date:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $transaction->updated_at->format('Y-m-d H:i') }}
</td>
</tr>
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('From:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $transaction->accountFrom->accountable->name }}
</td>
</tr>
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
<strong>{{ __('Description:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }}; border-bottom: 1px solid #e5e7eb;">
{{ $transaction->description }}
</td>
</tr>
<tr>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 14px; color: {{ theme_color('text.primary') }};">
<strong>{{ __('Amount:') }}</strong>
</td>
<td style="padding: 10px; font-family: Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; color: {{ theme_color('brand') }};">
{{ tbFormat($transaction->amount) }}
</td>
</tr>
</table>
{{-- Buttons --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 10px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $transactionStatement }}" style="height:40px;v-text-anchor:middle;width:220px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $transactionStatement }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 220px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('Transaction statement') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 10px auto 20px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $transactionHistoryUrl }}" style="height:40px;v-text-anchor:middle;width:220px;" arcsize="15%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $transactionHistoryUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; line-height: 40px; text-align: center; text-decoration: none; width: 220px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('Transaction history') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Closing --}}
<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 30px 0; padding: 0; line-height: 1.5;">
{{ timebank_config('mail.platform_sign_off_signature.' . app()->getLocale()) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endcomponent

View File

@@ -0,0 +1,42 @@
@component('emails.layouts.html', ['subject' => __('Verify your email address')])
{{-- Greeting --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; line-height: 1.6;">
{{ __('Hello :name,', ['name' => $notifiable->full_name ?? $notifiable->name]) }}
</p>
{{-- Main message --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 20px 0; line-height: 1.6;">
{!! __('Thank you for creating an account on <strong>:appname</strong>!', ['appname' => config('app.name')]) !!}
</p>
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 0 0 30px 0; line-height: 1.6;">
{{ __('Please verify your email address by clicking the button below. This link will expire in 60 minutes.') }}
</p>
{{-- Button --}}
<table role="presentation" class="mobile-button" cellpadding="0" cellspacing="0" border="0" align="center" style="margin: 30px auto;">
<tr>
<td align="center" style="border-radius: 6px; background-color: {{ theme_color('brand') }};">
<!--[if mso]>
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $verificationUrl }}" style="height:44px;v-text-anchor:middle;width:220px;" arcsize="14%" stroke="f" fillcolor="{{ theme_color('brand') }}">
<w:anchorlock/>
<center>
<![endif]-->
<a href="{{ $verificationUrl }}" style="background-color: {{ theme_color('brand') }}; border-radius: 6px; color: #ffffff; display: block; font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; font-weight: bold; line-height: 44px; text-align: center; text-decoration: none; width: 220px; -webkit-text-size-adjust: none; mso-hide: all;">
{{ __('Verify Email Address') }}
</a>
<!--[if mso]>
</center>
</v:roundrect>
<![endif]-->
</td>
</tr>
</table>
{{-- Closing --}}
<p style="font-family: {{ theme_font('font_family_body') }}, Arial, Helvetica, sans-serif; font-size: 16px; color: {{ theme_color('text.primary') }}; margin: 30px 0 0 0; line-height: 1.6;">
{{ timebank_config('mail.platform_sign_off_signature.' . app()->getLocale()) ?? timebank_config('mail.platform_sign_off_signature.en', 'See you around!') }}
</p>
@endcomponent

View File

@@ -0,0 +1,20 @@
@php
$layout = Auth::check() ? 'app-layout' : 'guest-layout';
@endphp
<x-dynamic-component :component="$layout">
<div class="mt-48 mb-36 flex flex-col items-center justify-center px-4">
<div class="text-center leading-loose">
<h3 class="text-lg font-medium text-theme-primary mb-4">
{{ __('Unauthorized') }}
</h3>
<div class="text-sm text-theme-secondary">
401
</div>
</div>
<x-jetstream.button onclick="window.location.href='{{ route('main') }}'" class="mt-12">
{{ __('Main page') }}
</x-jetstream.button>
</div>
</x-dynamic-component>

View File

@@ -0,0 +1,20 @@
@php
$layout = Auth::check() ? 'app-layout' : 'guest-layout';
@endphp
<x-dynamic-component :component="$layout">
<div class="mt-48 mb-36 flex flex-col items-center justify-center px-4">
<div class="text-center leading-loose">
<h3 class="text-lg font-medium text-theme-primary mb-4">
{{ __('Payment required') }}
</h3>
<div class="text-sm text-theme-secondary">
402
</div>
</div>
<x-jetstream.button onclick="window.location.href='{{ route('main') }}'" class="mt-12">
{{ __('Main page') }}
</x-jetstream.button>
</div>
</x-dynamic-component>

View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" data-theme="{{ config('themes.active') }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ __('Unauthorized Access') }} - 403</title>
@vite(['resources/css/app.css'])
</head>
<body class="bg-gray-50 dark:bg-gray-900">
<div class="min-h-screen flex flex-col items-center justify-center px-4">
<div class="text-center leading-loose max-w-md">
<h3 class="text-lg font-medium text-theme-primary mb-4">
{{ __('Unauthorized Access') }}
</h3>
<p class="text-sm text-theme-secondary mb-2">
{{ __('You do not have permission to access this resource. This may be due to a session mismatch or invalid authentication state.') }}
</p>
<div class="text-sm text-theme-secondary mb-8">
403
</div>
</div>
<div class="w-full max-w-xs">
<form method="POST" action="{{ route('logout') }}" class="w-full">
@csrf
<button type="submit" class="w-full inline-flex items-center justify-center px-4 py-2 bg-gray-800 dark:bg-gray-700 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 transition ease-in-out duration-150">
{{ __('Logout and Reset Session') }}
</button>
</form>
</div>
@if(config('app.debug'))
<div class="mt-8 p-4 bg-gray-100 dark:bg-gray-800 rounded-lg text-left max-w-2xl">
<p class="text-xs text-gray-500 dark:text-gray-400 font-mono break-all">
{{ $message ?? 'No additional details available.' }}
</p>
</div>
@endif
</div>
</body>
</html>

View File

@@ -0,0 +1,20 @@
@php
$layout = Auth::check() ? 'app-layout' : 'guest-layout';
@endphp
<x-dynamic-component :component="$layout">
<div class="mt-48 mb-36 flex flex-col items-center justify-center px-4">
<div class="text-center leading-loose">
<h3 class="text-lg font-medium text-theme-primary mb-4">
{{ __($exception->getMessage() ?: 'Forbidden') }}
</h3>
<div class="text-sm text-theme-secondary">
403
</div>
</div>
<x-jetstream.button onclick="window.location.href='{{ Auth::check() ? route('main') : route('welcome') }}'" class="mt-12">
{{ Auth::check() ? __('Main page') : __('Welcome') }}
</x-jetstream.button>
</div>
</x-dynamic-component>

View File

@@ -0,0 +1,26 @@
@php
$layout = Auth::check() ? 'app-layout' : 'guest-layout';
@endphp
<x-dynamic-component :component="$layout">
<div class="mt-48 mb-36 flex flex-col items-center justify-center px-4">
<div class="text-center leading-loose">
<h3 class="text-lg font-medium text-theme-primary mb-4">
{{ __('Page not found') }}
</h3>
<div class="text-sm text-theme-secondary">
404
</div>
</div>
<div class="mt-12">
<a href="{{ route('static-report-error') }}" target="_blank" rel="noopener noreferrer" class="text-theme-brand underline">
{{ __('Report website bugs and issues here') }}
</a>
</div>
<x-jetstream.button onclick="window.location.href='{{ route('main') }}'" class="mt-12">
{{ __('Main page') }}
</x-jetstream.button>
</div>
</x-dynamic-component>

View File

@@ -0,0 +1,20 @@
@php
$layout = Auth::check() ? 'app-layout' : 'guest-layout';
@endphp
<x-dynamic-component :component="$layout">
<div class="mt-48 mb-36 flex flex-col items-center justify-center px-4">
<div class="text-center leading-loose">
<h3 class="text-lg font-medium text-theme-primary mb-4">
{{ __('Page Expired') }}
</h3>
<div class="text-sm text-theme-secondary">
419
</div>
</div>
<x-jetstream.button onclick="window.location.href='{{ route('main') }}'" class="mt-12">
{{ __('Main page') }}
</x-jetstream.button>
</div>
</x-dynamic-component>

View File

@@ -0,0 +1,20 @@
@php
$layout = Auth::check() ? 'app-layout' : 'guest-layout';
@endphp
<x-dynamic-component :component="$layout">
<div class="mt-48 mb-36 flex flex-col items-center justify-center px-4">
<div class="text-center leading-loose">
<h3 class="text-lg font-medium text-theme-primary mb-4">
{{ __('Too many requests') }}
</h3>
<div class="text-sm text-theme-secondary">
429
</div>
</div>
<x-jetstream.button onclick="window.location.href='{{ route('main') }}'" class="mt-12">
{{ __('Main page') }}
</x-jetstream.button>
</div>
</x-dynamic-component>

View File

@@ -0,0 +1,26 @@
@php
$layout = Auth::check() ? 'app-layout' : 'guest-layout';
@endphp
<x-dynamic-component :component="$layout">
<div class="mt-48 mb-36 flex flex-col items-center justify-center px-4">
<div class="text-center leading-loose">
<h3 class="text-lg font-medium text-theme-primary mb-4">
{{ __('Server error') }}
</h3>
<div class="text-sm text-theme-secondary">
500
</div>
</div>
<div class="mt-12">
<a href="{{ route('static-report-error') }}" target="_blank" rel="noopener noreferrer" class="text-theme-brand underline">
{{ __('Report website bugs and issues here') }}
</a>
</div>
<x-jetstream.button onclick="window.location.href='{{ route('main') }}'" class="mt-12">
{{ __('Main page') }}
</x-jetstream.button>
</div>
</x-dynamic-component>

View File

@@ -0,0 +1,26 @@
@php
$layout = Auth::check() ? 'app-layout' : 'guest-layout';
@endphp
<x-dynamic-component :component="$layout">
<div class="mt-48 mb-36 flex flex-col items-center justify-center px-4">
<div class="text-center leading-loose">
<h3 class="text-lg font-medium text-theme-primary mb-4">
{{ __('Service unavailable') }}
</h3>
<div class="text-sm text-theme-secondary">
503
</div>
</div>
<div class="mt-12">
<a href="{{ route('static-report-error') }}" target="_blank" rel="noopener noreferrer" class="text-theme-brand underline">
{{ __('Report website bugs and issues here') }}
</a>
</div>
<x-jetstream.button onclick="window.location.href='{{ route('main') }}'" class="mt-12">
{{ __('Main page') }}
</x-jetstream.button>
</div>
</x-dynamic-component>

View File

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title')</title>
<!-- Styles -->
<style>
html, body {
background-color: #fff;
color: #636b6f;
font-family: 'Poppins', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
font-weight: 100;
height: 100vh;
margin: 0;
}
.full-height {
height: 100vh;
}
.flex-center {
align-items: center;
display: flex;
justify-content: center;
}
.position-ref {
position: relative;
}
.content {
text-align: center;
}
.title {
font-size: 36px;
padding: 20px;
}
</style>
</head>
<body>
<div class="flex-center position-ref full-height">
<div class="content">
<div class="title">
@yield('message')
</div>
</div>
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
<div class="flex items-center justify-center p-8">
<div class="text-center">
<div class="text-red-500 text-6xl mb-4">
<i class="fas fa-exclamation-triangle"></i>
</div>
<h2 class="text-2xl font-bold text-gray-800 dark:text-gray-200 mb-2">
{{ __('Unauthorized Access') }}
</h2>
<p class="text-gray-600 dark:text-gray-400">
{{ __('You do not have permission to access this content.') }}
</p>
</div>
</div>

View File

@@ -0,0 +1,34 @@
<x-guest-layout>
@if (session('result'))
<x-slot name="header">
{{ __('Goodbye')}}
</x-slot>
<div class="py-6">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-xl sm:rounded-lg">
<div class="border-b border-gray-200 bg-white p-6 sm:px-20">
<div class="mt-12">
<!-- TODO: insert goodbye image here -->
<div class="mt-8 text-xl lg:text-3xl font-bold text-theme-text-primary">
{{ __('Your profile has been deleted') }}
</div>
</div>
<div class="mb-12 mt-6 flex justify-between">
<p class="text-base lg:text-lg text-theme-text-primary">{{ __('Your profile has been deleted on:') }} {{ session('result')['time'] }}</p>
</div>
<div class="mb-12 mt-6 flex justify-between">
<p class="text-base lg:text-lg text-theme-text-primary">{{ trans_with_platform(__('On behalf of the @PLATFORM_NAME@ team, good bye!')) }}</p>
</div>
</div>
</div>
</div>
</div>
@else
<!-- No session('deleted_at') present -->
<script>
window.location.href = "{{ route('main') }}";
</script>
@endif
</x-guest-layout>

View File

@@ -0,0 +1,411 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" data-theme="@themeId">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1" name="viewport">
<meta content="{{ csrf_token() }}" name="csrf-token">
<meta content="{{config('app.name')}}" name="title">
@unless(timebank_config('seo.allow_indexing_auth'))
<meta name="robots" content="noindex, nofollow, noarchive, nosnippet">
@endunless
@auth
<meta name="user-id" content="{{ auth()->id() }}">
<meta name="user-guard" content="{{ config('auth.defaults.guard') }}">
@endauth
@php
// Determine page title: explicit title > header content > fallback
$pageTitle = null;
// Check if header slot is set and extract text from it
if (isset($header) && $header) {
$headerContent = (string) $header;
$pageTitle = trim(strip_tags($headerContent));
}
// Fall back to StringHelper if no valid header content
if (empty($pageTitle)) {
$pageTitle = \App\Helpers\StringHelper::getPageTitle();
}
@endphp
<title>@yield('title', $pageTitle) - {{ config('app.name') }}</title>
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ asset('favicon-32x32.png') }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ asset('favicon-16x16.png') }}">
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('apple-touch-icon.png') }}">
<!-- Scripts head -->
<script src="{{ route('lang.js') }}"></script>
<!-- Fonts -->
{{-- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap"> --}}
<!-- Styles -->
<link href="{{ asset('css/tagify.css') }}" rel="stylesheet">
<!-- Dynamic Theme CSS Custom Properties -->
<style>
:root {
{!! theme_css_vars() !!}
}
</style>
@vite(['resources/css/app.css', 'resources/css/fonts.css', 'resources/sass/custom_timebank.css'])
<link href="{{ asset('css/custom_tagify.css') }}" rel="stylesheet">
@livewireStyles
@wirechatStyles
<!-- Flatpickr Styles -->
<x-flatpickr::style />
<style>
/* Theme-aware typography */
body {
font-family: var(--font-family-body, 'Poppins', sans-serif) !important;
}
/* Theme-aware heading styles */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-family-heading, 'Oswald', sans-serif) !important;
text-transform: var(--heading-transform, uppercase) !important;
}
/* Apply theme-specific CSS custom properties */
:root {
@themeCssVars
}
</style>
<!-- Quill editor (loaded locally via Vite) -->
@vite('resources/js/quill.js')
<style>
.ql-editor {
height: 500px;
}
</style>
<!-- Scripts (wireui moved to body to fix Firefox Alpine init order) -->
{{-- TODO: Move styles below to separate css file, that can be compiled --}}
<style>
input[type=file]::file-selector-button {
border-style: none;
padding: 0;
color: #fff !important;
padding-left: 1.0rem;
padding-top: 0.25rem;
padding-right: 1.0rem;
padding-bottom: 0.25rem;
border-radius: 0.25rem;
-webkit-appearance: button;
font-weight: 700;
--tw-bg-opacity: 1;
background-color: rgb(107 114 128 / var(--tw-bg-opacity));
text-transform: none;
}
input[type=file]::file-selector-button:hover {
cursor: pointer;
--tw-text-opacity: 1;
--tw-bg-opacity: 1;
background-color: rgb(107 114 128 / var(--tw-bg-opacity));
}
progress {
width: 100%;
height: 20px;
border: none;
background-color: #f1f1f1;
}
progress::-webkit-progress-bar {
background-color: #f1f1f1;
}
progress::-webkit-progress-value {
background-color: #9ae6b4;
}
progress::-moz-progress-bar {
background-color: #9ae6b4;
}
</style>
</head>
<body class="font-sans antialiased flex flex-col min-h-screen">
<x-jetstream.banner />
<x-jetstream.toaster />
<div class="flex-grow md:bg-theme-surface">
@livewire('navigation-menu')
<x-notifications position="bottom-end" />
<header class="bg-theme-brand text-xl font-semibold text-theme-background shadow sm:mt-16">
<!-- System Anounnucement -->
@livewire('system-announcement', ['type' => 'SiteContents\SystemAnnouncement' ?? null, 'limit' => 1])
<!-- Maintenance Banner -->
@livewire('admin.maintenance-banner')
<!-- Header --->
@if (isset($header))
<div class="max-w-7xl mx-auto py-2 px-4 sm:px-6 lg:px-8">
{{ $header }}
</div>
@endif
</header>
<!-- Page Content -->
<main>
{{ $slot }}
</main>
</div>
<!-- Footer -->
<div class="mt-auto w-full">
<x-footer />
</div>
<!-- Forced Logout Modal -->
@auth
@livewire('forced-logout-modal')
@livewire('account-info-modal')
@endauth
<!-- Scripts body-->
<!-- Be careful with changing the loading order! -->
<wireui:scripts />
@livewireScripts
@vite('resources/js/app.js')
@wirechatAssets
<!-- Session Expiration Detection -->
<script>
// Detect session expiration and auto-reload
document.addEventListener('DOMContentLoaded', function() {
let sessionExpired = false;
let isLoggingOut = false;
// Mark when logout is initiated
document.addEventListener('click', function(e) {
const logoutButton = e.target.closest('form[action*="logout"]') ||
e.target.closest('button[wire\\:click*="logout"]') ||
e.target.closest('a[href*="logout"]');
if (logoutButton) {
isLoggingOut = true;
}
});
// Detect Livewire 401/419 errors (session expired)
window.addEventListener('livewire:request', ({ detail }) => {
detail.fail(({ status, content, preventDefault }) => {
if (status === 401 || status === 419) {
preventDefault(); // Always prevent default to avoid "Page expired" dialog
if (!sessionExpired) {
sessionExpired = true;
// Small delay to let other pending requests complete
setTimeout(() => {
// If logging out, redirect to home instead of reloading
if (isLoggingOut) {
window.location.href = '{{ LaravelLocalization::localizeUrl('/') }}';
} else {
window.location.reload();
}
}, 100);
}
}
});
});
// Detect Echo connection errors (session expired)
if (window.Echo && window.Echo.connector && window.Echo.connector.pusher) {
window.Echo.connector.pusher.connection.bind('error', function(err) {
// Check if it's an authentication error
if (err && (err.type === 'AuthError' || err.error?.data?.code === 4009)) {
if (!sessionExpired) {
sessionExpired = true;
// Delay reload slightly to avoid rapid reloads
setTimeout(() => window.location.reload(), 1000);
}
}
});
}
// Catch "Handler does not exist" errors globally
window.addEventListener('error', function(event) {
const message = event.message || '';
if (message.includes('Handler for event') && message.includes('does not exist')) {
// This means session expired and component is stale
if (!sessionExpired) {
sessionExpired = true;
window.location.reload();
}
event.preventDefault();
return false;
}
}, true);
// Suppress the specific Echo error message in console
const originalConsoleError = console.error;
console.error = function(...args) {
const message = args[0]?.toString() || '';
// Don't log Echo handler errors if we're already reloading
if (sessionExpired && message.includes('Handler for event')) {
return;
}
// Suppress handler errors and trigger reload
if (message.includes('Handler for event') && message.includes('does not exist')) {
if (!sessionExpired) {
sessionExpired = true;
setTimeout(() => window.location.reload(), 500);
}
return;
}
originalConsoleError.apply(console, args);
};
});
</script>
<!-- Flatpickr Scripts -->
<x-flatpickr::script />
<!-- Flatpickr Error Handling Override -->
<script>
// Wrap the original Flatpickr initialization with error handling
if (window.LaravelFlatpickr) {
const originalInit = window.LaravelFlatpickr.initializeFlatpickr;
window.LaravelFlatpickr.initializeFlatpickr = function(e) {
try {
// Check if element and required methods exist
if (!e || !e.getAttribute) return;
const targetId = e.getAttribute("data-selector-id");
if (!targetId) return;
const target = document.getElementById(targetId);
if (!target) return;
// Call original initialization
originalInit.call(this, e);
} catch (error) {
// Silently fail to prevent console spam
// console.warn('Flatpickr initialization skipped:', error);
}
};
}
</script>
<!-- Suppress non-critical Alpine.js errors during Livewire morphing -->
<script>
// Suppress WireUI select component errors during Livewire morphing
// These errors occur when Alpine tries to evaluate expressions before the component data is initialized
// They don't affect functionality as the components initialize correctly after morphing completes
// Store original console methods
const originalError = console.error;
const originalWarn = console.warn;
// List of error patterns to suppress
const suppressedPatterns = [
/positionable is not defined/,
/getSelectedValue is not defined/,
/isEmpty is not defined/,
/getPlaceholder is not defined/,
/config is not defined/,
/getSelectedDisplayText is not defined/,
/asyncData is not defined/,
/displayOptions is not defined/,
/isNotEmpty is not defined/,
/selectedOptions is not defined/,
/wireui_select/,
/Alpine Expression Error/,
/ReferenceError.*is not defined/
];
function shouldSuppressMessage(args) {
const message = args.map(arg => {
if (typeof arg === 'string') return arg;
if (arg instanceof Error) return arg.message;
return String(arg);
}).join(' ');
return suppressedPatterns.some(pattern => pattern.test(message));
}
// Override console.error
console.error = function(...args) {
if (!shouldSuppressMessage(args)) {
originalError.apply(console, args);
}
};
// Override console.warn (some frameworks log errors as warnings)
console.warn = function(...args) {
if (!shouldSuppressMessage(args)) {
originalWarn.apply(console, args);
}
};
// Catch uncaught errors in promises and event handlers
window.addEventListener('error', function(event) {
if (shouldSuppressMessage([event.message || event.error?.message || ''])) {
event.preventDefault();
event.stopPropagation();
return false;
}
}, true);
window.addEventListener('unhandledrejection', function(event) {
if (shouldSuppressMessage([event.reason?.message || event.reason || ''])) {
event.preventDefault();
return false;
}
}, true);
</script>
@stack('scripts')
@yield('scripts_body')
@yield('js')
@stack('modals')
<!-- Listen for forced logout event -->
@auth
<script>
document.addEventListener('DOMContentLoaded', function() {
if (window.Echo) {
window.Echo.private('user.logout.{{ auth()->id() }}')
.listen('.forced-logout', (e) => {
// Get current locale from HTML lang attribute
const locale = document.documentElement.lang || 'en';
// Translate message in user's locale using window.i18n
const messageKey = e.message_key || 'For security and maintenance, a system administrator has logged you out of your account. Sorry for this inconvenience and thanks for your patience.';
let message = messageKey;
if (window.i18n && window.i18n[locale] && window.i18n[locale][messageKey]) {
message = window.i18n[locale][messageKey];
}
// Show alert and immediately redirect to login page
// This avoids CSRF errors from deleted sessions
alert(message);
// Redirect to login page with a maintenance mode flag
window.location.href = '{{ route("login") }}?logged_out=maintenance';
});
}
});
</script>
@endauth
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="title" content="@yield('title', config('messenger-ui.site_name'))">
<title>Demo CKeditor</title>
@livewireStyles
</head>
<body>
@livewireScripts
</body>
</html>

View File

@@ -0,0 +1,108 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" data-theme="@themeId">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@unless(timebank_config('seo.allow_indexing_guest'))
<meta name="robots" content="noindex, nofollow, noarchive, nosnippet">
@endunless
@php
// Determine page title: explicit title > header content > fallback
$pageTitle = null;
// Check if header slot is set and extract text from it
if (isset($header) && $header) {
$headerContent = (string) $header;
$pageTitle = trim(strip_tags($headerContent));
}
// Fall back to StringHelper if no valid header content
if (empty($pageTitle)) {
$pageTitle = \App\Helpers\StringHelper::getPageTitle();
}
@endphp
<title>@yield('title', $pageTitle) - {{ config('app.name') }}</title>
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ asset('favicon-32x32.png') }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ asset('favicon-16x16.png') }}">
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('apple-touch-icon.png') }}">
{{-- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap"> --}}
<!-- Scripts -->
<wireui:scripts />
{{-- <script src="{{ mix('js/app.js') }}" defer></script> --}}
<!-- Styles -->
@vite(['resources/css/app.css', 'resources/css/fonts.css', 'resources/sass/custom_timebank.css', 'resources/js/app.js'])
@livewireStyles
@wirechatStyles
<!-- Dynamic Theme CSS Custom Properties -->
<style>
:root {
{!! theme_css_vars() !!}
}
</style>
<style>
/* Theme-aware typography */
body {
font-family: var(--font-family-body, 'Poppins', sans-serif) !important;
}
/* Theme-aware heading styles */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-family-heading, 'Oswald', sans-serif) !important;
text-transform: var(--heading-transform, uppercase) !important;
}
/* Apply theme-specific CSS custom properties */
:root {
@themeCssVars
}
</style>
</head>
<body class="font-sans antialiased flex flex-col min-h-screen">
<x-jetstream.banner />
<x-jetstream.toaster />
<x-notifications position="bottom-end" />
<!-- Fixed navigation menu -->
@include('components.navigation-menu-guest')
<!-- Main content with top padding to account for fixed navigation -->
<div class="flex-grow bg-theme-surface pt-16">
<x-notifications position="bottom-end" />
<!-- System Announcement - positioned below fixed navigation -->
@livewire('system-announcement', ['type' => 'SiteContents\SystemAnnouncement' ?? null, 'limit' => 1])
<header class="bg-theme-brand text-theme-surface shadow">
<!-- Header --->
@if (isset($header))
<div class="max-w-7xl mx-auto pt-1 pb-2 px-4 sm:px-6 lg:px-8">
{{ $header }}
</div>
@endif
</header>
<main>
{{ $slot }}
</main>
</div>
<!-- Footer -->
<div class="mt-auto w-full">
<x-footer />
</div>
<!-- Scripts body-->
<!-- Be careful with changing the loading order! -->
@livewireScripts
@wirechatAssets
@stack('scripts')
@yield('scripts_body')
@yield('js')
</body>
</html>

View File

@@ -0,0 +1,111 @@
<div>
@auth
@if($hasAccepted && !$needsReaccept)
{{-- User has accepted and version is current --}}
<div class="overflow-hidden bg-theme-background shadow-xl sm:rounded-lg mb-3">
<div class="px-3 sm:px-0">
<div class="max-w-4xl mx-auto my-12 p-4">
<div class="flex items-center space-x-3">
<svg class="h-6 w-6 text-theme-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<div>
<h3 class="text-lg font-semibold text-theme-primary">{{ __('Principles Accepted') }}</h3>
<p class="text-sm text-theme-secondary">
{{ __('You accepted these principles on') }} {{ \Carbon\Carbon::parse($acceptedData['accepted_at'])->isoFormat('LL') }}
</p>
<p class="text-xs text-theme-muted mt-1">
{{ __('Language') }}: {{ strtoupper($acceptedData['locale']) }} |
{{ __('Version updated') }}: {{ \Carbon\Carbon::parse($acceptedData['updated_at'])->isoFormat('LL') }}
</p>
</div>
</div>
</div>
</div>
</div>
@elseif($hasAccepted && $needsReaccept)
{{-- User has accepted but needs to re-accept newer version --}}
<div class="overflow-hidden bg-theme-background shadow-xl sm:rounded-lg mb-3">
<div class="px-3 sm:px-0">
<div class="max-w-4xl mx-auto my-12 p-4">
<div class="p-4 bg-gray-50 dark:bg-gray-800/20 border border-gray-300 dark:border-gray-700 rounded-lg mb-6">
<div class="flex items-start space-x-3">
<svg class="h-6 w-6 text-gray-400 dark:text-gray-500 flex-shrink-0 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
</svg>
<div>
<h3 class="text-base font-semibold text-gray-800 dark:text-gray-200">{{ __('Updated Principles') }}</h3>
<p class="text-sm text-gray-600 dark:text-gray-300 mt-1">
{{ __('Our principles have been updated since you last accepted them. Please review the changes and accept the new version.') }}
</p>
<p class="text-xs text-gray-500 dark:text-gray-400 mt-2">
{{ __('You previously accepted on') }}: {{ \Carbon\Carbon::parse($acceptedData['accepted_at'])->isoFormat('LL') }}
</p>
</div>
</div>
</div>
<h3 class="mb-6 text-xl font-semibold text-theme-primary">{{ __('Accept Updated Principles') }}</h3>
<form wire:submit.prevent="accept">
<div class="mb-6">
<label class="flex items-start space-x-3">
<x-jetstream.checkbox wire:model="agreed" />
<span class="text-theme-primary">
{{ __('I have read and accept the updated platform principles described above.') }}
</span>
</label>
</div>
<div class="flex items-center justify-end space-x-3">
<x-jetstream.button type="submit" wire:loading.attr="disabled">
<span wire:loading.remove wire:target="accept">
{{ __('Accept Updated Principles') }}
</span>
<span wire:loading wire:target="accept">
{{ __('Saving...') }}
</span>
</x-jetstream.button>
</div>
</form>
</div>
</div>
</div>
@else
{{-- User needs to accept --}}
<div class="overflow-hidden bg-theme-background shadow-xl sm:rounded-lg mb-3">
<div class="px-3 sm:px-0">
<div class="max-w-4xl mx-auto my-12 p-4">
<h3 class="mb-6 text-xl font-semibold text-theme-primary">{{ __('Accept Principles') }}</h3>
<form wire:submit.prevent="accept">
<div class="mb-6">
<label class="flex items-start space-x-3">
<x-jetstream.checkbox wire:model="agreed" />
<span class="text-theme-primary">
{{ __('I have read and accept the platform principles described above.') }}
</span>
</label>
</div>
<div class="flex items-center justify-end space-x-3">
<x-jetstream.button type="submit" wire:loading.attr="disabled">
<span wire:loading.remove wire:target="accept">
{{ __('Accept Principles') }}
</span>
<span wire:loading wire:target="accept">
{{ __('Saving...') }}
</span>
</x-jetstream.button>
</div>
</form>
</div>
</div>
</div>
@endif
@endauth
@guest
{{-- Not logged in - no action needed --}}
@endguest
</div>

Some files were not shown because too many files have changed in this diff Show More