diff --git a/.env.example b/.env.example
index 6e39755a..19bc4e61 100644
--- a/.env.example
+++ b/.env.example
@@ -36,6 +36,7 @@ MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=no-reply@laravel.cm
MAIL_FROM_NAME="${APP_NAME}"
+MAIL_SUPPORT=mail-support@laravel.cm
MAILGUN_DOMAIN=
MAILGUN_SECRET=
@@ -57,11 +58,6 @@ GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
GITHUB_REDIRECT=${APP_URL}/auth/github/callback
-SLACK_WEBHOOK_URL=
-SLACK_TEAM_NAME="Laravel Cameroun"
-SLACK_API_TOKEN=
-SLACK_TEAM_URL="https://laravelcm.slack.com"
-
MARKDOWNX_GIPHY_API_KEY=
TORCHLIGHT_TOKEN=
TORCHLIGHT_THEME=moonlight-ii
diff --git a/app/Http/Controllers/SponsoringController.php b/app/Http/Controllers/SponsoringController.php
deleted file mode 100644
index d29ac260..00000000
--- a/app/Http/Controllers/SponsoringController.php
+++ /dev/null
@@ -1,27 +0,0 @@
- Transaction::with(['user', 'user.media'])
- ->scopes('complete')
- ->get(['id', 'user_id', 'metadata'])
- );
-
- return view('sponsors.index', [
- 'sponsors' => $sponsors,
- ]);
- }
-}
diff --git a/app/Livewire/Components/SponsorSubscription.php b/app/Livewire/Components/SponsorSubscription.php
new file mode 100644
index 00000000..b108c1a3
--- /dev/null
+++ b/app/Livewire/Components/SponsorSubscription.php
@@ -0,0 +1,178 @@
+form->fill([
+ 'email' => $auth?->email,
+ 'name' => $auth?->name,
+ 'website' => $auth?->website,
+ 'profile' => 'developer',
+ 'currency' => 'xaf',
+ ]);
+ }
+
+ public function form(Form $form): Form
+ {
+ return $form
+ ->schema([
+ Forms\Components\TextInput::make('name')
+ ->label(__('validation.attributes.name'))
+ ->minLength(5)
+ ->required(),
+ Forms\Components\TextInput::make('email')
+ ->label(__('validation.attributes.email'))
+ ->email()
+ ->required(),
+ Forms\Components\ToggleButtons::make('profile')
+ ->label(__('pages/sponsoring.sponsor_form.profile'))
+ ->options([
+ 'developer' => __('validation.attributes.freelance'),
+ 'company' => __('validation.attributes.company'),
+ ])
+ ->icons([
+ 'developer' => 'phosphor-dev-to-logo-duotone',
+ 'company' => 'phosphor-buildings-duotone',
+ ])
+ ->grouped(),
+ Forms\Components\TextInput::make('website')
+ ->label(__('global.website'))
+ ->prefixIcon('heroicon-m-globe-alt')
+ ->url(),
+ Forms\Components\Group::make()
+ ->schema([
+ Forms\Components\Select::make('currency')
+ ->label(__('validation.attributes.currency'))
+ ->live()
+ ->native()
+ ->options([
+ 'xaf' => 'XAF',
+ 'eur' => 'EUR',
+ 'usd' => 'USD',
+ ]),
+ Forms\Components\TextInput::make('amount')
+ ->label(__('validation.attributes.amount'))
+ ->integer()
+ ->required()
+ ->afterStateUpdated(fn (?int $state) => $state ? abs($state) : 0)
+ ->prefix(fn (Forms\Get $get) => match ($get('currency')) {
+ 'usd' => '$',
+ default => null
+ })
+ ->suffix(fn (Forms\Get $get) => match ($get('currency')) {
+ 'eur' => '€',
+ 'xaf' => 'FCFA',
+ default => null,
+ })
+ ->columnSpan(3),
+ ])
+ ->columns(4)
+ ->columnSpanFull(),
+ ])
+ ->statePath('data')
+ ->columns();
+ }
+
+ public function submit(): void
+ {
+ $this->validate();
+
+ $email = data_get($this->form->getState(), 'email');
+ $amount = data_get($this->form->getState(), 'amount');
+
+ /** @var User $user */
+ $user = Auth::check() ? Auth::user() : User::findByEmailAddress(config('lcm.support_email'));
+
+ NotchPay::setApiKey(apiKey: config('lcm.notch-pay-public-token'));
+
+ try {
+ $payload = Payment::initialize([
+ 'amount' => $amount,
+ 'email' => $email,
+ 'name' => data_get($this->form->getState(), 'name'),
+ 'currency' => data_get($this->form->getState(), 'currency'),
+ 'reference' => $user->id.'-'.$user->username().'-'.uniqid(),
+ 'callback' => route('notchpay-callback'),
+ 'description' => __('Soutien de la communauté Laravel & PHP Cameroun.'),
+ ]);
+
+ Transaction::query()->create([
+ 'amount' => $amount,
+ 'status' => $payload->transaction->status,
+ 'transaction_reference' => $payload->transaction->reference,
+ 'user_id' => $user->id,
+ 'fees' => $payload->transaction->fee,
+ 'type' => TransactionType::ONETIME->value,
+ 'metadata' => [
+ 'currency' => $payload->transaction->currency,
+ 'reference' => $payload->transaction->reference,
+ 'merchant' => [
+ 'reference' => $payload->transaction->merchant_reference,
+ 'customer' => $payload->transaction->customer,
+ 'laravel_cm_id' => Auth::id() ?? null,
+ 'profile' => data_get($this->form->getState(), 'profile'),
+ ],
+ 'initiated_at' => $payload->transaction->created_at,
+ 'description' => $payload->transaction->description,
+ 'for' => PaymentType::SPONSORING->value,
+ ],
+ ]);
+
+ $this->redirect($payload->authorization_url); // @phpstan-ignore-line
+ } catch (ApiException $e) {
+ Log::error($e->getMessage());
+
+ Notification::make()
+ ->title(__('notifications.sponsor_error_title'))
+ ->body(__('notifications.sponsor_error_body'))
+ ->danger()
+ ->send();
+ }
+ }
+
+ public function render(): View
+ {
+ return view('livewire.components.sponsor-subscription', [
+ 'sponsors' => Cache::remember(
+ key: 'sponsors',
+ ttl: now()->addWeek(),
+ callback: fn () => Transaction::with(['user', 'user.media'])
+ ->scopes('complete')
+ ->distinct()
+ ->get(['id', 'user_id', 'metadata'])
+ ),
+ ]);
+ }
+}
diff --git a/app/Livewire/Modals/AnonymousSponsors.php b/app/Livewire/Modals/AnonymousSponsors.php
deleted file mode 100644
index 141c336b..00000000
--- a/app/Livewire/Modals/AnonymousSponsors.php
+++ /dev/null
@@ -1,116 +0,0 @@
-amount = $amount;
- $this->option = $option;
- $this->currency = $currency;
- }
-
- public function submit(): void
- {
- $this->validate(
- rules: [
- 'name' => 'required',
- 'email' => 'required|email',
- ],
- messages: [
- 'name.required' => __('Votre nom est requis'),
- 'email.required' => __('Une adresse e-mail est requise'),
- 'email.email' => __('Veuillez renseigner une adresse e-mail valide'),
- ]
- );
-
- $adminUser = User::findByEmailAddress(
- emailAddress: app()->environment('production') ? 'support@laravel.cm' : 'user@laravel.cm'
- );
-
- NotchPay::setApiKey(
- apiKey: config('lcm.notch-pay-public-token')
- );
-
- try {
- $payload = Payment::initialize([
- 'amount' => $this->amount,
- 'email' => $this->email,
- 'name' => $this->name,
- 'currency' => $this->currency,
- 'reference' => $adminUser->id.'-'.$adminUser->username().'-'.uniqid(),
- 'callback' => route('notchpay-callback'),
- 'description' => __('Soutien de la communauté Laravel & PHP Cameroun.'),
- ]);
-
- Transaction::query()->create([
- 'amount' => $this->amount,
- 'status' => $payload->transaction->status,
- 'transaction_reference' => $payload->transaction->reference,
- 'user_id' => $adminUser->id,
- 'fees' => $payload->transaction->fee,
- 'type' => $this->option === 'one-time'
- ? TransactionType::ONETIME->value
- : TransactionType::RECURSIVE->value,
- 'metadata' => [
- 'currency' => $payload->transaction->currency,
- 'reference' => $payload->transaction->reference,
- 'merchant' => [
- 'reference' => $payload->transaction->merchant_reference,
- 'name' => $payload->transaction->customer->name,
- 'email' => $payload->transaction->customer->email,
- 'laravel_cm_id' => null,
- ],
- 'initiated_at' => $payload->transaction->initiated_at,
- 'description' => $payload->transaction->description,
- 'for' => PaymentType::SPONSORING->value,
- ],
- ]);
-
- $this->redirect($payload->authorization_url); // @phpstan-ignore-line
- } catch (\NotchPay\Exceptions\ApiException $e) {
- Log::error($e->getMessage());
- session()->flash(
- key: 'error',
- value: __('Impossible de procéder au paiement, veuillez recommencer plus tard. Merci')
- );
- }
- }
-
- public static function modalMaxWidth(): string
- {
- return 'xl';
- }
-
- public function render(): View
- {
- return view('livewire.modals.anonymous-sponsors');
- }
-}
diff --git a/app/Livewire/Pages/Sponsoring.php b/app/Livewire/Pages/Sponsoring.php
new file mode 100644
index 00000000..b55cf810
--- /dev/null
+++ b/app/Livewire/Pages/Sponsoring.php
@@ -0,0 +1,16 @@
+title(__('pages/sponsoring.title'));
+ }
+}
diff --git a/app/Livewire/SponsorSubscription.php b/app/Livewire/SponsorSubscription.php
deleted file mode 100644
index 7fcea0c1..00000000
--- a/app/Livewire/SponsorSubscription.php
+++ /dev/null
@@ -1,93 +0,0 @@
-option = $option;
- }
-
- public function subscribe(): void
- {
- $this->validate(['amount' => 'required']);
-
- if (! Auth::check()) {
- $this->dispatch('openModal', component: 'modals.anonymous-sponsors', arguments: [
- 'amount' => $this->amount,
- 'option' => $this->option,
- 'currency' => $this->currency,
- ]);
-
- return;
- }
-
- NotchPay::setApiKey(apiKey: config('lcm.notch-pay-public-token'));
-
- try {
- $payload = Payment::initialize([
- 'amount' => $this->amount,
- 'email' => Auth::user()?->email,
- 'name' => Auth::user()?->name,
- 'currency' => $this->currency,
- 'reference' => Auth::id().'-'.Auth::user()?->username().'-'.uniqid(),
- 'callback' => route('notchpay-callback'),
- 'description' => __('Soutien de la communauté Laravel & PHP Cameroun.'),
- ]);
-
- Transaction::query()->create([
- 'amount' => $this->amount,
- 'status' => $payload->transaction->status,
- 'transaction_reference' => $payload->transaction->reference,
- 'user_id' => Auth::id(),
- 'fees' => $payload->transaction->fee,
- 'type' => $this->option === 'one-time'
- ? TransactionType::ONETIME->value
- : TransactionType::RECURSIVE->value,
- 'metadata' => [
- 'currency' => $payload->transaction->currency,
- 'reference' => $payload->transaction->reference,
- 'merchant' => [
- 'reference' => $payload->transaction->merchant_reference,
- 'name' => $payload->transaction->customer->name,
- 'email' => $payload->transaction->customer->email,
- 'phone' => $payload->transaction->customer->phone,
- 'laravel_cm_id' => Auth::id(),
- ],
- 'initiated_at' => $payload->transaction->initiated_at,
- 'description' => $payload->transaction->description,
- 'for' => PaymentType::SPONSORING->value,
- ],
- ]);
-
- $this->redirect($payload->authorization_url); // @phpstan-ignore-line
- } catch (\NotchPay\Exceptions\ApiException $e) {
- Log::error($e->getMessage());
- session()->flash('error', __('Impossible de procéder au paiement, veuillez recommencer plus tard. Merci'));
- }
- }
-
- public function render(): View
- {
- return view('livewire.sponsor-subscription');
- }
-}
diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php
index b0aa619b..4ad38e3f 100644
--- a/app/Models/Transaction.php
+++ b/app/Models/Transaction.php
@@ -7,16 +7,14 @@
use App\Enums\TransactionStatus;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
-use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
final class Transaction extends Model
{
- use HasFactory;
use HasUuids;
- public $guarded = [];
+ public $guarded = ['id'];
public $casts = [
'metadata' => 'array',
@@ -43,7 +41,7 @@ public function getMetadata(string $name, string $default = ''): string|array
public function setMetadata(array $revisions, bool $save = true): self
{
- $this->metadata = array_merge($this->metadata ?? [], $revisions);
+ $this->metadata = array_unique(array_merge($this->metadata ?? [], $revisions));
if ($save) {
$this->save();
diff --git a/config/lcm.php b/config/lcm.php
index bc0c0c24..f034385c 100644
--- a/config/lcm.php
+++ b/config/lcm.php
@@ -19,17 +19,12 @@
],
],
- 'slack' => [
- 'team' => env('SLACK_TEAM_NAME', 'Laravel Cameroun'),
- 'url' => env('SLACK_TEAM_URL', 'https://laravelcm.slack.com'),
- 'token' => env('SLACK_API_TOKEN', null),
- 'web_hook' => env('SLACK_WEBHOOK_URL', ''),
- ],
-
'supported_locales' => ['fr', 'en'],
'spa_url' => env('FRONTEND_APP_URL', 'http://localhost:4200'),
'notch-pay-public-token' => env('NOTCHPAY_PUBLIC_KEY', null),
+ 'support_email' => env('MAIL_SUPPORT', 'support@laravel.cm'),
+
];
diff --git a/lang/en/notifications.php b/lang/en/notifications.php
index 0fb1eb1f..eb09b32e 100644
--- a/lang/en/notifications.php
+++ b/lang/en/notifications.php
@@ -53,4 +53,7 @@
'save_comment' => 'Your comment has been saved',
'delete_comment' => 'Your comment has been deleted',
],
+
+ 'sponsor_error_title' => 'Payment error',
+ 'sponsor_error_body' => 'Unable to process payment, please try again later. Thank you',
];
diff --git a/lang/en/pages/sponsoring.php b/lang/en/pages/sponsoring.php
new file mode 100644
index 00000000..d00ffddd
--- /dev/null
+++ b/lang/en/pages/sponsoring.php
@@ -0,0 +1,27 @@
+ 'Support Laravel Cameroon',
+ 'support' => 'Support as a guest or',
+ 'support_as' => 'Support as',
+ 'support_badge' => 'If you are registered on the site, a badge will be on your avatar indicating that you are a sponsor of @laravelcm.',
+ 'paragraphes' => [
+ 'one' => 'Welcome to the Laravel Cameroun sponsorship page. Through this page, you can help support the development of the platform. Laravel.cm is the Laravel Cameroon community portal, a place for the community, by the community.
+ The code is entirely open source providing a learning resource for developers. Developers are free to ask
+ questions, contribute to the source code or use it as inspiration for their own projects.',
+ 'two' => "Since we started working with the community in 2018, we've spent a lot of time time setting up features and updating the site on a regular basis. From design to conception, integration and choice of tools for the frontend. And since then, other projects are about to see the light of day thanks to the work we've been putting in for years.",
+ 'three' => "With the funds we'll earn from this page, we want to take Laravel Cameroon to the next level. We plan to expand the platform with many new features and create the best possible portal for the Laravel community in Cameroon. To do this, we need your support.",
+ 'four' => 'Thanks to the sponsorship plans presented on this page, you can help us. Whether large or small, every contribution will help us cover the costs of the next steps.',
+ 'five' => 'Thank you for considering sponsoring Laravel Cameroun! Your help will keep the platform running and improving.',
+ ],
+ 'current_support' => 'Those who have already supported us.',
+ 'sponsor' => 'Support',
+ 'sponsor_github' => 'Support via Github',
+ 'sponsor_form' => [
+ 'profile' => 'You are sponsoring as',
+ ],
+
+];
diff --git a/lang/en/validation.php b/lang/en/validation.php
index 7bd9201c..741ab793 100644
--- a/lang/en/validation.php
+++ b/lang/en/validation.php
@@ -208,6 +208,10 @@
'website' => 'Your Website',
'location' => 'Localization',
'avatar' => 'Avatar',
+ 'company' => 'Enterprise',
+ 'freelance' => 'Freelance',
+ 'amount' => 'Amount',
+ 'currency' => 'Currency',
],
];
diff --git a/lang/fr/notifications.php b/lang/fr/notifications.php
index 501a24fe..5a16ce54 100644
--- a/lang/fr/notifications.php
+++ b/lang/fr/notifications.php
@@ -53,4 +53,8 @@
'save_comment' => 'Votre commentaire a été enregistré',
'delete_comment' => 'Votre commentaire a été supprimé.',
],
+
+ 'sponsor_error_title' => 'Erreur du paiement',
+ 'sponsor_error_body' => 'Impossible de procéder au paiement, veuillez recommencer plus tard. Merci',
+
];
diff --git a/lang/fr/pages/sponsoring.php b/lang/fr/pages/sponsoring.php
new file mode 100644
index 00000000..7f02cc4f
--- /dev/null
+++ b/lang/fr/pages/sponsoring.php
@@ -0,0 +1,37 @@
+ 'Soutenir Laravel Cameroun',
+ 'support' => 'Soutenir en tant qu\'invité ou',
+ 'support_as' => 'Soutenir comme',
+ 'support_badge' => 'Si vous êtes inscris sur le site, un badge sera sur votre avatar indiquant que vous êtes un sponsor de @laravelcm.',
+ 'paragraphes' => [
+ 'one' => 'Bienvenue sur la page de sponsoring de Laravel Cameroun. À travers cette page, vous pouvez aider à soutenir le développement de la plateforme. Laravel.cm est le portail de la
+ communauté Laravel Cameroun, un endroit pour la communauté, par la communauté. Son code est
+ entièrement ouvert (open source)
+ et constitue une ressource d\'apprentissage pour les développeurs. Les développeurs sont
+ libres de poser des questions,
+ de contribuer au code source ou de s\'en inspirer pour leurs propres projets.',
+ 'two' => "Depuis que nous avons débuté avec la communauté en 2018, nous avons consacré pas mal de
+ temps à la mise en place des fonctionnalités et à la mise à jour régulière du site. Du
+ Design à la conception, en passant par l'intégration et le choix des outils pour le
+ frontend. Et depuis lors d'autres projets sont sur le point de voir le jour grâce à ce
+ travail fourni depuis des années.",
+ 'three' => "Avec les fonds que nous gagnerons grâce à cette page, nous voulons amener Laravel Cameroun à
+ un niveau supérieur. Nous prévoyons d'étendre la plateforme avec de nombreuses nouvelles
+ fonctionnalités et de créer le meilleur portail possible pour la communauté Laravel au
+ Cameroun. Pour ce faire, nous avons besoin de soutien.",
+ 'four' => "Grâce aux plans de parrainage présentés sur cette page, vous pouvez nous aider. Qu'elle soit petite ou grande, chaque contribution nous aidera à couvrir les coûts des prochaines étapes.",
+ 'five' => "Merci d'envisager de sponsoriser Laravel Cameroun ! Votre aide permettra à la plateforme de continuer à fonctionner et à s'améliorer.",
+ ],
+ 'current_support' => 'Ceux qui nous ont déjà apportés leur soutien.',
+ 'sponsor' => 'Soutenir',
+ 'sponsor_github' => 'Soutenir via Github',
+ 'sponsor_form' => [
+ 'profile' => 'Vous sponsorisez en tant que',
+ ],
+
+];
diff --git a/lang/fr/validation.php b/lang/fr/validation.php
index c01de5f5..90739121 100644
--- a/lang/fr/validation.php
+++ b/lang/fr/validation.php
@@ -201,6 +201,10 @@
'website' => 'Votre site web',
'location' => 'Localisation',
'avatar' => 'Photo',
+ 'company' => 'Entreprise',
+ 'freelance' => 'Indépendant',
+ 'amount' => 'Montant',
+ 'currency' => 'Devise',
],
];
diff --git a/resources/views/components/error-message.blade.php b/resources/views/components/error-message.blade.php
index a6a08a68..2d9f8043 100644
--- a/resources/views/components/error-message.blade.php
+++ b/resources/views/components/error-message.blade.php
@@ -2,7 +2,7 @@
twMerge(['class' => 'rounded-md bg-red-50 p-4']) }}>
-
+
diff --git a/resources/views/components/join-sponsors.blade.php b/resources/views/components/join-sponsors.blade.php
index 5d9ec78a..fb0c1b63 100644
--- a/resources/views/components/join-sponsors.blade.php
+++ b/resources/views/components/join-sponsors.blade.php
@@ -23,17 +23,17 @@ class="hidden h-12 dark:block"
diff --git a/resources/views/components/modal.blade.php b/resources/views/components/modal.blade.php
deleted file mode 100644
index a8a7cc55..00000000
--- a/resources/views/components/modal.blade.php
+++ /dev/null
@@ -1,40 +0,0 @@
-@props([
- 'formAction' => false,
- 'headerClasses' => '',
- 'contentClasses' => 'px-4 sm:p-6',
- 'footerClasses' => 'px-4 pb-5 sm:px-4 sm:flex',
-])
-
-
- @if($formAction)
-
- @endif
-
diff --git a/resources/views/components/notification.blade.php b/resources/views/components/notification.blade.php
deleted file mode 100644
index eb230012..00000000
--- a/resources/views/components/notification.blade.php
+++ /dev/null
@@ -1,55 +0,0 @@
-
diff --git a/resources/views/components/sponsor-profile.blade.php b/resources/views/components/sponsor-profile.blade.php
index 14deaf1f..4c95ba69 100644
--- a/resources/views/components/sponsor-profile.blade.php
+++ b/resources/views/components/sponsor-profile.blade.php
@@ -2,7 +2,7 @@
'sponsor',
])
-