- public/images/logo.png replaced with the client's professionally-designed version, cropped to remove excess background margin (used sitewide via logo.blade.php / app-logo.blade.php / app-logo-icon.blade.php) - New standalone, unlinked registration form at /forms/nablus-workshop for a one-off workshop Libra is co-hosting with Smart Business Center, replicating a ClickUp form the client previously used but with Libra's own branding. Submissions email info@libra.adv.ps and redirect to /about. No nav/footer link, no DB storage, no captcha (PRD v1.3). - Tasks 17 (parent), 17-1 (Mailable + email template), 17-2 (page/route/form) taken through product-definition -> task-readiness -> dev-implement -> dev-qa, all Done. 11 new tests passing; full suite run clean of new regressions (69 pre-existing unrelated failures, documented in docs/tasks/17.md). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
4.0 KiB
id, title, status, date, parent
| id | title | status | date | parent |
|---|---|---|---|---|
| 17-1 | 17-1 Registration mailable and email template | Done | 2026-09-27 | 17 |
Description
Create a Mailable and Arabic markdown email template that, when sent, delivers a workshop
registration submission to info@libra.adv.ps. This is a prerequisite for task 17-2, which will
call it from the form's submit handler.
File to create: app/Mail/WorkshopRegistrationMail.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class WorkshopRegistrationMail extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct(
public string $fullName,
public string $contactNumber,
public ?string $email,
) {}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'تسجيل جديد - ورشة عمل ريادايات نابلس',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
markdown: 'emails.workshop-registration.ar',
with: [
'fullName' => $this->fullName,
'contactNumber' => $this->contactNumber,
'email' => $this->email,
],
);
}
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [];
}
}
This class deliberately does not extend App\Mail\BaseMailable — BaseMailable::getFromName()
switches on the app locale/from-name for the law firm's own bilingual mail, which doesn't apply
here; this mailable always sends in Arabic with a fixed subject, following the same
ShouldQueue + Queueable/SerializesModels pattern as App\Mail\GuestBookingSubmittedMail
(app/Mail/GuestBookingSubmittedMail.php) instead.
File to create: resources/views/emails/workshop-registration/ar.blade.php
<x-mail::message>
<div dir="rtl" style="text-align: right;">
# تسجيل جديد في ورشة عمل رياديات نابلس
تم استلام تسجيل جديد بالبيانات التالية:
- **الاسم الكامل:** {{ $fullName }}
- **رقم التواصل:** {{ $contactNumber }}
@if($email)
- **البريد الإلكتروني:** {{ $email }}
@endif
مع أطيب التحيات،<br>
{{ config('app.name') }}
</div>
</x-mail::message>
This follows the same <x-mail::message> + dir="rtl" wrapper pattern as
resources/views/emails/booking/guest-submitted/ar.blade.php.
No route or controller wiring belongs to this task — task 17-2 imports
App\Mail\WorkshopRegistrationMail, constructs it with the submitted field values, and sends it
with Mail::to('info@libra.adv.ps')->send(...).
Acceptance Criteria
App\Mail\WorkshopRegistrationMailexists, extendsIlluminate\Mail\Mailable, implementsIlluminate\Contracts\Queue\ShouldQueue, and its constructor acceptsfullName(string),contactNumber(string), andemail(nullable string)resources/views/emails/workshop-registration/ar.blade.phpexists, renders$fullNameand$contactNumberunconditionally, and renders$emailonly when it is not null/empty- Sending
new WorkshopRegistrationMail('Test Name', '0599123456', null)viaMail::fake()in a test produces an email with subjectتسجيل جديد - ورشة عمل ريادايات نابلسand body containing "Test Name" and "0599123456", with no email line rendered - Sending the same mailable with a non-null
emailvalue produces a body that additionally contains that email address
Sub-tasks
None.