Files
libra/docs/tasks/17-2.md
T
Naser Mansour 690c22395f Replace logo with client-supplied artwork; add Nablus workshop registration form
- 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>
2026-09-27 23:56:50 +03:00

9.8 KiB

id, title, status, date, parent
id title status date parent
17-2 17-2 Standalone registration page, form, and submit wiring Done 2026-09-27 17

Description

Build the standalone, unlinked Nablus workshop registration page at /forms/nablus-workshop. Depends on task 17-1 (App\Mail\WorkshopRegistrationMail must already exist).

1. Route

File to modify: routes/web.php

Add, near the other public Volt::route calls (after line 14, the /booking/success route), outside any auth/admin/client middleware group:

Volt::route('/forms/nablus-workshop', 'pages.forms.nablus-workshop')->name('forms.nablus-workshop');

Do not add any link to this route anywhere else in the codebase — specifically, do not touch resources/views/components/navigation.blade.php, resources/views/components/footer.blade.php, or any other menu/nav component. The page is reachable only by visiting the URL directly.

2. Standalone layout (no site nav/footer)

File to create: resources/views/components/layouts/standalone.blade.php

A minimal, self-contained HTML layout — it must NOT include <x-navigation /> or <x-footer /> (unlike resources/views/components/layouts/public.blade.php, which this page intentionally does not use, since the form must not carry the site's admin/login/booking navigation). Follow the <head> include pattern from resources/views/components/layouts/public.blade.php (its @include('partials.head')) but with a bare body:

<!DOCTYPE html>
<html lang="ar" dir="rtl">
    <head>
        @include('partials.head')
    </head>
    <body class="min-h-screen bg-[#F4F1EA]" style="font-family: var(--font-arabic)">
        <main class="min-h-screen flex flex-col items-center px-4 py-10 sm:py-16">
            <div class="w-full max-w-[640px]">
                {{ $slot }}
            </div>
        </main>
        @fluxScripts
    </body>
</html>

3. Page component

File to create: resources/views/livewire/pages/forms/nablus-workshop.blade.php

Class-based Volt component (this project's convention — see resources/views/livewire/pages/booking.blade.php for the pattern), using the new standalone layout, with these exact public properties, validation rules, and submit behavior:

<?php

use App\Mail\WorkshopRegistrationMail;
use Illuminate\Support\Facades\Mail;
use Livewire\Attributes\Layout;
use Livewire\Volt\Component;

new #[Layout('components.layouts.standalone')] class extends Component
{
    public string $fullName = '';

    public string $contactNumber = '';

    public string $email = '';

    public function register(): void
    {
        $validated = $this->validate([
            'fullName' => ['required', 'string', 'max:255'],
            'contactNumber' => ['required', 'string', 'max:50'],
            'email' => ['nullable', 'email', 'max:255'],
        ], [
            'fullName.required' => 'يرجى إدخال الاسم الكامل',
            'contactNumber.required' => 'يرجى إدخال رقم التواصل',
            'email.email' => 'يرجى إدخال بريد إلكتروني صحيح',
        ]);

        Mail::to('info@libra.adv.ps')->send(new WorkshopRegistrationMail(
            fullName: $validated['fullName'],
            contactNumber: $validated['contactNumber'],
            email: $validated['email'] !== '' ? $validated['email'] : null,
        ));

        $this->redirect(route('about'), navigate: false);
    }
}; ?>

<div class="flex flex-col gap-6">
    <img
        src="{{ asset('images/workshop-nablus-flyer.jpeg') }}"
        alt="ورشة متخصصة: القانون، التسويق الرقمي، وإدارة المتاجر الإلكترونية"
        class="w-full rounded-lg shadow-[0_2px_8px_rgba(0,0,0,0.1)]"
    />

    <div class="bg-white rounded-lg p-6" style="box-shadow: 0 2px 8px rgba(0,0,0,0.1)">
        <img src="{{ asset('images/logo.png') }}" alt="LIBRA for Rights" class="h-16 w-auto object-contain mb-4" />

        <h1 class="text-2xl font-bold mb-2" style="color: #2D322A">تسجيل في ورشة عمل ريادايات نابلس</h1>
        <p class="mb-4" style="color: #2D322A">تخططين لإطلاق مشروعك الخاص أو تطوير تجارتك الإلكترونية؟ 🚀</p>

        <p class="text-sm leading-relaxed mb-6" style="color: #2D322A">
            ندعوكم للانضمام إلينا في ورشة عمل متخصصة وشاملة تجمع بين القانون، التسويق الرقمي، وإدارة
            المتاجر الإلكترونية لبناء مشروعك على أسس متينة وناجحة! 🎯📊💡
            <br><br>
            برنامج الورشة:
            <br>
            ■ ١١:٠٠ – ١١:١٠ | الترحيب والافتتاحية والتعريف بالسوق الفلسطيني — أ. لينا عبد الهادي
            <br>
            ■ ١١:١٠ – ١١:٤٠ | كيف تبدأ مشروعاً ريادياً — أ. هبة المصري
            <br>
            ■ ١١:٤٥ – ١٢:٢٠ | أساسيات التسويق الرقمي للمشاريع الريادية عبر وسائل التواصل — أ. تالا حلوب
            <br>
            ■ ١٢:٢٠ – ١٢:٣٠ استراحة
            <br>
            ■ ١٢:٣٠ – ١:٠٠ | الحيثيات والإجراءات القانونية الخاصة بالتجارة الإلكترونية — أ. هدى عرموش
            <br>
            ■ ١:٠٥ – ١:٢٥ | البيع عبر المواقع الإلكترونية مقابل منصات التواصل الاجتماعي والفرق بينهما — أ. أيسر غزال
            <br><br>
            📍 المكان: قاعة "ورشة" – برج رفيديا – نابلس
            <br>
            الوقت: من الساعة ١١:٠٠ صباحاً حتى ١:٢٥ ظهراً
            <br>
            ✨ الدعوة عامة لجميع الرياديين/ات وأصحاب المشاريع الناشئة والمهتمين!
        </p>

        <form wire:submit="register" class="flex flex-col gap-4">
            <flux:input
                wire:model="fullName"
                label="الاسم الكامل"
                placeholder="أدخل اسمك الكامل"
                required
            />

            <flux:input
                wire:model="contactNumber"
                label="رقم التواصل"
                placeholder="أدخل رقم جوالك"
                required
            />

            <flux:input
                wire:model="email"
                type="email"
                label="ايميلك للتواصل"
                placeholder="أدخل بريدك الإلكتروني"
            />

            <flux:button variant="primary" type="submit" class="w-full">
                إرسال
            </flux:button>
        </form>
    </div>
</div>

flux:input renders the gold-focus-border / SemiBold-label / required-asterisk styling described in docs/ux-design.md "Forms" automatically (same components already used on pages.booking), so no additional CSS is required beyond the inline colors/classes above (Warm Cream #F4F1EA page background from the standalone layout, Forest Green #2D322A text, White card, Warm Gold accents via Flux's own primary-button styling — matching the existing site palette).

Acceptance Criteria

  • Visiting /forms/nablus-workshop returns HTTP 200 and does not require authentication
  • The rendered page contains neither <x-navigation nor <x-footer (verify: curl -s http://libra.test/forms/nablus-workshop | grep -E 'x-navigation|x-footer' returns no match)
  • resources/views/components/navigation.blade.php and resources/views/components/footer.blade.php contain no reference to forms.nablus-workshop or /forms/nablus-workshop (verify: rg 'nablus-workshop' resources/views/components/navigation.blade.php resources/views/components/footer.blade.php returns no match)
  • Submitting the form with fullName and contactNumber filled in and email left blank succeeds: no validation error is raised, Mail::to('info@libra.adv.ps')->send(...) is called with a WorkshopRegistrationMail carrying the submitted fullName/contactNumber and a null email, and the response redirects to route('about')
  • Submitting with fullName blank, or contactNumber blank, re-renders the form with a validation error and does not send any mail
  • Submitting with a non-empty but invalid email (e.g. not-an-email) re-renders the form with a validation error and does not send any mail
  • Submitting with a valid email filled in sends a WorkshopRegistrationMail whose email property equals the submitted value

Sub-tasks

None.

QA Notes (2026-09-27)

All 6 acceptance criteria verified: tests/Feature/Public/NablusWorkshopRegistrationTest.php (7 tests, all passing) covers route reachability without auth, absence of x-navigation/x-footer markup, absence of nablus-workshop references in navigation.blade.php/footer.blade.php, valid-submission mail dispatch with null email, validation failures for blank fullName/contactNumber and invalid email (no mail sent), and valid-email pass-through. No manual tests required — all criteria are HTTP/route/grep/mail testable. Regression check: last 5 Done tasks (16-4, 16-5, 16-6, 17-1) touch no files this task changed; 17-1's own mailable tests re-run clean (4/4). Full-suite gate run as parent 17 rollup: 1723 passed, 69 failed, 7 skipped — all 69 failures pre-existing/unrelated (About page scholarship section removed 2026-01-11 per 16-6, Card/Accessibility/Admin-export/Availability tests), none reference this task's files (routes/web.php, standalone layout, nablus-workshop page). Not fixed here per QA scope.