# ساخت کارت مکان با جستجو و پیش‌نمایش نقشه

<span id="poi-card"></span>

در این راهنما یک مکان را روی سرور جستجو می‌کنید و عنوان، آدرس و نشانگر آن را در یک کارت React نمایش می‌دهید.

## پیش‌نیازها

- یک برنامهٔ سرور Express و یک کلید خصوصی با دسترسی جستجو در متغیر محیطی `BALAD_API_KEY`.
- یک برنامهٔ React با بستهٔ `maplibre-gl` و یک کلید عمومی با دسترسی نقشه و مبدأ مجاز وب‌سایت.

کد سرور زیر یک مسیر به برنامهٔ Express شما اضافه می‌کند؛ اجرای خود سرور و رابط جستجو باید در برنامهٔ شما فراهم باشد.

## مراحل

1. مرورگر عبارت کاربر را به مسیر داخلی `/api/poi-card` می‌فرستد؛ کلید خصوصی جستجو هرگز در کد مرورگر قرار نمی‌گیرد.
2. سرور نخستین نتیجه را به داده‌های `title`، `address`، `lat` و `lng` تبدیل می‌کند.
3. نتیجهٔ جستجو را به ورودی `poi` کارت بدهید و برای ورودی `publicKey`، یک کلید عمومی با دسترسی نقشه و مبدأ مجاز وب‌سایت قرار دهید.
4. کارت، عنوان و آدرس مکان را همراه نقشه و نشانگر نمایش می‌دهد.

## جستجوی مکان روی سرور با Express

```javascript
import express from "express";

const app = express();
const BALAD_API_KEY = process.env.BALAD_API_KEY;

app.get("/api/poi-card", async (req, res) => {
  const query = typeof req.query.q === "string" ? req.query.q.trim() : "";
  if (!query) return res.sendStatus(400);

  try {
    const url = new URL("https://search.services.balad.ir/v5/service/");
    url.searchParams.set("text", query);
    url.searchParams.set("limit", "1");

    const response = await fetch(url, {
      headers: { Authorization: "Bearer " + BALAD_API_KEY }
    });
    if (!response.ok) return res.sendStatus(response.status);

    const { results = [] } = await response.json();
    const poi = results[0];
    if (!poi) return res.sendStatus(404);

    res.json({
      title: poi.maintext,
      address: poi.subtitle,
      lat: poi.center_point.lat,
      lng: poi.center_point.lng
    });
  } catch {
    res.sendStatus(502);
  }
});
```

## دریافت نتیجهٔ جستجو در مرورگر

```javascript
const response = await fetch("/api/poi-card?q=" + encodeURIComponent(query));
if (response.status === 404) throw new Error("مکانی پیدا نشد.");
if (!response.ok) throw new Error("دریافت نتیجهٔ جستجو ناموفق بود.");
const poi = await response.json();
```

## کارت مکان با React و MapLibre

```jsx
import { useEffect, useRef } from "react";
import maplibregl from "maplibre-gl";
import "maplibre-gl/dist/maplibre-gl.css";

if (maplibregl.getRTLTextPluginStatus() === "unavailable") {
  maplibregl.setRTLTextPlugin(
    "https://tile-vector.services.balad.ir/rtl/mapbox-gl-rtl-text.js", true,
  );
}

export function PoiCard({ poi, publicKey }) {
  const container = useRef(null);

  useEffect(() => {
    const map = new maplibregl.Map({
      container: container.current,
      style: "https://tile-vector.services.balad.ir/styles/vector.json?api_key="
        + publicKey,
      center: [poi.lng, poi.lat],
      zoom: 15,
      minZoom: 3,
      attributionControl: { compact: false },
    });
    const marker = new maplibregl.Marker()
      .setLngLat([poi.lng, poi.lat])
      .addTo(map);

    return () => {
      marker.remove();
      map.remove();
    };
  }, [poi.lng, poi.lat, publicKey]);

  return <article className="poi-card">
    <div ref={container} style={{ height: 300 }}
         aria-label={"نقشه موقعیت " + poi.title} />
    <div>
      <h2>{poi.title}</h2>
      <p>{poi.address}</p>
    </div>
  </article>;
}
```

## نتیجهٔ مورد انتظار

پس از دریافت یک نتیجه، کارت عنوان و آدرس مکان را همراه نقشه و یک نشانگر نشان می‌دهد. اگر نتیجه‌ای نباشد، مسیر نمونه وضعیت `404` برمی‌گرداند.

[![خروجی واقعی کارت مکان با نقشهٔ بلد و نشانگر؛ نام و آدرس کارت نمونه هستند](/dashboard/docs/assets/poi-example.webp)](/dashboard/docs/assets/poi-example.webp)

در این تصویر نقشه از بلد دریافت شده و نام و آدرس کارت برای آموزش به‌صورت فرضی قرار داده شده‌اند.

## نکات

- مسیر `/api/poi-card` نمونه‌ای از سرور برنامهٔ شماست و بخشی از API بلد نیست.
- تنها فیلدهای مستند پاسخ را استفاده کنید و حالت نتیجهٔ خالی، خطای سرویس و بارگذاری ناموفق نقشه را در رابط کاربری پوشش دهید.
- کلید خصوصی جستجو فقط روی سرور می‌ماند؛ برای نمایش نقشه از کلید عمومی با مبدأ مجاز وب‌سایت استفاده کنید. نمونهٔ React برای MapLibre GL JS نسخهٔ ۵ است.

[مرجع جستجوی مکان](/dashboard/docs/search) · [همهٔ آموزش‌های کاربردی](/dashboard/docs/guides)
