Navvo
الأدلّة

بناء محدّد مواقع المتاجر

ابحث عن الأماكن، واعرض تفاصيل غنية، ووجّه المستخدمين إلى المدخل الصحيح.

بناء محدّد مواقع المتاجر

تكامل كلاسيكي: دع المستخدمين يبحثون عن الأماكن، واعرض النتائج بالصور وحالة الفتح/الإغلاق، واعرض التفاصيل الكاملة عند اختيارهم لمكان. يستخدم البحث والأماكن وخريطة.

النطاقات المطلوبة: search وplaces (وtiles للخريطة).

1. ابحث أثناء كتابة المستخدم

استدعِ GET /search مع الاستعلام. أبطئ معالجة الإدخال (debounce) للبقاء ضمن حدود المعدّل.

async function search(q) {
  const res = await fetch(
    "https://navvo.io/api/v1/search?" + new URLSearchParams({ q, limit: "10" }),
    { headers: { "x-api-key": KEY } }
  );
  const data = await res.json();
  return data.places.items; // [{ slug, nameEn, nameAr, rating, lat, lng, imageUrl, hours, … }]
}

2. اعرض النتائج بالصور والحالة

تحمل كل نتيجة ما يعرضه صفّ النتائج، فلا حاجة إلى طلب إضافي لكل نتيجة. ففيها الصورة (imageUrl)، وrating وreviewCount، وcategoryName، وpriceRange، وaddress وarea، إضافةً إلى حالة الفتح اليوم في hours. ويُحذف الحقل إذا لم تتوفّر للمكان بياناته، لذا تحقّق من وجوده قبل استخدامه. راجع البحث ← تفاصيل النتيجة.

function hoursText(h) {
  if (!h) return "";                         // no opening hours on record
  if (h.alwaysOpen) return "Open 24 hours";
  if (h.state === "closed") return ["Closed · Opens", h.opensDay, h.opensAt].filter(Boolean).join(" ");
  return h.closesAt ? `${h.state === "closing" ? "Closing soon" : "Open"} · Closes ${h.closesAt}` : "Open";
}

function resultRow(item) {
  return {
    name: item.nameEn || item.nameAr,
    picture: item.imageUrl,                  // null when the place has none
    rating: item.rating > 0 ? `${item.rating.toFixed(1)} (${item.reviewCount ?? 0})` : "",
    subtitle: [item.categoryName, item.priceRange].filter(Boolean).join(" · "),
    address: [item.address, item.area].filter(Boolean).join(", "),
    hours: hoursText(item.hours),
  };
}

ارسم كل نتيجة على الخريطة عند lng / lat. ولتتيح للمستخدمين تضييق القائمة، أضف openNow=true، أو price مع مستويات السعر التي تريد إبقاءها: price=1,2 يُبقي الأماكن التي لا تتجاوز 10 دنانير للشخص. ولا يطابق مرشّحَ السعر أيُّ مكان ليس له سعر مُدرَج.

وإن كان لديك المعرّف النصي (slug) لمكان دون نتيجة بحث (من قائمة محفوظة مثلًا)، فإن GET /places/thumb يعيد صورته المصغّرة وحالة الفتح.

باستخدام حزمة الويب

تعيد @navvo/maps-js 0.3.0 الحقول نفسها مع أنواعها. وتحوّل موقع كل نتيجة إلى lngLat، وتقبل price قائمةً:

import { NavvoServices } from "@navvo/maps-js";

const services = new NavvoServices({ apiKey: KEY });
const r = await services.search("cafe", { near: [35.9106, 31.9539], price: [1, 2], mode: "submit" });
const rows = r.items.map(resultRow);

وفي صفحة تحمّل الحزمة بوسم <script> (راجع عرض خريطة)، أنشئ العميل بـ new NavvoMaps.NavvoServices({ apiKey: KEY }).

3. اعرض التفاصيل الكاملة عند الاختيار

عندما يختار المستخدم نتيجة، حمّل السجل الكامل من GET /places/{slug}:

async function detail(slug) {
  const res = await fetch(`https://navvo.io/api/v1/places/${encodeURIComponent(slug)}`, {
    headers: { "x-api-key": KEY },
  });
  const place = await res.json();
  if (!place) return null; // unknown slug returns 200 with null body
  return place; // includes reviews, photos, questions, arrivalIntelligence
}

اعرض nameEn/nameAr وcategories وcontact وopeningHours وrating وphotos وreviews.

4. وجّه المستخدمين إلى الباب الصحيح

يمنحك place.arrivalIntelligence المدخل المُوصى به — وهو أفضل من علامة المركز للتوجيه:

const target = place.arrivalIntelligence?.candidates?.[0]?.routeTarget; // { lat, lng }
const directionsUrl =
  `https://navvo.io/api/v1/routing/route`; // POST with that target — see Directions guide
استخدم arrivalIntelligence.candidates[0].routeTarget (المدخل المُوصى به) كوجهة للتوجيه بدلًا من center. لتطبيق توصيل، اعرض أيضًا lastMetersGuidance للسائق.

تجميع كل شيء معًا

البحث

GET /search?q=… ← نتائج تحمل الصورة والتقييم والسعر والعنوان وساعات اليوم.

التفاصيل

GET /places/{slug} عند الاختيار ← السجل الكامل + مدخل الوصول.

التوجيه

POST /routing/route (أو /traffic/route) إلى المدخل المُوصى به.

تحليلات البحث والخصوصية

كل استدعاء لـ GET /search يترك سجلًّا منقّى ومستعار الهوية تحتفظ به Navvo لتحسين البحث، لمدة 30 يومًا افتراضيًا (أو 90 يومًا إن اختار مشروعك ذلك، أو لا شيء إن أوقفت تحليلات البحث له). وينبغي لمحدّد مواقع المتاجر أن يُحسن ثلاثة أمور:

  • ميّز ضغطات المفاتيح. أرسل mode=typeahead أثناء الكتابة وmode=submit عند الضغط على Enter. عندها تُحتسب سلسلة ضغطات المفاتيح بحثًا واحدًا، ويبقى البحث أثناء الكتابة سريعًا لأن المطابقة بالمعنى لا تعمل معه أبدًا.
  • أبلِغ عمّا يختاره المستخدمون، لكن بموافقتهم فقط. إذا كان تطبيقك يقدّم إعدادًا مثل «حسّن البحث باستخدام نشاطي» وفعّله المستخدم، فأرسل معرّف X-Navvo-Session عشوائيًا لكل جلسة مع كل بحث. ثم أبلِغ عن النتيجة التي يفتحها عبر POST /search/events: click / open_place، ثم directions عندما يطلب الاتجاهات إليها.
  • ألغِ التسجيل حيث لا مكان للسجلّات. أضف analytics=false إلى الاختبارات الآلية والمهام المجمَّعة.

ما يُسجَّل، ومدة الاحتفاظ به، وكيفية التعامل مع عمليات البحث الحسّاسة، كلّه مشروح في تحليلات البحث والخصوصية.

Copyright © 2026