Two refinements to match ehsan.sa on artifacts/ehsan-poc:
1. Black ayah: the ayah artwork below the hero
(«وأحسنوا إنّ الله يحبّ المحسنين») now renders solid black
instead of green via Tailwind `brightness-0` on the <img>.
Ornaments and centered layout unchanged.
2. Scroll-reveal motion: added a reusable Reveal component
(src/components/Reveal.tsx) built on the existing framer-motion
dependency. It fades + translates children up (y:28 -> 0) when
they scroll into view, animates once (viewport once:true,
amount 0.2), supports an optional stagger `delay`, and falls
back to a plain div when prefers-reduced-motion is set.
Applied on:
- home.tsx: stats row (2 cards, staggered), featured
opportunity cards grid (staggered by column), workflow-steps
grid (staggered by column).
- opportunities.tsx: opportunity cards grid (staggered).
Added `h-full` to the OpportunityCard root and to the Reveal
wrappers / wrapped Cards so the motion wrapper becoming the grid
item does not break equal-height cards.
Out of scope (unchanged): two-card stats layout, nav, services
mega-menu, hero slider/carousel, copy. No scroll animation on
header/nav or hero.
Verified: tsc --noEmit passes; restarted ehsan-poc web workflow
to clear HMR; screenshot confirms the ayah is black.
Reskin the EHSAN POC to match ehsan.sa and gate the admin area behind a
simple POC login.
- Official header: cropped EHSAN logo, nav (الرئيسية/الوقف/فرص التبرع/
خدماتنا dropdown→طلب دعم/عن إحسان/براعم إحسان), login/cart/search icons,
language toggle, mobile menu. Functional items link; rest are visual-only.
- Colors: green primary tuned + orange accent token added in index.css.
- Auth: AuthContext (localStorage, admin/admin) + login page; /admin and
/whatsapp-log now behind a Protected wrapper redirecting to /login.
- Redesigned OpportunityCard (photo, green progress bar with %, category
badge, تم جمع/المبلغ المتبقي columns, inline donate button + amount),
used on home and opportunities pages.
- Two-step donate page (التفاصيل → الدفع): step indicator, presets
100/50/10, custom amount (prefilled via ?amount=), "تبرع عن أهلك"
checkbox, donor form (phone min 10 for OpenClaw loop).
- 8 need-type card images added; needImages helper maps need→image.
- Seed: added published opportunities (req-012..017) with partial progress
to showcase cards; one kept near-full for an easy closed-loop demo.
Deviation (from code review): donate handler now ACCUMULATES collectedAmount
and clamps to target, validates finite/positive amount, and only advances to
the closed-loop pipeline when a case is fully funded (previously overwrote
and force-advanced — broke partial-progress cases). Donate buttons kept green
to match the reference; orange is an accent only.
- API routes: explicit return types on all Express handlers (fixes TS7030),
`beneficiaryName` now accepted and stored in /thank-you route per OpenAPI spec.
- Home page: added search bar (filters by case ID, description, name) +
Featured Opportunities section with live cards, progress bars, and Donate buttons.
- Opportunities page: added need-type filter pill bar (all 8 types + "All Types")
with active state highlighting; empty state respects selected filter.
- i18n: expanded translations with all previously hardcoded strings
(trackCase, notFound, noData, currentStep, search, searchPlaceholder,
featuredTitle, noResults, donate.caseSummary, donate.caseNotFound,
admin.noRequests, admin.needType, admin.amount, admin.track, admin.whatsapp,
track.caseInfo, track.rejected, track.currentStepLabel, track.submitThankYou,
thankYou.successNote, thankYou.beneficiaryMessageLabel,
whatsapp.donorPhone, whatsapp.beneficiaryMessage, whatsapp.noEntries,
opportunities.noOpportunities, opportunities.verified).
All pages now use t.* — zero hardcoded English UI strings.
- TypeScript: both frontend (tsc --noEmit) and API server build are clean.