Test

/* File: src/config.ts */

export const EASY_ORDERS_FEED_URL =

 "https://api.easy-orders.net/api/v1/products/feed/0a7d9edabe47401d9f6257c4f9112f9e/channel/meta";


export const WHATSAPP_NUMBER = "201099425354";


export const PRODUCT_KEYWORDS = {

 omega3: ["omega 3", "omega-3", "fish oil", "أوميغا", "اوميغا", "fishoil"],

 magnesium: ["magnesium", "مغنيسيوم", "magnesium glycinate", "glycinate"],

 vitaminD3: ["vitamin d", "vitamin d3", "d3", "فيتامين د", "فيتامين د3"],

 multivitamin: [

  "multivitamin",

  "multi vitamin",

  "multivitamins",

  "مالتي",

  "متعدد الفيتامينات",

 ],

 probiotic: ["probiotic", "probiotics", "بروبيوتك", "probiotic 10", "digestive"],

} as const;


/* File: src/types.ts */

export type NutrientKey =

 | "omega3"

 | "magnesium"

 | "vitaminD3"

 | "multivitamin"

 | "probiotic";


export interface Product {

 id: string;

 name: string;

 price: number | null;

 image: string;

 url: string;

 brand?: string;

 description?: string;

 category?: string;

 raw?: unknown;

}


export interface QuizResult {

 realAge: number;

 biologicalAge: number;

 wellnessScore: number;

 topNeeds: NutrientKey[];

}


/* File: src/productFeed.ts */

import { EASY_ORDERS_FEED_URL, PRODUCT_KEYWORDS } from "./config";

import { NutrientKey, Product } from "./types";


function normalizeText(value: unknown): string {

 return String(value ?? "")

  .toLowerCase()

  .replace(/\s+/g, " ")

  .trim();

}


function mapFeedItemToProduct(item: any): Product {

 return {

  id: String(

   item?.id ??

    item?.product_id ??

    item?.sku ??

    item?.uid ??

    Math.random().toString(36).slice(2)

  ),

  name: String(

   item?.name ??

    item?.title ??

    item?.product_name ??

    item?.label ??

    "منتج بدون اسم"

  ),

  price:

   typeof item?.price === "number"

    ? item.price

    : typeof item?.sale_price === "number"

    ? item.sale_price

    : typeof item?.regular_price === "number"

    ? item.regular_price

    : item?.price

    ? Number(item.price)

    : null,

  image:

   item?.image ??

   item?.image_link ??

   item?.thumbnail ??

   item?.main_image ??

   item?.imageUrl ??

   "/placeholder-product.png",

  url:

   item?.url ??

   item?.link ??

   item?.product_url ??

   item?.url_link ??

   "#",

  brand: item?.brand ?? item?.vendor ?? item?.manufacturer ?? "",

  description: item?.description ?? item?.short_description ?? item?.desc ?? "",

  category: item?.category ?? item?.google_product_category ?? item?.cat ?? "",

  raw: item,

 };

}


export async function fetchProducts(): Promise<Product[]> {

 const res = await fetch(EASY_ORDERS_FEED_URL, {

  method: "GET",

  headers: {

   Accept: "application/json",

  },

 });


 if (!res.ok) {

  throw new Error(`Feed request failed: ${res.status}`);

 }


 const data = await res.json();

 const items = Array.isArray(data)

  ? data

  : Array.isArray(data?.products)

  ? data.products

  : Array.isArray(data?.items)

  ? data.items

  : Array.isArray(data?.data)

  ? data.data

  : [];

 return (items as any[]).map(mapFeedItemToProduct);

}


function scoreProductForNeed(product: Product, need: NutrientKey): number {

 const keywords = PRODUCT_KEYWORDS[need];

 const haystack = normalizeText(

  [product.name, product.brand, product.description, product.category].join(" ")

 );

 let score = 0;

 for (const keyword of keywords) {

  if (haystack.includes(normalizeText(keyword))) {

   score += 10;

  }

 }

 if (product.price !== null) score += 1;

 if (product.image && product.image !== "/placeholder-product.png") score += 1;

 if (product.url && product.url !== "#") score += 1;

 return score;

}


export function getTopProductsForNeed(

 products: Product[],

 need: NutrientKey,

 limit: number = 3

): Product[] {

 return [...products]

  .map((product) => ({ product, score: scoreProductForNeed(product, need) }))

  .filter((item) => item.score > 0)

  .sort((a, b) => b.score - a.score)

  .slice(0, limit)

  .map((item) => item.product);

}


/* File: src/productLabels.ts */

import { Product } from "./types";


export function getMarketingLabel(index: number, product: Product): string {

 switch (index) {

  case 0:

   return "الأكثر توافقًا مع نتيجتك";

  case 1:

   return "أفضل قيمة مقابل السعر";

  case 2:

   return "خيار بديل ممتاز";

  default:

   return "خيار مقترح";

 }

}


export function getArabicNeedLabel(need: string): string {

 switch (need) {

  case "omega3":

   return "أوميغا 3";

  case "magnesium":

   return "مغنيسيوم";

  case "vitaminD3":

   return "فيتامين D3";

  case "multivitamin":

   return "مالتي فيتامين";

  case "probiotic":

   return "بروبيوتك";

  default:

   return "مكمل مناسب";

 }

}


/* File: src/whatsapp.ts */

import { Product } from "./types";

import { WHATSAPP_NUMBER } from "./config";


export function openWhatsAppOrder(product: Product, needLabel?: string) {

 const text = `مرحباً، أريد طلب هذا المنتج:\n${product.name}\n${

  needLabel ? `الاحتياج المقترح: ${needLabel}\n` : ""

 }${product.url && product.url !== "#" ? `رابط المنتج: ${product.url}` : ""}`;

 const url = `https://wa.me/${WHATSAPP_NUMBER}?text=${encodeURIComponent(text)}`;

 window.open(url, "_blank");

}


/* File: src/RecommendedProducts.tsx */

import React, { useEffect, useMemo, useState } from "react";

import { NutrientKey, Product } from "./types";

import {

 fetchProducts,

 getTopProductsForNeed,

} from "./productFeed";

import {

 getMarketingLabel,

 getArabicNeedLabel,

} from "./productLabels";

import { openWhatsAppOrder } from "./whatsapp";


interface Props {

 primaryNeed: NutrientKey;

}


const RecommendedProducts: React.FC<Props> = ({ primaryNeed }) => {

 const [products, setProducts] = useState<Product[]>([]);

 const [loading, setLoading] = useState(true);

 const [error, setError] = useState("");


 useEffect(() => {

  let mounted = true;

  async function load() {

   try {

    setLoading(true);

    const data = await fetchProducts();

    if (mounted) {

     setProducts(data);

    }

   } catch (err) {

    if (mounted) {

     setError("تعذر تحميل المنتجات الآن");

    }

   } finally {

    if (mounted) {

     setLoading(false);

    }

   }

  }

  load();

  return () => {

   mounted = false;

  };

 }, []);


 const topThree = useMemo(() => {

  return getTopProductsForNeed(products, primaryNeed, 3);

 }, [products, primaryNeed]);


 if (loading) {

  return (

   <section className="rounded-3xl bg-white p-6 shadow-sm">

    <h3 className="mb-2 text-xl font-bold">جارٍ تجهيز أفضل الخيارات لك...</h3>

    <p className="text-sm text-gray-500">نقوم بمطابقة نتيجتك مع المنتجات الأنسب.</p>

   </section>

  );

 }


 if (error) {

  return (

   <section className="rounded-3xl bg-white p-6 shadow-sm">

    <h3 className="mb-2 text-xl font-bold">تعذر تحميل المنتجات</h3>

    <p className="text-sm text-red-500">{error}</p>

   </section>

  );

 }


 if (topThree.length === 0) {

  return (

   <section className="rounded-3xl bg-white p-6 shadow-sm">

    <h3 className="mb-2 text-xl font-bold">لم نجد 3 منتجات مناسبة الآن</h3>

    <p className="text-sm text-gray-500">

     يمكن تعديل الكلمات المفتاحية أو بيانات المنتجات لاحقًا.

    </p>

   </section>

  );

 }


 return (

  <section className="space-y-4">

   <div className="rounded-3xl bg-white p-6 shadow-sm">

    <h3 className="text-2xl font-bold">

     أفضل 3 منتجات مقترحة لاحتياج {getArabicNeedLabel(primaryNeed)}

    </h3>

    <p className="mt-2 text-sm text-gray-600">

     اختر المنتج الأنسب لك، ثم أكمل الطلب مباشرة عبر واتساب.

    </p>

   </div>


   <div className="grid gap-4 md:grid-cols-3">

    {topThree.map((product, index) => (

     <article

      key={product.id}

      className="overflow-hidden rounded-3xl bg-white shadow-sm border border-gray-100"

     >

      <div className="aspect-square bg-gray-50">

       <img

        src={product.image}

        alt={product.name}

        className="h-full w-full object-cover"

       />

      </div>


      <div className="space-y-3 p-5">

       <span className="inline-flex rounded-full bg-emerald-50 px-3 py-1 text-xs font-medium text-emerald-700">

        {getMarketingLabel(index, product)}

       </span>


       <h4 className="text-lg font-bold leading-7">{product.name}</h4>


       {product.price !== null && (

        <p className="text-base font-semibold">

         {product.price} ج.م

        </p>

       )}


       <p className="text-sm leading-6 text-gray-600">

        مناسب لاحتياج {getArabicNeedLabel(primaryNeed)} حسب نتيجتك الحالية.

       </p>


       <div className="grid gap-2">

        <button

         onClick={() =>

          openWhatsAppOrder(

           product,

           getArabicNeedLabel(primaryNeed)

          )

         }

         className="rounded-2xl bg-black px-4 py-3 text-sm font-semibold text-white"

        >

         اطلب الآن عبر واتساب

        </button>


        {product.url && product.url !== "#" && (

         <a

          href={product.url}

          target="_blank"

          rel="noreferrer"

          className="rounded-2xl border border-gray-200 px-4 py-3 text-center text-sm font-medium"

         >

          عرض تفاصيل المنتج

         </a>

        )}

       </div>

      </div>

     </article>

    ))}

   </div>

  </section>

 );

};


export default RecommendedProducts;


/* File: src/ReportPage.tsx */

import React from "react";

import { QuizResult } from "./types";

import RecommendedProducts from "./RecommendedProducts";


interface ReportPageProps {

 result: QuizResult;

}


const ReportPage: React.FC<ReportPageProps> = ({ result }) => {

 const primaryNeed = result.topNeeds[0];


 return (

  <main className="mx-auto max-w-6xl space-y-8 px-4 py-8">

   <section className="rounded-3xl bg-white p-6 shadow-sm">

    <h1 className="text-3xl font-bold">تقريرك الصحي الكامل</h1>

    <p className="mt-2 text-gray-600">

     العمر الحقيقي: {result.realAge} / العمر البيولوجي: {result.biologicalAge}

    </p>

    <p className="mt-2 text-gray-600">

     درجة العافية: {result.wellnessScore}/100

    </p>

   </section>

   {/* Recommended Products Section */}

   <RecommendedProducts primaryNeed={primaryNeed} />

  </main>

 );

};


export default ReportPage;